OpenFileDialog.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "resource.h"
  10. #include "strutil.h"
  11. #include "../nu/AutoChar.h"
  12. #include "api.h"
  13. #include <shlwapi.h>
  14. #include <shobjidl.h>
  15. /*static wchar_t *inc(wchar_t *p, size_t &size, int extra=0)
  16. {
  17. int len = lstrlenW(p) + extra;
  18. size-=len;
  19. p+=len;
  20. return p;
  21. }*/
  22. #if 0
  23. extern std::vector<In_Module*> in_modules;
  24. void getNewFileVistaPlus(int clearlist, HWND hwnd, const wchar_t *path)
  25. {
  26. IFileOpenDialog *pFileOpen;
  27. static int qq;
  28. if (qq) return;
  29. qq = 1;
  30. HRESULT hr = CoCreateInstance(__uuidof(FileOpenDialog), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpen));
  31. if (SUCCEEDED(hr))
  32. {
  33. wchar_t titleStr[128] = {0};
  34. pFileOpen->SetTitle(getStringW((clearlist ? IDS_OFD_OPEN_FILES : IDS_OFD_ADD_FILES_TO_PLAYLIST),titleStr,128));
  35. pFileOpen->SetDefaultExtension(L"");
  36. pFileOpen->SetOptions(FOS_FILEMUSTEXIST | FOS_ALLOWMULTISELECT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST);
  37. if(!clearlist) pFileOpen->SetOkButtonLabel(L"Add");
  38. IShellItem* shellItem;
  39. hr = SHCreateItemFromParsingName((!path ? WASABI_API_APP->path_getWorkingPath() : path), 0, IID_IShellItem, reinterpret_cast<void**>(&shellItem));
  40. if (SUCCEEDED(hr))
  41. {
  42. pFileOpen->SetFolder(shellItem);
  43. }
  44. wchar_t *fsb = in_getfltstrW(TRUE);
  45. int filterNum = 0;
  46. // allocate enough for the number of input plug-ins plus 'all supported' and 'all files'
  47. COMDLG_FILTERSPEC *fileTypes = new COMDLG_FILTERSPEC[in_modules.size() + 2];
  48. while(fsb && *fsb && *fsb+1)
  49. {
  50. int len = lstrlenW(fsb) + 1;
  51. wchar_t *fsb2 = fsb + len;
  52. fileTypes[filterNum].pszName = fsb;
  53. fileTypes[filterNum].pszSpec = fsb2;
  54. CharUpperBuffW(fsb2, lstrlenW(fsb2));
  55. filterNum++;
  56. fsb += len + lstrlenW(fsb2) + 1;
  57. }
  58. pFileOpen->SetFileTypes(filterNum, fileTypes);
  59. if (hwnd == hMainWindow)
  60. UninitDragDrops();
  61. hr = pFileOpen->Show(hwnd);
  62. if (SUCCEEDED(hr))
  63. {
  64. IShellItemArray *pItems;
  65. hr = pFileOpen->GetResults(&pItems);
  66. if (SUCCEEDED(hr))
  67. {
  68. IEnumShellItems *sItems;
  69. hr = pItems->EnumItems(&sItems);
  70. if (SUCCEEDED(hr))
  71. {
  72. DWORD numItems = 0;
  73. pItems->GetCount(&numItems);
  74. int sp;
  75. if (clearlist)
  76. {
  77. sp = 0; PlayList_delete();
  78. }
  79. else sp = PlayList_getlength();
  80. if(numItems <= 1)
  81. {
  82. IShellItem *pItem;
  83. if(sItems->Next(1, &pItem, NULL) == S_OK)
  84. {
  85. LPWSTR folderpath = NULL;
  86. LPWSTR filepath = NULL;
  87. hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &filepath);
  88. if (SUCCEEDED(hr))
  89. {
  90. IShellItem *ppItem;
  91. hr = pItem->GetParent(&ppItem);
  92. if (SUCCEEDED(hr))
  93. {
  94. hr = ppItem->GetDisplayName(SIGDN_FILESYSPATH, &folderpath);
  95. if (SUCCEEDED(hr))
  96. {
  97. WASABI_API_APP->path_setWorkingPath(folderpath);
  98. }
  99. }
  100. if (LoadPlaylist(filepath, 1, 0) == -1) // if not a playlist file
  101. {
  102. PlayList_append(filepath, 0);
  103. }
  104. CoTaskMemFree(filepath);
  105. CoTaskMemFree(folderpath);
  106. }
  107. }
  108. pItem->Release();
  109. }
  110. else
  111. {
  112. size_t size = ((numItems + 1) * MAX_PATH);
  113. wchar_t *temp = (wchar_t *)GlobalAlloc(GPTR, size * sizeof(wchar_t)), *p = temp;
  114. IShellItem *pItem;
  115. while(sItems->Next(1, &pItem, NULL) == S_OK)
  116. {
  117. LPWSTR folderpath = NULL;
  118. LPWSTR filepath = NULL;
  119. hr = pItem->GetDisplayName(SIGDN_NORMALDISPLAY, &filepath);
  120. if (SUCCEEDED(hr))
  121. {
  122. // replicate how lpstrFile is filled under a multiple select
  123. // -> selected folder followed by each filename \0 separated
  124. if(p == temp)
  125. {
  126. IShellItem *ppItem;
  127. hr = pItem->GetParent(&ppItem);
  128. if (SUCCEEDED(hr))
  129. {
  130. hr = ppItem->GetDisplayName(SIGDN_FILESYSPATH, &folderpath);
  131. if (SUCCEEDED(hr))
  132. {
  133. WASABI_API_APP->path_setWorkingPath(folderpath);
  134. if(StringCchCatW(p, size, folderpath) == S_OK)
  135. {
  136. int len = lstrlenW(folderpath) + 1;
  137. p += len;
  138. size -= len;
  139. }
  140. }
  141. }
  142. }
  143. if(StringCchCatW(p, size, filepath) == S_OK)
  144. {
  145. int len = lstrlenW(filepath) + 1;
  146. p += len;
  147. size -= len;
  148. }
  149. CoTaskMemFree(filepath);
  150. CoTaskMemFree(folderpath);
  151. }
  152. pItem->Release();
  153. }
  154. PlayList_addfromdlg(temp);
  155. if (config_rofiob&1) PlayList_sort(2, sp);
  156. GlobalFree(temp);
  157. }
  158. if (clearlist)
  159. BeginPlayback();
  160. sItems->Release();
  161. }
  162. pItems->Release();
  163. }
  164. }
  165. pFileOpen->Release();
  166. GlobalFree(fsb);
  167. if (hwnd == hMainWindow)
  168. InitDragDrops();
  169. for(;;)
  170. {
  171. MSG msg;
  172. if (!PeekMessage(&msg, hMainWindow, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
  173. break;
  174. }
  175. }
  176. qq = 0;
  177. }
  178. #endif
  179. void getNewFile(int clearlist, HWND hwnd, const wchar_t *path) // if clearlist is 1, playlist is cleared
  180. {
  181. // TODO - Egg was having stability issues with this so keeping disabled until resolved
  182. // on Vista and up use the IFileOpenDialog interface as it
  183. // allows us to get around the MAX_PATH file filter issues
  184. /*if(IsVista())
  185. {
  186. getNewFileVistaPlus(clearlist, hwnd, path);
  187. return;
  188. }*/
  189. // otherwise revert to using the older pre-Vista methods
  190. const int len = 256 * 1024 - 128;
  191. wchar_t oldCurPath[MAX_PATH] = {0}, titleStr[128] = {0};
  192. GetCurrentDirectoryW(MAX_PATH, oldCurPath);
  193. wchar_t *temp, *fsb;
  194. OPENFILENAMEW l = {sizeof(OPENFILENAMEW),0};
  195. static int q;
  196. if (q) return;
  197. q = 1;
  198. temp = (wchar_t *)GlobalAlloc(GPTR, len * sizeof(wchar_t));
  199. l.lStructSize = sizeof(l);
  200. l.hwndOwner = hwnd;
  201. l.lpstrFilter = fsb = in_getfltstrW(FALSE);
  202. l.lpstrFile = temp;
  203. l.nMaxFile = len - 1;
  204. l.lpstrTitle = getStringW((clearlist ? IDS_OFD_OPEN_FILES : IDS_OFD_ADD_FILES_TO_PLAYLIST),titleStr,128);
  205. l.lpstrDefExt = L"";
  206. l.lpstrInitialDir = path;
  207. if (!l.lpstrInitialDir) l.lpstrInitialDir = WASABI_API_APP->path_getWorkingPath();
  208. l.Flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ALLOWMULTISELECT
  209. | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
  210. if (hwnd == hMainWindow)
  211. UninitDragDrops();
  212. if (GetOpenFileNameW(&l))
  213. {
  214. wchar_t newCurPath[MAX_PATH] = {0};
  215. GetCurrentDirectoryW(MAX_PATH, newCurPath);
  216. WASABI_API_APP->path_setWorkingPath(newCurPath);
  217. int sp;
  218. if (clearlist)
  219. {
  220. sp = 0; PlayList_delete();
  221. }
  222. else sp = PlayList_getlength();
  223. if (temp[lstrlenW(temp)+1])
  224. {
  225. PlayList_addfromdlg(temp);
  226. if (config_rofiob&1) PlayList_sort(2, sp);
  227. }
  228. else
  229. {
  230. if (LoadPlaylist(temp, 1, 0) == -1) // if not a playlist file
  231. {
  232. PlayList_append(temp, 0);
  233. }
  234. }
  235. if (clearlist)
  236. BeginPlayback();
  237. }
  238. SetCurrentDirectoryW(oldCurPath);
  239. if (hwnd == hMainWindow)
  240. InitDragDrops();
  241. for(;;)
  242. {
  243. MSG msg;
  244. if (!PeekMessage(&msg, hMainWindow, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
  245. break;
  246. }
  247. GlobalFree(fsb);
  248. GlobalFree(temp);
  249. q = 0;
  250. }
  251. static wchar_t loc[FILENAME_SIZE];
  252. int ResizeComboBoxDropDown(HWND hwndDlg, UINT id, const char* str, int width){
  253. SIZE size = {0};
  254. HWND control = GetDlgItem(hwndDlg, id);
  255. HDC hdc = GetDC(control);
  256. // get and select parent dialog's font so that it'll calculate things correctly
  257. HFONT font = (HFONT)SendMessageW(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
  258. GetTextExtentPoint32A(hdc, str, lstrlenA(str)+1, &size);
  259. int ret = width;
  260. if(size.cx > width)
  261. {
  262. SendDlgItemMessage(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
  263. ret = size.cx;
  264. }
  265. SelectObject(hdc, oldfont);
  266. ReleaseDC(control, hdc);
  267. return ret;
  268. }
  269. int ResizeComboBoxDropDownW(HWND hwndDlg, UINT id, const wchar_t *str, int width){
  270. SIZE size = {0};
  271. HWND control = GetDlgItem(hwndDlg, id);
  272. HDC hdc = GetDC(control);
  273. // get and select parent dialog's font so that it'll calculate things correctly
  274. HFONT font = (HFONT)SendMessageW(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
  275. GetTextExtentPoint32W(hdc, str, (int) wcslen(str)+1, &size);
  276. int ret = width;
  277. if(size.cx > width)
  278. {
  279. SendDlgItemMessage(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
  280. ret = size.cx;
  281. }
  282. SelectObject(hdc, oldfont);
  283. ReleaseDC(control, hdc);
  284. return ret;
  285. }
  286. static LRESULT WINAPI locProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  287. {
  288. switch (uMsg)
  289. {
  290. case WM_INITDIALOG:
  291. if(lParam) SetWindowTextW(hwndDlg, getStringW(IDS_ADD_URL, NULL, 0));
  292. SendDlgItemMessageW(hwndDlg, IDC_URL_NEW, CB_LIMITTEXT, sizeof(loc)/sizeof(*loc) - 1, 0);
  293. {
  294. int width = 0, x = 0;
  295. HWND h = GetDlgItem(hwndDlg, IDC_URL_NEW);
  296. SendMessageW(h, CB_SETHORIZONTALEXTENT, 400, 0);
  297. while(1)
  298. {
  299. char s[123] = {0};
  300. wchar_t name[FILENAME_SIZE] = {0};
  301. StringCchPrintfA(s, 123, "RecentURL%d", x + 1);
  302. _r_sW(s, name, 123);
  303. if (!name[0]) break;
  304. SendMessageW(h, CB_ADDSTRING, 0, (LPARAM)name);
  305. width = ResizeComboBoxDropDownW(hwndDlg, IDC_URL_NEW, name, width);
  306. x++;
  307. }
  308. // show add / open loc window and restore last position as applicable
  309. POINT pt = {loc_rect.left, loc_rect.top};
  310. if (!windowOffScreen(hwndDlg, pt))
  311. SetWindowPos(hwndDlg, HWND_TOP, loc_rect.left, loc_rect.top, 0, 0, SWP_NOSIZE | SWP_NOSENDCHANGING);
  312. }
  313. SetDlgItemTextW(hwndDlg, IDC_URL_NEW, loc);
  314. return TRUE;
  315. case WM_COMMAND:
  316. switch (LOWORD(wParam))
  317. {
  318. case IDOK:
  319. GetDlgItemTextW(hwndDlg, IDC_URL_NEW, loc, sizeof(loc)/sizeof(*loc) - 1);
  320. {
  321. wchar_t *p = loc;
  322. while (IsCharSpaceW(*p)) p = CharNextW(p);
  323. if (!*p) EndDialog(hwndDlg, 1);
  324. else recent_add(loc);
  325. }
  326. case IDCANCEL:
  327. GetWindowRect(hwndDlg, &loc_rect);
  328. EndDialog(hwndDlg, (LOWORD(wParam) == IDCANCEL));
  329. return FALSE;
  330. case IDRESET:
  331. if (LPMessageBox(hwndDlg, IDS_RESET_URLS, IDS_RESET_URLS_TITLE, MB_ICONQUESTION | MB_YESNO) == IDYES)
  332. {
  333. int x = 1;
  334. while(1)
  335. {
  336. char s[123] = {0};
  337. wchar_t name[FILENAME_SIZE] = {0};
  338. StringCchPrintfA(s, 123, "RecentURL%d", x);
  339. _r_sW(s, name, 123);
  340. _w_sW(s, 0);
  341. if (!name[0]) break;
  342. x++;
  343. }
  344. // clear out but keep what's been currently entered so as not to annoy people...
  345. GetDlgItemTextW(hwndDlg, IDC_URL_NEW, loc, ARRAYSIZE(loc));
  346. SendDlgItemMessage(hwndDlg, IDC_URL_NEW, CB_RESETCONTENT, 0, 0);
  347. SetDlgItemTextW(hwndDlg, IDC_URL_NEW, loc);
  348. }
  349. return FALSE;
  350. }
  351. return FALSE;
  352. case WM_CLOSE:
  353. EndDialog(hwndDlg, 2);
  354. return FALSE;
  355. }
  356. return 0;
  357. }
  358. LRESULT getNewLocation(int clearlist, HWND hwnd) // if clearlist is 1, playlist is cleared
  359. {
  360. static int q;
  361. if (q) return 0;
  362. q = 1;
  363. if (!LPDialogBoxParamW(IDD_OPENLOC, hwnd, (DLGPROC)locProc, !clearlist))
  364. {
  365. wchar_t *beg = loc;
  366. wchar_t *l = loc;
  367. wchar_t buf[FILENAME_SIZE] = {0};
  368. wchar_t *pEnd;
  369. while (IsCharSpaceW(*l)) l = CharNextW(l);
  370. if (!wcsstr(l, L":/") && !wcsstr(l, L":\\"))
  371. {
  372. StringCchPrintfW(buf, FILENAME_SIZE, L"http://%s", l);
  373. l = buf;
  374. beg = buf;
  375. }
  376. if (clearlist < 0)
  377. {
  378. int psize = WideCharToMultiByte(CP_ACP, 0, l, -1, 0, 0, NULL, NULL);
  379. char* p = (char*)GlobalAlloc(GPTR, psize);
  380. WideCharToMultiByte(CP_ACP, 0, l, -1, p, psize, NULL, NULL);
  381. //trim any trailing spaces
  382. //l = p + lstrlen(p) - 1;
  383. if (IsCharSpaceW(*l))
  384. {
  385. while (IsCharSpaceW(*l))
  386. l = CharPrevW(beg, l);
  387. *CharNextW(l) = 0;
  388. }
  389. q = 0;
  390. return (LRESULT)p;
  391. }
  392. pEnd = GetLastCharacterW(l);
  393. if (IsCharSpaceW(*pEnd))
  394. {
  395. while (IsCharSpaceW(*pEnd))
  396. pEnd = CharPrevW(l, pEnd);
  397. *CharNextW(pEnd) = 0;
  398. }
  399. /* benski> CUT because 'idir' doesn't seem to be used
  400. int idir=0;
  401. HANDLE h;
  402. WIN32_FIND_DATA d;
  403. h = FindFirstFile(l,&d);
  404. if (h!=INVALID_HANDLE_VALUE)
  405. {
  406. FindClose(h);
  407. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  408. {
  409. idir=1;
  410. }
  411. }
  412. */
  413. if (clearlist)
  414. PlayList_delete();
  415. PlayList_appendthing(l, 0, 0);
  416. if (clearlist)
  417. BeginPlayback();
  418. }
  419. q = 0;
  420. return 0;
  421. }