From 595dfe169eb0ad0dbddf24cf3f94b954718b3cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Thu, 21 Jul 2022 22:10:22 +0200 Subject: Simplify OnTerminate. No, not "awful", AWFUN! Speaking of AWFUN, here is an alternative implementation of it: #define AWFUN(t, f) cond_fun template std::enable_if_t, decltype(F)> cond_fun = F; template auto cond_fun = G; This implementation uses a variable template instead of a function template, but I decided against it, as (at least I think) it would instantiate useless variables that merely point to pre-existing API functions. Like, auto cond_fun__wchar_t__blablabla = MessageBoxW; auto cond_fun__char__blablabla = MessageBoxA; which is quite useless. Better to just have a constexpr function, which the compiler may inline, return the real function pointer. --- c/common.h | 13 +++++++++++++ c/main.cpp | 36 +++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/c/common.h b/c/common.h index 0343914..4b42f45 100644 --- a/c/common.h +++ b/c/common.h @@ -74,6 +74,19 @@ inline T prefer(const T x) return x; } +/* Conditionally select between ANSI and wide string literal. */ +#define AWTEXT(t, s) cond_text(s, L"" s) +template constexpr const T* cond_text(const char*, const wchar_t*); +template <> constexpr const char* cond_text(const char* sz, const wchar_t*) { return sz; } +template <> constexpr const wchar_t* cond_text(const char*, const wchar_t* wsz) { return wsz; } + +/* Conditionally select between ANSI and wide Windows API function. */ +#define AWFUN(t, f) cond_fun() +template +constexpr std::enable_if_t, decltype(F)> cond_fun() { return F; } +template +constexpr std::enable_if_t, decltype(G)> cond_fun() { return G; } + /* Return integer scaled for current DPI. */ inline int Dpi(const int i) { diff --git a/c/main.cpp b/c/main.cpp index c426c65..4f31e7b 100644 --- a/c/main.cpp +++ b/c/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -46,30 +47,35 @@ static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); static void UpdateTheme(); +template +void TerminateMsg(const T* sz1, const T* sz2) noexcept +{ + std::basic_ostringstream ss; + ss << AWTEXT(T, "Episode Browser was terminated due to "); + ss << sz1; + if (sz2) + ss << ": " << sz2; + else + ss << "."; + AWFUN(T, MessageBox)((HWND)NULL, ss.str().c_str(), AWTEXT(T, "Fatal Error"), MB_ICONERROR); +} + void OnTerminate() noexcept { try { std::rethrow_exception(std::current_exception()); } catch (const term_t& t) { - std::basic_string tstr = TEXT("Episode Browser was terminated due to a Prolog exception: "); TCHAR* tsz; - if (PL_get_tchars(t, &tsz, CVT_WRITE)) { - tstr += tsz; - MessageBox(NULL, tstr.c_str(), TEXT("Fatal Error"), MB_ICONERROR); - } else - MessageBoxA(NULL, "Episode Browser was terminated due to a Prolog exception.", - "Fatal Error", MB_ICONERROR); + if (PL_get_tchars(t, &tsz, CVT_WRITE)) + TerminateMsg(TEXT("a Prolog exception"), tsz); + else + TerminateMsg("a Prolog exception", NULL); } catch (Win32Error& e) { - std::basic_string tstr = TEXT("Episode Browser was terminated due to a Windows error: "); - tstr += e.what(); - MessageBox(NULL, tstr.c_str(), TEXT("Fatal Error"), MB_ICONERROR); + TerminateMsg(TEXT("a Windows error"), e.what()); } catch (std::exception& e) { - std::string str = "Episode Browser was terminated due to an exception: "; - str += e.what(); - MessageBoxA(NULL, str.c_str(), "Fatal Error", MB_ICONERROR); + TerminateMsg("an exception", e.what()); } catch (...) { - MessageBoxA(NULL, "Episode Browser was terminated due to an exception.", - "Fatal Error", MB_ICONERROR); + TerminateMsg("an exception", NULL); } _Exit(1); } -- cgit v1.2.3