aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-07-10 23:23:09 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-07-10 23:25:09 +0200
commit295d423cc47f9ee8a72134dc544892a03b279311 (patch)
tree3e89b0bbcf42b3053225eb0dff88b887dd16df48
parent85a4ad2c184ed915915a2fb630415a80ed9a286f (diff)
downloadEpisodeBrowser-295d423cc47f9ee8a72134dc544892a03b279311.tar.gz
Convert to C++.
I already hit upon some object-oriented programming patterns in *listview.c, so I felt that it would be natural to use this as an opportunity to learn C++.
-rw-r--r--.dir-locals.el4
-rw-r--r--.gitignore1
-rw-r--r--Makefile8
-rw-r--r--README12
-rw-r--r--c/common.cpp (renamed from c/common.c)2
-rw-r--r--c/datalistview.cpp (renamed from c/datalistview.c)28
-rw-r--r--c/defs.h71
-rw-r--r--c/episodelistview.cpp (renamed from c/episodelistview.c)295
-rw-r--r--c/listview.c78
-rw-r--r--c/listview.cpp76
-rw-r--r--c/main.cpp (renamed from c/main.c)268
-rw-r--r--c/pl.cpp (renamed from c/pl.c)14
12 files changed, 453 insertions, 404 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index 62e25f6..6c6dcc0 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -1,2 +1,4 @@
((c-mode . ((flycheck-gcc-include-path . ("C:/Program Files/swipl/include"))
- (flycheck-gcc-definitions . ("UNICODE" "_UNICODE")))))
+ (flycheck-gcc-definitions . ("UNICODE" "_UNICODE"))))
+ (c++-mode . ((flycheck-gcc-include-path . ("C:/Program Files/swipl/include"))
+ (flycheck-gcc-definitions . ("UNICODE" "_UNICODE")))))
diff --git a/.gitignore b/.gitignore
index 9270add..44b07c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
/misc/
TAGS
*~
+*.db
diff --git a/Makefile b/Makefile
index 405e8c6..99b5f28 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
B = build/default/
-C = c/main.c
+C = c/main.cpp
PL = pl/cfg.pl pl/episode_data.pl pl/local_episodes.pl pl/track_episodes.pl
OBJ = $(B)common.obj $(B)datalistview.obj $(B)episodelistview.obj $(B)listview.obj $(B)pl.obj $(B)resource.obj
@@ -18,11 +18,11 @@ $(B)EpisodeBrowser.exe: $(C) $(OBJ) $(PL) c/defs.h Makefile
$(B)resource.obj: c/resource.h c/resource.rc c/application.manifest
windres -i c/resource.rc -o $(B)resource.obj
-$(B)%.obj: c/%.c c/defs.h
+$(B)%.obj: c/%.cpp c/*.h
$(CC) -c $(CFLAGS) -o $@ $<
-TAGS: c/*.c c/*.h pl/*.pl
- etags c/*.c c/*.h -lprolog pl/*.pl
+TAGS: c/*.cpp c/*.h pl/*.pl
+ etags c/*.cpp c/*.h -lprolog pl/*.pl
clean:
rm -fr $(B)EpisodeBrowser.exe $(B)*.obj
diff --git a/README b/README
index d6ceca7..489103e 100644
--- a/README
+++ b/README
@@ -28,16 +28,16 @@ modified.
Frontend
~~~~~~~~
-The graphical interface is implemented in C using the Win32 API (see
+The graphical interface is implemented in C++ using the Win32 API (see
the c folder). The source code is spread across a small number of
files. For an overview of the functions provided by each file, see
defs.h. In summary:
-main.c Entry point and initialization. Contains the main event handler.
-listview.c Creates and handles the shared aspects of the two list views.
-episodelistview.c Defines the interface to the episode list view.
-datalistview.c Defines the interface to the data list view.
-common.c Some useful functions that don't fit elsewhere.
+main.cpp Entry point and initialization. Contains the main event handler.
+listview.cpp Creates and handles the shared aspects of the two list views.
+episodelistview.cpp Defines the interface to the episode list view.
+datalistview.cpp Defines the interface to the data list view.
+common.cpp Some useful functions that don't fit elsewhere.
The frontend interacts with the Prolog backend via the SWI-Prolog API.
Note, however, that most interaction is done through ten or so macros,
diff --git a/c/common.c b/c/common.cpp
index a056993..63adb53 100644
--- a/c/common.c
+++ b/c/common.cpp
@@ -15,7 +15,7 @@ TszFromSz(const char *sz, int iCp)
cbMultiByte = strlen(sz)+1;
cchWideChar = MultiByteToWideChar(iCp, 0, sz, cbMultiByte, NULL, 0);
- tsz = malloc(cchWideChar*sizeof(WCHAR));
+ tsz = (TCHAR *)malloc(cchWideChar*sizeof(WCHAR));
if (!tsz) return NULL;
if (!MultiByteToWideChar(iCp, 0, sz, cbMultiByte, tsz, cchWideChar))
return NULL;
diff --git a/c/datalistview.c b/c/datalistview.cpp
index fbb46d0..3269dab 100644
--- a/c/datalistview.c
+++ b/c/datalistview.cpp
@@ -6,42 +6,38 @@
#include "resource.h"
#include "defs.h"
-HWND HDlv;
+extern EpisodeListView g_elv;
-HWND
-DlvCreate()
+void
+DataListView::Create()
{
LVCOLUMN lvc;
- HDlv = LvCreate((HMENU)IDC_DATALISTVIEW, LVS_NOCOLUMNHEADER);
+ ListView::Create((HMENU)IDC_DATALISTVIEW, LVS_NOCOLUMNHEADER);
lvc.mask = LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvc.iSubItem = DLVSIKEY;
lvc.pszText = TEXT("Key");
lvc.cx = Dpi(42);
- ListView_InsertColumn(HDlv, DLVSIKEY, &lvc);
+ ListView_InsertColumn(m_hWnd, DLVSIKEY, &lvc);
lvc.iSubItem = DLVSIVALUE;
lvc.pszText = TEXT("Value");
lvc.cx = 500;
- ListView_InsertColumn(HDlv, DLVSIVALUE, &lvc);
-
- return HDlv;
+ ListView_InsertColumn(m_hWnd, DLVSIVALUE, &lvc);
}
-/* Show episode data. */
void
-DlvShowEpisode(int iEpisode)
+DataListView::ShowEpisode(int iEpisode)
{
int i, iItem;
LVFINDINFO lvfi;
LVITEM lviKey, lviValue;
term_t t;
qid_t q;
- extern HWND HElv;
- ListView_DeleteAllItems(HDlv);
+ ListView_DeleteAllItems(m_hWnd);
lviKey.mask = LVIF_TEXT;
lviValue.mask = LVIF_TEXT;
@@ -67,12 +63,12 @@ DlvShowEpisode(int iEpisode)
lviKey.iItem = i;
lviKey.iSubItem = 0;
lviKey.pszText = tszKey;
- ListView_InsertItem(HDlv, &lviKey);
+ ListView_InsertItem(m_hWnd, &lviKey);
lviValue.iItem = i;
lviValue.iSubItem = 1;
lviValue.pszText = tszValue;
- ListView_SetItem(HDlv, &lviValue);
+ ListView_SetItem(m_hWnd, &lviValue);
free(tszValue);
c: free(tszKey);
@@ -83,7 +79,7 @@ DlvShowEpisode(int iEpisode)
lvfi.flags = LVFI_PARAM;
lvfi.lParam = iEpisode;
- iItem = ListView_FindItem(HElv, -1, &lvfi);
+ iItem = ListView_FindItem(g_elv.HWnd(), -1, &lvfi);
if (iItem != -1)
- ListView_EnsureVisible(HElv, iItem, TRUE);
+ ListView_EnsureVisible(g_elv.HWnd(), iItem, TRUE);
}
diff --git a/c/defs.h b/c/defs.h
index 8196a93..9f53c92 100644
--- a/c/defs.h
+++ b/c/defs.h
@@ -5,36 +5,51 @@
#include <commctrl.h>
#include <SWI-Prolog.h>
-/* common.c */
+/* common.cpp */
TCHAR *TszFromSz(const char *, int);
-/* main.c */
+/* main.cpp */
void UpdateLayout();
-/* listview.c */
-HWND LvCreate(HMENU, DWORD);
-int LvHeight(HWND, int);
-
-/* episodelistview.c */
-HWND ElvCreate();
-void ElvDoSort(void);
-LRESULT ElvHandleNotify(LPARAM);
-void ElvRedraw(void);
-void ElvSetTop(int);
-void ElvSelectFocus(void);
-void ElvSelectUnwatched(int);
-void ElvShowFocus(void);
-void ElvUpdate(void);
-void ElvUpdateItem(LPLVITEM);
-
-/* datalistview.c */
-HWND DlvCreate();
-void DlvShowEpisode(int);
-
-/* pl.c */
-int Pl(char *, char *, char *, ...);
-int Plp(term_t, char *, ...);
-int Plg(term_t, char *, ...);
+/* listview.cpp */
+class ListView {
+protected:
+ WNDPROC m_prevProc;
+ HWND m_hWnd;
+public:
+ void Create(HMENU, DWORD);
+ int Height(int);
+ HWND HWnd(void);
+ virtual LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+};
+
+/* episodelistview.cpp */
+class EpisodeListView: public ListView {
+public:
+ void Create(void);
+ void DoSort(void);
+ LRESULT HandleNotify(LPARAM);
+ void Redraw(void);
+ void SetTop(int);
+ void SelectFocus(void);
+ void SelectUnwatched(int);
+ void ShowFocus(void);
+ void Update(void);
+ void UpdateItem(LPLVITEM);
+ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+};
+
+/* datalistview.cpp */
+class DataListView: public ListView {
+public:
+ void Create(void);
+ void ShowEpisode(int);
+};
+
+/* pl.cpp */
+int Pl(const char *, const char *, const char *, ...);
+int Plp(term_t, const char *, ...);
+int Plg(term_t, const char *, ...);
/* defs.h */
#define DLVSIKEY 0
@@ -56,8 +71,8 @@ Cmp(int a, int b)
inline int
Dpi(int i)
{
- extern int IDPI;
- return MulDiv(i, IDPI, 96);
+ extern int g_iDPI;
+ return MulDiv(i, g_iDPI, 96);
}
#endif
diff --git a/c/episodelistview.c b/c/episodelistview.cpp
index a1973f8..8fb3ec7 100644
--- a/c/episodelistview.c
+++ b/c/episodelistview.cpp
@@ -6,48 +6,50 @@
#include "resource.h"
#include "defs.h"
-HWND HElv;
+extern DataListView g_dlv;
+
+HWND HSortLv;
+
int ISort;
LVITEM LviElvFocus; /* Focused episode. */
static int CALLBACK ElvSort(LPARAM, LPARAM, LPARAM);
-HWND
-ElvCreate()
+void
+EpisodeListView::Create()
{
LVCOLUMN lvc;
- HElv = LvCreate((HMENU)IDC_EPISODELISTVIEW, 0);
+ ListView::Create((HMENU)IDC_EPISODELISTVIEW, 0);
lvc.mask = LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvc.iSubItem = ELVSIEPISODE;
lvc.pszText = TEXT("#");
lvc.cx = Dpi(42);
- ListView_InsertColumn(HElv, ELVSIEPISODE, &lvc);
+ ListView_InsertColumn(m_hWnd, ELVSIEPISODE, &lvc);
lvc.iSubItem = ELVSITITLE;
lvc.pszText = TEXT("Title");
lvc.cx = 500;
- ListView_InsertColumn(HElv, ELVSITITLE, &lvc);
+ ListView_InsertColumn(m_hWnd, ELVSITITLE, &lvc);
lvc.iSubItem = ELVSIRATING;
lvc.pszText = TEXT("/");
lvc.cx = Dpi(30);
- ListView_InsertColumn(HElv, ELVSIRATING, &lvc);
+ ListView_InsertColumn(m_hWnd, ELVSIRATING, &lvc);
if (!Pl("cfg","get_sort","i",&ISort))
ISort = 1;
-
- return HElv;
}
void
-ElvDoSort()
+EpisodeListView::DoSort()
{
- ListView_SortItemsEx(HElv, ElvSort, ISort);
+ HSortLv = m_hWnd;
+ ListView_SortItemsEx(m_hWnd, ElvSort, ISort);
}
LRESULT
-ElvHandleNotify(LPARAM lParam)
+EpisodeListView::HandleNotify(LPARAM lParam)
{
LPNMLISTVIEW lpNmLv;
lpNmLv = (LPNMLISTVIEW)lParam;
@@ -58,8 +60,8 @@ ElvHandleNotify(LPARAM lParam)
(lpNmLv->uNewState & LVIS_FOCUSED)) {
LviElvFocus.iItem = lpNmLv->iItem;
LviElvFocus.lParam = lpNmLv->lParam;
- ElvUpdateItem(&LviElvFocus);
- DlvShowEpisode(lpNmLv->lParam);
+ UpdateItem(&LviElvFocus);
+ g_dlv.ShowEpisode(lpNmLv->lParam);
}
break;
case LVN_COLUMNCLICK: /* Sort by column. */
@@ -68,8 +70,8 @@ ElvHandleNotify(LPARAM lParam)
iColumn = lpNmLv->iSubItem+1;
ISort = abs(ISort) == iColumn? -ISort: iColumn;
Pl("cfg","set_sort","I",ISort);
- s: ElvDoSort();
- ElvShowFocus();
+ DoSort();
+ ShowFocus();
break;
}
case LVN_KEYDOWN: /* Navigate episodes by keyboard. */
@@ -78,10 +80,10 @@ ElvHandleNotify(LPARAM lParam)
lpNmLvKd = (LPNMLVKEYDOWN)lParam;
switch (lpNmLvKd->wVKey) {
case VK_LEFT:
- ElvSelectUnwatched(-1);
+ SelectUnwatched(-1);
break;
case VK_RIGHT:
- ElvSelectUnwatched(1);
+ SelectUnwatched(1);
break;
}
break;
@@ -96,9 +98,9 @@ ElvHandleNotify(LPARAM lParam)
break;
case CDDS_ITEMPREPAINT:
{
- extern HFONT HfBold;
+ extern HFONT g_fBold;
if (!Pl("track_episodes","watched","I",lpLvCd->nmcd.lItemlParam)) {
- SelectObject(lpLvCd->nmcd.hdc, HfBold);
+ SelectObject(lpLvCd->nmcd.hdc, g_fBold);
return CDRF_NEWFONT;
}
break;
@@ -117,12 +119,11 @@ ElvHandleNotify(LPARAM lParam)
case NM_RETURN: /* Open all selected episodes. */
{
LVITEM lvi;
- extern HWND HElv;
lvi.mask = LVIF_PARAM;
lvi.iItem = -1;
while ((lvi.iItem = ListView_GetNextItem(
- HElv, lvi.iItem, LVNI_SELECTED)) != -1) {
- if (!ListView_GetItem(HElv, &lvi)) goto b;
+ m_hWnd, lvi.iItem, LVNI_SELECTED)) != -1) {
+ if (!ListView_GetItem(m_hWnd, &lvi)) goto b;
if (!Pl("local_episodes","open_episode_locally","I",
lvi.lParam))
Pl("local_episodes","open_episode_online","I",
@@ -133,12 +134,12 @@ ElvHandleNotify(LPARAM lParam)
case NM_RCLICK:
{
DWORD dwPos;
- extern HWND HWnd;
- extern HMENU HPopupMenu;
+ extern HWND g_hWnd;
+ extern HMENU g_hPopupMenu;
dwPos = GetMessagePos();
- TrackPopupMenu(HPopupMenu, TPM_RIGHTBUTTON,
+ TrackPopupMenu(g_hPopupMenu, TPM_RIGHTBUTTON,
LOWORD(dwPos), HIWORD(dwPos), 0,
- HWnd, NULL);
+ g_hWnd, NULL);
break;
}
}
@@ -147,24 +148,24 @@ ElvHandleNotify(LPARAM lParam)
}
void
-ElvRedraw()
+EpisodeListView::Redraw()
{
- RedrawWindow(HElv, NULL, NULL,
+ RedrawWindow(m_hWnd, NULL, NULL,
RDW_ERASE|RDW_FRAME|RDW_INVALIDATE|RDW_ALLCHILDREN);
}
void
-ElvSetTop(int iItem)
+EpisodeListView::SetTop(int iItem)
{
int iLast;
- iLast = ListView_GetItemCount(HElv)-1;
- ListView_EnsureVisible(HElv, iLast, TRUE);
- ListView_EnsureVisible(HElv, iItem, TRUE);
+ iLast = ListView_GetItemCount(m_hWnd)-1;
+ ListView_EnsureVisible(m_hWnd, iLast, TRUE);
+ ListView_EnsureVisible(m_hWnd, iItem, TRUE);
}
/* Select previously focused episode. */
void
-ElvSelectFocus()
+EpisodeListView::SelectFocus()
{
int i, iEpisode, iItem;
LVFINDINFO lvfi;
@@ -175,31 +176,31 @@ ElvSelectFocus()
lvfi.flags = LVFI_PARAM;
lvfi.lParam = iEpisode;
i = 0;
- while ((iItem = ListView_FindItem(HElv, -1, &lvfi)) == -1 && i++ < 100)
+ while ((iItem = ListView_FindItem(m_hWnd, -1, &lvfi)) == -1 && i++ < 100)
lvfi.lParam = ++iEpisode;
if (iItem != -1) goto s;
iEpisode -= 100;
lvfi.lParam = iEpisode;
i = 0;
- while ((iItem = ListView_FindItem(HElv, -1, &lvfi)) == -1 && i++ < 100)
+ while ((iItem = ListView_FindItem(m_hWnd, -1, &lvfi)) == -1 && i++ < 100)
lvfi.lParam = --iEpisode;
if (iItem != -1) goto s;
return;
-s: ListView_SetItemState(HElv, -1, LVIF_STATE, LVIS_SELECTED);
- ElvSetTop(iItem > 5? iItem-5: 0);
- ListView_SetItemState(HElv, iItem,
+s: ListView_SetItemState(m_hWnd, -1, LVIF_STATE, LVIS_SELECTED);
+ SetTop(iItem > 5? iItem-5: 0);
+ ListView_SetItemState(m_hWnd, iItem,
LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
LviElvFocus.iItem = iItem;
LviElvFocus.lParam = iEpisode;
- ElvUpdateItem(&LviElvFocus);
- DlvShowEpisode(iEpisode);
+ UpdateItem(&LviElvFocus);
+ g_dlv.ShowEpisode(iEpisode);
}
/* Select next/previous unwatched episode. */
void
-ElvSelectUnwatched(int iDir)
+EpisodeListView::SelectUnwatched(int iDir)
{
int i, iEpNew, iItemNew;
LVFINDINFO lvfi;
@@ -207,8 +208,8 @@ ElvSelectUnwatched(int iDir)
/* Get focused episode. */
lviFocus.mask = LVIF_PARAM;
- if ((lviFocus.iItem = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED)) != -1
- && ListView_GetItem(HElv, &lviFocus))
+ if ((lviFocus.iItem = ListView_GetNextItem(m_hWnd, -1, LVNI_FOCUSED)) != -1
+ && ListView_GetItem(m_hWnd, &lviFocus))
;
else
return;
@@ -223,130 +224,83 @@ ElvSelectUnwatched(int iDir)
return;
lvfi.lParam = iEpNew;
- if ((iItemNew = ListView_FindItem(HElv, -1, &lvfi)) != -1) {
- ListView_SetItemState(HElv,-1,LVIF_STATE,LVIS_SELECTED);
- ListView_SetSelectionMark(HElv, iItemNew);
- ListView_SetItemState(HElv, iItemNew,
+ if ((iItemNew = ListView_FindItem(m_hWnd, -1, &lvfi)) != -1) {
+ ListView_SetItemState(m_hWnd,-1,LVIF_STATE,LVIS_SELECTED);
+ ListView_SetSelectionMark(m_hWnd, iItemNew);
+ ListView_SetItemState(m_hWnd, iItemNew,
LVIS_SELECTED|LVIS_FOCUSED,
LVIS_SELECTED|LVIS_FOCUSED);
- ElvRedraw();
- ListView_EnsureVisible(HElv, iItemNew, TRUE);
+ Redraw();
+ ListView_EnsureVisible(m_hWnd, iItemNew, TRUE);
return;
}
} while (i++ < 1000);
}
void
-ElvShowFocus()
+EpisodeListView::ShowFocus()
{
int iEpFocus;
- iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED);
+ iEpFocus = ListView_GetNextItem(m_hWnd, -1, LVNI_FOCUSED);
if (iEpFocus == -1) return;
- ListView_EnsureVisible(HElv, iEpFocus, TRUE);
-}
-
-/* Sort list view items, iSort being the 1-based index of the column
- * to sort by. If iSort is negative, the order is descending. */
-int CALLBACK
-ElvSort(LPARAM iItem1, LPARAM iItem2, LPARAM iSort)
-{
- int iOrder;
- LVITEM lvi1, lvi2;
- lvi1.mask = lvi2.mask = LVIF_PARAM;
- lvi1.iItem = iItem1; lvi2.iItem = iItem2;
- if (!ListView_GetItem(HElv, &lvi1)) return 0;
- if (!ListView_GetItem(HElv, &lvi2)) return 0;
- iOrder = Cmp(iSort, 0);
- switch (abs(iSort)-1) {
- case ELVSIEPISODE:
- return iOrder*Cmp(lvi1.lParam, lvi2.lParam);
- break;
- case ELVSIRATING:
- {
- int iRating1, iRating2;
- iRating1 = iSort > 0? 99: -1;
- iRating2 = iSort > 0? 99: -1;
- Pl("episode_data","episode_rating","Ii",lvi1.lParam,&iRating1);
- Pl("episode_data","episode_rating","Ii",lvi2.lParam,&iRating2);
- if (iRating1 == iRating2)
- return Cmp(lvi1.lParam, lvi2.lParam);
- return iOrder*Cmp(iRating1, iRating2);
- break;
- }
- case ELVSITITLE:
- {
- char *sz1, *sz2;
- int cch, cch1, cch2;
- if (!Pl("episode_data","episode_title","Is",lvi1.lParam,&sz1))
- return 0;
- if (!Pl("episode_data","episode_title","Is",lvi2.lParam,&sz2))
- return 0;
- cch1 = strlen(sz1);
- cch2 = strlen(sz2);
- cch = cch1 > cch2? cch2: cch1;
- return iOrder*_strnicmp(sz1, sz2, cch);
- break;
- }
- default:
- return 0;
- }
+ ListView_EnsureVisible(m_hWnd, iEpFocus, TRUE);
}
/* Update episode list. */
void
-ElvUpdate()
+EpisodeListView::Update()
{
int cEp, i, iEp, iEpFocus, iItem, iItemMark, iItemTopNew;
LVITEM lvi, lviEpisode, lviTop;
LVFINDINFO lvfi;
- extern HWND HWndStatus;
- static TCHAR tszDisp[16], tszEpisode[16], tszTotal[16];
+ extern HWND g_hWndStatus;
+ static TCHAR tszDisp[16], tszEpisode[16];
static int aEpSel[2048];
lviEpisode.mask = LVIF_TEXT|LVIF_PARAM;
/* Save scrolling position. */
- lviTop.iItem = ListView_GetTopIndex(HElv);
+ lviTop.iItem = ListView_GetTopIndex(m_hWnd);
lviTop.mask = LVIF_PARAM;
- ListView_GetItem(HElv, &lviTop);
+ ListView_GetItem(m_hWnd, &lviTop);
/* Save selected episodes. */
i = 0;
lvi.mask = LVIF_PARAM;
lvi.iItem = -1;
while ((lvi.iItem = ListView_GetNextItem(
- HElv, lvi.iItem, LVNI_SELECTED)) != -1
+ m_hWnd, lvi.iItem, LVNI_SELECTED)) != -1
&& i < 2048)
- if (ListView_GetItem(HElv, &lvi))
+ if (ListView_GetItem(m_hWnd, &lvi))
aEpSel[i++] = lvi.lParam;
aEpSel[i] = 0;
- iItemMark = ListView_GetSelectionMark(HElv);
+ iItemMark = ListView_GetSelectionMark(m_hWnd);
/* Save focus. */
iEpFocus = 0;
- if ((lvi.iItem = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED)) != -1
- && ListView_GetItem(HElv, &lvi))
+ if ((lvi.iItem = ListView_GetNextItem(m_hWnd, -1, LVNI_FOCUSED)) != -1
+ && ListView_GetItem(m_hWnd, &lvi))
iEpFocus = lvi.lParam;
- SendMessage(HElv, WM_SETREDRAW, FALSE, 0);
- ListView_DeleteAllItems(HElv);
+ SendMessage(m_hWnd, WM_SETREDRAW, FALSE, 0);
+ ListView_DeleteAllItems(m_hWnd);
if (!Pl("episode_data","ensure_episode_data","")) return;
if (!Pl("episode_data","episode_count","i",&cEp)) return;
for (iEp = 1, iItem = 0; iEp <= cEp; iEp++) {
- extern char SzLimitScreenwriter[];
- extern int BViewTVOriginal, BViewWatched;
+ extern char g_szLimitScreenwriter[];
+ extern int g_bViewTVOriginal, g_bViewWatched;
- if (SzLimitScreenwriter[0])
+ if (g_szLimitScreenwriter[0])
if (!Pl("episode_data","episode_datum","ISS",
- iEp,"Screenwriter",SzLimitScreenwriter))
+ iEp,"Screenwriter",g_szLimitScreenwriter))
continue;
- if (!BViewWatched)
+ if (!g_bViewWatched)
if (Pl("track_episodes","watched","I",iEp)) continue;
- if (!BViewTVOriginal)
+ if (!g_bViewTVOriginal)
if (Pl("episode_data","tv_original","I",iEp)) continue;
/* Format episode number string. */
@@ -357,11 +311,11 @@ ElvUpdate()
lviEpisode.iSubItem = ELVSIEPISODE;
lviEpisode.pszText = tszEpisode;
lviEpisode.lParam = iEp;
- ListView_InsertItem(HElv, &lviEpisode);
- ElvUpdateItem(&lviEpisode);
+ ListView_InsertItem(m_hWnd, &lviEpisode);
+ UpdateItem(&lviEpisode);
}
- ElvDoSort();
+ DoSort();
lvfi.flags = LVFI_PARAM;
@@ -369,12 +323,12 @@ ElvUpdate()
for (i = 0; aEpSel[i]; i++) {
int iItemSel;
lvfi.lParam = aEpSel[i];
- if ((iItemSel = ListView_FindItem(HElv, -1, &lvfi)) != -1)
- ListView_SetItemState(HElv, iItemSel,
+ if ((iItemSel = ListView_FindItem(m_hWnd, -1, &lvfi)) != -1)
+ ListView_SetItemState(m_hWnd, iItemSel,
LVIS_SELECTED, LVIS_SELECTED);
}
if (iItemMark != -1)
- ListView_SetSelectionMark(HElv, iItemMark);
+ ListView_SetSelectionMark(m_hWnd, iItemMark);
/* Reset focus. */
if (iEpFocus) {
@@ -382,10 +336,10 @@ ElvUpdate()
i = 0;
do
lvfi.lParam = iEpFocus+i;
- while ((iItemFocus = ListView_FindItem(HElv, -1, &lvfi)) == -1
+ while ((iItemFocus = ListView_FindItem(m_hWnd, -1, &lvfi)) == -1
&& i++ < 100);
if (iItemFocus != -1)
- ListView_SetItemState(HElv, iItemFocus,
+ ListView_SetItemState(m_hWnd, iItemFocus,
LVIS_FOCUSED, LVIS_FOCUSED);
}
@@ -394,19 +348,19 @@ ElvUpdate()
i = 0;
do
lvfi.lParam = lviTop.lParam+i;
- while ((iItemTopNew = ListView_FindItem(HElv, -1, &lvfi)) == -1
+ while ((iItemTopNew = ListView_FindItem(m_hWnd, -1, &lvfi)) == -1
&& i++ < 100);
if (iItemTopNew != -1)
- ElvSetTop(iItemTopNew);
+ SetTop(iItemTopNew);
_stprintf_s(tszDisp, sizeof(tszDisp), TEXT("%d"), iItem);
- SendMessage(HWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)tszDisp);
- SendMessage(HElv, WM_SETREDRAW, TRUE, 0);
+ SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)tszDisp);
+ SendMessage(m_hWnd, WM_SETREDRAW, TRUE, 0);
}
/* Update episode name and rating. */
void
-ElvUpdateItem(LPLVITEM lpLvi)
+EpisodeListView::UpdateItem(LPLVITEM lpLvi)
{
char *szName;
int iRating;
@@ -417,19 +371,90 @@ ElvUpdateItem(LPLVITEM lpLvi)
if (!Pl("episode_data","episode_title","Is",lpLvi->lParam,&szName)) {
if (!Pl("episode_data","update_episode_data","")) goto r;
if (!Pl("episode_data","episode_title","Is",lpLvi->lParam,&szName))
- goto r;
+ goto r;
}
tszName = TszFromSz(szName, CP_UTF8);
if (tszName)
- ListView_SetItemText(HElv, lpLvi->iItem, ELVSITITLE, tszName);
+ ListView_SetItemText(m_hWnd, lpLvi->iItem, ELVSITITLE, tszName);
r: if (!Pl("episode_data","episode_rating","Ii",lpLvi->lParam,&iRating)) {
- ListView_SetItemText(HElv, lpLvi->iItem, ELVSIRATING, TEXT(""));
+ ListView_SetItemText(m_hWnd, lpLvi->iItem, ELVSIRATING, TEXT(""));
goto f;
}
_stprintf_s(tszRating, sizeof(tszRating), TEXT("%d"), iRating);
- ListView_SetItemText(HElv, lpLvi->iItem, ELVSIRATING, tszRating);
+ ListView_SetItemText(m_hWnd, lpLvi->iItem, ELVSIRATING, tszRating);
f: if (tszName) free(tszName);
}
+
+/* Sort list view items, iSort being the 1-based index of the column
+ * to sort by. If iSort is negative, the order is descending. */
+int CALLBACK
+ElvSort(LPARAM iItem1, LPARAM iItem2, LPARAM iSort)
+{
+ int iOrder;
+ LVITEM lvi1, lvi2;
+ lvi1.mask = lvi2.mask = LVIF_PARAM;
+ lvi1.iItem = iItem1; lvi2.iItem = iItem2;
+ if (!ListView_GetItem(HSortLv, &lvi1)) return 0;
+ if (!ListView_GetItem(HSortLv, &lvi2)) return 0;
+ iOrder = Cmp(iSort, 0);
+ switch (abs(iSort)-1) {
+ case ELVSIEPISODE:
+ return iOrder*Cmp(lvi1.lParam, lvi2.lParam);
+ break;
+ case ELVSIRATING:
+ {
+ int iRating1, iRating2;
+ iRating1 = iSort > 0? 99: -1;
+ iRating2 = iSort > 0? 99: -1;
+ Pl("episode_data","episode_rating","Ii",lvi1.lParam,&iRating1);
+ Pl("episode_data","episode_rating","Ii",lvi2.lParam,&iRating2);
+ if (iRating1 == iRating2)
+ return Cmp(lvi1.lParam, lvi2.lParam);
+ return iOrder*Cmp(iRating1, iRating2);
+ break;
+ }
+ case ELVSITITLE:
+ {
+ char *sz1, *sz2;
+ int cch, cch1, cch2;
+ if (!Pl("episode_data","episode_title","Is",lvi1.lParam,&sz1))
+ return 0;
+ if (!Pl("episode_data","episode_title","Is",lvi2.lParam,&sz2))
+ return 0;
+ cch1 = strlen(sz1);
+ cch2 = strlen(sz2);
+ cch = cch1 > cch2? cch2: cch1;
+ return iOrder*_strnicmp(sz1, sz2, cch);
+ break;
+ }
+ default:
+ return 0;
+ }
+}
+
+LRESULT CALLBACK
+EpisodeListView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_GETDLGCODE:
+ {
+ LRESULT lResult;
+
+ /* For the episode list view, the Enter key should not
+ * be handled by the dialog manager, but instead be sent
+ * along to the main window procedure, so that it may be
+ * handled by the NM_RETURN case in ElvHandleNotify. */
+
+ lResult = CallWindowProc(m_prevProc, hWnd, uMsg, wParam, lParam);
+ if (lParam && ((MSG *)lParam)->message == WM_KEYDOWN
+ && ((MSG *)lParam)->wParam == VK_RETURN)
+ return DLGC_WANTMESSAGE;
+ return lResult;
+ }
+ }
+
+ return ListView::WndProc(hWnd, uMsg, wParam, lParam);
+}
diff --git a/c/listview.c b/c/listview.c
deleted file mode 100644
index 91838da..0000000
--- a/c/listview.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <windows.h>
-#include <commctrl.h>
-#include <uxtheme.h>
-
-#include "resource.h"
-#include "defs.h"
-
-extern HFONT HfNormal;
-extern HWND HWnd;
-WNDPROC LvPrevProc;
-static LRESULT CALLBACK LvProc(HWND, UINT, WPARAM, LPARAM);
-
-HWND
-LvCreate(HMENU hMenu, DWORD dwStyle)
-{
- HWND hLv;
-
- hLv = CreateWindowEx(
- WS_EX_CLIENTEDGE,
- WC_LISTVIEW,
- TEXT(""),
- dwStyle|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP
- |LVS_REPORT|LVS_SHOWSELALWAYS,
- 0, 0, 0, 0,
- HWnd, hMenu, GetModuleHandle(NULL), NULL
- );
-
- LvPrevProc = (WNDPROC)SetWindowLongPtr(hLv,
- GWLP_WNDPROC, (LONG_PTR)LvProc);
-
- ListView_SetExtendedListViewStyle(hLv, LVS_EX_FULLROWSELECT);
-
- SendMessage(hLv, WM_SETFONT, (WPARAM)HfNormal, MAKELPARAM(FALSE, 0));
-
- return hLv;
-}
-
-LRESULT CALLBACK
-LvProc(HWND hLv, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg) {
- case WM_NOTIFY:
- switch (((LPNMHDR)lParam)->code) {
- case HDN_ENDTRACK:
- UpdateLayout();
- return TRUE;
- }
- break;
- case WM_GETDLGCODE:
- {
- LRESULT lResult;
- extern HWND HElv;
-
- /* For the episode list view, the Enter key should not
- * be handled by the dialog manager, but instead be sent
- * along to the main window procedure, so that it may be
- * handled by the NM_RETURN case in ElvHandleNotify. */
-
- if (hLv != HElv) break;
- lResult = CallWindowProc(LvPrevProc, hLv, uMsg, wParam, lParam);
- if (lParam && ((MSG *)lParam)->message == WM_KEYDOWN
- && ((MSG *)lParam)->wParam == VK_RETURN)
- return DLGC_WANTMESSAGE;
- return lResult;
- }
- }
-
- return CallWindowProc(LvPrevProc, hLv, uMsg, wParam, lParam);
-}
-
-/* Naively calculate height of list view. */
-int
-LvHeight(HWND hLv, int bHeader)
-{
- int iCount;
- iCount = ListView_GetItemCount(hLv);
- return iCount? Dpi(bHeader? 27: 4)+iCount*Dpi(19): 0;
-}
diff --git a/c/listview.cpp b/c/listview.cpp
new file mode 100644
index 0000000..9f24dc3
--- /dev/null
+++ b/c/listview.cpp
@@ -0,0 +1,76 @@
+#include <windows.h>
+#include <commctrl.h>
+#include <uxtheme.h>
+
+#include "resource.h"
+#include "defs.h"
+
+extern HFONT g_hfNormal;
+extern HWND g_hWnd;
+static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+
+void
+ListView::Create(HMENU hMenu, DWORD dwStyle)
+{
+ m_hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ WC_LISTVIEW,
+ TEXT(""),
+ dwStyle
+ |WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|LVS_REPORT|LVS_SHOWSELALWAYS,
+ 0, 0, 0, 0,
+ g_hWnd, hMenu, GetModuleHandle(NULL), this
+ );
+
+ if (SetProp(m_hWnd, TEXT("this"), (HANDLE)this))
+ m_prevProc = (WNDPROC)SetWindowLongPtr(m_hWnd,
+ GWLP_WNDPROC, (LONG_PTR)::WndProc);
+
+ ListView_SetExtendedListViewStyle(m_hWnd, LVS_EX_FULLROWSELECT);
+
+ SendMessage(m_hWnd, WM_SETFONT, (WPARAM)g_hfNormal, MAKELPARAM(FALSE, 0));
+}
+
+/* Naively calculate height of list view. */
+int
+ListView::Height(int bHeader)
+{
+ int iCount;
+ iCount = ListView_GetItemCount(m_hWnd);
+ return iCount? Dpi(bHeader? 27: 4)+iCount*Dpi(19): 0;
+}
+
+HWND
+ListView::HWnd()
+{
+ return m_hWnd;
+}
+
+LRESULT CALLBACK
+ListView::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case HDN_ENDTRACK:
+ UpdateLayout();
+ return TRUE;
+ }
+ break;
+ }
+
+ return CallWindowProc(m_prevProc, hWnd, uMsg, wParam, lParam);
+}
+
+static LRESULT CALLBACK
+WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_DESTROY:
+ RemoveProp(hWnd, TEXT("this"));
+ break;
+ }
+
+ ListView *lpThis = (ListView *)GetProp(hWnd, TEXT("this"));
+ return lpThis? lpThis->WndProc(hWnd, uMsg, wParam, lParam): FALSE;
+}
diff --git a/c/main.c b/c/main.cpp
index ef3877a..6799280 100644
--- a/c/main.c
+++ b/c/main.cpp
@@ -6,20 +6,23 @@
#include "resource.h"
#include "defs.h"
-atom_t AThread;
-char SzLimitScreenwriter[64] = {0};
-HFONT HfNormal;
-HFONT HfBold;
-HMENU HPopupMenu;
-HWND HFocus;
-HWND HWnd;
-HWND HWndStatus;
-int BViewTVOriginal = 1;
-int BViewWatched = 1;
-int BThread = 0;
-int IDPI = -1;
-static int BThemes;
-static int CxVScroll;
+EpisodeListView g_elv;
+DataListView g_dlv;
+
+atom_t g_aThread;
+char g_szLimitScreenwriter[64] = {0};
+HFONT g_hfNormal;
+HFONT g_fBold;
+HMENU g_hPopupMenu;
+HWND g_hFocus;
+HWND g_hWnd;
+HWND g_hWndStatus;
+int g_bViewTVOriginal = 1;
+int g_bViewWatched = 1;
+int g_bThread = 0;
+int g_iDPI = -1;
+static int g_bThemes;
+static int g_cxVScroll;
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
static HWND CreateStatusBar(HWND, HINSTANCE);
@@ -41,12 +44,12 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
/* Set constant values. */
hModule = LoadLibrary(TEXT("uxtheme.dll"));
- BThemes = hModule && GetProcAddress(hModule,"SetWindowTheme");
+ g_bThemes = hModule && GetProcAddress(hModule,"SetWindowTheme");
if (hModule) FreeLibrary(hModule);
- CxVScroll = GetSystemMetrics(SM_CXVSCROLL);
+ g_cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
/* Initialize Prolog. */
- argv[0] = "EpisodeBrowser";
+ argv[0] = (char *)"EpisodeBrowser";
argv[1] = NULL;
tszErr = TEXT("Could not initialize Prolog.");
if (!PL_initialise(1, argv)) goto f;
@@ -59,8 +62,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
tszErr = TEXT("Could not initialize common controls.");
if (!InitCommonControlsEx(&icc)) goto f;
- HPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU));
- HPopupMenu = GetSubMenu(HPopupMenu, 0);
+ g_hPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU));
+ g_hPopupMenu = GetSubMenu(g_hPopupMenu, 0);
memset(&wc, 0, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
@@ -86,13 +89,13 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
);
tszErr = TEXT("Could not create main window.");
if (!hWnd) goto f;
- HWndStatus = CreateStatusBar(hWnd, hInstance);
+ g_hWndStatus = CreateStatusBar(hWnd, hInstance);
ShowWindow(hWnd, nCmdShow);
/* Populate episode list view. */
Pl("track_episodes", "update_tracked_episodes", "");
- ElvUpdate();
- ElvSelectFocus();
+ g_elv.Update();
+ g_elv.SelectFocus();
while (GetMessage(&msg, NULL, 0, 0) > 0) {
if (IsDialogMessage(hWnd, &msg)) continue;
@@ -114,36 +117,35 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_CREATE:
{
HMODULE hModule;
- FARPROC GetDpiForWindow;
- extern HWND HWnd, HElv;
- HWnd = hWnd;
- IDPI = 96;
+ UINT (*GetDpiForWindow)(HWND);
+ g_hWnd = hWnd;
+ g_iDPI = 96;
hModule = LoadLibrary(TEXT("User32.dll"));
- if (hModule && (GetDpiForWindow = GetProcAddress(hModule, "GetDpiForWindow"))) {
- IDPI = GetDpiForWindow(HWnd);
+ if (hModule && (GetDpiForWindow = (UINT (*)(HWND))GetProcAddress(hModule, "GetDpiForWindow"))) {
+ g_iDPI = GetDpiForWindow(g_hWnd);
FreeLibrary(hModule);
}
SetWindowPos(hWnd, NULL, -1, -1, Dpi(510), Dpi(400), SWP_NOMOVE);
- if (Pl("cfg","get_view_watched","i",&BViewWatched))
+ if (Pl("cfg","get_view_watched","i",&g_bViewWatched))
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED,
- BViewWatched? MF_CHECKED: MF_UNCHECKED);
- if (Pl("cfg","get_view_tv_original","i",&BViewTVOriginal))
+ g_bViewWatched? MF_CHECKED: MF_UNCHECKED);
+ if (Pl("cfg","get_view_tv_original","i",&g_bViewTVOriginal))
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL,
- BViewTVOriginal? MF_CHECKED: MF_UNCHECKED);
+ g_bViewTVOriginal? MF_CHECKED: MF_UNCHECKED);
{
char *sz;
if (!Pl("cfg","get_limit_screenwriter","s",&sz))
goto s;
- strcpy_s(SzLimitScreenwriter,
- sizeof(SzLimitScreenwriter), sz);
+ strcpy_s(g_szLimitScreenwriter,
+ sizeof(g_szLimitScreenwriter), sz);
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS,
- SzLimitScreenwriter[0]? MF_UNCHECKED: MF_CHECKED);
+ g_szLimitScreenwriter[0]? MF_UNCHECKED: MF_CHECKED);
}
s: SetupFonts();
- DlvCreate();
- ElvCreate();
+ g_dlv.Create();
+ g_elv.Create();
UpdateTheme();
- SetFocus(HElv);
+ SetFocus(g_elv.HWnd());
break;
}
case WM_CLOSE:
@@ -152,23 +154,23 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_DESTROY:
{
LVITEM lvi;
- extern HWND HElv;
+ HWND hElv;
+ hElv = g_elv.HWnd();
lvi.mask = LVIF_PARAM;
- if ((lvi.iItem=ListView_GetNextItem(HElv,-1,LVNI_FOCUSED)) != -1
- && ListView_GetItem(HElv, &lvi))
+ if ((lvi.iItem=ListView_GetNextItem(hElv,-1,LVNI_FOCUSED)) != -1
+ && ListView_GetItem(hElv, &lvi))
Pl("cfg","set_focus","I",lvi.lParam);
PostQuitMessage(0);
break;
}
case WM_SIZE:
- SendMessage(HWndStatus, WM_SIZE, wParam, lParam);
+ SendMessage(g_hWndStatus, WM_SIZE, wParam, lParam);
UpdateLayout();
break;
case WM_GETMINMAXINFO:
{
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
- extern HWND HDlv;
- lpMMI->ptMinTrackSize.y = LvHeight(HDlv, 0)+80;
+ lpMMI->ptMinTrackSize.y = g_dlv.Height(0)+80;
break;
}
case WM_THEMECHANGED:
@@ -178,7 +180,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPRECT lpr;
lpr = (LPRECT)lParam;
- IDPI = HIWORD(wParam);
+ g_iDPI = HIWORD(wParam);
SetWindowPos(hWnd, NULL,
lpr->left, lpr->top,
lpr->right-lpr->left,
@@ -190,19 +192,19 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_ACTIVATE:
switch (wParam) {
case WA_INACTIVE:
- HFocus = GetFocus();
+ g_hFocus = GetFocus();
break;
case WA_ACTIVE:
case WA_CLICKACTIVE:
- SetFocus(HFocus);
+ SetFocus(g_hFocus);
Pl("track_episodes","update_tracked_episodes","");
- ElvRedraw();
+ g_elv.Redraw();
}
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->idFrom) {
case IDC_EPISODELISTVIEW:
- return ElvHandleNotify(lParam);
+ return g_elv.HandleNotify(lParam);
}
break;
case WM_TIMER:
@@ -210,9 +212,9 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case IDT_TIMER:
{
static int i = 0;
- if (Pl("episode_data","thread_running","A",AThread)) {
+ if (Pl("episode_data","thread_running","A",g_aThread)) {
i = (i+1)%4;
- SendMessage(HWndStatus, SB_SETTEXT, MAKEWPARAM(1,0),
+ SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0),
(LPARAM)(i==0? TEXT("."):
i==1? TEXT(".."):
i==2? TEXT("..."):
@@ -220,7 +222,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
} else {
i = 0;
KillTimer(hWnd, IDT_TIMER);
- ElvUpdate();
+ g_elv.Update();
}
break;
}
@@ -232,19 +234,19 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
case IDM_FILE_REFRESH:
- ElvUpdate();
+ g_elv.Update();
break;
case IDM_FILE_FETCH_DATA:
- if (BThread) break;
- Pl("episode_data","thread_create","Sa","update_episode_data",&AThread);
+ if (g_bThread) break;
+ Pl("episode_data","thread_create","Sa","update_episode_data",&g_aThread);
goto t;
case IDM_FILE_FETCH_SCREENWRITERS:
- if (BThread) break;
- Pl("episode_data","thread_create","Sa","update_screenwriters",&AThread);
+ if (g_bThread) break;
+ Pl("episode_data","thread_create","Sa","update_screenwriters",&g_aThread);
t: KillTimer(hWnd, IDT_TIMER);
SetTimer(hWnd, IDT_TIMER, 500, NULL);
- SendMessage(HWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)TEXT("."));
- BThread = 1;
+ SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)TEXT("."));
+ g_bThread = 1;
break;
case IDM_FILE_ABOUT:
DialogBox(
@@ -257,61 +259,64 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case IDM_VIEW_WATCHED:
{
int iEpFocus;
- extern HWND HElv;
+ HWND hElv;
+ hElv = g_elv.HWnd();
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED,
- BViewWatched? MF_UNCHECKED: MF_CHECKED);
- BViewWatched = !BViewWatched;
- ElvUpdate();
- Pl("cfg","set_view_watched","I",BViewWatched);
- iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED);
+ g_bViewWatched? MF_UNCHECKED: MF_CHECKED);
+ g_bViewWatched = !g_bViewWatched;
+ g_elv.Update();
+ Pl("cfg","set_view_watched","I",g_bViewWatched);
+ iEpFocus = ListView_GetNextItem(hElv, -1, LVNI_FOCUSED);
if (iEpFocus == -1) break;
- ListView_EnsureVisible(HElv, iEpFocus, TRUE);
+ ListView_EnsureVisible(hElv, iEpFocus, TRUE);
break;
}
case IDM_VIEW_TV_ORIGINAL:
{
int iEpFocus;
- extern HWND HElv;
+ HWND hElv;
+ hElv = g_elv.HWnd();
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL,
- BViewTVOriginal? MF_UNCHECKED: MF_CHECKED);
- BViewTVOriginal = !BViewTVOriginal;
- ElvUpdate();
- Pl("cfg","set_view_tv_original","I",BViewTVOriginal);
- iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED);
+ g_bViewTVOriginal? MF_UNCHECKED: MF_CHECKED);
+ g_bViewTVOriginal = !g_bViewTVOriginal;
+ g_elv.Update();
+ Pl("cfg","set_view_tv_original","I",g_bViewTVOriginal);
+ iEpFocus = ListView_GetNextItem(hElv, -1, LVNI_FOCUSED);
if (iEpFocus == -1) break;
- ListView_EnsureVisible(HElv, iEpFocus, TRUE);
+ ListView_EnsureVisible(hElv, iEpFocus, TRUE);
break;
}
case IDM_VIEW_OTHERS: /* Show/hide other screenwriters. */
{
int iEpFocus;
- extern HWND HElv;
- if (SzLimitScreenwriter[0]) {
+ HWND hElv;
+ hElv = g_elv.HWnd();
+ if (g_szLimitScreenwriter[0]) {
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS,
MF_CHECKED);
- SzLimitScreenwriter[0] = 0;
+ g_szLimitScreenwriter[0] = 0;
} else {
char *sz;
LVITEM lvi;
- iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED);
+ iEpFocus = ListView_GetNextItem(hElv, -1, LVNI_FOCUSED);
if (iEpFocus == -1) break;
lvi.iItem = iEpFocus;
lvi.mask = LVIF_PARAM;
- if (!ListView_GetItem(HElv, &lvi)) break;
+ if (!ListView_GetItem(hElv, &lvi)) break;
if (!Pl("episode_data","episode_datum","ISs",
lvi.lParam,"Screenwriter",&sz))
break;
- strcpy_s(SzLimitScreenwriter,
- sizeof(SzLimitScreenwriter), sz);
+ strcpy_s(g_szLimitScreenwriter,
+ sizeof(g_szLimitScreenwriter), sz);
CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS,
MF_UNCHECKED);
}
- ElvUpdate();
+ g_elv.Update();
Pl("cfg","set_limit_screenwriter","S",
- SzLimitScreenwriter);
- iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED);
+ g_szLimitScreenwriter);
+ iEpFocus = ListView_GetNextItem(hElv, -1, LVNI_FOCUSED);
if (iEpFocus == -1) break;
- ListView_EnsureVisible(HElv, iEpFocus, TRUE);
+ ListView_EnsureVisible(hElv, iEpFocus, TRUE);
break;
}
case IDM_WATCH_LOCALLY:
@@ -334,7 +339,8 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int iRating;
LVITEM lvi;
- extern HWND HElv;
+ HWND hElv;
+ hElv = g_elv.HWnd();
/* Look through selected items, applying the
* selected command to each one. */
@@ -342,8 +348,8 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
lvi.mask = LVIF_PARAM;
lvi.iItem = -1;
while ((lvi.iItem = ListView_GetNextItem(
- HElv, lvi.iItem, LVNI_SELECTED)) != -1) {
- if (!ListView_GetItem(HElv, &lvi)) goto b;
+ hElv, lvi.iItem, LVNI_SELECTED)) != -1) {
+ if (!ListView_GetItem(hElv, &lvi)) goto b;
switch (LOWORD(wParam)) {
case IDM_WATCH_LOCALLY:
@@ -354,18 +360,18 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
case IDM_TOGGLE:
Pl("track_episodes","toggle_episode","I",lvi.lParam);
- ElvRedraw();
+ g_elv.Redraw();
break;
case IDM_FORGET:
Pl("track_episodes","forget_episode","I",lvi.lParam);
Pl("track_episodes","update_tracked_episodes","");
- ElvRedraw();
+ g_elv.Redraw();
break;
case IDM_LOOKUP:
Pl("episode_data","retract_episode","I",lvi.lParam);
- ElvUpdateItem(&lvi);
- ElvRedraw();
- DlvShowEpisode(lvi.lParam);
+ g_elv.UpdateItem(&lvi);
+ g_elv.Redraw();
+ g_dlv.ShowEpisode(lvi.lParam);
break;
case IDM_WIKI:
Pl("episode_data","open_episode_wiki","I",lvi.lParam);
@@ -403,7 +409,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case IDM_RATE0:
iRating = 0;
r: Pl("episode_data","rate_episode","II",lvi.lParam,iRating);
- ElvUpdateItem(&lvi);
+ g_elv.UpdateItem(&lvi);
break;
}
}
@@ -419,9 +425,9 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case IDM_RATE2:
case IDM_RATE1:
case IDM_RATE0:
- ElvRedraw();
- ElvDoSort();
- ElvShowFocus();
+ g_elv.Redraw();
+ g_elv.DoSort();
+ g_elv.ShowFocus();
}
b: break;
}
@@ -496,14 +502,14 @@ SetupFonts()
m.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(NONCLIENTMETRICS), &m, 0);
- HfNormal = CreateFontIndirect(&m.lfMessageFont);
+ g_hfNormal = CreateFontIndirect(&m.lfMessageFont);
FreeLibrary(hModule);
} else
- HfNormal = GetStockObject(DEFAULT_GUI_FONT);
+ g_hfNormal = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
- GetObject(HfNormal, sizeof(LOGFONT), &lf);
+ GetObject(g_hfNormal, sizeof(LOGFONT), &lf);
lf.lfWeight = FW_BOLD;
- HfBold = CreateFontIndirect(&lf);
+ g_fBold = CreateFontIndirect(&lf);
}
/***/
@@ -513,36 +519,39 @@ UpdateLayout()
{
int cxColumn, cyDlv, yStatus;
RECT rc, rcStatus;
- extern HWND HDlv, HElv;
+ HWND hDlv, hElv;
- GetClientRect(HWnd, &rc);
- GetClientRect(HWndStatus, &rcStatus);
+ hDlv = g_dlv.HWnd();
+ hElv = g_elv.HWnd();
+
+ GetClientRect(g_hWnd, &rc);
+ GetClientRect(g_hWndStatus, &rcStatus);
yStatus = rcStatus.bottom-rcStatus.top;
/* Resize data list view. */
- SendMessage(HDlv, WM_SETREDRAW, FALSE, 0);
- SendMessage(HElv, WM_SETREDRAW, FALSE, 0);
- cyDlv = rc.bottom-yStatus-LvHeight(HDlv, DLVSIKEY);
- MoveWindow(HDlv, 0, cyDlv, rc.right, rc.bottom-yStatus-cyDlv, TRUE);
- ListView_SetColumnWidth(HDlv, DLVSIKEY, LVSCW_AUTOSIZE);
- cxColumn = ListView_GetColumnWidth(HDlv, 0)+4;
- ListView_SetColumnWidth(HDlv, DLVSIKEY, cxColumn);
- ListView_SetColumnWidth(HDlv, DLVSIVALUE, rc.right-cxColumn-CxVScroll-4);
+ SendMessage(hDlv, WM_SETREDRAW, FALSE, 0);
+ SendMessage(hElv, WM_SETREDRAW, FALSE, 0);
+ cyDlv = rc.bottom-yStatus-g_dlv.Height(DLVSIKEY);
+ MoveWindow(hDlv, 0, cyDlv, rc.right, rc.bottom-yStatus-cyDlv, TRUE);
+ ListView_SetColumnWidth(hDlv, DLVSIKEY, LVSCW_AUTOSIZE);
+ cxColumn = ListView_GetColumnWidth(hDlv, 0)+4;
+ ListView_SetColumnWidth(hDlv, DLVSIKEY, cxColumn);
+ ListView_SetColumnWidth(hDlv, DLVSIVALUE, rc.right-cxColumn-g_cxVScroll-4);
/* Resize episode list view. */
- MoveWindow(HElv, 0, 0, rc.right, cyDlv+1, TRUE);
- ListView_SetColumnWidth(HElv, ELVSIEPISODE, LVSCW_AUTOSIZE);
- cxColumn = ListView_GetColumnWidth(HElv, ELVSIEPISODE)+4;
- ListView_SetColumnWidth(HElv, ELVSIEPISODE, cxColumn);
- cxColumn += ListView_GetColumnWidth(HElv, ELVSIRATING);
- ListView_SetColumnWidth(HElv, ELVSITITLE, rc.right-cxColumn-CxVScroll-4);
- SendMessage(HElv, WM_SETREDRAW, TRUE, 0);
- SendMessage(HDlv, WM_SETREDRAW, TRUE, 0);
+ MoveWindow(hElv, 0, 0, rc.right, cyDlv+1, TRUE);
+ ListView_SetColumnWidth(hElv, ELVSIEPISODE, LVSCW_AUTOSIZE);
+ cxColumn = ListView_GetColumnWidth(hElv, ELVSIEPISODE)+4;
+ ListView_SetColumnWidth(hElv, ELVSIEPISODE, cxColumn);
+ cxColumn += ListView_GetColumnWidth(hElv, ELVSIRATING);
+ ListView_SetColumnWidth(hElv, ELVSITITLE, rc.right-cxColumn-g_cxVScroll-4);
+ SendMessage(hElv, WM_SETREDRAW, TRUE, 0);
+ SendMessage(hDlv, WM_SETREDRAW, TRUE, 0);
/* Resize status bar parts. */
{
int aParts[] = {rc.right-Dpi(55), rc.right};
- SendMessage(HWndStatus, SB_SETPARTS,
+ SendMessage(g_hWndStatus, SB_SETPARTS,
(WPARAM)sizeof(aParts), (LPARAM)aParts);
}
}
@@ -554,9 +563,12 @@ UpdateTheme()
DWORD dwStyle;
LPTSTR tszTheme;
WORD wAction;
- extern HWND HElv, HDlv;
+ HWND hDlv, hElv;
+
+ hDlv = g_dlv.HWnd();
+ hElv = g_elv.HWnd();
- if (!BThemes) return;
+ if (!g_bThemes) return;
if (IsThemeActive()) {
dwStyle = LVS_EX_DOUBLEBUFFER;
tszTheme = TEXT("Explorer");
@@ -568,14 +580,14 @@ UpdateTheme()
}
/* Use modern "Explorer" theme. */
- SetWindowTheme(HElv, tszTheme, NULL);
- SetWindowTheme(HDlv, tszTheme, NULL);
+ SetWindowTheme(hElv, tszTheme, NULL);
+ SetWindowTheme(hDlv, tszTheme, NULL);
/* The modern theme requires double buffering. */
- ListView_SetExtendedListViewStyleEx(HElv, LVS_EX_DOUBLEBUFFER, dwStyle);
- ListView_SetExtendedListViewStyleEx(HDlv, LVS_EX_DOUBLEBUFFER, dwStyle);
+ ListView_SetExtendedListViewStyleEx(hElv, LVS_EX_DOUBLEBUFFER, dwStyle);
+ ListView_SetExtendedListViewStyleEx(hDlv, LVS_EX_DOUBLEBUFFER, dwStyle);
/* Hide focus rectangles. */
- SendMessage(HElv, WM_UPDATEUISTATE, MAKEWPARAM(wAction, UISF_HIDEFOCUS), 0);
- SendMessage(HDlv, WM_UPDATEUISTATE, MAKEWPARAM(wAction, UISF_HIDEFOCUS), 0);
+ SendMessage(hElv, WM_UPDATEUISTATE, MAKEWPARAM(wAction, UISF_HIDEFOCUS), 0);
+ SendMessage(hDlv, WM_UPDATEUISTATE, MAKEWPARAM(wAction, UISF_HIDEFOCUS), 0);
}
diff --git a/c/pl.c b/c/pl.cpp
index 50f5429..dd69517 100644
--- a/c/pl.c
+++ b/c/pl.cpp
@@ -3,12 +3,12 @@
#include <SWI-Prolog.h>
#include "defs.h"
-static int Plpv(term_t, char *, va_list);
-static int Plgv(term_t, char *, va_list);
+static int Plpv(term_t, const char *, va_list);
+static int Plgv(term_t, const char *, va_list);
/* Call Prolog predicate once. */
int
-Pl(char *szMod, char *szPred, char *szFmt, ...)
+Pl(const char *szMod, const char *szPred, const char *szFmt, ...)
{
int iArity;
term_t t;
@@ -36,7 +36,7 @@ f: va_end(vl);
/* Put known values in term. */
int
-Plp(term_t t, char *szFmt, ...)
+Plp(term_t t, const char *szFmt, ...)
{
int r;
va_list vl;
@@ -46,7 +46,7 @@ Plp(term_t t, char *szFmt, ...)
return r;
}
int
-Plpv(term_t t, char *szFmt, va_list vl)
+Plpv(term_t t, const char *szFmt, va_list vl)
{
int i;
for (i = 0; szFmt[i]; i++) {
@@ -90,7 +90,7 @@ Plpv(term_t t, char *szFmt, va_list vl)
/* Get unknown values from term. */
int
-Plg(term_t t, char *szFmt, ...)
+Plg(term_t t, const char *szFmt, ...)
{
int r;
va_list vl;
@@ -100,7 +100,7 @@ Plg(term_t t, char *szFmt, ...)
return r;
}
int
-Plgv(term_t t, char *szFmt, va_list vl)
+Plgv(term_t t, const char *szFmt, va_list vl)
{
int i;
for (i = 0; szFmt[i]; i++) {