/*=========================================================================
 *
 * GENERR.CPP - 27 November 1998, Dave Humphrey (aj589@freenet.carleton.ca)
 *
 * Contains general and custom error routines commonly used by myself.
 *
 *=======================================================================*/

	/* Platform/compiler specific includes */
#if defined(_MSC_VER) || defined(_WIN32)
  #include <windows.h>
#endif

#if defined(_D3D)
  #include "d3dcom.h"
#endif

	/* Required includes */
#include "genutil.h"


/*=========================================================================
 *
 * Begin Variable Definitions
 *
 *=======================================================================*/
	
/*=========================================================================
 *		End of Variable Definitions
 *=======================================================================*/


#undef  __FUNC__
#define __FUNC__ "ShowErrorMsgBox()"
/*===========================================================================
 *
 * Function - boolean ShowErrorMsgBox (Type, pTitle, pMsg);
 *
 * Local helper function to display a message box. Function used depends
 * on the platform and compiler type.
 *
 *=========================================================================*/

	/* Default windows function displays a message box */
#ifdef _WIN32

boolean ShowErrorMsgBox (const errlevel_t Level, const char *pTitle, const char *pMsg) {
  UINT uType;

	/* Select the message box icon type base on the error level */
  switch (Level) {
    case EL_INFO:     uType = MB_ICONINFORMATION; break;
    case EL_WARNING:  uType = MB_ICONEXCLAMATION; break;
    case EL_ERROR:    uType = MB_ICONSTOP; break;
    case EL_CRITICAL: uType = MB_ICONSTOP; break;
    case EL_UNKNOWN:  uType = MB_ICONQUESTION; break;
    default:          uType = MB_ICONEXCLAMATION; break;
   }

	/* Display the message box */
  MessageBox(NULL, pMsg, pTitle, uType | MB_OK | MB_TASKMODAL);
  return (TRUE);
 }  

#else	/* Default function, just output information to log file and stdout */

boolean ShowErrorMsgBox (const errlevel_t Level, const char *pTitle, const char *pMsg) {
  printf("   %s\n", pTitle);
  printf("      %s (Level = %s)\n", pMsg, ErrorLeveltoStr(Level));
  return (FALSE);
 }  
	
#endif
/*===========================================================================
 *		End of Function ShowErrorMsgBox()
 *=========================================================================*/


#undef __FUNC__
#define __FUNC__ "CErrorRecord::CErrorRecord()"
/*===========================================================================
 *
 * Class CErrorRecord Constructor
 *
 *=========================================================================*/
CErrorRecord::CErrorRecord (void) {
  Code = ERR_NONE;
  Level = EL_UNKNOWN;
  pDesc = NULL;
 }
/*===========================================================================
 *		End of Class CErrorRecord Constructor
 *=========================================================================*/


#undef __FUNC__
#define __FUNC__ "CErrorRecord::Destroy()"
/*===========================================================================
 *
 * Class CErrorRecord Method - void Destroy (void);
 *
 * Deletes any allocated data and resets all values to some default setting.
 *
 *=========================================================================*/
void CErrorRecord::Destroy (void) {
  
	/* Reset the error code and level values and unallocate memory */
  Code = ERR_NONE;
  Level = EL_UNKNOWN;
  DestroyPointer(pDesc);
 }
/*===========================================================================
 *		End of Class Method CErrorRecord::Destroy()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::CErrorHandler()"
/*===========================================================================
 *
 * Class CErrorHandler Constructor
 *
 *=========================================================================*/
