/*****************************************************************************
*   Main module of "Irit" - the 3d (not only polygonal) solid modeller.      *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                *
******************************************************************************
* Usage:								     *
*   Irit [-t] [-z]							     *
*									     *
* Written by:  Gershon Elber				Ver 3.0, Apr. 1990   *
*****************************************************************************/

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include "program.h"
#include "config.h"
#include "ctrl-brk.h"
#include "dosintr.h"
#include "inptprsg.h"
#include "iritprsr.h"
#include "irit_soc.h"
#include "objects.h"
#include "primitiv.h"
#include "iritgrap.h"
#include "bool_lib.h"
#include "trim_lib.h"
#include "triv_lib.h"
#include "symb_lib.h"
#ifdef __WINNT__
#include <direct.h>
#endif /* __WINNT__ */
#ifdef DJGCC
#include "intr_lib.h"
#include "intr_gr.h"
#endif /* DJGCC */

#ifdef NO_CONCAT_STR
static char
    *VersionStr = "Irit		Version 7.0, Gershon Elber,\n\
	(C) Copyright 1989/90-97 Gershon Elber, Non commercial use only.";
#else
static char
    *VersionStr = "Irit	        " IRIT_VERSION
	",	Gershon Elber,	" __DATE__ ",   " __TIME__ "\n"
	IRIT_COPYRIGHT ", Non commercial use only.";
#endif /* NO_CONCAT_STR */

static char
     *CtrlStr = "Irit [-t] [-z] [file.irt]";

char *GlblHelpFileName = "irit.hlp";

static char
    *GlblPrgmHeader = "                Irit - the not only polygonal solid modeller";
static char
    *GlblCopyRight  =
#ifdef DJGCC
     IRIT_COPYRIGHT ",  DJGCC " IRIT_VERSION ",   " __DATE__;
#else
#ifdef OS2GCC
     IRIT_COPYRIGHT ",  OS2   " IRIT_VERSION ",   " __DATE__;
#else
#ifdef AMIGA
     IRIT_COPYRIGHT ", Amiga  " IRIT_VERSION ",   " __DATE__;
#else
#ifdef __WINNT__
     IRIT_COPYRIGHT ", Win NT/95 " IRIT_VERSION ",   " __DATE__;
#else
#ifdef NO_CONCAT_STR
     "(C) Copyright 1989/90-97 Gershon Elber,  Unix  Version 7.0";
#else
     IRIT_COPYRIGHT ",  Unix  " IRIT_VERSION;
#endif /* NO_CONCAT_STR */
#endif /* __WINNT__ */
#endif /* AMIGA */
#endif /* OS2GCC */
#endif /* DJGCC */
static char
    *GlblAuthorName = "                         Written by Gershon Elber";

static int
    GlblIritMallocDebugPrint = FALSE;

IPObjectStruct
    *GlblObjList = NULL;		   /* All objects defined on system. */

char GlblCrntWorkingDir[LINE_LEN];     /* Save start CWD to recover on exit. */

FILE
    *GlblLogFile = NULL;

jmp_buf GlblLongJumpBuffer;		          /* Used in error recovery. */

int
#ifdef DJGCC					   /* Defaults for intr_lib. */
    GlblWindowFrameWidth = 8,
    GlblViewFrameColor   = INTR_COLOR_RED,
    GlblViewBackColor    = INTR_COLOR_BLACK,
    GlblTransFrameColor  = INTR_COLOR_GREEN,
    GlblTransBackColor   = INTR_COLOR_BLACK,
    GlblStatusFrameColor = INTR_COLOR_MAGENTA,
    GlblStatusBackColor  = INTR_COLOR_BLACK,
    GlblInputFrameColor  = INTR_COLOR_YELLOW,
    GlblInputBackColor   = INTR_COLOR_BLACK,
    GlblDrawHeader       = FALSE,
    GlblSmoothTextScroll = TRUE,
    GlblIntrSaveMethod   = INTR_SAVE_DISK,
    GlblMouseSensitivity = 10,       /* Sensitivity control of mouse device. */
    GlblJoystickExists   = FALSE,
