/*ScianErrors.c
  Eric Pepke
  March 26, 1990
  Error routines for scian
*/

#include "Scian.h"
#include "ScianTypes.h"
#include "ScianNames.h"
#include "ScianIDs.h"
#include "ScianWindows.h"
#include "ScianErrors.h"
#include "ScianDialogs.h"
#include "ScianTimers.h"
#include "ScianArrays.h"
#include "ScianColors.h"
#include "ScianStyle.h"

extern ObjPtr timedObjClass;		/*Timed variable, just in case*/

char *IDName(id)
NameTyp id;
/*Returns the internal string of id, or a code giving its number*/
{
    static char emergencyName[40];
    char *retVal;

    retVal = GetInternalString(id);
    if (retVal)
    {
	return retVal;
    }
    else
    {
	sprintf(emergencyName, "ID %d", id);
	return emergencyName;
    }
}

void OMErr()
/*Out of memory error*/
{
    ReportError("SciAn", "Out of memory!");
}

#ifdef PROTO
void Error(char *whichFunction, int whichError, ...)
#else
void Error(whichFunction, whichError)
char *whichFunction;
int whichError;
#endif
/*Announces error whichError determined in function whichFunction.
  Additional information may follow whichError*/
{
    NameTyp *extraVars;
    ObjPtr *extraObjects;
    ObjPtr name;

    extraVars = (NameTyp *) (&whichError + 1);

    switch(whichError)
    {
	case VARNOTFOUND:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s was not found in object %s",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s was not found", IDName(*extraVars));
	    }
	    break;
	case METHODNOTFOUND:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Method %s was not found in object %s",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Method %s was not found in object %lx", IDName(*extraVars), *extraObjects);
	    }
	    break;
	case VARNOTOBJECT:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not an object",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not an object", IDName(*extraVars));
	    }
	    break;
	case VARNOTARRAY:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not an array",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not an array", IDName(*extraVars));
	    }
	    break;
	case VARNOTMATRIX:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a matrix",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a matrix", IDName(*extraVars));
	    }
	    break;
	case VARNOTPICTURE:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a picture",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a picture", IDName(*extraVars));
	    }
	    break;
	case VARNOTWINDOW:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a window",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a window", IDName(*extraVars));
	    }
	    break;
	case VARNOTINT:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not an integer",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not an integer", IDName(*extraVars));
	    }
	    break;
	case VARNOTSYMBOL:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a symbol",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a symbol", IDName(*extraVars));
	    }
	    break;
	case VARNOTSTRING:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a string",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a string", IDName(*extraVars));
	    }
	    break;
	case VARNOTREAL:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a real number",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a real number", IDName(*extraVars));
	    }
	    break;
	case VARNOTPALETTE:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a palette",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a palette", IDName(*extraVars));
	    }
	    break;
	case VARNOTLIST:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Variable %s in object %s is not a list",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Variable %s is not a list", IDName(*extraVars));
	    }
	    break;
	case VARBADRANK:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "The rank of variable %s in object %s is wrong",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "The rank of variable %s is wrong", IDName(*extraVars));
	    }
	    break;
	case VARBADDIM:
	    extraObjects = (ObjPtr *) extraVars;
	    extraVars = (NameTyp *) (extraObjects + 1);
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "The dimensions of variable %s in object %s are wrong",
			IDName(*extraVars), GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "The dimensions of variable %s are wrong", IDName(*extraVars));
	    }
	    break;
	case NOCORRAL:
	    /*There is no corral in a window*/
	    extraObjects = (ObjPtr *) extraVars;
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "There is no corral in window %s", GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "There is no corral in the window");
	    }
	    break;
	case NOPANEL:
	    /*There is no panel in a window*/
	    extraObjects = (ObjPtr *) extraVars;
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "There is no panel in window %s", GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "There is no panel in the window");
	    }
	    break;
	case NOPARENT:
	    /*There is no parent for an object*/
	    extraObjects = (ObjPtr *) extraVars;
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Object %s has no parent", GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "An object has no parent");
	    }
	    break;
	case CREATEFILEERROR:
	    /*Error creating a file*/
	    sprintf(tempStr, "Failed to create or open file %s for writing",
		    *(char **) extraVars);
	    break;
	case OPENFILEERROR:
	    /*Error creating a file*/
	    sprintf(tempStr, "File %s does not exist or could not be opened",
		    *(char **) extraVars);
	    break;
	case NOCANVIS:
	    extraObjects = (ObjPtr *) extraVars;
	    name = GetVar(*extraObjects, NAME);
	    if (name && IsString(name))
	    {
		sprintf(tempStr, "Cannot visualize dataset object %s",
			GetString(name));
	    }
	    else
	    {
		sprintf(tempStr, "Cannot visualize a dataset object");
	    }
	    break;
	case ARRAYEXP:
	    sprintf(tempStr, "An array was expected but was not found");
	    break;
	case PALNOTSAMESIZE:
	    sprintf(tempStr, "The two palettes are not the same size");
	    break;
	default:
	    sprintf(tempStr, "Unrecognized error %d", whichError);
	    break;
    }
	ReportError(whichFunction, tempStr);
}

