1
0

fileview.cpp 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059
  1. #include "main.h"
  2. #include "./fileview.h"
  3. #include "./fileview_internal.h"
  4. #include "./resource.h"
  5. #include "./stockobjects.h"
  6. #include "../winamp/wa_dlg.h"
  7. #include "../nu/menushortcuts.h"
  8. #include "../nu/CGlobalAtom.h"
  9. #include <shlwapi.h>
  10. #include <strsafe.h>
  11. #ifndef ARRAYSIZE
  12. #define ARRAYSIZE(blah) (sizeof(blah)/sizeof(*blah))
  13. #endif
  14. #define FOLDERBROWSER_MIN_HEIGHT 64
  15. #define FILELIST_MIN_HEIGHT 120
  16. #define IDC_FILEVIEW_TOOLBAR 100001
  17. #define IDC_FILELIST 100010
  18. #define IDC_FILELIST_HEADER 100011
  19. #define IDT_INVALIDATELIST 1982
  20. #define IDT_ACTIVATELISTITEM 1983
  21. #define DELAY_INVALIDATELIST 75
  22. #define DELAY_ACTIVATELISTITEM 0
  23. #define ID_INTERNAL_UPDATE_COLUMN_INFO 20000
  24. typedef struct _FILEVIEW
  25. {
  26. FILEDATA fileData;
  27. UINT style;
  28. UINT sortColumn;
  29. BOOL bAscending;
  30. INT nMaxLineCount;
  31. INT infoTipIndex;
  32. BOOL infoTipFolded;
  33. INT statusIndex;
  34. HMENU hMenu;
  35. FILEVIEWCOLUMN szColumns[128 + 1]; // max allowed number of columns
  36. INT columnCount;
  37. LONG cyDivider;
  38. LONG cyToolbar;
  39. LONG yDivider;
  40. } FILEVIEW;
  41. #if (_WIN32_WINNT < 0x501)
  42. typedef struct tagLVSETINFOTIP
  43. {
  44. UINT cbSize;
  45. DWORD dwFlags;
  46. LPWSTR pszText;
  47. int iItem;
  48. int iSubItem;
  49. } LVSETINFOTIP, *PLVSETINFOTIP;
  50. #define LVM_SETINFOTIP (LVM_FIRST + 173)
  51. #endif // (_WIN32_WINNT < 0x501)
  52. static CGlobalAtom FILEVIEW_DATAW(L"FILEVIEW");
  53. #define GetFileView(__hwnd) ((FILEVIEW*)GetPropW((__hwnd), FILEVIEW_DATAW))
  54. static HMLIMGLST hmlilFileTypesSmall = NULL;
  55. static HMLIMGLST hmlilFileTypesLarge = NULL;
  56. static INT_PTR CALLBACK FileView_DialogProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  57. HWND FileView_CreateDialog(HWND hwndParent, UINT fStyle, HWND hwndInsertAfter, INT x, INT y, INT cx, INT cy)
  58. {
  59. HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_FILEVIEW, hwndParent, FileView_DialogProc, 0L);
  60. if (NULL == hwnd) return NULL;
  61. SetWindowPos(hwnd, hwndInsertAfter, x, y, cx, cy, SWP_NOACTIVATE);
  62. FileView_SetStyle(hwnd, fStyle, 0xFFFFFFFF);
  63. return hwnd;
  64. }
  65. static void FileView_LoadImages()
  66. {
  67. MLIMAGESOURCE_I mlis;
  68. ZeroMemory(&mlis, sizeof(MLIMAGESOURCE_I));
  69. mlis.type = SRC_TYPE_PNG;
  70. mlis.hInst = plugin.hDllInstance;
  71. if (NULL == hmlilFileTypesSmall)
  72. {
  73. hmlilFileTypesSmall = MLImageListI_Create(16, 16, MLILC_COLOR32_I, 3, 2, 3, hmlifMngr);
  74. if (NULL != hmlilFileTypesSmall)
  75. {
  76. INT imageList[] = { IDB_FILETYPE_UNKNOWN_SMALL, IDB_FILETYPE_AUDIO_SMALL, IDB_FILETYPE_VIDEO_SMALL, IDB_FILETYPE_PLAYLIST_SMALL,};
  77. for(int i = 0; i < sizeof(imageList)/sizeof(imageList[0]); i++)
  78. {
  79. mlis.lpszName = MAKEINTRESOURCEW(imageList[i]);
  80. MLImageListI_Add(hmlilFileTypesSmall, &mlis, MLIF_FILTER1_UID, imageList[i]);
  81. }
  82. }
  83. }
  84. if (NULL == hmlilFileTypesLarge)
  85. {
  86. hmlilFileTypesLarge = MLImageListI_Create(32, 32, MLILC_COLOR32_I, 3, 2, 3, hmlifMngr);
  87. if (NULL != hmlilFileTypesLarge)
  88. {
  89. INT imageList[] = { IDB_FILETYPE_UNKNOWN_LARGE, IDB_FILETYPE_AUDIO_LARGE, IDB_FILETYPE_VIDEO_LARGE, IDB_FILETYPE_PLAYLIST_LARGE, };
  90. for(int i = 0; i < sizeof(imageList)/sizeof(imageList[0]); i++)
  91. {
  92. mlis.lpszName = MAKEINTRESOURCEW(imageList[i]);
  93. MLImageListI_Add(hmlilFileTypesLarge, &mlis, MLIF_FILTER1_UID, imageList[i]);
  94. }
  95. }
  96. }
  97. }
  98. static LRESULT FileView_NotifyParent(HWND hdlg, UINT uCode, NMHDR *phdr)
  99. {
  100. HWND hParent = GetParent(hdlg);
  101. if (!phdr || !hParent) return 0L;
  102. phdr->code = uCode;
  103. phdr->hwndFrom = hdlg;
  104. phdr->idFrom = GetDlgCtrlID(hdlg);
  105. return SendMessageW(hParent, WM_NOTIFY, (WPARAM)phdr->idFrom, (LPARAM)phdr);
  106. }
  107. static BOOL FileView_OnSetRoot(HWND hwnd, LPCWSTR pszRoot)
  108. {
  109. HWND hBrowser = GetDlgItem(hwnd, IDC_FOLDER_BROWSER);
  110. if (NULL == hBrowser) return FALSE;
  111. BOOL br = FolderBrowser_SetRoot(hBrowser, pszRoot);
  112. PostMessageW(hwnd, FVM_REFRESH, 0, 0L);
  113. return br;
  114. }
  115. static INT FileView_OnGetRoot(HWND hwnd, LPCWSTR pszBufffer, INT cchMax)
  116. {
  117. HWND hBrowser = GetDlgItem(hwnd, IDC_FOLDER_BROWSER);
  118. if (NULL == hBrowser) return -1;
  119. return FolderBrowser_GetRoot(hBrowser, pszBufffer, cchMax);
  120. }
  121. static void FileView_AdjustSizes(HWND hdlg)
  122. {
  123. HWND hctrl;
  124. RECT rc, rw;
  125. UINT flags;
  126. INT nAddressBarHeight = 18;
  127. GetClientRect(hdlg, &rc);
  128. HDWP hdwp = BeginDeferWindowPos(4);
  129. if (NULL == hdwp) return;
  130. flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOMOVE;
  131. if (NULL != (hctrl = GetDlgItem(hdlg, IDC_LBL_ADDRESS)) && GetWindowRect(hctrl, &rw))
  132. {
  133. HDC hdc = GetDCEx(hctrl, NULL, DCX_CACHE);
  134. if (hdc)
  135. {
  136. HFONT hf = (HFONT)SendMessageW(hctrl, WM_GETFONT, 0, 0L);
  137. if (NULL == hf) hf = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  138. if (NULL != hf)
  139. {
  140. SIZE size;
  141. WCHAR szText[128] = {0};
  142. INT cch = (INT)SendMessageW(hctrl, WM_GETTEXT, (WPARAM)(sizeof(szText)/sizeof(szText[0])), (LPARAM)szText);
  143. HFONT hfo = (HFONT)SelectObject(hdc, hf);
  144. if (GetTextExtentPoint32W(hdc, szText, cch, &size))
  145. {
  146. nAddressBarHeight = size.cy + 4;
  147. rw.right = rw.left + size.cx;
  148. }
  149. SelectObject(hdc, hfo);
  150. }
  151. ReleaseDC(hctrl, hdc);
  152. }
  153. hdwp = DeferWindowPos(hdwp, hctrl, NULL, 0, 0, rw.right - rw.left, nAddressBarHeight, flags);
  154. }
  155. if (NULL != (hctrl = GetDlgItem(hdlg, IDC_EDT_PATH)) && GetWindowRect(hctrl, &rw))
  156. {
  157. hdwp = DeferWindowPos(hdwp, hctrl, NULL, 0, 0, rc.right - rc.left, nAddressBarHeight, flags);
  158. }
  159. if (NULL != (hctrl = GetDlgItem(hdlg, IDC_FILEVIEW_TOOLBAR)) && GetWindowRect(hctrl, &rw))
  160. {
  161. INT height = (INT)SendMessageW(hctrl, FVM_GETIDEALHEIGHT, 0, 0L);
  162. FILEVIEW *pfv = GetFileView(hdlg);
  163. if (pfv) pfv->cyToolbar = height;
  164. hdwp = DeferWindowPos(hdwp, hctrl, NULL, 0, 0, rc.right - rc.left, height, flags);
  165. }
  166. EndDeferWindowPos(hdwp);
  167. }
  168. static void FileView_LayoutWindows(HWND hdlg, BOOL bRedraw)
  169. {
  170. INT idList[] = {IDC_LBL_ADDRESS, IDC_EDT_PATH, IDC_FOLDER_BROWSER, IDC_HDELIM, IDC_FILEVIEW_TOOLBAR, IDC_FILELIST, };
  171. WINDOWPOS szwp[ARRAYSIZE(idList)], *pwp;
  172. RECT rc;
  173. LONG top, left, bottom;
  174. FILEVIEW *pfv = GetFileView(hdlg);
  175. if (!pfv) return;
  176. HDWP hdwp = BeginDeferWindowPos(ARRAYSIZE(idList));
  177. if (NULL == hdwp) return;
  178. for (INT i = 0; i < ARRAYSIZE(idList); i++)
  179. {
  180. szwp[i].hwnd = GetDlgItem(hdlg, idList[i]);
  181. szwp[i].flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOCOPYBITS | ((bRedraw) ? 0 : SWP_NOREDRAW);
  182. if (!szwp[i].hwnd || !GetWindowRect(szwp[i].hwnd, &rc)) SetRect(&rc, 0, 0, 0, 0);
  183. szwp[i].x = rc.left;
  184. szwp[i].y = rc.top;
  185. szwp[i].cx = rc.right - rc.left;
  186. szwp[i].cy = rc.bottom - rc.top;
  187. }
  188. GetClientRect(hdlg, &rc);
  189. top = rc.top + 2;
  190. left = rc.left + 2;
  191. if ((pwp = &szwp[0])->hwnd) // label address
  192. {
  193. pwp->y = top;
  194. pwp->x = left;
  195. hdwp = DeferWindowPos(hdwp, pwp->hwnd, NULL, pwp->x, pwp->y, pwp->cx, pwp->cy, pwp->flags);
  196. left += (pwp->cx + 2);
  197. }
  198. if ((pwp = &szwp[1])->hwnd) // edit path
  199. {
  200. pwp->y = top;
  201. pwp->x = left;
  202. pwp->cx = rc.right - pwp->x;
  203. if (pwp->cx < 0) pwp->cx = 0;
  204. hdwp = DeferWindowPos(hdwp, pwp->hwnd, NULL, pwp->x, pwp->y, pwp->cx, pwp->cy, pwp->flags);
  205. DWORD style = GetWindowLongPtrW(pwp->hwnd, GWL_STYLE);
  206. if ((pwp->cx == 0) != (0 != (WS_DISABLED & style)))
  207. SetWindowLongPtrW(pwp->hwnd, GWL_STYLE, (style & ~WS_DISABLED) | ((0 == pwp->cx) ? WS_DISABLED : 0));
  208. }
  209. left = rc.left;
  210. top = max((szwp[0].y + szwp[0].cy), (szwp[1].y + szwp[1].cy)) + 2;
  211. LONG yDividerReal = pfv->yDivider;
  212. LONG cyList = (rc.bottom - (yDividerReal + pfv->cyDivider));
  213. if (cyList < FILELIST_MIN_HEIGHT) cyList = FILELIST_MIN_HEIGHT;
  214. yDividerReal = rc.bottom - cyList - pfv->cyDivider;
  215. if (((yDividerReal + pfv->cyDivider) - top) < FOLDERBROWSER_MIN_HEIGHT)
  216. {
  217. cyList -= (FOLDERBROWSER_MIN_HEIGHT - ((yDividerReal + pfv->cyDivider) - top));
  218. if (cyList < FILELIST_MIN_HEIGHT) cyList = FILELIST_MIN_HEIGHT;
  219. yDividerReal = rc.bottom - cyList - pfv->cyDivider;
  220. }
  221. if ((pwp = &szwp[2])->hwnd) // folderbrowser
  222. {
  223. pwp->x = left;
  224. pwp->y = top;
  225. pwp->cx = rc.right - rc.left;
  226. pwp->cy = yDividerReal - top;
  227. if (pwp->cy < (FOLDERBROWSER_MIN_HEIGHT - pfv->cyDivider)) pwp->cy = 0;
  228. hdwp = DeferWindowPos(hdwp, pwp->hwnd, NULL, pwp->x, pwp->y, pwp->cx, pwp->cy, pwp->flags);
  229. DWORD style = GetWindowLongPtrW(pwp->hwnd, GWL_STYLE);
  230. if ((pwp->cy == 0) != (0 != (WS_DISABLED & style)))
  231. SetWindowLongPtrW(pwp->hwnd, GWL_STYLE, (style & ~WS_DISABLED) | ((0 == pwp->cy) ? WS_DISABLED : 0));
  232. top += pwp->cy;
  233. }
  234. if ((pwp = &szwp[3])->hwnd) // delimiter
  235. {
  236. pwp->x = left;
  237. pwp->y = top;
  238. pwp->cx = rc.right - rc.left;
  239. pwp->cy = (szwp[2].cy > 0) ? pfv->cyDivider : 0;
  240. if (pwp->cy < 0) pwp->cy = 0;
  241. hdwp = DeferWindowPos(hdwp, pwp->hwnd, NULL, pwp->x, pwp->y, pwp->cx, pwp->cy, pwp->flags);
  242. top += pwp->cy;
  243. DWORD style = GetWindowLongPtrW(pwp->hwnd, GWL_STYLE);
  244. if ((pwp->cy == 0) != (0 != (WS_DISABLED & style)))
  245. SetWindowLongPtrW(pwp->hwnd, GWL_STYLE, (style & ~WS_DISABLED) | ((0 == pwp->cy) ? WS_DISABLED : 0));
  246. }
  247. bottom = rc.bottom;
  248. if ((pwp = &szwp[4])->hwnd) // toolbar
  249. {
  250. pwp->x = left;
  251. pwp->y = top;
  252. pwp->cx = rc.right - rc.left;
  253. pwp->cy = pfv->cyToolbar;
  254. if ((bottom - pwp->cy) < 64) pwp->cy = 0;
  255. hdwp = DeferWindowPos(hdwp, pwp->hwnd, NULL, pwp->x, pwp->y, pwp->cx, pwp->cy, pwp->flags);
  256. top += pwp->cy;
  257. DWORD style = GetWindowLongPtrW(pwp->hwnd, GWL_STYLE);
  258. if ((pwp->cy == 0) != (0 != (WS_DISABLED & style)))
  259. SetWindowLongPtrW(pwp->hwnd, GWL_STYLE, (style & ~WS_DISABLED) | ((0 == pwp->cy) ? WS_DISABLED : 0));
  260. }
  261. if ((pwp = &szwp[5])->hwnd) // file list
  262. {
  263. pwp->x = left;
  264. pwp->y = top;
  265. pwp->cx = rc.right - rc.left;
  266. pwp->cy = bottom - top;
  267. if (pwp->cy < 0) pwp->cy = 0;
  268. hdwp = DeferWindowPos(hdwp, pwp->hwnd, NULL, pwp->x, pwp->y, pwp->cx, pwp->cy, pwp->flags);
  269. DWORD style = GetWindowLongPtrW(pwp->hwnd, GWL_STYLE);
  270. if ((pwp->cy == 0) != (0 != (WS_DISABLED & style)))
  271. SetWindowLongPtrW(pwp->hwnd, GWL_STYLE, (style & ~WS_DISABLED) | ((0 == pwp->cy) ? WS_DISABLED : 0));
  272. }
  273. EndDeferWindowPos(hdwp);
  274. pfv->nMaxLineCount = (INT)SendDlgItemMessageW(hdlg, IDC_FILELIST, LVM_GETCOUNTPERPAGE, 0, 0L);
  275. }
  276. static INT FileView_GetPreferredColumnWidth(HWND hdlg, UINT columnId)
  277. {
  278. HWND hctrl;
  279. FILEDATA *pfd;
  280. INT nameWidth = 0, prevMaxLen = 0;
  281. HDC hdc;
  282. HFONT hf, hfo = NULL;
  283. SIZE size;
  284. FILEVIEW *pfv = GetFileView(hdlg);
  285. if (!pfv) return -1;
  286. pfd = &pfv->fileData;
  287. hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  288. if (!hctrl) return -1;
  289. hdc = GetDCEx(hctrl, NULL, DCX_CACHE);
  290. if (!hdc) return -1;
  291. hf = (HFONT)SendMessageW(hctrl, WM_GETFONT, 0, 0L);
  292. if (NULL == hf) hf = (HFONT)MlStockObjects_Get(DEFAULT_FONT);
  293. if (NULL != hf) hfo = (HFONT)SelectObject(hdc, hf);
  294. for (size_t i = 0; i < pfd->count; i++)
  295. {
  296. LPCWSTR pszText = pfd->pRec[i].Info.cFileName;
  297. INT len = (pszText) ? lstrlenW(pszText) : 0;
  298. if (len > 0 && len > (prevMaxLen - 3) &&
  299. hdc && GetTextExtentPoint32W(hdc, pszText, len, &size) &&
  300. size.cx > nameWidth)
  301. {
  302. nameWidth = size.cx;
  303. prevMaxLen = len;
  304. }
  305. }
  306. if (NULL != hfo) SelectObject(hdc, hfo);
  307. ReleaseDC(hctrl, hdc);
  308. if (nameWidth < 100) nameWidth = 100;
  309. return nameWidth;
  310. }
  311. static void FileView_UpdateFileView(HWND hdlg, LPCWSTR pszPath)
  312. {
  313. HWND hwndList;
  314. FILEVIEW *pfv = GetFileView(hdlg);
  315. if (!pfv) return;
  316. if (pszPath && L'\0' != *pszPath &&
  317. CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT),
  318. NORM_IGNORECASE, pszPath, -1, pfv->fileData.szPath, -1)) return;
  319. pfv->fileData.count = 0;
  320. pfv->fileData.szPath[0] = 0x00;
  321. hwndList = GetDlgItem(hdlg, IDC_FILELIST);
  322. if (hwndList) SendMessageW(hwndList, LVM_SETITEMCOUNT, 0, 0L);
  323. size_t count = ((size_t)-1);
  324. if (pszPath && L'\0' != *pszPath)
  325. {
  326. FILESYSTEMINFO fi = {sizeof(FILESYSTEMINFO), };
  327. HWND hfb = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  328. if (!hfb || !FolderBrowser_GetFileSystemInfo(hfb, &fi)) return;
  329. count = FileView_ReadFileData(&pfv->fileData, pszPath, pfv->style, &fi);
  330. }
  331. FileViewMeta_TruncateQueue(0);
  332. if (((size_t)-1) != count)
  333. {
  334. StringCchCopyW(pfv->fileData.szPath, sizeof(pfv->fileData.szPath)/sizeof(pfv->fileData.szPath[0]), pszPath);
  335. FileView_SortByColumn(&pfv->fileData, pfv->sortColumn);
  336. if (hwndList)
  337. {
  338. SendMessageW(hwndList, LVM_SETITEMCOUNT, (WPARAM)count, LVSICF_NOINVALIDATEALL);
  339. if (FVS_LISTVIEW == (FVS_VIEWMASK & pfv->style))
  340. {
  341. INT w = FileView_GetPreferredColumnWidth(hdlg, FVCOLUMN_NAME);
  342. if (-1 != w) SendMessageW(hwndList, LVM_SETCOLUMNWIDTH, 0, w + 20);
  343. }
  344. }
  345. }
  346. NMHDR nmhdr;
  347. FileView_NotifyParent(hdlg, FVN_FOLDERCHANGED, &nmhdr);
  348. }
  349. static BOOL FileView_IsTypePlayable(UINT fileType, UINT uEnqueueFilter)
  350. {
  351. switch(fileType)
  352. {
  353. case FVFT_AUDIO: return (0 != (FVEF_AUDIO & uEnqueueFilter));
  354. case FVFT_VIDEO: return (0 != (FVEF_VIDEO & uEnqueueFilter));
  355. case FVFT_PLAYLIST: return (0 != (FVEF_PLAYLIST & uEnqueueFilter));
  356. case FVFT_UNKNOWN: return (0 != (FVEF_UNKNOWN & uEnqueueFilter));
  357. }
  358. return FALSE;
  359. }
  360. static void FileView_InitializeListColumn(HWND hdlg, LVCOLUMNW *pListColumn, const FILEVIEWCOLUMN *pViewColumn)
  361. {
  362. pListColumn->mask = LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
  363. pListColumn->pszText = IS_INTRESOURCE(pViewColumn->pszText) ? WASABI_API_LNGSTRINGW((UINT)(UINT_PTR)pViewColumn->pszText) : pViewColumn->pszText;
  364. pListColumn->cx = pViewColumn->width;
  365. pListColumn->fmt = pViewColumn->format;
  366. if (-1 == pListColumn->cx)
  367. {
  368. pListColumn->cx = FileView_GetPreferredColumnWidth(hdlg, pViewColumn->id);
  369. if (-1 == pListColumn->cx) pListColumn->cx = 140;
  370. pListColumn->cx += 24;
  371. }
  372. }
  373. static void CALLBACK OnDividerMoved(HWND hdiv, INT nPos, LPARAM param)
  374. {
  375. HWND hParent;
  376. hParent = GetParent(hdiv);
  377. if (hParent) FileView_SetDividerPos(hParent, nPos, FVRF_VALIDATE);
  378. }
  379. static BOOL FileView_OnInitDialog(HWND hdlg, HWND hwndFocus, LPARAM lParam)
  380. {
  381. FILEVIEW *pfv;
  382. RECT rw;
  383. pfv = (FILEVIEW*)calloc(1, sizeof(FILEVIEW));
  384. if (pfv)
  385. {
  386. pfv->style = ((UINT)-1);
  387. pfv->bAscending = TRUE;
  388. pfv->sortColumn = -1;
  389. pfv->yDivider = 240;
  390. }
  391. else
  392. {
  393. DestroyWindow(hdlg);
  394. return 0;
  395. }
  396. HWND hctrl;
  397. SkinWindowEx(hdlg, SKINNEDWND_TYPE_AUTO, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT);
  398. hctrl = GetDlgItem(hdlg, IDC_LBL_ADDRESS);
  399. SkinWindowEx(hctrl, SKINNEDWND_TYPE_STATIC, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT);
  400. hctrl = GetDlgItem(hdlg, IDC_EDT_PATH);
  401. SkinWindowEx(hctrl, SKINNEDWND_TYPE_AUTO, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT | SWES_VCENTER | SWES_SELECTONCLICK);
  402. hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  403. SkinWindowEx(hctrl, SKINNEDWND_TYPE_AUTO, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT);
  404. hctrl = GetDlgItem(hdlg, IDC_HDELIM);
  405. SkinWindowEx(hctrl, SKINNEDWND_TYPE_DIVIDER, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT | SWDIV_HORZ /*| SWDIV_NOHILITE*/);
  406. MLSkinnedDivider_SetCallback(hctrl, OnDividerMoved, NULL);
  407. pfv->cyDivider = (GetWindowRect(hctrl, &rw)) ? (rw.bottom - rw.top) : 0;
  408. HWND htool = FileViewToolbar_Create(hdlg);
  409. if (htool)
  410. {
  411. SetWindowLongPtrW(htool, GWLP_ID, IDC_FILEVIEW_TOOLBAR);
  412. SetWindowPos(htool, GetDlgItem(hdlg, IDC_HDELIM), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  413. SkinWindowEx(htool, SKINNEDWND_TYPE_AUTO, SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT);
  414. pfv->cyToolbar = (GetWindowRect(htool, &rw)) ? (rw.bottom - rw.top) : 0;
  415. }
  416. INT viewIndex = 0;
  417. for (int i = 0; i < RegisteredColumnsCount; i++)
  418. {
  419. if (FVCOLUMN_NAME == szRegisteredColumns[i].id)
  420. {
  421. CopyMemory(&pfv->szColumns[viewIndex], &szRegisteredColumns[i], sizeof(FILEVIEWCOLUMN));
  422. viewIndex++;
  423. break;
  424. }
  425. }
  426. pfv->columnCount = viewIndex;
  427. if (!SetPropW(hdlg, FILEVIEW_DATAW, pfv))
  428. {
  429. free(pfv);
  430. DestroyWindow(hdlg);
  431. return FALSE;
  432. }
  433. FileViewMeta_InitializeStorage(hdlg);
  434. FileView_LoadImages();
  435. FileView_SetStyle(hdlg, FVS_LISTVIEW | FVS_HIDEEXTENSION | FVS_IGNOREHIDDEN | FVS_SHOWAUDIO | FVS_SHOWVIDEO | FVS_SHOWPLAYLIST | FVS_SHOWUNKNOWN, 0xFFFFFFFF);
  436. FileView_AdjustSizes(hdlg);
  437. FileView_LayoutWindows(hdlg, FALSE);
  438. if (WASABI_API_APP)
  439. {
  440. HACCEL hAccel = WASABI_API_LOADACCELERATORSW(IDR_ACCELERATOR_FILEVIEW);
  441. if (hAccel) WASABI_API_APP->app_addAccelerators(hdlg, &hAccel, 1, TRANSLATE_MODE_CHILD);
  442. }
  443. return FALSE;
  444. }
  445. static void FileView_OnDestroy(HWND hdlg)
  446. {
  447. FILEVIEW *pfv = GetFileView(hdlg);
  448. if (pfv)
  449. {
  450. RemovePropW(hdlg,FILEVIEW_DATAW);
  451. if (pfv->fileData.allocated)
  452. {
  453. if (pfv->fileData.pRec) free(pfv->fileData.pRec);
  454. if (pfv->fileData.pSort) free(pfv->fileData.pSort);
  455. }
  456. free(pfv);
  457. }
  458. FileViewMeta_ReleaseStorage(hdlg);
  459. if (WASABI_API_APP) WASABI_API_APP->app_removeAccelerators(hdlg);
  460. }
  461. static void FileView_OnWindowPosChanged(HWND hdlg, WINDOWPOS *pwp)
  462. {
  463. if (SWP_NOSIZE == ((SWP_NOSIZE | SWP_FRAMECHANGED) & pwp->flags)) return;
  464. FileView_LayoutWindows(hdlg, (0 == (SWP_NOREDRAW & pwp->flags)));
  465. }
  466. static BOOL FileView_OnRefresh(HWND hdlg, BOOL bIncludeFolder, BOOL bForce)
  467. {
  468. NMHDR nmhdr;
  469. FILEVIEW *pfv = GetFileView(hdlg);
  470. if (!pfv) return FALSE;
  471. if (bForce) pfv->fileData.szPath[0] = 0x00;
  472. if (bIncludeFolder)
  473. {
  474. wchar_t szText[MAX_PATH*4] = {0};
  475. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  476. if (FolderBrowser_GetCurrentPath(hctrl, szText, sizeof(szText)/sizeof(szText[0])))
  477. {
  478. FolderBrowser_SetCurrentPath(hctrl, L"", FALSE);
  479. FolderBrowser_SetCurrentPath(hctrl, szText, TRUE);
  480. }
  481. }
  482. nmhdr.code = FBN_SELCHANGED;
  483. nmhdr.idFrom = IDC_FOLDER_BROWSER;
  484. nmhdr.hwndFrom = GetDlgItem(hdlg, (INT)nmhdr.idFrom);
  485. SendMessageW(hdlg, WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
  486. return TRUE;
  487. }
  488. static BOOL FileView_OnSetView(HWND hdlg, UINT uView, BOOL bRefresh)
  489. {
  490. FILEVIEW *pfv = GetFileView(hdlg);
  491. if (!pfv) return FALSE;
  492. if ((FVS_VIEWMASK & pfv->style) == uView) return TRUE;
  493. HWND hctrl, hnew;
  494. RECT rw;
  495. BOOL bFocused;
  496. DWORD style;
  497. switch(uView)
  498. {
  499. case FVS_LISTVIEW: style = LVS_LIST; break;
  500. case FVS_ICONVIEW: style = LVS_ICON; break;
  501. case FVS_DETAILVIEW: style = LVS_REPORT; break;
  502. default: return FALSE;
  503. }
  504. style |= WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP |
  505. LVS_SHOWSELALWAYS | LVS_ALIGNTOP | LVS_OWNERDATA | LVS_SHAREIMAGELISTS;
  506. hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  507. if (!hctrl || !GetWindowRect(hctrl, &rw)) SetRect(&rw, 0, 0, 1, 1);
  508. MapWindowPoints(HWND_DESKTOP, hdlg, (POINT*)&rw, 2);
  509. bFocused = (hctrl != NULL && hctrl == GetFocus());
  510. hnew = CreateWindowExW(WS_EX_NOPARENTNOTIFY, WC_LISTVIEWW, L"Files", style,
  511. rw.left, rw.top, rw.right - rw.left, rw.bottom - rw.top,
  512. hdlg, NULL, plugin.hDllInstance, 0L);
  513. if (!hnew) return FALSE;
  514. pfv->style = (pfv->style & ~FVS_VIEWMASK) | uView;
  515. if (hctrl) SetWindowLongPtrW(hctrl, GWLP_ID, 0);
  516. SetWindowLongPtrW(hnew, GWLP_ID, IDC_FILELIST);
  517. DWORD exStyle;
  518. exStyle = SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT | SWLVS_DOUBLEBUFFER;
  519. if (FVS_DETAILVIEW == uView) exStyle |= SWLVS_FULLROWSELECT;
  520. SkinWindowEx(hnew, SKINNEDWND_TYPE_LISTVIEW, exStyle);
  521. if (FVS_DETAILVIEW == uView)
  522. {
  523. LVCOLUMNW lvc;
  524. INT sortIndex = -1;
  525. for (int i = 0; i < pfv->columnCount; i++)
  526. {
  527. FileView_InitializeListColumn(hdlg, &lvc, &pfv->szColumns[i]);
  528. if (pfv->szColumns[i].id == pfv->sortColumn) sortIndex = i;
  529. SendMessageW(hnew, LVM_INSERTCOLUMNW, i, (LPARAM)&lvc);
  530. }
  531. MLSkinnedListView_DisplaySort(hnew, sortIndex, pfv->bAscending);
  532. }
  533. SendMessageW(hnew, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)MLImageListI_GetRealList(hmlilFileTypesLarge));
  534. SendMessageW(hnew, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)MLImageListI_GetRealList(hmlilFileTypesSmall));
  535. if (FVS_DETAILVIEW != uView) SendMessageW(hnew, LVM_ARRANGE, LVA_ALIGNLEFT | LVA_ALIGNTOP | LVA_SNAPTOGRID, 0L);
  536. // if (FVS_ICONVIEW == uView) SendMessageW(hnew, LVM_SETICONSPACING, 0, MAKELPARAM(96, 96));
  537. exStyle = LVS_EX_INFOTIP | LVS_EX_LABELTIP;
  538. if (FVS_DETAILVIEW == uView) exStyle |= LVS_EX_HEADERDRAGDROP;
  539. SendMessageW(hnew, LVM_SETEXTENDEDLISTVIEWSTYLE, exStyle, exStyle);
  540. HWND hHeader = (HWND)SendMessageW(hnew, LVM_GETHEADER, 0, 0L);
  541. if (hHeader) SetWindowLongPtrW(hHeader, GWLP_ID, IDC_FILELIST_HEADER);
  542. FileViewMeta_TruncateQueue(0);
  543. SetWindowPos(hnew, (hctrl) ? hctrl : GetDlgItem(hdlg, IDC_HDELIM), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  544. ShowWindow(hnew, SW_SHOWNA);
  545. if (bFocused) SetFocus(hnew);
  546. if (hctrl)
  547. {
  548. if (WASABI_API_APP) WASABI_API_APP->app_removeAccelerators(hctrl);
  549. DestroyWindow(hctrl);
  550. }
  551. SendDlgItemMessageW(hdlg,IDC_FILEVIEW_TOOLBAR, FVM_SETSTYLE, FVS_VIEWMASK, (LPARAM)uView);
  552. if (bRefresh) FileView_OnRefresh(hdlg, FALSE, TRUE);
  553. return TRUE;
  554. }
  555. static void CALLBACK FileView_OnInvalidateListElapsed(HWND hdlg, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  556. {
  557. KillTimer(hdlg, idEvent);
  558. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  559. if (hctrl) InvalidateRect(hctrl, NULL, FALSE);
  560. }
  561. static void CALLBACK FileView_OnMetaDataDiscovered(LPCWSTR pszFileName, ULONG_PTR param)
  562. {
  563. if (!param) return;
  564. HWND hdlg = (HWND)param;
  565. FILEVIEW *pfv = GetFileView(hdlg);
  566. if (!pfv) return;
  567. LPCWSTR pszFile = PathFindFileNameW(pszFileName);
  568. INT cchPath = (INT)(ULONG_PTR)(pszFile - pszFileName);
  569. if (cchPath) cchPath--;
  570. if (CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pfv->fileData.szPath, -1, pszFileName, cchPath))
  571. return;
  572. SetTimer(hdlg, IDT_INVALIDATELIST, DELAY_INVALIDATELIST, FileView_OnInvalidateListElapsed);
  573. if (pfv && (((size_t)pfv->infoTipIndex) < pfv->fileData.count || ((size_t)pfv->statusIndex) < pfv->fileData.count))
  574. {
  575. WCHAR szBuffer[2048] = {0};
  576. LPCWSTR pszTipFile;
  577. FILEDATA *pfd = &pfv->fileData;
  578. FILERECORD *pfr;
  579. size_t index;
  580. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  581. if (((size_t)pfv->infoTipIndex) < pfv->fileData.count)
  582. {
  583. index = ((pfv->bAscending) ? pfv->infoTipIndex : (pfd->count - pfv->infoTipIndex - 1));
  584. pfr = &pfd->pRec[pfd->pSort[index]];
  585. if (pfr->extOffset == (lstrlenW(pfr->Info.cFileName) + 1))
  586. {
  587. StringCchPrintfW(szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]), L"%s.%s", pfr->Info.cFileName, (pfr->Info.cFileName + pfr->extOffset));
  588. pszTipFile = szBuffer;
  589. }
  590. else pszTipFile = pfr->Info.cFileName;
  591. if (CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszFile, -1, pszTipFile, -1))
  592. {
  593. if (FileViewMeta_Discover(pfv->fileData.szPath, pfr, NULL, NULL, 0) && pfr->pMeta)
  594. {
  595. LVSETINFOTIP tip;
  596. ZeroMemory(&tip, sizeof(LVSETINFOTIP));
  597. tip.cbSize = sizeof(LVSETINFOTIP);
  598. tip.dwFlags = 0;
  599. tip.iItem = pfv->infoTipIndex;
  600. tip.iSubItem = 0;
  601. tip.pszText = szBuffer;
  602. if (pfv->infoTipFolded)
  603. {
  604. StringCchPrintfExW(tip.pszText, sizeof(szBuffer)/sizeof(szBuffer[0]), &tip.pszText, NULL, STRSAFE_IGNORE_NULLS, L"%s\r\n", pszTipFile);
  605. }
  606. FileView_FormatFileInfo(pfr, tip.pszText, sizeof(szBuffer)/sizeof(szBuffer[0]) - (ULONG_PTR)(tip.pszText - szBuffer), FIF_TOOLTIP);
  607. tip.pszText = szBuffer;
  608. SendMessageW(hctrl, LVM_SETINFOTIP, 0, (LPARAM)&tip);
  609. if (pfv->statusIndex == pfv->infoTipIndex)
  610. {
  611. NMHDR nmhdr;
  612. FileView_NotifyParent(hdlg, FVN_STATUSCHANGED, &nmhdr);
  613. pfv->statusIndex = -1;
  614. }
  615. }
  616. pfv->infoTipIndex = -1;
  617. pfv->infoTipFolded = FALSE;
  618. }
  619. }
  620. if (((size_t)pfv->statusIndex) < pfv->fileData.count)
  621. {
  622. index = ((pfv->bAscending) ? pfv->statusIndex : (pfd->count - pfv->statusIndex - 1));
  623. pfr = &pfd->pRec[pfd->pSort[index]];
  624. if (pfr->extOffset == (lstrlenW(pfr->Info.cFileName) + 1))
  625. {
  626. StringCchPrintfW(szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]), L"%s.%s", pfr->Info.cFileName, (pfr->Info.cFileName + pfr->extOffset));
  627. pszTipFile = szBuffer;
  628. }
  629. else pszTipFile = pfr->Info.cFileName;
  630. if (CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, pszFile, -1, pszTipFile, -1))
  631. {
  632. if (FileViewMeta_Discover(pfv->fileData.szPath, pfr, NULL, NULL, 0) && pfr->pMeta)
  633. {
  634. NMHDR nmhdr;
  635. FileView_NotifyParent(hdlg, FVN_STATUSCHANGED, &nmhdr);
  636. }
  637. pfv->statusIndex = -1;
  638. }
  639. }
  640. }
  641. }
  642. static COLORREF rgbText, rgbTextBk;
  643. static INT_PTR FileList_OnCustomDraw(HWND hdlg, NMLVCUSTOMDRAW *pcd)
  644. {
  645. switch(pcd->nmcd.dwDrawStage)
  646. {
  647. case CDDS_PREPAINT:
  648. return CDRF_NOTIFYITEMDRAW;
  649. case CDDS_ITEMPREPAINT:
  650. rgbText = pcd->clrText;
  651. rgbTextBk = pcd->clrTextBk;
  652. break;
  653. }
  654. return CDRF_DODEFAULT;
  655. }
  656. static void FileList_OnGetDispInfo(HWND hdlg, NMLVDISPINFOW *pdi)
  657. {
  658. FILEVIEW *pfv = GetFileView(hdlg);
  659. if (!pfv) return;
  660. FILEDATA *pfd = &pfv->fileData;
  661. if (pdi->item.iItem >= (INT)pfd->count)
  662. {
  663. pdi->item.pszText = L"Bad Index";
  664. return;
  665. }
  666. size_t index = ((pfv->bAscending) ? pdi->item.iItem : (pfd->count - pdi->item.iItem - 1));
  667. FILERECORD *pfr = &pfd->pRec[pfd->pSort[index]];
  668. if ((LVIF_TEXT & pdi->item.mask))
  669. {
  670. switch(pfv->szColumns[pdi->item.iSubItem].id)
  671. {
  672. case FVCOLUMN_NAME: pdi->item.pszText = pfr->Info.cFileName; break;
  673. case FVCOLUMN_SIZE: WASABI_API_LNG->FormattedSizeString(pdi->item.pszText, pdi->item.cchTextMax, (((__int64)pfr->Info.nFileSizeHigh << 32) | pfr->Info.nFileSizeLow)); break;
  674. case FVCOLUMN_TYPE: FileView_FormatType(pfr->fileType, pdi->item.pszText, pdi->item.cchTextMax); break;
  675. case FVCOLUMN_MODIFIED: FileView_FormatFileTime(&pfr->Info.ftLastWriteTime, pdi->item.pszText, pdi->item.cchTextMax); break;
  676. case FVCOLUMN_CREATED: FileView_FormatFileTime(&pfr->Info.ftCreationTime, pdi->item.pszText, pdi->item.cchTextMax); break;
  677. case FVCOLUMN_EXTENSION:
  678. if (pfr->extOffset)
  679. {
  680. StringCchCopyW(pdi->item.pszText, pdi->item.cchTextMax, &pfr->Info.cFileName[pfr->extOffset]);
  681. CharUpperBuffW(pdi->item.pszText, lstrlenW(pdi->item.pszText));
  682. }
  683. else pdi->item.pszText = NULL;
  684. break;
  685. case FVCOLUMN_ATTRIBUTES: FileView_FormatAttributes(pfr->Info.dwFileAttributes, pdi->item.pszText, pdi->item.cchTextMax); break;
  686. case FVCOLUMN_ARTIST:
  687. case FVCOLUMN_ALBUM:
  688. case FVCOLUMN_TITLE:
  689. case FVCOLUMN_INMLDB:
  690. case FVCOLUMN_GENRE:
  691. case FVCOLUMN_YEAR:
  692. case FVCOLUMN_LENGTH:
  693. case FVCOLUMN_BITRATE:
  694. case FVCOLUMN_TRACK:
  695. case FVCOLUMN_DISC:
  696. case FVCOLUMN_COMMENT:
  697. case FVCOLUMN_PUBLISHER:
  698. case FVCOLUMN_COMPOSER:
  699. case FVCOLUMN_ALBUMARTIST:
  700. if (FileViewMeta_Discover(pfv->fileData.szPath, pfr, FileView_OnMetaDataDiscovered, (ULONG_PTR)hdlg, pfv->nMaxLineCount) &&
  701. pfr->pMeta)
  702. {
  703. INT nVal, nVal2;
  704. switch(pfv->szColumns[pdi->item.iSubItem].id)
  705. {
  706. case FVCOLUMN_ARTIST: FileViewMeta_GetString(pfr->pMeta, MF_ARTIST, (LPCWSTR*)&pdi->item.pszText); break;
  707. case FVCOLUMN_ALBUM: FileViewMeta_GetString(pfr->pMeta, MF_ALBUM, (LPCWSTR*)&pdi->item.pszText); break;
  708. case FVCOLUMN_TITLE: FileViewMeta_GetString(pfr->pMeta, MF_TITLE, (LPCWSTR*)&pdi->item.pszText); break;
  709. case FVCOLUMN_INMLDB:
  710. if (FileViewMeta_GetInt(pfr->pMeta, MF_SOURCE, &nVal) && METADATA_SOURCE_UNKNOWN != nVal)
  711. FileView_FormatYesNo(METADATA_SOURCE_MLDB == nVal, pdi->item.pszText, pdi->item.cchTextMax);
  712. break;
  713. case FVCOLUMN_GENRE: FileViewMeta_GetString(pfr->pMeta, MF_GENRE, (LPCWSTR*)&pdi->item.pszText); break;
  714. case FVCOLUMN_YEAR:
  715. if (FileViewMeta_GetInt(pfr->pMeta, MF_YEAR, &nVal)) FileView_FormatYear(nVal, pdi->item.pszText, pdi->item.cchTextMax);
  716. break;
  717. case FVCOLUMN_LENGTH:
  718. if (FileViewMeta_GetInt(pfr->pMeta, MF_LENGTH, &nVal)) FileView_FormatLength(nVal, pdi->item.pszText, pdi->item.cchTextMax);
  719. break;
  720. case FVCOLUMN_BITRATE:
  721. if (FileViewMeta_GetInt(pfr->pMeta, MF_BITRATE, &nVal))
  722. FileView_FormatBitrate(nVal, pdi->item.pszText, pdi->item.cchTextMax); break;
  723. case FVCOLUMN_TRACK:
  724. if (!FileViewMeta_GetInt(pfr->pMeta, MF_TRACKNUM, &nVal)) nVal = -1;
  725. if (!FileViewMeta_GetInt(pfr->pMeta, MF_TRACKCOUNT, &nVal2)) nVal2 = -1;
  726. if (nVal != -1) FileView_FormatIntSlashInt(nVal, nVal2, pdi->item.pszText, pdi->item.cchTextMax);
  727. break;
  728. case FVCOLUMN_DISC:
  729. if (!FileViewMeta_GetInt(pfr->pMeta, MF_DISCNUM, &nVal)) nVal = -1;
  730. if (!FileViewMeta_GetInt(pfr->pMeta, MF_DISCCOUNT, &nVal2)) nVal2 = -1;
  731. if (nVal != -1) FileView_FormatIntSlashInt(nVal, nVal2, pdi->item.pszText, pdi->item.cchTextMax);
  732. break;
  733. case FVCOLUMN_COMMENT: FileViewMeta_GetString(pfr->pMeta, MF_COMMENT, (LPCWSTR*)&pdi->item.pszText); break;
  734. case FVCOLUMN_PUBLISHER: FileViewMeta_GetString(pfr->pMeta, MF_PUBLISHER, (LPCWSTR*)&pdi->item.pszText); break;
  735. case FVCOLUMN_COMPOSER: FileViewMeta_GetString(pfr->pMeta, MF_COMPOSER, (LPCWSTR*)&pdi->item.pszText); break;
  736. case FVCOLUMN_ALBUMARTIST: FileViewMeta_GetString(pfr->pMeta, MF_ALBUMARTIST, (LPCWSTR*)&pdi->item.pszText); break;
  737. }
  738. }
  739. break;
  740. }
  741. }
  742. if(LVIF_IMAGE & pdi->item.mask)
  743. {
  744. INT index;
  745. switch(pfr->fileType)
  746. {
  747. case FVFT_AUDIO: index = 1; break;
  748. case FVFT_VIDEO: index = 2; break;
  749. case FVFT_PLAYLIST: index = 3; break;
  750. default: index = 0; break;
  751. }
  752. pdi->item.iImage = MLImageListI_GetRealIndex((FVS_ICONVIEW == (FVS_VIEWMASK & pfv->style)) ? hmlilFileTypesLarge : hmlilFileTypesSmall, index, rgbTextBk, rgbText);
  753. }
  754. }
  755. static void CALLBACK FileView_OnActivateListItemElapsed(HWND hdlg, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  756. {
  757. KillTimer(hdlg, idEvent);
  758. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  759. if (!hctrl) return;
  760. INT index = (INT)SendMessageW(hctrl, LVM_GETNEXTITEM, 0, (LPARAM)(LVNI_ALL | LVNI_FOCUSED));
  761. if (-1 == index)
  762. {
  763. LVITEM lvi;
  764. lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  765. lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
  766. SendMessageW(hctrl, LVM_SETITEMSTATE, 0, (LPARAM)&lvi);
  767. }
  768. }
  769. static void FileList_OnSetFocus(HWND hdlg, NMHDR *phdr)
  770. {
  771. SetTimer(hdlg, IDT_ACTIVATELISTITEM, DELAY_ACTIVATELISTITEM, FileView_OnActivateListItemElapsed);
  772. }
  773. static void FileList_OnGetInfoTip(HWND hdlg, NMLVGETINFOTIPW *pit)
  774. {
  775. if (LVGIT_UNFOLDED & pit->dwFlags) pit->pszText[0] = L'\0';
  776. else StringCchCatW(pit->pszText, pit->cchTextMax, L"\r\n");
  777. FILEVIEW *pfv = GetFileView(hdlg);
  778. if (!pfv) return;
  779. FILEDATA *pfd = &pfv->fileData;
  780. if (pit->iItem < (INT)pfd->count)
  781. {
  782. size_t index = ((pfv->bAscending) ? pit->iItem : (pfd->count - pit->iItem - 1));
  783. FILERECORD *pfr = &pfd->pRec[pfd->pSort[index]];
  784. if (FVFT_UNKNOWN != pfr->fileType &&
  785. !FileViewMeta_Discover(pfv->fileData.szPath, pfr, FileView_OnMetaDataDiscovered, (ULONG_PTR)hdlg, 0))
  786. {
  787. pfv->infoTipFolded = (0 == (LVGIT_UNFOLDED & pit->dwFlags));
  788. pfv->infoTipIndex = pit->iItem;
  789. }
  790. INT len = lstrlenW(pit->pszText);
  791. FileView_FormatFileInfo(pfr, pit->pszText + len, pit->cchTextMax - len, FIF_TOOLTIP);
  792. }
  793. }
  794. static void FileList_OnKeyDown(HWND hdlg, NMLVKEYDOWN *pkd)
  795. {
  796. }
  797. static void FileList_OnColumnClick(HWND hdlg, NMLISTVIEW *pnmv)
  798. {
  799. FILEVIEW *pfv = GetFileView(hdlg);
  800. if (!pfv) return;
  801. UINT uColumn = pfv->szColumns[pnmv->iSubItem].id;
  802. BOOL bAscending = (uColumn == pfv->sortColumn) ? !pfv->bAscending : TRUE;
  803. HCURSOR hc = SetCursor(LoadCursor(NULL, IDC_WAIT));
  804. FileView_SetSort(hdlg, uColumn, bAscending);
  805. SetCursor(hc);
  806. }
  807. static void FileList_OnItemChanged(HWND hdlg, NMLISTVIEW *pnmv)
  808. {
  809. if (LVIF_STATE & pnmv->uChanged)
  810. {
  811. NMFVSTATECHANGED nmsc;
  812. nmsc.iFrom = pnmv->iItem;
  813. nmsc.iTo = pnmv->iItem;
  814. nmsc.uNewState = pnmv->uNewState;
  815. nmsc.uOldState = pnmv->uOldState;
  816. FileView_NotifyParent(hdlg, FVN_STATECHANGED, (NMHDR*)&nmsc);
  817. }
  818. }
  819. static void FileList_OnStateChanged(HWND hdlg, NMLVODSTATECHANGE *pnmsc)
  820. {
  821. NMFVSTATECHANGED nmsc;
  822. nmsc.iFrom = pnmsc->iFrom;
  823. nmsc.iTo = pnmsc->iTo;
  824. nmsc.uNewState = pnmsc->uNewState;
  825. nmsc.uOldState = pnmsc->uOldState;
  826. FileView_NotifyParent(hdlg, FVN_STATECHANGED, (NMHDR*)&nmsc);
  827. }
  828. static HMENU activePopup = NULL;
  829. void FileView_DisplayPopupMenu(HWND hdlg, UINT uMenu, UINT uFlags, POINT pt)
  830. {
  831. FILEVIEW *pfv = GetFileView(hdlg);
  832. if (!pfv) return;
  833. HMENU hMenu = FileView_GetMenu(hdlg, uMenu);
  834. if (!hMenu) return;
  835. uMenu = FileViewMenu_GetMenuType(hdlg, pfv->hMenu, hMenu);
  836. if (WASABI_API_APP)
  837. {
  838. HACCEL szAccel[24] = {0};
  839. INT c = WASABI_API_APP->app_getAccelerators(hdlg, szAccel, sizeof(szAccel)/sizeof(szAccel[0]), FALSE);
  840. AppendMenuShortcuts(hMenu, szAccel, c, MSF_REPLACE);
  841. }
  842. NMFVMENU popup;
  843. ZeroMemory(&popup, sizeof(NMFVMENU));
  844. popup.hMenu = hMenu;
  845. popup.uMenuType = uMenu;
  846. popup.ptAction = pt;
  847. activePopup = hMenu;
  848. if (0 == FileView_NotifyParent(hdlg, FVN_INITMENU, (NMHDR*)&popup))
  849. {
  850. SendMessageW(g_hwnd, WM_SETCURSOR, (WPARAM)hdlg, MAKELPARAM(HTCLIENT, WM_MOUSEMOVE));
  851. popup.uCommand = (UINT)MediaLibrary_TrackPopup(hMenu, uFlags | TPM_RETURNCMD,
  852. popup.ptAction.x, popup.ptAction.y, hdlg);
  853. if (0 == FileView_NotifyParent(hdlg, FVN_MENUCOMMAND, (NMHDR*)&popup) && 0 != popup.uCommand)
  854. {
  855. SendMessageW(hdlg, WM_COMMAND, MAKEWPARAM(popup.uCommand, 0), 0L);
  856. }
  857. }
  858. activePopup = NULL;
  859. }
  860. static void FileView_OnInitMenuPopup(HWND hdlg, HMENU hMenu, UINT iIndex, BOOL bWinMenu)
  861. {
  862. FILEVIEW *pfv = GetFileView(hdlg);
  863. if (!pfv || hMenu == activePopup) return;
  864. UINT uType = FileViewMenu_GetMenuType(hdlg, pfv->hMenu, hMenu);
  865. if (((UINT)-1) != uType && FileViewMenu_GetSubMenu(hdlg, pfv->hMenu, uType))
  866. {
  867. if (WASABI_API_APP)
  868. {
  869. HACCEL szAccel[24] = {0};
  870. INT c = WASABI_API_APP->app_getAccelerators(hdlg, szAccel, sizeof(szAccel)/sizeof(szAccel[0]), FALSE);
  871. AppendMenuShortcuts(hMenu, szAccel, c, MSF_REPLACE);
  872. }
  873. NMFVMENU popup;
  874. ZeroMemory(&popup, sizeof(NMFVMENU));
  875. popup.hMenu = hMenu;
  876. popup.uMenuType = uType;
  877. FileView_NotifyParent(hdlg, FVN_INITMENU, (NMHDR*)&popup);
  878. }
  879. }
  880. static void FileView_OnUninitMenuPopup(HWND hdlg, HMENU hMenu)
  881. {
  882. FILEVIEW *pfv = GetFileView(hdlg);
  883. if (!pfv) return;
  884. UINT uType = FileViewMenu_GetMenuType(hdlg, pfv->hMenu, hMenu);
  885. if (((UINT)-1) != uType)
  886. {
  887. NMFVMENU popup;
  888. ZeroMemory(&popup, sizeof(NMFVMENU));
  889. popup.hMenu = hMenu;
  890. popup.uMenuType = uType;
  891. FileView_NotifyParent(hdlg, FVN_UNINITMENU, (NMHDR*)&popup);
  892. }
  893. }
  894. static void FileView_DisplayColumnMenu(HWND hdlg)
  895. {
  896. POINT pt;
  897. GetCursorPos(&pt);
  898. FileView_DisplayPopupMenu(hdlg, FVMENU_COLUMNS, TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_TOPALIGN | TPM_LEFTALIGN, pt);
  899. }
  900. static void FileView_DisplayFileMenu(HWND hdlg)
  901. {
  902. POINT pt;
  903. GetCursorPos(&pt);
  904. FileView_DisplayPopupMenu(hdlg, FVMENU_FILECONTEXT, TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_TOPALIGN | TPM_LEFTALIGN, pt);
  905. }
  906. static void FileListHeader_OnRClick(HWND hdlg, NMHDR *phdr)
  907. {
  908. FileView_DisplayColumnMenu(hdlg);
  909. }
  910. static BOOL FileListHeader_OnEndDrag(HWND hdlg, NMHEADER *phdr)
  911. {
  912. PostMessage(hdlg, WM_COMMAND, MAKEWPARAM(ID_INTERNAL_UPDATE_COLUMN_INFO, 0), (LPARAM)phdr->hdr.hwndFrom);
  913. return FALSE;
  914. }
  915. static BOOL FileListHeader_OnItemChanging(HWND hdlg, NMHEADER *phdr)
  916. {
  917. if (phdr->pitem && (HDI_WIDTH & phdr->pitem->mask))
  918. {
  919. FILEVIEW *pfv = GetFileView(hdlg);
  920. if (pfv && phdr->iItem < pfv->columnCount)
  921. {
  922. FILEVIEWCOLUMN *pc = &pfv->szColumns[phdr->iItem];
  923. if (phdr->pitem->cxy < pc->widthMin) phdr->pitem->cxy = pc->widthMin;
  924. if (pc->widthMax > 0 && phdr->pitem->cxy > pc->widthMax) phdr->pitem->cxy = pc->widthMax;
  925. }
  926. }
  927. return FALSE;
  928. }
  929. static void FileListHeader_OnItemChanged(HWND hdlg, NMHEADER *phdr)
  930. {
  931. SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(ID_INTERNAL_UPDATE_COLUMN_INFO, 0), (LPARAM)phdr->hdr.hwndFrom);
  932. }
  933. static void FileList_NotifyActivate(HWND hdlg, NMITEMACTIVATE *pnma, UINT uCode)
  934. {
  935. NMFVFILEACTIVATE fva;
  936. KillTimer(hdlg, IDT_ACTIVATELISTITEM);
  937. fva.iFile = pnma->iItem;
  938. fva.ptAction = pnma->ptAction;
  939. fva.uKeyFlags = pnma->uKeyFlags;
  940. fva.uNewState = pnma->uNewState;
  941. fva.uOldState = pnma->uOldState;
  942. FileView_NotifyParent(hdlg, uCode, (NMHDR*)&fva);
  943. }
  944. static void FileList_OnClick(HWND hdlg, NMITEMACTIVATE *pnma)
  945. {
  946. FileList_NotifyActivate(hdlg, pnma, NM_CLICK);
  947. }
  948. static void FileList_OnDblClick(HWND hdlg, NMITEMACTIVATE *pnma)
  949. {
  950. FileList_NotifyActivate(hdlg, pnma, NM_DBLCLK);
  951. }
  952. static void FileList_OnRClick(HWND hdlg, NMITEMACTIVATE *pnma)
  953. {
  954. FileList_NotifyActivate(hdlg, pnma, NM_RCLICK);
  955. FileView_DisplayFileMenu(hdlg);
  956. }
  957. static void FileList_OnRDblClick(HWND hdlg, NMITEMACTIVATE *pnma)
  958. {
  959. FileList_NotifyActivate(hdlg, pnma, NM_RDBLCLK);
  960. }
  961. static INT_PTR FileView_OnNotify(HWND hdlg, INT ctrlId, NMHDR *phdr)
  962. {
  963. switch(phdr->idFrom)
  964. {
  965. case IDC_FILELIST:
  966. switch(phdr->code)
  967. {
  968. case LVN_GETDISPINFOW: FileList_OnGetDispInfo(hdlg, (NMLVDISPINFOW*)phdr); return TRUE;
  969. case NM_SETFOCUS: FileList_OnSetFocus(hdlg, phdr); break;
  970. case LVN_GETINFOTIPW: FileList_OnGetInfoTip(hdlg, (NMLVGETINFOTIPW*)phdr); break;
  971. case LVN_KEYDOWN: FileList_OnKeyDown(hdlg, (NMLVKEYDOWN*)phdr); break;
  972. case LVN_COLUMNCLICK: FileList_OnColumnClick(hdlg, (NMLISTVIEW*)phdr); break;
  973. case LVN_ITEMCHANGED: FileList_OnItemChanged(hdlg, (NMLISTVIEW*)phdr); break;
  974. case LVN_ODSTATECHANGED: FileList_OnStateChanged(hdlg, (NMLVODSTATECHANGE*)phdr); break;
  975. case NM_CLICK: FileList_OnClick(hdlg, (NMITEMACTIVATE*)phdr); break;
  976. case NM_DBLCLK: FileList_OnDblClick(hdlg, (NMITEMACTIVATE*)phdr); break;
  977. case NM_RCLICK: FileList_OnRClick(hdlg, (NMITEMACTIVATE*)phdr); break;
  978. case NM_RDBLCLK: FileList_OnRDblClick(hdlg, (NMITEMACTIVATE*)phdr); break;
  979. case NM_CUSTOMDRAW: return FileList_OnCustomDraw(hdlg, (NMLVCUSTOMDRAW*)phdr);
  980. case NM_KILLFOCUS: KillTimer(hdlg, IDT_ACTIVATELISTITEM); break;
  981. }
  982. break;
  983. case IDC_FILELIST_HEADER:
  984. switch(phdr->code)
  985. {
  986. case NM_RCLICK: FileListHeader_OnRClick(hdlg, phdr); break;
  987. case HDN_ENDDRAG: return FileListHeader_OnEndDrag(hdlg, (NMHEADER*)phdr);
  988. case HDN_ITEMCHANGINGW: return FileListHeader_OnItemChanging(hdlg, (NMHEADER*)phdr);
  989. case HDN_ITEMCHANGEDW: FileListHeader_OnItemChanged(hdlg, (NMHEADER*)phdr); break;
  990. }
  991. case IDC_FOLDER_BROWSER:
  992. switch(phdr->code)
  993. {
  994. case FBN_SELCHANGED:
  995. {
  996. wchar_t szText[MAX_PATH*2] = {0};
  997. FolderBrowser_GetCurrentPath(phdr->hwndFrom, szText, sizeof(szText)/sizeof(szText[0]));
  998. HWND hedt = GetDlgItem(hdlg, IDC_EDT_PATH);
  999. if (hedt && hedt != GetFocus())
  1000. {
  1001. SetWindowTextW(hedt, szText);
  1002. }
  1003. FileView_UpdateFileView(hdlg, szText);
  1004. }
  1005. break;
  1006. }
  1007. break;
  1008. case IDC_FILEVIEW_TOOLBAR:
  1009. switch(phdr->code)
  1010. {
  1011. case FVN_INITMENU:
  1012. case FVN_UNINITMENU:
  1013. return FileView_NotifyParent(hdlg, phdr->code, phdr);
  1014. }
  1015. break;
  1016. }
  1017. return 0;
  1018. }
  1019. static void FileView_OnSetFont(HWND hdlg, BOOL bRedraw)
  1020. {
  1021. FileView_AdjustSizes(hdlg);
  1022. FileView_LayoutWindows(hdlg, bRedraw);
  1023. }
  1024. static BOOL FileView_OnSetStyle(HWND hdlg, UINT uStyle, UINT uStyleMask)
  1025. {
  1026. FILEVIEW *pfv = GetFileView(hdlg);
  1027. if (!pfv) return FALSE;
  1028. if (FVS_VIEWMASK & uStyleMask) FileView_OnSetView(hdlg, (FVS_VIEWMASK & uStyle), FALSE);
  1029. uStyleMask &= ~FVS_VIEWMASK;
  1030. pfv->style = (pfv->style & ~uStyleMask) | (uStyle & uStyleMask);
  1031. if (FVS_IGNOREHIDDEN & uStyleMask)
  1032. {
  1033. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  1034. if (hctrl) SetWindowLongPtrW(hctrl, GWL_STYLE,
  1035. (GetWindowLongPtrW(hctrl, GWL_STYLE) & ~FBS_IGNOREHIDDEN) | ((FVS_IGNOREHIDDEN & uStyle) ? FBS_IGNOREHIDDEN : 0));
  1036. }
  1037. return TRUE;
  1038. }
  1039. static void FileView_InvertStyle(HWND hdlg, UINT style)
  1040. {
  1041. FILEVIEW *pfv = GetFileView(hdlg);
  1042. if (!pfv) return;
  1043. FileView_OnSetStyle(hdlg, pfv->style ^ style, style);
  1044. FileView_Refresh(hdlg, FALSE);
  1045. }
  1046. static UINT FileView_OnGetStyle(HWND hdlg)
  1047. {
  1048. FILEVIEW *pfv = GetFileView(hdlg);
  1049. return (pfv) ? pfv->style : 0;
  1050. }
  1051. static BOOL FileView_OnSetSort(HWND hdlg, UINT uColumn, BOOL bAscending)
  1052. {
  1053. FILEVIEW *pfv = GetFileView(hdlg);
  1054. if (!pfv) return FALSE;
  1055. INT index = 0;
  1056. for (index = 0; index < pfv->columnCount && uColumn != pfv->szColumns[index].id; index++);
  1057. if (index == pfv->columnCount) return FALSE;
  1058. if (uColumn == (INT)pfv->sortColumn)
  1059. {
  1060. if (pfv->bAscending == bAscending) return TRUE;
  1061. pfv->bAscending = bAscending;
  1062. }
  1063. else
  1064. {
  1065. pfv->sortColumn = uColumn;
  1066. pfv->bAscending = bAscending;
  1067. FileView_SortByColumn(&pfv->fileData, pfv->sortColumn);
  1068. }
  1069. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1070. if (hctrl)
  1071. {
  1072. MLSkinnedListView_DisplaySort(hctrl, index, pfv->bAscending);
  1073. SendMessageW(hctrl, LVM_REDRAWITEMS, 0, pfv->fileData.count);
  1074. InvalidateRect(hctrl, NULL, TRUE);
  1075. UpdateWindow(hctrl);
  1076. }
  1077. return TRUE;
  1078. }
  1079. static UINT FileView_OnGetSort(HWND hdlg)
  1080. {
  1081. FILEVIEW *pfv = GetFileView(hdlg);
  1082. return (pfv) ? MAKELONG(pfv->sortColumn, pfv->bAscending) : ((UINT)-1);
  1083. }
  1084. static INT FileView_OnGetColumnCount(HWND hdlg)
  1085. {
  1086. FILEVIEW *pfv = GetFileView(hdlg);
  1087. return (pfv) ? pfv->columnCount : 0;
  1088. }
  1089. typedef struct _CORDER
  1090. {
  1091. INT id;
  1092. INT order;
  1093. } CORDER;
  1094. static INT __cdecl QSort_CompareOrder(const void *p1, const void *p2)
  1095. {
  1096. return (((CORDER*)p1)->order - ((CORDER*)p2)->order);
  1097. }
  1098. static INT FileView_OnGetColumnArray(HWND hdlg, INT iCount, UINT *puArray)
  1099. {
  1100. FILEVIEW *pfv = GetFileView(hdlg);
  1101. if (!pfv) return -1;
  1102. CORDER szProxy[512] = {0};
  1103. INT count;
  1104. for (count = 0; count < pfv->columnCount; count++)
  1105. {
  1106. szProxy[count].id = pfv->szColumns[count].id;
  1107. szProxy[count].order = pfv->szColumns[count].order;
  1108. }
  1109. qsort(szProxy, pfv->columnCount, sizeof(szProxy[0]), QSort_CompareOrder);
  1110. for (count = 0; count < pfv->columnCount && count < iCount; count++) puArray[count] = szProxy[count].id;
  1111. return count;
  1112. }
  1113. static BOOL FileView_OnDeleteColumn(HWND hdlg, UINT uColumn)
  1114. {
  1115. FILEVIEW *pfv = GetFileView(hdlg);
  1116. if (!pfv) return FALSE;
  1117. INT index = 0;
  1118. for (index = 0; index < pfv->columnCount && uColumn != pfv->szColumns[index].id; index++);
  1119. if (index == pfv->columnCount) return FALSE;
  1120. if (index < (pfv->columnCount - 1))
  1121. {
  1122. MoveMemory(&pfv->szColumns[index], &pfv->szColumns[index + 1], sizeof(FILEVIEWCOLUMN)*(pfv->columnCount - index - 1));
  1123. }
  1124. pfv->columnCount--;
  1125. HWND hList = GetDlgItem(hdlg, IDC_FILELIST);
  1126. if (hList && (FVS_DETAILVIEW == (FVS_VIEWMASK & pfv->style)))
  1127. {
  1128. SendMessageW(hList, LVM_DELETECOLUMN, index, 0L);
  1129. UINT c = pfv->sortColumn;
  1130. pfv->sortColumn = ((UINT)-1);
  1131. if (c == uColumn)
  1132. {
  1133. if (index > 0) index--;
  1134. c = pfv->szColumns[index].id;
  1135. }
  1136. FileView_SetSort(hdlg, c, pfv->bAscending);
  1137. }
  1138. return TRUE;
  1139. }
  1140. static INT FileView_OnInsertColumn(HWND hdlg, FVCOLUMN *pColumn)
  1141. {
  1142. FILEVIEW *pfv = GetFileView(hdlg);
  1143. if (!pfv) return -1;
  1144. INT registeredIndex;
  1145. for( registeredIndex = 0;
  1146. registeredIndex < RegisteredColumnsCount && szRegisteredColumns[registeredIndex].id != pColumn->id;
  1147. registeredIndex++);
  1148. if (szRegisteredColumns[registeredIndex].id != pColumn->id) return -1;
  1149. INT index = 0;
  1150. for (index = 0; index < pfv->columnCount && pColumn->id != pfv->szColumns[index].id; index++);
  1151. if (index != pfv->columnCount)
  1152. {
  1153. return index;
  1154. }
  1155. INT order = 0;
  1156. UINT insertPos = (UINT)pfv->columnCount;
  1157. if (FVCF_ORDER & pColumn->mask)
  1158. {
  1159. order = pColumn->order;
  1160. if (FVCO_DEFAULT_ORDER == order) order = szRegisteredColumns[registeredIndex].order;
  1161. insertPos = 0;
  1162. for (INT index = 0; index < pfv->columnCount; index++)
  1163. {
  1164. if (pfv->szColumns[index].order < order) insertPos = (index + 1);
  1165. else break;
  1166. }
  1167. }
  1168. else order = pfv->columnCount;
  1169. if (insertPos < (UINT)pfv->columnCount)
  1170. {
  1171. index = insertPos;
  1172. MoveMemory(&pfv->szColumns[index + 1], &pfv->szColumns[index], sizeof(FILEVIEWCOLUMN)*(pfv->columnCount - index));
  1173. }
  1174. else index = pfv->columnCount;
  1175. CopyMemory(&pfv->szColumns[index], &szRegisteredColumns[registeredIndex], sizeof(FILEVIEWCOLUMN));
  1176. pfv->szColumns[index].order = order;
  1177. if (FVCF_WIDTH & pColumn->mask) pfv->szColumns[index].width = pColumn->width;
  1178. if (FVCF_WIDTHMIN & pColumn->mask) pfv->szColumns[index].widthMin = pColumn->widthMin;
  1179. if (FVCF_WIDTHMAX & pColumn->mask) pfv->szColumns[index].widthMax = pColumn->widthMax;
  1180. if (pfv->szColumns[index].width < pfv->szColumns[index].widthMin)
  1181. pfv->szColumns[index].width = pfv->szColumns[index].widthMin;
  1182. if (pfv->szColumns[index].widthMax > 0 && pfv->szColumns[index].width > pfv->szColumns[index].widthMax)
  1183. pfv->szColumns[index].width = pfv->szColumns[index].widthMax;
  1184. pfv->columnCount++;
  1185. HWND hList = GetDlgItem(hdlg, IDC_FILELIST);
  1186. if (hList && (FVS_DETAILVIEW == (FVS_VIEWMASK & pfv->style)))
  1187. {
  1188. LVCOLUMNW lvc;
  1189. FileView_InitializeListColumn(hdlg, &lvc, &pfv->szColumns[index]);
  1190. SendMessageW(hList, LVM_INSERTCOLUMNW, insertPos, (LPARAM)&lvc);
  1191. }
  1192. UINT c = pfv->sortColumn;
  1193. pfv->sortColumn = ((UINT)-1);
  1194. FileView_SetSort(hdlg, c, pfv->bAscending);
  1195. return index;
  1196. }
  1197. static BOOL FileView_OnGetColumnName(HWND hdlg, UINT uColumn, INT cchTextMax, LPWSTR pszText)
  1198. {
  1199. FILEVIEW *pfv = GetFileView(hdlg);
  1200. if (!pfv || !pszText) return FALSE;
  1201. LPWSTR pszColumn = NULL;
  1202. for(INT i = 0; i < pfv->columnCount; i++)
  1203. {
  1204. if (uColumn == pfv->szColumns[i].id)
  1205. {
  1206. pszColumn = pfv->szColumns[i].pszText;
  1207. break;
  1208. }
  1209. }
  1210. if (NULL == pszColumn)
  1211. {
  1212. for(INT i = 0; i < RegisteredColumnsCount; i++)
  1213. {
  1214. if (szRegisteredColumns[i].id == uColumn)
  1215. {
  1216. pszColumn = szRegisteredColumns[i].pszText;
  1217. return TRUE;
  1218. }
  1219. }
  1220. }
  1221. if (NULL != pszColumn)
  1222. {
  1223. if (IS_INTRESOURCE(pszColumn)) WASABI_API_LNGSTRINGW_BUF((UINT)(UINT_PTR)pszColumn, pszText, cchTextMax);
  1224. else StringCchCopyW(pszText, cchTextMax, pszColumn);
  1225. return TRUE;
  1226. }
  1227. return FALSE;
  1228. }
  1229. static INT FileView_OnGetColumnWidth(HWND hdlg, UINT uColumn)
  1230. {
  1231. FILEVIEW *pfv = GetFileView(hdlg);
  1232. if (!pfv) return -1;
  1233. INT index = 0;
  1234. for (index = 0; index < pfv->columnCount && uColumn != pfv->szColumns[index].id; index++);
  1235. return (index == pfv->columnCount) ? -1 : pfv->szColumns[index].width;
  1236. }
  1237. static BOOL FileView_OnSetFileSystemInfo(HWND hdlg, FILESYSTEMINFO *pfsi)
  1238. {
  1239. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  1240. return (hctrl) ? FolderBrowser_SetFileSystemInfo(hctrl, pfsi) : FALSE;
  1241. }
  1242. static BOOL FileView_OnGetFileSystemInfo(HWND hdlg, FILESYSTEMINFO *pfsi)
  1243. {
  1244. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  1245. return (hctrl) ? FolderBrowser_GetFileSystemInfo(hctrl, pfsi) : FALSE;
  1246. }
  1247. static INT FileView_OnGetFileCount(HWND hdlg)
  1248. {
  1249. FILEVIEW *pfv = GetFileView(hdlg);
  1250. return (pfv) ? (INT)pfv->fileData.count : 0;
  1251. }
  1252. static INT FileView_OnGetSelectedCount(HWND hdlg)
  1253. {
  1254. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1255. return ((NULL != hctrl) ? (INT)SendMessageW(hctrl, LVM_GETSELECTEDCOUNT, 0, 0L) : 0);
  1256. }
  1257. static INT FileView_OnGetNextFile(HWND hdlg, INT iStart, UINT uFlags)
  1258. {
  1259. INT iFile;
  1260. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1261. UINT lvFlags = (uFlags & 0xFF0F);
  1262. FILEVIEW *pfv = GetFileView(hdlg);
  1263. if (!pfv) return -1;
  1264. iFile = ((NULL != hctrl) ? (INT)SendMessageW(hctrl, LVM_GETNEXTITEM, iStart, (LPARAM)lvFlags) : -1);
  1265. if ((0x00F0 & uFlags) && -1 != iFile)
  1266. {
  1267. if (FVNF_PLAYABLE & uFlags)
  1268. {
  1269. size_t index = ((pfv->bAscending) ? iFile : (pfv->fileData.count - iFile - 1));
  1270. FILERECORD *pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1271. while (!FileView_IsTypePlayable(pfr->fileType, FVEF_ALLKNOWN))
  1272. {
  1273. iFile = (INT)SendMessageW(hctrl, LVM_GETNEXTITEM, iFile, (LPARAM)lvFlags);
  1274. if (-1 == iFile) return -1;
  1275. index = ((pfv->bAscending) ? iFile : (pfv->fileData.count - iFile - 1));
  1276. pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1277. }
  1278. }
  1279. }
  1280. return iFile;
  1281. }
  1282. static BOOL FileView_OnGetFile(HWND hdlg, INT iFile, FVITEM *pFile)
  1283. {
  1284. FILEVIEW *pfv = GetFileView(hdlg);
  1285. if (!pfv || ((size_t)iFile) >= pfv->fileData.count || !pFile) return FALSE;
  1286. size_t index = ((pfv->bAscending) ? iFile : (pfv->fileData.count - iFile - 1));
  1287. FILERECORD *pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1288. if (FVIF_TEXT & pFile->mask)
  1289. {
  1290. if (NULL == pFile->pszText) return FALSE;
  1291. if (pfr->extOffset != (lstrlenW(pfr->Info.cFileName) + 1)) pFile->pszText = pfr->Info.cFileName;
  1292. else
  1293. {
  1294. HRESULT hr;
  1295. hr = StringCchPrintfW(pFile->pszText, pFile->cchTextMax, L"%s.%s",
  1296. pfr->Info.cFileName, (pfr->Info.cFileName + pfr->extOffset));
  1297. if (S_OK != hr) return FALSE;
  1298. }
  1299. }
  1300. if (FVIF_STATE & pFile->mask)
  1301. {
  1302. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1303. if (!hctrl) return FALSE;
  1304. pFile->state = (UINT)SendMessageW(hctrl, LVM_GETITEMSTATE, iFile, (LPARAM)pFile->stateMask);
  1305. }
  1306. if (FVIF_SIZE & pFile->mask)
  1307. {
  1308. pFile->dwSizeLow = pfr->Info.nFileSizeLow;
  1309. pFile->dwSizeHigh = pfr->Info.nFileSizeHigh;
  1310. }
  1311. if (FVIF_ATTRIBUTES & pFile->mask) pFile->uAttributes = pfr->Info.dwFileAttributes;
  1312. if (FVIF_CREATETIME & pFile->mask) pFile->ftCreationTime = pfr->Info.ftCreationTime;
  1313. if (FVIF_ACCESSTIME & pFile->mask) pFile->ftLastAccessTime = pfr->Info.ftLastAccessTime;
  1314. if (FVIF_WRITETIME & pFile->mask) pFile->ftLastWriteTime = pfr->Info.ftLastWriteTime;
  1315. if (FVIF_TYPE & pFile->mask) pFile->wType = pfr->fileType;
  1316. return TRUE;
  1317. }
  1318. static BOOL FileView_OnGetCurrentPath(HWND hdlg, LPWSTR pszBuffer, INT cchBuffer)
  1319. {
  1320. if (!pszBuffer || !cchBuffer) return FALSE;
  1321. pszBuffer[0] = L'\0';
  1322. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  1323. if (!hctrl) return FALSE;
  1324. return FolderBrowser_GetCurrentPath(hctrl, pszBuffer, cchBuffer);
  1325. }
  1326. static BOOL FileView_OnSetCurrentPath(HWND hdlg, LPCWSTR pszPath, BOOL bRedraw)
  1327. {
  1328. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  1329. if (!hctrl) return FALSE;
  1330. return FolderBrowser_SetCurrentPath(hctrl, pszPath, bRedraw);
  1331. }
  1332. static DWORD FileView_OnGetFolderSize(HWND hdlg, BOOL bSelectedOnly, DWORD *pdwSizeHigh)
  1333. {
  1334. ULONGLONG size = 0;
  1335. FILEVIEW *pfv = GetFileView(hdlg);
  1336. if (pfv)
  1337. {
  1338. if (!bSelectedOnly) size = pfv->fileData.folderSize;
  1339. else
  1340. {
  1341. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1342. if (hctrl)
  1343. {
  1344. INT i = -1;
  1345. while( -1 != (i = (INT)SendMessage(hctrl, LVM_GETNEXTITEM, i, LVNI_SELECTED)))
  1346. {
  1347. size_t index = ((pfv->bAscending) ? i : (pfv->fileData.count - i - 1));
  1348. FILERECORD *pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1349. size += ((ULONGLONG)(((__int64)pfr->Info.nFileSizeHigh << 32) | pfr->Info.nFileSizeLow));
  1350. }
  1351. }
  1352. }
  1353. }
  1354. if (pdwSizeHigh) *pdwSizeHigh = (DWORD)(size >> 32);
  1355. return (DWORD)(MAXDWORD & size);
  1356. }
  1357. static BOOL FileView_OnGetStatusText(HWND hdlg, LPWSTR pszText, INT cchTextMax)
  1358. {
  1359. if (!pszText || !cchTextMax) return FALSE;
  1360. pszText[0] = L'\0';
  1361. FILEVIEW *pfv = GetFileView(hdlg);
  1362. if (!pfv) return FALSE;
  1363. pfv->statusIndex = -1;
  1364. if (!pfv->fileData.count)
  1365. {
  1366. WASABI_API_LNGSTRINGW_BUF(IDS_FILEVIEW_EMPTYFOLDER, pszText, cchTextMax);
  1367. return TRUE;
  1368. }
  1369. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1370. INT selectedCount = 0, selectedIndex = -1;
  1371. if (hctrl)
  1372. {
  1373. selectedCount = (INT)SendMessageW(hctrl, LVM_GETSELECTEDCOUNT, 0, 0L);
  1374. if (1 == selectedCount)
  1375. {
  1376. selectedIndex = (INT)SendMessageW(hctrl, LVM_GETNEXTITEM, -1, (LPARAM)FVNF_SELECTED);
  1377. }
  1378. }
  1379. WCHAR szTemplate[256] = {0}, szSize[64] = {0};
  1380. DWORD sizeLow, sizeHigh;
  1381. if (1 == selectedCount && -1 != selectedIndex)
  1382. {
  1383. size_t index = ((pfv->bAscending) ? selectedIndex : (pfv->fileData.count - selectedIndex - 1));
  1384. FILERECORD *pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1385. if (FVFT_UNKNOWN != pfr->fileType &&
  1386. !FileViewMeta_Discover(pfv->fileData.szPath, pfr, FileView_OnMetaDataDiscovered, (ULONG_PTR)hdlg, 0))
  1387. {
  1388. pfv->statusIndex = selectedIndex;
  1389. }
  1390. FileView_FormatFileInfo(pfr, pszText, cchTextMax, FIF_STATUS);
  1391. return TRUE;
  1392. }
  1393. WASABI_API_LNGSTRINGW_BUF(((selectedCount < 1) ? IDS_FILEVIEWSTATUS_GROUPTEMPLATE : IDS_FILEVIEWSTATUS_SELECTEDGROUPTEMPLATE),
  1394. szTemplate, sizeof(szTemplate)/sizeof(szTemplate[0]));
  1395. sizeLow = FileView_OnGetFolderSize(hdlg, (selectedCount > 1), &sizeHigh);
  1396. WASABI_API_LNG->FormattedSizeString(szSize, sizeof(szSize)/sizeof(szSize[0]), (((__int64)sizeHigh << 32) | sizeLow));
  1397. return (S_OK == StringCchPrintfW(pszText, cchTextMax, szTemplate, ((selectedCount < 1) ? pfv->fileData.count : selectedCount), szSize));
  1398. }
  1399. #define IsKeyword(__keyword, __val) (CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE,(__keyword), -1, (__val), -1))
  1400. wchar_t *FileView_TagFunc(const wchar_t *tag, void *p)
  1401. {
  1402. static WCHAR szBuffer[1024];
  1403. LPCWSTR pszVal;
  1404. INT nVal, nVal2;
  1405. FILERECORD *pfr = (FILERECORD*)p;
  1406. if (!pfr) return 0;
  1407. if (pfr->pMeta)
  1408. {
  1409. if (IsKeyword(L"artist", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_ARTIST, &pszVal)) ? (LPWSTR)pszVal : 0;
  1410. else if (IsKeyword(L"album", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_ALBUM, &pszVal)) ? (LPWSTR)pszVal : 0;
  1411. else if (IsKeyword(L"title", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_TITLE, &pszVal)) ? (LPWSTR)pszVal : 0;
  1412. else if (IsKeyword(L"albumartist", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_ALBUMARTIST, &pszVal)) ? (LPWSTR)pszVal : 0;
  1413. else if (IsKeyword(L"comment", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_COMMENT, &pszVal)) ? (LPWSTR)pszVal : 0;
  1414. else if (IsKeyword(L"composer", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_COMPOSER, &pszVal)) ? (LPWSTR)pszVal : 0;
  1415. else if (IsKeyword(L"genre", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_GENRE, &pszVal)) ? (LPWSTR)pszVal : 0;
  1416. else if (IsKeyword(L"publisher", tag)) return (FileViewMeta_GetString(pfr->pMeta, MF_PUBLISHER, &pszVal)) ? (LPWSTR)pszVal : 0;
  1417. else if (IsKeyword(L"bitrate", tag))
  1418. {
  1419. if (!FileViewMeta_GetInt(pfr->pMeta, MF_BITRATE, &nVal)) return 0;
  1420. FileView_FormatBitrate(nVal, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]));
  1421. return szBuffer;
  1422. }
  1423. else if (IsKeyword(L"year", tag))
  1424. {
  1425. if (!FileViewMeta_GetInt(pfr->pMeta, MF_YEAR, &nVal)) return 0;
  1426. FileView_FormatBitrate(nVal, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]));
  1427. return szBuffer;
  1428. }
  1429. else if (IsKeyword(L"tracknumber", tag) || IsKeyword(L"track", tag) )
  1430. {
  1431. if (!FileViewMeta_GetInt(pfr->pMeta, MF_TRACKNUM, &nVal)) return 0;
  1432. if (!FileViewMeta_GetInt(pfr->pMeta, MF_TRACKCOUNT, &nVal2)) nVal2 = -1;
  1433. FileView_FormatIntSlashInt(nVal, nVal2, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]));
  1434. return szBuffer;
  1435. }
  1436. else if (IsKeyword(L"disc", tag))
  1437. {
  1438. if (!FileViewMeta_GetInt(pfr->pMeta, MF_DISCNUM, &nVal)) return 0;
  1439. if (!FileViewMeta_GetInt(pfr->pMeta, MF_DISCCOUNT, &nVal2)) nVal2 = -1;
  1440. FileView_FormatIntSlashInt(nVal, nVal2, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]));
  1441. return szBuffer;
  1442. }
  1443. }
  1444. if (IsKeyword(L"filename", tag))
  1445. {
  1446. if (pfr->extOffset == (lstrlenW(pfr->Info.cFileName) + 1))
  1447. {
  1448. StringCchPrintfW(szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0]), L"%s.%s",
  1449. pfr->Info.cFileName, (pfr->Info.cFileName + pfr->extOffset));
  1450. return szBuffer;
  1451. }
  1452. return pfr->Info.cFileName;
  1453. }
  1454. return 0;
  1455. }
  1456. static BOOL FileView_OnIsFilePlayable(HWND hdlg, INT iFile, UINT uEnqueueFilter)
  1457. {
  1458. FILEVIEW *pfv = GetFileView(hdlg);
  1459. if (!pfv || ((size_t)iFile) >= pfv->fileData.count) return FALSE;
  1460. size_t index = ((pfv->bAscending) ? iFile : (pfv->fileData.count - iFile - 1));
  1461. FILERECORD *pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1462. return FileView_IsTypePlayable(pfr->fileType, uEnqueueFilter);
  1463. }
  1464. static INT FileView_OnEnqueueSelection(HWND hdlg, UINT uEnqueueFilter, INT *pnFocused)
  1465. {
  1466. FILERECORD *pfr;
  1467. wchar_t szPath[2*MAX_PATH] = {0}, szAtf[2048] = {0};
  1468. enqueueFileWithMetaStructW efs = {0};
  1469. waFormatTitleExtended ft = {0};
  1470. FILEVIEW *pfv = GetFileView(hdlg);
  1471. if (!pfv || 0 == uEnqueueFilter) return 0;
  1472. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1473. if (!hctrl) return 0;
  1474. INT sCount = (INT)SendMessageW(hctrl, LVM_GETSELECTEDCOUNT, 0, 0L);
  1475. if (0 == sCount) return 0;
  1476. ft.spec = NULL;
  1477. ft.TAGFUNC = FileView_TagFunc;
  1478. ft.TAGFREEFUNC = NULL;
  1479. ft.useExtendedInfo = 1;
  1480. sCount = 0;
  1481. INT iFile = -1, iFocused = -1;
  1482. if (pnFocused)
  1483. {
  1484. *pnFocused = -1;
  1485. iFocused = (INT)SendMessageW(hctrl, LVM_GETNEXTITEM, iFile, (LPARAM)LVIS_FOCUSED);
  1486. }
  1487. while (-1 != (iFile = (INT)SendMessageW(hctrl, LVM_GETNEXTITEM, iFile, (LPARAM)LVIS_SELECTED)))
  1488. {
  1489. size_t index = ((pfv->bAscending) ? iFile : (pfv->fileData.count - iFile - 1));
  1490. pfr = &pfv->fileData.pRec[pfv->fileData.pSort[index]];
  1491. if (FileView_IsTypePlayable(pfr->fileType, uEnqueueFilter) &&
  1492. PathCombineW(szPath, pfv->fileData.szPath, pfr->Info.cFileName))
  1493. {
  1494. if (pfr->extOffset == (lstrlenW(pfr->Info.cFileName) + 1))
  1495. {
  1496. StringCchCatW(szPath, sizeof(szPath)/sizeof(szPath[0]), L".");
  1497. StringCchCatW(szPath, sizeof(szPath)/sizeof(szPath[0]), (pfr->Info.cFileName + pfr->extOffset));
  1498. }
  1499. if (pfr->pMeta && METATYPE_PLAYLIST != pfr->pMeta->type)
  1500. {
  1501. szAtf[0] = L'\0';
  1502. ft.filename = szPath;
  1503. ft.out = szAtf;
  1504. ft.out_len = sizeof(szAtf)/sizeof(szAtf[0]);
  1505. ft.p = pfr;
  1506. SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&ft, IPC_FORMAT_TITLE_EXTENDED);
  1507. FileViewMeta_GetInt(pfr->pMeta, MF_LENGTH, &efs.length);
  1508. if (szAtf[0]) efs.title = szAtf;
  1509. else if (!FileViewMeta_GetString(pfr->pMeta, MF_TITLE, &efs.title)) efs.title = NULL;
  1510. }
  1511. else
  1512. {
  1513. efs.length = -1;
  1514. efs.title = NULL;
  1515. }
  1516. efs.filename = szPath;
  1517. efs.ext = NULL;
  1518. if (iFocused == iFile && pnFocused) *pnFocused = (INT)SENDWAIPC(plugin.hwndParent, IPC_GETLISTLENGTH, 0);
  1519. if(SENDWAIPC(plugin.hwndParent, IPC_ENQUEUEFILEW, (WPARAM)&efs)) sCount++;
  1520. else if (iFocused == iFile && pnFocused) *pnFocused = -1;
  1521. }
  1522. }
  1523. return sCount;
  1524. }
  1525. static void FileView_OnPlaySelection(HWND hdlg, BOOL bShiftPressed)
  1526. {
  1527. FILEVIEW *pfv = GetFileView(hdlg);
  1528. if (!pfv) return;
  1529. BOOL bPlay = ((FALSE == bShiftPressed) == (0 == (FVS_ENQUEUE & pfv->style)));
  1530. if (bPlay) SENDWAIPC(plugin.hwndParent, IPC_DELETE, 0);
  1531. if (FileView_OnEnqueueSelection(hdlg, FVEF_ALLKNOWN, NULL) && bPlay)
  1532. {
  1533. SENDWAIPC(plugin.hwndParent, IPC_SETPLAYLISTPOS, 0);
  1534. SENDWAIPC(plugin.hwndParent, IPC_STARTPLAY, 0);
  1535. }
  1536. }
  1537. static void FileView_UpdateColumnInfo(HWND hdlg, HWND hHeader)
  1538. {
  1539. FILEVIEW *pfv = GetFileView(hdlg);
  1540. if (!pfv || NULL == hHeader || 0 == pfv->columnCount) return;
  1541. INT count = (INT)SendMessage(hHeader, HDM_GETITEMCOUNT, 0, 0L);
  1542. if (count)
  1543. {
  1544. HDITEM item;
  1545. item.mask = HDI_ORDER | HDI_WIDTH;
  1546. if (count > pfv->columnCount) count = pfv->columnCount;
  1547. for (int i = 0; i < count; i++)
  1548. {
  1549. if (SendMessage(hHeader, HDM_GETITEM, (WPARAM)i, (LPARAM)&item))
  1550. {
  1551. pfv->szColumns[i].order = item.iOrder;
  1552. pfv->szColumns[i].width = item.cxy;
  1553. }
  1554. }
  1555. }
  1556. }
  1557. static void FileView_OnCommand(HWND hdlg, INT eventId, INT ctrlId, HWND hwndCtrl)
  1558. {
  1559. FILEVIEW *pfv = GetFileView(hdlg);
  1560. switch (ctrlId)
  1561. {
  1562. case IDC_EDT_PATH:
  1563. switch(eventId)
  1564. {
  1565. case EN_CHANGE:
  1566. if (hwndCtrl == GetFocus())
  1567. {
  1568. HWND hctrl = GetDlgItem(hdlg, IDC_FOLDER_BROWSER);
  1569. if (IsWindow(hctrl))
  1570. {
  1571. WCHAR szPath[MAX_PATH*2] = {0};
  1572. GetWindowTextW(hwndCtrl, szPath, sizeof(szPath)/sizeof(szPath[0]));
  1573. FolderBrowser_SetCurrentPath(hctrl, szPath, TRUE);
  1574. PostMessageW(hdlg, FVM_REFRESH, 0, 0L);
  1575. }
  1576. }
  1577. break;
  1578. }
  1579. break;
  1580. case ID_FILEVIEW_SETMODE_ICON: FileView_OnSetView(hdlg, FVS_ICONVIEW, TRUE); break;
  1581. case ID_FILEVIEW_SETMODE_LIST: FileView_OnSetView(hdlg, FVS_LISTVIEW, TRUE); break;
  1582. case ID_FILEVIEW_SETMODE_DETAIL: FileView_OnSetView(hdlg, FVS_DETAILVIEW, TRUE); break;
  1583. case ID_FILEVIEW_REFRESH: FileView_OnRefresh(hdlg, TRUE, TRUE); break;
  1584. case ID_FILEVIEW_PLAYSELECTION:
  1585. if (1 != eventId || GetFocus() == GetDlgItem(hdlg, IDC_FILELIST))
  1586. FileView_OnPlaySelection(hdlg, FALSE);
  1587. else if (1 == eventId)
  1588. {
  1589. HWND hFocus = GetFocus();
  1590. if (hFocus == GetDlgItem(hdlg, IDC_EDT_PATH) ||
  1591. hFocus == GetDlgItem(hdlg, IDC_FOLDER_BROWSER) ||
  1592. IsChild(GetDlgItem(hdlg, IDC_FOLDER_BROWSER), hFocus))
  1593. SendMessageW(hdlg, WM_NEXTDLGCTL, 0, MAKELPARAM(0, 0));
  1594. }
  1595. break;
  1596. case ID_FILEVIEW_PLAYSELECTION_SHIFT:
  1597. if (1 != eventId || GetFocus() == GetDlgItem(hdlg, IDC_FILELIST))
  1598. FileView_OnPlaySelection(hdlg, TRUE);
  1599. break;
  1600. case ID_FILEVIEW_SELECT_ALL:
  1601. if (1 != eventId || GetFocus() == GetDlgItem(hdlg, IDC_FILELIST))
  1602. {
  1603. LVITEMW lvi;
  1604. lvi.stateMask = LVIS_SELECTED;
  1605. lvi.state = LVIS_SELECTED;
  1606. SendMessageW(GetDlgItem(hdlg, IDC_FILELIST), LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvi);
  1607. }
  1608. else if (1 == eventId)
  1609. {
  1610. HWND hFocus = GetFocus();
  1611. if (hFocus == GetDlgItem(hdlg, IDC_EDT_PATH)) SendMessageW(hFocus, EM_SETSEL, 0, -1);
  1612. }
  1613. break;
  1614. case IDM_FILEVIEW_SORTASCENDING:
  1615. if (pfv) FileView_OnSetSort(hdlg, pfv->sortColumn, !pfv->bAscending);
  1616. break;
  1617. case IDM_FILEVIEW_HIDEEXTENSION: FileView_InvertStyle(hdlg, FVS_HIDEEXTENSION); break;
  1618. case IDM_FILEVIEW_IGNOREHIDDEN: FileView_InvertStyle(hdlg, FVS_IGNOREHIDDEN); break;
  1619. case IDM_FILEVIEW_SHOWAUDIO: FileView_InvertStyle(hdlg, FVS_SHOWAUDIO); break;
  1620. case IDM_FILEVIEW_SHOWVIDEO: FileView_InvertStyle(hdlg, FVS_SHOWVIDEO); break;
  1621. case IDM_FILEVIEW_SHOWPLAYLIST: FileView_InvertStyle(hdlg, FVS_SHOWPLAYLIST); break;
  1622. case IDM_FILEVIEW_SHOWUNKNOWN: FileView_InvertStyle(hdlg, FVS_SHOWUNKNOWN); break;
  1623. case ID_INTERNAL_UPDATE_COLUMN_INFO: FileView_UpdateColumnInfo(hdlg, hwndCtrl); break;
  1624. }
  1625. if (ctrlId >= IDM_COLUMN_SHOW_MIN && ctrlId <= IDM_COLUMN_SHOW_MAX)
  1626. {
  1627. INT cid = ctrlId - IDM_COLUMN_SHOW_MIN;
  1628. INT index;
  1629. for (index = 0; index < pfv->columnCount && cid != pfv->szColumns[index].id; index++);
  1630. if (index == pfv->columnCount)
  1631. {
  1632. FVCOLUMN fvc;
  1633. fvc.id = cid;
  1634. fvc.order = FVCO_DEFAULT_ORDER;
  1635. fvc.mask = FVCF_ORDER;
  1636. FileView_InsertColumn(hdlg, &fvc);
  1637. }
  1638. else FileView_DeleteColumn(hdlg, cid);
  1639. }
  1640. else if (ctrlId >= IDM_COLUMN_ARRANGE_MIN && ctrlId <= IDM_COLUMN_ARRANGE_MAX)
  1641. {
  1642. if (pfv && pfv->sortColumn != (ctrlId - IDM_COLUMN_ARRANGE_MIN))
  1643. FileView_OnSetSort(hdlg, ctrlId - IDM_COLUMN_ARRANGE_MIN, pfv->bAscending);
  1644. }
  1645. }
  1646. static BOOL FileView_OnSetFileState(HWND hdlg, INT iFile, FVITEM *pFile)
  1647. {
  1648. if (!pFile) return FALSE;
  1649. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1650. if (!hctrl) return FALSE;
  1651. LVITEMW lvi;
  1652. lvi.state = pFile->state;
  1653. lvi.stateMask = pFile->stateMask;
  1654. return (BOOL)SendMessageW(hctrl, LVM_SETITEMSTATE, (WPARAM)iFile, (LPARAM)&lvi);
  1655. }
  1656. static HMENU FileView_OnGetMenu(HWND hdlg, UINT uMenuType)
  1657. {
  1658. FILEVIEW *pfv = GetFileView(hdlg);
  1659. if (!pfv) return NULL;
  1660. if (!pfv->hMenu)
  1661. {
  1662. pfv->hMenu = FileViewMenu_Initialize();
  1663. if (!pfv->hMenu) return NULL;
  1664. }
  1665. return FileViewMenu_GetSubMenu(hdlg, pfv->hMenu, uMenuType);
  1666. }
  1667. static UINT FileView_OnGetActionCommand(HWND hdlg, UINT uAction)
  1668. {
  1669. FILEVIEW *pfv = GetFileView(hdlg);
  1670. if (!pfv) return 0;
  1671. switch(uAction)
  1672. {
  1673. case FVA_PLAY:
  1674. return (0 == (FVS_ENQUEUE & pfv->style)) ? ID_FILEVIEW_PLAYSELECTION : ID_FILEVIEW_PLAYSELECTION_SHIFT;
  1675. case FVA_ENQUEUE:
  1676. return (0 != (FVS_ENQUEUE & pfv->style)) ? ID_FILEVIEW_PLAYSELECTION : ID_FILEVIEW_PLAYSELECTION_SHIFT;
  1677. }
  1678. return 0;
  1679. }
  1680. static INT FileView_OnHitTest(HWND hdlg, FVHITTEST *pht)
  1681. {
  1682. HWND hctrl = GetDlgItem(hdlg, IDC_FILELIST);
  1683. if (!pht || !hctrl) return -1;
  1684. LVHITTESTINFO ht;
  1685. ht.pt = pht->pt;
  1686. MapWindowPoints(hdlg, hctrl, &ht.pt, 1);
  1687. INT r = (INT)SendMessageW(hctrl, LVM_HITTEST, 0, (LPARAM)&ht);
  1688. pht->iItem = ht.iItem;
  1689. pht->uFlags = (0xFF & ht.flags);
  1690. return r;
  1691. }
  1692. static INT FileView_OnGetDividerPos(HWND hdlg)
  1693. {
  1694. FILEVIEW *pfv = GetFileView(hdlg);
  1695. return (pfv) ? pfv->yDivider : 0;
  1696. }
  1697. static INT FileView_OnSetDividerPos(HWND hdlg, INT nPos, UINT uFlags)
  1698. {
  1699. FILEVIEW *pfv = GetFileView(hdlg);
  1700. RECT rc;
  1701. if (!pfv) return 0;
  1702. if (FVRF_VALIDATE & uFlags)
  1703. {
  1704. if (nPos < pfv->yDivider && GetWindowRect(GetDlgItem(hdlg, IDC_FOLDER_BROWSER), &rc))
  1705. {
  1706. MapWindowPoints(HWND_DESKTOP, hdlg, (POINT*)&rc, 2);
  1707. if (((nPos + pfv->cyDivider) - rc.top) < FOLDERBROWSER_MIN_HEIGHT)
  1708. nPos = rc.top + (FOLDERBROWSER_MIN_HEIGHT - pfv->cyDivider);
  1709. }
  1710. if (nPos > pfv->yDivider && GetClientRect(hdlg, &rc))
  1711. {
  1712. if ((nPos + pfv->cyDivider) > (rc.bottom - FILELIST_MIN_HEIGHT))
  1713. nPos = rc.bottom - FILELIST_MIN_HEIGHT - pfv->cyDivider;
  1714. }
  1715. }
  1716. if (nPos != pfv->yDivider)
  1717. {
  1718. pfv->yDivider = nPos;
  1719. if (0 == (FVRF_NOREDRAW & uFlags))
  1720. {
  1721. FileView_LayoutWindows(hdlg, TRUE);
  1722. UpdateWindow(hdlg);
  1723. }
  1724. }
  1725. return pfv->yDivider;
  1726. }
  1727. static INT_PTR CALLBACK FileView_DialogProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1728. {
  1729. switch(uMsg)
  1730. {
  1731. case WM_INITDIALOG: return FileView_OnInitDialog(hdlg, (HWND)wParam, lParam);
  1732. case WM_DESTROY: FileView_OnDestroy(hdlg); return TRUE;
  1733. case WM_WINDOWPOSCHANGED: FileView_OnWindowPosChanged(hdlg, (WINDOWPOS*)lParam); return TRUE;
  1734. case WM_COMMAND: FileView_OnCommand(hdlg, HIWORD(wParam), LOWORD(wParam), (HWND)lParam); return TRUE;
  1735. case WM_NOTIFY: MSGRESULT(hdlg, FileView_OnNotify(hdlg, (INT)wParam, (LPNMHDR) lParam));
  1736. case WM_SETFONT: FileView_OnSetFont(hdlg, LOWORD(lParam)); break;
  1737. case WM_INITMENUPOPUP: FileView_OnInitMenuPopup(hdlg, (HMENU)wParam, LOWORD(lParam), HIWORD(lParam)); break;
  1738. case WM_UNINITMENUPOPUP: FileView_OnUninitMenuPopup(hdlg, (HMENU)wParam); break;
  1739. case FVM_SETROOT: MSGRESULT(hdlg, FileView_OnSetRoot(hdlg, (LPCWSTR)lParam));
  1740. case FVM_GETROOT: MSGRESULT(hdlg, FileView_OnGetRoot(hdlg, (LPCWSTR)lParam, (INT)wParam));
  1741. case FVM_REFRESH: MSGRESULT(hdlg, FileView_OnRefresh(hdlg, (BOOL)wParam, TRUE));
  1742. case FVM_SETSTYLE: MSGRESULT(hdlg, FileView_OnSetStyle(hdlg, (UINT)lParam, (UINT)wParam));
  1743. case FVM_GETSTYLE: MSGRESULT(hdlg, FileView_OnGetStyle(hdlg));
  1744. case FVM_SETSORT: MSGRESULT(hdlg, FileView_OnSetSort(hdlg, LOWORD(wParam), HIWORD(wParam)));
  1745. case FVM_GETSORT: MSGRESULT(hdlg, FileView_OnGetSort(hdlg));
  1746. case FVM_GETCOLUMNCOUNT: MSGRESULT(hdlg, FileView_OnGetColumnCount(hdlg));
  1747. case FVM_GETCOLUMNARRAY: MSGRESULT(hdlg, FileView_OnGetColumnArray(hdlg, (INT)wParam, (UINT*)lParam));
  1748. case FVM_DELETECOLUMN: MSGRESULT(hdlg, FileView_OnDeleteColumn(hdlg, (UINT)wParam));
  1749. case FVM_INSERTCOLUMN: MSGRESULT(hdlg, FileView_OnInsertColumn(hdlg, (FVCOLUMN*)lParam));
  1750. case FVM_GETCOLUMNAME: MSGRESULT(hdlg, FileView_OnGetColumnName(hdlg, (UINT)LOWORD(wParam), (INT)HIWORD(wParam), (LPWSTR)lParam));
  1751. case FVM_SETFILESYSTEMINFO: MSGRESULT(hdlg, FileView_OnSetFileSystemInfo(hdlg, (FILESYSTEMINFO*)lParam));
  1752. case FVM_GETFILESYSTEMINFO: MSGRESULT(hdlg, FileView_OnGetFileSystemInfo(hdlg, (FILESYSTEMINFO*)lParam));
  1753. case FVM_GETFILECOUNT: MSGRESULT(hdlg, FileView_OnGetFileCount(hdlg));
  1754. case FVM_GETSELECTEDCOUNT: MSGRESULT(hdlg, FileView_OnGetSelectedCount(hdlg));
  1755. case FVM_GETNEXTFILE: MSGRESULT(hdlg, FileView_OnGetNextFile(hdlg, (INT)wParam, (UINT)lParam));
  1756. case FVM_GETFILE: MSGRESULT(hdlg, FileView_OnGetFile(hdlg, (INT)wParam, (FVITEM*)lParam));
  1757. case FVM_GETCURRENTPATH: MSGRESULT(hdlg, FileView_OnGetCurrentPath(hdlg, (LPWSTR)lParam, (INT)wParam));
  1758. case FVM_SETCURRENTPATH: MSGRESULT(hdlg, FileView_OnSetCurrentPath(hdlg, (LPCWSTR)lParam, (BOOL)wParam));
  1759. case FVM_GETFOLDERBROWSER: MSGRESULT(hdlg, GetDlgItem(hdlg, IDC_FOLDER_BROWSER));
  1760. case FVM_GETFOLDERSIZE: MSGRESULT(hdlg, FileView_OnGetFolderSize(hdlg, (BOOL)wParam, (DWORD*)lParam));
  1761. case FVM_GETSTATUSTEXT: MSGRESULT(hdlg, FileView_OnGetStatusText(hdlg, (LPWSTR)lParam, (INT)wParam));
  1762. case FVM_ENQUEUESELECTION: MSGRESULT(hdlg, FileView_OnEnqueueSelection(hdlg, (UINT)wParam, (INT*)lParam));
  1763. case FVM_ISFILEPLAYABLE: MSGRESULT(hdlg, FileView_OnIsFilePlayable(hdlg, (INT)lParam, (UINT)wParam));
  1764. case FVM_SETFILESTATE: MSGRESULT(hdlg, FileView_OnSetFileState(hdlg, (INT)wParam, (FVITEM*)lParam));
  1765. case FVM_GETMENU: MSGRESULT(hdlg, FileView_OnGetMenu(hdlg, (UINT)wParam));
  1766. case FVM_GETACTIONCMD: MSGRESULT(hdlg, FileView_OnGetActionCommand(hdlg, (UINT)wParam));
  1767. case FVM_HITTEST: MSGRESULT(hdlg, FileView_OnHitTest(hdlg, (FVHITTEST*)lParam));
  1768. case FVM_GETCOLUMNWIDTH: MSGRESULT(hdlg, FileView_OnGetColumnWidth(hdlg, (UINT)wParam));
  1769. case FVM_GETDIVIDERPOS: MSGRESULT(hdlg, FileView_OnGetDividerPos(hdlg));
  1770. case FVM_SETDIVIDERPOS: MSGRESULT(hdlg, FileView_OnSetDividerPos(hdlg, (INT)wParam, (UINT)lParam));
  1771. }
  1772. return 0;
  1773. }