// ------------------------------- //
// -------- Start of File -------- //
// ------------------------------- //
// ----------------------------------------------------------- // 
// C++ Source Code File Name: ehandler.cpp 
// Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
// Produced By: Doug Gaer  
// File Creation Date: 02/14/1996  
// Date Last Modified: 11/04/1998
// Copyright (c) 1997 Douglas M. Gaer
// ----------------------------------------------------------- // 
// ------------- Program Description and Details ------------- // 
// ----------------------------------------------------------- // 
/*
The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
All those who put this code or its derivatives in a commercial
product MUST mention this copyright in their documentation for
users of the products in which this code or its derivative
classes are used. Otherwise, you have the freedom to redistribute
verbatim copies of this source code, adapt it to your specific
needs, or improve the code and release your improvements to the
public provided that the modified files carry prominent notices
stating that you changed the files and the date of any change.

THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
CORRECTION.

The Ehandler class is used to catch program exceptions that
occur at run-time. This implementation can be used with or
without C++ built-in exception handling. If C++ exception
handling is not enabled with the CPP_EXCEPTIONS macro, then
the EHandler class can be used to display program errors,
exit the program, or trap a program error with a user defined
Action Function.
*/
// ----------------------------------------------------------- // 
#include <string.h>
#include "ehandler.hpp"

#ifdef __wxWINDOWS__
#include "wxincs.hpp"
#endif

#ifdef __CONSOLE__
#include <iostream.h>
#include <stdlib.h>
#endif

#ifdef __CURSES__
#include <stdlib.h>
#include "terminal.hpp"
#endif

const char *MessageBoxString = "Caught Exception: ";
const char *MessageBoxCaption = "Program Error";

EHandler ExceptionHandler;
EHandler *Error = &ExceptionHandler; // Global exception handler pointer

const char *ExceptionMessage[MessageCount] = {
    "No exception reported",                     // None
    "File not ready (failed or closed file)",    // FileNotReady
    "Could not write to file",                   // FileNotWriteable
    "Trying to write to a read-only file",       // ReadOnlyFile
    "Trying to use a closed file",               // FileNotOpenError
    "Error creating file",                       // FileCreationError
    "Error opening file",                        // FileOpenError
    "Error closing file",                        // FileCloseError
    "Error seeking in file",                     // FileSeekError
    "Error reading from file",                   // FileReadError
    "Error writing to file",                     // FileWriteError
    "Unexpected end of file",                    // EOFError
    "Wrong file type",                           // WrongFileType
    "File corrupted",                            // FileCorrupt
    "File already exists",                       // FileExists
    "No such file exists",                       // NoFileExists
    "Invalid path",                              // PathError
    "Dangling 'reference counted pointer'",      // DanglingPtr
    "Accessing a null pointer",                  // NullPtr
    "Cache full",                                // CacheFull
    "Stack full",                                // StkFull
    "Stack empty",                               // StkEmpty
    "Assertion failed",                          // AssertError
    "No database open",                          // NoDatabaseOpen
    "Object already exists",                     // ObjectExists
    "Bad Object Address",                        // BadObjectAddress
    "Bad Reference",                             // BadReference
    "Divide By Zero Error",                      // DivideByZero
    "Math overflow error",                       // OverFlow
    "Math under-flow error",                     // UnderFlow
    "Parse error",                               // ParseError         
    "No objects exist",                          // NoObjectsExist
    "Wrong object type",                         // BadClassID
    "Synchronization Error",                     // SyncError
    "Access Violation",                          // AccessViolation
    "Checksum Error"                             // ChecksumError
};

EHandler::~EHandler()
{
  // Destructor provided for virtuality
} 

void EHandler::DisplayException()
{
#ifdef __wxWINDOWS__
  int len = strlen(MessageBoxString) + strlen(ExceptionMessage[ExceptionCode]);
  char *comp = new char[len+1];
  comp[len+1] = '\0';
  strcpy(comp, MessageBoxString);
  strcat(comp, ExceptionMessage[ExceptionCode]);
  wxMessageBox(comp, (char *)MessageBoxCaption, wxOK|wxCENTRE);
  delete comp;
#endif

#ifdef __CURSES__
  terminal->ClearScreen();
  terminal->Write("Caught Exception: ", 0, 0);
  terminal->Write(ExceptionMessage[ExceptionCode]);
  terminal->AnyKey(0, 2);
#endif

#ifdef __CONSOLE__
    cout << endl << "Caught Exception: "
       << ExceptionMessage[ExceptionCode]
       << endl;
#endif
}

void EHandler::DisplayException(int ECode)
{
#ifdef __wxWINDOWS__
  int len = strlen(MessageBoxString) + strlen(ExceptionMessage[ExceptionCode]);
  char *comp = new char[len+1];
  comp[len+1] = '\0';
  strcpy(comp, MessageBoxString);
  strcat(comp, ExceptionMessage[ExceptionCode]);
  wxMessageBox(comp, (char *)MessageBoxCaption, wxOK|wxCENTRE);
  delete comp;
#endif

#ifdef __CURESES__
  terminal->ClearScreen();
  terminal->Write("Caught Exception: ");
  terminal->Write(ExceptionMessage[ECode]);
  terminal->AnyKey(0, 2);
#endif

#ifdef __CONSOLE__
  cout << endl << "Caught Exception: "
       << ExceptionMessage[ECode]
       << endl;
#endif
}

void EHandler::SignalException(int ECode, int Level, int DisplayError)
{
  SetException(ECode); // Set the exception code

  // By default a message will be displayed
  if(DisplayError) DisplayException(); 

  switch(Level)
    {
      case FATAL:    // Fatal error, terminate program immediately
	Terminate();

      case DISPLAY: // Dummy handler that does nothing
	return;

      default:
	Terminate();
    }
}

void EHandler::Message
(const char *mesg1, const char *mesg2, const char *mesg3)
{
#ifdef __wxWINDOWS__
  int len = strlen(mesg1) + strlen(mesg2) + strlen(mesg3);
  char *comp = new char[len+1];
  comp[len+1] = '\0';
  strcpy(comp, mesg1);
  strcat(comp, mesg2);
  strcat(comp, mesg3);
  wxMessageBox(comp, "Program Message", wxOK|wxCENTRE);
  delete comp;
#endif

  // #ifdef __CURSES__
  // Function not used in curses port
  // #endif

#ifdef __CONSOLE__
  cout << endl;
  if(mesg1) cout << mesg1;
  if(mesg2) cout << mesg2;
  if(mesg3) cout << mesg3;
  cout << endl;
#endif
}

void EHandler::Terminate()
{
#ifdef __wxWINDOWS__
  // Terminate the program using the wxExit() function.
  wxExit();
  // Exits application after calling wxApp::OnExit. Should only
  // be used in an emergency: normally the top-level frame should
  // be deleted (after deleting all other frames) to terminate the
  // application. 
#endif

#ifdef __CURSES__
  // Terminate the program abnormally
  terminal->finish();
  exit(FatalErrorLevel);
#endif

#ifdef __CONSOLE__
  // Terminate the program abnormally
  exit(FatalErrorLevel);
#endif
}

void EHandler::TrapException(AF ActionFunction)
{
  // Call the user defined routine
  (*ActionFunction)();
}
// ----------------------------------------------------------- //
// ------------------------------- //
// --------- End of File --------- //
// ------------------------------- //
