aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c/datalistview.h3
-rw-r--r--c/debug.cpp2
-rw-r--r--c/debug.h10
-rw-r--r--c/episodelistview.cpp3
-rw-r--r--c/episodelistview.h3
-rw-r--r--c/layout.h8
-rw-r--r--c/listview.cpp14
-rw-r--r--c/listview.h12
-rw-r--r--c/main.cpp18
-rw-r--r--c/pl.cpp11
-rw-r--r--c/pl.h11
-rw-r--r--c/util.h1
-rw-r--r--c/win.cpp12
-rw-r--r--c/win.h31
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<char*>("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 <memory>
+/* Format static wide string. */
template<size_t N, typename... T>
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> Library::Maybe(const wchar_t* const lib)
+std::optional<Library> 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 <optional>
#include <windows.h>
+/* 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<Library> Maybe(const wchar_t* lib);
+ /* Non-throwing named constructor. */
+ static std::optional<Library> Maybe(const wchar_t* lib) noexcept;
+
Library(const wchar_t* lib);
- ~Library();
- template <class T> T* GetProcAddress(const char* szProc);
+ ~Library() noexcept;
+
+ template <class T> T* GetProcAddress(const char* szProc) noexcept;
private:
- Library(HMODULE hModule);
+ /* Non-throwing constructor used by Maybe. */
+ Library(HMODULE hModule) noexcept;
HMODULE m_hModule;
};
template <typename T>
-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)();