From 295d423cc47f9ee8a72134dc544892a03b279311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Sun, 10 Jul 2022 23:23:09 +0200 Subject: 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++. --- c/episodelistview.c | 435 ---------------------------------------------------- 1 file changed, 435 deletions(-) delete mode 100644 c/episodelistview.c (limited to 'c/episodelistview.c') diff --git a/c/episodelistview.c b/c/episodelistview.c deleted file mode 100644 index a1973f8..0000000 --- a/c/episodelistview.c +++ /dev/null @@ -1,435 +0,0 @@ -#include -#include -#include -#include - -#include "resource.h" -#include "defs.h" - -HWND HElv; -int ISort; -LVITEM LviElvFocus; /* Focused episode. */ -static int CALLBACK ElvSort(LPARAM, LPARAM, LPARAM); - -HWND -ElvCreate() -{ - LVCOLUMN lvc; - - HElv = LvCreate((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); - - lvc.iSubItem = ELVSITITLE; - lvc.pszText = TEXT("Title"); - lvc.cx = 500; - ListView_InsertColumn(HElv, ELVSITITLE, &lvc); - - lvc.iSubItem = ELVSIRATING; - lvc.pszText = TEXT("/"); - lvc.cx = Dpi(30); - ListView_InsertColumn(HElv, ELVSIRATING, &lvc); - - if (!Pl("cfg","get_sort","i",&ISort)) - ISort = 1; - - return HElv; -} - -void -ElvDoSort() -{ - ListView_SortItemsEx(HElv, ElvSort, ISort); -} - -LRESULT -ElvHandleNotify(LPARAM lParam) -{ - LPNMLISTVIEW lpNmLv; - lpNmLv = (LPNMLISTVIEW)lParam; - - switch (lpNmLv->hdr.code) { - case LVN_ITEMCHANGED: /* Select/focus episode. */ - if ((lpNmLv->uChanged & LVIF_STATE) && - (lpNmLv->uNewState & LVIS_FOCUSED)) { - LviElvFocus.iItem = lpNmLv->iItem; - LviElvFocus.lParam = lpNmLv->lParam; - ElvUpdateItem(&LviElvFocus); - DlvShowEpisode(lpNmLv->lParam); - } - break; - case LVN_COLUMNCLICK: /* Sort by column. */ - { - int iColumn; - iColumn = lpNmLv->iSubItem+1; - ISort = abs(ISort) == iColumn? -ISort: iColumn; - Pl("cfg","set_sort","I",ISort); - s: ElvDoSort(); - ElvShowFocus(); - break; - } - case LVN_KEYDOWN: /* Navigate episodes by keyboard. */ - { - LPNMLVKEYDOWN lpNmLvKd; - lpNmLvKd = (LPNMLVKEYDOWN)lParam; - switch (lpNmLvKd->wVKey) { - case VK_LEFT: - ElvSelectUnwatched(-1); - break; - case VK_RIGHT: - ElvSelectUnwatched(1); - break; - } - break; - } - case NM_CUSTOMDRAW: /* Make unwatched episodes bold. */ - { - LPNMLVCUSTOMDRAW lpLvCd; - lpLvCd = (LPNMLVCUSTOMDRAW)lParam; - switch (lpLvCd->nmcd.dwDrawStage) { - case CDDS_PREPAINT: - return CDRF_NOTIFYITEMDRAW; - break; - case CDDS_ITEMPREPAINT: - { - extern HFONT HfBold; - if (!Pl("track_episodes","watched","I",lpLvCd->nmcd.lItemlParam)) { - SelectObject(lpLvCd->nmcd.hdc, HfBold); - return CDRF_NEWFONT; - } - break; - } - } - break; - } - case NM_DBLCLK: /* Open clicked episode. */ - { - if (!Pl("local_episodes","open_episode_locally","I", - LviElvFocus.lParam)) - Pl("local_episodes","open_episode_online","I", - LviElvFocus.lParam); - break; - } - 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; - if (!Pl("local_episodes","open_episode_locally","I", - lvi.lParam)) - Pl("local_episodes","open_episode_online","I", - lvi.lParam); - } - b: break; - } - case NM_RCLICK: - { - DWORD dwPos; - extern HWND HWnd; - extern HMENU HPopupMenu; - dwPos = GetMessagePos(); - TrackPopupMenu(HPopupMenu, TPM_RIGHTBUTTON, - LOWORD(dwPos), HIWORD(dwPos), 0, - HWnd, NULL); - break; - } - } - - return 0; -} - -void -ElvRedraw() -{ - RedrawWindow(HElv, NULL, NULL, - RDW_ERASE|RDW_FRAME|RDW_INVALIDATE|RDW_ALLCHILDREN); -} - -void -ElvSetTop(int iItem) -{ - int iLast; - iLast = ListView_GetItemCount(HElv)-1; - ListView_EnsureVisible(HElv, iLast, TRUE); - ListView_EnsureVisible(HElv, iItem, TRUE); -} - -/* Select previously focused episode. */ -void -ElvSelectFocus() -{ - int i, iEpisode, iItem; - LVFINDINFO lvfi; - - iItem = 0; - if (!Pl("cfg","get_focus","i",&iEpisode)) return; - - lvfi.flags = LVFI_PARAM; - lvfi.lParam = iEpisode; - i = 0; - while ((iItem = ListView_FindItem(HElv, -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) - 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, - LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); - LviElvFocus.iItem = iItem; - LviElvFocus.lParam = iEpisode; - ElvUpdateItem(&LviElvFocus); - DlvShowEpisode(iEpisode); -} - -/* Select next/previous unwatched episode. */ -void -ElvSelectUnwatched(int iDir) -{ - int i, iEpNew, iItemNew; - LVFINDINFO lvfi; - LVITEM lviFocus; - - /* Get focused episode. */ - lviFocus.mask = LVIF_PARAM; - if ((lviFocus.iItem = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED)) != -1 - && ListView_GetItem(HElv, &lviFocus)) - ; - else - return; - - i = 0; - lvfi.flags = LVFI_PARAM; - lvfi.lParam = lviFocus.lParam; - - do { - if (!Pl("track_episodes",iDir > 0? "next_unwatched": "previous_unwatched", - "Ii",lvfi.lParam,&iEpNew)) - 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, - LVIS_SELECTED|LVIS_FOCUSED, - LVIS_SELECTED|LVIS_FOCUSED); - ElvRedraw(); - ListView_EnsureVisible(HElv, iItemNew, TRUE); - return; - } - } while (i++ < 1000); -} - -void -ElvShowFocus() -{ - int iEpFocus; - iEpFocus = ListView_GetNextItem(HElv, -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; - } -} - -/* Update episode list. */ -void -ElvUpdate() -{ - 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]; - static int aEpSel[2048]; - - lviEpisode.mask = LVIF_TEXT|LVIF_PARAM; - - /* Save scrolling position. */ - lviTop.iItem = ListView_GetTopIndex(HElv); - lviTop.mask = LVIF_PARAM; - ListView_GetItem(HElv, &lviTop); - - /* Save selected episodes. */ - i = 0; - lvi.mask = LVIF_PARAM; - lvi.iItem = -1; - while ((lvi.iItem = ListView_GetNextItem( - HElv, lvi.iItem, LVNI_SELECTED)) != -1 - && i < 2048) - if (ListView_GetItem(HElv, &lvi)) - aEpSel[i++] = lvi.lParam; - aEpSel[i] = 0; - iItemMark = ListView_GetSelectionMark(HElv); - - /* Save focus. */ - iEpFocus = 0; - if ((lvi.iItem = ListView_GetNextItem(HElv, -1, LVNI_FOCUSED)) != -1 - && ListView_GetItem(HElv, &lvi)) - iEpFocus = lvi.lParam; - - SendMessage(HElv, WM_SETREDRAW, FALSE, 0); - ListView_DeleteAllItems(HElv); - - 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; - - if (SzLimitScreenwriter[0]) - if (!Pl("episode_data","episode_datum","ISS", - iEp,"Screenwriter",SzLimitScreenwriter)) - continue; - - if (!BViewWatched) - if (Pl("track_episodes","watched","I",iEp)) continue; - - if (!BViewTVOriginal) - if (Pl("episode_data","tv_original","I",iEp)) continue; - - /* Format episode number string. */ - _stprintf_s(tszEpisode, sizeof(tszEpisode), TEXT("%d"), iEp); - - /* Insert item. */ - lviEpisode.iItem = iItem++; - lviEpisode.iSubItem = ELVSIEPISODE; - lviEpisode.pszText = tszEpisode; - lviEpisode.lParam = iEp; - ListView_InsertItem(HElv, &lviEpisode); - ElvUpdateItem(&lviEpisode); - } - - ElvDoSort(); - - lvfi.flags = LVFI_PARAM; - - /* Reset selection. */ - for (i = 0; aEpSel[i]; i++) { - int iItemSel; - lvfi.lParam = aEpSel[i]; - if ((iItemSel = ListView_FindItem(HElv, -1, &lvfi)) != -1) - ListView_SetItemState(HElv, iItemSel, - LVIS_SELECTED, LVIS_SELECTED); - } - if (iItemMark != -1) - ListView_SetSelectionMark(HElv, iItemMark); - - /* Reset focus. */ - if (iEpFocus) { - int iItemFocus; - i = 0; - do - lvfi.lParam = iEpFocus+i; - while ((iItemFocus = ListView_FindItem(HElv, -1, &lvfi)) == -1 - && i++ < 100); - if (iItemFocus != -1) - ListView_SetItemState(HElv, iItemFocus, - LVIS_FOCUSED, LVIS_FOCUSED); - } - - /* Try to reset scrolling position. Note that this must be - * done last, as focusing an item scrolls it into view. */ - i = 0; - do - lvfi.lParam = lviTop.lParam+i; - while ((iItemTopNew = ListView_FindItem(HElv, -1, &lvfi)) == -1 - && i++ < 100); - if (iItemTopNew != -1) - ElvSetTop(iItemTopNew); - - _stprintf_s(tszDisp, sizeof(tszDisp), TEXT("%d"), iItem); - SendMessage(HWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)tszDisp); - SendMessage(HElv, WM_SETREDRAW, TRUE, 0); -} - -/* Update episode name and rating. */ -void -ElvUpdateItem(LPLVITEM lpLvi) -{ - char *szName; - int iRating; - TCHAR *tszName; - static TCHAR tszRating[3]; - - tszName = NULL; - 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; - } - tszName = TszFromSz(szName, CP_UTF8); - if (tszName) - ListView_SetItemText(HElv, lpLvi->iItem, ELVSITITLE, tszName); - -r: if (!Pl("episode_data","episode_rating","Ii",lpLvi->lParam,&iRating)) { - ListView_SetItemText(HElv, lpLvi->iItem, ELVSIRATING, TEXT("")); - goto f; - } - - _stprintf_s(tszRating, sizeof(tszRating), TEXT("%d"), iRating); - ListView_SetItemText(HElv, lpLvi->iItem, ELVSIRATING, tszRating); - -f: if (tszName) free(tszName); -} -- cgit v1.2.3