ObjPtr GetObjectVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is an object, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;
    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsObject(retVal))
    {
	Error(whichFunction, VARNOTOBJECT, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetListVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a list, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;
    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsList(retVal))
    {
	Error(whichFunction, VARNOTLIST, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetTimedVar(object, var)
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a timed var, selects the current*/
{
    ObjPtr retVal;
    MakeVar(object, var);
    retVal = GetVar(object, var);
    return retVal;
}

ObjPtr GetPictureVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a picture, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;
    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetTimedVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsPicture(retVal))
    {
	Error(whichFunction, VARNOTPICTURE, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetWindowVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a window, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;
    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsWindow(retVal))
    {
	Error(whichFunction, VARNOTWINDOW, object, var);
	return NULLOBJ;
    }
    return retVal;
}


ObjPtr GetArrayVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is an array, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetTimedVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsRealArray(retVal))
    {
	Error(whichFunction, VARNOTARRAY, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetMatrixVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a matrix, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsMatrix(retVal))
    {
	Error(whichFunction, VARNOTMATRIX, object, var);
	return NULLOBJ;
    }
    return retVal;
}

FuncTyp GetMethodSurely(whichFunction, object, method)
char *whichFunction;
ObjPtr object;
NameTyp method;
/*Gets method from object.  If it is there, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way

  And don't call me surely.
*/
{
    FuncTyp retVal;

    if (!object)
    {
	return 0;
    }
    retVal = GetMethod(object, method);
    if (!retVal)
    {
	Error(whichFunction, METHODNOTFOUND, object, method);
	return 0;
    }
    return retVal;
}

ObjPtr GetIntVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is an int, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsInt(retVal))
    {
	Error(whichFunction, VARNOTINT, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetSymbolVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a symbol, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsSymbol(retVal))
    {
	Error(whichFunction, VARNOTSYMBOL, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetStringVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a string, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsString(retVal))
    {
	Error(whichFunction, VARNOTSTRING, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetRealVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a real, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsReal(retVal))
    {
	Error(whichFunction, VARNOTREAL, object, var);
	return NULLOBJ;
    }
    return retVal;
}

ObjPtr GetPaletteVar(whichFunction, object, var)
char *whichFunction;
ObjPtr object;
NameTyp var;
/*Gets var from object.  If it is a palette, returns it.  If not, prints
  error as if from function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsPalette(retVal))
    {
	Error(whichFunction, VARNOTPALETTE, object, var);
	return NULLOBJ;
    }
    return retVal;
}

#ifdef PROTO
ObjPtr GetFixedArrayVar(char *whichFunction, ObjPtr object, 
	NameTyp var, int rank, ...) 
#else
ObjPtr GetFixedArrayVar(whichFunction, object, var, rank)
char *whichFunction;
ObjPtr object;
NameTyp var;
int rank;
#endif
/*Gets var from object.  If it is an array and conforms to rank and
  the following dimensions, returns it.  If not, prints error as if from 
  function whichFunction.  If object is 0, returns 0, so this
  can be used in a dataflow sort of way*/
{
    ObjPtr retVal;
    long *dims;
    int k;

    dims = (long *)(&rank + 1);

    if (!object)
    {
	return NULLOBJ;
    }
    retVal = GetTimedVar(object, var);
    if (!retVal)
    {
	Error(whichFunction, VARNOTFOUND, object, var);
	return NULLOBJ;
    }
    if (!IsRealArray(retVal))
    {
	Error(whichFunction, VARNOTARRAY, object, var);
	return NULLOBJ;
    }
    if (rank != RANK(retVal))
    {
	Error(whichFunction, VARBADRANK, object, var);
	return NULLOBJ;
    }
    for (k = 0; k < rank; ++k)
    {
	if (*dims != DIMS(retVal)[k])
	{
	    Error(whichFunction, VARBADDIM, object, var);
	    return NULLOBJ;
	}
	++dims;
    }
    return retVal;
}

Bool GetPredicate(object, var)
ObjPtr object;
NameTyp var;
/*Checks predicate var in object*/
{
    ObjPtr value;
    value = GetVar(object, var);
    if (value && IsInt(value) && GetInt(value))
    {
	return true;
    }
    else
    {
	return false;
    }
}

Bool IntVarEql(object, var, value)
ObjPtr object;
NameTyp var;
int value;
/*Returns true iff object has an integer variable var which has value value,
  false otherwise*/
{
    ObjPtr varval;
    if (!object)
    {
	return false;
    }
    varval = GetVar(object, var);
    if (varval && IsInt(varval))
    {
	return GetInt(varval) == value ? true : false;
    }
    else
    {
	return false;
    }
}

void DoNumberError()
/*Whines at the user about a numeric error*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "There is a syntax error in the number.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("There is a syntax error in the number you have just entered.  \
Please enter the number once more."));
}

void DoRangeError()
/*Whines at the user about a range error*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The maximum value must be greater than the minimum.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered would cause the maximum value \
to be less than the minimum.  \
Please enter the number once more."));
}

void DoWrongNColorsError()
/*Whines at the user about the wrong number of colors*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The number of colors must be between 5 and 2048.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered is an invalid number of colors \
for a color table.  \
Please enter a number between 5 and 2048."));
}

void DoLE0Error()
/*Whines at the user about a number that must be greater than zero*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The number entered must be greater than zero.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered is less than or equal to zero, which will not \
work here.  \
Please enter the number once more."));
}

void DoLT0Error()
/*Whines at the user about a number that must be greater than or equal to zero*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The number entered may not be negative.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered is less than zero, which will not \
work here.  \
Please enter the number once more."));
}

void DoNonIntError()
/*Whines at the user about a number that must be integral*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The number entered must be an integer.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered is a real number, which will not \
work here.  \
Please enter the number once more."));
}

void DoInfinityError()
/*Whines at the user about a number that must not be infinite*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The number entered may not be infinite.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered is an infinite number, which will not \
work here.  \
Please enter the number once more."));
}

void DoMissingError()
/*Whines at the user about a number that must not be infinite*/
{
    WinInfoPtr errWindow;
    errWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "The number entered may not be missing.", 0, 0, "");
    SetVar((ObjPtr) errWindow, HELPSTRING,
	NewString("The number you have just entered is a missing value, which will not \
work here.  \
Please enter the number once more."));
}
