From 2ac7d06a503b256b290678f5bba158bf7d219bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Thu, 4 Aug 2022 16:26:27 +0200 Subject: Add comments. --- c/datalistview.h | 3 +++ c/debug.cpp | 2 +- c/debug.h | 10 +++++++++- c/episodelistview.cpp | 3 --- c/episodelistview.h | 3 +++ c/layout.h | 8 +++++++- c/listview.cpp | 14 ++++---------- c/listview.h | 12 ++++++++++++ c/main.cpp | 18 ++++++++++++------ c/pl.cpp | 11 ++--------- c/pl.h | 11 +++++++++-- c/util.h | 1 + c/win.cpp | 12 ++++++++---- c/win.h | 31 ++++++++++++++++++++----------- 14 files changed, 91 insertions(+), 48 deletions(-) diff --git a/c/datalistview.h b/c/datalistview.h index 5a4c7ca..26ba8c9 100644 --- a/c/datalistview.h +++ b/c/datalistview.h @@ -9,8 +9,11 @@ struct DataListView : public ListView { DataListView(HWND hWndParent); + /* Return manual height, if set, or calculate height + * appropriate for number of items. */ int Height() override; void ResizeColumns(int w) override; + /* Set manual height. */ void SetHeight(int h); void ShowEpisode(int iEpisode); private: diff --git a/c/debug.cpp b/c/debug.cpp index 934533b..35f8933 100644 --- a/c/debug.cpp +++ b/c/debug.cpp @@ -66,7 +66,7 @@ Benchmark::~Benchmark() } } -const char* MsgName(const unsigned uMsg) +const char* WmName(const unsigned uMsg) { static const unsigned vKey[] = { 0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, diff --git a/c/debug.h b/c/debug.h index 83ff289..f58c700 100644 --- a/c/debug.h +++ b/c/debug.h @@ -1,11 +1,18 @@ #ifndef DEBUG_H #define DEBUG_H +/* Benchmark objects measure and print the time in microseconds + * between construction and destruction. Given a unique id, they also + * calculate a running average of the last `avgmax' instances of + * objects of the same id. */ struct Benchmark { Benchmark(const char* name, int id, int avgmax); ~Benchmark(); + + /* Don't print time on destruction. */ void Disable(); + long long ticks; bool disabled = false; int id; @@ -13,6 +20,7 @@ struct Benchmark const char* name; }; -const char* MsgName(unsigned uMsg); +/* Return name of given window message (WM_*). */ +const char* WmName(unsigned uMsg); #endif diff --git a/c/episodelistview.cpp b/c/episodelistview.cpp index d35bebb..c22b109 100644 --- a/c/episodelistview.cpp +++ b/c/episodelistview.cpp @@ -189,7 +189,6 @@ void EpisodeListView::SetTop(const int iItem) ListView_EnsureVisible(hWnd, iItem, TRUE); } -/* Select next/previous unwatched episode. */ void EpisodeListView::SelectUnwatched(int dir) { /* Get focused episode. */ @@ -281,7 +280,6 @@ int CALLBACK EpisodeListView::SortProc(const LPARAM iItem1, const LPARAM iItem2, } } -/* Update episode list. */ void EpisodeListView::Update() { if (!Pl("episode_data","ensure_episode_data")) return; @@ -402,7 +400,6 @@ void EpisodeListView::Update() SendMessage(hWnd, WM_SETREDRAW, TRUE, 0); } -/* Update episode name and rating. */ void EpisodeListView::UpdateItem(const int iItem, const LPARAM lParam) { WcharPtr name; diff --git a/c/episodelistview.h b/c/episodelistview.h index 420d038..532c76c 100644 --- a/c/episodelistview.h +++ b/c/episodelistview.h @@ -20,10 +20,13 @@ struct EpisodeListView : public ListView void RestoreFocus(); void SaveFocus(); void SetTop(int iItem); + /* Select next/previous unwatched episode. */ void SelectUnwatched(int dir); void ShowFocus(); void Sort(); + /* Update episode list. */ void Update(); + /* Update episode name and rating. */ void UpdateItem(int iItem, LPARAM lParam); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) override; private: diff --git a/c/layout.h b/c/layout.h index da29d25..3c616b7 100644 --- a/c/layout.h +++ b/c/layout.h @@ -7,6 +7,8 @@ #include "pl.h" #include "win.h" +/* Given main window's width and height, set appropriate positions and + * sizes for child windows. */ void UpdateLayout(int w = 0, int h = 0); /* Dragger objects implement draggable portions of the client area, @@ -22,9 +24,10 @@ protected: bool IsDown(); bool IsDouble(); virtual bool InDragArea(int x, int y); + /* Perform drag, resizing relevant windows. */ virtual void Drag(int x, int y); + /* Called after drag, when mouse button is released. */ virtual void Done(); - /* Reset dragger to automatic position. */ virtual void Reset(); private: @@ -44,6 +47,9 @@ private: void Done() override; }; +/* Below follows the implementation of the non-virtual member + * functions of Dragger, on which derived objects rely. */ + inline bool Dragger::IsDouble() { const long time = GetMessageTime(); diff --git a/c/listview.cpp b/c/listview.cpp index bd92246..82c6df6 100644 --- a/c/listview.cpp +++ b/c/listview.cpp @@ -5,11 +5,14 @@ #include "layout.h" #include "win.h" -extern HFONT g_hfNormal; +/* Actual window procedure for all list views, which calls the + * appropriate WndProc member function. */ static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ListView::ListView(const HWND hWndParent, const HMENU hMenu, const DWORD dwStyle) { + extern HFONT g_hfNormal; + m_hWndParent = hWndParent; hWnd = Require(CreateWindowEx( WS_EX_CLIENTEDGE, @@ -25,15 +28,6 @@ ListView::ListView(const HWND hWndParent, const HMENU hMenu, const DWORD dwStyle SendMessage(hWnd, WM_SETFONT, (WPARAM)g_hfNormal, MAKELPARAM(FALSE, 0)); } -/* Retrieve next matching list view item. */ -bool ListView::FindNextItem(LVITEM* const lvi, const LPARAM lParam) -{ - if ((lvi->iItem = ListView_GetNextItem(hWnd, lvi->iItem, lParam)) == -1) - return false; - return ListView_GetItem(hWnd, lvi); -} - -/* Naively calculate height of list view. */ int ListView::Height() { const int cItem = ListView_GetItemCount(hWnd); diff --git a/c/listview.h b/c/listview.h index 1de6cc1..008f995 100644 --- a/c/listview.h +++ b/c/listview.h @@ -9,9 +9,14 @@ struct ListView HWND hWnd; ListView(HWND hWndParent, HMENU hMenu, DWORD dwStyle); + /* Retrieve next matching list view item. */ bool FindNextItem(LVITEM* lvi, LPARAM lParam); + /* Naively calculate height appropriate for number of items. */ virtual int Height(); + /* Update column widths on window size change (unimplemented + * by default). */ virtual void ResizeColumns(int w); + /* Enable/disable "modern" theme. */ virtual void UpdateTheme(BOOL bThemeActive); virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); protected: @@ -19,4 +24,11 @@ protected: HWND m_hWndParent; }; +inline bool ListView::FindNextItem(LVITEM* const lvi, const LPARAM lParam) +{ + if ((lvi->iItem = ListView_GetNextItem(hWnd, lvi->iItem, lParam)) == -1) + return false; + return ListView_GetItem(hWnd, lvi); +} + #endif diff --git a/c/main.cpp b/c/main.cpp index 24dd6da..7dcffa6 100644 --- a/c/main.cpp +++ b/c/main.cpp @@ -12,6 +12,10 @@ #include "pl.h" #include "util.h" +/* main.cpp defines all global (non-template) variables used in the + * program. `extern' is used to access them from other files, when + * need be. */ + /* Looked-up constants. */ int g_dpi = 96; @@ -47,12 +51,19 @@ char g_limitScreenwriter[64]; BOOL (*IsThemeActive)(); BOOL (*SetWindowTheme)(HWND, LPCWSTR, LPCWSTR); +/* Initialize important global state on parent window creation. */ static LRESULT CALLBACK CBTProc(int, WPARAM, LPARAM); +/* Process parent window commands. */ static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +/* Process main menu commands. */ static void HandleMainMenu(HWND, unsigned short); +/* Process context menu commands. */ static void HandleContextMenu(HWND, unsigned short); +/* Call Prolog predicate in other thread, if available. */ static void WaitFor(const char*, const char*); +/* Handle messages to Help > About dialog. */ static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); +/* Try to style application according to current Windows theme. */ static void UpdateTheme(); void OnTerminate() noexcept @@ -89,7 +100,7 @@ int WINAPI WinMain(const HINSTANCE hInstance, const HINSTANCE, char* const, cons std::set_terminate(OnTerminate); /* Initialize Prolog. */ - char* argv[] = { (char*)"EpisodeBrowser", NULL }; + char* argv[] = { const_cast("EpisodeBrowser"), NULL }; if (!PL_initialise(1, argv)) throw std::runtime_error("Could not initialize Prolog."); if (!Pl("track_episodes","attach") || !Pl("episode_data","attach")) @@ -367,7 +378,6 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, return 0; } -/* Process main menu commands. */ void HandleMainMenu(const HWND hWnd, unsigned short command) { switch (command) { @@ -434,7 +444,6 @@ void HandleMainMenu(const HWND hWnd, unsigned short command) } } -/* Process context menu commands. */ void HandleContextMenu(const HWND, unsigned short command) { int cNotFound = 0; @@ -493,7 +502,6 @@ void HandleContextMenu(const HWND, unsigned short command) } } -/* Call Prolog predicate in other thread, if available. */ void WaitFor(const char* mod, const char* pred) { static atom_t aThread; @@ -540,7 +548,6 @@ void WaitFor(const char* mod, const char* pred) } } -/* Handle messages to Help > About dialog. */ INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM) { switch (uMsg) { @@ -561,7 +568,6 @@ INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wPa return TRUE; } -/* Try to style application according to current Windows theme. */ void UpdateTheme() { if (!IsThemeActive) return; diff --git a/c/pl.cpp b/c/pl.cpp index b0e7f8e..bab2f31 100644 --- a/c/pl.cpp +++ b/c/pl.cpp @@ -3,8 +3,6 @@ #include "pl.h" -/* Frame: Wrapper for opening and closing Prolog foreign frames. */ - Frame::Frame() { m_f = PL_open_foreign_frame(); @@ -20,7 +18,6 @@ void Frame::Close() PL_close_foreign_frame(m_f); } -/* Close foreign frame and invalidate associated data. */ void Frame::Discard() { PL_discard_foreign_frame(m_f); @@ -31,8 +28,6 @@ void Frame::Rewind() PL_rewind_foreign_frame(m_f); } -/* Mark: Wrapper for marking and releasing strings on the Prolog stack. */ - Mark::Mark() { PL_mark_string_buffers(&m_m); @@ -43,8 +38,6 @@ Mark::~Mark() PL_release_string_buffers_from_mark(m_m); } -/* Query: Wrapper for opening, solving and cutting Prolog query. */ - Query::Query(const module_t ctx, const predicate_t p, const term_t t0) { m_q = PL_open_query(ctx, PL_Q_CATCH_EXCEPTION, p, t0); @@ -66,11 +59,11 @@ int Query::Cut() return 0; } -/* Cut query and invalidate associated data. */ int Query::Close(std::nothrow_t) { return PL_close_query(m_q); } + int Query::Close() { if (PL_close_query(m_q)) return 1; @@ -82,6 +75,7 @@ int Query::NextSolution(std::nothrow_t) { return PL_next_solution(m_q); } + int Query::NextSolution() { if (PL_next_solution(m_q)) return 1; @@ -89,7 +83,6 @@ int Query::NextSolution() return 0; } -/* Convert Prolog term to wide characters. */ WcharPtr PlString(const term_t t, const int flags) { char* s; diff --git a/c/pl.h b/c/pl.h index 5720eda..b0cdbbd 100644 --- a/c/pl.h +++ b/c/pl.h @@ -7,19 +7,23 @@ #include "wcharptr.h" +/* Convert Prolog term to wide characters. */ WcharPtr PlString(const term_t t, const int flags = CVT_WRITE); +/* Wrapper for opening and closing Prolog foreign frames. */ struct Frame { Frame(); ~Frame(); void Close(); + /* Close foreign frame AND invalidate associated data. */ void Discard(); void Rewind(); private: fid_t m_f; }; +/* Wrapper for marking and releasing strings on the Prolog stack. */ struct Mark { Mark(); @@ -28,12 +32,14 @@ private: buf_mark_t m_m; }; +/* Wrapper for opening, solving and cutting Prolog query. */ struct Query { Query(module_t ctx, predicate_t p, term_t t0); ~Query(); int Cut(); int Cut(std::nothrow_t); + /* Cut query AND invalidate associated data. */ int Close(); int Close(std::nothrow_t); int NextSolution(); @@ -67,12 +73,13 @@ inline int PlGet(term_t t, long* x) { return PL_get_long(t, x); } inline int PlGet(term_t t, long long* x) { return PL_get_int64(t, x); } inline int PlGet(term_t t, atom_t* x) { return PL_get_atom(t, x); } inline int PlGet(term_t t, char** x) { return PL_get_atom_chars(t, x); } -inline int PlGet(term_t t, WcharPtr* x) { +inline int PlGet(term_t t, WcharPtr* x) +{ Mark m; char* s; if (!PlGet(t, &s)) return 0; *x = WcharPtr::FromNarrow(s); - return 1; /* or catch potential exception from BstrFromSz? */ + return 1; } /* Put in or get from a term reference an arbitrary number of values, diff --git a/c/util.h b/c/util.h index babe0c5..11840fa 100644 --- a/c/util.h +++ b/c/util.h @@ -3,6 +3,7 @@ #include +/* Format static wide string. */ template inline int Swprintf(wchar_t (&buf)[N], const wchar_t* const fmt, T... xs) { diff --git a/c/win.cpp b/c/win.cpp index 703c011..a120f96 100644 --- a/c/win.cpp +++ b/c/win.cpp @@ -3,8 +3,11 @@ #include "win.h" -Win32Error::Win32Error() : code(GetLastError()) {} -Win32Error::Win32Error(const DWORD code) : code(code) {} +Win32Error::Win32Error() noexcept + : code(GetLastError()) {} + +Win32Error::Win32Error(const DWORD code) noexcept + : code(code) {} Win32Error::~Win32Error() { @@ -40,14 +43,15 @@ const wchar_t* Win32Error::What() const noexcept return m_wszMsg; } -std::optional Library::Maybe(const wchar_t* const lib) +std::optional Library::Maybe(const wchar_t* const lib) noexcept { HMODULE hModule = LoadLibrary(lib); if (!hModule) return {}; return Library(hModule); } -Library::Library(const HMODULE hModule) : m_hModule(hModule) {} +Library::Library(const HMODULE hModule) noexcept + : m_hModule(hModule) {} Library::Library(const wchar_t* const lib) { diff --git a/c/win.h b/c/win.h index 1615985..baafbf0 100644 --- a/c/win.h +++ b/c/win.h @@ -4,15 +4,17 @@ #include #include +/* Display message box centered in main window. */ int EBMessageBox(const wchar_t* wszText, const wchar_t* wszCaption, unsigned uType); +/* Retrieve mouse position relative to given window's client area. */ int GetRelativeCursorPos(HWND hWnd, POINT* pt); -/* Win32Error: Exception for Windows API errors. */ +/* Exception for Windows API errors. */ struct Win32Error : public std::exception { - Win32Error(); - Win32Error(DWORD code); - ~Win32Error(); + Win32Error() noexcept; + Win32Error(DWORD code) noexcept; + ~Win32Error() noexcept; const char* what() const noexcept override; const wchar_t* What() const noexcept; DWORD code; @@ -21,20 +23,24 @@ private: wchar_t* m_wszMsg = NULL; }; -/* Library: Wrapper for loading and freeing dynamically linked libraries. */ +/* Wrapper for loading and freeing dynamically linked libraries. */ struct Library { - static std::optional Maybe(const wchar_t* lib); + /* Non-throwing named constructor. */ + static std::optional Maybe(const wchar_t* lib) noexcept; + Library(const wchar_t* lib); - ~Library(); - template T* GetProcAddress(const char* szProc); + ~Library() noexcept; + + template T* GetProcAddress(const char* szProc) noexcept; private: - Library(HMODULE hModule); + /* Non-throwing constructor used by Maybe. */ + Library(HMODULE hModule) noexcept; HMODULE m_hModule; }; template -T* Library::GetProcAddress(const char* const szProc) +T* Library::GetProcAddress(const char* const szProc) noexcept { return (T*)(void*)::GetProcAddress(m_hModule, szProc); } @@ -69,7 +75,7 @@ inline int Dpi(const int i) return MulDiv(i, g_dpi, 96); } -/* Get window rectangle relative to parent. */ +/* Retrieve given window's rectangle relative to parent's client area. */ inline BOOL GetRelativeRect(const HWND hWnd, RECT* const rr) { if (!GetClientRect(hWnd, rr)) return 0; @@ -90,6 +96,9 @@ inline BOOL SetWindowRect(const HWND hWnd, const RECT r) return SetWindowRect(hWnd, r.left, r.top, r.right, r.bottom); } +/* The following functions call uxtheme.dll functions, if uxtheme.dll + * exists, and otherwise do nothing.. */ + inline BOOL EBIsThemeActive() { extern BOOL (*IsThemeActive)(); -- cgit v1.2.3