summaryrefslogtreecommitdiff
path: root/deps/g3dlite/source/debugAssert.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'deps/g3dlite/source/debugAssert.cpp')
-rw-r--r--deps/g3dlite/source/debugAssert.cpp389
1 files changed, 389 insertions, 0 deletions
diff --git a/deps/g3dlite/source/debugAssert.cpp b/deps/g3dlite/source/debugAssert.cpp
new file mode 100644
index 0000000000..41aad02c64
--- /dev/null
+++ b/deps/g3dlite/source/debugAssert.cpp
@@ -0,0 +1,389 @@
+/**
+ @file debugAssert.cpp
+
+ Windows implementation of assertion routines.
+
+ @maintainer Morgan McGuire, graphics3d.com
+
+ @created 2001-08-26
+ @edited 2009-06-02
+ */
+
+#include "G3D/debugAssert.h"
+#include "G3D/platform.h"
+#ifdef G3D_WIN32
+ #include <tchar.h>
+#endif
+#include "G3D/format.h"
+#include "G3D/prompt.h"
+#include <string>
+#include "G3D/debugPrintf.h"
+#include "G3D/Log.h"
+
+#include <cstdlib>
+
+#ifdef _MSC_VER
+ // disable: "C++ exception handler used"
+# pragma warning (push)
+# pragma warning (disable : 4530)
+#endif
+
+using namespace std;
+
+namespace G3D { namespace _internal {
+
+ConsolePrintHook _consolePrintHook;
+AssertionHook _debugHook = _handleDebugAssert_;
+AssertionHook _failureHook = _handleErrorCheck_;
+
+#ifdef G3D_LINUX
+#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
+ Display* x11Display = NULL;
+ Window x11Window = 0;
+#endif
+#endif
+
+
+#ifdef G3D_WIN32
+static void postToClipboard(const char *text) {
+ if (OpenClipboard(NULL)) {
+ HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(text) + 1);
+ if (hMem) {
+ char *pMem = (char*)GlobalLock(hMem);
+ strcpy(pMem, text);
+ GlobalUnlock(hMem);
+
+ EmptyClipboard();
+ SetClipboardData(CF_TEXT, hMem);
+ }
+
+ CloseClipboard();
+ GlobalFree(hMem);
+ }
+}
+#endif
+
+/**
+ outTitle should be set before the call
+ */
+static void createErrorMessage(
+ const char* expression,
+ const std::string& message,
+ const char* filename,
+ int lineNumber,
+ std::string& outTitle,
+ std::string& outMessage) {
+
+ std::string le = "";
+ const char* newline = "\n";
+
+ #ifdef G3D_WIN32
+ newline = "\r\n";
+
+ // The last error value. (Which is preserved across the call).
+ DWORD lastErr = GetLastError();
+
+ // The decoded message from FormatMessage
+ LPTSTR formatMsg = NULL;
+
+ if (NULL == formatMsg) {
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lastErr,
+ 0,
+ (LPTSTR)&formatMsg,
+ 0,
+ NULL);
+ }
+
+ // Make sure the message got translated into something.
+ LPTSTR realLastErr;
+ if (NULL != formatMsg) {
+ realLastErr = formatMsg;
+ } else {
+ realLastErr = _T("Last error code does not exist.");
+ }
+
+ if (lastErr != 0) {
+ le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
+ }
+
+ // Get rid of the allocated memory from FormatMessage.
+ if (NULL != formatMsg) {
+ LocalFree((LPVOID)formatMsg);
+ }
+
+ char modulePath[MAX_PATH];
+ GetModuleFileNameA(NULL, modulePath, MAX_PATH);
+
+ const char* moduleName = strrchr(modulePath, '\\');
+ outTitle = outTitle + string(" - ") + string(moduleName ? (moduleName + 1) : modulePath);
+
+ #endif
+
+ // Build the message.
+ outMessage =
+ G3D::format("%s%s%sExpression: %s%s%s:%d%s%s%s",
+ message.c_str(), newline, newline, expression, newline,
+ filename, lineNumber, newline, newline, le.c_str());
+}
+
+
+bool _handleDebugAssert_(
+ const char* expression,
+ const std::string& message,
+ const char* filename,
+ int lineNumber,
+ bool useGuiPrompt) {
+
+ std::string dialogTitle = "Assertion Failure";
+ std::string dialogText = "";
+ createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
+
+ #ifdef G3D_WIN32
+ DWORD lastErr = GetLastError();
+ postToClipboard(dialogText.c_str());
+ debugPrintf("\n%s\n", dialogText.c_str());
+ #endif
+
+ const int cBreak = 0;
+ const int cIgnore = 1;
+ const int cAbort = 2;
+
+ static const char* choices[] = {"Debug", "Ignore", "Exit"};
+
+ // Log the error
+ Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
+
+ int result = G3D::prompt(dialogTitle.c_str(), dialogText.c_str(), (const char**)choices, 3, useGuiPrompt);
+
+# ifdef G3D_WIN32
+ // Put the incoming last error back.
+ SetLastError(lastErr);
+# endif
+
+ switch (result) {
+ // -1 shouldn't actually occur because it means
+ // that we're in release mode.
+ case -1:
+ case cBreak:
+ return true;
+ break;
+
+ case cIgnore:
+ return false;
+ break;
+
+ case cAbort:
+ exit(-1);
+ break;
+ }
+
+ // Should never get here
+ return false;
+}
+
+
+bool _handleErrorCheck_(
+ const char* expression,
+ const std::string& message,
+ const char* filename,
+ int lineNumber,
+ bool useGuiPrompt) {
+
+ std::string dialogTitle = "Critical Error";
+ std::string dialogText = "";
+
+ createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
+
+ // Log the error
+ Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
+ #ifdef G3D_WIN32
+ DWORD lastErr = GetLastError();
+ (void)lastErr;
+ postToClipboard(dialogText.c_str());
+ debugPrintf("\n%s\n", dialogText.c_str());
+ #endif
+
+ static const char* choices[] = {"Ok"};
+
+ const std::string& m =
+ std::string("An internal error has occured in this program and it will now close. "
+ "The specific error is below. More information has been saved in \"") +
+ Log::getCommonLogFilename() + "\".\n" + dialogText;
+
+ int result = G3D::prompt("Error", m.c_str(), (const char**)choices, 1, useGuiPrompt);
+ (void)result;
+
+ return true;
+}
+
+
+#ifdef G3D_WIN32
+static HCURSOR oldCursor;
+static RECT oldCursorRect;
+static POINT oldCursorPos;
+static int oldShowCursorCount;
+#endif
+
+void _releaseInputGrab_() {
+ #ifdef G3D_WIN32
+
+ GetCursorPos(&oldCursorPos);
+
+ // Stop hiding the cursor if the application hid it.
+ oldShowCursorCount = ShowCursor(true) - 1;
+
+ if (oldShowCursorCount < -1) {
+ for (int c = oldShowCursorCount; c < -1; ++c) {
+ ShowCursor(true);
+ }
+ }
+
+ // Set the default cursor in case the application
+ // set the cursor to NULL.
+ oldCursor = GetCursor();
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+ // Allow the cursor full access to the screen
+ GetClipCursor(&oldCursorRect);
+ ClipCursor(NULL);
+
+ #elif defined(G3D_LINUX)
+#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
+ if (x11Display != NULL) {
+ XUngrabPointer(x11Display, CurrentTime);
+ XUngrabKeyboard(x11Display, CurrentTime);
+ if (x11Window != 0) {
+ //XUndefineCursor(x11Display, x11Window);
+ // TODO: Note that we leak this cursor; it should be
+ // freed in the restore code.
+ Cursor c = XCreateFontCursor(x11Display, 68);
+ XDefineCursor(x11Display, x11Window, c);
+ }
+ XSync(x11Display, false);
+ XAllowEvents(x11Display, AsyncPointer, CurrentTime);
+ XFlush(x11Display);
+ }
+#endif
+ #elif defined(G3D_OSX)
+ // TODO: OS X
+ #endif
+}
+
+
+void _restoreInputGrab_() {
+ #ifdef G3D_WIN32
+
+ // Restore the old clipping region
+ ClipCursor(&oldCursorRect);
+
+ SetCursorPos(oldCursorPos.x, oldCursorPos.y);
+
+ // Restore the old cursor
+ SetCursor(oldCursor);
+
+ // Restore old visibility count
+ if (oldShowCursorCount < 0) {
+ for (int c = 0; c > oldShowCursorCount; --c) {
+ ShowCursor(false);
+ }
+ }
+
+ #elif defined(G3D_LINUX)
+ // TODO: Linux
+ #elif defined(G3D_OSX)
+ // TODO: OS X
+ #endif
+}
+
+
+}; // internal namespace
+
+void setAssertionHook(AssertionHook hook) {
+ G3D::_internal::_debugHook = hook;
+}
+
+AssertionHook assertionHook() {
+ return G3D::_internal::_debugHook;
+}
+
+void setFailureHook(AssertionHook hook) {
+ G3D::_internal::_failureHook = hook;
+}
+
+AssertionHook failureHook() {
+ return G3D::_internal::_failureHook;
+}
+
+
+void setConsolePrintHook(ConsolePrintHook h) {
+ G3D::_internal::_consolePrintHook = h;
+}
+
+ConsolePrintHook consolePrintHook() {
+ return G3D::_internal::_consolePrintHook;
+}
+
+
+std::string __cdecl debugPrint(const std::string& s) {
+# ifdef G3D_WIN32
+ const int MAX_STRING_LEN = 1024;
+
+ // Windows can't handle really long strings sent to
+ // the console, so we break the string.
+ if (s.size() < MAX_STRING_LEN) {
+ OutputDebugStringA(s.c_str());
+ } else {
+ for (unsigned int i = 0; i < s.size(); i += MAX_STRING_LEN) {
+ std::string sub = s.substr(i, MAX_STRING_LEN);
+ OutputDebugStringA(sub.c_str());
+ }
+ }
+# else
+ fprintf(stderr, "%s", s.c_str());
+ fflush(stderr);
+# endif
+
+ return s;
+}
+
+std::string __cdecl debugPrintf(const char* fmt ...) {
+ va_list argList;
+ va_start(argList, fmt);
+ std::string s = G3D::vformat(fmt, argList);
+ va_end(argList);
+
+ return debugPrint(s);
+// return debugPrint(consolePrint(s));
+}
+
+std::string consolePrint(const std::string& s) {
+ FILE* L = Log::common()->getFile();
+ fprintf(L, "%s", s.c_str());
+
+ if (consolePrintHook()) {
+ consolePrintHook()(s);
+ }
+
+ fflush(L);
+ return s;
+}
+
+
+std::string __cdecl consolePrintf(const char* fmt ...) {
+ va_list argList;
+ va_start(argList, fmt);
+ std::string s = G3D::vformat(fmt, argList);
+ va_end(argList);
+
+ return consolePrint(s);
+}
+
+} // namespace
+
+#ifdef _MSC_VER
+# pragma warning (pop)
+#endif