#endif /* DJGCC */
    GlblDisplayDeviceInput = -1,
    GlblDisplayDeviceOutput = -1,
    GlblInterpProd	 = TRUE,
    GlblLoadColor        = DEFAULT_LOAD_COLOR,
    GlblPrimColor        = DEFAULT_PRIM_COLOR,
    GlblDoGraphics       = TRUE,/* Control if running in graphics/text mode. */
    GlblFatalError       = FALSE, /* True if disaster in system - must quit! */
    GlblPrintLogFile     = FALSE,    /* If TRUE everything goes to log file. */
    GlblPointLenAux      = IG_POINT_DEFAULT_LENGTH;

RealType
    GlblPointLen = 0.02;		       /* Scaler for point if drawn. */

char
#ifdef DJGCC					   /* Defaults for intr_lib. */
    *GlblViewWndwPos   = "0.02, 0.02, 0.72, 0.66",
    *GlblTransWndwPos  = "0.75, 0.02, 0.98, 0.66",
    *GlblStatusWndwPos = "0.75, 0.02, 0.98, 0.66",
    *GlblInputWndwPos  = "0.04, 0.7,  0.98, 0.98",
    *GlblIntrSaveDisk  = "c:\\",
#endif /* DJGCC */
    *GlblStartFileName = "",
    *GlblLogFileName = "",
#ifdef IRIT_DOUBLE
    *GlblFloatFormat = "%-8.6lg";
#else
    *GlblFloatFormat = "%-8.6g";
#endif /* IRIT_DOUBLE */

static ConfigStruct SetUp[] =
{
#ifdef DJGCC
  { "Joystick",		"",   (VoidPtr) &GlblJoystickExists, SU_BOOLEAN_TYPE },
  { "MouseSensitivity",	"",   (VoidPtr) &GlblMouseSensitivity,SU_INTEGER_TYPE },
  { "WndwWidth",	"",   (VoidPtr) &GlblWindowFrameWidth,SU_INTEGER_TYPE },
  { "WndwHeader",	"",   (VoidPtr) &GlblDrawHeader,     SU_BOOLEAN_TYPE },
  { "WndwSmthTxtScrl",	"",   (VoidPtr) &GlblSmoothTextScroll,SU_BOOLEAN_TYPE },
  { "WndwViewClr",	"",   (VoidPtr) &GlblViewFrameColor, SU_INTEGER_TYPE },
  { "WndwTransClr",	"",   (VoidPtr) &GlblTransFrameColor,SU_INTEGER_TYPE },
  { "WndwInputClr",	"",   (VoidPtr) &GlblInputFrameColor,SU_INTEGER_TYPE },
  { "WndwViewPos",	"",   (VoidPtr) &GlblViewWndwPos,    SU_STRING_TYPE },
  { "WndwTransPos",	"",   (VoidPtr) &GlblStatusWndwPos,  SU_STRING_TYPE },
  { "WndwInputPos",	"",   (VoidPtr) &GlblInputWndwPos,   SU_STRING_TYPE },
  { "WndwBackSave",	"",   (VoidPtr) &GlblIntrSaveMethod, SU_INTEGER_TYPE },
  { "WndwBackSavePath",	"",   (VoidPtr) &GlblIntrSaveDisk,   SU_STRING_TYPE },
#endif /* DJGCC */
  { "DoGraphics",	"-t", (VoidPtr) &GlblDoGraphics,     SU_BOOLEAN_TYPE },
  { "InterpProd",	"",   (VoidPtr) &GlblInterpProd,     SU_BOOLEAN_TYPE },
  { "PointLength",	"",   (VoidPtr) &GlblPointLenAux,    SU_INTEGER_TYPE },
  { "LoadColor",	"",   (VoidPtr) &GlblLoadColor,	     SU_INTEGER_TYPE },
  { "PrimColor",	"",   (VoidPtr) &GlblPrimColor,	     SU_INTEGER_TYPE },
  { "StartFile",	"",   (VoidPtr) &GlblStartFileName,  SU_STRING_TYPE },
  { "LogFile",		"",   (VoidPtr) &GlblLogFileName,    SU_STRING_TYPE },
  { "FloatFrmt",	"",   (VoidPtr) &GlblFloatFormat,    SU_STRING_TYPE },
};
#define NUM_SET_UP	(sizeof(SetUp) / sizeof(ConfigStruct))