CErrorHandler::CErrorHandler (void) {


	/* Initialize member values */
  ErrorCode = ERR_NONE;
  SystemErrorCode = ERR_NONE;
  WindowsErrorCode = ERR_NONE;
  D3DErrorCode = ERR_NONE;
  NumCustomErrors = 0;

	/* Extended error information */
  pErrorFile = NULL;
  ErrorLine = 0;
  pErrorMessage = NULL;
  pErrorFunction = NULL;

  NotifyType = ERR_NOTIFY_USER;
  NotifiedUser = FALSE;

	/* Add the default custom errors to the class */
  AddError (ERR_NONE,     "No error generated.", EL_INFO);
  AddError (ERR_FILE,     "Failed to open file!", EL_ERROR);
  AddError (ERR_READ,     "Could not read from file!", EL_ERROR);
  AddError (ERR_WRITE,    "Could not write to file!", EL_ERROR);
  AddError (ERR_MEM,      "Not enough memory to allocate pointer!", EL_CRITICAL);
  AddError (ERR_INDEX,    "Array index exceeds minimum/maximum array limits!", EL_WARNING);
  AddError (ERR_HEAP,     "Corrupt heap space detected!", EL_CRITICAL);
  AddError (ERR_MAXINDEX, "Array has reached it's maximum size, could not add record!", EL_WARNING);
  AddError (ERR_NULL,     "Received invalid NULL pointer!", EL_WARNING);
  AddError (ERR_INPUT,    "Received input is invalid!", EL_WARNING);
  AddError (ERR_UINTMAX,  "Value exceeds the maximum value for an integer!", EL_ERROR);
  AddError (ERR_STRING,   "Operation exceeded the string's minimum/maximum limits!", EL_ERROR);
  AddError (ERR_OVERFLOW, "Received input that would result in an overflow!", EL_ERROR);
  AddError (ERR_FILETYPE, "File is not the correct type!", EL_ERROR);
  AddError (ERR_CUSTOM,   "Custom error.", EL_ERROR);
 }
/*===========================================================================
 *		End of Class CErrorHandler Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::AddError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - boolean AddError (NewCode, pNewDesc, NewLevel);
 *
 * Attempts to add a new custom error to the class.  On success the function
 * returns TRUE and FALSE if new custom error will not fit into array.
 *
 *=========================================================================*/
