1 /******************************************************************************
2 *
3 *  NSSDC/CDF                                                    CDFexport/1.
4 *
5 *  Version 1.2b, 21-Feb-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  15-Sep-95, J Love     Original version.
10 *   V1.0a 18-Sep-95, J Love	Macintosh event handling.
11 *   V1.1  26-Aug-96, J Love	CDF V2.6.
12 *   V1.2  15-Nov-96, J Love	Added `simple' mode.
13 *   V1.2a 15-Jan-97, J Love	Added attribute entries to beginning of text
14 *				file listings.
15 *   V1.2b 21-Feb-97, J Love	Removed RICE.
16 *
17 ******************************************************************************/
18 
19 #include "cdfxp.h"
20 
21 /******************************************************************************
22 * Error messages.
23 ******************************************************************************/
24 
25 static char listOpenError[] = "Error opening listing file.";
26 static char listWriteError[] = "Error writing to listing file.";
27 static char listCloseError[] = "Error closing listing file.";
28 
29 /******************************************************************************
30 * Function prototypes.
31 ******************************************************************************/
32 
33 char *StandardFormat PROTOARGs((long dataType));
34 int StandardWidth PROTOARGs((long dataType, long numElems));
35 
36 /******************************************************************************
37 * ToScreenHori.
38 * Output to ASCII/screen, horizontal listing.
39 * Returns FALSE if a fatal CDF error occurred (meaning NO_MORE_ACCESS).
40 ******************************************************************************/
41 
ToScreenHori()42 Logical ToScreenHori () {
43   AOSs1 (header, BLANKs78)
44   static char screenLines[SCREENtextMAX+1];
45   static char line[] = { BLANKs78 };
46   AOSs1A (keyDefsPrompt, "More: ________   Exit: ________   Help: ________   Continuous: ________")
47   AOSs1B (keyDefsEnd, "End of listing.  Hit ________ to continue.")
48   AOSs1C (keyDefsLoading, "Loading lines.  Use ________ to abort.")
49   AOSs1D (keyDefsCruise, "Continuous.  Use ________ to stop.")
50   static char *keyDefsAborting[1] = { "Aborting at user's request." };
51   static char *keyDefsInitial[1] = { "Loading..." };
52   static int exitKeys[] = { NUL };
53   static struct EditWindowStruct EWscr = {
54     " Screen Listing ", 0, 0, SCREEN_WIDTH, 1, header, screenLines,
55     NUMscreenLINES, 1, NULL, FALSE, TRUE, exitKeys, REFRESHkey_FSI, NUL, NUL,
56     NUL, NUL, NUL, NUL, NUL, NUL, NUL
57   };
58   int lineN, totalWidth = 0, noRoom = 0, filterStatus, addL, key;
59   int lineL = SCREEN_WIDTH - 2; long firstRec, lastRec, recN, nRecs;
60   static Logical first = TRUE; Logical prompt = TRUE;
61   double timeMark; CDFstatus status; struct ItemStruct *Item, *exportHead;
62   /****************************************************************************
63   * Encode key definitions first time.
64   ****************************************************************************/
65   if (first) {
66     EncodeKeyDefinitions (1, keyDefsPrompt, ENTERkey_FSI, EXITkey_FSI,
67 			  HELPkey_FSI, CRUISEkey_EXPORT);
68     EncodeKeyDefinitions (1, keyDefsEnd, ENTERkey_FSI);
69     EncodeKeyDefinitions (1, keyDefsCruise, ABORTkey_EXPORT);
70     EncodeKeyDefinitions (1, keyDefsLoading, ABORTkey_EXPORT);
71     first = FALSE;
72   }
73   /****************************************************************************
74   * Build export list.
75   ****************************************************************************/
76   BuildExportList (&exportHead, LogicalFALSE);
77   /****************************************************************************
78   * Validate `Record' and `Indices' selections.
79   ****************************************************************************/
80   ValidateRecordIndices (OUTPUTtoSCREENh, FALSE, 0L, exportHead);
81   /****************************************************************************
82   * Check for enough room for each exported item and calculate the maximum
83   * record number.
84   ****************************************************************************/
85   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
86      if (Item->output) {
87        /***********************************************************************
88        * Determine if enough room.
89        ***********************************************************************/
90        addL = BOO(totalWidth == 0,0,opt.spacing);
91        switch (Item->type) {
92 	 case RECORDt:
93 	   addL += Item->width;
94 	   break;
95 	 case VARIABLEt:
96 	   addL += (int) ((Item->Var->nRecordValues * Item->width) +
97 			  (opt.spacing * (Item->Var->nRecordValues - 1)));
98 	   break;
99        }
100        if (totalWidth + addL <= lineL) {
101 	 totalWidth += addL;
102 	 continue;
103        }
104        /***********************************************************************
105        * Not enough room.
106        ***********************************************************************/
107        noRoom++;
108        Item->output = FALSE;
109      }
110   }
111   /****************************************************************************
112   * Display message if some items could not be listed.
113   ****************************************************************************/
114   if (noRoom > 0) {
115     char msg[SCREEN_WIDTH+1];
116     sprintf (msg, "Not enough room for %d item%s.",
117 	     noRoom, BOO(noRoom == 1,"","s"));
118     DisplayMessage (msg, NOBEEPWAIT1);
119   }
120   /****************************************************************************
121   * Check if a valid listing.
122   ****************************************************************************/
123   if (totalWidth == 0) {
124     DisplayMessage ("Nothing selected for listing.", BEEPWAIT1);
125     return TRUE;
126   }
127   /****************************************************************************
128   * Determine first/last records.
129   ****************************************************************************/
130   switch (FirstLastRecord(&firstRec,&lastRec,FALSE,exportHead)) {
131     case PASSED: break;
132     case FAILED: return TRUE;
133     case FATAL: return FALSE;
134   }
135   /****************************************************************************
136   * Remove items from the export list that are not being output or filtered.
137   ****************************************************************************/
138   RemoveExportItems (&exportHead);
139   /****************************************************************************
140   * Initialize header.
141   ****************************************************************************/
142   MakeNUL (header[0]);
143   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
144      if (Item->output) {
145        if (!NULstring(header[0])) CatNcharacters (header[0],opt.spacing,' ');
146        switch (Item->type) {
147 	 case RECORDt:
148 	   CatToString (header[0], "Record", Item->width, LEFT_JUSTIFY, "*");
149 	   break;
150 	 case VARIABLEt: {
151 	   int varWidth = (int) ((Item->Var->nRecordValues * Item->width) +
152 				 (opt.spacing * (Item->Var->nRecordValues-1)));
153 	   CatToString (header[0], Item->Var->name, varWidth, CENTER_JUSTIFY,
154 			"*");
155 	   break;
156 	 }
157        }
158      }
159   }
160   /****************************************************************************
161   * Initialize listing lines.
162   ****************************************************************************/
163   MakeNUL (screenLines);
164   lineN = 0;
165   /****************************************************************************
166   * Display listing window.
167   ****************************************************************************/
168   EWscr.tLines = keyDefsInitial;
169   EditWindow (NEWew, &EWscr, LogicalTRUE);
170   nRecs = lastRec - firstRec + 1;
171   timeMark = SystemClock ();
172   /****************************************************************************
173   * Read values until end of listing or user requests an early exit.
174   ****************************************************************************/
175   for (recN = firstRec; recN <= lastRec; recN++) {
176      /*************************************************************************
177      * Check if the abort key has been entered.
178      *************************************************************************/
179      if (read_input(
180 #if defined(CURSESui)
181 		    EWscr.wid,
182 #endif
183 			      &key,PASSTHRUri,FALSE)) {
184        if (key == ABORTkey_EXPORT) {
185 	 if (prompt) {
186 	   EWscr.tLines = keyDefsAborting;
187 	   EditWindow (UPDATEew, &EWscr, LogicalTRUE);
188 	   zzzzz (1.0);
189 	   EditWindow (DELETEew, &EWscr, TRUE);
190 	   return TRUE;
191 	 }
192 	 else
193 	   prompt = TRUE;
194        }
195        else
196 	 EditWindow (BEEPew, &EWscr);
197      }
198      /*************************************************************************
199      * Should `loading' message be displayed?
200      *************************************************************************/
201      if (SystemClock() - timeMark > 1.0) {
202        UpdateToScreen (&EWscr, keyDefsLoading[0], recN, nRecs);
203        timeMark = SystemClock ();
204      }
205      /*************************************************************************
206      * Encode line.
207      *************************************************************************/
208      status = EncodeLineHori(line,recN,&filterStatus,exportHead,FALSE);
209      if (StatusBAD(status)) {
210        char text[CDF_STATUSTEXT_LEN+1];
211        CDFlib (SELECT_, CDF_STATUS_, status,
212 	       GET_, STATUS_TEXT_, text,
213 	       NULL_);
214        InfoWindow ("An error occurred while reading the CDF.", text, NULL,
215 		   TRUE, TRUE, 0);
216        EditWindow (DELETEew, &EWscr, TRUE);
217        return FALSE;
218      }
219      /*************************************************************************
220      * Check if line should be added to display.
221      *************************************************************************/
222      if (SHOWline(filterStatus)) {
223        if (lineN == NUMscreenLINES) {
224 	 Logical loop = TRUE;
225 	 UpdateToScreen (&EWscr, BOO(prompt,keyDefsPrompt[0],keyDefsCruise[0]),
226 			 recN, nRecs);
227 	 if (prompt)
228 	   EditWindow (READew, &EWscr);
229 	 else
230 	   EWscr.key = ENTERkey_FSI;
231 	 while (loop) {
232 	   switch (EWscr.key) {
233 	     case CRUISEkey_EXPORT:
234 	       prompt = FALSE;          /* No `break' is intentional. */
235 	     case ENTERkey_FSI:
236 	       MakeNUL (screenLines);
237 	       lineN = 0;
238 	       loop = FALSE;
239 	       break;
240 	     case HELPkey_FSI:
241 	       OnlineHelpWindow ("cdfxp.ilh", SCREENhelpID);
242 	       EditWindow (READew, &EWscr);
243 	       break;
244 	     case EXITkey_FSI:
245 	       EditWindow (DELETEew, &EWscr, TRUE);
246 	       return TRUE;
247 	     default:
248 	       EditWindow (BEEPew, &EWscr);
249 	       EditWindow (READew, &EWscr);
250 	       break;
251 	   }
252 	 }
253 	 timeMark = SystemClock ();
254        }
255        strcatX (screenLines, line, SCREENtextMAX);
256        strcatX (screenLines, "\n", SCREENtextMAX);
257        lineN++;
258      }
259   }
260   /****************************************************************************
261   * End of listing.
262   ****************************************************************************/
263   EWscr.tLines = keyDefsEnd;
264   EditWindow (UPDATEew, &EWscr, LogicalTRUE);
265   EditWindow (READew, &EWscr);
266   EditWindow (DELETEew, &EWscr, TRUE);
267   return TRUE;
268 }
269 
270 /******************************************************************************
271 * ToFileHori.
272 * Output to ASCII/file, horizontal listing.
273 * Returns FALSE if a fatal CDF error occurred (meaning NO_MORE_ACCESS).
274 ******************************************************************************/
275 
ToFileHori()276 Logical ToFileHori () {
277   long addL, lineL = 0; int filterStatus;
278   char *line; long firstRec, lastRec, recN, nRecs;
279   struct ItemStruct *Item, *exportHead; FILE *oFp;
280   CDFstatus status; Logical first = TRUE, cdfFatal;
281   static char pctMsg[] = "Listing started...";
282   static char keyDefsBlank[] = "\n\n";
283   static char keyDefsAbort[] = "Abort: ________\n\n";
284   /****************************************************************************
285   * Encode key definitions first time.
286   ****************************************************************************/
287   if (first) {
288     char *p1 = keyDefsAbort;
289     EncodeKeyDefinitions (1, &p1, ABORTkey_EXPORT);
290     first = FALSE;
291   }
292   /****************************************************************************
293   * Build export list.
294   ****************************************************************************/
295   BuildExportList (&exportHead, LogicalFALSE);
296   /****************************************************************************
297   * Validate `Record' and `Indices' selections.
298   ****************************************************************************/
299   ValidateRecordIndices (OUTPUTtoFILEh, FALSE, 0L, exportHead);
300   /****************************************************************************
301   * Calculate the width of each line and the maximum record number.
302   ****************************************************************************/
303   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
304      if (Item->output) {
305        /***********************************************************************
306        * Add to total width.
307        ***********************************************************************/
308        addL = BOO(lineL == 0,0,opt.spacing);
309        switch (Item->type) {
310 	 case RECORDt:
311 	   addL += Item->width;
312 	   break;
313 	 case VARIABLEt: {
314 	   int width = BOO(simpleMode,
315 			   StandardWidth(Item->Var->dataType,
316 					 Item->Var->numElems),Item->width);
317 	   addL += (Item->Var->nRecordValues * width) +
318 		   (opt.spacing * (Item->Var->nRecordValues - 1));
319 	   break;
320 	 }
321        }
322        lineL += addL;
323      }
324   }
325   /****************************************************************************
326   * Check if a valid listing.
327   ****************************************************************************/
328   if (lineL == 0) {
329     DisplayMessage ("Nothing selected for listing.", BEEPWAIT1);
330     return TRUE;
331   }
332   /****************************************************************************
333   * Determine first/last records.
334   ****************************************************************************/
335   switch (FirstLastRecord(&firstRec,&lastRec,FALSE,exportHead)) {
336     case PASSED: break;
337     case FAILED: return TRUE;
338     case FATAL: return FALSE;
339   }
340   /****************************************************************************
341   * Remove items from the export list that are not being output or filtered.
342   ****************************************************************************/
343   RemoveExportItems (&exportHead);
344   /****************************************************************************
345   * Allocate buffer for line.
346   ****************************************************************************/
347 #if defined(dos)
348   if (TOObigIBMpc(lineL+1))
349     line = NULL;
350   else
351 #endif
352     line = (char *) cdf_AllocateMemory ((size_t) (lineL+1), NULL);
353   if (line == NULL) {
354     DisplayMessage ("Not enough memory.", BEEPWAIT);
355     return TRUE;
356   }
357   /****************************************************************************
358   * Prompt for listing file path (unless in batch mode) and open file.
359   ****************************************************************************/
360   if (!BATCH(batchMode)) {
361     if (!PromptFor(outputText,DU_MAX_PATH_LEN,strlen(outputText),
362 		   "Enter path for listing file...",oFILEhelpID)) {
363       cdf_FreeMemory (line, FatalError);
364       return TRUE;
365     }
366   }
367   oFp = fopen (outputText, "w");
368   if (oFp == NULL) {
369     DisplayMessage (listOpenError, BEEPWAIT);
370     cdf_FreeMemory (line, FatalError);
371     return TRUE;
372   }
373   /****************************************************************************
374   * Output header line(s).
375   ****************************************************************************/
376   if (opt.textHeading) {
377     if (!ListAttributes(oFp,&cdfFatal)) {
378       if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
379       cdf_FreeMemory (line, FatalError);
380       return (!cdfFatal);
381     }
382     MakeNUL (line);
383     for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
384        if (Item->output) {
385          if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
386          switch (Item->type) {
387 	   case RECORDt:
388 	     CatToString (line, "Record", Item->width, LEFT_JUSTIFY, "*");
389 	     break;
390 	   case VARIABLEt: {
391 	     int standardWidth = StandardWidth(Item->Var->dataType,
392 					       Item->Var->numElems);
393 	     int valueWidth = BOO(simpleMode,standardWidth,Item->width);
394 	     int varWidth = (int) ((Item->Var->nRecordValues*valueWidth) +
395 				   (opt.spacing*(Item->Var->nRecordValues-1)));
396 	     CatToString (line, Item->Var->name, varWidth,
397 			  CENTER_JUSTIFY, "*");
398 	     break;
399 	   }
400          }
401        }
402     }
403     if (fprintf(oFp,"\nVariables:\n\n%s\n",line) < 0) {
404       DisplayMessage (listWriteError, BEEPWAIT);
405       if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
406       cdf_FreeMemory (line, FatalError);
407       return TRUE;
408     }
409   }
410   /****************************************************************************
411   * Read/output values until end of listing.
412   ****************************************************************************/
413   nRecs = lastRec - firstRec + 1;
414   DisplayPctComplete (NO_PCT, pctMsg);
415   NEWkeyDEFS (EWkey, keyDefsAbort, batchMode)
416   for (recN = firstRec; recN <= lastRec; recN++) {
417      if (AbortListing(oFp,line)) {
418        NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
419        return TRUE;
420      }
421      status = EncodeLineHori(line,recN,&filterStatus,exportHead,simpleMode);
422      DisplayStatus (status, readingCDF);
423      if (StatusBAD(status)) {
424        if (fprintf(oFp,"Incomplete listing.\n") < 0) {
425 	 DisplayMessage (listWriteError, BEEPWAIT);
426        }
427        if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
428        cdf_FreeMemory (line, FatalError);
429        return FALSE;
430      }
431      if (SHOWline(filterStatus)) {
432        if (fprintf(oFp,"%s\n",line) < 0) {
433 	 DisplayMessage (listWriteError, BEEPWAIT);
434 	 if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
435 	 cdf_FreeMemory (line, FatalError);
436 	 return TRUE;
437        }
438      }
439      DisplayPctComplete (PCT(recN,nRecs,1,1), pctMsg);
440   }
441   /****************************************************************************
442   * End of listing.
443   ****************************************************************************/
444   NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
445   if (fclose(oFp) == EOF) {
446     DisplayMessage (listCloseError, BEEPWAIT);
447     cdf_FreeMemory (line, FatalError);
448     return TRUE;
449   }
450   cdf_FreeMemory (line, FatalError);
451   if (!BATCH(batchMode)) DisplayMessage ("Complete.", NOBEEPWAIT1);
452   return TRUE;
453 }
454 
455 /******************************************************************************
456 * EncodeLineHori.
457 ******************************************************************************/
458 
EncodeLineHori(line,recN,filterStatus,exportHead,standard)459 CDFstatus EncodeLineHori (line, recN, filterStatus, exportHead, standard)
460 char *line;
461 long recN;
462 int *filterStatus;
463 struct ItemStruct *exportHead;
464 Logical standard;
465 {
466   struct ItemStruct *Item; Logical failedFilter; CDFstatus pStatus = CDF_OK;
467   Logical outRowMajor = ROWmajor(MAJORITYtoOUT(opt.majority,inMajority));
468   /****************************************************************************
469   * Initialize line and filter status.
470   ****************************************************************************/
471   MakeNUL (line);
472   *filterStatus = PASSes;
473   /****************************************************************************
474   * Encode each exported item.
475   ****************************************************************************/
476   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
477      switch (Item->type) {
478        /***********************************************************************
479        * Record number.
480        ***********************************************************************/
481        case RECORDt: {
482 	 /*********************************************************************
483 	 * Check to see if record number passes filter.  If the record number
484 	 * failed the filter...
485 	 *********************************************************************/
486 	 failedFilter = RECORDfailedFILTER(Item,recN);
487 	 if (failedFilter) {
488 	   if (opt.showFiltered)
489 	     *filterStatus = SHOWit;
490 	   else {
491 	     *filterStatus = FAILrecord;
492 	     return pStatus;
493 	   }
494 	 }
495 	 /*********************************************************************
496 	 * Output record number.
497 	 *********************************************************************/
498 	 if (Item->output) {
499 	   if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
500 	   if (failedFilter)
501 	     CatNcharacters (line, Item->width, '-');
502 	   else
503 	     EncodeRecordJustify (EofS(line), recN, -(Item->width));
504 	 }
505 	 break;
506        }
507        /***********************************************************************
508        * Variable.
509        ***********************************************************************/
510        case VARIABLEt: {
511 	 CDFstatus status; int dimN;
512 	 /*********************************************************************
513 	 * Select variable, record number, and indices and read value.
514 	 *********************************************************************/
515 	 status = CDFlib (SELECT_, BOO(Item->Var->zVar,
516 				       zVAR_,rVAR_), Item->Var->varN,
517 				   BOO(Item->Var->zVar,
518 				       zVAR_RECNUMBER_,
519 				       rVARs_RECNUMBER_), recN,
520 			  NULL_);
521 	 if (!sX(status,&pStatus)) return pStatus;
522 	 /*********************************************************************
523 	 * Process each value in the variable record (array).
524 	 *********************************************************************/
525 	 for (dimN = 0; dimN < Item->Var->numDims; dimN++) {
526 	    Item->Var->indices[dimN] = 0;
527 	 }
528 	 for (Item->Var->valueN = 0;
529 	      Item->Var->valueN < Item->Var->nRecordValues;
530 	      Item->Var->valueN++) {
531 	    /******************************************************************
532 	    * Read the next value.
533 	    ******************************************************************/
534 	    status = CDFlib (SELECT_, BOO(Item->Var->zVar,
535 					  zVAR_DIMINDICES_,
536 					  rVARs_DIMINDICES_),
537 							Item->Var->indices,
538 			     GET_, VAR_DATA(Item->Var->zVar), Item->Var->value,
539 			     NULL_);
540 	    if (!sX(status,&pStatus)) return pStatus;
541 	    /******************************************************************
542 	    * Filter value.  If a scalar value was filtered out...
543 	    ******************************************************************/
544 	    failedFilter = VARfailedFILTER(Item,Item->Var->value);
545 	    if (failedFilter && Item->Var->scalar) {
546 	      if (opt.showFiltered)
547 		*filterStatus = SHOWit;
548 	      else {
549 		*filterStatus = FAILrecord;
550 		return pStatus;
551 	      }
552 	    }
553 	    /******************************************************************
554 	    * Encode value.
555 	    ******************************************************************/
556 	    if (Item->output) {
557 	      if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
558 	      if (failedFilter)
559 		CatNcharacters (line, Item->width, '-');
560 	      else {
561 		int standardWidth = StandardWidth(Item->Var->dataType,
562 					          Item->Var->numElems);
563 		int width = BOO(standard,standardWidth,Item->width);
564 		char *format = BOO(standard,
565 				   StandardFormat(Item->Var->dataType),
566 				   Item->Var->format);
567 		EncodeValuesFormat (Item->Var->dataType, Item->Var->numElems,
568 				    Item->Var->value, EofS(line),
569 				    format, width, width, opt.epochStyle);
570 	      }
571 	    }
572 	    /******************************************************************
573 	    * Increment indices.
574 	    ******************************************************************/
575 	    if (outRowMajor)
576 	      INCRindicesROW (Item->Var->numDims, Item->Var->dimSizes,
577 			      Item->Var->indices);
578 	    else
579 	      INCRindicesCOL (Item->Var->numDims, Item->Var->dimSizes,
580 			      Item->Var->indices);
581 	 }
582 	 break;
583        }
584      }
585   }
586   return pStatus;
587 }
588 
589 /******************************************************************************
590 * ToScreenVert.
591 * Output to ASCII/screen, vertical listing.
592 * Returns FALSE if a fatal CDF error occurred (meaning NO_MORE_ACCESS).
593 ******************************************************************************/
594 
ToScreenVert()595 Logical ToScreenVert () {
596   AOSs1 (header, BLANKs78)
597   static char screenLines[SCREENtextMAX+1];
598   static char line[] = { BLANKs78 };
599   AOSs1A (keyDefsPrompt, "More: ________   Exit: ________   Help: ________   Continuous: ________")
600   AOSs1B (keyDefsEnd, "End of listing.  Hit ________ to continue.")
601   AOSs1C (keyDefsLoading, "Loading lines.  Use ________ to abort.")
602   AOSs1D (keyDefsCruise, "Continuous.  Use ________ to stop.")
603   static char *keyDefsAborting[1] = { "Aborting at user's request." };
604   static char *keyDefsInitial[1] = { "Loading..." };
605   static int exitKeys[] = { NUL };
606   static struct EditWindowStruct EWscr = {
607     " Screen Listing ", 0, 0, SCREEN_WIDTH, 1, header, screenLines,
608     NUMscreenLINES, 1, NULL, FALSE, TRUE, exitKeys, REFRESHkey_FSI, NUL, NUL,
609     NUL, NUL, NUL, NUL, NUL, NUL, NUL
610   };
611   int lineN, totalWidth = 0, filterStatus, noRoom = 0, addL, key;
612   int lineL = SCREEN_WIDTH - 2; double timeMark;
613   struct ItemStruct *Item, *exportHead; CDFstatus status;
614   long firstRec, lastRec, recN, nValues = 0, valueN, numDims, atLine;
615   long dimSizes[CDF_MAX_DIMS], indices[CDF_MAX_DIMS], nLinesTotal;
616   long firstIndices[CDF_MAX_DIMS], lastIndices[CDF_MAX_DIMS];
617   Logical prompt = TRUE, same, sameGt0; static Logical first = TRUE;
618   Logical outRowMajor = ROWmajor(MAJORITYtoOUT(opt.majority,inMajority));
619   /****************************************************************************
620   * Encode key definitions first time.
621   ****************************************************************************/
622   if (first) {
623     EncodeKeyDefinitions (1, keyDefsPrompt, ENTERkey_FSI, EXITkey_FSI,
624 			  HELPkey_FSI, CRUISEkey_EXPORT);
625     EncodeKeyDefinitions (1, keyDefsEnd, ENTERkey_FSI);
626     EncodeKeyDefinitions (1, keyDefsCruise, ABORTkey_EXPORT);
627     EncodeKeyDefinitions (1, keyDefsLoading, ABORTkey_EXPORT);
628     first = FALSE;
629   }
630   /****************************************************************************
631   * Build export list.
632   ****************************************************************************/
633   BuildExportList (&exportHead, LogicalFALSE);
634   /****************************************************************************
635   * Determine if the dimensionalities are all the same.
636   ****************************************************************************/
637   same = SameDimensionalities (&numDims, dimSizes, exportHead);
638   sameGt0 = (same && numDims > 0);
639   /****************************************************************************
640   * Validate `Record' and `Indices' selections.
641   ****************************************************************************/
642   ValidateRecordIndices (OUTPUTtoSCREENv, same, numDims, exportHead);
643   /****************************************************************************
644   * Check for enough room for each exported item and calculate the maximum
645   * record number and maximum number of values per record (array).
646   ****************************************************************************/
647   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
648      if (Item->output) {
649        /***********************************************************************
650        * Determine if enough room.
651        ***********************************************************************/
652        addL = BOO(totalWidth == 0,0,opt.spacing) + Item->width;
653        if (totalWidth + addL <= lineL) {
654 	 totalWidth += addL;
655 	 if (Item->type == VARIABLEt) {
656 	   nValues = MAXIMUM(nValues,Item->Var->nRecordValues);
657 	 }
658 	 continue;
659        }
660        /***********************************************************************
661        * Not enough room.
662        ***********************************************************************/
663        noRoom++;
664        Item->output = FALSE;
665      }
666   }
667   /****************************************************************************
668   * Display message if some items could not be listed.
669   ****************************************************************************/
670   if (noRoom > 0) {
671     char msg[SCREEN_WIDTH+1];
672     sprintf (msg, "Not enough room for %d item%s.",
673 	     noRoom, BOO(noRoom == 1,"","s"));
674     DisplayMessage (msg, NOBEEPWAIT1);
675   }
676   /****************************************************************************
677   * Check if a valid listing.
678   ****************************************************************************/
679   if (totalWidth == 0) {
680     DisplayMessage ("Nothing selected for listing.", BEEPWAIT1);
681     return TRUE;
682   }
683   /****************************************************************************
684   * Determine first/last record/indices.
685   ****************************************************************************/
686   switch (FirstLastRecord(&firstRec,&lastRec,FALSE,exportHead)) {
687     case PASSED: break;
688     case FAILED: return TRUE;
689     case FATAL: return FALSE;
690   }
691   if (sameGt0) {
692     switch (FirstLastIndices(numDims,dimSizes,firstIndices,
693 			     lastIndices,&nValues,FALSE,exportHead)) {
694       case PASSED: break;
695       case FAILED: return TRUE;
696       case FATAL: return FALSE;
697     }
698   }
699   /****************************************************************************
700   * Remove items from the export list that are not being output or filtered.
701   ****************************************************************************/
702   RemoveExportItems (&exportHead);
703   /****************************************************************************
704   * Initialize header.
705   ****************************************************************************/
706   MakeNUL (header[0]);
707   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
708      if (Item->output) {
709        if (!NULstring(header[0])) CatNcharacters (header[0],opt.spacing,' ');
710        switch (Item->type) {
711 	 case RECORDt:
712 	   CatToString (header[0], "Record", Item->width, LEFT_JUSTIFY, "*");
713 	   break;
714 	 case INDICESt:
715 	   CatToString (header[0], "Indices", Item->width, LEFT_JUSTIFY, "*");
716 	   break;
717 	 case VARIABLEt:
718 	   CatToString (header[0], Item->Var->name, Item->width,
719 			CENTER_JUSTIFY, "*");
720 	   break;
721        }
722      }
723   }
724   /****************************************************************************
725   * Initialize listing lines and display listing window.
726   ****************************************************************************/
727   MakeNUL (screenLines);
728   lineN = 0;
729   EWscr.tLines = keyDefsInitial;
730   EditWindow (NEWew, &EWscr, LogicalTRUE);
731   nLinesTotal = (lastRec - firstRec + 1) * nValues;
732   timeMark = SystemClock ();
733   /****************************************************************************
734   * Read/list values until end of listing or user requests an early exit.
735   ****************************************************************************/
736   for (recN = firstRec, atLine = 0; recN <= lastRec; recN++) {
737      /*************************************************************************
738      * If same dimensionalities, initialize indices.
739      *************************************************************************/
740      if (sameGt0) {
741        ARRAYtoARRAY (indices, firstIndices, numDims)
742      }
743      /*************************************************************************
744      * For each value...
745      *************************************************************************/
746      for (valueN = 0; valueN < nValues; valueN++) {
747 	/**********************************************************************
748 	* Check if the abort key has been entered.
749 	**********************************************************************/
750 	if (read_input(
751 #if defined(CURSESui)
752 		       EWscr.wid,
753 #endif
754 				 &key,PASSTHRUri,FALSE)) {
755 	  if (key == ABORTkey_EXPORT) {
756 	    if (prompt) {
757 	      EWscr.tLines = keyDefsAborting;
758 	      EditWindow (UPDATEew, &EWscr, LogicalTRUE);
759 	      zzzzz (1.0);
760 	      EditWindow (DELETEew, &EWscr, TRUE);
761 	      return TRUE;
762 	    }
763 	    else
764 	      prompt = TRUE;
765 	  }
766 	  else
767 	    EditWindow (BEEPew, &EWscr);
768 	}
769 	/**********************************************************************
770 	* Should `loading' message be displayed?
771 	**********************************************************************/
772 	if (SystemClock() - timeMark > 1.0) {
773 	  UpdateToScreen (&EWscr, keyDefsLoading[0], atLine, nLinesTotal);
774 	  timeMark = SystemClock ();
775 	}
776 	/**********************************************************************
777 	* Encode line.
778 	**********************************************************************/
779 	status = EncodeLineVert(line,recN,valueN,numDims,indices,
780 				same,&filterStatus,exportHead,
781 				outRowMajor,FALSE);
782 	if (StatusBAD(status)) {
783 	  char text[CDF_STATUSTEXT_LEN+1];
784 	  CDFlib (SELECT_, CDF_STATUS_, status,
785 		  GET_, STATUS_TEXT_, text,
786 		  NULL_);
787 	  InfoWindow ("An error occurred while reading the CDF.", text, NULL,
788 		      TRUE, TRUE, 0);
789 	  EditWindow (DELETEew, &EWscr, TRUE);
790 	  return FALSE;
791 	}
792 	/**********************************************************************
793 	* Check filter status to see if the line should be added to the screen.
794 	**********************************************************************/
795 	if (SHOWline(filterStatus)) {
796 	  if (lineN == NUMscreenLINES) {
797 	    Logical loop = TRUE;
798 	    UpdateToScreen (&EWscr, BOO(prompt,keyDefsPrompt[0],
799 					       keyDefsCruise[0]),
800 			    atLine, nLinesTotal);
801 	    if (prompt)
802 	      EditWindow (READew, &EWscr);
803 	    else
804 	      EWscr.key = ENTERkey_FSI;
805 	    while (loop) {
806 	      switch (EWscr.key) {
807 		case CRUISEkey_EXPORT:
808 		  prompt = FALSE;       /* No `break' is intentional. */
809 		case ENTERkey_FSI:
810 		  MakeNUL (screenLines);
811 		  lineN = 0;
812 		  loop = FALSE;
813 		  break;
814 		case HELPkey_FSI:
815 		  OnlineHelpWindow ("cdfxp.ilh", SCREENhelpID);
816 		  EditWindow (READew, &EWscr);
817 		  break;
818 		case EXITkey_FSI:
819 		  EditWindow (DELETEew, &EWscr, TRUE);
820 		  return TRUE;
821 		default:
822 		  EditWindow (BEEPew, &EWscr);
823 		  EditWindow (READew, &EWscr);
824 		  break;
825 	      }
826 	    }
827 	    timeMark = SystemClock ();
828 	  }
829 	  strcatX (screenLines, line, SCREENtextMAX);
830 	  strcatX (screenLines, "\n", SCREENtextMAX);
831 	  lineN++;
832 	}
833 	/**********************************************************************
834 	* Check filter status to see if this record should be aborted.
835 	**********************************************************************/
836 	if (filterStatus == FAILrecord) {
837 	  atLine += nValues;
838 	  break;
839 	}
840 	/**********************************************************************
841 	* If same dimensionalities, increment indices.
842 	**********************************************************************/
843 	if (sameGt0) {
844 	  if (outRowMajor)
845 	    IncrIndicesFirstLastRow (numDims, firstIndices,
846 				     lastIndices, indices);
847 	  else
848 	    IncrIndicesFirstLastCol (numDims, firstIndices,
849 				     lastIndices, indices);
850 	}
851 	/**********************************************************************
852 	* Increment percentage counter.
853 	**********************************************************************/
854 	atLine++;
855      }
856   }
857   /****************************************************************************
858   * End of listing.
859   ****************************************************************************/
860   EWscr.tLines = keyDefsEnd;
861   EditWindow (UPDATEew, &EWscr, LogicalTRUE);
862   EditWindow (READew, &EWscr);
863   EditWindow (DELETEew, &EWscr, TRUE);
864   return TRUE;
865 }
866 
867 /******************************************************************************
868 * ToFileVert.
869 * Output to ASCII/file, vertical listing.
870 * Returns FALSE if a fatal CDF error occurred (meaning NO_MORE_ACCESS).
871 ******************************************************************************/
872 
ToFileVert()873 Logical ToFileVert () {
874   int lineL = 0, filterStatus;
875   struct ItemStruct *Item, *exportHead; FILE *oFp; char *line;
876   long firstRec, lastRec, recN, maxRecordValues = 0, valueN, numDims;
877   long dimSizes[CDF_MAX_DIMS], nLinesTotal, atLine;
878   long indices[CDF_MAX_DIMS], firstIndices[CDF_MAX_DIMS];
879   long lastIndices[CDF_MAX_DIMS]; Logical same, sameGt0;
880   Logical outRowMajor = ROWmajor(MAJORITYtoOUT(opt.majority,inMajority));
881   CDFstatus status; Logical first = TRUE, cdfFatal;
882   static char pctMsg[] = "Listing started...";
883   static char keyDefsBlank[] = "\n\n";
884   static char keyDefsAbort[] = "Abort: ________\n\n";
885   /****************************************************************************
886   * Encode key definitions first time.
887   ****************************************************************************/
888   if (first) {
889     char *p1 = keyDefsAbort;
890     EncodeKeyDefinitions (1, &p1, ABORTkey_EXPORT);
891     first = FALSE;
892   }
893   /****************************************************************************
894   * Build export list.
895   ****************************************************************************/
896   BuildExportList (&exportHead, LogicalFALSE);
897   /****************************************************************************
898   * Determine if the dimensionalities are all the same.
899   ****************************************************************************/
900   same = SameDimensionalities (&numDims, dimSizes, exportHead);
901   sameGt0 = (same && numDims > 0);
902   /****************************************************************************
903   * Validate `Record' and `Indices' selections.
904   ****************************************************************************/
905   ValidateRecordIndices (OUTPUTtoFILEv, same, numDims, exportHead);
906   /****************************************************************************
907   * Calculate the width of each line and the maximum record number and
908   * maximum number of values per record (array).
909   ****************************************************************************/
910   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
911      if (Item->output) {
912        switch (Item->type) {
913 	 case RECORDt:
914 	 case INDICESt:
915 	   lineL += BOO(lineL == 0,0,opt.spacing) + Item->width;
916 	   break;
917 	 case VARIABLEt: {
918 	   int width = BOO(simpleMode,
919 			   StandardWidth(Item->Var->dataType,
920 					 Item->Var->numElems),Item->width);
921 	   int addL = BOO(lineL == 0,0,opt.spacing) + width;
922 	   lineL += addL;
923 	   maxRecordValues = MAXIMUM(maxRecordValues,Item->Var->nRecordValues);
924 	   break;
925 	 }
926        }
927      }
928   }
929   /****************************************************************************
930   * Check if a valid listing.
931   ****************************************************************************/
932   if (lineL == 0) {
933     DisplayMessage ("Nothing selected for listing.", BEEPWAIT1);
934     return TRUE;
935   }
936   /****************************************************************************
937   * Determine first/last records/indices.
938   ****************************************************************************/
939   switch (FirstLastRecord(&firstRec,&lastRec,FALSE,exportHead)) {
940     case PASSED: break;
941     case FAILED: return TRUE;
942     case FATAL: return FALSE;
943   }
944   if (sameGt0) {
945     switch (FirstLastIndices(numDims,dimSizes,firstIndices,lastIndices,
946 			     &maxRecordValues,FALSE,exportHead)) {
947       case PASSED: break;
948       case FAILED: return TRUE;
949       case FATAL: return FALSE;
950     }
951   }
952   /****************************************************************************
953   * Remove items from the export list that are not being output or filtered.
954   ****************************************************************************/
955   RemoveExportItems (&exportHead);
956   /****************************************************************************
957   * Allocate buffer for line.
958   ****************************************************************************/
959   line = (char *) cdf_AllocateMemory ((size_t) (lineL + 1), NULL);
960   if (line == NULL) {
961     DisplayMessage ("Not enough memory.", BEEPWAIT);
962     return TRUE;
963   }
964   /****************************************************************************
965   * Prompt for listing file path (unless in batch mode) and open file.
966   ****************************************************************************/
967   if (!BATCH(batchMode)) {
968     if (!PromptFor(outputText,DU_MAX_PATH_LEN,strlen(outputText),
969 		   "Enter path for listing file...",oFILEhelpID)) {
970       cdf_FreeMemory (line, FatalError);
971       return TRUE;
972     }
973   }
974   oFp = fopen (outputText, "w");
975   if (oFp == NULL) {
976     DisplayMessage (listOpenError, BEEPWAIT);
977     cdf_FreeMemory (line, FatalError);
978     return TRUE;
979   }
980   /****************************************************************************
981   * Output header line(s).
982   ****************************************************************************/
983   if (opt.textHeading) {
984     if (!ListAttributes(oFp,&cdfFatal)) {
985       if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
986       cdf_FreeMemory (line, FatalError);
987       return (!cdfFatal);
988     }
989     MakeNUL (line);
990     for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
991        if (Item->output) {
992          if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
993          switch (Item->type) {
994 	   case RECORDt:
995 	     CatToString (line, "Record", Item->width, LEFT_JUSTIFY, "*");
996 	     break;
997 	   case INDICESt:
998 	     CatToString (line, "Indices", Item->width, LEFT_JUSTIFY, "*");
999 	     break;
1000 	   case VARIABLEt: {
1001 	     int standardWidth = StandardWidth(Item->Var->dataType,
1002 					       Item->Var->numElems);
1003 	     int valueWidth = BOO(simpleMode,standardWidth,Item->width);
1004 	     CatToString (line, Item->Var->name, valueWidth,
1005 			  CENTER_JUSTIFY, "*");
1006 	     break;
1007 	   }
1008          }
1009        }
1010     }
1011     if (fprintf(oFp,"\nVariables:\n\n%s\n",line) < 0) {
1012       DisplayMessage (listWriteError, BEEPWAIT);
1013       if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
1014       cdf_FreeMemory (line, FatalError);
1015       return TRUE;
1016     }
1017   }
1018   /****************************************************************************
1019   * If same dimensionalities, initialize indices.
1020   ****************************************************************************/
1021   if (sameGt0) {
1022     ARRAYtoARRAY (indices, firstIndices, numDims)
1023   }
1024   /****************************************************************************
1025   * Read/output values until end of listing.
1026   ****************************************************************************/
1027   nLinesTotal = (lastRec - firstRec + 1) * maxRecordValues;
1028   DisplayPctComplete (NO_PCT, pctMsg);
1029   NEWkeyDEFS (EWkey, keyDefsAbort, batchMode)
1030   for (recN = firstRec, atLine = 0; recN <= lastRec; recN++) {
1031      for (valueN = 0; valueN < maxRecordValues; valueN++) {
1032 	/**********************************************************************
1033 	* Check for abort key.
1034 	**********************************************************************/
1035 	if (AbortListing(oFp,line)) {
1036 	  NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
1037 	  return TRUE;
1038 	}
1039 	/**********************************************************************
1040 	* Encode line.
1041 	**********************************************************************/
1042 	status = EncodeLineVert(line,recN,valueN,numDims,indices,
1043 				same,&filterStatus,exportHead,
1044 				outRowMajor,simpleMode);
1045 	DisplayStatus (status, readingCDF);
1046 	if (StatusBAD(status)) {
1047 	  if (fprintf(oFp,"Incomplete listing.\n") < 0) {
1048 	    DisplayMessage (listWriteError, BEEPWAIT);
1049 	  }
1050 	  if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
1051 	  cdf_FreeMemory (line, FatalError);
1052 	  return FALSE;
1053 	}
1054 	/**********************************************************************
1055 	* Check filter status to see if the line should be output.
1056 	**********************************************************************/
1057 	if (SHOWline(filterStatus)) {
1058 	  if (fprintf(oFp,"%s\n",line) < 0) {
1059 	    DisplayMessage (listWriteError, BEEPWAIT);
1060 	    if (fclose(oFp) == EOF) DisplayMessage (listCloseError, BEEPWAIT);
1061 	    cdf_FreeMemory (line, FatalError);
1062 	    return TRUE;
1063 	  }
1064 	}
1065 	/**********************************************************************
1066 	* Check filter status to see if this record should be aborted.
1067 	**********************************************************************/
1068 	if (filterStatus == FAILrecord) {
1069 	  while (valueN < maxRecordValues) {
1070 	    DisplayPctComplete (PCT(atLine,nLinesTotal,1,1), pctMsg);
1071 	    valueN++;
1072 	    atLine++;
1073 	  }
1074 	  break;
1075 	}
1076 	/**********************************************************************
1077 	* If same dimensionalities, increment indices.
1078 	**********************************************************************/
1079 	if (sameGt0) {
1080 	  if (outRowMajor)
1081 	    IncrIndicesFirstLastRow (numDims, firstIndices,
1082 				     lastIndices, indices);
1083 	  else
1084 	    IncrIndicesFirstLastCol (numDims, firstIndices,
1085 				     lastIndices, indices);
1086 	}
1087 	/**********************************************************************
1088 	* Update percentage complete message.
1089 	**********************************************************************/
1090 	DisplayPctComplete (PCT(atLine,nLinesTotal,1,1), pctMsg);
1091 	atLine++;
1092      }
1093   }
1094   /****************************************************************************
1095   * End of listing.
1096   ****************************************************************************/
1097   NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
1098   if (fclose(oFp) == EOF) {
1099     DisplayMessage (listCloseError, BEEPWAIT);
1100     cdf_FreeMemory (line, FatalError);
1101     return TRUE;
1102   }
1103   cdf_FreeMemory (line, FatalError);
1104   if (!BATCH(batchMode)) DisplayMessage ("Complete.", NOBEEPWAIT1);
1105   return TRUE;
1106 }
1107 
1108 /******************************************************************************
1109 * EncodeLineVert.
1110 ******************************************************************************/
1111 
EncodeLineVert(line,recN,valueN,numDims,indices,same,filterStatus,exportHead,outRowMajor,standard)1112 CDFstatus EncodeLineVert (line, recN, valueN, numDims, indices, same,
1113 			  filterStatus, exportHead, outRowMajor, standard)
1114 char *line;
1115 long recN;
1116 long valueN;                    /* Ignored if same dimensionalities. */
1117 long numDims;                   /* Ignored if different dimensionalities. */
1118 long indices[CDF_MAX_DIMS];     /* Ignored if different dimensionalities. */
1119 Logical same;
1120 int *filterStatus;
1121 struct ItemStruct *exportHead;
1122 Logical outRowMajor;
1123 Logical standard;
1124 {
1125   struct ItemStruct *Item; CDFstatus pStatus = CDF_OK; Logical failedFilter;
1126   /****************************************************************************
1127   * Initialize line and filter status.
1128   ****************************************************************************/
1129   MakeNUL (line);
1130   *filterStatus = PASSes;
1131   /****************************************************************************
1132   * Encode each exported item.
1133   ****************************************************************************/
1134   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
1135      switch (Item->type) {
1136        /***********************************************************************
1137        * Record number.
1138        ***********************************************************************/
1139        case RECORDt: {
1140 	 failedFilter = RECORDfailedFILTER(Item,recN);
1141 	 if (failedFilter) {
1142 	   if (opt.showFiltered)
1143 	     *filterStatus = SHOWit;
1144 	   else {
1145 	     *filterStatus = FAILrecord;
1146 	     return pStatus;
1147 	   }
1148 	 }
1149 	 if (Item->output) {
1150 	   if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
1151 	   if (failedFilter)
1152 	     CatNcharacters (line, Item->width, '-');
1153 	   else
1154 	     EncodeRecordJustify (EofS(line), recN, -(Item->width));
1155 	 }
1156 	 break;
1157        }
1158        /***********************************************************************
1159        * Indices.
1160        *   This case will not occur if different dimensionalities.
1161        ***********************************************************************/
1162        case INDICESt: {
1163 	 /*********************************************************************
1164 	 * Filter indices.
1165 	 *********************************************************************/
1166 	 failedFilter = INDICESfailedFILTER(Item,indices);
1167 	 if (failedFilter) {
1168 	   if (opt.showFiltered)
1169 	     *filterStatus = SHOWit;
1170 	   else {
1171 	     *filterStatus = FAILline;
1172 	     return pStatus;
1173 	   }
1174 	 }
1175 	 /*********************************************************************
1176 	 * Output indices (if requested).
1177 	 *********************************************************************/
1178 	 if (Item->output) {
1179 	   if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
1180 	   if (failedFilter)
1181 	     CatNcharacters (line, Item->width, '-');
1182 	   else
1183 	     EncodeIndicesJustify (EofS(line), numDims, indices,
1184 				   -(Item->width));
1185 	 }
1186 	 break;
1187        }
1188        /***********************************************************************
1189        * Variable.
1190        ***********************************************************************/
1191        case VARIABLEt: {
1192 	 CDFstatus status; int dimN;
1193 	 int standardWidth = StandardWidth(Item->Var->dataType,
1194 					   Item->Var->numElems);
1195 	 int width = BOO(standard,standardWidth,Item->width);
1196 	 char *format = BOO(standard,
1197 			    StandardFormat(Item->Var->dataType),
1198 			    Item->Var->format);
1199 	 /*********************************************************************
1200 	 * If different dimensionalities and first value in a record,
1201 	 * initialize the indices and value number for the variable.
1202 	 *********************************************************************/
1203 	 if (!same) {
1204 	   if (valueN == 0) {
1205 	     for (dimN = 0; dimN < Item->Var->numDims; dimN++) {
1206 		Item->Var->indices[dimN] = 0;
1207 	     }
1208 	     Item->Var->valueN = 0;
1209 	   }
1210 	 }
1211 	 /*********************************************************************
1212 	 * If different dimensionalities, check if no more values for this
1213 	 * variable.
1214 	 *********************************************************************/
1215 	 if (!same) {
1216 	   if (Item->Var->valueN == Item->Var->nRecordValues) {
1217 	     if (Item->output) {
1218 	       if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
1219 	       CatNcharacters (line, width, ' ');
1220 	     }
1221 	     break;
1222 	   }
1223 	 }
1224 	 /*********************************************************************
1225 	 * Select variable, record number, and indices and then read value.
1226 	 *********************************************************************/
1227 	 status = CDFlib (SELECT_, BOO(Item->Var->zVar,
1228 				       zVAR_,rVAR_), Item->Var->varN,
1229 				   BOO(Item->Var->zVar,
1230 				       zVAR_RECNUMBER_,rVARs_RECNUMBER_), recN,
1231 				   BOO(Item->Var->zVar,
1232 				       zVAR_DIMINDICES_,
1233 				       rVARs_DIMINDICES_),
1234 					  BOO(same,indices,Item->Var->indices),
1235 			  GET_, BOO(Item->Var->zVar,
1236 				    zVAR_DATA_,rVAR_DATA_), Item->Var->value,
1237 			  NULL_);
1238 	 if (!sX(status,&pStatus)) return pStatus;
1239 	 /*********************************************************************
1240 	 * Filter value.  If the value failed the filter...
1241 	 *********************************************************************/
1242 	 failedFilter = VARfailedFILTER(Item,Item->Var->value);
1243 	 if (failedFilter) {
1244 	   if (opt.showFiltered)
1245 	     *filterStatus = SHOWit;
1246 	   else {
1247 	     if (same) {
1248 	       if (Item->Var->scalar)
1249 		 *filterStatus = FAILrecord;
1250 	       else
1251 		 *filterStatus = FAILline;
1252 	       return pStatus;
1253 	     }
1254 	     else {
1255 	       if (Item->Var->nRecordValues == 1) {
1256 		 *filterStatus = FAILrecord;
1257 		 return pStatus;
1258 	       }
1259 	     }
1260 	   }
1261 	 }
1262 	 /*********************************************************************
1263 	 * Encode value.
1264 	 *********************************************************************/
1265 	 if (Item->output) {
1266 	   if (!NULstring(line)) CatNcharacters (line, opt.spacing, ' ');
1267 	   if (failedFilter)
1268 	     CatNcharacters (line, width, '-');
1269 	   else
1270 	     EncodeValuesFormat (Item->Var->dataType, Item->Var->numElems,
1271 				 Item->Var->value, EofS(line),
1272 				 format, width, width, opt.epochStyle);
1273 	 }
1274 	 /*********************************************************************
1275 	 * If different dimensionalities, increment to next value/indices.
1276 	 *********************************************************************/
1277 	 if (!same) {
1278 	   if (outRowMajor)
1279 	     INCRindicesROW (Item->Var->numDims, Item->Var->dimSizes,
1280 			     Item->Var->indices);
1281 	   else
1282 	     INCRindicesCOL (Item->Var->numDims, Item->Var->dimSizes,
1283 			     Item->Var->indices);
1284 	   Item->Var->valueN++;
1285 	 }
1286 	 break;
1287        }
1288      }
1289   }
1290   return pStatus;
1291 }
1292 
1293 /******************************************************************************
1294 * ListAttributes.
1295 * Returns FALSE if an error occurred.
1296 ******************************************************************************/
1297 
ListAttributes(oFp,cdfFatal)1298 Logical ListAttributes (oFp, cdfFatal)
1299 FILE *oFp;
1300 Logical *cdfFatal;	/* Set TRUE if a fatal CDF error occurred. */
1301 {
1302   CDFstatus status; long attrN, nAttrs;
1303   /****************************************************************************
1304   * Display heading.
1305   ****************************************************************************/
1306   if (fprintf(oFp,"Global attributes:\n") < 0) {
1307     *cdfFatal = FALSE;
1308     return FALSE;
1309   }
1310   /****************************************************************************
1311   * Inquire the number of attributes.
1312   ****************************************************************************/
1313   status = CDFlib (GET_, CDF_NUMATTRS_, &nAttrs,
1314 		   NULL_);
1315   DisplayStatus (status, readingCDF);
1316   if (StatusBAD(status)) {
1317     *cdfFatal = TRUE;
1318     return FALSE;
1319   }
1320   /****************************************************************************
1321   * For each attribute...
1322   ****************************************************************************/
1323   for (attrN = 0; attrN < nAttrs; attrN++) {
1324      long scope;
1325      /*************************************************************************
1326      * Inquire the attribute scope.
1327      *************************************************************************/
1328      status = CDFlib (SELECT_, ATTR_, attrN,
1329 		      GET_, ATTR_SCOPE_, &scope,
1330 		      NULL_);
1331      DisplayStatus (status, readingCDF);
1332      if (StatusBAD(status)) {
1333        *cdfFatal = TRUE;
1334        return FALSE;
1335      }
1336      /*************************************************************************
1337      * If a gAttribute...
1338      *************************************************************************/
1339      if (scope == GLOBAL_SCOPE) {
1340        long maxEntry, entryN; char attrName[CDF_ATTR_NAME_LEN+1];
1341        /***********************************************************************
1342        * Inquire the attribute's name and maximum gEntry number.
1343        ***********************************************************************/
1344        status = CDFlib (GET_, ATTR_NAME_, attrName,
1345 			ATTR_MAXgENTRY_, &maxEntry,
1346 			NULL_);
1347        DisplayStatus (status, readingCDF);
1348        if (StatusBAD(status)) {
1349 	 *cdfFatal = TRUE;
1350 	 return FALSE;
1351        }
1352        RemoveTrailingBlanks (attrName);
1353        if (fprintf(oFp,"\n  %s\n",attrName) < 0) {
1354 	 *cdfFatal = FALSE;
1355 	 return FALSE;
1356        }
1357        /***********************************************************************
1358        * For each gEntry...
1359        ***********************************************************************/
1360        for (entryN = 0; entryN <= maxEntry; entryN++) {
1361 	  long dataType, numElems, nBytes; void *value;
1362 	  char encoded[MAXgENTRYencodedLEN+1];
1363 	  /********************************************************************
1364 	  * If this entry might exist...
1365 	  ********************************************************************/
1366 	  status = CDFlib (SELECT_, gENTRY_, entryN,
1367 			   CONFIRM_, CURgENTRY_EXISTENCE_,
1368 			   NULL_);
1369 	  if (status != NO_SUCH_ENTRY) {
1370 	    /******************************************************************
1371 	    * Check if some other error occurred.
1372 	    ******************************************************************/
1373 	    DisplayStatus (status, readingCDF);
1374 	    if (StatusBAD(status)) {
1375 	      *cdfFatal = TRUE;
1376 	      return FALSE;
1377 	    }
1378 	    /******************************************************************
1379 	    * Inquire the data specification.
1380 	    ******************************************************************/
1381 	    status = CDFlib (GET_, gENTRY_DATATYPE_, &dataType,
1382 				   gENTRY_NUMELEMS_, &numElems,
1383 			     NULL_);
1384 	    DisplayStatus (status, readingCDF);
1385 	    if (StatusBAD(status)) {
1386 	      *cdfFatal = TRUE;
1387 	      return FALSE;
1388 	    }
1389 	    /******************************************************************
1390 	    * Inquire the value.
1391 	    ******************************************************************/
1392 	    nBytes = CDFelemSize(dataType) * numElems;
1393 	    value = cdf_AllocateMemory ((size_t) nBytes, FatalError);
1394 	    status = CDFlib (GET_, gENTRY_DATA_, value,
1395 			     NULL_);
1396 	    DisplayStatus (status, readingCDF);
1397 	    if (StatusBAD(status)) {
1398 	      *cdfFatal = TRUE;
1399 	      return FALSE;
1400 	    }
1401 	    /******************************************************************
1402 	    * List the value.
1403 	    ******************************************************************/
1404 	    EncodeValuesFormat (dataType, numElems, value, encoded, NULL,
1405 				0, MAXgENTRYencodedLEN, opt.epochStyle);
1406 	    if (fprintf(oFp,"    %s\n",encoded) < 0) {
1407 	      *cdfFatal = FALSE;
1408 	      return FALSE;
1409 	    }
1410 	    cdf_FreeMemory (value, FatalError);
1411 	  }
1412        }
1413      }
1414   }
1415   return TRUE;
1416 }
1417 
1418 /******************************************************************************
1419 * ToCDF.
1420 * Output to CDF.
1421 * Returns FALSE if a fatal error occurred on the input CDF only.
1422 * This routine must ensure that the input CDF is made the current CDF
1423 * before returning.  It is assumed that the input CDF is also the current
1424 * CDF when this routine is called.
1425 ******************************************************************************/
1426 
ToCDF(inID)1427 Logical ToCDF (inID)
1428 CDFid inID;
1429 {
1430   int dimN; CDFid outID; Logical same, sameGt0;
1431   struct ItemStruct *Item; CDFstatus status;
1432   struct ItemStruct *exportHead;
1433   long outMajority = MAJORITYtoOUT(opt.majority,inMajority);
1434   long firstRec, lastRec, nAttrs;
1435   long numDims, dimSizes[CDF_MAX_DIMS];
1436   long firstIndices[CDF_MAX_DIMS], lastIndices[CDF_MAX_DIMS];
1437   static char keyDefsBlank[] = "\n\n";
1438   /****************************************************************************
1439   * Build export list.
1440   ****************************************************************************/
1441   BuildExportList (&exportHead, LogicalFALSE);
1442   /****************************************************************************
1443   * Determine if the variables being output/filtered have the same
1444   * dimensionalities.
1445   ****************************************************************************/
1446   same = SameDimensionalities (&numDims, dimSizes, exportHead);
1447   sameGt0 = (same && numDims > 0);
1448   /****************************************************************************
1449   * Validate `Record' and `Indices' selections.
1450   ****************************************************************************/
1451   ValidateRecordIndices (OUTPUTtoCDF, same, numDims, exportHead);
1452   /****************************************************************************
1453   * Check the number of variables being output.  Note that at this point if
1454   * an item is being output then it must be a variable.
1455   ****************************************************************************/
1456   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
1457      if (Item->output) break;
1458   }
1459   if (Item == NULL) {
1460     DisplayMessage ("No variables selected for output.", BEEPWAIT1);
1461     return TRUE;
1462   }
1463   /****************************************************************************
1464   * Calculate the first/last record and indices.
1465   ****************************************************************************/
1466   switch (FirstLastRecord(&firstRec,&lastRec,TRUE,exportHead)) {
1467     case PASSED: break;
1468     case FAILED: return TRUE;
1469     case FATAL: return FALSE;
1470   }
1471   if (sameGt0) {
1472     switch (FirstLastIndices(numDims,dimSizes,firstIndices,
1473 			     lastIndices,NULL,TRUE,exportHead)) {
1474       case PASSED: break;
1475       case FAILED: return TRUE;
1476       case FATAL: return FALSE;
1477     }
1478   }
1479   /****************************************************************************
1480   * Remove items from the export list that are not being output or filtered.
1481   ****************************************************************************/
1482   RemoveExportItems (&exportHead);
1483   /****************************************************************************
1484   * Prompt for new CDF's path unless in batch mode.
1485   ****************************************************************************/
1486   if (!BATCH(batchMode)) {
1487     if (!PromptFor(outputCDF,CDF_PATHNAME_LEN,strlen(outputCDF),
1488 		   "Enter path for output CDF...",oCDFhelpID)) return TRUE;
1489   }
1490   /****************************************************************************
1491   * If same dimensionalities, calculate rDimensionality for output CDF.  If
1492   * different dimensionalities, inquire rDimensionality of input CDF.
1493   ****************************************************************************/
1494   if (sameGt0) {
1495     for (dimN = 0; dimN < numDims; dimN++) {
1496        dimSizes[dimN] = lastIndices[dimN] - firstIndices[dimN] + 1;
1497     }
1498   }
1499   else {
1500     status = CDFlib (GET_, rVARs_NUMDIMS_, &numDims,
1501 			   rVARs_DIMSIZES_, dimSizes,
1502 		     NULL_);
1503     DisplayStatus (status, readingCDF);
1504     if (StatusBAD(status)) return FALSE;
1505   }
1506   /****************************************************************************
1507   * Delete existing CDF with same name?
1508   ****************************************************************************/
1509   if (opt.deleteExisting) {
1510     if (IsCDF(outputCDF)) {
1511       if (!BATCH(batchMode)) {
1512 	DisplayMessage ("Deleting existing output CDF...", NOWAIT);
1513       }
1514       status = CDFlib (OPEN_, CDF_, outputCDF, &outID,
1515 		       NULL_);
1516       DisplayStatus (status, "opening existing CDF");
1517       if (StatusBAD(status)) {
1518 	SELECTcdf (inID);
1519 	return TRUE;
1520       }
1521       status = CDFlib (DELETE_, CDF_,
1522 		       NULL_);
1523       DisplayStatus (status, "deleting existing CDF");
1524       if (StatusBAD(status)) {
1525 	CDFclose (outID);
1526 	SELECTcdf (inID);
1527 	return TRUE;
1528       }
1529       if (!BATCH(batchMode)) DisplayMessage ("", NOWAIT);
1530     }
1531   }
1532   /****************************************************************************
1533   * Create output CDF.
1534   ****************************************************************************/
1535   if (!BATCH(batchMode)) DisplayMessage ("Creating output CDF...", NOWAIT);
1536   status = CDFlib (CREATE_, CDF_, outputCDF, numDims, dimSizes, &outID,
1537 		   NULL_);
1538   DisplayStatus (status, "creating output CDF");
1539   if (StatusBAD(status)) {
1540     SELECTcdf (inID);
1541     return TRUE;
1542   }
1543   status = CDFlib (SELECT_, CDF_CACHESIZE_, workingCache,
1544 			    STAGE_CACHESIZE_, stageCache,
1545 			    COMPRESS_CACHESIZE_, compressCache,
1546 		   PUT_, CDF_FORMAT_, BOO(opt.singleFile,SINGLE_FILE,
1547 							 MULTI_FILE),
1548 			 CDF_ENCODING_, opt.encoding,
1549 			 CDF_MAJORITY_, outMajority,
1550 			 CDF_COMPRESSION_, CDFcType, CDFcParms,
1551 			 CDF_CHECKSUM_, CDFchecksum,
1552 		   NULL_);
1553   DisplayStatus (status, "configuring output CDF");
1554   if (StatusBAD(status)) {
1555     CDFclose (outID);
1556     SELECTcdf (inID);
1557     return TRUE;
1558   }
1559   /****************************************************************************
1560   * Create attributes/entries and variables in output CDF.
1561   ****************************************************************************/
1562   switch (CopyAttributesANDgEntries(inID,outID,&nAttrs)) {
1563     case SUCCESS:
1564       break;
1565     case FATALin:
1566       CDFclose (outID);
1567       SELECTcdf (inID);
1568       return FALSE;
1569     case FATALout:
1570       CDFclose (outID);
1571       SELECTcdf (inID);
1572       return TRUE;
1573   }
1574   switch (CopyVariablesANDrzEntries(inID,outID,nAttrs,same,
1575 				    numDims,dimSizes,exportHead)) {
1576     case SUCCESS:
1577       break;
1578     case FATALin:
1579       CDFclose (outID);
1580       SELECTcdf (inID);
1581       return FALSE;
1582     case FATALout:
1583       CDFclose (outID);
1584       SELECTcdf (inID);
1585       return TRUE;
1586   }
1587   /****************************************************************************
1588   * Write to variables in output CDF.
1589   ****************************************************************************/
1590   switch (BOO(sameGt0,ToCDFsameGt0(inID,outID,firstRec,lastRec,
1591 				   numDims,dimSizes,firstIndices,
1592 				   outMajority,exportHead),
1593 		      ToCDFdiffOrZero(inID,outID,firstRec,
1594 				      lastRec,outMajority,exportHead))) {
1595     case SUCCESS:
1596       break;
1597     case FATALin:
1598       CDFclose (outID);
1599       SELECTcdf (inID);
1600       return FALSE;
1601     case FATALout:
1602       CDFclose (outID);
1603       SELECTcdf (inID);
1604       return TRUE;
1605   }
1606   /****************************************************************************
1607   * Close output CDF.
1608   ****************************************************************************/
1609   NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
1610   if (!BATCH(batchMode)) DisplayMessage ("Closing CDF...", NOWAIT);
1611   if (dumpStats) {
1612     vSTATS vStatsDotCDF, vStatsStage, vStatsCompress;
1613     char temp1[MAX_SCREENLINE_LEN+1],
1614 	 temp2[MAX_SCREENLINE_LEN+1],
1615 	 temp3[MAX_SCREENLINE_LEN+1];
1616     if (!BATCH(batchMode)) DisplayMessage ("", NOWAIT);
1617     status = CDFlib (SELECT_, CDF_, outID,
1618 		     CLOSE_, CDFwithSTATS_, &vStatsDotCDF,
1619 					    &vStatsStage,
1620 					    &vStatsCompress,
1621 		     NULL_);
1622     DisplayStatus (status, "closing output CDF");
1623     if (StatusOK(status)) {
1624       if (vStatsDotCDF.maxBuffers > 0) {
1625         BuildStatistics ("output CDF DotCDF file", &vStatsDotCDF,
1626 		         temp1, temp2, temp3);
1627 	if (BATCH(batchMode))
1628 	  printf ("%s\n%s\n%s\n", temp1, temp2, temp3);
1629 	else
1630 	  InfoWindow (temp1, temp2, temp3, FALSE, FALSE, 0);
1631       }
1632       if (vStatsStage.maxBuffers > 0) {
1633         BuildStatistics ("output CDF staging file", &vStatsStage,
1634 		         temp1, temp2, temp3);
1635 	if (BATCH(batchMode))
1636 	  printf ("%s\n%s\n%s\n", temp1, temp2, temp3);
1637 	else
1638 	  InfoWindow (temp1, temp2, temp3, FALSE, FALSE, 0);
1639       }
1640       if (vStatsCompress.maxBuffers > 0) {
1641         BuildStatistics ("output CDF compression scratch file",
1642 			 &vStatsCompress, temp1, temp2, temp3);
1643 	if (BATCH(batchMode))
1644 	  printf ("%s\n%s\n%s\n", temp1, temp2, temp3);
1645 	else
1646 	  InfoWindow (temp1, temp2, temp3, FALSE, FALSE, 0);
1647       }
1648     }
1649   }
1650   else {
1651     status = CDFclose (outID);
1652     DisplayStatus (status, "closing output CDF");
1653     if (StatusOK(status)) {
1654       if (!BATCH(batchMode)) DisplayMessage ("", NOBEEPWAIT1);
1655     }
1656   }
1657   SELECTcdf (inID);
1658   return TRUE;
1659 }
1660 
1661 /******************************************************************************
1662 * ToCDFsameGt0.
1663 * Same dimensionalities and the number of dimensions is greater than zero.
1664 * Returns SUCCESS, FATALin, or FATALout;
1665 ******************************************************************************/
1666 
ToCDFsameGt0(inID,outID,firstRec,lastRec,numDims,dimSizes,firstIndices,outMajority,exportHead)1667 int ToCDFsameGt0 (inID, outID, firstRec, lastRec, numDims, dimSizes,
1668 		  firstIndices, outMajority, exportHead)
1669 CDFid inID;
1670 CDFid outID;
1671 long firstRec;
1672 long lastRec;
1673 long numDims;           /* For the output CDF. */
1674 long dimSizes[];        /* For the output CDF. */
1675 long firstIndices[];    /* From the input CDF. */
1676 long outMajority;
1677 struct ItemStruct *exportHead;
1678 {
1679   long nValues, nRecordValues, indicesI[CDF_MAX_DIMS], nHypers, hyperN;
1680   long recF, recL; static Logical first = TRUE;
1681   int dimN, i; Byte ***handles; size_t *nValueBytes;
1682   int scalarCount, hyperCount, varCount, scalarX, hyperX;
1683   struct ItemStruct *Item, *prevItem, *scalarHead, *scalarTail;
1684   struct ItemStruct *hyperHead, *hyperTail;
1685   struct HyperStruct hyper; struct GroupStruct groups;
1686   Logical filteringScalars, filteringHypers; CDFstatus status;
1687   static char rvMsg[] = "Reading/writing variable values...";
1688   static char keyDefsAbort[] = "Abort: ________\n\n";
1689   /****************************************************************************
1690   * Encode key definitions first time.
1691   ****************************************************************************/
1692   if (first) {
1693     char *p1 = keyDefsAbort;
1694     EncodeKeyDefinitions (1, &p1, ABORTkey_EXPORT);
1695     first = FALSE;
1696   }
1697   /****************************************************************************
1698   * Read/write first (and only) record for NRV variables.  Note that
1699   * if an item is being output it must be a variable.
1700   ****************************************************************************/
1701   switch (OutputNRVvalues(inID,outID,exportHead,TRUE,
1702 			  dimSizes,firstIndices,outMajority)) {
1703     case SUCCESS: break;
1704     case FATALin: return FATALin;
1705     case FATALout: return FATALout;
1706   }
1707   /****************************************************************************
1708   * Remove NRV variables from export list if they are not being filtered.
1709   ****************************************************************************/
1710   for (Item = exportHead, prevItem = NULL;
1711        Item != NULL; Item = Item->nextExport) {
1712     if (!Item->Var->recVary && !Item->filter) {
1713       if (prevItem == NULL)
1714 	exportHead = Item->nextExport;
1715       else
1716 	prevItem->nextExport = Item->nextExport;
1717     }
1718     else
1719       prevItem = Item;
1720   }
1721   /****************************************************************************
1722   * Determine scalars and hypers.
1723   ****************************************************************************/
1724   for (Item = exportHead, scalarCount = 0, hyperCount = 0;
1725        Item != NULL; Item = Item->nextExport) {
1726      if (Item->Var->scalar)
1727        scalarCount++;
1728      else
1729        hyperCount++;
1730   }
1731   varCount = scalarCount + hyperCount;
1732   handles = (Byte ***) cdf_AllocateMemory (varCount * sizeof(Byte **),
1733 				       FatalError);
1734   nValueBytes = (size_t *) cdf_AllocateMemory (varCount * sizeof(size_t),
1735 					   FatalError);
1736   for (Item = exportHead, scalarX = 0, hyperX = scalarCount,
1737        scalarHead = scalarTail = NULL, hyperHead = hyperTail = NULL,
1738        filteringScalars = FALSE, filteringHypers = FALSE;
1739        Item != NULL; Item = Item->nextExport) {
1740      if (Item->Var->scalar) {
1741        handles[scalarX] = &(Item->Var->buffer);
1742        nValueBytes[scalarX++] = Item->Var->nValueBytes;
1743        if (scalarHead == NULL)
1744 	 scalarHead = scalarTail = Item;
1745        else
1746 	 scalarTail = scalarTail->nextScalar = Item;
1747        Item->nextScalar = NULL;
1748        if (Item->filter) filteringScalars = TRUE;
1749      }
1750      else {
1751        handles[hyperX] = &(Item->Var->buffer);
1752        nValueBytes[hyperX++] = Item->Var->nValueBytes;
1753        if (hyperHead == NULL)
1754 	 hyperHead = hyperTail = Item;
1755        else
1756 	 hyperTail = hyperTail->nextHyper = Item;
1757        Item->nextHyper = NULL;
1758        if (Item->filter) filteringHypers = TRUE;
1759      }
1760   }
1761   /****************************************************************************
1762   * Preallocate variable records.
1763   ****************************************************************************/
1764   if (opt.preAllocate) {
1765     switch (PreAllocateRecords(inID,outID,scalarHead,
1766 			       hyperHead,&firstRec,&lastRec)) {
1767       case SUCCESS: break;
1768       case FATALin: return FATALin;
1769       case FATALout: return FATALout;
1770     }
1771   }
1772   /****************************************************************************
1773   * Allocate buffers.
1774   ****************************************************************************/
1775   DisplayPctComplete (NO_PCT, rvMsg);
1776   NEWkeyDEFS (EWkey, keyDefsAbort, batchMode)
1777   AllocateBuffers (lastRec - firstRec + 1, numDims, dimSizes, &groups,
1778 		   scalarCount, hyperCount, handles, nValueBytes,
1779 		   ROWmajor(inMajority), 5, FatalError);
1780   cdf_FreeMemory (handles, FatalError);
1781   cdf_FreeMemory (nValueBytes, FatalError);
1782   /****************************************************************************
1783   * Count number of values per record.
1784   ****************************************************************************/
1785   for (dimN = 0, nRecordValues = 1; dimN < numDims; dimN++) {
1786      nRecordValues *= dimSizes[dimN];
1787   }
1788   /****************************************************************************
1789   * Read/write each record for RV variables.  Note that NRV variables are
1790   * still read for filtering.
1791   ****************************************************************************/
1792   if (HyperFullRecord(&groups,numDims)) {
1793     /**************************************************************************
1794     * Each hyper read/write consists of one or more hyper records.
1795     **************************************************************************/
1796     long recNo = 0, recX, firstX, lastX, thisCount;
1797     InitHyperParms (&hyper, &groups, numDims, &nHypers, &nValues);
1798     for (hyperN = 0; hyperN < nHypers; hyperN++) {
1799        /***********************************************************************
1800        * Hyper read scalar input variables.
1801        ***********************************************************************/
1802        for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
1803 	  status = HYPERget (inID, Item->Var->varN, Item->Var->zVar,
1804 			     firstRec + hyper.recNumber, hyper.recCount,
1805 			     dimIndices_0, dimCounts_1, Item->Var->buffer);
1806 	  DisplayStatus (status, readingCDF);
1807 	  if (StatusBAD(status)) {
1808 	    FreeExportBuffers (exportHead);
1809 	    return FATALin;
1810 	  }
1811        }
1812        DisplayPctComplete (PCT(hyperN,nHypers,1,2), rvMsg);
1813        if (AbortCDF(exportHead)) return SUCCESS;
1814        /***********************************************************************
1815        * Until no more records...
1816        ***********************************************************************/
1817        for (recX = 0;;) {
1818 	  /********************************************************************
1819 	  * Determine first record to be output.
1820 	  ********************************************************************/
1821 	  firstX = FindFirstRecord (recX, scalarHead, filteringScalars,
1822 				    hyper.recCount);
1823 	  if (firstX == NO_RECORD) break;
1824 	  /********************************************************************
1825 	  * Determine last record to be output.
1826 	  ********************************************************************/
1827 	  lastX = FindLastRecord (firstX, scalarHead, filteringScalars,
1828 			          hyper.recCount);
1829 	  thisCount = lastX - firstX + 1;
1830 	  recF = firstRec + hyper.recNumber + firstX;
1831 	  recL = firstRec + hyper.recNumber + lastX;
1832 	  /********************************************************************
1833 	  * Hyper write to scalar output variables (being output).
1834 	  ********************************************************************/
1835 	  for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
1836 	     if (Item->output) {
1837 	       if (recF <= Item->Var->maxRec) {
1838 		 long count = MINIMUM(recL,Item->Var->maxRec) - recF + 1;
1839 		 Byte *buffer = Item->Var->buffer +
1840 				(size_t) (Item->Var->nValueBytes * firstX);
1841 		 status = HYPERput (outID, Item->Var->varNo, Item->Var->zVar,
1842 				    recNo, count, dimIndices_0, dimCounts_1,
1843 				    buffer);
1844 		 DisplayStatus (status, writingCDF);
1845 		 if (StatusBAD(status)) {
1846 		   FreeExportBuffers (exportHead);
1847 		   return FATALout;
1848 		 }
1849 	       }
1850 	     }
1851 	  }
1852 	  if (AbortCDF(exportHead)) return SUCCESS;
1853 	  /********************************************************************
1854 	  * Read hyper input variables.
1855 	  ********************************************************************/
1856 	  for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
1857 	     status = HYPERget (inID, Item->Var->varN, Item->Var->zVar,
1858 				recF, thisCount, firstIndices, dimSizes,
1859 				Item->Var->buffer);
1860 	     DisplayStatus (status, readingCDF);
1861 	     if (StatusBAD(status)) {
1862 	       FreeExportBuffers (exportHead);
1863 	       return FATALin;
1864 	     }
1865 	     if (AbortCDF(exportHead)) return SUCCESS;
1866 	  }
1867 	  /********************************************************************
1868 	  * Filter hyper variables.
1869 	  ********************************************************************/
1870 	  if (filteringHypers) FilterHypers (hyperHead, nValues);
1871 	  /********************************************************************
1872 	  * Write to hyper output variables (being output).
1873 	  ********************************************************************/
1874 	  for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
1875 	     if (Item->output) {
1876 	       if (AbortCDF(exportHead)) return SUCCESS;
1877 	       if (recF <= Item->Var->maxRec) {
1878 		 long count = MINIMUM(recL,Item->Var->maxRec) - recF + 1;
1879 		 if (!OutputHyperBuffer(outID,Item->Var->varNo,
1880 					Item->Var->zVar,outMajority,
1881 					recNo,count,dimIndices_0,dimSizes,
1882 					numDims,dimSizes,Item->Var->buffer,
1883 					nValues,TRUE,Item->Var->nValueBytes,
1884 					nRecordValues)) {
1885 		   FreeExportBuffers (exportHead);
1886 		   return FATALout;
1887 	         }
1888 	       }
1889 	     }
1890 	  }
1891 	  /********************************************************************
1892 	  * Increment to next...
1893 	  ********************************************************************/
1894 	  recNo += thisCount;
1895 	  recX = lastX + 1;
1896 	  if (recX == hyper.recCount) break;
1897        }
1898        DisplayPctComplete (PCT(hyperN,nHypers,2,2), rvMsg);
1899        /***********************************************************************
1900        * Increment to next hyper group.
1901        ***********************************************************************/
1902        IncrHyperParms (&hyper, &groups, numDims, ROWmajor(inMajority),
1903 		       &nValues);
1904     }
1905   }
1906   else {
1907     /**************************************************************************
1908     * Each hyper read/write consists of less than a full record.
1909     **************************************************************************/
1910     long nHypersPerRecord = HypersPerRecord (&groups, numDims);
1911     long recNi, recNo = -1;
1912     InitHyperParms (&hyper, &groups, numDims, &nHypers, &nValues);
1913     for (hyperN = 0; hyperN < nHypers; hyperN++) {
1914        recNi = firstRec + hyper.recNumber;
1915        /***********************************************************************
1916        * If at the start of a record...
1917        ***********************************************************************/
1918        if (HyperStartOfRecord(&hyper,numDims)) {
1919 	 Logical skipRecord = FALSE;
1920 	 /*********************************************************************
1921 	 * Read/filter values for scalar input variables.
1922 	 *********************************************************************/
1923 	 for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
1924 	    status = SINGLEget (inID, Item->Var->varN, Item->Var->zVar,
1925 				recNi, dimIndices_0, Item->Var->buffer);
1926 	    DisplayStatus (status, readingCDF);
1927 	    if (StatusBAD(status)) {
1928 	      FreeExportBuffers (exportHead);
1929 	      return FATALin;
1930 	    }
1931 	    if (VARfailedFILTER(Item,Item->Var->buffer)) {
1932 	      skipRecord = TRUE;
1933 	      break;
1934 	    }
1935 	 }
1936 	 /*********************************************************************
1937 	 * If this record is to be skipped, increment the hyper counter by
1938 	 * one less than the number of hypers per record.  This is because
1939 	 * the `continue' still causes the increment part of the `for' loop
1940 	 * to be executed.
1941 	 *********************************************************************/
1942 	 if (skipRecord) {
1943 	   for (i = 0; i < nHypersPerRecord; i++) {
1944 	      IncrHyperParms (&hyper,&groups,numDims,
1945 			      ROWmajor(inMajority),&nValues);
1946 	   }
1947 	   hyperN += (nHypersPerRecord - 1);
1948 	   continue;
1949 	 }
1950 	 else
1951 	   recNo++;
1952 	 /*********************************************************************
1953 	 * Single write to scalar output variables (being output).
1954 	 *********************************************************************/
1955 	 for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
1956 	    if (Item->output && recNi <= Item->Var->maxRec) {
1957 	      status = SINGLEput (outID, Item->Var->varNo, Item->Var->zVar,
1958 				  recNo, dimIndices_0, Item->Var->buffer);
1959 	      DisplayStatus (status, readingCDF);
1960 	      if (StatusBAD(status)) {
1961 		FreeExportBuffers (exportHead);
1962 		return FATALout;
1963 	      }
1964 	    }
1965 	 }
1966        }
1967        DisplayPctComplete (PCT(hyperN,nHypers,1,4), rvMsg);
1968        if (AbortCDF(exportHead)) return SUCCESS;
1969        /***********************************************************************
1970        * Read from hyper input variables.
1971        ***********************************************************************/
1972        for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
1973 	  for (dimN = 0; dimN < numDims; dimN++) {
1974 	     indicesI[dimN] = firstIndices[dimN] + hyper.dimIndices[dimN];
1975 	  }
1976 	  status = HYPERget (inID, Item->Var->varN, Item->Var->zVar, recNi,
1977 			     1L, indicesI, hyper.dimCounts, Item->Var->buffer);
1978 	  DisplayStatus (status, readingCDF);
1979 	  if (StatusBAD(status)) {
1980 	    FreeExportBuffers (exportHead);
1981 	    return FATALin;
1982 	  }
1983 	  if (AbortCDF(exportHead)) return SUCCESS;
1984        }
1985        DisplayPctComplete (PCT(hyperN,nHypers,2,4), rvMsg);
1986        /***********************************************************************
1987        * Filter values in hyper buffers.
1988        ***********************************************************************/
1989        if (filteringHypers) FilterHypers (hyperHead, nValues);
1990        DisplayPctComplete (PCT(hyperN,nHypers,3,4), rvMsg);
1991        /***********************************************************************
1992        * Hyper/single write to hyper output variables (being output).
1993        ***********************************************************************/
1994        for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
1995 	  if (Item->output && recNi <= Item->Var->maxRec) {
1996 	    if (!OutputHyperBuffer(outID,Item->Var->varNo,Item->Var->zVar,
1997 				   outMajority,recNo,1L,hyper.dimIndices,
1998 				   hyper.dimCounts,numDims,dimSizes,
1999 				   Item->Var->buffer,nValues,FALSE,
2000 				   Item->Var->nValueBytes,nRecordValues)) {
2001 	      FreeExportBuffers (exportHead);
2002 	      return FATALout;
2003 	    }
2004 	    if (AbortCDF(exportHead)) return SUCCESS;
2005 	  }
2006        }
2007        DisplayPctComplete (PCT(hyperN,nHypers,4,4), rvMsg);
2008        /***********************************************************************
2009        * Increment to next hyper group.
2010        ***********************************************************************/
2011        IncrHyperParms (&hyper,&groups,numDims,ROWmajor(inMajority),&nValues);
2012      }
2013   }
2014   FreeExportBuffers (exportHead);
2015   return SUCCESS;
2016 }
2017 
2018 /******************************************************************************
2019 * ToCDFdiffOrZero.
2020 * Different dimensionalities or all with zero dimensions.
2021 * Returns SUCCESS, FATALin, or FATALout;
2022 ******************************************************************************/
2023 
ToCDFdiffOrZero(inID,outID,firstRec,lastRec,outMajority,exportHead)2024 int ToCDFdiffOrZero (inID, outID, firstRec, lastRec, outMajority, exportHead)
2025 CDFid inID;
2026 CDFid outID;
2027 long firstRec;
2028 long lastRec;
2029 long outMajority;
2030 struct ItemStruct *exportHead;
2031 {
2032   int scalarCount, hyperCount, scalarX; size_t *nValueBytes;
2033   long recNo, nHypers, hyperN, nValues, recX, firstX, lastX, thisCount;
2034   long recF, recL; Byte ***handles; CDFstatus status;
2035   Logical filteringScalars; static Logical first = TRUE;
2036   struct ItemStruct *Item, *prevItem, *scalarHead, *scalarTail, *hyperHead;
2037   struct ItemStruct *hyperTail; struct GroupStruct groups;
2038   struct HyperStruct hyper;
2039   static char rvMsg[] = "Reading/writing variable values...";
2040   static char keyDefsAbort[] = "Abort: ________\n\n";
2041   /****************************************************************************
2042   * Encode key definitions first time.
2043   ****************************************************************************/
2044   if (first) {
2045     char *p1 = keyDefsAbort;
2046     EncodeKeyDefinitions (1, &p1, ABORTkey_EXPORT);
2047     first = FALSE;
2048   }
2049   /****************************************************************************
2050   * Read/write first (and only) record for NRV variables.  Note that
2051   * if an item is being output it must be a variable.
2052   ****************************************************************************/
2053   switch (OutputNRVvalues(inID,outID,exportHead,FALSE,NULL,NULL,outMajority)) {
2054     case SUCCESS: break;
2055     case FATALin: return FATALin;
2056     case FATALout: return FATALout;
2057   }
2058   /****************************************************************************
2059   * Remove NRV variables and hyper variables not being output from export list.
2060   ****************************************************************************/
2061   for (Item = exportHead, prevItem = NULL;
2062        Item != NULL; Item = Item->nextExport) {
2063     if (!Item->Var->recVary || (!Item->Var->scalar && !Item->output)) {
2064       if (prevItem == NULL)
2065 	exportHead = Item->nextExport;
2066       else
2067 	prevItem->nextExport = Item->nextExport;
2068     }
2069     else
2070       prevItem = Item;
2071   }
2072   /****************************************************************************
2073   * Count scalars/hypers and allocate buffers for scalars.
2074   ****************************************************************************/
2075   for (Item = exportHead, scalarCount = 0, hyperCount = 0;
2076        Item != NULL; Item = Item->nextExport) {
2077      if (Item->Var->scalar)
2078        scalarCount++;
2079      else
2080        hyperCount++;
2081   }
2082   handles = (Byte ***) cdf_AllocateMemory (scalarCount * sizeof(Byte **),
2083 				       FatalError);
2084   nValueBytes = (size_t *) cdf_AllocateMemory (scalarCount * sizeof(size_t),
2085 					   FatalError);
2086   for (Item = exportHead, scalarX = 0, scalarHead = scalarTail = NULL,
2087        hyperHead = hyperTail = NULL, filteringScalars = FALSE;
2088        Item != NULL; Item = Item->nextExport) {
2089      if (Item->Var->scalar) {
2090        handles[scalarX] = &(Item->Var->buffer);
2091        nValueBytes[scalarX++] = Item->Var->nValueBytes;
2092        if (scalarHead == NULL)
2093 	 scalarHead = scalarTail = Item;
2094        else
2095 	 scalarTail = scalarTail->nextScalar = Item;
2096        Item->nextScalar = NULL;
2097        if (Item->filter) filteringScalars = TRUE;
2098      }
2099      else {
2100        if (hyperHead == NULL)
2101 	 hyperHead = hyperTail = Item;
2102        else
2103 	 hyperTail = hyperTail->nextHyper = Item;
2104        Item->nextHyper = NULL;
2105        Item->Var->buffer = NULL;
2106      }
2107   }
2108   /****************************************************************************
2109   * Preallocate variable records.
2110   ****************************************************************************/
2111   if (opt.preAllocate) {
2112     switch (PreAllocateRecords(inID,outID,scalarHead,
2113 			       hyperHead,&firstRec,&lastRec)) {
2114       case SUCCESS:
2115 	break;
2116       case FATALin:
2117 	if (handles != NULL) cdf_FreeMemory (handles, FatalError);
2118 	if (nValueBytes != NULL) cdf_FreeMemory (nValueBytes, FatalError);
2119 	return FATALin;
2120       case FATALout:
2121 	if (handles != NULL) cdf_FreeMemory (handles, FatalError);
2122 	if (nValueBytes != NULL) cdf_FreeMemory (nValueBytes, FatalError);
2123 	return FATALout;
2124     }
2125   }
2126   /****************************************************************************
2127   * Allocate buffers for scalar variables.  Note that if there were no scalar
2128   * variables the handles and value sizes would be NULL and one hyper would be
2129   * specified covering the entire range of input records.
2130   ****************************************************************************/
2131   DisplayPctComplete (NO_PCT, rvMsg);
2132   NEWkeyDEFS (EWkey, keyDefsAbort, batchMode)
2133   AllocateBuffers(lastRec - firstRec + 1, 0L, NULL, &groups, scalarCount, 0,
2134 		  handles, nValueBytes, ROWmajor(inMajority), 5, FatalError);
2135   if (handles != NULL) cdf_FreeMemory (handles, FatalError);
2136   if (nValueBytes != NULL) cdf_FreeMemory (nValueBytes, FatalError);
2137   /****************************************************************************
2138   * For each hyper...
2139   ****************************************************************************/
2140   InitHyperParms (&hyper, &groups, 0L, &nHypers, &nValues);
2141   for (hyperN = 0, recNo = 0; hyperN < nHypers; hyperN++) {
2142      /*************************************************************************
2143      * Hyper read scalar input variables.
2144      *************************************************************************/
2145      for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
2146 	status = HYPERget (inID, Item->Var->varN, Item->Var->zVar,
2147 			   firstRec + hyper.recNumber, hyper.recCount,
2148 			   dimIndices_0, dimCounts_1, Item->Var->buffer);
2149 	DisplayStatus (status, readingCDF);
2150 	if (StatusBAD(status)) {
2151 	  FreeExportBuffers (exportHead);
2152 	  return FATALin;
2153 	}
2154      }
2155      DisplayPctComplete (PCT(hyperN,nHypers,1,2), rvMsg);
2156      if (AbortCDF(exportHead)) return SUCCESS;
2157      /**********************************************************************
2158      * Until no more records...
2159      **********************************************************************/
2160      for (recX = 0;;) {
2161 	/**********************************************************************
2162 	* Determine first record to be output.
2163 	**********************************************************************/
2164 	firstX = FindFirstRecord (recX, scalarHead, filteringScalars,
2165 			          hyper.recCount);
2166 	if (firstX == NO_RECORD) break;
2167 	/**********************************************************************
2168 	* Determine last record to be output.
2169 	**********************************************************************/
2170 	lastX = FindLastRecord (firstX, scalarHead, filteringScalars,
2171 			        hyper.recCount);
2172 	thisCount = lastX - firstX + 1;
2173 	recF = firstRec + hyper.recNumber + firstX;
2174 	recL = firstRec + hyper.recNumber + lastX;    /* lastRec -> firstRec */
2175 	/**********************************************************************
2176 	* Hyper write to scalar output variables (being output).
2177 	**********************************************************************/
2178 	for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
2179 	   if (Item->output) {
2180 	     if (recF <= Item->Var->maxRec) {
2181 	       long count = MINIMUM(recL,Item->Var->maxRec) - recF + 1;
2182 	       Byte *buffer = Item->Var->buffer +
2183 			      (size_t) (Item->Var->nValueBytes * firstX);
2184 	       status = HYPERput (outID, Item->Var->varNo, Item->Var->zVar,
2185 				  recNo, count, dimIndices_0, dimCounts_1,
2186 				  buffer);
2187 	       DisplayStatus (status, writingCDF);
2188 	       if (StatusBAD(status)) {
2189 	         FreeExportBuffers (exportHead);
2190 	         return FATALout;
2191 	       }
2192 	     }
2193 	   }
2194 	}
2195 	if (AbortCDF(exportHead)) return SUCCESS;
2196 	/**********************************************************************
2197 	* Hyper read/filter/write each hyper variable being output.
2198 	**********************************************************************/
2199 	for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
2200 	   if (recF <= Item->Var->maxRec) {
2201 	     long count = MINIMUM(recL,Item->Var->maxRec) - recF + 1;
2202 	     struct GroupStruct groups1; Logical fullRecord1;
2203 	     Byte *buffer1, **handles1 = &buffer1; struct HyperStruct hyper1;
2204 	     long nHypers1, hyperN1, nValues1;
2205 	     size_t nValueBytes1 = Item->Var->nValueBytes;
2206 	     AllocateBuffers (count, Item->Var->numDims, Item->Var->dimSizes,
2207 			      &groups1, 0, 1, &handles1, &nValueBytes1,
2208 			      ROWmajor(inMajority), 5, FatalError);
2209 	     fullRecord1 = HyperFullRecord (&groups1, Item->Var->numDims);
2210 	     InitHyperParms (&hyper1, &groups1, Item->Var->numDims, &nHypers1,
2211 			     &nValues1);
2212 	     for (hyperN1 = 0; hyperN1 < nHypers1; hyperN1++) {
2213 	        status = HYPERget (inID, Item->Var->varN, Item->Var->zVar,
2214 				   recF + hyper1.recNumber, hyper1.recCount,
2215 				   hyper1.dimIndices, hyper1.dimCounts,
2216 				   buffer1);
2217 	        DisplayStatus (status, readingCDF);
2218 	        if (StatusBAD(status)) {
2219 		  FreeExportBuffers (exportHead);
2220 		  return FATALin;
2221 	        }
2222 	        if (Item->filter) FilterBuffer (Item, buffer1, nValues1);
2223 	        if (!OutputHyperBuffer(outID,Item->Var->varNo,Item->Var->zVar,
2224 				       outMajority,recNo + hyper1.recNumber,
2225 				       hyper1.recCount,hyper1.dimIndices,
2226 				       hyper1.dimCounts,Item->Var->numDims,
2227 				       Item->Var->dimSizes,buffer1,nValues1,
2228 				       fullRecord1,Item->Var->nValueBytes,
2229 				       Item->Var->nRecordValues)) {
2230 		  FreeExportBuffers (exportHead);
2231 		  return FATALout;
2232 	        }
2233 	        IncrHyperParms (&hyper1, &groups1, Item->Var->numDims,
2234 			        ROWmajor(inMajority), &nValues1);
2235 	        if (AbortCDF(exportHead)) return SUCCESS;
2236 	     }
2237 	     cdf_FreeMemory (buffer1, FatalError);
2238 	   }
2239 	}
2240 	/*******************************************************************
2241 	* Increment to next...
2242 	*******************************************************************/
2243 	recNo += thisCount;
2244 	recX = lastX + 1;
2245 	if (recX == hyper.recCount) break;
2246      }
2247      DisplayPctComplete (PCT(hyperN,nHypers,2,2), rvMsg);
2248      /**********************************************************************
2249      * Increment to next hyper group.
2250      **********************************************************************/
2251      IncrHyperParms (&hyper, &groups, 0L, ROWmajor(inMajority), &nValues);
2252   }
2253   FreeExportBuffers (exportHead);
2254   return SUCCESS;
2255 }
2256 
2257 /******************************************************************************
2258 * OutputNRVvalues.
2259 * Returns SUCCESS, FATALin, or FATALout;
2260 ******************************************************************************/
2261 
OutputNRVvalues(inID,outID,exportHead,same,dimSizes,firstIndices,outMajority)2262 Logical OutputNRVvalues (inID, outID, exportHead, same, dimSizes,
2263 			 firstIndices, outMajority)
2264 CDFid inID;
2265 CDFid outID;
2266 struct ItemStruct *exportHead;
2267 Logical same;                   /* Same dimensionalities? */
2268 long dimSizes[];                /* N/a if different dimensionalities. */
2269 long firstIndices[];            /* N/a if different dimensionalities. */
2270 long outMajority;
2271 {
2272   long nrvCount, nrvAt, nHypers, hyperN, nRecordValues; size_t *nValueBytes;
2273   long phyDimSizes[CDF_MAX_DIMS], indicesI[CDF_MAX_DIMS], nValues;
2274   struct HyperStruct hyper; struct GroupStruct groups; struct ItemStruct *Item;
2275   Byte ***handles, *buffer; CDFstatus status; int dimN; Logical fullRecord;
2276   static char nrvMsg[] = "Reading/writing NRV variable values...";
2277   /****************************************************************************
2278   * Count number of NRV variables being output.
2279   ****************************************************************************/
2280   for (Item = exportHead, nrvCount=0; Item != NULL; Item = Item->nextExport) {
2281      if (NRVtoOUTPUT(Item) && Item->Var->maxRec == 0) nrvCount++;
2282   }
2283   DisplayPctComplete (NO_PCT, nrvMsg);
2284   /****************************************************************************
2285   * Output values for each NRV variable.
2286   ****************************************************************************/
2287   for (Item = exportHead, nrvAt = 0; Item != NULL; Item = Item->nextExport) {
2288      if (NRVtoOUTPUT(Item) && Item->Var->maxRec == 0) {
2289        /***********************************************************************
2290        * Allocate hyper buffer.
2291        ***********************************************************************/
2292        for (dimN = 0, nRecordValues = 1; dimN < Item->Var->numDims; dimN++) {
2293 	  if (Item->Var->dimVarys[dimN])
2294 	    phyDimSizes[dimN] = BOO(same,dimSizes[dimN],
2295 					 Item->Var->dimSizes[dimN]);
2296 	  else
2297 	    phyDimSizes[dimN] = 1;
2298 	  nRecordValues *= phyDimSizes[dimN];
2299        }
2300        handles = (Byte ***) cdf_AllocateMemory (sizeof(Byte **), FatalError);
2301        nValueBytes = (size_t *) cdf_AllocateMemory (sizeof(size_t), FatalError);
2302        handles[0] = &buffer;
2303        nValueBytes[0] = Item->Var->nValueBytes;
2304        AllocateBuffers (1L, Item->Var->numDims, phyDimSizes, &groups,
2305 			0, 1, handles, nValueBytes, ROWmajor(inMajority),
2306 			1, FatalError);
2307        cdf_FreeMemory (handles, FatalError);
2308        cdf_FreeMemory (nValueBytes, FatalError);
2309        /***********************************************************************
2310        * Perform each hyper read/filter/write(s).
2311        ***********************************************************************/
2312        fullRecord = HyperFullRecord (&groups, Item->Var->numDims);
2313        InitHyperParms (&hyper, &groups, Item->Var->numDims, &nHypers,
2314 		       &nValues);
2315        for (hyperN = 0; hyperN < nHypers; hyperN++) {
2316 	  /********************************************************************
2317 	  * Set indices for input CDF.
2318 	  ********************************************************************/
2319 	  for (dimN = 0; dimN < Item->Var->numDims; dimN++) {
2320 	     indicesI[dimN] = hyper.dimIndices[dimN] +
2321 			      BOO(same,firstIndices[dimN],0);
2322 	  }
2323 	  /********************************************************************
2324 	  * Read the buffer from the input CDF.
2325 	  ********************************************************************/
2326 	  status = HYPERget (inID, Item->Var->varN, Item->Var->zVar, 0L, 1L,
2327 			     indicesI, hyper.dimCounts, buffer);
2328 	  DisplayStatus (status, readingCDF);
2329 	  if (StatusBAD(status)) {
2330 	    cdf_FreeMemory (buffer, FatalError);
2331 	    return FATALin;
2332 	  }
2333 	  /********************************************************************
2334 	  * If this variable is being filtered, check each value in the
2335 	  * buffer.  If a value fails the filter, replace it with the fill
2336 	  * value (if one is specified) or the pad value (if a fill value
2337 	  * is not specified).
2338 	  ********************************************************************/
2339 	  if (Item->filter) {
2340 	    FilterBuffer (Item, buffer, nValues);
2341 	  }
2342 	  /********************************************************************
2343 	  * Write the buffer to the output CDF.
2344 	  ********************************************************************/
2345 	  if (!OutputHyperBuffer(outID,Item->Var->varNo,Item->Var->zVar,
2346 				 outMajority,0L,1L,hyper.dimIndices,
2347 				 hyper.dimCounts,Item->Var->numDims,
2348 				 phyDimSizes,buffer,nValues,fullRecord,
2349 				 Item->Var->nValueBytes,nRecordValues)) {
2350 	    cdf_FreeMemory (buffer, FatalError);
2351 	    return FATALout;
2352 	  }
2353 	  /********************************************************************
2354 	  * Increment to the next hyper parameters.
2355 	  ********************************************************************/
2356 	  IncrHyperParms (&hyper, &groups, Item->Var->numDims,
2357 			  ROWmajor(inMajority), &nValues);
2358        }
2359        /***********************************************************************
2360        * Free hyper buffer.
2361        ***********************************************************************/
2362        cdf_FreeMemory (buffer, FatalError);
2363        /***********************************************************************
2364        * Update percent complete message.
2365        ***********************************************************************/
2366        DisplayPctComplete (PCT(nrvAt,nrvCount,1,1), nrvMsg);
2367        nrvAt++;
2368      }
2369   }
2370   return SUCCESS;
2371 }
2372 
2373 /******************************************************************************
2374 * OutputHyperBuffer.
2375 * Returns FALSE if an error occurred.
2376 ******************************************************************************/
2377 
OutputHyperBuffer(outID,varNo,zVar,outMajority,recNumber,recCount,dimIndices,dimCounts,numDims,dimSizes,buffer,nValues,fullRecord,nValueBytes,nRecordValues)2378 Logical OutputHyperBuffer (outID, varNo, zVar, outMajority, recNumber,
2379 			   recCount, dimIndices, dimCounts, numDims, dimSizes,
2380 			   buffer, nValues, fullRecord, nValueBytes,
2381 			   nRecordValues)
2382 CDFid outID;
2383 long varNo;
2384 Logical zVar;
2385 long outMajority;
2386 long recNumber;
2387 long recCount;
2388 long dimIndices[];
2389 long dimCounts[];
2390 long numDims;
2391 long dimSizes[];
2392 Byte *buffer;
2393 long nValues;
2394 Logical fullRecord;
2395 size_t nValueBytes;
2396 long nRecordValues;
2397 {
2398   CDFstatus status; long indicesO[CDF_MAX_DIMS], recX; Byte *value;
2399   /****************************************************************************
2400   * If majorities are the same use one hyper write.
2401   ****************************************************************************/
2402   if (outMajority == inMajority) {
2403     status = HYPERput (outID, varNo, zVar, recNumber, recCount, dimIndices,
2404 		       dimCounts, buffer);
2405     DisplayStatus (status, writingCDF);
2406     if (StatusBAD(status)) return FALSE;
2407     return TRUE;
2408   }
2409   /****************************************************************************
2410   * If majority can be switched use one hyper write.
2411   ****************************************************************************/
2412   if (fullRecord) {
2413     if (SwitchMajority(buffer,ROWmajor(inMajority),numDims,
2414 		       dimSizes,recCount,nValueBytes)) {
2415       status = HYPERput (outID, varNo, zVar, recNumber, recCount, dimIndices,
2416 			 dimCounts, buffer);
2417       DisplayStatus (status, writingCDF);
2418       if (StatusBAD(status)) return FALSE;
2419       return TRUE;
2420     }
2421   }
2422   /****************************************************************************
2423   * Otherwise use single writes.
2424   ****************************************************************************/
2425   ARRAYtoARRAY (indicesO, dimIndices, numDims)
2426   for (recX = 0, value = buffer; recX < recCount; recX++) {
2427      long nValuesX = BOO(fullRecord,nRecordValues,nValues), valueN;
2428      for (valueN = 0; valueN < nValuesX; valueN++, value += nValueBytes) {
2429 	status = SINGLEput (outID, varNo, zVar, recNumber + recX, indicesO,
2430 			    value);
2431 	DisplayStatus (status, writingCDF);
2432 	if (StatusBAD(status)) return FALSE;
2433 	if (ROWmajor(inMajority))
2434 	  INCRindicesROW (numDims, dimSizes, indicesO);
2435 	else
2436 	  INCRindicesCOL (numDims, dimSizes, indicesO);
2437      }
2438   }
2439   return TRUE;
2440 }
2441 
2442 /******************************************************************************
2443 * CopyAttributesANDgEntries.
2444 * Returns SUCCESS, FATALin, or FATALout;
2445 ******************************************************************************/
2446 
CopyAttributesANDgEntries(inID,outID,nAttrs)2447 int CopyAttributesANDgEntries (inID, outID, nAttrs)
2448 CDFid inID;
2449 CDFid outID;
2450 long *nAttrs;
2451 {
2452   long attrN, scope, aNum; CDFstatus status;
2453   char attrName[CDF_ATTR_NAME_LEN+1];
2454   AOSs1A (pctMsg,"Creating attributes/global entries...")
2455   /****************************************************************************
2456   * Inquire number of attributes in input CDF.
2457   ****************************************************************************/
2458   DisplayPctComplete (NO_PCT, pctMsg[0]);
2459   status = CDFlib (SELECT_, CDF_, inID,
2460 		   GET_, CDF_NUMATTRS_, nAttrs,
2461 		   NULL_);
2462   DisplayStatus (status, readingCDF);
2463   if (StatusBAD(status)) return FATALin;
2464   /****************************************************************************
2465   * For each attribute in the input CDF create a corresponding attribute in
2466   * the output CDF.
2467   ****************************************************************************/
2468   for (attrN = 0; attrN < *nAttrs; attrN++) {
2469      /*************************************************************************
2470      * Read attribute information from input CDF.
2471      *************************************************************************/
2472      status = CDFlib (SELECT_, CDF_, inID,
2473 			       ATTR_, attrN,
2474 		      GET_, ATTR_NAME_, attrName,
2475 			    ATTR_SCOPE_, &scope,
2476 		      NULL_);
2477      DisplayStatus (status, readingCDF);
2478      if (StatusBAD(status)) return FATALin;
2479      /*************************************************************************
2480      * Create attribute in output CDF.
2481      *************************************************************************/
2482      status = CDFlib (SELECT_, CDF_, outID,
2483 		      CREATE_, ATTR_, attrName, scope, &aNum,
2484 		      NULL_);
2485      DisplayStatus (status, writingCDF);
2486      if (StatusBAD(status)) return FATALout;
2487      /*************************************************************************
2488      * If global-scope, also copy entries from the input CDF to the output CDF.
2489      *************************************************************************/
2490      if (scope == GLOBAL_SCOPE) {
2491        long maxEntry, entryN;
2492        /***********************************************************************
2493        * Inquire maximum gEntry number.
2494        ***********************************************************************/
2495        status = CDFlib (SELECT_, CDF_, inID,
2496 			GET_, ATTR_MAXgENTRY_, &maxEntry,
2497 			NULL_);
2498        DisplayStatus (status, readingCDF);
2499        if (StatusBAD(status)) return FATALin;
2500        /***********************************************************************
2501        * Copy each entry.
2502        ***********************************************************************/
2503        for (entryN = 0; entryN <= maxEntry; entryN++) {
2504 	  /********************************************************************
2505 	  * Confirm that this gEntry exists.  If so, write the entry to the
2506 	  * output CDF.
2507 	  ********************************************************************/
2508 	  status = CDFlib (SELECT_, CDF_, inID,
2509 			   CONFIRM_, gENTRY_EXISTENCE_, entryN,
2510 			   NULL_);
2511 	  switch (status) {
2512 	    case NO_SUCH_ENTRY:
2513 	      break;
2514 	    default: {
2515 	      long dataType, numElems; void *buffer; size_t nBytes;
2516 	      DisplayStatus (status, readingCDF);
2517 	      if (StatusBAD(status)) return FATALin;
2518 	      /****************************************************************
2519 	      * Inquire the data type/number of elements from the input CDF.
2520 	      ****************************************************************/
2521 	      status = CDFlib (SELECT_, CDF_, inID,
2522 					gENTRY_, entryN,
2523 			       GET_, gENTRY_DATATYPE_, &dataType,
2524 				     gENTRY_NUMELEMS_, &numElems,
2525 			       NULL_);
2526 	      DisplayStatus (status, readingCDF);
2527 	      if (StatusBAD(status)) return FATALin;
2528 	      /****************************************************************
2529 	      * Allocate a buffer for the entry value.
2530 	      ****************************************************************/
2531 	      nBytes = (size_t) (CDFelemSize(dataType) * numElems);
2532 	      buffer = cdf_AllocateMemory (nBytes, FatalError);
2533 	      /****************************************************************
2534 	      * Read the entry value from the input CDF.
2535 	      ****************************************************************/
2536 	      status = CDFlib (SELECT_, CDF_, inID,
2537 			       GET_, gENTRY_DATA_, buffer,
2538 			       NULL_);
2539 	      DisplayStatus (status, readingCDF);
2540 	      if (StatusBAD(status)) {
2541 		cdf_FreeMemory (buffer, FatalError);
2542 		return FATALin;
2543 	      }
2544 	      /****************************************************************
2545 	      * Write the entry to the output CDF.
2546 	      ****************************************************************/
2547 	      status = CDFlib (SELECT_, CDF_, outID,
2548 					gENTRY_, entryN,
2549 			       PUT_, gENTRY_DATA_, dataType, numElems, buffer,
2550 			       NULL_);
2551 	      DisplayStatus (status, writingCDF);
2552 	      if (StatusBAD(status)) {
2553 		cdf_FreeMemory (buffer, FatalError);
2554 		return FATALout;
2555 	      }
2556 	      /****************************************************************
2557 	      * Free the buffer.
2558 	      ****************************************************************/
2559 	      cdf_FreeMemory (buffer, FatalError);
2560 	      break;
2561 	    }
2562 	  }
2563        }
2564      }
2565      /*************************************************************************
2566      * Update percentage complete message.
2567      *************************************************************************/
2568      DisplayPctComplete (PCT(attrN,*nAttrs,1,1), pctMsg[0]);
2569   }
2570   return SUCCESS;
2571 }
2572 
2573 /******************************************************************************
2574 * CopyVariablesANDrzEntries.
2575 * Returns SUCCESS, FATALin, or FATALout;
2576 ******************************************************************************/
2577 
CopyVariablesANDrzEntries(inID,outID,nAttrs,same,numDims,dimSizes,exportHead)2578 int CopyVariablesANDrzEntries (inID, outID, nAttrs, same, numDims, dimSizes,
2579 			       exportHead)
2580 CDFid inID;
2581 CDFid outID;
2582 long nAttrs;
2583 Logical same;
2584 long numDims;
2585 long dimSizes[];
2586 struct ItemStruct *exportHead;
2587 {
2588   struct ItemStruct *Item; CDFstatus status; int nVars, atVar;
2589   AOSs1A (pctMsg,"Creating variables/entries...")
2590   /****************************************************************************
2591   * Count number of variables being output.
2592   ****************************************************************************/
2593   DisplayPctComplete (NO_PCT, pctMsg[0]);
2594   for (Item = exportHead, nVars = 0; Item != NULL; Item = Item->nextExport) {
2595      if (Item->output) nVars++;
2596   }
2597   /****************************************************************************
2598   * Scan list of exported items for variables being output.
2599   ****************************************************************************/
2600   for (Item = exportHead, atVar = 0; Item != NULL; Item = Item->nextExport) {
2601      if (Item->output) {
2602        long attrN;
2603        /***********************************************************************
2604        * Create output variable.
2605        ***********************************************************************/
2606        if (Item->Var->zVar)
2607 	 status = CDFlib (SELECT_, CDF_, outID,
2608 			  CREATE_, zVAR_, Item->Var->name,
2609 					  Item->Var->dataType,
2610 					  Item->Var->numElems,
2611 					  BOO(same,numDims,Item->Var->numDims),
2612 					  BOO(same,dimSizes,
2613 					      Item->Var->dimSizes),
2614 					  Item->Var->recVary,
2615 					  Item->Var->dimVarys,
2616 					  &(Item->Var->varNo),
2617 			  NULL_);
2618        else
2619 	 status = CDFlib (SELECT_, CDF_, outID,
2620 			  CREATE_, rVAR_, Item->Var->name, Item->Var->dataType,
2621 					  Item->Var->numElems,
2622 					  Item->Var->recVary,
2623 					  Item->Var->dimVarys,
2624 					  &(Item->Var->varNo),
2625 			  NULL_);
2626        DisplayStatus (status, writingCDF);
2627        if (StatusBAD(status)) return FATALout;
2628        /***********************************************************************
2629        * If a pad value exists for the input variable, write it to the output
2630        * variable.  Note that `Item->Var->pad' will always be non-NULL.  It
2631        * points to either the variable's default (based on data type) or
2632        * explicit pad value.
2633        ***********************************************************************/
2634        status = CDFlib (SELECT_, CDF_, inID,
2635 				 BOO(Item->Var->zVar,
2636 				     zVAR_,rVAR_), Item->Var->varN,
2637 			CONFIRM_, BOO(Item->Var->zVar,
2638 				      zVAR_PADVALUE_,rVAR_PADVALUE_),
2639 			NULL_);
2640        switch (status) {
2641 	 case NO_PADVALUE_SPECIFIED:
2642 	   break;
2643 	 default:
2644 	   DisplayStatus (status, readingCDF);
2645 	   if (StatusBAD(status)) return FATALin;
2646 	   status = CDFlib (SELECT_, CDF_, outID,
2647 			    PUT_, BOO(Item->Var->zVar,
2648 				      zVAR_PADVALUE_,
2649 				      rVAR_PADVALUE_), Item->Var->pad,
2650 			    NULL_);
2651 	   DisplayStatus (status, writingCDF);
2652 	   if (StatusBAD(status)) return FATALout;
2653 	   break;
2654        }
2655        /***********************************************************************
2656        * Specify sparseness, compression, and blocking factor for output
2657        * variable.
2658        ***********************************************************************/
2659        status = CDFlib (SELECT_, CDF_, outID,
2660 			PUT_, BOO(Item->Var->zVar,
2661 				  zVAR_SPARSERECORDS_,
2662 				  rVAR_SPARSERECORDS_),
2663 						Item->Var->sRecordsType,
2664 			      BOO(Item->Var->zVar,
2665 				  zVAR_SPARSEARRAYS_,
2666 				  rVAR_SPARSEARRAYS_), Item->Var->sArraysType,
2667 						       Item->Var->sArraysParms,
2668 			      BOO(Item->Var->zVar,
2669 				  zVAR_COMPRESSION_,
2670 				  rVAR_COMPRESSION_), Item->Var->cType,
2671 						      Item->Var->cParms,
2672 			      BOO(Item->Var->zVar,
2673 				  zVAR_BLOCKINGFACTOR_,
2674 				  rVAR_BLOCKINGFACTOR_), Item->Var->blocking,
2675 			NULL_);
2676        DisplayStatus (status, writingCDF);
2677        if (StatusBAD(status)) return FATALout;
2678        /***********************************************************************
2679        * Specify reserve percentage for output variable.
2680        ***********************************************************************/
2681        if (Item->Var->reserve != NA_RESERVE) {
2682 	 status = CDFlib (SELECT_, BOO(Item->Var->zVar,
2683 				       zVAR_RESERVEPERCENT_,
2684 				       rVAR_RESERVEPERCENT_),
2685 							Item->Var->reserve,
2686 			  NULL_);
2687 	 DisplayStatus (status, writingCDF);
2688 	 if (StatusBAD(status)) return FATALout;
2689        }
2690        /***********************************************************************
2691        * Copy corresponding r/zEntries from the input CDF to the output CDF.
2692        ***********************************************************************/
2693        for (attrN = 0; attrN < nAttrs; attrN++) {
2694 	  long scope;
2695 	  /********************************************************************
2696 	  * Determine attribute name and scope.
2697 	  ********************************************************************/
2698 	  status = CDFlib (SELECT_, CDF_, inID,
2699 				    ATTR_, attrN,
2700 			   GET_, ATTR_SCOPE_, &scope,
2701 			   NULL_);
2702 	  DisplayStatus (status, readingCDF);
2703 	  if (StatusBAD(status)) return FATALin;
2704 	  /********************************************************************
2705 	  * If variable-scope, copy r/zEntry if it exists.
2706 	  ********************************************************************/
2707 	  if (scope == VARIABLE_SCOPE) {
2708 	    status = CDFlib (SELECT_, CDF_, inID,
2709 			     CONFIRM_, BOO(Item->Var->zVar,
2710 					   zENTRY_EXISTENCE_,
2711 					   rENTRY_EXISTENCE_), Item->Var->varN,
2712 			     NULL_);
2713 	    switch (status) {
2714 	      case NO_SUCH_ENTRY:
2715 		break;
2716 	      default: {
2717 		long dataType, numElems; void *buffer; size_t nBytes;
2718 		DisplayStatus (status, readingCDF);
2719 		if (StatusBAD(status)) return FATALin;
2720 		/**************************************************************
2721 		* Inquire the data type/number of elements from the input CDF.
2722 		**************************************************************/
2723 		status = CDFlib (SELECT_, CDF_, inID,
2724 					  BOO(Item->Var->zVar,
2725 					      zENTRY_,rENTRY_),Item->Var->varN,
2726 				 GET_, BOO(Item->Var->zVar,
2727 					   zENTRY_DATATYPE_,
2728 					   rENTRY_DATATYPE_), &dataType,
2729 				       BOO(Item->Var->zVar,
2730 					   zENTRY_NUMELEMS_,
2731 					   rENTRY_NUMELEMS_), &numElems,
2732 				 NULL_);
2733 		DisplayStatus (status, readingCDF);
2734 		if (StatusBAD(status)) return FATALin;
2735 		/**************************************************************
2736 		* Allocate a buffer for the entry value.
2737 		**************************************************************/
2738 		nBytes = (size_t) (CDFelemSize(dataType) * numElems);
2739 		buffer = cdf_AllocateMemory (nBytes, FatalError);
2740 		/**************************************************************
2741 		* Read the entry value from the input CDF.
2742 		**************************************************************/
2743 		status = CDFlib (SELECT_, CDF_, inID,
2744 				 GET_, BOO(Item->Var->zVar,
2745 					   zENTRY_DATA_,rENTRY_DATA_), buffer,
2746 				 NULL_);
2747 		DisplayStatus (status, readingCDF);
2748 		if (StatusBAD(status)) {
2749 		  cdf_FreeMemory (buffer, FatalError);
2750 		  return FATALin;
2751 		}
2752 		/**************************************************************
2753 		* Write the entry to the output CDF.
2754 		**************************************************************/
2755 		status = CDFlib (SELECT_, CDF_, outID,
2756 					  ATTR_, attrN,
2757 					  BOO(Item->Var->zVar,
2758 					      zENTRY_,
2759 					      rENTRY_), Item->Var->varNo,
2760 				 PUT_, BOO(Item->Var->zVar,
2761 					   zENTRY_DATA_,
2762 					   rENTRY_DATA_), dataType, numElems,
2763 							  buffer,
2764 				 NULL_);
2765 		DisplayStatus (status, writingCDF);
2766 		if (StatusBAD(status)) {
2767 		  cdf_FreeMemory (buffer, FatalError);
2768 		  return FATALout;
2769 		}
2770 		/**************************************************************
2771 		* Free the buffer.
2772 		**************************************************************/
2773 		cdf_FreeMemory (buffer, FatalError);
2774 		break;
2775 	      }
2776 	    }
2777 	  }
2778        }
2779        /***********************************************************************
2780        * Update percentage complete message.
2781        ***********************************************************************/
2782        DisplayPctComplete (PCT(atVar,nVars,1,1), pctMsg[0]);
2783        atVar++;
2784      }
2785   }
2786   return SUCCESS;
2787 }
2788 
2789 /******************************************************************************
2790 * FirstLastRecord.
2791 * Returns: FATAL if a fatal error occurred,
2792 *	   FAILED if the output/listing should not continue, or
2793 *	   PASSED if the output/listing should continue.
2794 * The existence of at least one record in the CDF is assumed.
2795 ******************************************************************************/
2796 
FirstLastRecord(firstRec,lastRec,toCDF,exportHead)2797 int FirstLastRecord (firstRec, lastRec, toCDF, exportHead)
2798 long *firstRec;
2799 long *lastRec;
2800 Logical toCDF;
2801 struct ItemStruct *exportHead;
2802 {
2803   CDFstatus status; long rMaxRec, zMaxRec; struct ItemStruct *Item;
2804   static char noRecordsMsg[] = "No records in valid range.";
2805   /****************************************************************************
2806   * Inquire maximum r/zRecord.
2807   ****************************************************************************/
2808   status = CDFlib (GET_, rVARs_MAXREC_, &rMaxRec,
2809 			 zVARs_MAXREC_, &zMaxRec,
2810 		   NULL_);
2811   DisplayStatus (status, readingCDF);
2812   if (StatusBAD(status)) return FATAL;
2813   /****************************************************************************
2814   * Set first and last records based on number of records in CDF.
2815   ****************************************************************************/
2816   *firstRec = 0;
2817   *lastRec = MAXIMUM(rMaxRec,zMaxRec);
2818   /****************************************************************************
2819   * If filters are disabled or filtered lines are to be shown (and output is
2820   * not to a CDF), return now.
2821   ****************************************************************************/
2822   if (!opt.overallFilter) return PASSED;
2823   if (opt.showFiltered && !toCDF) return PASSED;
2824   /****************************************************************************
2825   * Scan list of exported items.
2826   ****************************************************************************/
2827   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
2828      switch (Item->type) {
2829        case RECORDt:
2830 	 if (Item->filter) {
2831 	   if (Item->Record->min != NOminMax) {
2832 	     /*****************************************************************
2833 	     * Check if last record passes minimum filter value.
2834 	     *****************************************************************/
2835 	     if (!RecordPassesMin(Item,*lastRec)) {
2836 	       DisplayMessage (noRecordsMsg, BEEPWAIT1);
2837 	       return FAILED;
2838 	     }
2839 	     /*****************************************************************
2840 	     * Reset first record based on minimum filter value.
2841 	     *****************************************************************/
2842 	     *firstRec = MaxLong(*firstRec,BOO(Item->inclusive,
2843 					       Item->Record->min,
2844 					       Item->Record->min + 1));
2845 	   }
2846 	   if (Item->Record->max != NOminMax) {
2847 	     /*****************************************************************
2848 	     * Check if first record passes maximum filter value.
2849 	     *****************************************************************/
2850 	     if (!RecordPassesMax(Item,*firstRec)) {
2851 	       DisplayMessage (noRecordsMsg, BEEPWAIT1);
2852 	       return FAILED;
2853 	     }
2854 	     /*****************************************************************
2855 	     * Reset last record based on maximum filter value.
2856 	     *****************************************************************/
2857 	     *lastRec = MinLong(*lastRec,BOO(Item->inclusive,
2858 					     Item->Record->max,
2859 					     Item->Record->max - 1));
2860 	   }
2861 	   Item->filter = FALSE;
2862 	 }
2863 	 break;
2864        case VARIABLEt:
2865 	 if (Item->filter) {
2866 	   if (Item->Var->scalar) {
2867 	     if (Item->Var->monotonic == UNKNOWNmono) {
2868 	       if (!SetVarMonotonicity(Item->Var)) return FATAL;
2869 	     }
2870 	     switch (Item->Var->monotonic) {
2871 	       case INCREASEmono:
2872 		 /*************************************************************
2873 		 * Check if a minimum filter value exists.
2874 		 *************************************************************/
2875 		 if (Item->Var->min != NULL) {
2876 		   /***********************************************************
2877 		   * Check if scalar value at last record passes minimum filter
2878 		   * value.
2879 		   ***********************************************************/
2880 		   if (!ReadScalarValue(Item->Var,*lastRec)) return FATAL;
2881 		   if (!VarPassesMin(Item,Item->Var->value)) {
2882 		     DisplayMessage (noRecordsMsg, BEEPWAIT1);
2883 		     return FAILED;
2884 		   }
2885 		   /***********************************************************
2886 		   * Increment first record until it either reaches the last
2887 		   * record or passes the minimum filter value.
2888 		   ***********************************************************/
2889 		   while (*firstRec < *lastRec) {
2890 		     if (!ReadScalarValue(Item->Var,*firstRec)) return FATAL;
2891 		     if (VarPassesMin(Item,Item->Var->value)) break;
2892 		     (*firstRec)++;
2893 		   }
2894 		 }
2895 		 /*************************************************************
2896 		 * Check if a maximum filter value exists.
2897 		 *************************************************************/
2898 		 if (Item->Var->max != NULL) {
2899 		   /***********************************************************
2900 		   * Check if scalar value at first record passes maximum
2901 		   * filter value.
2902 		   ***********************************************************/
2903 		   if (!ReadScalarValue(Item->Var,*firstRec)) return FATAL;
2904 		   if (!VarPassesMax(Item,Item->Var->value)) {
2905 		     DisplayMessage (noRecordsMsg, BEEPWAIT1);
2906 		     return FAILED;
2907 		   }
2908 		   /***********************************************************
2909 		   * Decrement last record until it either reaches the first
2910 		   * record or passes the maximum filter value.
2911 		   ***********************************************************/
2912 		   while (*lastRec > *firstRec) {
2913 		     if (!ReadScalarValue(Item->Var,*lastRec)) return FATAL;
2914 		     if (VarPassesMax(Item,Item->Var->value)) break;
2915 		     (*lastRec)--;
2916 		   }
2917 		 }
2918 		 Item->filter = FALSE;
2919 		 break;
2920 	       case DECREASEmono:
2921 		 if (Item->Var->min != NULL) {
2922 		   /***********************************************************
2923 		   * Check if scalar value at first record passes minimum
2924 		   * filter value.
2925 		   ***********************************************************/
2926 		   if (!ReadScalarValue(Item->Var,*firstRec)) return FATAL;
2927 		   if (!VarPassesMin(Item,Item->Var->value)) {
2928 		     DisplayMessage (noRecordsMsg, BEEPWAIT1);
2929 		     return FAILED;
2930 		   }
2931 		   /***********************************************************
2932 		   * Decrement last record until it either reaches the first
2933 		   * record or passes the minimum filter value.
2934 		   ***********************************************************/
2935 		   while (*lastRec > *firstRec) {
2936 		     if (!ReadScalarValue(Item->Var,*lastRec)) return FATAL;
2937 		     if (VarPassesMin(Item,Item->Var->value)) break;
2938 		     (*lastRec)--;
2939 		   }
2940 		 }
2941 		 /*************************************************************
2942 		 * Check if a maximum filter value exists.
2943 		 *************************************************************/
2944 		 if (Item->Var->max != NULL) {
2945 		   /***********************************************************
2946 		   * Check if scalar value at last record passes maximum filter
2947 		   * value.
2948 		   ***********************************************************/
2949 		   if (!ReadScalarValue(Item->Var,*lastRec)) return FATAL;
2950 		   if (!VarPassesMax(Item,Item->Var->value)) {
2951 		     DisplayMessage (noRecordsMsg, BEEPWAIT1);
2952 		     return FAILED;
2953 		   }
2954 		   /***********************************************************
2955 		   * Increment first record until it either reaches the last
2956 		   * record or passes the maximum filter value.
2957 		   ***********************************************************/
2958 		   while (*firstRec < *lastRec) {
2959 		     if (!ReadScalarValue(Item->Var,*firstRec)) return FATAL;
2960 		     if (VarPassesMax(Item,Item->Var->value)) break;
2961 		     (*firstRec)++;
2962 		   }
2963 		 }
2964 		 Item->filter = FALSE;
2965 		 break;
2966 	     }
2967 	   }
2968 	 }
2969 	 break;
2970      }
2971   }
2972   return PASSED;
2973 }
2974 
2975 /******************************************************************************
2976 * FirstLastIndices.
2977 * Returns: FATAL if a fatal error occurred,
2978 *	   FAILED if the output/listing should not continue, or
2979 *	   PASSED if the output/listing should continue.
2980 * The existence of at least one record in the CDF is assumed.
2981 ******************************************************************************/
2982 
FirstLastIndices(numDims,dimSizes,firstIndices,lastIndices,nValues,toCDF,exportHead)2983 int FirstLastIndices (numDims, dimSizes, firstIndices, lastIndices, nValues,
2984 		      toCDF, exportHead)
2985 long numDims;
2986 long dimSizes[];
2987 long firstIndices[];
2988 long lastIndices[];
2989 long *nValues;          /* NULL if not requested. */
2990 Logical toCDF;
2991 struct ItemStruct *exportHead;
2992 {
2993   int dimN; struct ItemStruct *Item;
2994   static char noIndicesMsg[] = "No indices in valid range.";
2995   /****************************************************************************
2996   * Set first and last indices based on dimensionality.
2997   ****************************************************************************/
2998   for (dimN = 0; dimN < numDims; dimN++) {
2999      firstIndices[dimN] = 0;
3000      lastIndices[dimN] = dimSizes[dimN] - 1;
3001   }
3002   /****************************************************************************
3003   * If filters are disabled or filtered lines are to be shown (and output is
3004   * not to a CDF), return now.
3005   ****************************************************************************/
3006   if (!opt.overallFilter) return PASSED;
3007   if (opt.showFiltered && !toCDF) return PASSED;
3008   /****************************************************************************
3009   * Scan list of exported items.
3010   ****************************************************************************/
3011   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
3012      switch (Item->type) {
3013        case INDICESt: {
3014 	 if (Item->filter) {
3015 	   if (Item->Indices->minNumDims != NOminMax) {
3016 	     /*****************************************************************
3017 	     * Check if last indices pass minimum filter value.
3018 	     *****************************************************************/
3019 	     if (!IndicesPassMin(Item,lastIndices)) {
3020 	       DisplayMessage (noIndicesMsg, BEEPWAIT1);
3021 	       return FAILED;
3022 	     }
3023 	     /*****************************************************************
3024 	     * Reset first indices based on minimum filter value.
3025 	     *****************************************************************/
3026 	     for (dimN = 0; dimN < numDims; dimN++) {
3027 		firstIndices[dimN] = MaxLong(firstIndices[dimN],
3028 				     BOO(Item->inclusive,
3029 					 Item->Indices->minIndices[dimN],
3030 					 Item->Indices->minIndices[dimN] + 1));
3031 	     }
3032 	   }
3033 	   if (Item->Indices->maxNumDims != NOminMax) {
3034 	     /*****************************************************************
3035 	     * Check if first indices pass maximum filter value.
3036 	     *****************************************************************/
3037 	     if (!IndicesPassMax(Item,firstIndices)) {
3038 	       DisplayMessage (noIndicesMsg, BEEPWAIT1);
3039 	       return FAILED;
3040 	     }
3041 	     /*****************************************************************
3042 	     * Reset last indices based on maximum filter value.
3043 	     *****************************************************************/
3044 	     for (dimN = 0; dimN < numDims; dimN++) {
3045 		lastIndices[dimN] = MinLong(lastIndices[dimN],
3046 				    BOO(Item->inclusive,
3047 					Item->Indices->maxIndices[dimN],
3048 					Item->Indices->maxIndices[dimN]-1));
3049 	     }
3050 	   }
3051 	   Item->filter = FALSE;
3052 	 }
3053 	 break;
3054        }
3055        case VARIABLEt:
3056 	 if (Item->filter) {
3057 	   if (DimensionalVariable(Item->Var,&dimN)) {
3058 	     if (Item->Var->monotonic == UNKNOWNmono) {
3059 	       if (!SetVarMonotonicity(Item->Var)) return FATAL;
3060 	     }
3061 	     switch (Item->Var->monotonic) {
3062 	       case INCREASEmono:
3063 		 /*************************************************************
3064 		 * Check if a minimum filter value exists.
3065 		 *************************************************************/
3066 		 if (Item->Var->min != NULL) {
3067 		   /***********************************************************
3068 		   * Check if value at last index passes minimum filter value.
3069 		   ***********************************************************/
3070 		   if (!ReadDimensionalValue(Item->Var,
3071 					     lastIndices)) return FATAL;
3072 		   if (!VarPassesMin(Item,Item->Var->value)) {
3073 		     DisplayMessage (noIndicesMsg, BEEPWAIT1);
3074 		     return FAILED;
3075 		   }
3076 		   /***********************************************************
3077 		   * Increment first index until it either reaches the last
3078 		   * index or passes the minimum filter value.
3079 		   ***********************************************************/
3080 		   while (firstIndices[dimN] < lastIndices[dimN]) {
3081 		     if (!ReadDimensionalValue(Item->Var,
3082 					       firstIndices)) return FATAL;
3083 		     if (VarPassesMin(Item,Item->Var->value)) break;
3084 		     firstIndices[dimN]++;
3085 		   }
3086 		 }
3087 		 /*************************************************************
3088 		 * Check if a maximum filter value exists.
3089 		 *************************************************************/
3090 		 if (Item->Var->max != NULL) {
3091 		   /***********************************************************
3092 		   * Check if value at first index passes maximum filter value.
3093 		   ***********************************************************/
3094 		   if (!ReadDimensionalValue(Item->Var,
3095 					     firstIndices)) return FATAL;
3096 		   if (!VarPassesMax(Item,Item->Var->value)) {
3097 		     DisplayMessage (noIndicesMsg, BEEPWAIT1);
3098 		     return FAILED;
3099 		   }
3100 		   /***********************************************************
3101 		   * Decrement last index until it either reaches the first
3102 		   * index or passes the maximum filter value.
3103 		   ***********************************************************/
3104 		   while (lastIndices[dimN] > firstIndices[dimN]) {
3105 		     if (!ReadDimensionalValue(Item->Var,
3106 					       lastIndices)) return FATAL;
3107 		     if (VarPassesMax(Item,Item->Var->value)) break;
3108 		     lastIndices[dimN]--;
3109 		   }
3110 		 }
3111 		 Item->filter = FALSE;
3112 		 break;
3113 	       case DECREASEmono:
3114 		 if (Item->Var->min != NULL) {
3115 		   /***********************************************************
3116 		   * Check if value at first index passes minimum filter value.
3117 		   ***********************************************************/
3118 		   if (!ReadDimensionalValue(Item->Var,
3119 					     firstIndices)) return FATAL;
3120 		   if (!VarPassesMin(Item,Item->Var->value)) {
3121 		     DisplayMessage (noIndicesMsg, BEEPWAIT1);
3122 		     return FAILED;
3123 		   }
3124 		   /***********************************************************
3125 		   * Decrement last index until it either reaches the first
3126 		   * index or passes the minimum filter value.
3127 		   ***********************************************************/
3128 		   while (lastIndices[dimN] > firstIndices[dimN]) {
3129 		     if (!ReadDimensionalValue(Item->Var,
3130 					       lastIndices)) return FATAL;
3131 		     if (VarPassesMin(Item,Item->Var->value)) break;
3132 		     lastIndices[dimN]--;
3133 		   }
3134 		 }
3135 		 /*************************************************************
3136 		 * Check if a maximum filter value exists.
3137 		 *************************************************************/
3138 		 if (Item->Var->max != NULL) {
3139 		   /***********************************************************
3140 		   * Check if value at last index passes maximum filter value.
3141 		   ***********************************************************/
3142 		   if (!ReadDimensionalValue(Item->Var,
3143 					     lastIndices)) return FATAL;
3144 		   if (!VarPassesMax(Item,Item->Var->value)) {
3145 		     DisplayMessage (noIndicesMsg, BEEPWAIT1);
3146 		     return FAILED;
3147 		   }
3148 		   /***********************************************************
3149 		   * Increment first index until it either reaches the last
3150 		   * index or passes the maximum filter value.
3151 		   ***********************************************************/
3152 		   while (firstIndices[dimN] < lastIndices[dimN]) {
3153 		     if (!ReadDimensionalValue(Item->Var,
3154 					       firstIndices)) return FATAL;
3155 		     if (VarPassesMax(Item,Item->Var->value)) break;
3156 		     firstIndices[dimN]++;
3157 		   }
3158 		 }
3159 		 Item->filter = FALSE;
3160 		 break;
3161 	     }
3162 	   }
3163 	 }
3164 	 break;
3165      }
3166   }
3167   /****************************************************************************
3168   * Recalculate number of values.
3169   ****************************************************************************/
3170   if (nValues != NULL) {
3171     for (*nValues = 1, dimN = 0; dimN < numDims; dimN++) {
3172        *nValues *= (lastIndices[dimN] - firstIndices[dimN] + 1);
3173     }
3174   }
3175   return PASSED;
3176 }
3177 
3178 /******************************************************************************
3179 * ScalarVariable.
3180 ******************************************************************************/
3181 
ScalarVariable(Var)3182 Logical ScalarVariable (Var)
3183 struct VarStruct *Var;
3184 {
3185   switch (Var->numDims) {
3186     case 0:
3187       return TRUE;
3188     default: {
3189       int dimN;
3190       for (dimN = 0; dimN < Var->numDims; dimN++) {
3191 	 if (Var->dimVarys[dimN] && Var->dimSizes[dimN] > 1) return FALSE;
3192       }
3193       return TRUE;
3194     }
3195   }
3196 }
3197 
3198 /******************************************************************************
3199 * DimensionalVariable.
3200 ******************************************************************************/
3201 
DimensionalVariable(Var,dimN)3202 Logical DimensionalVariable (Var, dimN)
3203 struct VarStruct *Var;
3204 int *dimN;
3205 {
3206   int dimNt, count;
3207   if (Var->recVary) return FALSE;
3208   if (Var->numDims == 0) return FALSE;
3209   for (count = 0, dimNt = 0; dimNt < Var->numDims; dimNt++) {
3210      if (Var->dimVarys[dimNt]) {
3211        *dimN = dimNt;
3212        count++;
3213      }
3214   }
3215   return (count == 1);
3216 }
3217 
3218 /******************************************************************************
3219 * OneDimensionVaries.
3220 ******************************************************************************/
3221 
OneDimensionVaries(Var)3222 Logical OneDimensionVaries (Var)
3223 struct VarStruct *Var;
3224 {
3225   int dimN, count = 0;
3226   if (Var->recVary) count++;
3227   for (dimN = 0; dimN < Var->numDims; dimN++) {
3228      if (Var->dimVarys[dimN]) count++;
3229   }
3230   return (count == 1);
3231 }
3232 
3233 /******************************************************************************
3234 * ReadScalarValue.
3235 ******************************************************************************/
3236 
ReadScalarValue(Var,recN)3237 Logical ReadScalarValue (Var, recN)
3238 struct VarStruct *Var;
3239 long recN;
3240 {
3241   static long indices[CDF_MAX_DIMS] = { 0,0,0,0,0,0,0,0,0,0 };
3242   CDFstatus status;
3243   status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_,rVAR_), Var->varN,
3244 			    BOO(Var->zVar,zVAR_RECNUMBER_,
3245 					  rVARs_RECNUMBER_), recN,
3246 			    BOO(Var->zVar,zVAR_DIMINDICES_,
3247 					  rVARs_DIMINDICES_), indices,
3248 		   GET_, BOO(Var->zVar,zVAR_DATA_,rVAR_DATA_), Var->value,
3249 		   NULL_);
3250   DisplayStatus (status, readingCDF);
3251   if (StatusBAD(status)) return FALSE;
3252   return TRUE;
3253 }
3254 
3255 /******************************************************************************
3256 * ReadDimensionalValue.
3257 ******************************************************************************/
3258 
ReadDimensionalValue(Var,indices)3259 Logical ReadDimensionalValue (Var, indices)
3260 struct VarStruct *Var;
3261 long indices[];
3262 {
3263   CDFstatus status;
3264   status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_,rVAR_), Var->varN,
3265 			    BOO(Var->zVar,zVAR_RECNUMBER_,
3266 					  rVARs_RECNUMBER_), 0L,
3267 			    BOO(Var->zVar,zVAR_DIMINDICES_,
3268 					  rVARs_DIMINDICES_), indices,
3269 		   GET_, BOO(Var->zVar,zVAR_DATA_,rVAR_DATA_), Var->value,
3270 		   NULL_);
3271   DisplayStatus (status, readingCDF);
3272   if (StatusBAD(status)) return FALSE;
3273   return TRUE;
3274 }
3275 
3276 /******************************************************************************
3277 * ValidFormat.
3278 ******************************************************************************/
3279 
ValidFormat(format)3280 Logical ValidFormat (format)
3281 char *format;
3282 {
3283   if (NULstring(format)) return FALSE;
3284   return TRUE;
3285 }
3286 
3287 /******************************************************************************
3288 * SameDimensionalities.
3289 ******************************************************************************/
3290 
SameDimensionalities(numDims,dimSizes,exportHead)3291 Logical SameDimensionalities (numDims, dimSizes, exportHead)
3292 long *numDims;
3293 long dimSizes[];
3294 struct ItemStruct *exportHead;
3295 {
3296   struct ItemStruct *Item; Logical first = TRUE; int n;
3297   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
3298      if (Item->type == VARIABLEt && (Item->output || Item->filter)) {
3299        if (first) {
3300 	 *numDims = Item->Var->numDims;
3301 	 for (n = 0; n < *numDims; n++) dimSizes[n] = Item->Var->dimSizes[n];
3302 	 first = FALSE;
3303        }
3304        else {
3305 	 if (Item->Var->numDims != *numDims) return FALSE;
3306 	 for (n = 0; n < *numDims; n++) {
3307 	    if (Item->Var->dimSizes[n] != dimSizes[n]) return FALSE;
3308 	 }
3309        }
3310      }
3311   }
3312   return TRUE;
3313 }
3314 
3315 /******************************************************************************
3316 * ValidateRecordIndices.
3317 ******************************************************************************/
3318 
ValidateRecordIndices(type,same,numDims,exportHead)3319 void ValidateRecordIndices (type, same, numDims, exportHead)
3320 int type;                       /* Output type. */
3321 Logical same;                   /* Ignored if horizontal mode. */
3322 long numDims;                   /* Ignored if horizontal mode. */
3323 struct ItemStruct *exportHead;
3324 {
3325   struct ItemStruct *Item; int dimN;
3326   static char recordMsgOUT[] = {
3327     "`Record' not allowed for output."
3328   };
3329   static char indicesMsgODD[] = {
3330     "`Indices' not allowed for output (different dimensionalities)."
3331   };
3332   static char indicesMsgFDD[] = {
3333     "`Indices' not allowed for filtering (different dimensionalities)."
3334   };
3335   static char indicesMsgMIN[] = {
3336     "Wrong number of dimensions for minimum `Indices' filter."
3337   };
3338   static char indicesMsgMAX[] = {
3339     "Wrong number of dimensions for maximum `Indices' filter."
3340   };
3341   static char indicesMsgGT[] = {
3342     "Minimum `Indices' filter index is greater than maximum index."
3343   };
3344   static char indicesMsgOHM[] = {
3345     "`Indices' not allowed for output (horizontal mode)."
3346   };
3347   static char indicesMsgFHM[] = {
3348     "`Indices' not allowed for filtering (horizontal mode)."
3349   };
3350   static char indicesMsgOZD[] = {
3351     "`Indices' not allowed for output (zero dimensions)."
3352   };
3353   static char indicesMsgFZD[] = {
3354     "`Indices' not allowed for filtering (zero dimensions)."
3355   };
3356   static char indicesMsgOUT[] = {
3357     "`Indices' not allowed for output."
3358   };
3359   /****************************************************************************
3360   * Search list of exported items for `Record'.
3361   ****************************************************************************/
3362   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
3363      if (Item->type == RECORDt) {
3364        if (Item->output) {
3365 	 if (type == OUTPUTtoCDF) {
3366 	   DisplayMessage (recordMsgOUT, NOBEEPWAIT1);
3367 	   Item->output = FALSE;
3368 	 }
3369        }
3370        break;
3371      }
3372   }
3373   /****************************************************************************
3374   * Search list of exported items for `Indices'.
3375   ****************************************************************************/
3376   for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
3377      if (Item->type == INDICESt) {
3378        switch (type) {
3379 	case OUTPUTtoSCREENh:
3380 	case OUTPUTtoFILEh:
3381 	 /*********************************************************************
3382 	 * Output not allowed in horizontal mode.
3383 	 *********************************************************************/
3384 	 if (Item->output) {
3385 	   DisplayMessage (indicesMsgOHM, NOBEEPWAIT1);
3386 	   Item->output = FALSE;
3387 	 }
3388 	 /*********************************************************************
3389 	 * Filtering not allowed in horizontal mode.
3390 	 *********************************************************************/
3391 	 if (Item->filter) {
3392 	   DisplayMessage (indicesMsgFHM, NOBEEPWAIT1);
3393 	   Item->filter = FALSE;
3394 	 }
3395 	 break;
3396 	case OUTPUTtoSCREENv:
3397 	case OUTPUTtoFILEv:
3398 	 if (same) {
3399 	   if (Item->output) {
3400 	     /*****************************************************************
3401 	     * Output not allowed if zero dimensions.
3402 	     *****************************************************************/
3403 	     if (numDims == 0) {
3404 	       DisplayMessage (indicesMsgOZD, NOBEEPWAIT1);
3405 	       Item->output = FALSE;
3406 	     }
3407 	   }
3408 	   if (Item->filter) {
3409 	     Logical checkGT = TRUE;
3410 	     /*****************************************************************
3411 	     * Filtering not allowed if zero dimensions.
3412 	     *****************************************************************/
3413 	     if (numDims == 0) {
3414 	       DisplayMessage (indicesMsgFZD, NOBEEPWAIT1);
3415 	       Item->filter = FALSE;
3416 	     }
3417 	     /*****************************************************************
3418 	     * Filtering not allowed if wrong number of indices (minimum).
3419 	     *****************************************************************/
3420 	     if (Item->Indices->minNumDims != NOminMax) {
3421 	       if (Item->Indices->minNumDims != numDims) {
3422 		 DisplayMessage (indicesMsgMIN, NOBEEPWAIT1);
3423 		 Item->filter = FALSE;
3424 		 checkGT = FALSE;
3425 	       }
3426 	     }
3427 	     /*****************************************************************
3428 	     * Filtering not allowed if wrong number of indices (maximum).
3429 	     *****************************************************************/
3430 	     if (Item->Indices->maxNumDims != NOminMax) {
3431 	       if (Item->Indices->maxNumDims != numDims) {
3432 		 DisplayMessage (indicesMsgMAX, NOBEEPWAIT1);
3433 		 Item->filter = FALSE;
3434 		 checkGT = FALSE;
3435 	       }
3436 	     }
3437 	     /*****************************************************************
3438 	     * Filtering not allowed if minimum greater than maximum.
3439 	     *****************************************************************/
3440 	     if (Item->Indices->minNumDims != NOminMax &&
3441 		 Item->Indices->maxNumDims != NOminMax && checkGT) {
3442 	       for (dimN = 0; dimN < numDims; dimN++) {
3443 		  if (Item->Indices->minIndices[dimN] >
3444 		      Item->Indices->maxIndices[dimN]) {
3445 		    DisplayMessage (indicesMsgGT, NOBEEPWAIT1);
3446 		    Item->filter = FALSE;
3447 		  }
3448 	       }
3449 	     }
3450 	   }
3451 	 }
3452 	 else {
3453 	   /*******************************************************************
3454 	   * Output not allowed if different dimensionalities.
3455 	   *******************************************************************/
3456 	   if (Item->output) {
3457 	     DisplayMessage (indicesMsgODD, NOBEEPWAIT1);
3458 	     Item->output = FALSE;
3459 	   }
3460 	   /*******************************************************************
3461 	   * Filtering not allowed if different dimensionalities.
3462 	   *******************************************************************/
3463 	   if (Item->filter) {
3464 	     DisplayMessage (indicesMsgFDD, NOBEEPWAIT1);
3465 	     Item->filter = FALSE;
3466 	   }
3467 	 }
3468 	 break;
3469 	case OUTPUTtoCDF:
3470 	 /*********************************************************************
3471 	 * Output not allowed.
3472 	 *********************************************************************/
3473 	 if (Item->output) {
3474 	   DisplayMessage (indicesMsgOUT, NOBEEPWAIT1);
3475 	   Item->output = FALSE;
3476 	 }
3477 	 if (same) {
3478 	   if (Item->filter) {
3479 	     Logical checkGT = TRUE;
3480 	     /*****************************************************************
3481 	     * Filtering not allowed if zero dimensions.
3482 	     *****************************************************************/
3483 	     if (numDims == 0) {
3484 	       DisplayMessage (indicesMsgFZD, NOBEEPWAIT1);
3485 	       Item->filter = FALSE;
3486 	     }
3487 	     /*****************************************************************
3488 	     * Filtering not allowed if wrong number of indices (minimum).
3489 	     *****************************************************************/
3490 	     if (Item->Indices->minNumDims != NOminMax) {
3491 	       if (Item->Indices->minNumDims != numDims) {
3492 		 DisplayMessage (indicesMsgMIN, NOBEEPWAIT1);
3493 		 Item->filter = FALSE;
3494 		 checkGT = FALSE;
3495 	       }
3496 	     }
3497 	     /*****************************************************************
3498 	     * Filtering not allowed if wrong number of indices (maximum).
3499 	     *****************************************************************/
3500 	     if (Item->Indices->maxNumDims != NOminMax) {
3501 	       if (Item->Indices->maxNumDims != numDims) {
3502 		 DisplayMessage (indicesMsgMAX, NOBEEPWAIT1);
3503 		 Item->filter = FALSE;
3504 		 checkGT = FALSE;
3505 	       }
3506 	     }
3507 	     /*****************************************************************
3508 	     * Filtering not allowed if minimum greater than maximum.
3509 	     *****************************************************************/
3510 	     if (Item->Indices->minNumDims != NOminMax &&
3511 		 Item->Indices->maxNumDims != NOminMax && checkGT) {
3512 	       for (dimN = 0; dimN < numDims; dimN++) {
3513 		  if (Item->Indices->minIndices[dimN] >
3514 		      Item->Indices->maxIndices[dimN]) {
3515 		    DisplayMessage (indicesMsgGT, NOBEEPWAIT1);
3516 		    Item->filter = FALSE;
3517 		  }
3518 	       }
3519 	     }
3520 	   }
3521 	 }
3522 	 else {
3523 	   /*******************************************************************
3524 	   * Filtering not allowed if different dimensionalities.
3525 	   *******************************************************************/
3526 	   if (Item->filter) {
3527 	     DisplayMessage (indicesMsgFDD, NOBEEPWAIT1);
3528 	     Item->filter = FALSE;
3529 	   }
3530 	 }
3531 	 break;
3532        }
3533        break;
3534      }
3535   }
3536   return;
3537 }
3538 
3539 /******************************************************************************
3540 * RecordPassesMin.
3541 *   It is assumed that overall filtered and filtering for the `Record' item
3542 * are both enabled.
3543 ******************************************************************************/
3544 
RecordPassesMin(Item,recN)3545 Logical RecordPassesMin (Item, recN)
3546 struct ItemStruct *Item;
3547 long recN;
3548 {
3549   if (Item->Record->min == NOminMax) return TRUE;
3550   if (BOO(Item->inclusive,
3551 	  recN >= Item->Record->min,
3552 	  recN > Item->Record->min)) return TRUE;
3553   return FALSE;
3554 }
3555 
3556 /******************************************************************************
3557 * RecordPassesMax.
3558 *   It is assumed that overall filtered and filtering for the `Record' item
3559 * are both enabled.
3560 ******************************************************************************/
3561 
RecordPassesMax(Item,recN)3562 Logical RecordPassesMax (Item, recN)
3563 struct ItemStruct *Item;
3564 long recN;
3565 {
3566   if (Item->Record->max == NOminMax) return TRUE;
3567   if (BOO(Item->inclusive,
3568 	  recN <= Item->Record->max,
3569 	  recN < Item->Record->max)) return TRUE;
3570   return FALSE;
3571 }
3572 
3573 /******************************************************************************
3574 * IndicesPassMin.
3575 *   It is assumed that overall filtered and filtering for the `Indices' item
3576 * are both enabled.
3577 ******************************************************************************/
3578 
IndicesPassMin(Item,indices)3579 Logical IndicesPassMin (Item, indices)
3580 struct ItemStruct *Item;
3581 long indices[];
3582 {
3583   int dimN;
3584   if (Item->Indices->minNumDims == NOminMax) return TRUE;
3585   for (dimN = 0; dimN < Item->Indices->minNumDims; dimN++) {
3586      if (BOO(Item->inclusive,
3587 	     indices[dimN] < Item->Indices->minIndices[dimN],
3588 	     indices[dimN] <= Item->Indices->minIndices[dimN])) return FALSE;
3589   }
3590   return TRUE;
3591 }
3592 
3593 /******************************************************************************
3594 * IndicesPassMax.
3595 *   It is assumed that overall filtered and filtering for the `Indices' item
3596 * are both enabled.
3597 ******************************************************************************/
3598 
IndicesPassMax(Item,indices)3599 Logical IndicesPassMax (Item, indices)
3600 struct ItemStruct *Item;
3601 long indices[];
3602 {
3603   int dimN;
3604   if (Item->Indices->maxNumDims == NOminMax) return TRUE;
3605   for (dimN = 0; dimN < Item->Indices->maxNumDims; dimN++) {
3606      if (BOO(Item->inclusive,
3607 	     indices[dimN] > Item->Indices->maxIndices[dimN],
3608 	     indices[dimN] >= Item->Indices->maxIndices[dimN])) return FALSE;
3609   }
3610   return TRUE;
3611 }
3612 
3613 /******************************************************************************
3614 * VarPassesMin.
3615 *   It is assumed that overall filtered and filtering for this variable are
3616 * both enabled.
3617 ******************************************************************************/
3618 
VarPassesMin(Item,value)3619 Logical VarPassesMin (Item, value)
3620 struct ItemStruct *Item;
3621 void *value;
3622 {
3623   if (Item->Var->min == NULL) return TRUE;
3624   if (BOO(Item->inclusive,
3625 	  GEx(value,Item->Var->min,Item->Var->dataType,Item->Var->numElems),
3626 	  GTx(value,Item->Var->min,Item->Var->dataType,Item->Var->numElems))) {
3627     return TRUE;
3628   }
3629   if (USEFILL(Item->Var,opt)) {
3630     if (EQx(value,Item->Var->fill,Item->Var->dataType,Item->Var->numElems)) {
3631       return TRUE;
3632     }
3633   }
3634   return FALSE;
3635 }
3636 
3637 /******************************************************************************
3638 * VarPassesMax.
3639 *   It is assumed that overall filtered and filtering for this variable are
3640 * both enabled.
3641 ******************************************************************************/
3642 
VarPassesMax(Item,value)3643 Logical VarPassesMax (Item, value)
3644 struct ItemStruct *Item;
3645 void *value;
3646 {
3647   if (Item->Var->max == NULL) return TRUE;
3648   if (BOO(Item->inclusive,
3649 	  LEx(value,Item->Var->max,Item->Var->dataType,Item->Var->numElems),
3650 	  LTx(value,Item->Var->max,Item->Var->dataType,Item->Var->numElems))) {
3651     return TRUE;
3652   }
3653   if (USEFILL(Item->Var,opt)) {
3654     if (EQx(value,Item->Var->fill,Item->Var->dataType,Item->Var->numElems)) {
3655       return TRUE;
3656     }
3657   }
3658   return FALSE;
3659 }
3660 
3661 /******************************************************************************
3662 * DisplayPctComplete.
3663 * Does nothing if in batch mode.
3664 ******************************************************************************/
3665 
DisplayPctComplete(pct,msg)3666 void DisplayPctComplete (pct, msg)
3667 int pct;
3668 char *msg;
3669 {
3670   static int lastPct;
3671   if (BATCH(batchMode)) return;
3672   if (pct == NO_PCT) {
3673     lastPct = NO_PCT;
3674     DisplayMessage (msg, NOWAIT);
3675     return;
3676   }
3677   if (pct > lastPct) {
3678     char text[SCREEN_WIDTH+1], pctText[8+1]; int pad;
3679     strcpyX (text, msg, SCREEN_WIDTH - 2);
3680     sprintf (pctText, "%d%%", pct);
3681     pad = (SCREEN_WIDTH - 2) - strlen(text) - strlen(pctText);
3682     CatNcharacters (text, pad, ' ');
3683     strcatX (text, pctText, SCREEN_WIDTH - 2);
3684     DisplayMessage (text, NOWAIT);
3685     lastPct = pct;
3686   }
3687   return;
3688 }
3689 
3690 /******************************************************************************
3691 * UpdateToScreen.
3692 ******************************************************************************/
3693 
UpdateToScreen(EWscr,trailerMsg,at,total)3694 void UpdateToScreen (EWscr, trailerMsg, at, total)
3695 struct EditWindowStruct *EWscr;
3696 char *trailerMsg;
3697 long at;
3698 long total;
3699 {
3700   int pad; char pct[8+1];
3701   AOSs1 (trailer, BLANKs78)
3702   strcpyX (trailer[0], trailerMsg, SCREEN_WIDTH - 2);
3703   sprintf (pct, "%ld%%", (100 * at) / total);
3704   pad = (SCREEN_WIDTH - 2) - strlen(trailer[0]) - strlen(pct);
3705   CatNcharacters (trailer[0], pad, ' ');
3706   strcatX (trailer[0], pct, SCREEN_WIDTH - 2);
3707   EWscr->tLines = trailer;
3708   EditWindow (UPDATEew, EWscr, LogicalTRUE);
3709   return;
3710 }
3711 
3712 /******************************************************************************
3713 * StandardFormat.
3714 ******************************************************************************/
3715 
StandardFormat(dataType)3716 char *StandardFormat (dataType)
3717 long dataType;
3718 {
3719   switch (dataType) {
3720     case CDF_CHAR:
3721     case CDF_UCHAR: return NULL;
3722     case CDF_BYTE:
3723     case CDF_INT1: return "%4d";
3724     case CDF_UINT1: return "%3u";
3725     case CDF_INT2: return "%6d";
3726     case CDF_UINT2: return "%5u";
3727     case CDF_INT4: return Int32FORMATstandard;
3728     case CDF_UINT4: return Int32uFORMATstandard;
3729     case CDF_REAL4:
3730     case CDF_FLOAT: return "%16.9e";
3731     case CDF_REAL8:
3732     case CDF_DOUBLE: return "%25.17e";
3733     case CDF_EPOCH:
3734       switch (opt.epochStyle) {
3735         case EPOCH0_STYLE:
3736         case EPOCH1_STYLE:
3737         case EPOCH2_STYLE:
3738         case EPOCH3_STYLE: return NULL;
3739         case EPOCHf_STYLE: return StandardFormat(CDF_REAL8);
3740         case EPOCHx_STYLE: return EPOCHx_FORMAT_STANDARD;
3741       }
3742     case CDF_EPOCH16:	/* Based on EPOCH, it only shows 1 of 2 doubles.*/
3743       switch (opt.epochStyle) {
3744         case EPOCH0_STYLE:
3745         case EPOCH1_STYLE:
3746         case EPOCH2_STYLE:
3747         case EPOCH3_STYLE: return NULL;
3748         case EPOCHf_STYLE: return StandardFormat(CDF_REAL8);
3749         case EPOCHx_STYLE: return EPOCHx_FORMAT_STANDARD;
3750       }
3751   }
3752   return NULL;
3753 }
3754 
3755 /******************************************************************************
3756 * StandardWidth.
3757 ******************************************************************************/
3758 
StandardWidth(dataType,numElems)3759 int StandardWidth (dataType, numElems)
3760 long dataType;
3761 long numElems;
3762 {
3763   switch (dataType) {
3764     case CDF_CHAR:
3765     case CDF_UCHAR: return (int) (1 + numElems + 1);
3766     case CDF_BYTE:
3767     case CDF_INT1:
3768     case CDF_UINT1:
3769     case CDF_INT2:
3770     case CDF_UINT2:
3771     case CDF_INT4:
3772     case CDF_UINT4:
3773     case CDF_REAL4:
3774     case CDF_FLOAT:
3775     case CDF_REAL8:
3776     case CDF_DOUBLE: return FormatWidth(StandardFormat(dataType));
3777     case CDF_EPOCH:
3778       switch (opt.epochStyle) {
3779         case EPOCH0_STYLE: return EPOCH_STRING_LEN;
3780         case EPOCH1_STYLE: return EPOCH1_STRING_LEN;
3781         case EPOCH2_STYLE: return EPOCH2_STRING_LEN;
3782         case EPOCH3_STYLE: return EPOCH3_STRING_LEN;
3783         case EPOCHf_STYLE: return FormatWidth(StandardFormat(CDF_REAL8));
3784         case EPOCHx_STYLE: return (int) strlen(EPOCHx_FORMAT_STANDARD);
3785       }
3786     case CDF_EPOCH16:	/* Based on EPOCH, it only shows 1 of 2 doubles.*/
3787       switch (opt.epochStyle) {
3788         case EPOCH0_STYLE: return EPOCH16_STRING_LEN;
3789         case EPOCH1_STYLE: return EPOCH16_1_STRING_LEN;
3790         case EPOCH2_STYLE: return EPOCH16_2_STRING_LEN;
3791         case EPOCH3_STYLE: return EPOCH16_3_STRING_LEN;
3792         case EPOCHf_STYLE: return FormatWidth(StandardFormat(CDF_REAL8));
3793         case EPOCHx_STYLE: return (int) strlen(EPOCHx_FORMAT_STANDARD);
3794       }
3795   }
3796   return 0;
3797 }
3798