Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Switched assert system to use new message box functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Oct 31, 2012
1 parent adae3e0 commit cc331e6
Showing 1 changed file with 75 additions and 190 deletions.
265 changes: 75 additions & 190 deletions src/SDL_assert.c
Expand Up @@ -22,6 +22,8 @@

#include "SDL.h"
#include "SDL_atomic.h"
#include "SDL_messagebox.h"
#include "SDL_video.h"
#include "SDL_assert.h"
#include "SDL_assert_c.h"
#include "video/SDL_sysvideo.h"
Expand Down Expand Up @@ -59,160 +61,13 @@ debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
static void
debug_print(const char *fmt, ...)
{
#ifdef __WIN32__
/* Format into a buffer for OutputDebugStringA(). */
char buf[1024];
char *startptr;
char *ptr;
LPTSTR tstr;
int len;
va_list ap;
va_start(ap, fmt);
len = (int) SDL_vsnprintf(buf, sizeof (buf), fmt, ap);
va_end(ap);

/* Visual C's vsnprintf() may not null-terminate the buffer. */
if ((len >= sizeof (buf)) || (len < 0)) {
buf[sizeof (buf) - 1] = '\0';
}

/* Write it, sorting out the Unix newlines... */
startptr = buf;
for (ptr = startptr; *ptr; ptr++) {
if (*ptr == '\n') {
*ptr = '\0';
tstr = WIN_UTF8ToString(startptr);
OutputDebugString(tstr);
SDL_free(tstr);
OutputDebugString(TEXT("\r\n"));
startptr = ptr+1;
}
}

/* catch that last piece if it didn't have a newline... */
if (startptr != ptr) {
tstr = WIN_UTF8ToString(startptr);
OutputDebugString(tstr);
SDL_free(tstr);
}
#else
/* Unix has it easy. Just dump it to stderr. */
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
SDL_LogMessageV(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_WARN, fmt, ap);
va_end(ap);
fflush(stderr);
#endif
}


#ifdef __WIN32__
static SDL_assert_state SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT;
static const SDL_assert_data *SDL_Windows_AssertData = NULL;

static LRESULT CALLBACK
SDL_Assertion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
/* !!! FIXME: all this code stinks. */
const SDL_assert_data *data = SDL_Windows_AssertData;
char buf[1024];
LPTSTR tstr;
const int w = 100;
const int h = 25;
const int gap = 10;
int x = gap;
int y = 50;
int len;
int i;
static const struct {
LPCTSTR name;
SDL_assert_state state;
} buttons[] = {
{TEXT("Abort"), SDL_ASSERTION_ABORT },
{TEXT("Break"), SDL_ASSERTION_BREAK },
{TEXT("Retry"), SDL_ASSERTION_RETRY },
{TEXT("Ignore"), SDL_ASSERTION_IGNORE },
{TEXT("Always Ignore"), SDL_ASSERTION_ALWAYS_IGNORE },
};

len = (int) SDL_snprintf(buf, sizeof (buf),
"Assertion failure at %s (%s:%d), triggered %u time%s:\r\n '%s'",
data->function, data->filename, data->linenum,
data->trigger_count, (data->trigger_count == 1) ? "" : "s",
data->condition);
if ((len < 0) || (len >= sizeof (buf))) {
buf[sizeof (buf) - 1] = '\0';
}

tstr = WIN_UTF8ToString(buf);
CreateWindow(TEXT("STATIC"), tstr,
WS_VISIBLE | WS_CHILD | SS_LEFT,
x, y, 550, 100,
hwnd, (HMENU) 1, NULL, NULL);
SDL_free(tstr);
y += 110;

for (i = 0; i < (sizeof (buttons) / sizeof (buttons[0])); i++) {
CreateWindow(TEXT("BUTTON"), buttons[i].name,
WS_VISIBLE | WS_CHILD,
x, y, w, h,
hwnd, (HMENU) buttons[i].state, NULL, NULL);
x += w + gap;
}
break;
}

case WM_COMMAND:
SDL_Windows_AssertChoice = ((SDL_assert_state) (LOWORD(wParam)));
SDL_Windows_AssertData = NULL;
break;

case WM_DESTROY:
SDL_Windows_AssertData = NULL;
break;
}

return DefWindowProc(hwnd, msg, wParam, lParam);
}

static SDL_assert_state
SDL_PromptAssertion_windows(const SDL_assert_data *data)
{
HINSTANCE hInstance = 0; /* !!! FIXME? */
HWND hwnd;
MSG msg;
WNDCLASS wc = {0};

SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT;
SDL_Windows_AssertData = data;

wc.lpszClassName = TEXT("SDL_assert");
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = SDL_Assertion_WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);