boolean CErrorHandler::AddError (const errnum_t NewCode, const char *pNewDesc, const errlevel_t NewLevel) {

	/* Will a new custom error fit into array */
  if (NumCustomErrors >= MAX_CUSTOM_ERRORS) return (FALSE);

	/* Allocate new custom error record */
  CreatePointer(pCustomErrors[NumCustomErrors], CErrorRecord);

	/* Copy given custom error data into new record */
  pCustomErrors[NumCustomErrors]->SetCode(NewCode);
  pCustomErrors[NumCustomErrors]->SetLevel(NewLevel);
  pCustomErrors[NumCustomErrors]->SetDesc(pNewDesc);
  NumCustomErrors++;

	/* Return success */
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::AddError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC_ "CErrorHandler::Destroy()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void Destroy (void);
 *
 * Deletes any allocated data and resets values to their initial settings.
 *
 *=========================================================================*/
void CErrorHandler::Destroy (void) {
  int LoopCounter;

	/* Clear the current error code values */
  ErrorCode = ERR_NONE;
  NotifiedUser = FALSE;

	/* Clear the extended error information */
  ErrorLine = -1;
  DestroyPointer(pErrorFile);
  DestroyPointer(pErrorMessage);
  DestroyPointer(pErrorFunction);

	/* Unallocate any valid record in the custom error array */
  for (LoopCounter = 0; LoopCounter < NumCustomErrors; LoopCounter++) {
    DestroyPointer(pCustomErrors[LoopCounter]);
   }

	/* Reset the number of custom errors defined */
  NumCustomErrors = 0;
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::Destroy()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::Exit()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void Exit (pString, ...);
 *
 * Outputs error message to user depending on the current system and exits
 * the program.  Accepts input as per the usual printf() format.
 *
 *=========================================================================*/
void CErrorHandler::Exit (const char *pString, ...) {
  char       MsgBuf[MAX_ERRMSG_SIZE+1];	/* String for creating error message */
  char       Title[MAX_ERRBUF_SIZE+1];	/* Title string buffer for output message */
  errlevel_t ErrLevel;
  size_t     MsgLength;			/* Used for saving the length of the message string */
  va_list    Args;				/* Used to print a variable list of arguments */

	/* Retrive the current error level */
  ErrLevel = GetErrorLevel();

	/* Create the message title */
  strnncpy (Title, ErrorLeveltoStr(ErrLevel), MAX_ERRBUF_SIZE);

	/* Output the error description to the string */
  strnncpy (MsgBuf, GetErrorMessage(), MAX_ERRMSG_SIZE-1);
  chrcat (MsgBuf, '\n');
  MsgLength = strlen(MsgBuf);

	/* Add the custom message string, if present */
  if (pErrorMessage != NULL) {
    strncat (MsgBuf, pErrorMessage, MAX_ERRMSG_SIZE - MsgLength - 1);
    chrcat (MsgBuf, '\n');
    MsgLength = strlen(MsgBuf);
   }

	/* Add the user's message string, if present */
  if (pString != NULL) {
    va_start (Args, pString);
    vsprintf (MsgBuf + MsgLength, pString, Args);
    va_end (Args);
   }

   	/* Display message box to the user */
  ShowErrorMsgBox (ErrLevel, Title, MsgBuf);
  NotifiedUser = TRUE;

	/* Exit the program */ 
  exit (EXIT_FAILURE);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::Exit()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::FindCustomError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - int FindCustomError (ErrCode);
 *
 * Searches through the list of custom errors for a matching error code.
 * Returns the array index on success or CUSTOM_ERROR_NOTFOUND on error.
 * Protected class member (not for public use).
 *
 *=========================================================================*/
int CErrorHandler::FindCustomError (const errnum_t ErrCode) {
  int LoopCounter;

	/* Compare each custom error in array for a match */
  for (LoopCounter = 0; LoopCounter < NumCustomErrors; LoopCounter++) {
    if (pCustomErrors[LoopCounter]->GetCode() == ErrCode) return (LoopCounter);
   }

	/* If none found, return failure */
  return (CUSTOM_ERROR_NOTFOUND);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::FindCustomError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::GetErrorCode()"
/*===========================================================================
 *
 * Class CErrorHandler Method - errnum_t GetErrorCode (void);
 *
 * Returns the raw value of the error code depending on its type.  
 *
 *=========================================================================*/
errnum_t CErrorHandler::GetErrorCode (void) {

	/* Check for a system, windows, or a custom error code */
  if (ErrorCode == ERR_SYSTEM)
    return ((errnum_t) SystemErrorCode);
  else if (ErrorCode == ERR_WINDOWS)
    return ((errnum_t) WindowsErrorCode);
  else if (ErrorCode == ERR_D3D)
    return ((errnum_t) D3DErrorCode);
  else
    return (ErrorCode);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::GetErrorCode()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::GetErrorLevel()"
/*===========================================================================
 *
 * Class CErrorHandler Method - errlevel_t GetErrorLevel (void);
 *
 * Returns the error level associated with the current error code.
 *
 *=========================================================================*/
errlevel_t CErrorHandler::GetErrorLevel (void) {
  int ErrorIndex;

	/* Is the error type a system or windows error? */
  if (ErrorCode == ERR_SYSTEM || ErrorCode == ERR_WINDOWS) return (EL_ERROR);

	/* Otherwise, find the error's level */
  ErrorIndex = FindCustomError(ErrorCode);

	/* Make sure the error code was found */
  if (ErrorIndex == CUSTOM_ERROR_NOTFOUND) return (EL_UNKNOWN);
  return (pCustomErrors[ErrorIndex]->GetLevel());
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::GetErrorLevel()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::GetErrorMessage()"
/*===========================================================================
 *
 * Class CErrorHandler Method - char* GetErrorMessage (void);
 *
 * Returns the description string of the current error code.  The error code
 * can represent any custom error or any in the set of system errors.
 * Never returns NULL.  If error code cannot be found, a message stated that
 * will be returned.
 *
 *=========================================================================*/
char* CErrorHandler::GetErrorMessage (void) { 
  static char ErrBuf[MAX_ERRBUF_SIZE+1];	/* String buffer for holding error messages */
  
	/* Special case for a system or windows error */
  if (ErrorCode == ERR_SYSTEM)
    return (GetSystemErrorMessage(ErrBuf));
  else if (ErrorCode == ERR_WINDOWS)
    return (GetWindowsErrorMessage(ErrBuf));
  else if (ErrorCode == ERR_D3D) 
    return (GetD3DErrorMessage(ErrBuf));
   
	/* Otherwise, error must be a custom error */
  int ErrorIndex = FindCustomError(ErrorCode);

	/* Does the given custom error code exist? */
  if (ErrorIndex == CUSTOM_ERROR_NOTFOUND) {
    sprintf (ErrBuf, "Custom error code %d not found!", ErrorCode);
    return (ErrBuf);
   }

	/* Is the description of the custom error valid? */
  if (pCustomErrors[ErrorIndex]->GetDesc() == NULL) {
    sprintf (ErrBuf, "No description available for the error code %d!", ErrorCode);
    return (ErrBuf);
   }

	/* Return custom error message */
  return (pCustomErrors[ErrorIndex]->GetDesc());
 }
/*===========================================================================
 *		End of Class* CErrorHandler::GetErrorMessage()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::GetD3DErrorMessage()"
/*===========================================================================
 *
 * Class CErrorHandler Method - char * GetD3DErrorMessage (pString);
 *
 * An internal class function used to create a string from the D3D error
 * code.  The function never returns NULL.
 *
 *=========================================================================*/
char *CErrorHandler::GetD3DErrorMessage (char *pString) {

	/* Ensure that we are compiling in windows */
#ifndef _D3D
  return ("No Direct3D errors defined!");
#else

	/* Retrieve the D3D error message (in the default language) */
  return D3DRMErrorToString(D3DErrorCode);
#endif
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::GetD3DErrorMessage()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::GetSystemErrorMessage()"
/*===========================================================================
 *
 * Class CErrorHandler Method - char* GetSystemErrorMessage (pString);
 *
 * An internal class function used to create a string from the system error
 * code.  The function never returns NULL.
 *
 *=========================================================================*/
char* CErrorHandler::GetSystemErrorMessage (char *pString) {
  char* pErrDesc;
  
	/* Get the system error message */
  pErrDesc = strerror(SystemErrorCode);

	/* Ensure the error string is valid */
  if (pErrDesc == NULL) {
    sprintf (pString, "System error code %d not found!", errno);
    return (pString);
   }

  return (pErrDesc);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::GetSystemErrorMessage()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::GetWindowsErrorMessage()"
/*===========================================================================
 *
 * Class CErrorHandler Method - char * GetWindowsErrorMessage (pString);
 *
 * An internal class function used to create a string from the system error
 * code.  The function never returns NULL.
 *
 *=========================================================================*/
char *CErrorHandler::GetWindowsErrorMessage (char *pString) {

	/* Ensure that we are compiling in windows */
  #ifndef _WIN32
    return ("No windows error defined!");
  #else 
    DWORD Result;

	/* Retrieve the windows error message (in the default language) */
    Result = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, 
		       NULL, WindowsErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		       pString, 255, NULL);
    if (Result == 0) sprintf (pString, "Error retrieving windows error message %u!", WindowsErrorCode);
    return (pString);
  #endif
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::GetWindowsErrorMessage()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::Notify()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void Notify (pString, ...);
 *
 * Outputs error message to user depending on the current system.  Exits the
 * program only if the error is a critical one.  Accepts input as per the 
 * usual printf() format.
 *
 *=========================================================================*/
void CErrorHandler::Notify (const char *pString, ...) {
  char MsgBuf[MAX_ERRMSG_SIZE+1];	/* String for creating error message */
  char Title[MAX_ERRBUF_SIZE+1];	/* Title string buffer for output message */
  errlevel_t ErrLevel;
  size_t MsgLength;			/* Used for saving the length of the message string */
  va_list args;				/* Used to print a variable list of arguments */

	/* Retrive the current error message, code, and level */
  ErrLevel = GetErrorLevel();

	/* Create the message title */
  strnncpy (Title, ErrorLeveltoStr(ErrLevel), MAX_ERRBUF_SIZE);

	/* Output the error description to the string */
  strnncpy (MsgBuf, GetErrorMessage(), MAX_ERRMSG_SIZE-2);
  chrcat (MsgBuf, '\n');
  MsgLength = strlen(MsgBuf);

  	/* Add the custom message string, if present */
  if (pErrorMessage != NULL) {
    strncat (MsgBuf, pErrorMessage, MAX_ERRMSG_SIZE - MsgLength - 1);
    chrcat (MsgBuf, '\n');
    MsgLength = strlen(MsgBuf);
   }

	/* Add the user's message string, if present */
  if (pString != NULL) {
    va_start (args, pString);
    vsprintf (MsgBuf+MsgLength, pString, args);
    va_end (args);
   }

	/* Determine what to do */
  if (NotifyType == ERR_NOTIFY_USER)
    ShowErrorMsgBox (ErrLevel, Title, MsgBuf);
  else if (NotifyType == ERR_NOTIFY_LOG)
    SystemLog.Printf ("Error %s: %s", Title, MsgBuf);

	/* Exit the program only if the error is critical */ 
  NotifiedUser = TRUE;
  if (ErrLevel == EL_CRITICAL) exit (EXIT_FAILURE);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::Notify()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::OutputLog()"
/*===========================================================================
 *
 * Class CErrorHandler Method - boolean OutputLog (pFileHandle);
 *
 * Outputs the current error information to the given file stream.
 * If the input file handle is NULL, the data will attempt to output
 * to the current SystemLog file.  Returns FALSE on any error.
 *
 *=========================================================================*/
boolean CErrorHandler::OutputLog (FILE* pFileHandle) {
  char TimeString[21];

	/* Ignore if nothing interesting has happened */
  if (!IsError()) return (TRUE);

	/* Default to using the SystemLog as output, ensuring its valid */
  if (pFileHandle == NULL) {
    pFileHandle = SystemLog.GetFileHandle();
    if (pFileHandle == NULL) return (FALSE);
   }

  clearerr(pFileHandle);
  fprintf (pFileHandle, "********** Error Log (%s) **********\n", _strtime (TimeString));
  fprintf (pFileHandle, "\tError Code = \t %d, %s\n", ErrorCode, GetErrorMessage());

	/* Output extended error information, if available */
  if (pErrorMessage != NULL) fprintf (pFileHandle, "\tMessage: \t %s\n", pErrorMessage);
  if (pErrorFile != NULL)    fprintf (pFileHandle, "\tFilename: \t %s\n", pErrorFile);
  if (pErrorFunction != NULL && *pErrorFunction != NULL_CHAR) 
			     fprintf (pFileHandle, "\tFunction: \t %s\n", pErrorFunction);
  if (ErrorLine > 0)	     fprintf (pFileHandle, "\tLineNumber: \t %ld\n", ErrorLine);
  
	/* Ensure the data is flushed from the file buffer, if any */
  fflush(pFileHandle);

	/* Ensure data was correctly output to file */
  if (ferror(pFileHandle) || feof(pFileHandle)) return (FALSE);
  return (TRUE);  
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::OutputLog()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::SetError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void SetError (NewCode);
 *
 * Sets the current error code(s) based on the given error code and any of 
 * the current system errors.
 *
 *=========================================================================*/
void CErrorHandler::SetError (const errnum_t NewCode) {

	/* Check to see if new error is a system type */
  if (NewCode == ERR_SYSTEM) {
    SystemErrorCode = errno;
   }
	/* Check to see if new error is a windows type */
  else if (NewCode == ERR_WINDOWS) {

#ifndef _WIN32
    WindowsErrorCode = ERR_NONE;
#else
    WindowsErrorCode = GetLastError();
#endif

   }

	/* Check to see if new error is a D3D type */
  else if (NewCode == ERR_D3D) {

#ifndef _D3D
    D3DErrorCode = ERR_NONE;
#else
		/* Error must be defined by user via SetD3DError() */
#endif

   }

	/* Otherwise error must be a custom error */
  ErrorCode = NewCode;

	/* Destroy any extended error information */
  NotifiedUser = FALSE;
  SetFile(NULL);
  SetMessage(NULL);
  SetFunction(NULL);
  SetLine(-1);
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::SetError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::SetExtError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void SetExtError (NewCode, pFile, pFunc, Line);
 *
 * Sets the current extended error code(s) based on the given error 
 * code and any of the current system errors.
 *
 *=========================================================================*/
void CErrorHandler::SetExtError (const errnum_t NewCode, const char* pFile, const char* pFunc, const long Line) { 

	/* Set the error code */
  SetError(NewCode);

	/* Set the extended error information */
  SetLine(Line);
  SetFile(pFile);
  SetFunction(pFunc);
  SetMessage(NULL);
  NotifiedUser = FALSE;

	/* Output information to log file */
  OutputLog();
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::SetExtError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::SetExtError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void SetExtError (NewCode, pFile, pFunc, Line, pMsg, ...);
 *
 * Sets the current extended error code(s) based on the given error 
 * code and any of the current system errors.
 *
 *=========================================================================*/
void CErrorHandler::SetExtError (const errnum_t NewCode, const char* pFile, const char* pFunc, const long Line, const char* pMsg, ...) {
  char    Buffer[1024];
  va_list Args;

	/* Set the error code */
  SetError(NewCode);

	/* Set the extended error information */
  SetLine(Line);
  SetFile(pFile);
  SetFunction(pFunc);
  SetMessage(NULL);
  NotifiedUser = FALSE;

	/* Create the message string if present */
  if (pMsg != NULL) {
    va_start (Args, pMsg);
    vsprintf (Buffer, pMsg, Args);
    va_end (Args);
    SetMessage(Buffer);
   }

  OutputLog();
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::SetExtError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::SetWindowsError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void SetWindowsError (NewCode);
 *
 * Sets the current windows error code(s) based on the given error code.
 *
 *=========================================================================*/
void CErrorHandler::SetWindowsError (const long NewCode) {

	/* Set the windows error code */
  ErrorCode = ERR_WINDOWS;
  WindowsErrorCode = NewCode;
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::SetWindowsError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CErrorHandler::SetD3DError()"
/*===========================================================================
 *
 * Class CErrorHandler Method - void SetD3DError (NewCode);
 *
 * Sets the current windows error code(s) based on the given error code.
 *
 *=========================================================================*/
void CErrorHandler::SetD3DError (const long NewCode) {

	/* Set the windows error code */
  ErrorCode = ERR_D3D;
  D3DErrorCode = NewCode;
 }
/*===========================================================================
 *		End of Class Method CErrorHandler::SetD3DError()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CustomAssert()"
/*===========================================================================
 *
 * Function - void CustomAssert (pString, pFile, pFunc, Line);
 *
 * A custom assertion type function used if one is not supplied by the 
 * system.  Accepts a message string, file name, and line number where the
 * assertion occurred.  Does not return, exits program with EXIT_FAILURE.
 * Outtputs message to any log file and stderr.
 *
 *=========================================================================*/
void CustomAssert (const char *pString, const char *pFile, const char* pFunc, const int Line) {
  char MsgBuffer[1024];
  
	/* Output input parameters to log file */
  SystemLog.Printf ("Assertion Failed: '%s'", pString);
  SystemLog.Printf ("     File %s,  Line %d", pFile, Line);

	/* Output message to user */
  sprintf (MsgBuffer, "Assertion Failed: %s!\r\n\tFile: \t%s\r\n\tFunction: \t%s\r\n\tLine: \t%ld", pString, pFile, pFunc, Line);
  ShowErrorMsgBox(EL_ERROR, "Assertion Failed!", MsgBuffer);

	/* Abort program */
  exit(EXIT_FAILURE);
 }
/*===========================================================================
 *		End of Function CustomAssert()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "GetErrorHandler()"
/*===========================================================================
 *
 * Function - CErrorHandler& GetErrorHandler (void)
 *
 * Returns a reference to the global error handler object.  This is done 
 * instead of a global variable because we need to ensure that the
 * error handler is constructed and initialized before any custom errors
 * are added to it.  Since the errors could be added during the program
 * startup, we have no guaruntee that a global object would be constructed
 * before others.  Thus, we use a static function object in a global function.
 * The object is constructed the first time the function is called.
 *
 *=========================================================================*/
CErrorHandler& GetErrorHandler (void) {
  static CErrorHandler ErrHandler;
  return (ErrHandler);
 }
/*===========================================================================
 *		End of Function GetErrorHandler()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "ErrorLeveltoStr()"
/*===========================================================================
 *
 * Function - char *ErrorLeveltoStr (Level);
 *
 * Converts an error level value to a string.
 *
 *=========================================================================*/
char *ErrorLeveltoStr (const errlevel_t Level) {

  switch (Level) {
    case EL_INFO:     return ("Information");
    case EL_WARNING:  return ("Warning");
    case EL_ERROR:    return ("Error");
    case EL_CRITICAL: return ("Critical Error");
    case EL_UNKNOWN:  return ("Unknown");
    default:          return ("Invalid Level");
   }
 }
/*===========================================================================
 *		End of Function ErrorLeveltoStr()
 *=========================================================================*/