#include #include #include #include #include "resource.h" #include "defs.h" char SzLimitScreenwriter[64] = {0}; HFONT HfNormal; HFONT HfBold; HMENU HPopupMenu; HWND HFocus; HWND HWnd; HWND HWndStatus; int BViewTVOriginal = 1; int BViewWatched = 1; int IDPI = -1; static int BThemes; static int CxVScroll; static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); static HWND CreateStatusBar(HWND, HINSTANCE); static int Attach(void); static void SetupFonts(void); static void UpdateTheme(void); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { char *argv[2]; HMODULE hModule; HWND hWnd; LPTSTR tszErr; MSG msg; INITCOMMONCONTROLSEX icc; term_t t; WNDCLASSEX wc; /* Set constant values. */ hModule = LoadLibrary(TEXT("uxtheme.dll")); BThemes = hModule && GetProcAddress(hModule,"SetWindowTheme"); if (hModule) FreeLibrary(hModule); CxVScroll = GetSystemMetrics(SM_CXVSCROLL); /* Initialize Prolog. */ argv[0] = "EpisodeBrowser"; argv[1] = NULL; tszErr = TEXT("Could not initialize Prolog."); if (!PL_initialise(1, argv)) goto f; tszErr = TEXT("Could not attach databases."); if (!Attach()) goto f; /* Initialize common controls, load menu and register window class. */ icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; tszErr = TEXT("Could not initialize common controls."); if (!InitCommonControlsEx(&icc)) goto f; HPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); HPopupMenu = GetSubMenu(HPopupMenu, 0); memset(&wc, 0, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = WndProc; 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 = TEXT("Episode Browser"); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); tszErr = TEXT("Could not register window class."); if (!RegisterClassEx(&wc)) goto f; /* Create window. */ hWnd = CreateWindowEx( 0, TEXT("Episode Browser"), TEXT("Episode Browser"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, hInstance, NULL ); tszErr = TEXT("Could not create main window."); if (!hWnd) goto f; HWndStatus = CreateStatusBar(hWnd, hInstance); ShowWindow(hWnd, nCmdShow); /* Populate episode list view. */ t = T(0); P("track_episodes","update_tracked_episodes",0,t); ElvUpdate(); ElvSelectRecent(); while (GetMessage(&msg, NULL, 0, 0) > 0) { if (IsDialogMessage(hWnd, &msg)) continue; TranslateMessage(&msg); DispatchMessage(&msg); } PL_halt(0); return 0; f: MessageBox(NULL, tszErr, TEXT("Error"), MB_ICONERROR); PL_halt(1); return 1; } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: { HMODULE hModule; FARPROC GetDpiForWindow; extern HWND HWnd, HElv; HWnd = hWnd; IDPI = 96; hModule = LoadLibrary(TEXT("User32.dll")); if (hModule && (GetDpiForWindow = GetProcAddress(hModule, "GetDpiForWindow"))) { IDPI = GetDpiForWindow(HWnd); FreeLibrary(hModule); } SetWindowPos(hWnd, NULL, -1, -1, Dpi(510), Dpi(400), SWP_NOMOVE); { term_t t; t = T(1); P("cfg","get_view_watched",1,t) goto s; GI(t,&BViewWatched) goto s; CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, BViewWatched? MF_CHECKED: MF_UNCHECKED); } s: { term_t t; t = T(1); P("cfg","get_view_tv_original",1,t) goto t; GI(t,&BViewTVOriginal) goto t; CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, BViewTVOriginal? MF_CHECKED: MF_UNCHECKED); } t: { char *sz; term_t t; t = T(1); P("cfg","get_limit_screenwriter",1,t) goto u; GAC(t,&sz) goto u; strcpy_s(SzLimitScreenwriter, sizeof(SzLimitScreenwriter), sz); CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, SzLimitScreenwriter[0]? MF_UNCHECKED: MF_CHECKED); } u: SetupFonts(); DlvCreate(); ElvCreate(); UpdateTheme(); SetFocus(HElv); break; } case WM_CLOSE: DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_SIZE: SendMessage(HWndStatus, WM_SIZE, wParam, lParam); UpdateLayout(); break; case WM_GETMINMAXINFO: { LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; extern HWND HDlv; lpMMI->ptMinTrackSize.y = LvHeight(HDlv, 0)+80; break; } case WM_THEMECHANGED: UpdateTheme(); break; case 0x02E0: /* WM_DPICHANGED */ { LPRECT lpr; lpr = (LPRECT)lParam; IDPI = HIWORD(wParam); SetWindowPos(hWnd, NULL, lpr->left, lpr->top, lpr->right-lpr->left, lpr->bottom-lpr->top, SWP_NOZORDER | SWP_NOACTIVATE); UpdateLayout(); break; } case WM_ACTIVATE: switch (wParam) { case WA_INACTIVE: HFocus = GetFocus(); break; case WA_ACTIVE: case WA_CLICKACTIVE: { term_t t; SetFocus(HFocus); t = T(0); P("track_episodes","update_tracked_episodes",0,t); ElvRedraw(); } } break; case WM_NOTIFY: switch (((LPNMHDR)lParam)->idFrom) { case IDC_EPISODELISTVIEW: return ElvHandleNotify(lParam); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_FILE_EXIT: PostMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_FILE_REFRESH: ElvUpdate(); break; case IDM_FILE_RESET: ElvSelectRecent(); break; case IDM_FILE_FETCH: { term_t t; t = T(0); P("episode_data","update_episode_data",0,t); ElvUpdate(); break; } case IDM_FILE_SCREENWRITERS: { term_t t; t = T(0); P("episode_data","update_screenwriters",0,t); ElvUpdate(); break; } case IDM_FILE_ABOUT: DialogBox( GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc ); break; case IDM_VIEW_WATCHED: { int iEpFocus; term_t t; extern HWND HElv; CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, BViewWatched? MF_UNCHECKED: MF_CHECKED); BViewWatched = !BViewWatched; ElvUpdate(); t = T(1); PI(t,BViewWatched) break; P("cfg","set_view_watched",1,t); iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED); if (iEpFocus == -1) break; ListView_EnsureVisible(HElv, iEpFocus, TRUE); break; } case IDM_VIEW_TV_ORIGINAL: { int iEpFocus; term_t t; extern HWND HElv; CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, BViewTVOriginal? MF_UNCHECKED: MF_CHECKED); BViewTVOriginal = !BViewTVOriginal; ElvUpdate(); t = T(1); PI(t,BViewTVOriginal) break; P("cfg","set_view_tv_original",1,t); iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED); if (iEpFocus == -1) break; ListView_EnsureVisible(HElv, iEpFocus, TRUE); break; } case IDM_VIEW_OTHERS: /* Show/hide other screenwriters. */ { atom_t a; int iEpFocus; term_t t; extern HWND HElv; if (SzLimitScreenwriter[0]) { CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, MF_CHECKED); SzLimitScreenwriter[0] = 0; } else { atom_t a; char *sz; LVITEM lvi; term_t t; iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED); if (iEpFocus == -1) break; lvi.iItem = iEpFocus; lvi.mask = LVIF_PARAM; if (!ListView_GetItem(HElv, &lvi)) break; t = T(3); a = A("Screenwriter"); PI(t,lvi.lParam) break; PA(t+1,a) break; P("episode_data","episode_datum",3,t) break; GAC(t+2,&sz) break; strcpy_s(SzLimitScreenwriter, sizeof(SzLimitScreenwriter), sz); CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, MF_UNCHECKED); } ElvUpdate(); t = T(1); a = A(SzLimitScreenwriter); PA(t,a) break; P("cfg","set_limit_screenwriter",1,t); iEpFocus = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED); if (iEpFocus == -1) break; ListView_EnsureVisible(HElv, iEpFocus, TRUE); break; } case IDM_WATCH: case IDM_TOGGLE: case IDM_FORGET: case IDM_LOOKUP: case IDM_RATE10: case IDM_RATE9: case IDM_RATE8: case IDM_RATE7: case IDM_RATE6: case IDM_RATE5: case IDM_RATE4: case IDM_RATE3: case IDM_RATE2: case IDM_RATE1: case IDM_RATE0: { LVITEM lvi; term_t t; extern HWND HElv; /* Look through selected items, applying the * selected command to each one. */ lvi.mask = LVIF_PARAM; lvi.iItem = -1; t = T(2); while ((lvi.iItem = ListView_GetNextItem( HElv, lvi.iItem, LVNI_SELECTED)) != -1) { if (!ListView_GetItem(HElv, &lvi)) goto b; PI(t,lvi.lParam) goto b; switch (LOWORD(wParam)) { case IDM_WATCH: P("local_episode","open_episode",1,t); break; case IDM_TOGGLE: P("track_episodes","toggle_episode",1,t); ElvRedraw(); break; case IDM_FORGET: P("track_episodes","forget_episode",1,t); P("track_episodes","update_tracked_episodes",0,t); ElvRedraw(); break; case IDM_LOOKUP: P("episode_data","retract_episode",1,t); ElvUpdateItem(&lvi); ElvRedraw(); DlvShowEpisode(lvi.lParam); break; case IDM_RATE10: PI(t+1,10) break; goto r; case IDM_RATE9: PI(t+1,9) break; goto r; case IDM_RATE8: PI(t+1,8) break; goto r; case IDM_RATE7: PI(t+1,7) break; goto r; case IDM_RATE6: PI(t+1,6) break; goto r; case IDM_RATE5: PI(t+1,5) break; goto r; case IDM_RATE4: PI(t+1,4) break; goto r; case IDM_RATE3: PI(t+1,3) break; goto r; case IDM_RATE2: PI(t+1,2) break; goto r; case IDM_RATE1: PI(t+1,1) break; goto r; case IDM_RATE0: PI(t+1,0) break; r: P("episode_data","rate_episode",2,t); ElvUpdateItem(&lvi); break; } } switch (LOWORD(wParam)) { case IDM_RATE10: case IDM_RATE9: case IDM_RATE8: case IDM_RATE7: case IDM_RATE6: case IDM_RATE5: case IDM_RATE4: case IDM_RATE3: case IDM_RATE2: case IDM_RATE1: case IDM_RATE0: ElvRedraw(); ElvDoSort(); ElvShowFocus(); } b: break; } } 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_CLOSE: EndDialog(hWnd, IDOK); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: EndDialog(hWnd, IDOK); break; } break; default: return FALSE; } return TRUE; } HWND CreateStatusBar(HWND hWndParent, HINSTANCE hInstance) { HWND hWnd; hWnd = CreateWindowEx( 0, STATUSCLASSNAME, (LPCTSTR) NULL, WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP, 0, 0, 0, 0, hWndParent, (HMENU)ID_STATUS, hInstance, NULL ); return hWnd; } /***/ /* Attach persistent databases. */ int Attach() { term_t t; t = T(0); P("track_episodes","attach",0,t) return 0; P("episode_data","attach",0,t) return 0; return 1; } 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); HfNormal = CreateFontIndirect(&m.lfMessageFont); FreeLibrary(hModule); } else HfNormal = GetStockObject(DEFAULT_GUI_FONT); GetObject(HfNormal, sizeof(LOGFONT), &lf); lf.lfWeight = FW_BOLD; HfBold = CreateFontIndirect(&lf); } /***/ void UpdateLayout() { int cxColumn, cyDlv, yStatus; RECT rc, rcStatus; extern HWND HDlv, HElv; GetClientRect(HWnd, &rc); GetClientRect(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); /* 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); /* Resize status bar parts. */ { int aParts[] = {rc.right-Dpi(100), rc.right-Dpi(50), rc.right}; SendMessage(HWndStatus, SB_SETPARTS, (WPARAM)sizeof(aParts), (LPARAM)aParts); } } /* Try to style application according to current Windows theme. */ void UpdateTheme() { DWORD dwStyle; LPTSTR tszTheme; WORD wAction; extern HWND HElv, HDlv; if (!BThemes) return; if (IsThemeActive()) { dwStyle = LVS_EX_DOUBLEBUFFER; tszTheme = TEXT("Explorer"); wAction = UIS_SET; } else { dwStyle = 0; tszTheme = NULL; wAction = UIS_CLEAR; } /* Use modern "Explorer" theme. */ 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); /* Hide focus rectangles. */ SendMessage(HElv, WM_UPDATEUISTATE, MAKEWPARAM(wAction, UISF_HIDEFOCUS), 0); SendMessage(HDlv, WM_UPDATEUISTATE, MAKEWPARAM(wAction, UISF_HIDEFOCUS), 0); }