aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-09-02 23:51:40 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-09-02 23:51:40 +0200
commit00447478cd1d0d64752114df49fee5ee8bdcedbe (patch)
treeca1168b19ab977c1857d3a3e341a3e80b33cc6d3
parentff9ba3f6e60fa30f52dd94e48214be5e1be1b28a (diff)
downloadEpisodeBrowser-00447478cd1d0d64752114df49fee5ee8bdcedbe.tar.gz
Add Act.
-rw-r--r--README8
-rw-r--r--c/data.cpp9
-rw-r--r--c/data.h1
-rw-r--r--c/datalistview.cpp2
-rw-r--r--c/datalistview.h2
-rw-r--r--c/listview.cpp2
-rw-r--r--c/listview.h6
-rw-r--r--c/main.cpp11
-rw-r--r--c/test.cpp3
-rw-r--r--c/util.h2
-rw-r--r--c/win32.cpp21
-rw-r--r--c/win32.h3
-rw-r--r--c/window.h2
13 files changed, 50 insertions, 22 deletions
diff --git a/README b/README
index c26ab24..ff7a892 100644
--- a/README
+++ b/README
@@ -60,7 +60,7 @@ To build Episode Browser, the following programs are required:
Furthermore, the following dependencies are required:
- - libxml2 (included with MSYS GCC)
+ - libxml2 (included with MSYS GCC, downloaded separately for MSVC)
You may need to manually provide library and header file directories
in c/CMakeLists.txt.
@@ -69,7 +69,9 @@ Episode Browse may be built by issuing `make' from the root directory.
The build process is controlled by a few environment variables:
- SYSTEM = vs2019 (default) or mingw
- - CONFIG = Debug (default) or Release
+ - VS_CONFIG = Debug (default) or Release
+ - VS_TOOLSET = v142 (default), v141_xp (for Windows XP support)
+ - VS_PLATFORM = x64 (default) or Win32 (32-bit x86)
Hacking
~~~~~~~
@@ -98,3 +100,5 @@ without NUL, `len' is used.
While specific Hungarian prefixes are unnecessary for most variables,
"natural" word order should be avoided. In other words, lenString is
preferred over stringLen, because it mirrors vString.
+
+Hungarian notation should not be used for type names.
diff --git a/c/data.cpp b/c/data.cpp
index b1c028e..62d544a 100644
--- a/c/data.cpp
+++ b/c/data.cpp
@@ -125,7 +125,7 @@ void WaitFor(Window& window, void (*f)(unsigned char*))
sig |= DONE;
} catch (...) {
sig |= DONE;
- ShowException(L"Remote data could not be fetched due to an error: %s",
+ ShowException(L"Remote data could not be fetched due to an error while %s: %s",
L"Error", MB_ICONWARNING);
}
};
@@ -155,6 +155,8 @@ void WaitFor(Window& window, void (*f)(unsigned char*))
void FetchData(unsigned char* sig)
{
+ Act(L"fetching and parsing general episode data");
+
/* The remote data is retrieved using WinINet from the
* Detective Conan World wiki. Using libxml2's "push parser",
* the HTML is parsed piece by piece as it is retrieved. The
@@ -181,6 +183,8 @@ void FetchData(unsigned char* sig)
if (!nodes || !nodes->nodeNr)
throw std::runtime_error("could not find remote episode information");
+ Act(L"inserting remote data");
+
for (int i = 0; i < nodes->nodeNr; i++) {
if (*sig & ABORT)
return;
@@ -222,6 +226,8 @@ void FetchData(unsigned char* sig)
void FetchScreenwriters(unsigned char* sig)
{
+ Act(L"fetching and parsing screenwriter data");
+
/* Screenwriters are expensive to fetch, so we try to avoid
* fetching screenwriters for episodes that already have a
* screenwriter. Additionally, in the same session, we don't
@@ -262,7 +268,6 @@ void FetchScreenwriters(unsigned char* sig)
Wcscpy(Buf(url)+Len(prefix), d.wiki);
/* Retrieve screenwriter from HTML. */
-
UniqueOk<htmlParserCtxtPtr, xmlFreeParserCtxt> ctx = RemoteParserCtxt(url, nullptr);
xpathCtx = xmlXPathNewContext(ctx.v->myDoc);
if (xpathCtx.Bad(0))
diff --git a/c/data.h b/c/data.h
index 919e1b4..2c287a2 100644
--- a/c/data.h
+++ b/c/data.h
@@ -74,6 +74,7 @@ struct CfgA
wchar_t root[260] = {0};
wchar_t glob[64] = {0};
wchar_t url[192] = {0};
+ wchar_t prefixUrl[48] = {0};
};
/* Variable template for obtaining the version of a given struct. */
diff --git a/c/datalistview.cpp b/c/datalistview.cpp
index 92fc05c..4ed3d41 100644
--- a/c/datalistview.cpp
+++ b/c/datalistview.cpp
@@ -30,7 +30,7 @@ DataListView::DataListView(Window& parent)
m_height = parent.cfg.heightDlv;
}
-int DataListView::Height()
+int DataListView::Height() noexcept
{
return m_height? m_height: ListView::Height();
}
diff --git a/c/datalistview.h b/c/datalistview.h
index 21d6f05..2593b49 100644
--- a/c/datalistview.h
+++ b/c/datalistview.h
@@ -12,7 +12,7 @@ struct DataListView : public ListView
DataListView(Window& parent);
/* Return manual height, if set, or calculate height
* appropriate for number of items. */
- int Height() override;
+ int Height() noexcept override;
void ResizeColumns(int w) override;
/* Set manual height. */
void SetHeight(int h);
diff --git a/c/listview.cpp b/c/listview.cpp
index 03a65ae..b638f7b 100644
--- a/c/listview.cpp
+++ b/c/listview.cpp
@@ -29,7 +29,7 @@ ListView::ListView(Window& parent, const HMENU hMenu, const DWORD dwStyle) : par
SendMessageW(hWnd, WM_SETFONT, reinterpret_cast<WPARAM>(g_hfNormal), MAKELPARAM(FALSE, 0));
}
-int ListView::Height()
+int ListView::Height() noexcept
{
const int cItem = ListView_GetItemCount(hWnd);
return Dpi(4)+cItem*Dpi(19);
diff --git a/c/listview.h b/c/listview.h
index 30164f7..ba3a115 100644
--- a/c/listview.h
+++ b/c/listview.h
@@ -13,9 +13,9 @@ struct ListView
ListView(Window& parent, HMENU hMenu, DWORD dwStyle);
/* Retrieve next matching list view item. */
- bool FindNextItem(LVITEM* lvi, LPARAM lParam);
+ bool FindNextItem(LVITEM* lvi, LPARAM lParam) noexcept;
/* Naively calculate height appropriate for number of items. */
- virtual int Height();
+ virtual int Height() noexcept;
/* Update column widths on window size change (unimplemented
* by default). */
virtual void ResizeColumns(int w);
@@ -26,7 +26,7 @@ protected:
WNDPROC m_proc0;
};
-inline bool ListView::FindNextItem(LVITEM* const lvi, const LPARAM lParam)
+inline bool ListView::FindNextItem(LVITEM* const lvi, const LPARAM lParam) noexcept
{
if ((lvi->iItem = ListView_GetNextItem(hWnd, lvi->iItem, lParam)) == -1)
return false;
diff --git a/c/main.cpp b/c/main.cpp
index ea12db9..82cda68 100644
--- a/c/main.cpp
+++ b/c/main.cpp
@@ -124,11 +124,13 @@ static void InitializeMainWindow_(const HWND hWnd)
* initializes global variables that are used by WndProc. */
/* Look up DPI. */
+ Act(L"looking up DPI");
if (auto lib = Library::Maybe(L"User32.dll");
auto GetDpiForWindow = lib? lib->GetProcAddress<UINT(HWND)>("GetDpiForWindow"): nullptr)
g_dpi = GetDpiForWindow(hWnd);
/* Load normal font. */
+ Act(L"loading fonts");
if (auto lib = Library::Maybe(L"User32.dll");
lib && lib->GetProcAddress<void>("SystemParametersInfoW")) {
NONCLIENTMETRICSW m = {sizeof(NONCLIENTMETRICSW)};
@@ -156,6 +158,7 @@ static void InitializeMainWindow_(const HWND hWnd)
SetWindowTheme = (decltype(SetWindowTheme))(void*)GetProcAddress(hModule, "SetWindowTheme");
}
+ Act(L"setting up main window");
g_window = new Window(hWnd);
}
@@ -164,17 +167,18 @@ void InitializeMainWindow(const HWND hWnd) noexcept
try {
InitializeMainWindow_(hWnd);
} catch (...) {
- ShowException(L"Initialization failed due to an error: %s");
+ ShowException(L"Initialization failed due to an error while %s: %s");
exit(1);
}
}
LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
+ Act(nullptr);
try {
return g_window->WndProc(hWnd, uMsg, wParam, lParam);
} catch (...) {
- ShowException(L"The action was cancelled due to an error: %s");
+ ShowException(L"The action was cancelled due to an error while %s: %s");
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
@@ -200,6 +204,7 @@ LRESULT CALLBACK Window::WndProc(const HWND hWnd, const UINT uMsg, const WPARAM
{
switch (uMsg) {
case WM_CREATE:
+ Act(L"creating main window");
UpdateTheme();
SetWindowPos(hWnd, nullptr, -1, -1, Dpi(510), Dpi(412), SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
SetFocus(elv.hWnd);
@@ -426,7 +431,7 @@ void Window::HandleMainMenu(const HWND hWnd, const WORD command)
}
}
-void Window::Status(const wchar_t* msg, unsigned short i)
+void Window::Status(const wchar_t* msg, unsigned short i) noexcept
{
SendMessage(hWndStatus, SB_SETTEXT, MAKEWPARAM(i, 0), reinterpret_cast<LPARAM>(msg));
}
diff --git a/c/test.cpp b/c/test.cpp
index c0a9445..21f52f4 100644
--- a/c/test.cpp
+++ b/c/test.cpp
@@ -107,6 +107,7 @@ TESTS
// SCPY(root);
// SCPY(glob);
// SCPY(url);
+// SCPY(prefixUrl);
// #undef CPY
// #undef SCPY
@@ -120,7 +121,7 @@ int RunTests(Window& window)
const Test tests[] = {
StrcpyWithSmallerDestination(),
//IO(),
- //MigrateCfg(),
+ // MigrateCfg(),
};
printf("Results (%llu tests):\n", sizeof(tests)/sizeof(*tests));
diff --git a/c/util.h b/c/util.h
index eb2b2f8..da77ff9 100644
--- a/c/util.h
+++ b/c/util.h
@@ -15,7 +15,7 @@
std::set_terminate([]() noexcept \
{ \
ShowException( \
- L"Episode Browser was terminated due to an error: %s", \
+ L"Episode Browser was terminated due to an error while %s: %s", \
L"Fatal Error", MB_ICONERROR); \
_Exit(1); \
})
diff --git a/c/win32.cpp b/c/win32.cpp
index ce1fc9d..2686f2e 100644
--- a/c/win32.cpp
+++ b/c/win32.cpp
@@ -8,6 +8,8 @@
#include "win32.h"
#include "window.h"
+static thread_local const wchar_t* s_action;
+
std::wstring WideFromNarrow(const std::string_view src, const int cp)
{
int cchNarrow = src.length()+1;
@@ -93,23 +95,30 @@ int EBMessageBox(const std::wstring_view text, const std::wstring_view caption,
return MessageBox(hWnd, text.data(), caption.data(), uType);
}
+void Act(const wchar_t* action)
+{
+ s_action = action;
+}
+
void ShowException(const wchar_t* const fmt, const wchar_t* const title, const UINT uType) noexcept
{
+ if (!s_action)
+ s_action = L"performing an unknown action";
try {
std::rethrow_exception(std::current_exception());
} catch (const WideException& e) {
- std::wstring msg(wcslen(fmt)+wcslen(e.What()), 0);
- Swprintf(msg, fmt, e.What());
+ std::wstring msg(wcslen(fmt)+wcslen(s_action)+wcslen(e.What()), 0);
+ Swprintf(msg, fmt, s_action, e.What());
EBMessageBox(msg, title, uType);
} catch (const std::exception& e) {
std::wstring what = WideFromNarrow(e.what());
- std::wstring msg(wcslen(fmt)+what.length(), 0);
- Swprintf(msg, fmt, what.c_str());
+ std::wstring msg(wcslen(fmt)+wcslen(s_action)+what.length(), 0);
+ Swprintf(msg, fmt, s_action, what.c_str());
EBMessageBox(msg, title, uType);
} catch (...) {
const wchar_t* what = L"an unknown error occurred";
- std::wstring msg(wcslen(fmt)+wcslen(what), 0);
- Swprintf(msg, fmt, what);
+ std::wstring msg(wcslen(fmt)+wcslen(s_action)+wcslen(what), 0);
+ Swprintf(msg, fmt, s_action, what);
EBMessageBox(msg, title, uType);
}
}
diff --git a/c/win32.h b/c/win32.h
index c4e57b7..a88e97c 100644
--- a/c/win32.h
+++ b/c/win32.h
@@ -15,6 +15,9 @@ void WithNextWindow(void (*proc)(HWND));
/* Display message box centered in main window. */
int EBMessageBox(std::wstring_view text, std::wstring_view data, UINT uType);
+/* Specify current action (used by ShowException). */
+void Act(const wchar_t* action);
+
/* Show message box for current exception. */
void ShowException(
const wchar_t* fmt = L"An error occurred: %s",
diff --git a/c/window.h b/c/window.h
index 5cdffe4..2c81194 100644
--- a/c/window.h
+++ b/c/window.h
@@ -41,7 +41,7 @@ struct Window
void HandleMainMenu(HWND, WORD);
/* Display text in status bar. */
- void Status(const wchar_t* msg, unsigned short i = 0);
+ void Status(const wchar_t* msg, unsigned short i = 0) noexcept;
/* Try to style application according to current Windows theme. */
void UpdateTheme();