RegisterClass(&wc);
hwnd = CreateWindow(wc.lpszClassName, TEXT("SDL assertion failure"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
150, 150, 570, 260, 0, 0, hInstance, 0);

while (GetMessage(&msg, NULL, 0, 0) && (SDL_Windows_AssertData != NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

DestroyWindow(hwnd);
UnregisterClass(wc.lpszClassName, hInstance);
return SDL_Windows_AssertChoice;
}
#endif


static void SDL_AddAssertionToReport(SDL_assert_data *data)
{
/* (data) is always a static struct defined with the assert macros, so
Expand Down Expand Up @@ -274,20 +129,39 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
const char *envr;
SDL_assert_state state = SDL_ASSERTION_ABORT;
SDL_Window *window;
SDL_MessageBoxData messagebox;
SDL_MessageBoxButtonData buttons[] = {
{ 0, SDL_ASSERTION_RETRY, "Retry" },
{ 0, SDL_ASSERTION_BREAK, "Break" },
{ 0, SDL_ASSERTION_ABORT, "Abort" },
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
SDL_ASSERTION_IGNORE, "Ignore" },
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
SDL_ASSERTION_ALWAYS_IGNORE, "Always Ignore" }
};
char *message;
int selected;

(void) userdata; /* unused in default handler. */

debug_print("\n\n"
"Assertion failure at %s (%s:%d), triggered %u time%s:\n"
" '%s'\n"
"\n",
data->function, data->filename, data->linenum,
data->trigger_count, (data->trigger_count == 1) ? "" : "s",
data->condition);
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (!message) {
/* Uh oh, we're in real trouble now... */
return SDL_ASSERTION_ABORT;
}
SDL_snprintf(message, SDL_MAX_LOG_MESSAGE,
"Assertion failure at %s (%s:%d), triggered %u %s:\r\n '%s'",
data->function, data->filename, data->linenum,
data->trigger_count, (data->trigger_count == 1) ? "time" : "times",
data->condition);

debug_print("\n\n%s\n\n", message);

/* let env. variable override, so unit tests won't block in a GUI. */
envr = SDL_getenv("SDL_ASSERT");
if (envr != NULL) {
SDL_stack_free(message);

if (SDL_strcmp(envr, "abort") == 0) {
return SDL_ASSERTION_ABORT;
} else if (SDL_strcmp(envr, "break") == 0) {
Expand All @@ -311,54 +185,65 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
} else {
/* !!! FIXME: ungrab the input if we're not fullscreen? */
/* No need to mess with the window */
window = 0;
window = NULL;
}
}

/* platform-specific UI... */

#ifdef __WIN32__
state = SDL_PromptAssertion_windows(data);

#elif defined __MACOSX__ && defined SDL_VIDEO_DRIVER_COCOA
/* This has to be done in an Objective-C (*.m) file, so we call out. */
extern SDL_assert_state SDL_PromptAssertion_cocoa(const SDL_assert_data *);
state = SDL_PromptAssertion_cocoa(data);

#else
/* this is a little hacky. */
for ( ; ; ) {
char buf[32];
fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : ");
fflush(stderr);
if (fgets(buf, sizeof (buf), stdin) == NULL) {
break;
/* Show a messagebox if we can, otherwise fall back to stdio */
SDL_zero(messagebox);
messagebox.flags = SDL_MESSAGEBOX_WARNING;
messagebox.window = window;
messagebox.title = "Assertion Failed";
messagebox.message = message;
messagebox.numbuttons = SDL_arraysize(buttons);
messagebox.buttons = buttons;

if (SDL_ShowMessageBox(&messagebox, &selected) == 0) {
if (selected == -1) {
state = SDL_ASSERTION_IGNORE;
} else {
state = (SDL_assert_state)selected;
}
}
#ifdef HAVE_STDIO_H
else
{
/* this is a little hacky. */
for ( ; ; ) {
char buf[32];
fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : ");
fflush(stderr);
if (fgets(buf, sizeof (buf), stdin) == NULL) {
break;
}

if (SDL_strcmp(buf, "a") == 0) {
state = SDL_ASSERTION_ABORT;
break;
} else if (SDL_strcmp(buf, "b") == 0) {
state = SDL_ASSERTION_BREAK;
break;
} else if (SDL_strcmp(buf, "r") == 0) {
state = SDL_ASSERTION_RETRY;
break;
} else if (SDL_strcmp(buf, "i") == 0) {
state = SDL_ASSERTION_IGNORE;
break;
} else if (SDL_strcmp(buf, "A") == 0) {
state = SDL_ASSERTION_ALWAYS_IGNORE;
break;
if (SDL_strcmp(buf, "a") == 0) {
state = SDL_ASSERTION_ABORT;
break;
} else if (SDL_strcmp(buf, "b") == 0) {
state = SDL_ASSERTION_BREAK;
break;
} else if (SDL_strcmp(buf, "r") == 0) {
state = SDL_ASSERTION_RETRY;
break;
} else if (SDL_strcmp(buf, "i") == 0) {
state = SDL_ASSERTION_IGNORE;
break;
} else if (SDL_strcmp(buf, "A") == 0) {
state = SDL_ASSERTION_ALWAYS_IGNORE;
break;
}
}
}
#endif
#endif /* HAVE_STDIO_H */

/* Re-enter fullscreen mode */
if (window) {
SDL_RestoreWindow(window);
}

SDL_stack_free(message);

return state;
}

Expand Down

0 comments on commit cc331e6

Please sign in to comment.