static void Interact(void);
static void ValidateVariables(void);
static void PrintInptPrsrError(void);

/*****************************************************************************
* DESCRIPTION:                                                               M
* Main module of IRIT - Read command line and do what is needed...	     M
*                                                                            *
* PARAMETERS:                                                                M
*   argc, argv:  Command line.                                               M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   main                                                                     M
*****************************************************************************/
void main(int argc, char **argv)
{
    char *FullPathStartFileName;

    IritCPUTime(TRUE);					 /* Reset the clock. */

    Config("irit", SetUp, NUM_SET_UP);       /* Read config. file if exists. */

    while (argc >= 2) {
    	if (strncmp(argv[1], "-z", 2) == 0) {
	    fprintf(stderr, "\n%s\n\nUsage: %s\n", VersionStr, CtrlStr);
	    ConfigPrint(SetUp, NUM_SET_UP);
	    exit(0);
    	}
	else if (strncmp(argv[1], "-t", 2) == 0) {
	    GlblDoGraphics = FALSE;
	}
	else {
	    break;
	}
    	argv++;
	argc--;
    }

    getcwd(GlblCrntWorkingDir, LINE_LEN - 1);

    SetUpCtrlBrk();	     /* Set up control break trap routine (int 1bh). */
    signal(SIGFPE, DefaultFPEHandler);	 /* Will trap floating point errors. */

    BspMultInterpFlag(GlblInterpProd);
    IritPrsrSetFloatFormat(GlblFloatFormat);
    IritPrsrSetFlattenObjects(FALSE);
    IritPrsrSetPolyListCirc(TRUE);

    /* Print some copyright messages: */
    WndwInputWindowPutStr(GlblPrgmHeader);
    WndwInputWindowPutStr(GlblCopyRight);
    WndwInputWindowPutStr(GlblAuthorName);

    SetUpPredefObjects();		  /* Prepare the predefined objects. */

    /* Execute the file specified in the command line if was one: */
    if (argc == 2)
	FileInclude(argv[1]);

    /* Execute the start up file first by inserting it to the include stack. */
    if ((int) strlen(GlblStartFileName) > 0 &&
	(FullPathStartFileName = searchpath(GlblStartFileName)) != NULL)
	FileInclude(FullPathStartFileName);

    Interact();				      /* Go and do some real work... */

    IritExit(0);
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Interact - the main read/eval/print routine. This routine reads data from  *
* standart input and execute it "forever" (using Input Parser).		     *
*   Note exit from this program is controled by input parser itself.	     *
*                                                                            *
* PARAMETERS:                                                                *
*   None                                                                     *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*****************************************************************************/
static void Interact(void)
{
    /* setjmp return 0 on first install time. Will return 1 if error is      */
    /* recoverable, 2 if cannt continue - must quit the program now.	     */
    switch (setjmp(GlblLongJumpBuffer)) {         /* Used in error recovery. */
	case 1:
	    ValidateVariables();
	case 0:
	    while (TRUE) {
		if (!InputParser())		 /* Print the error message. */
		    PrintInptPrsrError();
		ValidateVariables();
		if (GlblIritMallocDebugPrint) {
		    GlblIritMallocDebugPrint = FALSE;
		    IritDebugMallocAllocated();
		}
	    }
	case 2:
	    WndwInputWindowPutStr("Press return to die...");
	    getchar();
	    break;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               *
*   Validates all the variables in the global list, scream and remove        *
* undefined variables.                                                       *
*                                                                            *
* PARAMETERS:                                                                *
*   None                                                                     *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*****************************************************************************/
static void ValidateVariables(void)
{
    IPObjectStruct *PObj, *PTmp;
    char Line[LINE_LEN];

    while (GlblObjList != NULL && IP_IS_UNDEF_OBJ(GlblObjList)) {
	sprintf(Line,
		"Error: undefined object \"%s\" has been removed from global data base\n",
		GlblObjList -> Name);
	WndwInputWindowPutStr(Line);

	PObj = GlblObjList -> Pnext;
	IPFreeObject(GlblObjList);
	GlblObjList = PObj;
    }

    if (GlblObjList) {
	for (PObj = GlblObjList; PObj -> Pnext != NULL; PObj = PObj -> Pnext) {
	    if (IP_IS_UNDEF_OBJ(PObj -> Pnext)) {
		sprintf(Line,
			"Error: undefined object \"%s\" has been removed from global data base\n",
			PObj -> Pnext -> Name);
		WndwInputWindowPutStr(Line);

		PTmp = PObj -> Pnext -> Pnext;
		IPFreeObject(PObj -> Pnext);
		PObj -> Pnext = PTmp;
	    }
	}
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Modifies the state of the IRIT solid modeller.			     M
*                                                                            *
* PARAMETERS:                                                                M
*   Name:      Name of state variable.                                       M
*   Data:      New value of state variable.                                  M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   SetIritState                                                             M
*****************************************************************************/
void SetIritState(char *Name, IPObjectStruct *Data)
{
    if (stricmp(Name, "Coplanar") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    BoolSetHandleCoplanarPoly(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "DebugFunc") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    InptPrsrDebugFuncLevel(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "DebugMalloc") == 0) {
	if (IP_IS_STR_OBJ(Data)) {
	    if (stricmp(Data -> U.Str, "Reset") == 0)
		IritDebugMallocReset();
	    else if (strcmp(Data -> U.Str, "Print") == 0) {
		/* Delay print until parsing tree of this command is free. */
		GlblIritMallocDebugPrint = TRUE;
	    }
	    else {
		int i;
		long l;

		if (sscanf(Data -> U.Str, "%lx,%d", &l, &i) == 2 ||
		    sscanf(Data -> U.Str, "%ld,%d", &l, &i) == 2) {
		    char Line[LINE_LEN];

		    sprintf(Line,
			    "Malloc searching for %ld (0x%08lx), abort = %d",
			    l, (unsigned long) l, i);
		    WndwInputWindowPutStr(Line);
		    IritDebugMallocSearchPtr((VoidPtr) l, i);
		}
	    }
	}
	else
	    WndwInputWindowPutStr("String state value expected");
    }
    else if (stricmp(Name, "DumpLevel") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    SetDumpLevel(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "EchoSource") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    InptPrsrEchoSource(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "FloatFrmt") == 0) {
	if (IP_IS_STR_OBJ(Data)) {
	    strcpy(GlblFloatFormat, Data -> U.Str);
	    IritPrsrSetFloatFormat(GlblFloatFormat);
	}
	else
	    WndwInputWindowPutStr("String state value expected");
    }
    else if (stricmp(Name, "InterCrv") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    BoolSetOutputInterCurve(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "InterpProd") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    BspMultInterpFlag(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "PolySort") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    BoolSetPolySortAxis(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "PrimSrfs") == 0) {
	if (IP_IS_NUM_OBJ(Data)) {
	    PrimSetPolygonalPrimitives(!REAL_TO_INT(Data -> U.R));
	}
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "PrimRatSrfs") == 0) {
	if (IP_IS_NUM_OBJ(Data)) {
	    PrimSetSurfacePrimitiveRational(REAL_TO_INT(Data -> U.R));
	}
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "TrimCrvs") == 0) {
	if (IP_IS_NUM_OBJ(Data)) {
	    TrimSetEuclidComposedFromUV(Data -> U.R <= 0);
	    TrimSetTrimCrvLinearApprox((int) (fabs(Data -> U.R)),
				       SYMB_CRV_APPROX_UNIFORM);
	}
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
    else if (stricmp(Name, "UVBoolean") == 0) {
	if (IP_IS_NUM_OBJ(Data))
	    BoolSetParamSurfaceUVVals(REAL_TO_INT(Data -> U.R));
	else
	    WndwInputWindowPutStr("Numeric state value expected");
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               *
* Routine to query (and print) the errors found by InputParser.		     *
*                                                                            *
* PARAMETERS:                                                                *
*   None                                                                     *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*****************************************************************************/
static void PrintInptPrsrError(void)
{
    InptPrsrEvalErrType ErrorNum;
    char *ErrorMsg, *p;
    char Line[LINE_LEN_LONG];

    if ((ErrorNum = InptPrsrParseError(&ErrorMsg)) != IPE_NO_ERR) {/*Prsr err*/
	sprintf(Line, "Parsing Error: ");
	p = &Line[strlen(Line)];
	switch (ErrorNum) {
	    case IP_ERR_WRONG_SYNTAX:
		sprintf(p, "Wrong syntax\n");
		break;
	    case IP_ERR_PARAM_EXPECT:
		sprintf(p, "Parameter Expected\n");
		break;
	    case IP_ERR_ONE_OPERAND:
	    case IP_ERR_TWO_OPERAND:
		sprintf(p, "Wrong # of operands - %s\n", ErrorMsg);
		break;
	    case IP_ERR_STACK_OV:
		sprintf(p, "Internal Stack OverFlow at - %s\n", ErrorMsg);
		break;
	    case IP_ERR_PARAM_MATCH:
		sprintf(p, "Parenthesis mismatch - %s\n", ErrorMsg);
		break;
	    case IP_ERR_UNDEF_TOKEN:
		sprintf(p, "Undefined token - %s\n", ErrorMsg);
		break;
	    case IP_ERR_UNDEF_FUNC:
		sprintf(p, "Undefined function - %s\n", ErrorMsg);
		break;
	    case IP_ERR_NAME_TOO_LONG:
		sprintf(p, "Object name too long - %s\n", ErrorMsg);
		break;
	    case IP_ERR_PARAM_FUNC:
		sprintf(p, "Parameters expected in func %s\n", ErrorMsg);
		break;
	    case IP_ERR_NO_PARAM_FUNC:
		sprintf(p, "No Parameters expected in func %s\n", ErrorMsg);
		break;
	    case IP_ERR_STR_TOO_LONG:
		sprintf(p, "String too long - %s\n", ErrorMsg);
		break;
	    default:
		sprintf(p, "Undefined error %d", ErrorNum);
		break;
	}
	WndwInputWindowPutStr(Line);
	return;
    }

    if ((ErrorNum = InptPrsrEvalError(&ErrorMsg)) != IPE_NO_ERR) {/*Eval err.*/
	sprintf(Line, "Eval Error: ");
	p = &Line[strlen(Line)];
	switch (ErrorNum) {
	    case IE_ERR_FATAL_ERROR:
		sprintf(p, "Fatal error - %s\n", ErrorMsg);
		break;
	    case IE_ERR_DIV_BY_ZERO:
		sprintf(p, "Division by zero - %s\n", ErrorMsg);
		break;
	    case IE_ERR_NO_OBJ_METHOD:
		sprintf(p, "No such method for object - %s\n", ErrorMsg);
		break;
	    case IE_ERR_TYPE_MISMATCH:
		sprintf(p, "Parameter type mismatch - %s\n",
			ErrorMsg);
		break;
	    case IE_ERR_ASSIGN_LEFT_OP:
		sprintf(p, "Lval is not a parameter - %s\n", ErrorMsg);
		break;
	    case IE_ERR_MIXED_OBJ:
		sprintf(p, "Mixed types in expression - %s\n", ErrorMsg);
		break;
	    case IE_ERR_IP_OBJ_UNDEFINED:
		sprintf(p, "No such object defined - %s\n", ErrorMsg);
		break;
	    case IE_ERR_NO_ASSIGNMENT:
		sprintf(p, "Assignment was expected\n");
		break;
	    case IE_ERR_FP_ERROR:
		sprintf(p, "Floating Point Error - %s\n", ErrorMsg);
		break;
	    case IE_ERR_NUM_PRM_MISMATCH:
		sprintf(p, "Number of func. param. mismatch - %s\n", ErrorMsg);
		break;
	    case IE_ERR_MAT_POWER:
		sprintf(p, "Wrong range or not exists, operator - %s\n", ErrorMsg);
		break;
	    case IE_ERR_FREE_SIMPLE:
		sprintf(p, "Free only geometric objects - %s\n", ErrorMsg);
		break;
	    case IE_ERR_MODIF_ITER_VAR:
		sprintf(p, "Iteration var. type modified or freed - %s\n", ErrorMsg);
		break;
	    case IE_ERR_BOOLEAN_ERR:
		sprintf(p, "Geometric Boolean operation error - %s\n", ErrorMsg);
		break;
	    case IE_ERR_OUT_OF_RANGE:
		sprintf(p, "Out of range.\n");
		break;
	    case IE_ERR_DATA_PRSR_ERROR:
		sprintf(p, "%s", ErrorMsg);
		break;
	    case IE_ERR_USER_FUNC_NO_RETVAL:
		sprintf(p, "User defined function \"%s\" has no returned value\n",
			ErrorMsg);
		break;
	    case IE_ERR_INCOMPARABLE_TYPES:
		sprintf(p, "Incomparable object types found");
		break;
	    case IE_ERR_ONLYEQUALITY_TEST:
		sprintf(p, "Only equality or non equality test is valid for these objects");
		break;
	    case IE_ERR_IF_HAS_NO_COND:
		sprintf(p, "Condition of if clause is illegal");
		break;
	    case IE_ERR_IP_USERFUNC_DUP_VAR:
		sprintf(p, "Duplicated variable, %s", ErrorMsg);
		break;
	    case IE_ERR_UNDEF_INSTANCE:
		sprintf(p, "Undefined object to instantiate from, %s",
			ErrorMsg);
		break;
	    default:
		sprintf(p, "Undefined error %d\n", ErrorNum);
		break;
	}
	WndwInputWindowPutStr(Line);
	return;
    }
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* IRIT Exit routine. Error code of zero.				     M
*                                                                            *
* PARAMETERS:                                                                M
*   None                                                                     *
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   IritExit0                                                                M
*****************************************************************************/
void IritExit0(void)
{
    IritExit(0);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* IRIT Exit routine.                           				     M
*                                                                            *
* PARAMETERS:                                                                M
*   ExitCode:   Exit code.                                                   *
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   IritExit                                                                 M
*****************************************************************************/
void IritExit(int ExitCode)
{
    if (GlblDoGraphics) {
    	WndwViewExit();
    }

    ClientCloseAll(TRUE);

    chdir(GlblCrntWorkingDir);	  /* Recover original directory before exit. */

    if (GlblPrintLogFile)
	fclose(GlblLogFile);		      /* Close log file if was open. */

    exit(ExitCode);
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Traps Cagd_lib errors right here. Call back function of cagd_lib.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrID:    Error number in cagd_lib library.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   CagdFatalError                                                           M
*****************************************************************************/
void CagdFatalError(CagdFatalErrorType ErrID)
{
    char Line[LINE_LEN],
	*ErrorMsg = CagdDescribeError(ErrID);

    sprintf(Line, "CAGD_LIB: %s", ErrorMsg);
    WndwInputWindowPutStr(Line);

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Traps Symb_lib errors right here. Call back function of symb_lib.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrID:    Error number in symb_lib library.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   SymbFatalError                                                           M
*****************************************************************************/
void SymbFatalError(SymbFatalErrorType ErrID)
{
    char Line[LINE_LEN],
	*ErrorMsg = SymbDescribeError(ErrID);

    sprintf(Line, "SYMB_LIB: %s", ErrorMsg);
    WndwInputWindowPutStr(Line);

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Traps Trim_lib errors right here. Call back function of trim_lib.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrID:    Error number in trim_lib library.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   TrimFatalError                                                           M
*****************************************************************************/
void TrimFatalError(TrimFatalErrorType ErrID)
{
    char Line[LINE_LEN],
	*ErrorMsg = TrimDescribeError(ErrID);

    sprintf(Line, "TRIM_LIB: %s", ErrorMsg);
    WndwInputWindowPutStr(Line);

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Traps Triv_lib errors right here. Call back function of triv_lib.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrID:    Error number in triv_lib library.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   TrivFatalError                                                           M
*****************************************************************************/
void TrivFatalError(TrivFatalErrorType ErrID)
{
    char Line[LINE_LEN],
	*ErrorMsg = TrivDescribeError(ErrID);

    sprintf(Line, "TRIV_LIB: %s", ErrorMsg);
    WndwInputWindowPutStr(Line);

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Traps Trng_lib errors right here. Call back function of trng_lib.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrID:    Error number in trng_lib library.                              M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   TrivFatalError                                                           M
*****************************************************************************/
void TrngFatalError(TrngFatalErrorType ErrID)
{
    char Line[LINE_LEN],
	*ErrorMsg = TrngDescribeError(ErrID);

    sprintf(Line, "TRNG_LIB: %s", ErrorMsg);
    WndwInputWindowPutStr(Line);

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Prints IRIT none fatal error message and go back to cursor mode.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrorMsg:    Error message to print out.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   TrivNonFatalError                                                        M
*****************************************************************************/
void IritNonFatalError(char *ErrorMsg)
{
    if (ErrorMsg != NULL) {
	WndwInputWindowPutStr(ErrorMsg);
    }

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Prints IRIT's fatal error message and go back to cursor mode.		     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrorMsg:    Error message to print out.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   IritPrsrFatalError                                                       M
*****************************************************************************/
void IritFatalError(char *ErrorMsg)
{
    if (ErrorMsg != NULL) {
	WndwInputWindowPutStr("Fatal error occured, please report it:");
	WndwInputWindowPutStr(ErrorMsg);
    }

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Prints IRIT parser's fatal error message and go back to cursor mode.	     M
*                                                                            *
* PARAMETERS:                                                                M
*   ErrorMsg:    Error message to print out.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            M
* KEYWORDS:                                                                  M
*   IritPrsrFatalError                                                       M
*****************************************************************************/
void IritPrsrFatalError(char *ErrorMsg)
{
    if (ErrorMsg != NULL) {
	WndwInputWindowPutStr(ErrorMsg);
    }

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);	   /* Go back to main loop directly. */
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Called from the floating point package in case of fatal floating point     M
* error.								     M
*   Prints error message and long jumps to main loop.			     M
*   Default FPE handler - must be reset after redirected to other module.    M
*                                                                            *
* PARAMETERS:                                                                M
*   Type:      Of floating point error.                                      M
*                                                                            *
* RETURN VALUE:                                                              M
*   void                                                                     M
*                                                                            *
* KEYWORDS:                                                                  M
*   DefaultFPEHandler                                                        M
*****************************************************************************/
void DefaultFPEHandler(int Type)
{
    char Line[LINE_LEN];

    sprintf(Line, "Floating point error %d.", Type);
    WndwInputWindowPutStr(Line);

    FlushToEndOfExpr(TRUE);

    longjmp(GlblLongJumpBuffer, 1);
}

#ifdef DEBUG

/*****************************************************************************
* DESCRIPTION:                                                               *
*    Dummy function to link at debugging time.                               *
*                                                                            *
* PARAMETERS:                                                                *
*                                                                            *
* RETURN VALUE:                                                              *
*   void                                                                     *
*                                                                            *
* KEYWORDS:                                                                  *
*****************************************************************************/
void DummyLinkCagdDebug(void)
{
    IritPrsrDbg();
}

#endif /* DEBUG */
