aboutsummaryrefslogtreecommitdiff
path: root/c/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'c/main.cpp')
-rw-r--r--c/main.cpp167
1 files changed, 78 insertions, 89 deletions
diff --git a/c/main.cpp b/c/main.cpp
index 203a24d..58c0441 100644
--- a/c/main.cpp
+++ b/c/main.cpp
@@ -9,6 +9,7 @@
#include "datalistview.h"
#include "episodelistview.h"
#include "layout.h"
+#include "main.h"
#include "test.h"
#include "util.h"
@@ -24,56 +25,37 @@
* program. `extern' is used to access them from other files, when
* need be. */
-/* Exit gracefully on uncaught exception. */
-static auto _ = SET_TERMINATE;
-
/* Looked-up constants. */
int g_dpi = 96;
-/* Cursors. */
-HCURSOR g_hcArrow = LoadCursorW(nullptr, IDC_ARROW);
-HCURSOR g_hcSizeNs = LoadCursorW(nullptr, IDC_SIZENS);
-
/* Fonts. */
HFONT g_hfNormal;
HFONT g_hfBold;
+/* Cursors. */
+HCURSOR g_hcArrow = LoadCursorW(nullptr, IDC_ARROW);
+HCURSOR g_hcSizeNs = LoadCursorW(nullptr, IDC_SIZENS);
+
/* Menus. */
HMENU g_hMenuPopup;
/* Windows. */
HWND g_hWndFocus;
-HWND g_hWnd;
HWND g_hWndStatus;
-/* Child window objects. */
-DataListView* g_dlv;
-EpisodeListView* g_elv;
-
-/* Layout handlers. */
-DlvDragger g_dragDlv;
-
-/* File views. */
-FileView<CfgA> g_fvCfg = FileView<CfgA>::Initialized(L"cfg.dat", 1);
-CfgA& g_cfg = g_fvCfg.At(0);
-FileView<ElvDataA> g_fvElv(L"elvdata.dat", g_cfg.cEp+128u);
-FileView<DlvDataA> g_fvDlv(L"dlvdata.dat", g_cfg.cEp+128u);
-
/* Optional Windows functions. */
BOOL (__stdcall *IsThemeActive)();
HRESULT (__stdcall *SetWindowTheme)(HWND, const wchar_t*, const wchar_t*);
+/* Main window object. */
+Window* g_window;
+
/* Initialize important global state on parent window creation. */
-static void InitializeMainWindow(HWND);
+static void InitializeMainWindow(HWND) noexcept;
/* Process parent window commands. */
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
-static LRESULT CALLBACK HandleMsg(HWND, UINT, WPARAM, LPARAM);
-/* Process main menu commands. */
-static void HandleMainMenu(HWND, WORD);
/* 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();
+INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(
_In_ const HINSTANCE hInstance,
@@ -81,6 +63,9 @@ int WINAPI WinMain(
_In_ char* const,
_In_ const int nCmdShow)
{
+ /* Exit gracefully on uncaught exception. */
+ SET_TERMINATE;
+
setbuf(stdout, nullptr);
LIBXML_TEST_VERSION;
@@ -126,8 +111,8 @@ int WINAPI WinMain(
/* Populate episode list view. */
/* TODO: Update tracked episodes. */
- g_elv->Update();
- g_elv->RestoreFocus();
+ g_window->elv.Update();
+ g_window->elv.RestoreFocus();
#ifdef _DEBUG
RunTests();
@@ -143,7 +128,7 @@ int WINAPI WinMain(
return 0;
}
-void InitializeMainWindow(const HWND hWnd)
+static void InitializeMainWindow_(const HWND hWnd)
{
/* This code is run ONCE, at the creation of the top-level
* window -- before WndProc! This is important, as it
@@ -186,37 +171,58 @@ void InitializeMainWindow(const HWND hWnd)
g_hMenuPopup = Require(LoadMenuW(nullptr, MAKEINTRESOURCE(IDR_POPUPMENU)));
g_hMenuPopup = Require(GetSubMenu(g_hMenuPopup, 0));
- /* Create child windows. */
- g_dlv = new DataListView(hWnd);
- g_elv = new EpisodeListView(hWnd);
+ g_window = new Window(hWnd);
+}
- /* The global main window handle must only be set AFTER
- * successful initialization. */
- g_hWnd = hWnd;
+void InitializeMainWindow(const HWND hWnd) noexcept
+{
+ try {
+ InitializeMainWindow_(hWnd);
+ } catch (...) {
+ ShowException(L"Initialization failed due to an error: %s");
+ exit(1);
+ }
}
LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
try {
- return HandleMsg(hWnd, uMsg, wParam, lParam);
+ return g_window->WndProc(hWnd, uMsg, wParam, lParam);
} catch (...) {
ShowException(L"The action was cancelled due to an error: %s");
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
-LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
+INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM)
+{
+ switch (uMsg) {
+ case WM_CLOSE:
+ EndDialog(hWnd, IDOK);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK)
+ EndDialog(hWnd, IDOK);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+LRESULT CALLBACK Window::WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
UpdateTheme();
SetWindowPos(hWnd, nullptr, -1, -1, Dpi(510), Dpi(412), SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
- SetFocus(g_elv->hWnd);
+ SetFocus(elv.hWnd);
/* Set menu item checkmarks according to saved settings. */
- CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, g_cfg.bViewWatched? MF_CHECKED: MF_UNCHECKED);
- CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, g_cfg.bViewTVOriginal? MF_CHECKED: MF_UNCHECKED);
- CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, g_cfg.limitToScreenwriter[0]? MF_UNCHECKED: MF_CHECKED);
+ CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, cfg.bViewWatched? MF_CHECKED: MF_UNCHECKED);
+ CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, cfg.bViewTVOriginal? MF_CHECKED: MF_UNCHECKED);
+ CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, cfg.limitToScreenwriter[0]? MF_UNCHECKED: MF_CHECKED);
return 0;
case WM_CLOSE:
@@ -224,7 +230,7 @@ LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam
return 0;
case WM_DESTROY:
- g_elv->SaveFocus();
+ elv.SaveFocus();
PostQuitMessage(0);
return 0;
@@ -270,14 +276,14 @@ LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam
else {
SetFocus(g_hWndFocus);
/* TODO: Update tracked episodes. */
- g_elv->Redraw();
+ elv.Redraw();
}
return 0;
case WM_NOTIFY:
switch (reinterpret_cast<NMHDR*>(lParam)->idFrom) {
case IDC_EPISODELISTVIEW:
- return g_elv->HandleNotify(lParam);
+ return elv.HandleNotify(lParam);
}
return 0;
@@ -289,7 +295,7 @@ LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam
HandleMainMenu(hWnd, command);
return 0;
case IDG_CTX:
- g_elv->HandleContextMenu(command);
+ elv.HandleContextMenu(command);
return 0;
default:
return 0;
@@ -309,13 +315,13 @@ LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam
/*IDM_FILE_FETCH_SCREENWRITERS*/L"Fetch screenwriters from the web (may take a minute).",
/*IDM_FILE_FETCH_CANCEL*/L"Stop fetching data from the web.",
/*IDM_FILE_ABOUT*/L"Show information about Episode Browser.",
- /*IDM_VIEW_WATCHED*/(g_cfg.bViewWatched?
+ /*IDM_VIEW_WATCHED*/(cfg.bViewWatched?
L"Click to hide watched episodes.":
L"Click to show watched episodes."),
- /*IDM_VIEW_TV_ORIGINAL*/(g_cfg.bViewTVOriginal?
+ /*IDM_VIEW_TV_ORIGINAL*/(cfg.bViewTVOriginal?
L"Click to hide TV original episodes.":
L"Click to show TV original episodes."),
- /*IDM_VIEW_OTHERS*/(g_cfg.limitToScreenwriter?
+ /*IDM_VIEW_OTHERS*/(cfg.limitToScreenwriter?
L"Click to hide episodes by other screenwriters.":
L"Click to show episodes by other screenwriters.")
};
@@ -349,11 +355,11 @@ LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam
}
case WM_LBUTTONDOWN:
- g_dragDlv.HandleLButtonDown();
+ dragDlv.HandleLButtonDown();
return 0;
case WM_SETCURSOR:
- if (g_dragDlv.HandleSetCursor())
+ if (dragDlv.HandleSetCursor())
return 1;
else {
/* Use default cursor. */
@@ -368,7 +374,7 @@ LRESULT CALLBACK HandleMsg(const HWND hWnd, const UINT uMsg, const WPARAM wParam
}
}
-void HandleMainMenu(const HWND hWnd, const WORD command)
+void Window::HandleMainMenu(const HWND hWnd, const WORD command)
{
switch (command) {
case IDM_FILE_EXIT:
@@ -376,7 +382,7 @@ void HandleMainMenu(const HWND hWnd, const WORD command)
break;
case IDM_FILE_REFRESH:
- g_elv->Update();
+ elv.Update();
break;
case IDM_FILE_FETCH_DATA:
@@ -402,61 +408,44 @@ void HandleMainMenu(const HWND hWnd, const WORD command)
break;
case IDM_VIEW_WATCHED:
- CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, g_cfg.bViewWatched? MF_UNCHECKED: MF_CHECKED);
- g_cfg.bViewWatched = !g_cfg.bViewWatched;
- g_elv->Update();
- g_elv->EnsureFocusVisible();
+ CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, cfg.bViewWatched? MF_UNCHECKED: MF_CHECKED);
+ cfg.bViewWatched = !cfg.bViewWatched;
+ elv.Update();
+ elv.EnsureFocusVisible();
/* TODO: Remember last valid focus. In case of
* non-existing focus, use the last valid focus. */
break;
case IDM_VIEW_TV_ORIGINAL:
- CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, g_cfg.bViewTVOriginal? MF_UNCHECKED: MF_CHECKED);
- g_cfg.bViewTVOriginal = !g_cfg.bViewTVOriginal;
- g_elv->Update();
- g_elv->EnsureFocusVisible();
+ CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, cfg.bViewTVOriginal? MF_UNCHECKED: MF_CHECKED);
+ cfg.bViewTVOriginal = !cfg.bViewTVOriginal;
+ elv.Update();
+ elv.EnsureFocusVisible();
break;
case IDM_VIEW_OTHERS:
- if (g_cfg.limitToScreenwriter[0]) { /* Show episodes by all screenwriters. */
+ if (cfg.limitToScreenwriter[0]) { /* Show episodes by all screenwriters. */
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, MF_CHECKED);
- g_cfg.limitToScreenwriter[0] = 0;
+ cfg.limitToScreenwriter[0] = 0;
} else { /* Hide episodes by other screenwriters than current. */
LVITEM lvi = {LVIF_PARAM, -1};
- if (g_elv->FindNextItem(&lvi, LVNI_FOCUSED)
- && g_fvDlv.At(lvi.lParam-1).screenwriter[0]) {
- Wcscpy(g_cfg.limitToScreenwriter, g_fvDlv.At(lvi.lParam-1).screenwriter);
+ if (elv.FindNextItem(&lvi, LVNI_FOCUSED)
+ && fvDlv.At(lvi.lParam-1).screenwriter[0]) {
+ Wcscpy(cfg.limitToScreenwriter, fvDlv.At(lvi.lParam-1).screenwriter);
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, MF_UNCHECKED);
}
}
- g_elv->Update();
- g_elv->EnsureFocusVisible();
+ elv.Update();
+ elv.EnsureFocusVisible();
break;
}
}
-INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM)
-{
- switch (uMsg) {
- case WM_CLOSE:
- EndDialog(hWnd, IDOK);
- return TRUE;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK)
- EndDialog(hWnd, IDOK);
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
-void UpdateTheme()
+void Window::UpdateTheme()
{
if (IsThemeActive) {
const bool bThemeActive = IsThemeActive();
- g_dlv->UpdateTheme(bThemeActive);
- g_elv->UpdateTheme(bThemeActive);
+ dlv.UpdateTheme(bThemeActive);
+ elv.UpdateTheme(bThemeActive);
}
}