1
0

DownloadsDialog.cpp 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. #include "main.h"
  2. #include "api__ml_downloads.h"
  3. #include "RFCDate.h"
  4. #include "Downloaded.h"
  5. #include "DownloadStatus.h"
  6. #include "Defaults.h"
  7. #include "../nu/listview.h"
  8. #include "..\..\General\gen_ml/ml_ipc.h"
  9. #include "..\..\General\gen_ml/menu.h"
  10. #include <vector>
  11. #include "../nu/menushortcuts.h"
  12. #include <commctrl.h>
  13. #include <shlwapi.h>
  14. #include <shellapi.h>
  15. #include <strsafe.h>
  16. #include <algorithm>
  17. HWND downloads_window = 0;
  18. extern int downloads_treeItem;
  19. extern int no_auto_hide;
  20. int groupBtn = 1, enqueuedef = 0, customAllowed = 0;
  21. HMENU g_context_menus2 = NULL;
  22. static viewButtons view;
  23. #ifndef HDF_SORTUP
  24. #define HDF_SORTUP 0x0400
  25. #define HDF_SORTDOWN 0x0200
  26. #endif // !HDF_SORTUP
  27. using namespace Nullsoft::Utility;
  28. enum
  29. {
  30. COL_TITLE = 0,
  31. COL_PROGRESS,
  32. COL_DATE,
  33. COL_SOURCE,
  34. COL_SIZE,
  35. COL_PATH,
  36. NUM_COLUMNS,
  37. };
  38. int downloadsSourceWidth = DOWNLOADSSOURCEWIDTHDEFAULT;
  39. int downloadsTitleWidth = DOWNLOADSTITLEWIDTHDEFAULT;
  40. int downloadsProgressWidth = DOWNLOADSPROGRESSWIDTHDEFAULT;
  41. int downloadsDateWidth = DOWNLOADSDATEWIDTHDEFAULTS;
  42. int downloadsSizeWidth = DOWNLOADSSIZEWIDTHDEFAULTS;
  43. int downloadsPathWidth = DOWNLOADSPATHWIDTHDEFAULTS;
  44. W_ListView downloadList;
  45. int downloadsItemSort = 2; // -1 means no sort active
  46. bool downloadsSortAscending = false;
  47. enum
  48. {
  49. DOWNLOADSDIALOG_TIMER_UPDATESTATUSBAR = 0,
  50. };
  51. class DownloadListItem
  52. {
  53. public:
  54. DownloadedFile *f = NULL;
  55. DownloadToken token = NULL;
  56. wchar_t *source = 0;
  57. wchar_t *title = 0;
  58. wchar_t *path = 0;
  59. wchar_t status[ 20 ] = { 0 };
  60. DownloadListItem( DownloadedFile *fi )
  61. {
  62. f = new DownloadedFile( *fi );
  63. ZeroMemory( status, sizeof( status ) );
  64. }
  65. DownloadListItem( DownloadToken p_token, const wchar_t *p_source, const wchar_t *p_title, const wchar_t *p_path, size_t p_downloaded, size_t p_maxSize ) : token( p_token )
  66. {
  67. if ( p_maxSize )
  68. StringCchPrintf( status, 20, WASABI_API_LNGSTRINGW( IDS_DOWNLOADING_PERCENT ), (int)( p_downloaded / ( p_maxSize / 100 ) ) );
  69. else
  70. {
  71. if ( WAC_API_DOWNLOADMANAGER->IsPending( p_token ) )
  72. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOAD_PENDING, status, 20 );
  73. else
  74. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOADING, status, 20 );
  75. }
  76. source = p_source ? _wcsdup( p_source ) : NULL;
  77. title = p_title ? _wcsdup( p_title ) : NULL;
  78. path = p_path ? _wcsdup( p_path ) : NULL;
  79. }
  80. ~DownloadListItem()
  81. {
  82. clean();
  83. if ( f )
  84. delete f;
  85. }
  86. void clean()
  87. {
  88. if ( source )
  89. {
  90. free( source );
  91. source = 0;
  92. }
  93. if ( title )
  94. {
  95. free( title );
  96. title = 0;
  97. }
  98. if ( path )
  99. {
  100. free( path );
  101. path = 0;
  102. }
  103. }
  104. };
  105. static std::vector<DownloadListItem*> listContents;
  106. bool GetDownload( int &download )
  107. {
  108. download = ListView_GetNextItem( downloadList.getwnd(), download, LVNI_ALL | LVNI_SELECTED );
  109. if ( download == -1 )
  110. return false;
  111. else
  112. return true;
  113. }
  114. void Downloads_Play( bool enqueue = false )
  115. {
  116. int download = -1;
  117. AutoLock lock( downloadedFiles );
  118. while ( GetDownload( download ) )
  119. {
  120. if ( !enqueue )
  121. {
  122. if ( listContents[ download ]->f )
  123. mediaLibrary.PlayFile( listContents[ download ]->f->path );
  124. else if ( listContents[ download ]->path )
  125. mediaLibrary.PlayFile( listContents[ download ]->path );
  126. enqueue = true;
  127. }
  128. else
  129. {
  130. if ( listContents[ download ]->f )
  131. mediaLibrary.EnqueueFile( listContents[ download ]->f->path );
  132. else if ( listContents[ download ]->path )
  133. mediaLibrary.EnqueueFile( listContents[ download ]->path );
  134. }
  135. }
  136. }
  137. void DownloadsUpdated( const DownloadStatus::Status &s, DownloadToken token )
  138. {
  139. listContents.push_back( new DownloadListItem( token, s.source, s.title, s.path, s.downloaded, s.maxSize ) );
  140. downloadList.SetVirtualCountAsync( (int)listContents.size() );
  141. }
  142. void DownloadsUpdated( DownloadToken token, const DownloadedFile *f )
  143. {
  144. for ( DownloadListItem *l_content : listContents )
  145. {
  146. if ( l_content->token == token )
  147. {
  148. l_content->token = 0;
  149. if ( f )
  150. {
  151. l_content->f = new DownloadedFile( *f );
  152. l_content->clean();
  153. }
  154. else
  155. lstrcpyn( l_content->status, L"Error", 20 );
  156. break;
  157. }
  158. }
  159. PostMessage( downloadList.getwnd(), LVM_REDRAWITEMS, 0, listContents.size() );
  160. }
  161. void DownloadsUpdated()
  162. {
  163. for ( DownloadListItem *l_content : listContents )
  164. delete l_content;
  165. listContents.clear();
  166. for ( DownloadedFile &l_download : downloadedFiles.downloadList )
  167. listContents.push_back( new DownloadListItem( &l_download ) );
  168. {
  169. AutoLock lock( downloadStatus.statusLock );
  170. for ( DownloadStatus::Downloads::iterator itr = downloadStatus.downloads.begin(); itr != downloadStatus.downloads.end(); itr++ )
  171. {
  172. listContents.push_back( new DownloadListItem( itr->first, itr->second.source, itr->second.title, itr->second.path, itr->second.downloaded, itr->second.maxSize ) );
  173. }
  174. }
  175. downloadList.SetVirtualCountAsync( (int)listContents.size() );
  176. // Navigation_ShowService( SERVICE_DOWNLOADS, SHOWMODE_AUTO );
  177. }
  178. static void CleanupDownloads()
  179. {
  180. {
  181. AutoLock lock( downloadedFiles );
  182. DownloadList::DownloadedFileList &downloads = downloadedFiles.downloadList;
  183. DownloadList::iterator itr, next;
  184. for ( itr = downloads.begin(); itr != downloads.end();)
  185. {
  186. next = itr;
  187. ++next;
  188. if ( !PathFileExists( itr->path ) )
  189. downloads.erase( itr );
  190. else
  191. itr = next;
  192. }
  193. }
  194. // Navigation_ShowService(SERVICE_DOWNLOADS, SHOWMODE_AUTO);
  195. }
  196. void Downloads_UpdateStatusBar(HWND hwndDlg)
  197. {
  198. wchar_t status[256]=L"";
  199. downloadStatus.GetStatusString(status, 256);
  200. SetWindowText(GetDlgItem(hwndDlg, IDC_STATUS), status);
  201. }
  202. void Downloads_Paint(HWND hwndDlg)
  203. {
  204. int tab[] = { IDC_DOWNLOADLIST | DCW_SUNKENBORDER, };
  205. dialogSkinner.Draw(hwndDlg, tab, sizeof(tab) / sizeof(tab[0]));
  206. }
  207. static HRGN g_rgnUpdate = NULL;
  208. static int offsetX = 0, offsetY = 0;
  209. typedef struct _LAYOUT
  210. {
  211. INT id;
  212. HWND hwnd;
  213. INT x;
  214. INT y;
  215. INT cx;
  216. INT cy;
  217. DWORD flags;
  218. HRGN rgn;
  219. }
  220. LAYOUT, PLAYOUT;
  221. #define SETLAYOUTPOS(_layout, _x, _y, _cx, _cy) { _layout->x=_x; _layout->y=_y;_layout->cx=_cx;_layout->cy=_cy;_layout->rgn=NULL; }
  222. #define SETLAYOUTFLAGS(_layout, _r) \
  223. { \
  224. BOOL fVis; \
  225. fVis = (WS_VISIBLE & (LONG)GetWindowLongPtr(_layout->hwnd, GWL_STYLE)); \
  226. if (_layout->x == _r.left && _layout->y == _r.top) _layout->flags |= SWP_NOMOVE; \
  227. if (_layout->cx == (_r.right - _r.left) && _layout->cy == (_r.bottom - _r.top)) _layout->flags |= SWP_NOSIZE; \
  228. if ((SWP_HIDEWINDOW & _layout->flags) && !fVis) _layout->flags &= ~SWP_HIDEWINDOW; \
  229. if ((SWP_SHOWWINDOW & _layout->flags) && fVis) _layout->flags &= ~SWP_SHOWWINDOW; \
  230. }
  231. #define LAYOUTNEEEDUPDATE(_layout) ((SWP_NOMOVE | SWP_NOSIZE) != ((SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_SHOWWINDOW) & _layout->flags))
  232. #define GROUP_MIN 0x1
  233. #define GROUP_MAX 0x2
  234. #define GROUP_STATUSBAR 0x1
  235. #define GROUP_MAIN 0x2
  236. static void LayoutWindows(HWND hwnd, BOOL fRedraw, BOOL fUpdateAll = FALSE)
  237. {
  238. static INT controls[] =
  239. {
  240. GROUP_STATUSBAR, IDC_PLAY, IDC_ENQUEUE, IDC_CUSTOM, IDC_REMOVE, IDC_CLEANUP, IDC_STATUS,
  241. GROUP_MAIN, IDC_DOWNLOADLIST
  242. };
  243. INT index;
  244. RECT rc, rg, ri;
  245. LAYOUT layout[sizeof(controls)/sizeof(controls[0])], *pl;
  246. BOOL skipgroup;
  247. HRGN rgn = NULL;
  248. GetClientRect(hwnd, &rc);
  249. if (rc.right == rc.left || rc.bottom == rc.top)
  250. return;
  251. if ( rc.right > WASABI_API_APP->getScaleX( 4 ) )
  252. rc.right -= WASABI_API_APP->getScaleX( 4 );
  253. SetRect( &rg, rc.left, rc.top, rc.right, rc.top );
  254. pl = layout;
  255. skipgroup = FALSE;
  256. InvalidateRect(hwnd, NULL, TRUE);
  257. for (index = 0; index < sizeof(controls) / sizeof(*controls); index++)
  258. {
  259. if (controls[index] >= GROUP_MIN && controls[index] <= GROUP_MAX) // group id
  260. {
  261. skipgroup = FALSE;
  262. switch (controls[index])
  263. {
  264. case GROUP_STATUSBAR:
  265. {
  266. wchar_t buffer[128] = {0};
  267. WASABI_API_LNGSTRINGW_BUF(IDC_PLAY, buffer, ARRAYSIZE(buffer));
  268. LRESULT idealSize = MLSkinnedButton_GetIdealSize(GetDlgItem(hwnd, IDC_PLAY), buffer);
  269. SetRect(&rg, rc.left + WASABI_API_APP->getScaleX(1),
  270. rc.bottom - WASABI_API_APP->getScaleY(HIWORD(idealSize)),
  271. rc.right, rc.bottom);
  272. rc.bottom = rg.top - WASABI_API_APP->getScaleY(3);
  273. break;
  274. }
  275. case GROUP_MAIN:
  276. SetRect(&rg, rc.left + WASABI_API_APP->getScaleX(1), rc.top, rc.right, rc.bottom);
  277. break;
  278. }
  279. continue;
  280. }
  281. if (skipgroup) continue;
  282. pl->id = controls[index];
  283. pl->hwnd = GetDlgItem(hwnd, pl->id);
  284. if ( !pl->hwnd )
  285. continue;
  286. GetWindowRect(pl->hwnd, &ri);
  287. MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT)&ri, 2);
  288. pl->flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS;
  289. switch (pl->id)
  290. {
  291. case IDC_PLAY:
  292. case IDC_ENQUEUE:
  293. case IDC_CUSTOM:
  294. case IDC_REMOVE:
  295. case IDC_CLEANUP:
  296. if ( IDC_CUSTOM != pl->id || customAllowed )
  297. {
  298. if ( groupBtn && pl->id == IDC_PLAY && enqueuedef == 1 )
  299. {
  300. pl->flags |= SWP_HIDEWINDOW;
  301. break;
  302. }
  303. if ( groupBtn && pl->id == IDC_ENQUEUE && enqueuedef != 1 )
  304. {
  305. pl->flags |= SWP_HIDEWINDOW;
  306. break;
  307. }
  308. if ( groupBtn && ( pl->id == IDC_PLAY || pl->id == IDC_ENQUEUE ) && customAllowed )
  309. {
  310. pl->flags |= SWP_HIDEWINDOW;
  311. break;
  312. }
  313. wchar_t buffer[ 128 ] = { 0 };
  314. GetWindowTextW( pl->hwnd, buffer, ARRAYSIZE( buffer ) );
  315. LRESULT idealSize = MLSkinnedButton_GetIdealSize( pl->hwnd, buffer );
  316. LONG width = LOWORD( idealSize ) + WASABI_API_APP->getScaleX( 6 );
  317. SETLAYOUTPOS( pl, rg.left, rg.bottom - WASABI_API_APP->getScaleY( HIWORD( idealSize ) ), width, WASABI_API_APP->getScaleY( HIWORD( idealSize ) ) );
  318. pl->flags |= ( ( rg.right - rg.left ) > width ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  319. if ( SWP_SHOWWINDOW & pl->flags )
  320. rg.left += ( pl->cx + WASABI_API_APP->getScaleX( 4 ) );
  321. }
  322. else
  323. pl->flags |= SWP_HIDEWINDOW;
  324. break;
  325. case IDC_STATUS:
  326. SETLAYOUTPOS(pl, rg.left, rg.top, rg.right - rg.left, (rg.bottom - rg.top));
  327. pl->flags |= (pl->cx > 16) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  328. break;
  329. case IDC_DOWNLOADLIST:
  330. pl->flags |= (rg.top < rg.bottom) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  331. SETLAYOUTPOS( pl, rg.left, rg.top + WASABI_API_APP->getScaleY( 1 ), rg.right - rg.left + WASABI_API_APP->getScaleY( 1 ), ( rg.bottom - rg.top ) - WASABI_API_APP->getScaleY( 2 ) );
  332. break;
  333. }
  334. SETLAYOUTFLAGS(pl, ri);
  335. if ( LAYOUTNEEEDUPDATE( pl ) )
  336. {
  337. if ( SWP_NOSIZE == ( ( SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_NOSIZE ) & pl->flags ) && ri.left == ( pl->x + offsetX ) && ri.top == ( pl->y + offsetY ) && IsWindowVisible( pl->hwnd ) )
  338. {
  339. SetRect( &ri, pl->x, pl->y, pl->cx + pl->x, pl->y + pl->cy );
  340. ValidateRect( hwnd, &ri );
  341. }
  342. pl++;
  343. }
  344. else if ( ( fRedraw || ( !offsetX && !offsetY ) ) && IsWindowVisible( pl->hwnd ) )
  345. {
  346. ValidateRect( hwnd, &ri );
  347. if ( GetUpdateRect( pl->hwnd, NULL, FALSE ) )
  348. {
  349. if ( !rgn )
  350. rgn = CreateRectRgn( 0, 0, 0, 0 );
  351. GetUpdateRgn( pl->hwnd, rgn, FALSE );
  352. OffsetRgn( rgn, pl->x, pl->y );
  353. InvalidateRgn( hwnd, rgn, FALSE );
  354. }
  355. }
  356. }
  357. if (pl != layout)
  358. {
  359. LAYOUT *pc;
  360. HDWP hdwp = BeginDeferWindowPos((INT)(pl - layout));
  361. for(pc = layout; pc < pl && hdwp; pc++)
  362. {
  363. hdwp = DeferWindowPos(hdwp, pc->hwnd, NULL, pc->x, pc->y, pc->cx, pc->cy, pc->flags);
  364. }
  365. if (hdwp)
  366. EndDeferWindowPos(hdwp);
  367. if ( !rgn )
  368. rgn = CreateRectRgn( 0, 0, 0, 0 );
  369. if (fRedraw)
  370. {
  371. GetUpdateRgn(hwnd, rgn, FALSE);
  372. for ( pc = layout; pc < pl && hdwp; pc++ )
  373. {
  374. if ( pc->rgn )
  375. {
  376. OffsetRgn( pc->rgn, pc->x, pc->y );
  377. CombineRgn( rgn, rgn, pc->rgn, RGN_OR );
  378. }
  379. }
  380. RedrawWindow(hwnd, NULL, rgn, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN);
  381. }
  382. if (g_rgnUpdate)
  383. {
  384. GetUpdateRgn(hwnd, g_rgnUpdate, FALSE);
  385. for(pc = layout; pc < pl && hdwp; pc++)
  386. {
  387. if (pc->rgn)
  388. {
  389. OffsetRgn(pc->rgn, pc->x, pc->y);
  390. CombineRgn(g_rgnUpdate, g_rgnUpdate, pc->rgn, RGN_OR);
  391. }
  392. }
  393. }
  394. for(pc = layout; pc < pl && hdwp; pc++) if (pc->rgn) DeleteObject(pc->rgn);
  395. }
  396. if ( rgn )
  397. DeleteObject( rgn );
  398. ValidateRgn(hwnd, NULL);
  399. }
  400. void Downloads_DisplayChange(HWND hwndDlg)
  401. {
  402. ListView_SetTextColor(downloadList.getwnd(), dialogSkinner.Color(WADLG_ITEMFG));
  403. ListView_SetBkColor(downloadList.getwnd(), dialogSkinner.Color(WADLG_ITEMBG));
  404. ListView_SetTextBkColor(downloadList.getwnd(), dialogSkinner.Color(WADLG_ITEMBG));
  405. downloadList.SetFont(dialogSkinner.GetFont());
  406. LayoutWindows(hwndDlg, TRUE);
  407. }
  408. static void DownloadsDialog_SkinControls(HWND hwnd, const INT *itemList, INT itemCount, UINT skinType, UINT skinStyle)
  409. {
  410. MLSKINWINDOW skinWindow = {0};
  411. skinWindow.style = skinStyle;
  412. skinWindow.skinType = skinType;
  413. for(INT i = 0; i < itemCount; i++)
  414. {
  415. skinWindow.hwndToSkin = GetDlgItem(hwnd, itemList[i]);
  416. if (NULL != skinWindow.hwndToSkin)
  417. {
  418. MLSkinWindow(plugin.hwndLibraryParent, &skinWindow);
  419. }
  420. }
  421. }
  422. static void DownloadDialog_InitializeList(HWND hwnd)
  423. {
  424. HWND hControl = GetDlgItem(hwnd, IDC_DOWNLOADLIST);
  425. if (NULL == hControl) return;
  426. UINT styleEx = (UINT)GetWindowLongPtr(hControl, GWL_EXSTYLE);
  427. SetWindowLongPtr(hControl, GWL_EXSTYLE, styleEx & ~WS_EX_NOPARENTNOTIFY);
  428. styleEx = LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP;
  429. SendMessage(hControl, LVM_SETEXTENDEDLISTVIEWSTYLE, styleEx, styleEx);
  430. SendMessage(hControl, LVM_SETUNICODEFORMAT, (WPARAM)TRUE, 0L);
  431. MLSKINWINDOW skinWindow;
  432. skinWindow.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWLVS_ALTERNATEITEMS;
  433. skinWindow.skinType = SKINNEDWND_TYPE_LISTVIEW;
  434. skinWindow.hwndToSkin = hControl;
  435. MLSkinWindow(plugin.hwndLibraryParent, &skinWindow);
  436. }
  437. bool COL_SOURCE_Sort(const DownloadListItem* item1, const DownloadListItem* item2)
  438. {
  439. if (item1->f && item2->f)
  440. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, (item1->f->source), -1, (item2->f->source), -1));
  441. else if (!item1->f && !item2->f)
  442. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, (item1->source), -1, (item2->source), -1));
  443. else if (!item1->f)
  444. return (FALSE == downloadsSortAscending)?0:1;
  445. else //if (!item2->f)
  446. return (FALSE == downloadsSortAscending)?1:0;
  447. //return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  448. // (item1->f?item1->f->source:item1->source), -1,
  449. // (item2->f?item2->f->source:item2->source), -1));
  450. }
  451. bool COL_TITLE_Sort(const DownloadListItem* item1, const DownloadListItem* item2)
  452. {
  453. if (item1->f && item2->f)
  454. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, (item1->f->title), -1, (item2->f->title), -1));
  455. else if (!item1->f && !item2->f)
  456. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, (item1->title), -1, (item2->title), -1));
  457. else if (!item1->f)
  458. return (FALSE == downloadsSortAscending)?0:1;
  459. else //if (!item2->f)
  460. return (FALSE == downloadsSortAscending)?1:0;
  461. //return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  462. // (item1->f?item1->f->title:item1->title), -1,
  463. // (item2->f?item2->f->title:item2->title), -1));
  464. }
  465. bool COL_PROGRESS_Sort( const DownloadListItem *item1, const DownloadListItem *item2 )
  466. {
  467. if ( item1->f && item2->f )
  468. return ( item1->f->downloadStatus > item2->f->downloadStatus );
  469. else if ( !item1->f && !item2->f )
  470. return ( item1->token < item2->token );
  471. else if ( !item1->f )
  472. return ( FALSE == downloadsSortAscending ) ? 0 : 1;
  473. else //if (!item2->f)
  474. return ( FALSE == downloadsSortAscending ) ? 1 : 0;
  475. //return ((item1->f?item1->f->downloadStatus:-1) < (item2->f?item2->f->downloadStatus:-1));
  476. //return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  477. // (item1->f?GetDownloadStatus(item1->f->downloadStatus):item1->status), -1,
  478. // (item2->f?GetDownloadStatus(item2->f->downloadStatus):item2->status), -1));
  479. }
  480. bool COL_PATH_Sort(const DownloadListItem* item1, const DownloadListItem* item2)
  481. {
  482. if (item1->f && item2->f)
  483. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, (item1->f->path), -1, (item2->f->path), -1));
  484. else if (!item1->f && !item2->f)
  485. return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, (item1->path), -1, (item2->path), -1));
  486. else if (!item1->f)
  487. return (FALSE == downloadsSortAscending)?0:1;
  488. else //if (!item2->f)
  489. return (FALSE == downloadsSortAscending)?1:0;
  490. //return (CSTR_LESS_THAN == CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
  491. // (item1->f?item1->f->path:item1->path), -1,
  492. // (item2->f?item2->f->path:item2->path), -1));
  493. }
  494. bool COL_DATE_Sort(const DownloadListItem* item1, const DownloadListItem* item2)
  495. {
  496. if (item1->f && item2->f)
  497. return item1->f->downloadDate < item2->f->downloadDate;
  498. else if (!item1->f && !item2->f)
  499. return item1->token < item2->token;
  500. else if (!item1->f)
  501. return (FALSE == downloadsSortAscending)?0:1;
  502. else //if (!item2->f)
  503. return (FALSE == downloadsSortAscending)?1:0;
  504. }
  505. bool COL_SIZE_Sort(const DownloadListItem* item1, const DownloadListItem* item2)
  506. {
  507. if (item1->f && item2->f)
  508. return item1->f->totalSize < item2->f->totalSize;
  509. else if (!item1->f && !item2->f)
  510. return item1->token < item2->token;
  511. else if (!item1->f)
  512. return (FALSE == downloadsSortAscending)?0:1;
  513. else //if (!item2->f)
  514. return (FALSE == downloadsSortAscending)?1:0;
  515. }
  516. static BOOL Downloads_SortItems(int sortColumn)
  517. {
  518. AutoLock lock (downloadedFiles);
  519. switch (sortColumn)
  520. {
  521. case COL_TITLE:
  522. std::sort(listContents.begin(), listContents.end(), COL_TITLE_Sort);
  523. if (FALSE == downloadsSortAscending) std::reverse(listContents.begin(), listContents.end());
  524. return TRUE;
  525. case COL_PROGRESS:
  526. std::sort(listContents.begin(), listContents.end(), COL_PROGRESS_Sort);
  527. if (FALSE == downloadsSortAscending) std::reverse(listContents.begin(), listContents.end());
  528. return TRUE;
  529. case COL_DATE:
  530. std::sort(listContents.begin(), listContents.end(), COL_DATE_Sort);
  531. if (FALSE == downloadsSortAscending) std::reverse(listContents.begin(), listContents.end());
  532. return TRUE;
  533. case COL_SOURCE:
  534. std::sort(listContents.begin(), listContents.end(), COL_SOURCE_Sort);
  535. if (FALSE == downloadsSortAscending) std::reverse(listContents.begin(), listContents.end());
  536. return TRUE;
  537. case COL_SIZE:
  538. std::sort(listContents.begin(), listContents.end(), COL_SIZE_Sort);
  539. if (FALSE == downloadsSortAscending) std::reverse(listContents.begin(), listContents.end());
  540. return TRUE;
  541. case COL_PATH:
  542. std::sort(listContents.begin(), listContents.end(), COL_PATH_Sort);
  543. if (FALSE == downloadsSortAscending) std::reverse(listContents.begin(), listContents.end());
  544. return TRUE;
  545. }
  546. return FALSE;
  547. }
  548. static void Downloads_SetListSortColumn(HWND hwnd, INT listId, INT index, BOOL fAscending)
  549. {
  550. HWND hItems = GetDlgItem(hwnd, listId);
  551. if (NULL == hItems) return;
  552. HWND hHeader = (HWND)SNDMSG(hItems, LVM_GETHEADER, 0, 0L);
  553. if (NULL == hHeader) return;
  554. HDITEM item;
  555. item.mask = HDI_FORMAT;
  556. // reset first (ml req)
  557. INT count = (INT)SNDMSG(hHeader, HDM_GETITEMCOUNT, 0, 0L);
  558. for (INT i = 0; i < count; i++)
  559. {
  560. if (index != i && FALSE != (BOOL)SNDMSG(hHeader, HDM_GETITEM, i, (LPARAM)&item))
  561. {
  562. if (0 != ((HDF_SORTUP | HDF_SORTDOWN) & item.fmt))
  563. {
  564. item.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
  565. SNDMSG(hHeader, HDM_SETITEM, i, (LPARAM)&item);
  566. }
  567. }
  568. }
  569. if (FALSE != (BOOL)SNDMSG(hHeader, HDM_GETITEM, index, (LPARAM)&item))
  570. {
  571. INT fmt = item.fmt & ~(HDF_SORTUP | HDF_SORTDOWN);
  572. fmt |= (FALSE == fAscending) ? HDF_SORTDOWN : HDF_SORTUP;
  573. if (fmt != item.fmt)
  574. {
  575. item.fmt = fmt;
  576. SNDMSG(hHeader, HDM_SETITEM, index, (LPARAM)&item);
  577. }
  578. }
  579. }
  580. static BOOL Downloads_Sort(HWND hwnd, INT iColumn, bool fAscending)
  581. {
  582. BOOL result = TRUE;
  583. downloadsSortAscending = fAscending;
  584. Downloads_SortItems(iColumn);
  585. Downloads_SetListSortColumn(hwnd, IDC_DOWNLOADLIST, iColumn, fAscending);
  586. if (FALSE != result)
  587. {
  588. HWND hItems = GetDlgItem(hwnd, IDC_DOWNLOADLIST);
  589. if (NULL != hItems)
  590. InvalidateRect(hItems, NULL, TRUE);
  591. }
  592. return TRUE;
  593. }
  594. void Downloads_UpdateButtonText(HWND hwndDlg, int _enqueuedef)
  595. {
  596. if (groupBtn)
  597. {
  598. switch(_enqueuedef)
  599. {
  600. case 1:
  601. SetDlgItemTextW(hwndDlg, IDC_PLAY, view.enqueue);
  602. customAllowed = FALSE;
  603. break;
  604. default:
  605. // v5.66+ - re-use the old predixis parts so the button can be used functionally via ml_enqplay
  606. // pass the hwnd, button id and plug-in id so the ml plug-in can check things as needed
  607. pluginMessage p = {ML_MSG_VIEW_BUTTON_HOOK_IN_USE, (INT_PTR)_enqueuedef, 0, 0};
  608. wchar_t *pszTextW = (wchar_t *)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p);
  609. if (pszTextW && pszTextW[0] != 0)
  610. {
  611. // set this to be a bit different so we can just use one button and not the
  612. // mixable one as well (leaving that to prevent messing with the resources)
  613. SetDlgItemTextW(hwndDlg, IDC_PLAY, pszTextW);
  614. customAllowed = TRUE;
  615. }
  616. else
  617. {
  618. SetDlgItemTextW(hwndDlg, IDC_PLAY, view.play);
  619. customAllowed = FALSE;
  620. }
  621. break;
  622. }
  623. }
  624. }
  625. static void Downloads_ManageButtons( HWND hwndDlg )
  626. {
  627. int has_selection = downloadList.GetSelectedCount();
  628. const int buttonids[] = { IDC_PLAY, IDC_ENQUEUE, IDC_CUSTOM, IDC_REMOVE };
  629. for ( size_t i = 0; i != sizeof( buttonids ) / sizeof( buttonids[ 0 ] ); i++ )
  630. {
  631. HWND controlHWND = GetDlgItem( hwndDlg, buttonids[ i ] );
  632. EnableWindow( controlHWND, has_selection );
  633. }
  634. }
  635. void Downloads_Init(HWND hwndDlg)
  636. {
  637. HWND hLibrary = plugin.hwndLibraryParent;
  638. downloads_window = hwndDlg;
  639. if (!view.play)
  640. {
  641. SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_GET_VIEW_BUTTON_TEXT, (WPARAM)&view);
  642. }
  643. HACCEL accel = WASABI_API_LOADACCELERATORSW(IDR_VIEW_DOWNLOAD_ACCELERATORS);
  644. if (accel)
  645. WASABI_API_APP->app_addAccelerators(hwndDlg, &accel, 1, TRANSLATE_MODE_CHILD);
  646. g_context_menus2 = WASABI_API_LOADMENU(IDR_MENU1);
  647. groupBtn = ML_GROUPBTN_VAL();
  648. enqueuedef = (ML_ENQDEF_VAL() == 1);
  649. // v5.66+ - re-use the old predixis parts so the button can be used functionally via ml_enqplay
  650. // pass the hwnd, button id and plug-in id so the ml plug-in can check things as needed
  651. pluginMessage p = {ML_MSG_VIEW_BUTTON_HOOK, (INT_PTR)hwndDlg, (INT_PTR)MAKELONG(IDC_CUSTOM, IDC_ENQUEUE), (INT_PTR)L"ml_downloads"};
  652. wchar_t *pszTextW = (wchar_t *)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p);
  653. if (pszTextW && pszTextW[0] != 0)
  654. {
  655. // set this to be a bit different so we can just use one button and not the
  656. // mixable one as well (leaving that to prevent messing with the resources)
  657. customAllowed = TRUE;
  658. SetDlgItemTextW(hwndDlg, IDC_CUSTOM, pszTextW);
  659. }
  660. else
  661. customAllowed = FALSE;
  662. MLSkinWindow2(hLibrary, hwndDlg, SKINNEDWND_TYPE_AUTO, SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
  663. const INT szControls[] = {IDC_PLAY, IDC_ENQUEUE, IDC_CUSTOM};
  664. DownloadsDialog_SkinControls(hwndDlg, szControls, ARRAYSIZE(szControls), SKINNEDWND_TYPE_AUTO,
  665. SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | (groupBtn ? SWBS_SPLITBUTTON : 0));
  666. const INT szControlz[] = {IDC_REMOVE, IDC_CLEANUP, IDC_STATUS};
  667. DownloadsDialog_SkinControls(hwndDlg, szControlz, ARRAYSIZE(szControlz), SKINNEDWND_TYPE_AUTO,
  668. SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS);
  669. DownloadDialog_InitializeList(hwndDlg);
  670. Downloads_UpdateStatusBar(hwndDlg);
  671. downloadList.setwnd(GetDlgItem(hwndDlg, IDC_DOWNLOADLIST));
  672. downloadList.AddCol(WASABI_API_LNGSTRINGW(IDS_TITLE), downloadsTitleWidth);
  673. downloadList.AddCol(WASABI_API_LNGSTRINGW(IDS_PROGRESS), downloadsProgressWidth);
  674. downloadList.AddCol(WASABI_API_LNGSTRINGW(IDS_DATE), downloadsDateWidth);
  675. downloadList.AddCol(WASABI_API_LNGSTRINGW(IDS_SOURCE), downloadsSourceWidth);
  676. downloadList.AddCol(WASABI_API_LNGSTRINGW(IDS_SIZE), downloadsSizeWidth);
  677. downloadList.AddCol(WASABI_API_LNGSTRINGW(IDS_PATH), downloadsPathWidth);
  678. DownloadsUpdated();
  679. downloadList.SetVirtualCount((int)listContents.size());
  680. Downloads_UpdateButtonText(hwndDlg, enqueuedef == 1);
  681. Downloads_ManageButtons(hwndDlg);
  682. Downloads_DisplayChange(hwndDlg);
  683. Downloads_Sort(hwndDlg, downloadsItemSort, downloadsSortAscending);
  684. SetTimer(hwndDlg, DOWNLOADSDIALOG_TIMER_UPDATESTATUSBAR , 1000, 0);
  685. }
  686. void Downloads_Timer( HWND hwndDlg, UINT timerId )
  687. {
  688. switch ( timerId )
  689. {
  690. case DOWNLOADSDIALOG_TIMER_UPDATESTATUSBAR:
  691. Downloads_UpdateStatusBar( hwndDlg );
  692. {
  693. AutoLock lock( downloadStatus.statusLock );
  694. for ( DownloadListItem *l_content : listContents )
  695. {
  696. if ( l_content->token )
  697. {
  698. size_t d = downloadStatus.downloads[ l_content->token ].downloaded;
  699. size_t s = downloadStatus.downloads[ l_content->token ].maxSize;
  700. if ( s )
  701. StringCchPrintf( l_content->status, 20, WASABI_API_LNGSTRINGW( IDS_DOWNLOADING_PERCENT ), (int)( d / ( s / 100 ) ) );
  702. else
  703. {
  704. if ( WAC_API_DOWNLOADMANAGER->IsPending( l_content->token ) )
  705. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOAD_PENDING, l_content->status, 20 );
  706. else
  707. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOADING, l_content->status, 20 );
  708. }
  709. PostMessage( downloadList.getwnd(), LVM_REDRAWITEMS, 0, listContents.size() );
  710. }
  711. }
  712. }
  713. break;
  714. }
  715. }
  716. static INT Downloads_GetListSortColumn(HWND hwnd, INT listId, bool *fAscending)
  717. {
  718. HWND hItems = GetDlgItem(hwnd, listId);
  719. if (NULL != hItems)
  720. {
  721. HWND hHeader = (HWND)SNDMSG(hItems, LVM_GETHEADER, 0, 0L);
  722. if (NULL != hHeader)
  723. {
  724. HDITEM item;
  725. item.mask = HDI_FORMAT;
  726. INT count = (INT)SNDMSG(hHeader, HDM_GETITEMCOUNT, 0, 0L);
  727. for (INT i = 0; i < count; i++)
  728. {
  729. if (FALSE != (BOOL)SNDMSG(hHeader, HDM_GETITEM, i, (LPARAM)&item) &&
  730. 0 != ((HDF_SORTUP | HDF_SORTDOWN) & item.fmt))
  731. {
  732. if (NULL != fAscending)
  733. {
  734. *fAscending = (0 != (HDF_SORTUP & item.fmt));
  735. }
  736. return i;
  737. }
  738. }
  739. }
  740. }
  741. return -1;
  742. }
  743. void Downloads_Destroy( HWND hwndDlg )
  744. {
  745. downloads_window = 0;
  746. downloadsSourceWidth = downloadList.GetColumnWidth( COL_SOURCE );
  747. downloadsTitleWidth = downloadList.GetColumnWidth( COL_TITLE );
  748. downloadsProgressWidth = downloadList.GetColumnWidth( COL_PROGRESS );
  749. downloadsPathWidth = downloadList.GetColumnWidth( COL_PATH );
  750. downloadsDateWidth = downloadList.GetColumnWidth( COL_DATE );
  751. downloadsSizeWidth = downloadList.GetColumnWidth( COL_SIZE );
  752. for ( DownloadListItem *l_content : listContents )
  753. delete l_content;
  754. listContents.clear();
  755. downloadList.setwnd( NULL );
  756. bool fAscending;
  757. downloadsItemSort = Downloads_GetListSortColumn( hwndDlg, IDC_DOWNLOADLIST, &fAscending );
  758. downloadsSortAscending = ( -1 != downloadsItemSort ) ? ( FALSE != fAscending ) : true;
  759. int activeDownloads = 0;
  760. int historyDownloads = 0;
  761. {
  762. Nullsoft::Utility::AutoLock historylock( downloadedFiles.downloadedLock );
  763. Nullsoft::Utility::AutoLock statuslock( downloadStatus.statusLock );
  764. historyDownloads = (int)downloadedFiles.downloadList.size();
  765. activeDownloads = (int)downloadStatus.downloads.size();
  766. }
  767. if ( !activeDownloads && !historyDownloads && !no_auto_hide )
  768. {
  769. HNAVITEM hItem = MLNavCtrl_FindItemById( plugin.hwndLibraryParent, downloads_treeItem );
  770. if ( hItem )
  771. {
  772. MLNavCtrl_DeleteItem( plugin.hwndLibraryParent, hItem );
  773. downloads_treeItem = 0;
  774. }
  775. }
  776. }
  777. void Downloads_Remove( bool del = false, HWND parent = NULL )
  778. {
  779. int d = -1;
  780. int r = 0;
  781. while ( GetDownload( d ) )
  782. {
  783. int download = d - r;
  784. DownloadListItem *item = listContents[ download ];
  785. if ( item->f )
  786. {
  787. AutoLock lock( downloadedFiles );
  788. int j = 0;
  789. for ( DownloadList::iterator i = downloadedFiles.begin(); i != downloadedFiles.end(); ++i )
  790. {
  791. if ( !_wcsicmp( i->path, item->f->path ) )
  792. {
  793. if ( del )
  794. {
  795. if ( !downloadedFiles.RemoveAndDelete( j ) )
  796. MessageBox( parent, WASABI_API_LNGSTRINGW( IDS_DELETEFAILED ), downloadedFiles.downloadList[ j ].path, 0 );
  797. }
  798. else
  799. downloadedFiles.Remove( j );
  800. delete item;
  801. listContents.erase( listContents.begin() + download );
  802. r++;
  803. dirty++;
  804. break;
  805. }
  806. ++j;
  807. }
  808. }
  809. else if ( item->token )
  810. {
  811. AutoLock lock( downloadStatus.statusLock );
  812. downloadStatus.downloads[ item->token ].killswitch = 1;
  813. delete item;
  814. listContents.erase( listContents.begin() + download );
  815. r++;
  816. }
  817. else
  818. {
  819. delete item;
  820. listContents.erase( listContents.begin() + download );
  821. r++;
  822. }
  823. }
  824. downloadList.SetVirtualCountAsync( (int)listContents.size() );
  825. downloadList.UnselectAll();
  826. // Navigation_ShowService(SERVICE_DOWNLOADS, SHOWMODE_AUTO);
  827. }
  828. void Downloads_Delete( HWND parent )
  829. {
  830. wchar_t message[ 256 ] = { 0 };
  831. int c = downloadList.GetSelectedCount();
  832. if ( !c )
  833. return;
  834. else if ( c == 1 )
  835. WASABI_API_LNGSTRINGW_BUF( IDS_PERM_DELETE_ARE_YOU_SURE, message, 256 );
  836. else
  837. StringCchPrintf( message, 256, WASABI_API_LNGSTRINGW( IDS_PERM_DELETE_THESE_ARE_YOU_SURE ), c );
  838. if ( MessageBox( NULL, message, WASABI_API_LNGSTRINGW( IDS_DELETION ), MB_ICONWARNING | MB_YESNO ) == IDNO )
  839. return;
  840. Downloads_Remove( true, parent );
  841. }
  842. void Downloads_CleanUp(HWND hwndDlg)
  843. {
  844. wchar_t titleStr[64] = {0};
  845. if ( MessageBox( hwndDlg, WASABI_API_LNGSTRINGW( IDS_CLEAR_ALL_FINISHED_DOWNLOADS ), WASABI_API_LNGSTRINGW_BUF( IDS_CLEAN_UP_LIST, titleStr, 64 ), MB_ICONWARNING | MB_YESNO ) == IDNO )
  846. return;
  847. {
  848. AutoLock lock( downloadedFiles );
  849. downloadedFiles.downloadList.clear();
  850. }
  851. dirty++;
  852. DownloadsUpdated();
  853. }
  854. void Downloads_InfoBox( HWND parent )
  855. {
  856. int download = -1;
  857. if ( GetDownload( download ) )
  858. {
  859. const wchar_t *fn;
  860. if ( listContents[ download ]->f )
  861. fn = listContents[ download ]->f->path;
  862. else
  863. fn = listContents[ download ]->path;
  864. if ( fn )
  865. {
  866. infoBoxParamW p = { parent, fn };
  867. SendMessage( plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&p, IPC_INFOBOXW );
  868. }
  869. }
  870. }
  871. void Downloads_SelectAll()
  872. {
  873. int l = downloadList.GetCount();
  874. for ( int i = 0; i < l; i++ )
  875. downloadList.SetSelected( i );
  876. }
  877. static void exploreItemFolder( HWND hwndDlg )
  878. {
  879. if ( downloadList.GetSelectionMark() >= 0 )
  880. {
  881. int download = -1;
  882. while ( GetDownload( download ) )
  883. {
  884. wchar_t *file;
  885. if ( listContents[ download ]->f )
  886. file = listContents[ download ]->f->path;
  887. else
  888. file = listContents[ download ]->path;
  889. WASABI_API_EXPLORERFINDFILE->AddFile( file );
  890. }
  891. WASABI_API_EXPLORERFINDFILE->ShowFiles();
  892. }
  893. }
  894. void Downloads_Cancel()
  895. {
  896. int l_selected_count = downloadList.GetSelectedCount();
  897. for ( int i = -1; i < l_selected_count; ++i )
  898. {
  899. if ( GetDownload( i ) )
  900. {
  901. dirty++;
  902. if ( !listContents[ i ]->f )
  903. WAC_API_DOWNLOADMANAGER->CancelDownload( listContents[ i ]->token );
  904. break; // Workaround for 5.9.1 to avoid crash if cancel of many downloads in same time
  905. }
  906. }
  907. }
  908. int we_are_drag_and_dropping = 0;
  909. static void Downloads_OnColumnClick(HWND hwnd, NMLISTVIEW *plv)
  910. {
  911. bool fAscending;
  912. INT iSort = Downloads_GetListSortColumn(hwnd, IDC_DOWNLOADLIST, &fAscending);
  913. fAscending = (-1 != iSort && iSort == plv->iSubItem) ? (!fAscending) : true;
  914. Downloads_Sort(hwnd, plv->iSubItem, fAscending);
  915. }
  916. LRESULT DownloadList_Notify( LPNMHDR l, HWND hwndDlg )
  917. {
  918. switch ( l->code )
  919. {
  920. case LVN_COLUMNCLICK:
  921. Downloads_OnColumnClick( hwndDlg, (NMLISTVIEW *)l );
  922. break;
  923. case NM_DBLCLK:
  924. Downloads_Play( ( ( !!( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) ) ^ ML_ENQDEF_VAL() ) );
  925. break;
  926. case LVN_BEGINDRAG:
  927. we_are_drag_and_dropping = 1;
  928. SetCapture( hwndDlg );
  929. break;
  930. case LVN_ITEMCHANGED:
  931. Downloads_ManageButtons( hwndDlg );
  932. break;
  933. case LVN_GETDISPINFO:
  934. NMLVDISPINFO *lpdi = (NMLVDISPINFO *)l;
  935. size_t item = lpdi->item.iItem;
  936. if ( item < 0 || item >= listContents.size() )
  937. return 0;
  938. //if (FALSE == downloadsSortAscending) item = listContents.size() - item - 1;
  939. DownloadListItem *l = listContents[ item ];
  940. if ( lpdi->item.mask & LVIF_TEXT )
  941. {
  942. lpdi->item.pszText[ 0 ] = 0;
  943. switch ( lpdi->item.iSubItem )
  944. {
  945. case COL_TITLE:
  946. if ( !l->token && l->f )
  947. {
  948. wchar_t *l_title = L"";
  949. if ( l->f->title != NULL )
  950. l_title = l->f->title;
  951. lstrcpyn( lpdi->item.pszText, l_title, lpdi->item.cchTextMax );
  952. }
  953. else
  954. {
  955. if ( l->title ) lstrcpyn( lpdi->item.pszText, l->title, lpdi->item.cchTextMax );
  956. }
  957. break;
  958. case COL_PROGRESS:
  959. if ( !l->token && l->f )
  960. {
  961. switch ( l->f->downloadStatus )
  962. {
  963. case DownloadedFile::DOWNLOAD_SUCCESS:
  964. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOAD_SUCCESS, lpdi->item.pszText, lpdi->item.cchTextMax );
  965. break;
  966. case DownloadedFile::DOWNLOAD_FAILURE:
  967. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOAD_FAILURE, lpdi->item.pszText, lpdi->item.cchTextMax );
  968. break;
  969. case DownloadedFile::DOWNLOAD_CANCELED:
  970. WASABI_API_LNGSTRINGW_BUF( IDS_DOWNLOAD_CANCELED, lpdi->item.pszText, lpdi->item.cchTextMax );
  971. break;
  972. }
  973. }
  974. else lstrcpyn( lpdi->item.pszText, l->status, lpdi->item.cchTextMax );
  975. break;
  976. case COL_DATE:
  977. {
  978. if ( !l->token && l->f && l->f->downloadDate )
  979. {
  980. wchar_t tmp[ 128 ] = { 0 };
  981. MakeDateString( l->f->downloadDate, tmp, 128 );
  982. lstrcpyn( lpdi->item.pszText, tmp, lpdi->item.cchTextMax );
  983. }
  984. else
  985. {
  986. WASABI_API_LNGSTRINGW_BUF( IDS_N_A, lpdi->item.pszText, lpdi->item.cchTextMax );
  987. }
  988. break;
  989. }
  990. case COL_SOURCE:
  991. if ( !l->token && l->f )
  992. {
  993. wchar_t *l_source = L"";
  994. if ( l->f->source != NULL )
  995. l_source = l->f->source;
  996. lstrcpyn( lpdi->item.pszText, l_source, lpdi->item.cchTextMax );
  997. }
  998. else
  999. lstrcpyn( lpdi->item.pszText, l->source, lpdi->item.cchTextMax );
  1000. break;
  1001. case COL_SIZE:
  1002. {
  1003. if ( !l->token && l->f && l->f->totalSize > 0 )
  1004. WASABI_API_LNG->FormattedSizeString( lpdi->item.pszText, lpdi->item.cchTextMax, l->f->totalSize );
  1005. else
  1006. WASABI_API_LNGSTRINGW_BUF( IDS_N_A, lpdi->item.pszText, lpdi->item.cchTextMax );
  1007. break;
  1008. }
  1009. case COL_PATH:
  1010. if ( !l->token && l->f )
  1011. {
  1012. wchar_t *l_path = L"";
  1013. if ( l->f->path != NULL )
  1014. l_path = l->f->path;
  1015. lstrcpyn( lpdi->item.pszText, l_path, lpdi->item.cchTextMax );
  1016. }
  1017. else
  1018. {
  1019. if ( l->path )
  1020. lstrcpyn( lpdi->item.pszText, l->path, lpdi->item.cchTextMax );
  1021. }
  1022. break;
  1023. }
  1024. }
  1025. break;
  1026. }
  1027. return 0;
  1028. }
  1029. void listbuild( wchar_t **buf, int &buf_size, int &buf_pos, const wchar_t *tbuf )
  1030. {
  1031. if ( !*buf )
  1032. {
  1033. *buf = (wchar_t *)calloc( 4096, sizeof( wchar_t ) );
  1034. if ( *buf )
  1035. {
  1036. buf_size = 4096;
  1037. buf_pos = 0;
  1038. }
  1039. else
  1040. {
  1041. buf_size = buf_pos = 0;
  1042. }
  1043. }
  1044. int newsize = buf_pos + lstrlenW( tbuf ) + 1;
  1045. if ( newsize < buf_size )
  1046. {
  1047. size_t old_buf_size = buf_size;
  1048. buf_size = newsize + 4096;
  1049. wchar_t *new_buf = (wchar_t *)realloc( *buf, ( buf_size + 1 ) * sizeof( wchar_t ) );
  1050. if ( new_buf )
  1051. {
  1052. *buf = new_buf;
  1053. }
  1054. else
  1055. {
  1056. new_buf = (wchar_t*)calloc( ( buf_size + 1 ), sizeof( wchar_t ) );
  1057. if ( new_buf )
  1058. {
  1059. memcpy( new_buf, *buf, ( old_buf_size * sizeof( wchar_t ) ) );
  1060. free( *buf );
  1061. *buf = new_buf;
  1062. }
  1063. else buf_size = (int)old_buf_size;
  1064. }
  1065. }
  1066. StringCchCopyW( *buf + buf_pos, buf_size, tbuf );
  1067. buf_pos = newsize;
  1068. }
  1069. wchar_t *getSelectedList()
  1070. {
  1071. wchar_t *path = NULL;
  1072. int buf_pos = 0;
  1073. int buf_size = 0;
  1074. int download = -1;
  1075. while ( GetDownload( download ) )
  1076. {
  1077. if ( listContents[ download ]->f )
  1078. listbuild( &path, buf_size, buf_pos, listContents[ download ]->f->path );
  1079. }
  1080. if ( path )
  1081. path[ buf_pos ] = 0;
  1082. return path;
  1083. }
  1084. static void SwapPlayEnqueueInMenu( HMENU listMenu )
  1085. {
  1086. int playPos = -1, enqueuePos = -1;
  1087. MENUITEMINFOW playItem = { sizeof( MENUITEMINFOW ), 0, }, enqueueItem = { sizeof( MENUITEMINFOW ), 0, };
  1088. int numItems = GetMenuItemCount( listMenu );
  1089. for ( int i = 0; i < numItems; i++ )
  1090. {
  1091. UINT id = GetMenuItemID( listMenu, i );
  1092. if ( id == IDC_PLAY )
  1093. {
  1094. playItem.fMask = MIIM_ID;
  1095. playPos = i;
  1096. GetMenuItemInfoW( listMenu, i, TRUE, &playItem );
  1097. }
  1098. else if ( id == IDC_ENQUEUE )
  1099. {
  1100. enqueueItem.fMask = MIIM_ID;
  1101. enqueuePos = i;
  1102. GetMenuItemInfoW( listMenu, i, TRUE, &enqueueItem );
  1103. }
  1104. }
  1105. playItem.wID = IDC_ENQUEUE;
  1106. enqueueItem.wID = IDC_PLAY;
  1107. SetMenuItemInfoW( listMenu, playPos, TRUE, &playItem );
  1108. SetMenuItemInfoW( listMenu, enqueuePos, TRUE, &enqueueItem );
  1109. }
  1110. static void SyncMenuWithAccelerators( HWND hwndDlg, HMENU menu )
  1111. {
  1112. HACCEL szAccel[ 24 ] = { 0 };
  1113. INT c = WASABI_API_APP->app_getAccelerators( hwndDlg, szAccel, sizeof( szAccel ) / sizeof( szAccel[ 0 ] ), FALSE );
  1114. AppendMenuShortcuts( menu, szAccel, c, MSF_REPLACE );
  1115. }
  1116. void UpdateMenuItems( HWND hwndDlg, HMENU menu )
  1117. {
  1118. bool swapPlayEnqueue = false;
  1119. if ( ML_ENQDEF_VAL() )
  1120. {
  1121. SwapPlayEnqueueInMenu( menu );
  1122. swapPlayEnqueue = true;
  1123. }
  1124. SyncMenuWithAccelerators( hwndDlg, menu );
  1125. if ( swapPlayEnqueue )
  1126. SwapPlayEnqueueInMenu( menu );
  1127. }
  1128. static int IPC_LIBRARY_SENDTOMENU = 0;
  1129. static librarySendToMenuStruct s = { 0 };
  1130. static void DownloadList_RightClick(HWND hwndDlg, HWND listHwnd, POINTS pts)
  1131. {
  1132. POINT pt;
  1133. POINTSTOPOINT(pt, pts);
  1134. RECT controlRect, headerRect;
  1135. if (FALSE == GetClientRect(listHwnd, &controlRect))
  1136. SetRectEmpty(&controlRect);
  1137. else
  1138. MapWindowPoints(listHwnd, HWND_DESKTOP, (POINT*)&controlRect, 2);
  1139. if ( -1 == pt.x && -1 == pt.y )
  1140. {
  1141. RECT itemRect;
  1142. int selected = downloadList.GetNextSelected();
  1143. if ( selected != -1 ) // if something is selected we'll drop the menu from there
  1144. {
  1145. downloadList.GetItemRect( selected, &itemRect );
  1146. ClientToScreen( listHwnd, (POINT *)&itemRect );
  1147. }
  1148. else // otherwise we'll drop it from the top-left corner of the listview, adjusting for the header location
  1149. {
  1150. GetWindowRect( listHwnd, &itemRect );
  1151. HWND hHeader = (HWND)SNDMSG( listHwnd, LVM_GETHEADER, 0, 0L );
  1152. RECT headerRect;
  1153. if ( ( WS_VISIBLE & GetWindowLongPtr( hHeader, GWL_STYLE ) ) && GetWindowRect( hHeader, &headerRect ) )
  1154. {
  1155. itemRect.top += ( headerRect.bottom - headerRect.top );
  1156. }
  1157. }
  1158. pt.x = itemRect.left;
  1159. pt.y = itemRect.top;
  1160. }
  1161. HWND hHeader = (HWND)SNDMSG(listHwnd, LVM_GETHEADER, 0, 0L);
  1162. if ( 0 == ( WS_VISIBLE & GetWindowLongPtr( hHeader, GWL_STYLE ) ) || FALSE == GetWindowRect( hHeader, &headerRect ) )
  1163. {
  1164. SetRectEmpty( &headerRect );
  1165. }
  1166. if ( FALSE != PtInRect( &headerRect, pt ) )
  1167. {
  1168. return;
  1169. }
  1170. LVHITTESTINFO hitTest;
  1171. hitTest.pt = pt;
  1172. MapWindowPoints( HWND_DESKTOP, listHwnd, &hitTest.pt, 1 );
  1173. int index = ( downloadList.GetNextSelected() != -1 ? ListView_HitTest( listHwnd, &hitTest ) : -1 );
  1174. HMENU baseMenu = WASABI_API_LOADMENU( IDR_MENU1 );
  1175. if ( baseMenu == NULL )
  1176. return;
  1177. HMENU menu = GetSubMenu( baseMenu, 0 );
  1178. if ( menu != NULL )
  1179. {
  1180. if ( ( index == -1 ) || ( index != -1 ) && listContents[ index ]->f )
  1181. DeleteMenu( menu, ID_DOWNLOADS_CANCELDOWNLOAD, MF_BYCOMMAND );
  1182. UINT enableExtras = MF_ENABLED;
  1183. if ( ( index == -1 ) || ( index != -1 ) && !listContents[ index ]->f
  1184. || ( index != -1 ) && ( listContents[ index ]->f->downloadStatus != 1 ) )
  1185. enableExtras = ( MF_GRAYED | MF_DISABLED );
  1186. UINT enableViewExtras = MF_ENABLED;
  1187. if ( index == -1 )
  1188. enableViewExtras = ( MF_GRAYED | MF_DISABLED );
  1189. EnableMenuItem( menu, IDC_PLAY, MF_BYCOMMAND | enableExtras );
  1190. EnableMenuItem( menu, IDC_ENQUEUE, MF_BYCOMMAND | enableExtras );
  1191. EnableMenuItem( menu, IDC_REMOVE, MF_BYCOMMAND | enableViewExtras );
  1192. EnableMenuItem( menu, IDC_DELETE, MF_BYCOMMAND | enableExtras );
  1193. EnableMenuItem( menu, IDC_INFOBOX, MF_BYCOMMAND | enableExtras );
  1194. EnableMenuItem( menu, ID_DOWNLOADS_EXPLORERITEMFOLDER, MF_BYCOMMAND | enableExtras );
  1195. EnableMenuItem( menu, 2, MF_BYPOSITION | enableExtras );
  1196. { // send-to menu shit...
  1197. ZeroMemory( &s, sizeof( s ) );
  1198. IPC_LIBRARY_SENDTOMENU = (int)SendMessage( plugin.hwndWinampParent, WM_WA_IPC, ( WPARAM ) & "LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE );
  1199. if ( IPC_LIBRARY_SENDTOMENU > 65536 && SendMessage( plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)0, IPC_LIBRARY_SENDTOMENU ) == 0xffffffff )
  1200. {
  1201. s.mode = 1;
  1202. s.hwnd = hwndDlg;
  1203. s.data_type = ML_TYPE_FILENAMESW;
  1204. s.ctx[ 1 ] = 1;
  1205. s.build_hMenu = GetSubMenu( menu, 2 );
  1206. }
  1207. }
  1208. UpdateMenuItems( hwndDlg, menu );
  1209. int r = Menu_TrackPopup( plugin.hwndLibraryParent, menu, TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON, pt.x, pt.y, hwndDlg, NULL );
  1210. if ( !SendMessage( hwndDlg, WM_COMMAND, r, 0 ) )
  1211. {
  1212. s.menu_id = r; // more send to menu shit...
  1213. if ( s.mode == 2 && SendMessage( plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU ) == 0xffffffff )
  1214. {
  1215. s.mode = 3;
  1216. wchar_t *path = getSelectedList();
  1217. if ( path )
  1218. {
  1219. s.data = path;
  1220. SendMessage( plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU );
  1221. free( path );
  1222. }
  1223. }
  1224. }
  1225. if ( s.mode )
  1226. { // yet more send to menu shit...
  1227. s.mode = 4;
  1228. SendMessage( plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU ); // cleanup
  1229. }
  1230. }
  1231. DestroyMenu( baseMenu );
  1232. }
  1233. static void Downloads_ContextMenu( HWND hwndDlg, WPARAM wParam, LPARAM lParam )
  1234. {
  1235. HWND sourceWindow = (HWND)wParam;
  1236. if ( sourceWindow == downloadList.getwnd() )
  1237. DownloadList_RightClick( hwndDlg, sourceWindow, MAKEPOINTS( lParam ) );
  1238. }
  1239. enum
  1240. {
  1241. BPM_ECHO_WM_COMMAND=0x1, // send WM_COMMAND and return value
  1242. BPM_WM_COMMAND = 0x2, // just send WM_COMMAND
  1243. };
  1244. BOOL Downloads_ButtonPopupMenu( HWND hwndDlg, int buttonId, HMENU menu, int flags = 0 )
  1245. {
  1246. RECT r;
  1247. HWND buttonHWND = GetDlgItem( hwndDlg, buttonId );
  1248. GetWindowRect( buttonHWND, &r );
  1249. UpdateMenuItems( hwndDlg, menu );
  1250. MLSkinnedButton_SetDropDownState( buttonHWND, TRUE );
  1251. UINT tpmFlags = TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_BOTTOMALIGN | TPM_LEFTALIGN;
  1252. if ( !( flags & BPM_WM_COMMAND ) )
  1253. tpmFlags |= TPM_RETURNCMD;
  1254. int x = Menu_TrackPopup( plugin.hwndLibraryParent, menu, tpmFlags, r.left, r.top, hwndDlg, NULL );
  1255. if ( ( flags & BPM_ECHO_WM_COMMAND ) && x )
  1256. SendMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( x, 0 ), 0 );
  1257. MLSkinnedButton_SetDropDownState( buttonHWND, FALSE );
  1258. return x;
  1259. }
  1260. static void Downloads_Play( HWND hwndDlg, HWND from, UINT idFrom )
  1261. {
  1262. HMENU listMenu = GetSubMenu( g_context_menus2, 0 );
  1263. int count = GetMenuItemCount( listMenu );
  1264. if ( count > 2 )
  1265. {
  1266. for ( int i = 2; i < count; i++ )
  1267. {
  1268. DeleteMenu( listMenu, 2, MF_BYPOSITION );
  1269. }
  1270. }
  1271. Downloads_ButtonPopupMenu( hwndDlg, idFrom, listMenu, BPM_WM_COMMAND );
  1272. }
  1273. static BOOL WINAPI DownloadDialog_DlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  1274. {
  1275. switch (msg)
  1276. {
  1277. case WM_INITMENUPOPUP: // yet yet more send to menu shit...
  1278. if (wParam && (HMENU)wParam == s.build_hMenu && s.mode==1)
  1279. {
  1280. if (SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(WPARAM)&s,IPC_LIBRARY_SENDTOMENU)==0xffffffff)
  1281. s.mode=2;
  1282. }
  1283. break;
  1284. case WM_USER+543:
  1285. Navigation_Update();
  1286. break;
  1287. case WM_CONTEXTMENU:
  1288. Downloads_ContextMenu(hwndDlg, wParam, lParam);
  1289. return TRUE;
  1290. case WM_NOTIFYFORMAT:
  1291. return NFR_UNICODE;
  1292. case WM_INITDIALOG:
  1293. Downloads_Init(hwndDlg);
  1294. break;
  1295. case WM_NOTIFY:
  1296. {
  1297. LPNMHDR l = (LPNMHDR)lParam;
  1298. if (l->idFrom == IDC_DOWNLOADLIST)
  1299. return (BOOL)DownloadList_Notify(l,hwndDlg);
  1300. }
  1301. break;
  1302. case WM_DESTROY:
  1303. Downloads_Destroy(hwndDlg);
  1304. return 0;
  1305. case WM_DISPLAYCHANGE:
  1306. Downloads_DisplayChange(hwndDlg);
  1307. return 0;
  1308. case WM_TIMER:
  1309. Downloads_Timer(hwndDlg, (UINT)wParam);
  1310. break;
  1311. case WM_MOUSEMOVE:
  1312. if (we_are_drag_and_dropping && GetCapture() == hwndDlg)
  1313. {
  1314. POINT p = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  1315. ClientToScreen(hwndDlg, &p);
  1316. mlDropItemStruct m;
  1317. ZeroMemory(&m, sizeof(mlDropItemStruct));
  1318. m.type = ML_TYPE_FILENAMESW;
  1319. m.p = p;
  1320. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDRAG);
  1321. }
  1322. break;
  1323. case WM_LBUTTONUP:
  1324. if (we_are_drag_and_dropping && GetCapture() == hwndDlg)
  1325. {
  1326. we_are_drag_and_dropping = 0;
  1327. ReleaseCapture();
  1328. POINT p = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  1329. ClientToScreen(hwndDlg, &p);
  1330. mlDropItemStruct m = {0};
  1331. m.type = ML_TYPE_FILENAMESW;
  1332. m.p = p;
  1333. m.flags = ML_HANDLEDRAG_FLAG_NOCURSOR;
  1334. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDRAG);
  1335. if (m.result > 0)
  1336. {
  1337. m.flags = 0;
  1338. m.result = 0;
  1339. wchar_t* path = getSelectedList();
  1340. if(path)
  1341. {
  1342. m.data = path;
  1343. SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDROP);
  1344. free(path);
  1345. }
  1346. }
  1347. }
  1348. break;
  1349. case WM_PAINT:
  1350. {
  1351. int tab[] = { IDC_DOWNLOADLIST|DCW_SUNKENBORDER};
  1352. dialogSkinner.Draw(hwndDlg, tab, sizeof(tab) / sizeof(tab[0]));
  1353. }
  1354. return 0;
  1355. case WM_WINDOWPOSCHANGED:
  1356. if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE) & ((WINDOWPOS*)lParam)->flags) ||
  1357. (SWP_FRAMECHANGED & ((WINDOWPOS*)lParam)->flags))
  1358. {
  1359. LayoutWindows(hwndDlg, !(SWP_NOREDRAW & ((WINDOWPOS*)lParam)->flags));
  1360. }
  1361. return 0;
  1362. case WM_USER + 0x200:
  1363. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); // yes, we support no - redraw resize
  1364. return TRUE;
  1365. case WM_USER + 0x201:
  1366. offsetX = (short)LOWORD(wParam);
  1367. offsetY = (short)HIWORD(wParam);
  1368. g_rgnUpdate = (HRGN)lParam;
  1369. return TRUE;
  1370. case WM_APP + 104:
  1371. {
  1372. Downloads_UpdateButtonText(hwndDlg, (int)wParam);
  1373. LayoutWindows(hwndDlg, TRUE);
  1374. return 0;
  1375. }
  1376. case WM_COMMAND:
  1377. switch ( LOWORD( wParam ) )
  1378. {
  1379. case IDC_PLAY:
  1380. case IDC_ENQUEUE:
  1381. case IDC_CUSTOM:
  1382. if ( HIWORD( wParam ) == MLBN_DROPDOWN )
  1383. {
  1384. Downloads_Play( hwndDlg, (HWND)lParam, LOWORD( wParam ) );
  1385. }
  1386. else
  1387. {
  1388. bool action;
  1389. if ( LOWORD( wParam ) == IDC_PLAY )
  1390. {
  1391. action = ( HIWORD( wParam ) == 1 ) ? ML_ENQDEF_VAL() == 1 : 0;
  1392. }
  1393. else if ( LOWORD( wParam ) == IDC_ENQUEUE )
  1394. {
  1395. action = ( HIWORD( wParam ) == 1 ) ? ML_ENQDEF_VAL() != 1 : 1;
  1396. }
  1397. else
  1398. break;
  1399. Downloads_Play( action );
  1400. }
  1401. break;
  1402. case IDC_REMOVE:
  1403. Downloads_Remove();
  1404. break;
  1405. case IDC_DELETE:
  1406. Downloads_Delete( hwndDlg );
  1407. break;
  1408. case IDC_CLEANUP:
  1409. Downloads_CleanUp( hwndDlg );
  1410. break;
  1411. case IDC_INFOBOX:
  1412. Downloads_InfoBox( hwndDlg );
  1413. break;
  1414. case IDC_SELECTALL:
  1415. Downloads_SelectAll();
  1416. break;
  1417. case ID_DOWNLOADS_EXPLORERITEMFOLDER:
  1418. exploreItemFolder( hwndDlg );
  1419. break;
  1420. case ID_DOWNLOADS_CANCELDOWNLOAD:
  1421. Downloads_Cancel();
  1422. break;
  1423. default:
  1424. return 0;
  1425. }
  1426. return 1;
  1427. }
  1428. return 0;
  1429. }
  1430. HWND CALLBACK DownloadDialog_Create( HWND hParent )
  1431. {
  1432. return WASABI_API_CREATEDIALOGPARAMW( IDD_DOWNLOADS, hParent, DownloadDialog_DlgProc, 0 );
  1433. }