/******************************************************************************
*
* NSSDC/CDF CDFexport/2.
*
* Version 1.2b, 2-Sep-97, Hughes STX.
*
* Modification history:
*
* V1.0 15-Sep-95, J Love Original version.
* V1.0a 18-Sep-95, J Love Macintosh event handling.
* V1.0b 22-Sep-95, J Love INITIALRECS/ALLOCATERECS in `AllocateRecords'.
* V1.1 9-Sep-96, J Love CDF V2.6.
* V1.2 15-Nov-96, J Love Added `simple' mode and batch mode.
* V1.2a 8-Jan-96, J Love Changed settings file messages.
* V1.2b 2-Sep-97, J Love Fixed `inclusive' filtering.
*
******************************************************************************/
#include "cdfxp.h"
/******************************************************************************
* Local macros.
******************************************************************************/
#define SETTINGS_DELIM '"'
#define COUNTx(max,first,last) \
BOO(max < first,0,BOO(max < last,max-first+1,last-first+1));
/******************************************************************************
* Local function prototypes.
******************************************************************************/
static Logical SetFilter PROTOARGs((char *field, struct ItemStruct *Item));
static Logical SetOutput PROTOARGs((char *field, struct ItemStruct *Item));
static Logical SetWidth PROTOARGs((char *field, struct ItemStruct *Item));
static Logical SetBlocking PROTOARGs((char *field, struct VarStruct *Var));
static Logical SetMonotonic PROTOARGs((char *field, struct VarStruct *Var));
static Logical SetSparseness PROTOARGs((char *field, struct VarStruct *Var));
static Logical SetCompression PROTOARGs((char *field, struct VarStruct *Var));
static Logical ScanValueField PROTOARGs((
char *fieldPtr, long dataType, long numElems, char **commaPtr, void **value
));
static void WriteDelimitedString PROTOARGs((
FILE *fp, int delim, char *string
));
static char *EndingDelimiter PROTOARGs((char *string));
static void RemoveDelimiters PROTOARGs((char *string));
static Logical AllocateRecords PROTOARGs((
CDFid outID, struct ItemStruct *scalarHead, struct ItemStruct *hyperHead
));
static CDFstatus BuildWalkScreen PROTOARGs((
struct ItemStruct *exportHead, long recordN, long numDims, long indices[],
char *lineS[], int lineNs[], int colS[], int lenS[], struct VarStruct *Vars[]
));
static Logical PromptForRecordNumber PROTOARGs((long *recordN, long maxRec));
static Logical PromptForDimensionIndex PROTOARGs((long *index, long dimSize));
static Logical PromptForVariableSearch PROTOARGs((
struct VarStruct *Var, int *searchType, void **searchValue
));
static CDFstatus SearchForVariableValue PROTOARGs((
struct VarStruct *Var, long numDims, long dimSizes[], long *recordAt,
long indicesAt[], long maxRec, int searchType, void *searchValue
));
static Logical AbortSearch PROTOARGs((void));
/******************************************************************************
* SaveSettings.
******************************************************************************/
void SaveSettings () {
FILE *fp; long version, release, increment; char subIncr;
struct ItemStruct *Item; CDFstatus status;
status = CDFlib (GET_, LIB_VERSION_, &version,
LIB_RELEASE_, &release,
LIB_INCREMENT_, &increment,
LIB_subINCREMENT_, &subIncr,
NULL_);
DisplayStatus (status, "inquiring CDF");
if (StatusBAD(status)) return;
fp = fopen (settingsFile, "w");
if (fp == NULL) {
DisplayMessage ("Error opening settings file.", BEEPWAIT1);
return;
}
fprintf (fp, "CDF V%ld.%ld.%ld%c%s\n", version, release, increment, subIncr,
BOO(simpleMode," (SimpleMode)",""));
for (Item = itemHead; Item != NULL; Item = Item->nextItem) {
switch (Item->type) {
case RECORDt:
fprintf (fp, "ITEM=Record,");
fprintf (fp, "%s,", BOO(Item->outputSetting,"YES","no"));
if (!simpleMode) {
if (Item->Record->min == NOminMax)
fprintf (fp, ",");
else
fprintf (fp, "%ld,", Item->Record->min + 1);
if (Item->Record->max == NOminMax)
fprintf (fp, ",");
else
fprintf (fp, "%ld,", Item->Record->max + 1);
fprintf (fp, "%s,", BOO(Item->filterSetting,
BOO(opt.exclusive,
BOO(Item->inclusive,"YeS","yEs"),
"YES"),
"no"));
fprintf (fp, "%d,", Item->width);
}
fprintf (fp, "\n");
break;
case INDICESt:
fprintf (fp, "ITEM=Indices,");
fprintf (fp, "%s,", BOO(Item->outputSetting,"YES","no"));
if (!simpleMode) {
if (Item->Indices->minNumDims == NOminMax)
fprintf (fp, ",");
else {
char indices[MAXitemFieldLEN+1];
EncodeIndicesJustify (indices, Item->Indices->minNumDims,
Item->Indices->minIndices, 0);
fprintf (fp, "%s,", indices);
}
if (Item->Indices->maxNumDims == NOminMax)
fprintf (fp, ",");
else {
char indices[MAXitemFieldLEN+1];
EncodeIndicesJustify (indices, Item->Indices->maxNumDims,
Item->Indices->maxIndices, 0);
fprintf (fp, "%s,", indices);
}
fprintf (fp, "%s,", BOO(Item->filterSetting,
BOO(opt.exclusive,
BOO(Item->inclusive,"YeS","yEs"),
"YES"),
"no"));
fprintf (fp, "%d,", Item->width);
}
fprintf (fp, "\n");
break;
case VARIABLEt:
fprintf (fp, "ITEM=Variable,");
WriteDelimitedString (fp, (int) SETTINGS_DELIM, Item->Var->name);
fprintf (fp, ",");
fprintf (fp, "%s,", BOO(Item->outputSetting,"YES","no"));
if (!simpleMode) {
if (Item->Var->min != NULL) {
if (STRINGdataType(Item->Var->dataType))
WriteDelimitedString (fp, (int) SETTINGS_DELIM,
(char *) Item->Var->min);
else {
char temp[MAX_nonSTRING_VALUE_LEN+1];
EncodeValueFormat (BOO(EPOCHdataType(Item->Var->dataType),
CDF_REAL8,Item->Var->dataType),
Item->Var->min, temp,
BOO(EPOCHdataType(Item->Var->dataType),
"%.13e",NULL),
0, MAX_nonSTRING_VALUE_LEN, 0);
fprintf (fp, "[%s]", temp);
}
}
fprintf (fp, ",");
if (Item->Var->max != NULL) {
if (STRINGdataType(Item->Var->dataType))
WriteDelimitedString (fp, (int) SETTINGS_DELIM,
(char *) Item->Var->max);
else {
char temp[MAX_nonSTRING_VALUE_LEN+1];
EncodeValueFormat (BOO(EPOCHdataType(Item->Var->dataType),
CDF_REAL8,Item->Var->dataType),
Item->Var->max, temp,
BOO(EPOCHdataType(Item->Var->dataType),
"%.13e",NULL),
0, MAX_nonSTRING_VALUE_LEN, 0);
fprintf (fp, "[%s]", temp);
}
}
fprintf (fp, ",");
fprintf (fp, "%s,", BOO(Item->filterSetting,
BOO(opt.exclusive,
BOO(Item->inclusive,"YeS","yEs"),
"YES"),
"no"));
if (Item->Var->fill != NULL) {
if (STRINGdataType(Item->Var->dataType))
WriteDelimitedString (fp, (int) SETTINGS_DELIM,
(char *) Item->Var->fill);
else {
char temp[MAX_nonSTRING_VALUE_LEN+1];
EncodeValueFormat (BOO(EPOCHdataType(Item->Var->dataType),
CDF_REAL8,Item->Var->dataType),
Item->Var->fill, temp,
BOO(EPOCHdataType(Item->Var->dataType),
"%.13e",NULL),
0, MAX_nonSTRING_VALUE_LEN, 0);
fprintf (fp, "[%s]", temp);
}
}
fprintf (fp, ",");
fprintf (fp, "%s,", monos[Item->Var->monotonic+1]);
if (Item->Var->format != NULL) {
WriteDelimitedString (fp, (int)SETTINGS_DELIM, Item->Var->format);
}
fprintf (fp, ",");
fprintf (fp, "%d,", Item->width);
fprintf (fp, "%s,", SparsenessToken(Item->Var->sRecordsType,
Item->Var->sArraysType,
Item->Var->sArraysParms));
fprintf (fp, "%s,", CompressionToken(Item->Var->cType,
Item->Var->cParms));
fprintf (fp, "%ld,", Item->Var->blocking);
}
fprintf (fp, "\n");
break;
}
}
if (!simpleMode) {
fprintf (fp, "USE_FILTERS=%s\n", BOO(opt.overallFilter,"YES","no"));
fprintf (fp, "USE_FILLS=%s\n", BOO(opt.useFills,"YES","no"));
fprintf (fp, "CDF_FORMAT=%s\n", BOO(opt.singleFile,"single","multi"));
fprintf (fp, "CDF_ENCODING=%s\n", encodings[(int)opt.encoding]);
if (CDFcType != NO_COMPRESSION)
fprintf (fp, "CDF_COMPRESSION=%s\n",CompressionToken(CDFcType, CDFcParms));
if (CDFchecksum != NO_CHECKSUM)
fprintf (fp, "CDF_CHECKSUM=%s\n",ChecksumToken(CDFchecksum));
fprintf (fp, "EPOCH_STYLE=%s\n", epochStyles[opt.epochStyle]);
fprintf (fp, "ORIENTATION=%s\n",
BOO(opt.horizontalMode,"horizontal","vertical"));
fprintf (fp, "MAJORITY=%s\n", majorities[(int)opt.majority]);
fprintf (fp, "SHOW_FILTERED=%s\n", BOO(opt.showFiltered,"YES","no"));
fprintf (fp, "SPACING=%d\n", opt.spacing);
fprintf (fp, "DELETE_EXISTING=%s\n", BOO(opt.deleteExisting,"YES","no"));
fprintf (fp, "PREALLOCATE=%s\n", BOO(opt.preAllocate,"YES","no"));
}
fclose (fp);
return;
}
/******************************************************************************
* RestoreSettings.
******************************************************************************/
void RestoreSettings () {
char *equalPtr, *newlinePtr, *commaPtr, *fieldPtr, *linePtr, *delimPtr;
FILE *fp; long valueL; struct ItemStruct *Item;
char line[MAX_SETTINGS_LEN+1+1]; /* +1+1 for newline+NUL. */
if (!IsReg(settingsFile)) {
DisplayMessage ("Settings file does not exist.", BEEPWAIT1);
return;
}
fp = fopen (settingsFile, "r");
if (fp == NULL) {
DisplayMessage ("Error opening settings file.", BEEPWAIT1);
return;
}
linePtr = fgets (line, MAX_SETTINGS_LEN+1+1, fp);
if (linePtr == NULL) {
DisplayMessage ("Error reading settings file.", BEEPWAIT1);
return;
}
while ((linePtr = fgets(line,MAX_SETTINGS_LEN+1+1,fp)) != NULL) {
newlinePtr = strchr (line, '\n');
if (newlinePtr != NULL)
*newlinePtr = NUL;
else {
/* Line was longer than MAX_SETTINGS_LEN. What should we do? */
}
equalPtr = strchr (line, '=');
if (equalPtr == NULL) break;
*equalPtr = NUL;
/**************************************************************************
* Check for item/variable.
**************************************************************************/
if (!strcmp(line,"ITEM")) {
fieldPtr = equalPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
/************************************************************************
* Check for `Record' item.
************************************************************************/
if (!strcmp(fieldPtr,"Record")) {
/**********************************************************************
* Check if `Record' is present in SelectionWindow.
**********************************************************************/
for (Item = itemHead; Item != NULL; Item = Item->nextItem) {
if (Item->type == RECORDt) break;
}
if (Item == NULL) continue;
/**********************************************************************
* Check for `Output' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetOutput(fieldPtr,Item)) break;
/**********************************************************************
* A settings file created in `simple' mode will end here.
**********************************************************************/
if (*(commaPtr+1) == NUL) continue;
/**********************************************************************
* Check for `Minimum' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (NULstring(fieldPtr))
Item->Record->min = NOminMax;
else
if (sscanf(fieldPtr,"%ld",&valueL) == 1)
if (valueL > 0)
Item->Record->min = valueL - 1;
else
break;
else
break;
/**********************************************************************
* Check for `Maximum' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (NULstring(fieldPtr))
Item->Record->max = NOminMax;
else
if (sscanf(fieldPtr,"%ld",&valueL) == 1)
if (valueL > 0)
Item->Record->max = valueL - 1;
else
break;
else
break;
/**********************************************************************
* Check that Minimum/Maximum fields are legal.
**********************************************************************/
if (Item->Record->min != NOminMax && Item->Record->max != NOminMax) {
if (Item->Record->min > Item->Record->max) {
Item->Record->min = NOminMax;
Item->Record->max = NOminMax;
break;
}
}
/**********************************************************************
* Check for `Filter' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetFilter(fieldPtr,Item)) break;
/**********************************************************************
* Check for `Width' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetWidth(fieldPtr,Item)) break;
continue;
}
/************************************************************************
* Check for `Indices' item.
************************************************************************/
if (!strcmp(fieldPtr,"Indices")) {
/**********************************************************************
* Check if `Indices' is present in SelectionWindow.
**********************************************************************/
for (Item = itemHead; Item != NULL; Item = Item->nextItem) {
if (Item->type == INDICESt) break;
}
if (Item == NULL) continue;
/**********************************************************************
* Check for `Output' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetOutput(fieldPtr,Item)) break;
/**********************************************************************
* A settings file created in `simple' mode will end here.
**********************************************************************/
if (*(commaPtr+1) == NUL) continue;
/**********************************************************************
* Check for `Minimum' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (*fieldPtr == '[') {
long numDims, indices[CDF_MAX_DIMS]; int dimN;
commaPtr = strchr (fieldPtr + 1, ']');
if (commaPtr == NULL) break;
commaPtr = strchr (commaPtr + 1, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (DecodeRecordAndIndices(fieldPtr,NULL,&numDims,indices)) {
Item->Indices->minNumDims = numDims;
for (dimN = 0; dimN < numDims; dimN++) {
Item->Indices->minIndices[dimN] = indices[dimN];
}
}
else
break;
}
else
if (*fieldPtr == ',') {
Item->Indices->minNumDims = NOminMax;
commaPtr = fieldPtr;
}
else
break;
/**********************************************************************
* Check for `Maximum' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (*fieldPtr == '[') {
long numDims, indices[CDF_MAX_DIMS]; int dimN;
commaPtr = strchr (fieldPtr + 1, ']');
if (commaPtr == NULL) break;
commaPtr = strchr (commaPtr + 1, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (DecodeRecordAndIndices(fieldPtr,NULL,&numDims,indices)) {
Item->Indices->maxNumDims = numDims;
for (dimN = 0; dimN < numDims; dimN++) {
Item->Indices->maxIndices[dimN] = indices[dimN];
}
}
else
break;
}
else
if (*fieldPtr == ',') {
Item->Indices->maxNumDims = NOminMax;
commaPtr = fieldPtr;
}
else
break;
/**********************************************************************
* Check for `Filter' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetFilter(fieldPtr,Item)) break;
/**********************************************************************
* Check for `Width' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetWidth(fieldPtr,Item)) break;
continue;
}
/************************************************************************
* Check for `Variable' item.
************************************************************************/
if (!strcmp(fieldPtr,"Variable")) {
/**********************************************************************
* Parse variable name.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (*fieldPtr != SETTINGS_DELIM) break;
delimPtr = EndingDelimiter (fieldPtr);
if (delimPtr == NULL) break;
commaPtr = delimPtr + 1;
if (*commaPtr != ',') break;
*commaPtr = NUL;
RemoveDelimiters (fieldPtr);
/**********************************************************************
* Check if the variable is in the SelectionWindow.
**********************************************************************/
for (Item = itemHead; Item != NULL; Item = Item->nextItem) {
if (Item->type == VARIABLEt) {
if (!strcmp(fieldPtr,Item->Var->name)) break;
}
}
if (Item == NULL) continue;
/**********************************************************************
* Check for `Output' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetOutput(fieldPtr,Item)) break;
/**********************************************************************
* A settings file created in `simple' mode will end here.
**********************************************************************/
if (*(commaPtr+1) == NUL) continue;
/**********************************************************************
* Check for `Minimum' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (!ScanValueField(fieldPtr,Item->Var->dataType,
Item->Var->numElems,&commaPtr,
&(Item->Var->min))) break;
/**********************************************************************
* Check for `Maximum' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (!ScanValueField(fieldPtr,Item->Var->dataType,
Item->Var->numElems,&commaPtr,
&(Item->Var->max))) break;
/**********************************************************************
* Check for `Filter' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetFilter(fieldPtr,Item)) break;
/**********************************************************************
* Check for `Fill' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (!ScanValueField(fieldPtr,Item->Var->dataType,
Item->Var->numElems,&commaPtr,
&(Item->Var->fill))) break;
/**********************************************************************
* Check for `Monotonicity' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetMonotonic(fieldPtr,Item->Var)) break;
/**********************************************************************
* Check for `Format' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
if (*fieldPtr == SETTINGS_DELIM) {
delimPtr = EndingDelimiter (fieldPtr);
if (delimPtr == NULL) break;
commaPtr = delimPtr + 1;
if (*commaPtr != ',') break;
*commaPtr = NUL;
RemoveDelimiters (fieldPtr);
if (Item->Var->format != NULL) {
cdf_FreeMemory (Item->Var->format, FatalError);
}
Item->Var->format = (char *) cdf_AllocateMemory (strlen(fieldPtr) + 1,
FatalError);
strcpyX (Item->Var->format, fieldPtr, 0);
}
else {
commaPtr = fieldPtr;
if (Item->Var->format != NULL) {
cdf_FreeMemory (Item->Var->format, FatalError);
Item->Var->format = NULL;
}
}
/**********************************************************************
* Check for `Width' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetWidth(fieldPtr,Item)) break;
/**********************************************************************
* Check for `Sparseness' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetSparseness(fieldPtr,Item->Var)) break;
/**********************************************************************
* Check for `Compression' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetCompression(fieldPtr,Item->Var)) break;
/**********************************************************************
* Check for `Blocking' field.
**********************************************************************/
fieldPtr = commaPtr + 1;
commaPtr = strchr (fieldPtr, ',');
if (commaPtr == NULL) break;
*commaPtr = NUL;
if (!SetBlocking(fieldPtr,Item->Var)) break;
/**********************************************************************
* Continue to next line...
**********************************************************************/
continue;
}
break;
}
/**************************************************************************
* Check for `Use filters'.
**************************************************************************/
if (!strcmp(line,"USE_FILTERS")) {
if (!strcmp(equalPtr+1,"YES")) {
opt.overallFilter = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"no")) {
opt.overallFilter = FALSE;
continue;
}
break;
}
/**************************************************************************
* Check for `Use fills'.
**************************************************************************/
if (!strcmp(line,"USE_FILLS")) {
if (!strcmp(equalPtr+1,"YES")) {
opt.useFills = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"no")) {
opt.useFills = FALSE;
continue;
}
break;
}
/**************************************************************************
* Check for `CDF Format'.
**************************************************************************/
if (!strcmp(line,"CDF_FORMAT")) {
if (!strcmp(equalPtr+1,"single")) {
opt.singleFile = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"multi")) {
opt.singleFile = FALSE;
continue;
}
break;
}
/**************************************************************************
* Check for `CDF Encoding'.
**************************************************************************/
if (!strcmp(line,"CDF_ENCODING")) {
int encoding; Logical found;
for (encoding = 0, found = FALSE; encoding <= MAX_ENCODING; encoding++) {
if (encodings[encoding] != NULL) {
if (!strcmp(equalPtr+1,encodings[encoding])) {
opt.encoding = encoding;
found = TRUE;
break;
}
}
}
if (found) continue;
break;
}
/**************************************************************************
* Check for `CDF Compression'.
**************************************************************************/
if (!strcmp(line,"CDF_COMPRESSION")) {
long type; Logical found;
long ct, cp[CDF_MAX_DIMS];
type = WhichCompression(equalPtr+1, &ct, cp);
if (type > -1) {
CDFcType = ct;
CDFcParms[0] = cp[0];
found = TRUE;
}
if (found) continue;
break;
}
/**************************************************************************
* Check for `CDF Checksum'.
**************************************************************************/
if (!strcmp(line,"CDF_CHECKSUM")) {
int type; Logical found;
for (type = 0, found = FALSE; type <= MAX_CHECKSUM; type++) {
if (checksums[type] != NULL) {
if (strcmpIgCase(equalPtr+1,checksums[type]) != 0) {
CDFchecksum = (long) type;
found = TRUE;
break;
}
}
}
if (found) continue;
break;
}
/**************************************************************************
* Check for `EPOCH Style'.
**************************************************************************/
if (!strcmp(line,"EPOCH_STYLE")) {
int style; Logical found;
for (style = EPOCH0_STYLE, found = FALSE;
style <= EPOCHx_STYLE; style++) {
if (!strcmp(equalPtr+1,epochStyles[style])) {
opt.epochStyle = style;
found = TRUE;
break;
}
}
if (found) continue;
break;
}
/**************************************************************************
* Check for `Listing Orientation'.
**************************************************************************/
if (!strcmp(line,"ORIENTATION")) {
if (!strcmp(equalPtr+1,"horizontal")) {
opt.horizontalMode = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"vertical")) {
opt.horizontalMode = FALSE;
continue;
}
break;
}
/**************************************************************************
* Check for `Listing/CDF Majority'.
**************************************************************************/
if (!strcmp(line,"MAJORITY")) {
if (!strcmp(equalPtr+1,"row")) {
opt.majority = ROW_MAJOR;
continue;
}
if (!strcmp(equalPtr+1,"column")) {
opt.majority = COLUMN_MAJOR;
continue;
}
if (!strcmp(equalPtr+1,"input")) {
opt.majority = INPUT_MAJOR;
continue;
}
break;
}
/**************************************************************************
* Check for `Show Filtered Lines'.
**************************************************************************/
if (!strcmp(line,"SHOW_FILTERED")) {
if (!strcmp(equalPtr+1,"YES")) {
opt.showFiltered = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"no")) {
opt.showFiltered = FALSE;
continue;
}
break;
}
/**************************************************************************
* Check for `Listing Spacing'.
**************************************************************************/
if (!strcmp(line,"SPACING")) {
int spacing;
if (sscanf(equalPtr+1,"%d",&spacing) == 1) {
if (0 <= spacing) {
opt.spacing = spacing;
continue;
}
else
break;
}
else
break;
}
/**************************************************************************
* Check for `Delete Existing CDF'.
**************************************************************************/
if (!strcmp(line,"DELETE_EXISTING")) {
if (!strcmp(equalPtr+1,"YES")) {
opt.deleteExisting = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"no")) {
opt.deleteExisting = FALSE;
continue;
}
break;
}
/**************************************************************************
* Check for `Preallocate Variable Records'.
**************************************************************************/
if (!strcmp(line,"PREALLOCATE")) {
if (!strcmp(equalPtr+1,"YES")) {
opt.preAllocate = TRUE;
continue;
}
if (!strcmp(equalPtr+1,"no")) {
opt.preAllocate = FALSE;
continue;
}
break;
}
break;
}
fclose (fp);
if (linePtr != NULL) {
DisplayMessage ("Error parsing settings file.", BEEPWAIT1);
return;
}
return;
}
/******************************************************************************
* SetFilter.
******************************************************************************/
static Logical SetFilter (field, Item)
char *field;
struct ItemStruct *Item;
{
if (!strcmp(field,"YES")) {
Item->filterSetting = TRUE;
Item->inclusive = TRUE;
return TRUE;
}
if (!strcmp(field,"YeS")) {
Item->filterSetting = TRUE;
Item->inclusive = TRUE;
return TRUE;
}
if (!strcmp(field,"yEs")) {
Item->filterSetting = TRUE;
Item->inclusive = FALSE;
return TRUE;
}
if (!strcmp(field,"no")) {
Item->filterSetting = FALSE;
Item->inclusive = TRUE;
return TRUE;
}
return FALSE;
}
/******************************************************************************
* SetOutput.
******************************************************************************/
static Logical SetOutput (field, Item)
char *field;
struct ItemStruct *Item;
{
if (!strcmp(field,"YES")) {
Item->outputSetting = TRUE;
return TRUE;
}
if (!strcmp(field,"no")) {
Item->outputSetting = FALSE;
return TRUE;
}
return FALSE;
}
/******************************************************************************
* SetWidth.
******************************************************************************/
static Logical SetWidth (field, Item)
char *field;
struct ItemStruct *Item;
{
int width;
if (sscanf(field,"%d",&width) != 1) return FALSE;
if (width < 1) return FALSE;
Item->width = width;
return TRUE;
}
/******************************************************************************
* SetBlocking.
******************************************************************************/
static Logical SetBlocking (field, Var)
char *field;
struct VarStruct *Var;
{
long blocking;
if (sscanf(field,"%ld",&blocking) != 1) return FALSE;
if (blocking < 0) return FALSE;
Var->blocking = blocking;
return TRUE;
}
/******************************************************************************
* SetMonotonic.
******************************************************************************/
static Logical SetMonotonic (field, Var)
char *field;
struct VarStruct *Var;
{
if (Var->monotonic != NAmono) {
if (!strcmp(field,"Increase")) {
Var->monotonic = INCREASEmono;
return TRUE;
}
if (!strcmp(field,"Decrease")) {
Var->monotonic = DECREASEmono;
return TRUE;
}
if (!strcmp(field,"False")) {
Var->monotonic = FALSEmono;
return TRUE;
}
if (!strcmp(field,"Unknown")) {
Var->monotonic = UNKNOWNmono;
return TRUE;
}
return FALSE;
}
return TRUE;
}
/******************************************************************************
* SetSparseness.
******************************************************************************/
static Logical SetSparseness (field, Var)
char *field;
struct VarStruct *Var;
{
Var->sRecordsType = NO_SPARSERECORDS;
if (strstr(field,"sRecords.PAD") != NULL) {
Var->sRecordsType = PAD_SPARSERECORDS;
return TRUE;
}
if (strstr(field,"sRecords.PREV") != NULL) {
Var->sRecordsType = PREV_SPARSERECORDS;
return TRUE;
}
return TRUE;
}
/******************************************************************************
* SetCompression.
******************************************************************************/
static Logical SetCompression (field, Var)
char *field;
struct VarStruct *Var;
{
if (!strcmp(field,"None")) {
Var->cType = NO_COMPRESSION;
return TRUE;
}
if (!strcmp(field,"RLE.0")) {
Var->cType = RLE_COMPRESSION;
Var->cParms[0] = RLE_OF_ZEROs;
return TRUE;
}
if (!strcmp(field,"HUFF.0")) {
Var->cType = HUFF_COMPRESSION;
Var->cParms[0] = OPTIMAL_ENCODING_TREES;
return TRUE;
}
if (!strcmp(field,"AHUFF.0")) {
Var->cType = AHUFF_COMPRESSION;
Var->cParms[0] = OPTIMAL_ENCODING_TREES;
return TRUE;
}
return TRUE;
}
/******************************************************************************
* ScanValueField.
******************************************************************************/
static Logical ScanValueField (fieldPtr, dataType, numElems, commaPtr, value)
char *fieldPtr; /* In: Pointer to beginning of field. */
long dataType; /* In: Data type of variable. */
long numElems; /* In: Number of elements of variable. */
char **commaPtr; /* Out: Pointer (to pointer) to ending comma. */
void **value; /* Out: Pointer (to pointer) to value. */
{
if (*fieldPtr == ',') {
if (*value != NULL) {
cdf_FreeMemory (*value, FatalError);
*value = NULL;
}
*commaPtr = fieldPtr;
return TRUE;
}
if (*fieldPtr == SETTINGS_DELIM) {
char *delimPtr = EndingDelimiter (fieldPtr);
if (delimPtr == NULL) return FALSE;
*commaPtr = delimPtr + 1;
if (**commaPtr != ',') return FALSE;
**commaPtr = NUL;
if (STRINGdataType(dataType)) {
RemoveDelimiters (fieldPtr);
if ((int) strlen(fieldPtr) == (int) numElems) {
if (*value == NULL) {
size_t nBytes = (size_t) (numElems + 1);
*value = (char *) cdf_AllocateMemory (nBytes, FatalError);
}
strcpyX (*value, fieldPtr, 0);
}
}
return TRUE;
}
if (*fieldPtr == '[') {
void *newValue; long newNumElems;
char *endPtr = strchr (fieldPtr + 1, ']');
if (endPtr == NULL) return FALSE;
*commaPtr = endPtr + 1;
if (**commaPtr != ',') return FALSE;
fieldPtr++;
*endPtr = NUL;
if (!STRINGdataType(dataType)) {
if (!DecodeValues(fieldPtr,BOO(EPOCHdataType(dataType),
CDF_REAL8,dataType),
&newNumElems,&newValue,0)) return FALSE;
if (newNumElems != numElems) {
cdf_FreeMemory (newValue, FatalError);
return FALSE;
}
if (*value != NULL) cdf_FreeMemory (*value, FatalError);
*value = newValue;
}
return TRUE;
}
return FALSE;
}
/******************************************************************************
* WriteDelimitedString.
******************************************************************************/
static void WriteDelimitedString (fp, delim, string)
FILE *fp;
int delim;
char *string;
{
int i;
fprintf (fp, "%c", (char) delim);
for (i = 0; string[i] != NUL; i++) {
if (string[i] == (char) delim) fprintf (fp, "%c", (char) delim);
fprintf (fp, "%c", string[i]);
}
fprintf (fp, "%c", (char) delim);
return;
}
/******************************************************************************
* EndingDelimiter.
******************************************************************************/
static char *EndingDelimiter (string)
char *string;
{
int i; char delim;
for (i = 1, delim = string[0]; string[i] != NUL; i++) {
if (string[i] == delim) {
if (string[i+1] != delim)
return &(string[i]);
else
i++;
}
}
return NULL;
}
/******************************************************************************
* RemoveDelimiters.
******************************************************************************/
static void RemoveDelimiters (string)
char *string;
{
int to = 0, from = 1; char delim = string[0];
for (;;) {
if (string[from] == NUL) {
string[to] = NUL;
return;
}
if (string[from] == delim)
if (string[from+1] == delim) {
string[to++] = delim;
from += 2;
}
else
from++;
else
string[to++] = string[from++];
}
}
/******************************************************************************
* SetItemMonotonicities.
* Returns FALSE if a fatal error occurred.
******************************************************************************/
Logical SetItemMonotonicities () {
struct ItemStruct *Item;
DisplayMessage ("Setting variable monotonicities.", NOBEEPWAIT1);
for (Item = itemHead; Item != NULL; Item = Item->nextItem) {
switch (Item->type) {
case RECORDt:
case INDICESt:
break;
case VARIABLEt:
if (Item->Var->monotonic != NAmono) {
if (!SetVarMonotonicity(Item->Var)) return FALSE;
}
break;
}
}
DisplayMessage ("", NOWAIT);
return TRUE;
}
/******************************************************************************
* SetVarMonotonicity.
* Returns FALSE if a fatal error occurred.
******************************************************************************/
Logical SetVarMonotonicity (Var)
struct VarStruct *Var;
{
static long indices[CDF_MAX_DIMS] = { 0,0,0,0,0,0,0,0,0,0 };
void *prevValue = NULL; CDFstatus status;
Var->monotonic = UNKNOWNmono;
status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_,rVAR_), Var->varN,
BOO(Var->zVar,zVAR_SEQPOS_,
rVAR_SEQPOS_), 0L, indices,
NULL_);
DisplayStatus (status, "setting variable monotonicity");
if (StatusBAD(status)) return FALSE;
status = CDFlib (GET_, BOO(Var->zVar,zVAR_SEQDATA_,
rVAR_SEQDATA_), Var->value,
NULL_);
while (StatusOK(status)) {
if (prevValue == NULL) {
prevValue = cdf_AllocateMemory (Var->nValueBytes, FatalError);
ASSIGNx (prevValue, Var->value, Var->dataType, Var->numElems);
}
else {
switch (Var->monotonic) {
case UNKNOWNmono:
if (GTx(Var->value,prevValue,Var->dataType,Var->numElems)) {
Var->monotonic = INCREASEmono;
break;
}
if (LTx(Var->value,prevValue,Var->dataType,Var->numElems)) {
Var->monotonic = DECREASEmono;
break;
}
Var->monotonic = FALSEmono;
cdf_FreeMemory (prevValue, FatalError);
return TRUE;
case INCREASEmono:
if (LTx(Var->value,prevValue,Var->dataType,Var->numElems)) {
Var->monotonic = FALSEmono;
cdf_FreeMemory (prevValue, FatalError);
return TRUE;
}
break;
case DECREASEmono:
if (GTx(Var->value,prevValue,Var->dataType,Var->numElems)) {
Var->monotonic = FALSEmono;
cdf_FreeMemory (prevValue, FatalError);
return TRUE;
}
break;
}
ASSIGNx (prevValue, Var->value, Var->dataType, Var->numElems);
}
status = CDFlib (GET_, BOO(Var->zVar,zVAR_SEQDATA_,
rVAR_SEQDATA_), Var->value,
NULL_);
}
if (prevValue != NULL) cdf_FreeMemory (prevValue, FatalError);
if (status != END_OF_VAR) {
DisplayStatus (status, "setting variable monotonicity");
if (StatusBAD(status)) return FALSE;
}
return TRUE;
}
/******************************************************************************
* BuildExportList.
******************************************************************************/
void BuildExportList (exportHead, walking)
struct ItemStruct **exportHead;
Logical walking;
{
struct ItemStruct *Item, *exportTail = NULL;
*exportHead = NULL;
for (Item = itemHead; Item != NULL; Item = Item->nextItem) {
if ((walking && Item->outputSetting && Item->type == VARIABLEt) ||
(!walking && (Item->outputSetting ||
(opt.overallFilter && Item->filterSetting)))) {
if (*exportHead == NULL)
*exportHead = exportTail = Item;
else
exportTail = exportTail->nextExport = Item;
Item->nextExport = NULL;
Item->output = Item->outputSetting;
Item->filter = BOO(opt.overallFilter,Item->filterSetting,FALSE);
}
}
return;
}
/******************************************************************************
* RemoveExportItems.
******************************************************************************/
void RemoveExportItems (exportHead)
struct ItemStruct **exportHead;
{
struct ItemStruct *Item = *exportHead, *prevItem = NULL;
while (Item != NULL) {
if (!Item->output && !Item->filter) {
if (prevItem == NULL)
*exportHead = Item->nextExport;
else
prevItem->nextExport = Item->nextExport;
}
else
prevItem = Item;
Item = Item->nextExport;
}
return;
}
/******************************************************************************
* FreeExportBuffers.
******************************************************************************/
void FreeExportBuffers (exportHead)
struct ItemStruct *exportHead;
{
struct ItemStruct *Item;
for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
if (Item->Var->buffer != NULL) cdf_FreeMemory (Item->Var->buffer,
FatalError);
}
return;
}
/******************************************************************************
* FindFirstRecord.
******************************************************************************/
long FindFirstRecord (recX, scalarHead, filteringScalars, recCount)
long recX;
struct ItemStruct *scalarHead;
Logical filteringScalars;
long recCount;
{
struct ItemStruct *Item; long firstX;
if (!filteringScalars) return recX;
for (firstX = recX; firstX < recCount; firstX++) {
Logical passes = TRUE;
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->filter) {
Byte *value = Item->Var->buffer +
(size_t) (firstX * Item->Var->nValueBytes);
if (!VarPassesMin(Item,value) || !VarPassesMax(Item,value)) {
passes = FALSE;
break;
}
}
}
if (passes) return firstX;
}
return NO_RECORD;
}
/******************************************************************************
* FindLastRecord.
******************************************************************************/
long FindLastRecord (firstX, scalarHead, filteringScalars, recCount)
long firstX;
struct ItemStruct *scalarHead;
Logical filteringScalars;
long recCount;
{
struct ItemStruct *Item; long recX;
if (!filteringScalars) return (recCount - 1);
for (recX = firstX + 1; recX < recCount; recX++) {
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->filter) {
Byte *value = Item->Var->buffer +
(size_t) (recX * Item->Var->nValueBytes);
if (!VarPassesMin(Item,value) ||
!VarPassesMax(Item,value)) return (recX - 1);
}
}
}
return (recCount - 1);
}
/******************************************************************************
* FilterBuffer.
******************************************************************************/
void FilterBuffer (Item, buffer, nValues)
struct ItemStruct *Item;
Byte *buffer;
long nValues;
{
long valueN; Byte *value;
for (valueN = 0, value = buffer; valueN < nValues;
valueN++, value += Item->Var->nValueBytes) {
if (!VarPassesMin(Item,value) || !VarPassesMax(Item,value)) {
if (USEFILL(Item->Var,opt))
ASSIGNx (value, Item->Var->fill,
Item->Var->dataType, Item->Var->numElems);
else
ASSIGNx (value, Item->Var->pad,
Item->Var->dataType, Item->Var->numElems);
}
}
return;
}
/******************************************************************************
* FilterHypers.
******************************************************************************/
void FilterHypers (hyperHead, nValues)
struct ItemStruct *hyperHead;
long nValues;
{
long valueN; Byte *value; struct ItemStruct *Item;
for (valueN = 0; valueN < nValues; valueN++) {
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->filter) {
value = VALUEinBUFFER (Item->Var, valueN);
if (!VarPassesMin(Item,value) || !VarPassesMax(Item,value)) {
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->output) {
value = VALUEinBUFFER (Item->Var, valueN);
if (USEFILL(Item->Var,opt))
ASSIGNx (value, Item->Var->fill, Item->Var->dataType,
Item->Var->numElems);
else
ASSIGNx (value, Item->Var->pad, Item->Var->dataType,
Item->Var->numElems);
}
}
break;
}
}
}
}
return;
}
/******************************************************************************
* AbortListing.
* Does nothing if in batch mode.
******************************************************************************/
Logical AbortListing (oFp, line)
FILE *oFp;
char *line;
{
int key;
static char keyDefsBlank[] = "\n\n";
if (BATCH(batchMode)) return FALSE;
if (read_input(
#if defined(CURSESui)
EWmsg->wid,
#endif
&key,PASSTHRUri,FALSE)) {
if (key == ABORTkey_EXPORT) {
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
DisplayMessage ("Aborting at user's request.", NOBEEPWAIT1);
DisplayMessage ("Listing file is not complete.", BEEPWAIT);
if (fclose(oFp) == EOF) {
DisplayMessage ("Error closing listing file.", BEEPWAIT);
}
cdf_FreeMemory (line, FatalError);
return TRUE;
}
else
EditWindow (BEEPew, EWmsg);
}
return FALSE;
}
/******************************************************************************
* AbortCDF.
* Does nothing if in batch mode.
******************************************************************************/
Logical AbortCDF (exportHead)
struct ItemStruct *exportHead;
{
int key;
static char keyDefsBlank[] = "\n\n";
if (BATCH(batchMode)) return FALSE;
if (read_input(
#if defined(CURSESui)
EWmsg->wid,
#endif
&key,PASSTHRUri,FALSE)) {
if (key == ABORTkey_EXPORT) {
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
DisplayMessage ("Aborting at user's request.", NOBEEPWAIT1);
DisplayMessage ("CDF is not complete.", BEEPWAIT);
FreeExportBuffers (exportHead);
return TRUE;
}
else
EditWindow (BEEPew, EWmsg);
}
return FALSE;
}
/******************************************************************************
* PreAllocateRecords.
******************************************************************************/
Logical PreAllocateRecords (inID, outID, scalarHead, hyperHead, firstRec,
lastRec)
CDFid inID;
CDFid outID;
struct ItemStruct *scalarHead;
struct ItemStruct *hyperHead;
long *firstRec;
long *lastRec;
{
long nRecords = *lastRec - *firstRec + 1, newFirstRec, newLastRec, nHypers;
long nValues, hyperN, recX, firstX, lastX, recF, recL;
CDFstatus status; struct ItemStruct *Item; struct HyperStruct hyper;
size_t nBytes, *nValueBytes; Byte ***handles; struct GroupStruct groups;
int filterCount, filterX;
AOSs1A (allocMsg,"Allocating variable records...")
/****************************************************************************
* Count number of scalars still being filtered. Note that monotonic
* scalars will have already been considered when the first/last record was
* determined (and filtering turned off for them).
****************************************************************************/
DisplayPctComplete (NO_PCT, allocMsg[0]);
for (Item = scalarHead, filterCount = 0;
Item != NULL; Item = Item->nextScalar) if (Item->filter) filterCount++;
/****************************************************************************
* If no scalars are being filtered, allocate records based on the current
* first/last records.
****************************************************************************/
if (filterCount == 0) {
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->output) {
Item->Var->oRecords = COUNTx(Item->Var->maxRec,*firstRec,*lastRec);
}
}
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->output) {
Item->Var->oRecords = COUNTx(Item->Var->maxRec,*firstRec,*lastRec);
}
}
if (!AllocateRecords(outID,scalarHead,hyperHead)) return FALSE;
return TRUE;
}
/****************************************************************************
* Allocate buffers for the scalars.
****************************************************************************/
nBytes = filterCount * sizeof(Byte **);
handles = (Byte ***) cdf_AllocateMemory (nBytes, FatalError);
nBytes = filterCount * sizeof(size_t);
nValueBytes = (size_t *) cdf_AllocateMemory (nBytes, FatalError);
for (Item = scalarHead, filterX = 0;
Item != NULL; Item = Item->nextScalar) {
if (Item->filter) {
handles[filterX] = &(Item->Var->buffer);
nValueBytes[filterX++] = Item->Var->nValueBytes;
}
}
AllocateBuffers (nRecords, 0L, NULL, &groups, filterCount, 0, handles,
nValueBytes, ROWmajor(inMajority), 1, FatalError);
cdf_FreeMemory (handles, FatalError);
cdf_FreeMemory (nValueBytes, FatalError);
/****************************************************************************
* Initialize new first/last records and output record counts (for those
* variables being output).
****************************************************************************/
newFirstRec = *lastRec + 1;
newLastRec = *firstRec - 1;
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->output) Item->Var->oRecords = 0;
}
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->output) Item->Var->oRecords = 0;
}
/****************************************************************************
* Read values for scalars being filtered and count the number of records
* that pass the filters. Also update the first/last records if needed.
****************************************************************************/
InitHyperParms (&hyper, &groups, 0L, &nHypers, &nValues);
for (hyperN = 0; hyperN < nHypers; hyperN++) {
/*************************************************************************
* Hyper read scalar values.
*************************************************************************/
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->filter) {
status = HYPERget (inID, Item->Var->varN, Item->Var->zVar,
*firstRec + hyper.recNumber, hyper.recCount,
dimIndices_0, dimCounts_1, Item->Var->buffer);
DisplayStatus (status, readingCDF);
if (StatusBAD(status)) {
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
cdf_FreeMemory (Item->Var->buffer, FatalError);
}
return FALSE;
}
}
}
/*************************************************************************
* Until no more records...
*************************************************************************/
for (recX = 0;;) {
/**********************************************************************
* Determine next range of records in this hyper read that pass the
* filters.
**********************************************************************/
firstX = FindFirstRecord (recX, scalarHead, TRUE, hyper.recCount);
if (firstX == NO_RECORD) break;
lastX = FindLastRecord (firstX, scalarHead, TRUE, hyper.recCount);
/**********************************************************************
* Calculate the absolute record number of this range and set the new
* first/last records accordingly.
**********************************************************************/
recF = *firstRec + hyper.recNumber + firstX;
recL = *firstRec + hyper.recNumber + lastX;
newFirstRec = MINIMUM(newFirstRec,recF);
newLastRec = MAXIMUM(newLastRec,recL);
/**********************************************************************
* Add to the output record count of those variables being output.
**********************************************************************/
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->output) {
Item->Var->oRecords += COUNTx(Item->Var->maxRec,recF,recL);
}
}
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->output) {
Item->Var->oRecords += COUNTx(Item->Var->maxRec,recF,recL);
}
}
/**********************************************************************
* Increment to check for the next range of records.
**********************************************************************/
recX = lastX + 1;
if (recX == hyper.recCount) break;
}
/*************************************************************************
* Increment to next hyper.
*************************************************************************/
IncrHyperParms (&hyper, &groups, 0L, ROWmajor(inMajority), &nValues);
}
/****************************************************************************
* Free memory used.
****************************************************************************/
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->Var->buffer != NULL)
cdf_FreeMemory (Item->Var->buffer, FatalError);
}
/****************************************************************************
* Check/set the new first/last records.
****************************************************************************/
if (newLastRec < newFirstRec) {
DisplayMessage ("No records in valid range.", BEEPWAIT1);
return FALSE;
}
*firstRec = newFirstRec;
*lastRec = newLastRec;
/****************************************************************************
* Allocate the records.
****************************************************************************/
if (!AllocateRecords(outID,scalarHead,hyperHead)) return FALSE;
return TRUE;
}
/******************************************************************************
* AllocateRecords.
******************************************************************************/
static Logical AllocateRecords (outID, scalarHead, hyperHead)
CDFid outID;
struct ItemStruct *scalarHead;
struct ItemStruct *hyperHead;
{
CDFstatus status; struct ItemStruct *Item; int varCount = 0, varNum = 0;
AOSs1A (allocMsg,"Allocating variable records.")
#if defined(vms)
long rItem = rVAR_INITIALRECS_;
long zItem = zVAR_INITIALRECS_;
#else
long rItem = rVAR_ALLOCATERECS_;
long zItem = zVAR_ALLOCATERECS_;
#endif
/****************************************************************************
* Count number of variables being allocated.
****************************************************************************/
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->output && Item->Var->oRecords > 0) varCount++;
}
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->output && Item->Var->oRecords > 0) varCount++;
}
/****************************************************************************
* Select output CDF.
****************************************************************************/
status = CDFlib (SELECT_, CDF_, outID,
NULL_);
DisplayStatus (status, "selecting output CDF");
if (StatusBAD(status)) return FALSE;
/****************************************************************************
* Allocate records for scalar variables being output. Also check that one
* or more records will be written to the variable.
****************************************************************************/
for (Item = scalarHead; Item != NULL; Item = Item->nextScalar) {
if (Item->output && Item->Var->oRecords > 0) {
struct VarStruct *Var = Item->Var;
if (Var->sRecordsType == NO_SPARSERECORDS &&
Var->sArraysType == NO_SPARSEARRAYS &&
Var->cType == NO_COMPRESSION) {
status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_,rVAR_), Var->varNo,
PUT_, BOO(Var->zVar,zItem,rItem), Var->oRecords,
NULL_);
DisplayStatus (status, "allocating output records");
if (StatusBAD(status)) return FALSE;
}
DisplayPctComplete (PCT(varNum,varCount,1,1), allocMsg[0]);
varNum++;
}
}
/****************************************************************************
* Allocate records for hyper variables being output. Also check that one
* or more records will be written to the variable.
****************************************************************************/
for (Item = hyperHead; Item != NULL; Item = Item->nextHyper) {
if (Item->output && Item->Var->oRecords > 0) {
struct VarStruct *Var = Item->Var;
if (Var->sRecordsType == NO_SPARSERECORDS &&
Var->sArraysType == NO_SPARSEARRAYS &&
Var->cType == NO_COMPRESSION) {
status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_,rVAR_), Var->varNo,
PUT_, BOO(Var->zVar,zItem,rItem), Var->oRecords,
NULL_);
DisplayStatus (status, "allocating output records");
if (StatusBAD(status)) return FALSE;
}
DisplayPctComplete (PCT(varNum,varCount,1,1), allocMsg[0]);
varNum++;
}
}
return TRUE;
}
/******************************************************************************
* ToWalk.
* Returns FALSE if a fatal error occurred.
******************************************************************************/
Logical ToWalk () {
CDFstatus status; struct ItemStruct *exportHead, *Item;
long numDims, dimSizes[CDF_MAX_DIMS], indices[CDF_MAX_DIMS], recordN = 0;
int varCount = 0, itemN = 0, varX, searchType; long maxRec = NO_RECORD;
static Logical first = TRUE; void *searchValue;
struct VarStruct *Vars[MAXwalkingVARs];
static int lineNs[1+CDF_MAX_DIMS+MAXwalkingVARs];
static int colS[1+CDF_MAX_DIMS+MAXwalkingVARs];
static int lenS[1+CDF_MAX_DIMS+MAXwalkingVARs];
AOSs15 (lineS, BLANKs78, BLANKs78, BLANKs78, BLANKs78, BLANKs78, BLANKs78,
BLANKs78, BLANKs78, BLANKs78, BLANKs78, BLANKs78, BLANKs78, BLANKs78,
BLANKs78, BLANKs78)
static int exitChars[] = {
EXITkey_FSI, INCREMENTkey_EDIT, DECREMENTkey_EDIT, HELPkey_FSI,
NEXTFIELDkey_EXPORT, PREVFIELDkey_EXPORT, SWITCHkey_EXPORT,
OPTIONSkey_EXPORT, ENTERkey_FSI, NUL
};
static struct ItemWindowStruct IW = {
0, 0, SCREEN_WIDTH, " Walking... ", 0, NULL, 0, lineS, 0, lineNs, colS,
lenS, 2 + MAXwalkingVARs, 0, NULL, exitChars, REFRESHkey_FSI, FALSE, NUL,
NUL
};
static char keyDefsBlank[] = "\n\n";
static char keyDefsAbort[] = "Abort: ________\n\n";
static char keyDefsRI[] = "Enter: ________ Next field: __________ Increment: _______ Help: ________\nVariables: _____ Prev field: __________ Decrement: _________ Exit: ________\n";
static char keyDefsVAR[] = "Search: ________ Next variable: ___________ Help: ________\nRecord/indices: _____ Prev variable: ___________ Exit: ________\n";
/***************************************************************************
* First time...
***************************************************************************/
if (first) {
char *p1 = keyDefsRI;
EncodeKeyDefinitions (1, &p1, ENTERkey_FSI, NEXTFIELDkey_EXPORT,
INCREMENTkey_EXPORT, HELPkey_FSI, SWITCHkey_EXPORT,
PREVFIELDkey_EXPORT, DECREMENTkey_EXPORT,
EXITkey_FSI);
p1 = keyDefsVAR;
EncodeKeyDefinitions (1, &p1, ENTERkey_FSI, DECREMENTkey_EXPORT,
HELPkey_FSI, SWITCHkey_EXPORT, INCREMENTkey_EXPORT,
EXITkey_FSI);
p1 = keyDefsAbort;
EncodeKeyDefinitions (1, &p1, ABORTkey_EXPORT);
first = FALSE;
}
/****************************************************************************
* Build export list. This should contain only variables being output.
****************************************************************************/
BuildExportList (&exportHead, LogicalTRUE);
/****************************************************************************
* Check that the dimensionalities are the same.
****************************************************************************/
if (!SameDimensionalities(&numDims,dimSizes,exportHead)) {
static char msg[] = {
"Walking allowed only if the variable dimensionalities are the same."
};
DisplayMessage (msg, BEEPWAIT2);
return TRUE;
}
/****************************************************************************
* Check if enough room for each variable.
****************************************************************************/
for (Item = exportHead; Item != NULL; Item = Item->nextExport) {
varCount++;
maxRec = MAXIMUM (maxRec, Item->Var->maxRec);
if (varCount == MAXwalkingVARs && Item->nextExport != NULL) {
Item->nextExport = NULL;
DisplayMessage ("Not enough room for all the variables.", NOBEEPWAIT1);
break;
}
}
/****************************************************************************
* Check if valid selections.
****************************************************************************/
if (varCount == 0) {
DisplayMessage ("No variables selected for walking.", BEEPWAIT2);
return TRUE;
}
if (maxRec == NO_RECORD) {
DisplayMessage ("No variable records exist.", BEEPWAIT2);
return TRUE;
}
/****************************************************************************
* Display a "loading" walking window.
****************************************************************************/
strcpyX (lineS[0], "Loading...", 0);
IW.NiLines = 1;
ItemWindow (NEWiw, &IW, 0);
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
/****************************************************************************
* Display variable values and "walk" until exit requested.
****************************************************************************/
IW.nItems = (int) (1 + numDims + varCount);
ARRAYtoVALUE (indices, 0, numDims)
IW.NiLines = varCount + 2;
for (;;) {
/*************************************************************************
* Update with variable values...
*************************************************************************/
status = BuildWalkScreen (exportHead, recordN, numDims, indices,
lineS, lineNs, colS, lenS, Vars);
if (StatusBAD(status)) {
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
DisplayStatus (status, readingCDF);
ItemWindow (DELETEiw, &IW);
return (!NoMoreAccess(NULL));
}
ItemWindow (UPDATEiw, &IW, itemN);
if (INCLUSIVE(0,IW.itemN,numDims)) {
NEWkeyDEFS (EWkey, keyDefsRI, batchMode)
}
else {
NEWkeyDEFS (EWkey, keyDefsVAR, batchMode)
}
/*************************************************************************
* ...and do as the user commands.
*************************************************************************/
ItemWindow (READiw, &IW);
switch (IW.key) {
/***********************************************************************
* Enter...
***********************************************************************/
case ENTERkey_FSI:
/*********************************************************************
* ...the record number.
*********************************************************************/
if (IW.itemN == 0) {
PromptForRecordNumber (&recordN, maxRec);
NEWkeyDEFS (EWkey, keyDefsRI, batchMode)
break;
}
/*********************************************************************
* ...a dimension index.
*********************************************************************/
if (INCLUSIVE(1,IW.itemN,numDims)) {
int dimN = IW.itemN - 1;
PromptForDimensionIndex (&indices[dimN], dimSizes[dimN]);
NEWkeyDEFS (EWkey, keyDefsRI, batchMode)
break;
}
/*********************************************************************
* ...a variable value.
*********************************************************************/
varX = (int) (IW.itemN - 1 - numDims);
if (PromptForVariableSearch(Vars[varX],&searchType,&searchValue)) {
double timeMark = SystemClock ();
DisplayMessage ("Searching...", NOWAIT);
NEWkeyDEFS (EWkey, keyDefsAbort, batchMode)
status = SearchForVariableValue (Vars[varX], numDims, dimSizes,
&recordN, indices, maxRec,
searchType, searchValue);
if (StatusBAD(status)) {
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
DisplayStatus (status, readingCDF);
cdf_FreeMemory (searchValue, FatalError);
ItemWindow (DELETEiw, &IW);
return (!NoMoreAccess(NULL));
}
cdf_FreeMemory (searchValue, FatalError);
for (;;) if (1.0 <= SystemClock() - timeMark) break;
DisplayMessage ("", NOWAIT);
}
NEWkeyDEFS (EWkey, keyDefsVAR, batchMode)
break;
/***********************************************************************
* Switch between record/indices and variables...
***********************************************************************/
case SWITCHkey_EXPORT:
itemN = BOO(INCLUSIVE(0,IW.itemN,numDims),(int)(numDims + 1),0);
break;
/***********************************************************************
* Next/previous field...
***********************************************************************/
case NEXTFIELDkey_EXPORT:
case PREVFIELDkey_EXPORT: {
if (INCLUSIVE(0,IW.itemN,numDims))
itemN = BOO(IW.key == NEXTFIELDkey_EXPORT,
BOO(IW.itemN < numDims,IW.itemN + 1,0),
BOO(IW.itemN > 0,IW.itemN - 1,(int)numDims));
else
ItemWindow (BEEPiw, &IW);
break;
}
/***********************************************************************
* Increment/decrement...
***********************************************************************/
case INCREMENTkey_EXPORT:
case DECREMENTkey_EXPORT: {
Logical increase = (IW.key == INCREMENTkey_EXPORT);
/*********************************************************************
* ...the record number.
*********************************************************************/
if (IW.itemN == 0) {
recordN = BOO(increase,
BOO(recordN == maxRec,0,recordN + 1),
BOO(recordN == 0,maxRec,recordN - 1));
break;
}
/*********************************************************************
* ...a dimension index.
*********************************************************************/
if (INCLUSIVE(1,IW.itemN,numDims)) {
int dimN = IW.itemN - 1;
indices[dimN] = BOO(increase,
BOO(indices[dimN] == dimSizes[dimN] - 1,
0,indices[dimN] + 1),
BOO(indices[dimN] == 0,
dimSizes[dimN] - 1,indices[dimN] - 1));
break;
}
/*********************************************************************
* ...to the next/previous variable.
*********************************************************************/
itemN = BOO(IW.key == DECREMENTkey_EXPORT,
BOO(IW.itemN < IW.nItems - 1,
IW.itemN + 1,(int)(1 + numDims)),
BOO(IW.itemN > 1 + numDims,
IW.itemN - 1,IW.nItems - 1));
break;
}
case OPTIONSkey_EXPORT:
OptionMenu ();
break;
case EXITkey_FSI:
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
ItemWindow (DELETEiw, &IW);
return TRUE;
case HELPkey_FSI:
OnlineHelpWindow ("cdfxp.ilh", BOO(INCLUSIVE(0,IW.itemN,numDims),
WALKriHelpID,WALKvarHelpID));
break;
}
}
}
/******************************************************************************
* BuildWalkScreen.
******************************************************************************/
static CDFstatus BuildWalkScreen (exportHead, recordN, numDims, indices,
lineS, lineNs, colS, lenS, Vars)
struct ItemStruct *exportHead;
long recordN;
long numDims;
long indices[];
char *lineS[];
int lineNs[];
int colS[];
int lenS[];
struct VarStruct *Vars[];
{
CDFstatus status, pStatus = CDF_OK; int dimN, lineN, itemN = 0, varX;
struct ItemStruct *Item; char *rightField;
/****************************************************************************
* Encode record/indices line.
****************************************************************************/
MakeNUL (lineS[0]);
CatToString (lineS[0], "Record/Indices.......", WALKleftLEN, LEFT_JUSTIFY,
dots);
strcatX (lineS[0], " ", 0);
colS[itemN] = strlen(lineS[0]);
sprintf (EofS(lineS[0]), "%ld", (long) (recordN + 1));
lenS[itemN] = strlen(&(lineS[0][colS[itemN]]));
lineNs[itemN++] = 0;
strcatX (lineS[0], ":[", 0);
for (dimN = 0; dimN < numDims; dimN++) {
if (dimN > 0) strcatX (lineS[0], ",", 0);
colS[itemN] = strlen(lineS[0]);
sprintf (EofS(lineS[0]), "%ld", (long) (indices[dimN] + 1));
lenS[itemN] = strlen(&(lineS[0][colS[itemN]]));
lineNs[itemN++] = 0;
}
strcatX (lineS[0], "]", 0);
/****************************************************************************
* A blank line is next.
****************************************************************************/
MakeNUL (lineS[1]);
/****************************************************************************
* Encode the variable lines.
****************************************************************************/
for (Item = exportHead, lineN = 2, varX = 0;
Item != NULL; Item = Item->nextExport, lineN++, varX++) {
EncodeString ((long) strlen(Item->Var->name), Item->Var->name,
lineS[lineN], -WALKleftLEN, WALKleftLEN);
strcatX (lineS[lineN], " ", 0);
status = CDFlib (SELECT_, VAR(Item->Var->zVar), Item->Var->varN,
BOO(Item->Var->zVar,zVAR_RECNUMBER_,
rVARs_RECNUMBER_), recordN,
BOO(Item->Var->zVar,zVAR_DIMINDICES_,
rVARs_DIMINDICES_), indices,
GET_, VAR_DATA(Item->Var->zVar), Item->Var->value,
NULL_);
if (!sX(status,&pStatus)) return pStatus;
colS[itemN] = strlen(lineS[lineN]);
rightField = EofS(lineS[lineN]);
EncodeValuesFormat (Item->Var->dataType, Item->Var->numElems,
Item->Var->value, rightField, Item->Var->format, 0,
WALKrightLEN, opt.epochStyle);
RemoveLeadingBlanks (rightField);
lenS[itemN] = strlen(rightField);
lineNs[itemN++] = lineN;
Vars[varX] = Item->Var;
}
return pStatus;
}
/******************************************************************************
* PromptForRecordNumber.
******************************************************************************/
static Logical PromptForRecordNumber (recordN, maxRec)
long *recordN;
long maxRec;
{
static char value[MAXrecordNumberLEN+1]; long newRecordN;
sprintf (value, "%ld", (long) (*recordN + 1));
if (!PromptFor(value,MAXrecordNumberLEN,strlen(value),
"Enter the record number...",RECORDhelpID)) return FALSE;
if (NULstring(value)) return FALSE;
if (sscanf(value,"%ld",&newRecordN) != 1) {
DisplayMessage ("Error decoding record number.", BEEPWAIT1);
return FALSE;
}
if (!INCLUSIVE(1,newRecordN,maxRec+1)) {
DisplayMessage ("Record number out of range.", BEEPWAIT1);
return FALSE;
}
*recordN = newRecordN - 1L;
return TRUE;
}
/******************************************************************************
* PromptForDimensionIndex.
******************************************************************************/
static Logical PromptForDimensionIndex (index, dimSize)
long *index;
long dimSize;
{
static char value[MAXdimensionIndexLEN+1]; long newIndex;
sprintf (value, "%ld", (long) (*index + 1));
if (!PromptFor(value,MAXdimensionIndexLEN,strlen(value),
"Enter the dimension index...",INDEXhelpID)) return FALSE;
if (NULstring(value)) return FALSE;
if (sscanf(value,"%ld",&newIndex) != 1) {
DisplayMessage ("Error decoding dimension index.", BEEPWAIT1);
return FALSE;
}
if (!INCLUSIVE(1,newIndex,dimSize)) {
DisplayMessage ("Dimension index out of range.", BEEPWAIT1);
return FALSE;
}
*index = newIndex - 1L;
return TRUE;
}
/******************************************************************************
* PromptForVariableSearch.
******************************************************************************/
static Logical PromptForVariableSearch (Var, searchType, searchValue)
struct VarStruct *Var;
int *searchType;
void **searchValue;
{
static char value[MAXvalueLEN+1]; long numElems; int iniChar;
static Logical first = TRUE; Logical done = FALSE;
static int exitChars[] = { ENTERkey_FSI, EXITkey_FSI, HELPkey_FSI, NUL };
AOSs1 (iLines, "EQUAL LESS LESS/EQUAL GREATER GREATER/EQUAL")
static int iLineNs[] = { 0,0,0,0,0 };
static int iCols[] = { 0,8,15,28,38 };
static int iLens[] = { 5,4,10,7,13 };
static struct ItemWindowStruct IW = {
21, 0, 80, " Select search type... ", 0, NULL, 1, iLines, 5, iLineNs,
iCols, iLens, 1, 0, NULL, exitChars, REFRESHkey_FSI, FALSE, NUL, NUL
};
static char keyDefs[] = {
"Enter: ________ Help: ________ Exit: ________\n\n"
};
static char keyDefsBlank[] = "";
/****************************************************************************
* First time...
****************************************************************************/
if (first) {
char *p1 = keyDefs;
EncodeKeyDefinitions (1, &p1, ENTERkey_FSI, HELPkey_FSI, EXITkey_FSI);
first = FALSE;
}
/****************************************************************************
* Prompt for type of search.
****************************************************************************/
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
ItemWindow (NEWiw, &IW, 0);
NEWkeyDEFS (EWkey, keyDefs, batchMode)
while (!done) {
ItemWindow (READiw, &IW);
switch (IW.key) {
case ENTERkey_FSI:
switch (IW.itemN) {
case 0: *searchType = EQsearch; break;
case 1: *searchType = LTsearch; break;
case 2: *searchType = LEsearch; break;
case 3: *searchType = GTsearch; break;
case 4: *searchType = GEsearch; break;
}
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
ItemWindow (DELETEiw, &IW);
done = TRUE;
break;
case HELPkey_FSI:
OnlineHelpWindow ("cdfxp.ilh", SEARCHTYPEhelpID);
break;
case EXITkey_FSI:
NEWkeyDEFS (EWkey, keyDefsBlank, batchMode)
ItemWindow (DELETEiw, &IW);
return FALSE;
}
}
/****************************************************************************
* Prompt for value.
****************************************************************************/
EncodeValuesFormat (Var->dataType, Var->numElems, Var->value, value,
Var->format, 0, MAXvalueLEN, opt.epochStyle);
RemoveLeadingBlanks (value);
iniChar = strlen(value) - BOO(STRINGdataType(Var->dataType),1,0);
if (!PromptFor(value,MAXvalueLEN,iniChar,
"Enter the search value...",VALUEhelpID)) return FALSE;
if (NULstring(value)) return FALSE;
if (!DecodeValues(value,Var->dataType,&numElems,
searchValue,opt.epochStyle)) {
DisplayMessage ("Error decoding value.", BEEPWAIT1);
return FALSE;
}
if (numElems != Var->numElems) {
DisplayMessage ("Wrong number of elements.", BEEPWAIT1);
cdf_FreeMemory (*searchValue, FatalError);
return FALSE;
}
return TRUE;
}
/******************************************************************************
* SearchForVariableValue.
******************************************************************************/
static CDFstatus SearchForVariableValue (Var, numDims, dimSizes, recordAt,
indicesAt, maxRec, searchType,
searchValue)
struct VarStruct *Var;
long numDims;
long dimSizes[];
long *recordAt;
long indicesAt[];
long maxRec;
int searchType;
void *searchValue;
{
CDFstatus status, pStatus = CDF_OK;
long recordN, indices[CDF_MAX_DIMS], indicesFirst[CDF_MAX_DIMS], pct;
long indicesLast[CDF_MAX_DIMS], nValuesPerRecord, dimCounts[CDF_MAX_DIMS];
long nValues, valueN, nDimValues[CDF_MAX_DIMS], valueOffset, lastPct = -1L;
size_t nBytes; void *value; int dimN;
Logical outRowMajor = ROWmajor(MAJORITYtoOUT(opt.majority,inMajority));
static Logical (*entryPoints[])PROTOARGs((void *, void *, long, long)) = {
EQx, LTx, LEx, GTx, GEx
};
/****************************************************************************
* Initialize...
****************************************************************************/
recordN = BOO(Var->recVary,*recordAt,maxRec);
for (dimN = 0; dimN < numDims; dimN++) {
indices[dimN] = BOO(Var->dimVarys[dimN],indicesAt[dimN],0);
indicesFirst[dimN] = 0;
indicesLast[dimN] = BOO(Var->dimVarys[dimN],dimSizes[dimN] - 1,0);
dimCounts[dimN] = indicesLast[dimN] - indicesFirst[dimN] + 1;
}
/****************************************************************************
* Calculate the number of values from the current record/indices to the end
* of the variable's values.
****************************************************************************/
for (nValuesPerRecord = 1, dimN = 0; dimN < numDims; dimN++) {
nValuesPerRecord *= dimCounts[dimN];
}
if (numDims > 0) {
if (outRowMajor) {
nDimValues[(int)(numDims-1)] = 1;
for (dimN = (int) (numDims - 2); dimN >= 0; dimN--) {
nDimValues[dimN] = dimCounts[dimN+1] * nDimValues[dimN+1];
}
}
else {
nDimValues[0] = 1;
for (dimN = 1; dimN < numDims; dimN++) {
nDimValues[dimN] = dimCounts[dimN-1] * nDimValues[dimN-1];
}
}
}
for (valueOffset = 0, dimN = 0; dimN < numDims; dimN++) {
valueOffset += (indices[dimN] * nDimValues[dimN]);
}
nValues = nValuesPerRecord - valueOffset;
nValues += (nValuesPerRecord * (maxRec - recordN));
/****************************************************************************
* Increment past the current record/indices. Return if there is only one
* value to search.
****************************************************************************/
if (nValues > 1) {
IncrRecordIndicesFirstLast (outRowMajor, &recordN, numDims,
indicesFirst, indicesLast, indices);
nValues--;
}
else
return pStatus;
/****************************************************************************
* Select the variable.
****************************************************************************/
status = CDFlib (SELECT_, VAR(Var->zVar), Var->varN,
NULL_);
if (!sX(status,&pStatus)) return pStatus;
/****************************************************************************
* Allocate memory to hold the value.
****************************************************************************/
nBytes = (size_t) (Var->numElems * CDFelemSize(Var->dataType));
value = (void *) cdf_AllocateMemory (nBytes, FatalError);
/****************************************************************************
* For each value to be searched...
****************************************************************************/
for (valueN = 0; valueN < nValues; valueN++) {
/*************************************************************************
* Read the value.
*************************************************************************/
status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_RECNUMBER_,
rVARs_RECNUMBER_), recordN,
NULL_);
if (!sX(status,&pStatus)) {
cdf_FreeMemory (value, FatalError);
return pStatus;
}
if (numDims > 0) {
status = CDFlib (SELECT_, BOO(Var->zVar,zVAR_DIMINDICES_,
rVARs_DIMINDICES_), indices,
NULL_);
if (!sX(status,&pStatus)) {
cdf_FreeMemory (value, FatalError);
return pStatus;
}
}
status = CDFlib (GET_, VAR_DATA(Var->zVar), value,
NULL_);
if (!sX(status,&pStatus)) {
cdf_FreeMemory (value, FatalError);
return pStatus;
}
/*************************************************************************
* If equal, set the record/indices and return.
*************************************************************************/
if ((entryPoints[searchType])(value,searchValue,
Var->dataType,Var->numElems)) {
if (Var->recVary) *recordAt = recordN;
for (dimN = 0; dimN < numDims; dimN++) {
if (Var->dimVarys[dimN]) indicesAt[dimN] = indices[dimN];
}
cdf_FreeMemory (value, FatalError);
return pStatus;
}
/*************************************************************************
* Update percentage complete.
*************************************************************************/
pct = (100L * valueN) / nValues;
if (pct > lastPct) {
static char msg[] = "Searching... ";
sprintf (&msg[75], "%2ld%%", pct);
DisplayMessage (msg, NOWAIT);
lastPct = pct;
}
/*************************************************************************
* Check if search should be aborted.
*************************************************************************/
if (AbortSearch()) {
cdf_FreeMemory (value, FatalError);
return pStatus;
}
/*************************************************************************
* Increment to the next record/indices based on the majority selected.
*************************************************************************/
IncrRecordIndicesFirstLast (outRowMajor, &recordN, numDims,
indicesFirst, indicesLast, indices);
}
/****************************************************************************
* The value was not found...
****************************************************************************/
DisplayMessage ("Matching value not found.", BEEPWAIT1);
cdf_FreeMemory (value, FatalError);
return pStatus;
}
/******************************************************************************
* AbortSearch.
******************************************************************************/
static Logical AbortSearch () {
int key;
if (read_input(
#if defined(CURSESui)
EWmsg->wid,
#endif
&key,PASSTHRUri,FALSE)) {
if (key == ABORTkey_EXPORT) {
DisplayMessage ("Aborting at user's request.", NOBEEPWAIT1);
return TRUE;
}
else
EditWindow (BEEPew, EWmsg);
}
return FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1