aboutsummaryrefslogtreecommitdiff
path: root/c/win.c
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-02-15 16:29:59 +0100
committerJohn Ankarström <john@ankarstrom.se>2022-02-15 16:29:59 +0100
commit52fb337856497cb151081f3738e7cfa4bc2883bd (patch)
tree3309edbd0834bf90a5635b93038d1d088224e96e /c/win.c
parent09ec144a99f1234a37d04854bdfb81485540be97 (diff)
downloadEpisodeBrowser-52fb337856497cb151081f3738e7cfa4bc2883bd.tar.gz
Rework list view code.
Diffstat (limited to 'c/win.c')
-rw-r--r--c/win.c560
1 files changed, 0 insertions, 560 deletions
diff --git a/c/win.c b/c/win.c
deleted file mode 100644
index 6f82645..0000000
--- a/c/win.c
+++ /dev/null
@@ -1,560 +0,0 @@
-#include <windows.h>
-#include <TCHAR.H>
-#include <commctrl.h>
-#include <uxtheme.h>
-#include <stdio.h>
-#include <string.h>
-#include <SWI-Prolog.h>
-#include "resource.h"
-
-#define CLASSNAME TEXT("Episode Browser")
-
-HFONT g_GUIFont;
-HFONT g_GUIFontBold;
-WNDPROC g_PrevLvProc;
-
-int g_SelectedItem = -1; /* Remembered after refresh. */
-
-static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
-static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
-static LRESULT CALLBACK LvProc(HWND, UINT, WPARAM, LPARAM);
-
-static void CreateListView(HWND);
-static LRESULT HandleListViewNotify(HWND, LPARAM);
-static void UpdateLayout(HWND);
-
-static void SetupFonts();
-static TCHAR *TSZFromSZ(char *, int);
-
-static int Attach(void);
-static void UpdateName(HWND, NMLISTVIEW *);
-static void UpdateList(HWND);
-static void ShowEpisode(HWND, int);
-static int Watched(int);
-
-int WINAPI
-WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, INT nCmdShow)
-{
- char *rgArgs[2];
- HWND hWnd;
- MSG msg;
- INITCOMMONCONTROLSEX icc;
- WNDCLASSEX wc;
-
- /* Initialize Prolog. */
-
- rgArgs[0] = "episode_browser";
- rgArgs[1] = NULL;
-
- if (!PL_initialise(1, rgArgs))
- PL_halt(1);
-
- Attach();
-
- /* Create window. */
-
- icc.dwSize = sizeof(icc);
- icc.dwICC = ICC_WIN95_CLASSES;
- InitCommonControlsEx(&icc);
-
- SetupFonts();
-
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = 0;
- wc.lpfnWndProc = WndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
- wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
- wc.lpszClassName = CLASSNAME;
- wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
-
- RegisterClassEx(&wc);
-
- hWnd = CreateWindowEx(
- 0,
- CLASSNAME,
- TEXT("Episode Browser"),
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, /* Position */
- 510, 300, /* Size */
- NULL, /* Parent window */
- NULL, /* Menu */
- hInstance,
- NULL
- );
-
- if (!hWnd)
- return 0;
-
- ShowWindow(hWnd, nCmdShow);
-
- while (GetMessage(&msg, NULL, 0, 0) > 0) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return 0;
-}
-
-LRESULT CALLBACK
-WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg) {
- case WM_CLOSE:
- DestroyWindow(hWnd);
- break;
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case ID_FILE_EXIT:
- PostMessage(hWnd, WM_CLOSE, 0, 0);
- break;
- case ID_FILE_REFRESH:
- UpdateList(hWnd);
- break;
- case ID_FILE_ABOUT:
- DialogBox(
- GetModuleHandle(NULL),
- MAKEINTRESOURCE(IDD_ABOUT),
- hWnd,
- AboutDlgProc
- );
- break;
- }
- break;
- case WM_CREATE:
- CreateListView(hWnd);
- break;
- case WM_SIZE:
- UpdateLayout(hWnd);
- break;
- case WM_NOTIFY:
- switch (((NMHDR *)lParam)->idFrom) {
- case IDC_LISTVIEW:
- return HandleListViewNotify(hWnd, lParam);
- }
- break;
- default:
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
-
- return 0;
-}
-
-INT_PTR CALLBACK
-AboutDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg) {
- case WM_INITDIALOG:
- return TRUE;
- case WM_CLOSE:
- EndDialog(hWnd, IDOK);
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDOK:
- EndDialog(hWnd, IDOK);
- break;
- }
- break;
- default:
- return FALSE;
- }
-
- return TRUE;
-}
-
-LRESULT CALLBACK
-LvProc(HWND hListView, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch (uMsg) {
- case WM_NOTIFY:
- switch (((NMHDR *)lParam)->code) {
- case HDN_ENDTRACK:
- UpdateLayout(GetParent(hListView));
- return TRUE;
- }
- break;
- }
-
- return CallWindowProc(g_PrevLvProc,
- hListView, uMsg, wParam, lParam);
-}
-
-/***/
-
-void
-CreateListView(HWND hWnd)
-{
- HMODULE hModule;
- HWND hListView;
- LVCOLUMN lvc;
-
- hListView = CreateWindowEx(
- 0,
- WC_LISTVIEW,
- TEXT(""),
- WS_CHILD|WS_VISIBLE|WS_VSCROLL|LVS_REPORT,
- 0, 0, 0, 0,
- hWnd,
- (HMENU)IDC_LISTVIEW,
- GetModuleHandle(NULL),
- NULL
- );
-
- g_PrevLvProc = (WNDPROC)SetWindowLongPtr(hListView,
- GWLP_WNDPROC, (LONG_PTR)LvProc);
-
- SendMessage(hListView, WM_SETFONT,
- (WPARAM)g_GUIFont, MAKELPARAM(FALSE, 0));
-
- ListView_SetExtendedListViewStyle(hListView,
- LVS_EX_DOUBLEBUFFER);
-
- hModule = LoadLibrary(TEXT("uxtheme.dll"));
- if (hModule && GetProcAddress(hModule, "SetWindowTheme")) {
- ListView_SetExtendedListViewStyle(hListView,
- LVS_EX_FULLROWSELECT|LVS_EX_DOUBLEBUFFER);
- SendMessage(hListView, WM_CHANGEUISTATE,
- MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS), 0);
- SetWindowTheme(hListView, TEXT("Explorer"), NULL);
- }
-
- lvc.mask = LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
-
- lvc.iSubItem = 0;
- lvc.pszText = TEXT("#");
- lvc.cx = 42;
- ListView_InsertColumn(hListView, 0, &lvc);
-
- lvc.iSubItem = 1;
- lvc.pszText = TEXT("Title");
- lvc.cx = 500;
- ListView_InsertColumn(hListView, 1, &lvc);
-
- UpdateList(hWnd);
-}
-
-LRESULT
-HandleListViewNotify(HWND hWnd, LPARAM lParam)
-{
- NMLISTVIEW *pNmLv;
-
- pNmLv = (NMLISTVIEW *)lParam;
-
- switch (pNmLv->hdr.code) {
- case LVN_ITEMCHANGED:
- if ((pNmLv->uChanged & LVIF_STATE)
- && (pNmLv->uNewState & LVIS_FOCUSED)) {
- g_SelectedItem = pNmLv->iItem;
- UpdateName(hWnd, pNmLv);
- //ShowEpisode(hWnd, pNmLv->lParam);
- }
- break;
- case NM_CUSTOMDRAW:
- {
- NMLVCUSTOMDRAW *pLvCd;
- pLvCd = (NMLVCUSTOMDRAW *)lParam;
- switch (pLvCd->nmcd.dwDrawStage) {
- case CDDS_PREPAINT:
- return CDRF_NOTIFYITEMDRAW;
- break;
- case CDDS_ITEMPREPAINT:
- if (!Watched(pLvCd->nmcd.lItemlParam)) {
- SelectObject(pLvCd->nmcd.hdc,
- g_GUIFontBold);
- return CDRF_NEWFONT;
- }
- break;
- }
- }
- break;
- }
-
- return 0;
-}
-
-void
-UpdateLayout(HWND hWnd)
-{
- HWND hListView;
- int cxColumn;
- RECT rc;
- static int cxVScroll = 0;
-
- if (cxVScroll == 0)
- cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
-
- GetClientRect(hWnd, &rc);
- hListView = GetDlgItem(hWnd, IDC_LISTVIEW);
- MoveWindow(hListView, 0, 0,
- rc.right, rc.bottom,
- TRUE);
-
- cxColumn = ListView_GetColumnWidth(hListView, 0);
- ListView_SetColumnWidth(hListView, 1,
- rc.right-cxColumn-cxVScroll);
-
- ListView_EnsureVisible(hListView, g_SelectedItem, TRUE);
-}
-
-/***/
-
-void
-SetupFonts()
-{
- HMODULE hModule;
- LOGFONT lf;
-
- hModule = LoadLibrary(TEXT("User32.dll"));
- if (hModule && GetProcAddress(hModule, "SystemParametersInfoW")) {
- NONCLIENTMETRICS m;
-
- m.cbSize = sizeof(NONCLIENTMETRICS);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
- sizeof(NONCLIENTMETRICS), &m, 0);
- g_GUIFont = CreateFontIndirect(&m.lfMessageFont);
- } else {
- g_GUIFont = GetStockObject(DEFAULT_GUI_FONT);
- }
-
- GetObject(g_GUIFont, sizeof(LOGFONT), &lf);
- lf.lfWeight = FW_BOLD;
- g_GUIFontBold = CreateFontIndirect(&lf);
-}
-
-/* Convert zero-terminated non-wide (multi-byte) string to
- * zero-terminated wide/non-wide string depending on UNICODE. */
-TCHAR *
-TSZFromSZ(char *sz, int iCp)
-{
- TCHAR *tsz;
-
-#ifdef UNICODE
- int cbMultiByte, cchWideChar;
-
- cbMultiByte = strlen(sz)+1;
- cchWideChar = MultiByteToWideChar(iCp, 0, sz, cbMultiByte, NULL, 0);
- tsz = malloc(cchWideChar*sizeof(WCHAR));
- if (!tsz)
- return NULL;
- if (!MultiByteToWideChar(iCp, 0, sz, cbMultiByte, tsz, cchWideChar))
- return NULL;
-#else
- tsz = malloc(strlen(sz)+1);
- if (!tsz)
- return NULL;
- strcpy(tsz, sz);
-#endif
-
- return tsz;
-}
-
-/***/
-
-/* Attach persistent databases. */
-int
-Attach()
-{
- int r;
- term_t t;
-
- t = PL_new_term_refs(2);
- r = PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("attach", 0, "track_episodes"),
- t);
- if (!r) return r;
-
- r = PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("attach", 0, "episode_data"),
- t);
- if (!r) return r;
-
- return 1;
-}
-
-/* Show episode data. */
-void
-ShowEpisode(HWND hWnd, int iEpisode)
-{
- int r;
- term_t t;
-
- t = PL_new_term_refs(3);
- if(!PL_put_integer(t+0, iEpisode))
- return;
-
- r = PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("lookup_episode_local", 3, "episode_data"),
- t);
- if (!r)
- return;
-
- /* The episode data is a list of unary compounds,
- * whose functor is the key and whose argument is the value. */
-
- {
- term_t tHead, tList;
-
- tHead = PL_new_term_ref();
- tList = PL_copy_term_ref(t+2);
-
- while (PL_get_list(tList, tHead, tList)) {
- atom_t aKey;
- const char *szKey;
- char *szValue;
- term_t tValue;
- size_t iArity;
-
- if (!PL_get_name_arity(tHead, &aKey, &iArity))
- continue;
- szKey = PL_atom_chars(aKey);
-
- if (!PL_get_arg(1, tHead, tValue))
- continue;
- if (!PL_get_atom_chars(tValue, &szValue))
- continue;
-
- printf("%s/%d: %s\n", szKey, iArity, szValue);
- }
- }
-}
-
-/* Update episode name. */
-void
-UpdateName(HWND hWnd, NMLISTVIEW *pNmLv)
-{
- char *szName;
- HWND hListView;
- TCHAR *tszName;
- term_t t;
-
- t = PL_new_term_refs(3);
- if (!PL_put_integer(t+0, pNmLv->lParam))
- return;
-
- PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("lookup_episode", 3, "episode_data"),
- t);
-
- if (!PL_get_atom_chars(t+1, &szName))
- return;
-
- tszName = TSZFromSZ(szName, CP_UTF8);
- if (!tszName)
- return;
-
- hListView = GetDlgItem(hWnd, IDC_LISTVIEW);
- ListView_SetItemText(hListView, pNmLv->iItem, 1, tszName);
-}
-
-/* Update episode list. */
-void
-UpdateList(HWND hWnd)
-{
- HWND hListView;
- LVITEM lviEpisode, lviName;
- qid_t q;
- term_t t;
-
- hListView = GetDlgItem(hWnd, IDC_LISTVIEW);
-
- ListView_DeleteAllItems(hListView);
-
- lviEpisode.mask = LVIF_TEXT|LVIF_PARAM;
- lviName.mask = LVIF_TEXT;
-
- t = PL_new_term_refs(2);
- PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("update_tracked_episodes", 0, "track_episodes"),
- t);
-
- q = PL_open_query(NULL, PL_Q_NORMAL,
- PL_predicate("episode_file", 2, "local_episodes"),
- t);
-
- for (int i = 0; PL_next_solution(q); i++) {
- char *szName;
- int cb, iEpisode, iItem, r;
- TCHAR *tszEpisode, *tszName;
- term_t t2;
-
- /* Lookup episode name. */
-
- if (!PL_get_integer(t+0, &iEpisode))
- goto close;
-
- t2 = PL_new_term_refs(3);
- if(!PL_put_integer(t2+0, iEpisode))
- return;
-
- r = PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("lookup_episode_local", 3, "episode_data"),
- t2);
-
- /* Format episode, name strings. */
-
- tszName = NULL;
- if (r && PL_get_atom_chars(t2+1, &szName)) {
- tszName = TSZFromSZ(szName, CP_UTF8);
- if (!tszName)
- continue;
- }
-
- cb = 100;
- tszEpisode = malloc(cb*sizeof(TCHAR));
- if (!tszEpisode)
- continue;
- _stprintf_s(tszEpisode, cb, TEXT("%d"),
- iEpisode);
-
- /* Insert item. */
-
- lviEpisode.mask = LVIF_TEXT|LVIF_STATE|LVIF_PARAM;
- lviEpisode.iItem = i;
- lviEpisode.iSubItem = 0;
- lviEpisode.pszText = tszEpisode;
- lviEpisode.lParam = iEpisode;
- ListView_InsertItem(hListView, &lviEpisode);
-
- if (tszName) {
- lviName.iItem = i;
- lviName.iSubItem = 1;
- lviName.pszText = tszName;
- ListView_SetItem(hListView, &lviName);
- }
-
- free(tszName);
- free(tszEpisode);
- }
-
- if (g_SelectedItem != -1) {
- ListView_SetItemState(hListView, g_SelectedItem,
- LVIS_SELECTED, LVIS_SELECTED);
- ListView_EnsureVisible(hListView, g_SelectedItem, TRUE);
- }
-
-close:
- PL_close_query(q);
-}
-
-int
-Watched(int iEpisode)
-{
- term_t t;
-
- t = PL_new_term_refs(1);
- if (!PL_put_integer(t+0, iEpisode))
- return 0;
-
- return PL_call_predicate(NULL, PL_Q_NORMAL,
- PL_predicate("watched", 1, "track_episodes"),
- t);
-}