11#include " stdafx.h"
22#pragma hdrstop
33
4+ #include < SDL.h>
5+ #include < SDL_syswm.h>
6+
47#include " xrDebug.h"
58#include " os_clipboard.h"
69#include " log.h"
@@ -58,11 +61,11 @@ static BOOL bException = FALSE;
5861#endif
5962
6063#if defined XR_X64
61- # define MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64
64+ #define MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64
6265#elif defined XR_X86
63- # define MACHINE_TYPE IMAGE_FILE_MACHINE_I386
66+ #define MACHINE_TYPE IMAGE_FILE_MACHINE_I386
6467#else
65- # error CPU architecture is not supported.
68+ #error CPU architecture is not supported.
6669#endif
6770
6871namespace
@@ -92,6 +95,83 @@ ICN void* GetInstructionPtr()
9295}
9396}
9497
98+ enum MessageBoxResult
99+ {
100+ resultUndefined = -1 ,
101+ resultContinue = 0 ,
102+ resultTryAgain = 1 ,
103+ resultCancel = 2
104+ };
105+
106+ constexpr SDL_MessageBoxButtonData buttons[] =
107+ {
108+ /* .flags, .buttonid, .text */
109+ { 0 , resultContinue, " Continue" },
110+ { 0 , resultTryAgain, " Try again" },
111+ { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT |
112+ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
113+ resultCancel, " Cancel" }
114+ };
115+
116+ SDL_MessageBoxData messageboxdata =
117+ {
118+ SDL_MESSAGEBOX_ERROR,
119+ nullptr ,
120+ " Fatal error" ,
121+ " Vse clomalocb, tashite novyy dvizhok" ,
122+ SDL_arraysize (buttons),
123+ buttons,
124+ nullptr
125+ };
126+
127+ int xrDebug::ShowMessage (pcstr title, pcstr message, bool simple)
128+ {
129+ #ifdef WINDOWS // because Windows default Message box is fancy
130+ HWND hwnd = nullptr ;
131+
132+ if (applicationWindow)
133+ {
134+ SDL_SysWMinfo info;
135+ SDL_VERSION (&info.version );
136+ if (SDL_GetWindowWMInfo (applicationWindow, &info))
137+ {
138+ switch (info.subsystem )
139+ {
140+ case SDL_SYSWM_WINDOWS:
141+ hwnd = info.info .win .window ;
142+ break ;
143+ default : break ;
144+ }
145+ }
146+ }
147+
148+ if (simple)
149+ return MessageBox (hwnd, message, title, MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
150+
151+ const int result = MessageBox (hwnd, message, title,
152+ MB_CANCELTRYCONTINUE | MB_ICONERROR | MB_SYSTEMMODAL);
153+
154+ switch (result)
155+ {
156+ case IDCANCEL: return resultCancel;
157+ case IDTRYAGAIN: return resultTryAgain;
158+ case IDCONTINUE: return resultContinue;
159+ default : return resultUndefined;
160+ }
161+ #else
162+ if (simple)
163+ return SDL_ShowSimpleMessageBox (SDL_MESSAGEBOX_ERROR, title, message, applicationWindow);
164+
165+ messageboxdata.window = applicationWindow;
166+ messageboxdata.title = title;
167+ messageboxdata.message = message;
168+ int button = resultUndefined;
169+ SDL_ShowMessageBox (&messageboxdata, &button);
170+ return button;
171+ #endif
172+ }
173+
174+ SDL_Window* xrDebug::applicationWindow = nullptr ;
95175xrDebug::UnhandledExceptionFilter xrDebug::PrevFilter = nullptr ;
96176xrDebug::OutOfMemoryCallbackFunc xrDebug::OutOfMemoryCallback = nullptr ;
97177xrDebug::CrashHandler xrDebug::OnCrash = nullptr ;
@@ -103,9 +183,9 @@ bool xrDebug::symEngineInitialized = false;
103183Lock xrDebug::dbgHelpLock;
104184
105185#if defined(WINDOWS)
106- void xrDebug::SetBugReportFile (const char * fileName) { strcpy_s (BugReportFile, fileName); }
186+ void xrDebug::SetBugReportFile (const char * fileName) { xr_strcpy (BugReportFile, fileName); }
107187#elif defined(LINUX)
108- void xrDebug::SetBugReportFile (const char * fileName) { strcpy_s (BugReportFile, 0 , fileName); }
188+ void xrDebug::SetBugReportFile (const char * fileName) { xr_strcpy (BugReportFile, 0 , fileName); }
109189#endif
110190
111191#if defined(WINDOWS)
@@ -245,7 +325,7 @@ xr_vector<xr_string> xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesC
245325 stackFrame.AddrFrame .Mode = AddrModeFlat;
246326 stackFrame.AddrFrame .Offset = threadCtx->Ebp ;
247327#else
248- # error CPU architecture is not supported.
328+ #error CPU architecture is not supported.
249329#endif
250330
251331 while (GetNextStackFrameString (&stackFrame, threadCtx, frameStr) && traceResult.size () <= maxFramesCount)
@@ -377,7 +457,7 @@ void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* exp
377457 string4096 assertionInfo;
378458 GatherInfo (assertionInfo, loc, expr, desc, arg1, arg2);
379459#ifdef USE_OWN_ERROR_MESSAGE_WINDOW
380- strcat (assertionInfo,
460+ xr_strcat (assertionInfo,
381461 " \r\n "
382462 " Press CANCEL to abort execution\r\n "
383463 " Press TRY AGAIN to continue execution\r\n "
@@ -389,25 +469,29 @@ void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* exp
389469 if (OnDialog)
390470 OnDialog (true );
391471 FlushLog ();
392- #if defined(WINDOWS)
393472 if (Core.PluginMode )
394- MessageBox ( NULL , assertionInfo, " X-Ray error" , MB_OK | MB_ICONERROR | MB_SYSTEMMODAL );
473+ ShowMessage ( " X-Ray error" , assertionInfo );
395474 else
396475 {
397476#ifdef USE_OWN_ERROR_MESSAGE_WINDOW
398- int result = MessageBox (NULL , assertionInfo, " Fatal error" ,
399- MB_CANCELTRYCONTINUE | MB_ICONERROR | MB_SYSTEMMODAL);
400- switch (result)
477+ switch (ShowMessage (" Fatal error" , assertionInfo, false ))
401478 {
402- case IDCANCEL:
479+ case resultUndefined:
480+ xr_strcat (assertionInfo, SDL_GetError ());
481+ [[fallthrough]];
482+
483+ case resultCancel:
403484#ifdef USE_BUG_TRAP
404485 BT_SetUserMessage (assertionInfo);
405486#endif
406487 DEBUG_BREAK;
407488 break ;
408- case IDTRYAGAIN: ErrorAfterDialog = false ;
489+
490+ case resultTryAgain:
491+ ErrorAfterDialog = false ;
409492 break ;
410- case IDCONTINUE:
493+
494+ case resultContinue:
411495 ErrorAfterDialog = false ;
412496 ignoreAlways = true ;
413497 break ;
@@ -420,7 +504,6 @@ void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* exp
420504 DEBUG_BREAK;
421505#endif
422506 }
423- #endif
424507 if (OnDialog)
425508 OnDialog (false );
426509
@@ -436,8 +519,8 @@ void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* exp
436519void xrDebug::DoExit (const std::string& message)
437520{
438521 FlushLog ();
522+ ShowMessage (" Error" , message.c_str ());
439523#if defined(WINDOWS)
440- MessageBox (NULL , message.c_str (), " Error" , MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
441524 TerminateProcess (GetCurrentProcess (), 1 );
442525#endif
443526}
@@ -491,13 +574,13 @@ void WINAPI xrDebug::PreErrorHandler(INT_PTR)
491574 string256 currentDir;
492575 _getcwd (currentDir, sizeof (currentDir));
493576 string256 relDir;
494- strcpy_s (relDir, logDir);
577+ xr_strcpy (relDir, logDir);
495578 strconcat (sizeof (logDir), logDir, currentDir, " \\ " , relDir);
496579 }
497580 }
498581 __except (EXCEPTION_EXECUTE_HANDLER)
499582 {
500- strcpy_s (logDir, " logs" );
583+ xr_strcpy (logDir, " logs" );
501584 }
502585 string_path temp;
503586 strconcat (sizeof (temp), temp, logDir, log_name ());
@@ -573,7 +656,7 @@ void xrDebug::SaveMiniDump(EXCEPTION_POINTERS *exPtrs)
573656 __except (EXCEPTION_EXECUTE_HANDLER)
574657 {
575658 string_path temp;
576- strcpy_s (temp, dumpPath);
659+ xr_strcpy (temp, dumpPath);
577660 sprintf (dumpPath, " logs/%s" , temp);
578661 }
579662 WriteMiniDump (MINIDUMP_TYPE (MiniDumpFilterMemory | MiniDumpScanMemory), dumpPath, GetCurrentThreadId (), exPtrs);
@@ -628,7 +711,7 @@ LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS* exPtrs)
628711 {
629712 if (shared_str_initialized)
630713 Msg (" \n %s" , errMsg);
631- strcat (errMsg, " \r\n " );
714+ xr_strcat (errMsg, " \r\n " );
632715#ifdef DEBUG
633716 if (!IsDebuggerPresent ())
634717 os_clipboard::update_clipboard (buffer);
@@ -646,10 +729,9 @@ LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS* exPtrs)
646729 {
647730 if (OnDialog)
648731 OnDialog (true );
649- MessageBox (NULL ,
650- " Fatal error occurred\n\n "
651- " Press OK to abort program execution" ,
652- " Fatal error" , MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
732+ constexpr pcstr msg = " Fatal error occurred\n\n "
733+ " Press OK to abort program execution" ;
734+ ShowMessage (" Fatal error" , msg);
653735 }
654736#endif
655737 ReportFault (exPtrs, 0 );
@@ -671,11 +753,11 @@ void _terminate()
671753#if defined(WINDOWS)
672754 if (strstr (GetCommandLine (), " -silent_error_mode" ))
673755 exit (-1 );
756+ #endif
674757 string4096 assertionInfo;
675758 xrDebug::GatherInfo (assertionInfo, DEBUG_INFO, nullptr , " Unexpected application termination" );
676- strcat (assertionInfo, " Press OK to abort execution\r\n " );
677- MessageBox (GetTopWindow (NULL ), assertionInfo, " Fatal Error" , MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
678- #endif
759+ xr_strcat (assertionInfo, " Press OK to abort execution\r\n " );
760+ ShowMessage (" Fatal Error" , assertionInfo);
679761 exit (-1 );
680762}
681763#endif // USE_BUG_TRAP
0 commit comments