Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

942 lines
30 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* WFSEARCH.C - */
  4. /* */
  5. /* File System Search Routines */
  6. /* */
  7. /****************************************************************************/
  8. #include "winfile.h"
  9. #include "lfn.h"
  10. INT maxExt;
  11. INT iDirsRead;
  12. DWORD LastUpdateTime;
  13. WORD APIENTRY StackAvail(VOID);
  14. INT FillSearchLB(HWND hwndLB, LPSTR szSearchFileSpec, BOOL bSubDirOnly);
  15. INT SearchList(HWND hwndLB, LPSTR szPath, LPSTR szFileSpec, BOOL bRecurse, LPHANDLE lphMem, INT iFileCount);
  16. LPSTR SearchGetSelection(HWND hwndLB, BOOL bMostRecent, BOOL *pfDir);
  17. /*--------------------------------------------------------------------------*/
  18. /* */
  19. /* SearchList() - */
  20. /* */
  21. /* This is a recursive routine. It returns the number of files found. */
  22. // szPath OEM
  23. // szFileSpec OEM
  24. /* */
  25. /*--------------------------------------------------------------------------*/
  26. #define DTA_GRANULARITY 20
  27. INT
  28. SearchList(
  29. HWND hwndLB,
  30. LPSTR szPath,
  31. LPSTR szFileSpec,
  32. BOOL bRecurse,
  33. LPHANDLE lphMem,
  34. INT iFileCount
  35. )
  36. {
  37. INT iRetVal;
  38. INT cxExt;
  39. BOOL bFound;
  40. LPSTR pszNewPath;
  41. LPSTR pszNextFile;
  42. LFNDTA lfndta;
  43. LPDTASEARCH lpdtasch;
  44. HDC hdc;
  45. HANDLE hOld;
  46. HANDLE hMem, hMemT;
  47. DWORD TimeNow;
  48. STKCHK();
  49. hMem = *lphMem;
  50. /* Just return 0 files so parent dirs will still be searched
  51. */
  52. if (StackAvail() < 1024)
  53. return(iFileCount);
  54. TimeNow = GetTickCount();
  55. if (TimeNow > LastUpdateTime+1000) {
  56. LastUpdateTime = TimeNow;
  57. if (LoadString(hAppInstance, IDS_DIRSREAD, szMessage, sizeof(szMessage)))
  58. wsprintf(szStatusTree, szMessage, iDirsRead);
  59. InvalidateRect(hwndFrame, NULL, FALSE);
  60. UpdateWindow(hwndFrame);
  61. }
  62. iDirsRead++;
  63. if (!hMem) {
  64. hMem = LocalAlloc(LPTR, (DWORD)DTA_GRANULARITY * sizeof(DTASEARCH));
  65. if (!hMem)
  66. return -1;
  67. *lphMem = hMem;
  68. }
  69. lpdtasch = (LPDTASEARCH)LocalLock(hMem);
  70. // allocate the buffer for this level
  71. pszNewPath = (LPSTR)LocalAlloc(LPTR, lstrlen(szPath) + MAXFILENAMELEN + 2);
  72. if (!pszNewPath)
  73. return -1;
  74. lstrcpy(pszNewPath, szPath);
  75. AddBackslash(pszNewPath);
  76. pszNextFile = pszNewPath + lstrlen(pszNewPath);
  77. lstrcpy(pszNextFile, szFileSpec);
  78. bFound = WFFindFirst(&lfndta, pszNewPath, ATTR_ALL);
  79. hdc = GetDC(hwndLB);
  80. hOld = SelectObject(hdc, hFont);
  81. while (bFound) {
  82. // alow escape to exit
  83. if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
  84. bRecurse = FALSE;
  85. iFileCount = -1;
  86. break;
  87. }
  88. // Make sure this is not a "." or ".." directory
  89. if (lfndta.fd.cFileName[0] != '.') {
  90. BOOL bLFN;
  91. lstrcpy(pszNextFile, lfndta.fd.cFileName);
  92. OemToAnsi(pszNewPath, szMessage);
  93. bLFN = IsLFN(lfndta.fd.cFileName);
  94. iRetVal = (INT)SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM)szMessage);
  95. MGetTextExtent(hdc, szMessage, lstrlen(szMessage), &cxExt, NULL);
  96. maxExt = max(maxExt, cxExt);
  97. if (iRetVal >= 0) {
  98. if (iFileCount && ((iFileCount % DTA_GRANULARITY) == 0)) {
  99. LocalUnlock(hMem);
  100. if (!(hMemT = LocalReAlloc(hMem, (DWORD)((iFileCount + DTA_GRANULARITY) * sizeof(DTASEARCH)), LMEM_MOVEABLE))) {
  101. LocalLock(hMem);
  102. bRecurse = FALSE; // simulate an abort
  103. iFileCount = -1;
  104. break;
  105. } else {
  106. hMem = hMemT;
  107. *lphMem = hMemT;
  108. }
  109. lpdtasch = (LPDTASEARCH)LocalLock(hMem);
  110. }
  111. lpdtasch[iFileCount] = *((LPDTASEARCH)(&lfndta.fd));
  112. if (bLFN)
  113. lpdtasch[iFileCount].sch_dwAttrs |= ATTR_LFN;
  114. SendMessage(hwndLB, LB_SETITEMDATA, iRetVal, (LONG)iFileCount);
  115. iFileCount++;
  116. }
  117. }
  118. /* Search for more files in the current directory */
  119. bFound = WFFindNext(&lfndta);
  120. }
  121. WFFindClose(&lfndta);
  122. if (hOld)
  123. SelectObject(hdc, hOld);
  124. ReleaseDC(hwndLB, hdc);
  125. LocalUnlock(hMem);
  126. SetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH, (LONG_PTR)hMem);
  127. if (!bRecurse)
  128. goto SearchEnd;
  129. /* Now see if there are any subdirectories here */
  130. lstrcpy(pszNextFile, szStarDotStar);
  131. bFound = WFFindFirst(&lfndta, pszNewPath, ATTR_DIR | ATTR_HS);
  132. while (bFound) {
  133. // alow escape to exit
  134. if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
  135. bRecurse = FALSE;
  136. iFileCount = -1;
  137. break;
  138. }
  139. /* Make sure this is not a "." or ".." directory. */
  140. if ((lfndta.fd.cFileName[0] != '.') && (lfndta.fd.dwFileAttributes & ATTR_DIR)) {
  141. /* Yes, search and add files in this directory */
  142. lstrcpy(pszNextFile, lfndta.fd.cFileName);
  143. /* Add all files in this subdirectory. */
  144. if ((iRetVal = SearchList(hwndLB, pszNewPath, szFileSpec, bRecurse, lphMem, iFileCount)) < 0) {
  145. iFileCount = iRetVal;
  146. break;
  147. }
  148. iFileCount = iRetVal;
  149. }
  150. bFound = WFFindNext(&lfndta);
  151. }
  152. WFFindClose(&lfndta);
  153. SearchEnd:
  154. LocalFree((HANDLE)pszNewPath);
  155. return iFileCount;
  156. }
  157. VOID
  158. FixUpFileSpec(
  159. LPSTR szFileSpec
  160. )
  161. {
  162. CHAR szTemp[MAXPATHLEN+1];
  163. register LPSTR p;
  164. if (*szFileSpec == '.') {
  165. lstrcpy(szTemp, "*");
  166. lstrcat(szTemp, szFileSpec);
  167. lstrcpy(szFileSpec, szTemp);
  168. }
  169. /* HACK: If there isn't a dot and the last char is a *, append ".*" */
  170. p = szFileSpec;
  171. while ((*p) && (*p != '.'))
  172. p = AnsiNext(p);
  173. if ((!*p) && (p != szFileSpec)) {
  174. p = AnsiPrev(szFileSpec, p);
  175. if (*p == '*')
  176. lstrcat(p, ".*");
  177. }
  178. }
  179. /*--------------------------------------------------------------------------*/
  180. /* */
  181. /* FillSearchLB() - */
  182. /* */
  183. /*--------------------------------------------------------------------------*/
  184. /* This parses the given string for Drive, PathName, FileSpecs and
  185. * calls SearchList() with proper parameters;
  186. *
  187. * hwndLB : List box where files are to be displayed;
  188. * szSearchFileSpec : ANSI path to search
  189. * bSubDirOnly : TRUE, if only subdirectories are to be searched;
  190. */
  191. INT
  192. FillSearchLB(
  193. HWND hwndLB,
  194. LPSTR szSearchFileSpec,
  195. BOOL bRecurse
  196. )
  197. {
  198. INT iRet;
  199. HCURSOR hCursor;
  200. CHAR szFileSpec[MAXPATHLEN+1];
  201. CHAR szPathName[MAXPATHLEN+1];
  202. HANDLE hMemIn = NULL;
  203. FixAnsiPathForDos(szSearchFileSpec);
  204. /* Get the file specification part of the string. */
  205. lstrcpy(szFileSpec, szSearchFileSpec);
  206. lstrcpy(szPathName, szSearchFileSpec);
  207. StripPath(szFileSpec);
  208. StripFilespec(szPathName);
  209. FixUpFileSpec(szFileSpec);
  210. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  211. ShowCursor(TRUE);
  212. maxExt = 0;
  213. iDirsRead = 1;
  214. LastUpdateTime = 0;
  215. iRet = SearchList(hwndLB, szPathName, szFileSpec, bRecurse, &hMemIn, 0);
  216. ShowCursor(FALSE);
  217. SetCursor(hCursor);
  218. SendMessage(hwndLB, LB_SETSEL, TRUE, 0L);
  219. return(iRet);
  220. }
  221. /*--------------------------------------------------------------------------*/
  222. /* */
  223. /* SearchGetSelection() - */
  224. /* */
  225. /*--------------------------------------------------------------------------*/
  226. /* Returns a string containing the names of the selected
  227. * files seperated by spaces. If bMostRecent is TRUE, it only returns the
  228. * most recently selected file.
  229. *
  230. * The string is returned and a *pfDir is set indicating if it points
  231. * to a directory.
  232. *
  233. * NOTE: The caller must free the returned pointer!
  234. */
  235. LPSTR
  236. SearchGetSelection(
  237. HWND hwndLB,
  238. BOOL bMostRecent,
  239. BOOL *pfDir
  240. )
  241. {
  242. register LPSTR p;
  243. LPSTR pT;
  244. register WORD i;
  245. WORD iMac;
  246. WORD cch = 1;
  247. BOOL bDir;
  248. HANDLE hMem;
  249. LPDTASEARCH lpdtasch;
  250. CHAR szTemp[MAXPATHLEN];
  251. BOOL bLFNTest;
  252. if (bLFNTest = (bMostRecent == 2)) {
  253. bMostRecent = FALSE;
  254. } else {
  255. p = (LPSTR)LocalAlloc(LPTR, 1);
  256. if (!p)
  257. return NULL;
  258. }
  259. if (bMostRecent == 3)
  260. bMostRecent = 0;
  261. bDir = TRUE;
  262. iMac = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
  263. hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH);
  264. lpdtasch = (LPDTASEARCH)LocalLock(hMem);
  265. for (i=0; i < iMac; i++) {
  266. if (!(BOOL)SendMessage(hwndLB, LB_GETSEL, i, 0L))
  267. continue;
  268. cch += (WORD)SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)szTemp);
  269. cch++;
  270. if (bLFNTest) {
  271. if (IsLFN(szTemp)) {
  272. if (pfDir)
  273. *pfDir = TRUE;
  274. return NULL;
  275. }
  276. } else {
  277. pT = (LPSTR)LocalReAlloc((HANDLE)p, cch, LMEM_MOVEABLE | LMEM_ZEROINIT);
  278. if (!pT)
  279. goto SGSExit;
  280. p = pT;
  281. lstrcat(p, szTemp);
  282. bDir = lpdtasch[(INT)SendMessage(hwndLB, LB_GETITEMDATA, i, 0L)].sch_dwAttrs & ATTR_DIR;
  283. if (bMostRecent)
  284. break;
  285. lstrcat(p, szBlank);
  286. }
  287. }
  288. SGSExit:
  289. LocalUnlock(hMem);
  290. if (bLFNTest) {
  291. if (pfDir)
  292. *pfDir = FALSE;
  293. return NULL;
  294. }
  295. if (pfDir)
  296. *pfDir = bDir;
  297. return(p);
  298. }
  299. VOID
  300. CreateLine(
  301. WORD wLineFormat,
  302. LPSTR szFile,
  303. LPDTASEARCH lpdtasch,
  304. LPSTR szBuffer
  305. )
  306. {
  307. LPSTR pch;
  308. BYTE chAttribute;
  309. pch = szBuffer;
  310. chAttribute = (BYTE)lpdtasch->sch_dwAttrs;
  311. /* Copy the file name. */
  312. lstrcpy(pch, szFile);
  313. pch += lstrlen(pch);
  314. *pch = TEXT('\0');
  315. /* Should we show the size? */
  316. if (wLineFormat & VIEW_SIZE) {
  317. *pch++ = TABCHAR;
  318. if (!(chAttribute & ATTR_DIR))
  319. pch += PutSize(lpdtasch->sch_nFileSizeLow, pch);
  320. }
  321. /* Should we show the date? */
  322. if (wLineFormat & VIEW_DATE) {
  323. *pch++ = TABCHAR;
  324. pch += PutDate(&lpdtasch->sch_ftLastWriteTime, pch);
  325. }
  326. /* Should we show the time? */
  327. if (wLineFormat & VIEW_TIME) {
  328. *pch++ = TABCHAR;
  329. pch += PutTime(&lpdtasch->sch_ftLastWriteTime, pch);
  330. }
  331. /* Should we show the attributes? */
  332. if (wLineFormat & VIEW_FLAGS) {
  333. *pch++ = TABCHAR;
  334. pch += PutAttributes((WORD)chAttribute, pch);
  335. }
  336. }
  337. // the window text looks like "Search Window: C:\FOO\BAR\*.*"
  338. VOID
  339. GetSearchPath(
  340. HWND hWnd,
  341. LPSTR pszPath
  342. )
  343. {
  344. LPSTR p;
  345. CHAR szTemp[MAXPATHLEN+32];
  346. // the search window doesn't have a current directory
  347. GetWindowText(hWnd, szTemp, sizeof(szTemp));
  348. // the window text looks like "Search Window: C:\FOO\BAR\*.*"
  349. p = szTemp;
  350. while (*p && *p != ':') // find the :
  351. p = AnsiNext(p);
  352. p += 2; // skip the ": "
  353. lstrcpy(pszPath, p);
  354. }
  355. /*--------------------------------------------------------------------------*/
  356. /* */
  357. /* UpdateSearchStatus() - */
  358. /* */
  359. /*--------------------------------------------------------------------------*/
  360. VOID
  361. UpdateSearchStatus(
  362. HWND hwndLB
  363. )
  364. {
  365. INT nCount;
  366. nCount = (INT)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
  367. if (LoadString(hAppInstance, IDS_SEARCHMSG, szMessage, sizeof(szMessage)))
  368. wsprintf(szStatusTree, szMessage, nCount);
  369. szStatusDir[0] = '\0';
  370. InvalidateRect(hwndFrame, NULL, FALSE);
  371. }
  372. /*--------------------------------------------------------------------------*/
  373. /* */
  374. /* SearchWndProc() - */
  375. /* */
  376. /*--------------------------------------------------------------------------*/
  377. INT_PTR
  378. APIENTRY
  379. SearchWndProc(
  380. register HWND hWnd,
  381. UINT wMsg,
  382. WPARAM wParam,
  383. LPARAM lParam
  384. )
  385. {
  386. INT iRet;
  387. INT iSel;
  388. HWND hwndLB;
  389. CHAR szTemp[MAXPATHLEN + 32];
  390. CHAR szPath[MAXPATHLEN];
  391. STKCHK();
  392. hwndLB = GetDlgItem(hWnd, IDCW_LISTBOX);
  393. switch (wMsg) {
  394. case FS_GETDRIVE:
  395. MSG("SearchWndProc", "FS_GETDRIVE");
  396. // Returns the letter of the corresponding directory
  397. SendMessage(hWnd, FS_GETDIRECTORY, sizeof(szPath), (LPARAM)szPath);
  398. return szPath[0]; // first character
  399. case FS_GETDIRECTORY:
  400. MSG("SearchWndProc", "FS_GETDIRECTORY");
  401. GetSearchPath(hWnd, szPath);
  402. StripFilespec(szPath); // remove the filespec
  403. AddBackslash(szPath); // to be the same as DirWndProc
  404. lstrcpy((LPSTR)lParam, szPath);
  405. break;
  406. case FS_GETFILESPEC:
  407. MSG("SearchWndProc", "FS_GETFILESPEC");
  408. // the search window doesn't have a current directory
  409. GetSearchPath(hWnd, szPath);
  410. StripPath(szPath); // remove the path (leave the filespec)
  411. lstrcpy((LPSTR)lParam, szPath);
  412. break;
  413. case FS_SETSELECTION:
  414. MSG("SearchWndProc", "FS_SETSELECTION");
  415. // wParam is the select(TRUE)/unselect(FALSE) param
  416. // lParam is the filespec to match against
  417. SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);
  418. DSSetSelection(hwndLB, wParam ? TRUE : FALSE, (LPSTR)lParam, TRUE);
  419. SendMessage(hwndLB, WM_SETREDRAW, TRUE, 0L);
  420. InvalidateRect(hwndLB, NULL, TRUE);
  421. break;
  422. case FS_GETSELECTION:
  423. MSG("SearchWndProc", "FS_GETSELECTION");
  424. return (INT_PTR)SearchGetSelection(hwndLB, wParam ? TRUE : FALSE, (BOOL *)lParam);
  425. break;
  426. case WM_MDIACTIVATE:
  427. if (wParam) {
  428. UpdateSearchStatus(hwndLB);
  429. // if we are dirty, ask if we should update
  430. if (GetWindowLong(hWnd, GWL_FSCFLAG))
  431. PostMessage(hWnd, FS_CHANGEDISPLAY, CD_SEARCHUPDATE, 0L);
  432. }
  433. break;
  434. case WM_FILESYSCHANGE:
  435. SetWindowLong(hWnd, GWL_FSCFLAG, TRUE); // I need updating
  436. // if the search window is not active or FSCs are disabled
  437. // don't prompt now, wait till we get the end FSC or are
  438. // activated (above in WM_ACTIVATE)
  439. if (cDisableFSC ||
  440. (hWnd != (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L)) &&
  441. (GetActiveWindow() != hwndFrame))
  442. break;
  443. PostMessage(hWnd, FS_CHANGEDISPLAY, CD_SEARCHUPDATE, 0L);
  444. break;
  445. case FS_CHANGEDISPLAY:
  446. MSG("SearchWndProc", "FS_CHANGEDISPLAY");
  447. SetWindowLong(hWnd, GWL_FSCFLAG, FALSE); // I am clean
  448. if (wParam == CD_SEARCHUPDATE) {
  449. LoadString(hAppInstance, IDS_SEARCHTITLE, szTitle, sizeof(szTitle));
  450. LoadString(hAppInstance, IDS_SEARCHREFRESH, szMessage, sizeof(szMessage));
  451. if (MessageBox(hWnd, szMessage, szTitle, MB_YESNO | MB_ICONQUESTION) != IDYES)
  452. break;
  453. }
  454. // is this a refresh?
  455. if (!lParam) {
  456. GetSearchPath(hWnd, szPath);
  457. } else {
  458. lstrcpy(szPath, (LPSTR)lParam); // explicit re-search
  459. }
  460. LoadString(hAppInstance, IDS_SEARCHTITLE, szMessage, 32);
  461. lstrcat(szMessage, szPath);
  462. SetWindowText(hWnd, szMessage);
  463. SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);
  464. SendMessage(hwndLB, LB_RESETCONTENT, 0, 0L);
  465. iRet = FillSearchLB(hwndLB, szPath, bSearchSubs);
  466. FixTabsAndThings(hwndLB,(WORD *)GetWindowLongPtr(hWnd, GWLP_TABARRAYSEARCH), maxExt + dxText,wNewView);
  467. SendMessage(hwndLB, WM_SETREDRAW, TRUE, 0L);
  468. InvalidateRect(hwndLB, NULL, TRUE);
  469. if (iRet == 0) {
  470. LoadString(hAppInstance, IDS_SEARCHTITLE, szTitle, sizeof(szTitle));
  471. LoadString(hAppInstance, IDS_SEARCHNOMATCHES, szMessage, sizeof(szMessage));
  472. MessageBox(hwndFrame, szMessage, szTitle, MB_OK | MB_ICONINFORMATION);
  473. ShowWindow(hWnd, SW_HIDE);
  474. PostMessage(hWnd, WM_CLOSE, 0, 0L);
  475. return FALSE;
  476. } else {
  477. UpdateSearchStatus(hwndLB);
  478. }
  479. if (GetFocus() != hwndLB)
  480. return(iRet);
  481. /*** FALL THRU ***/
  482. case WM_SETFOCUS:
  483. MSG("SearchWndProc", "WM_SETFOCUS");
  484. SetFocus(hwndLB);
  485. return (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
  486. case WM_CLOSE:
  487. MSG("SearchWndProc", "WM_CLOSE");
  488. hwndSearch = NULL;
  489. goto DefChildProc;
  490. case WM_COMMAND:
  491. /* Was this a double-click? */
  492. if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_DBLCLK)
  493. SendMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_OPEN, 0, 0));
  494. else if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) {
  495. INT i;
  496. for (i = 0; i < iNumExtensions; i++) {
  497. (extensions[i].ExtProc)(hwndFrame, FMEVENT_SELCHANGE, 0L);
  498. }
  499. }
  500. break;
  501. case WM_DESTROY:
  502. MSG("SearchWndProc", "WM_DESTROY");
  503. {
  504. HANDLE hMem;
  505. if (hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTASEARCH))
  506. LocalFree(hMem);
  507. if (hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_TABARRAYSEARCH))
  508. LocalFree(hMem);
  509. }
  510. break;
  511. case WM_CREATE:
  512. TRACE(BF_WM_CREATE, "SearchWndProc - WM_CREATE");
  513. {
  514. // globals used:
  515. // szSearch path to start search at
  516. // bSearchSubs tells us to do a recursive search
  517. RECT rc;
  518. WORD *pwTabs;
  519. GetClientRect(hWnd, &rc);
  520. hwndLB = CreateWindowEx(0, szListbox, NULL,
  521. WS_CHILD | WS_BORDER | LBS_SORT | LBS_NOTIFY |
  522. LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL |
  523. LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
  524. LBS_HASSTRINGS | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
  525. -1, -1, rc.right+2, rc.bottom+2,
  526. hWnd, (HMENU)IDCW_LISTBOX,
  527. hAppInstance, NULL);
  528. if (!hwndLB)
  529. return -1L;
  530. if ((pwTabs = (WORD *)LocalAlloc(LPTR,sizeof(WORD) * 4)) == NULL)
  531. return -1L;
  532. hwndSearch = hWnd;
  533. SetWindowLong(hWnd, GWL_TYPE, TYPE_SEARCH);
  534. SetWindowLong(hWnd, GWL_VIEW, wNewView);
  535. SetWindowLong(hWnd, GWL_SORT, IDD_NAME);
  536. SetWindowLong(hWnd, GWL_ATTRIBS,ATTR_DEFAULT);
  537. SetWindowLong(hWnd, GWL_FSCFLAG, FALSE);
  538. SetWindowLongPtr(hWnd, GWLP_HDTASEARCH, 0);
  539. SetWindowLongPtr(hWnd, GWLP_TABARRAYSEARCH, (LONG_PTR)pwTabs);
  540. SetWindowLongPtr(hWnd, GWLP_LASTFOCUSSEARCH, (LONG_PTR)hwndLB);
  541. // Fill the listbox
  542. if (!FillSearchLB(hwndLB, szSearch, bSearchSubs)) {
  543. LoadString(hAppInstance, IDS_SEARCHTITLE, szTitle, sizeof(szTitle));
  544. LoadString(hAppInstance, IDS_SEARCHNOMATCHES, szMessage, sizeof(szMessage));
  545. MessageBox(hwndFrame, szMessage, szTitle, MB_OK | MB_ICONINFORMATION);
  546. hwndSearch = NULL;
  547. return -1L;
  548. } else {
  549. FixTabsAndThings(hwndLB,pwTabs, maxExt + dxText,wNewView);
  550. SendMessage(hwndLB, WM_SETFONT, (WPARAM)hFont, 0L);
  551. ShowWindow(hwndSearch, SW_SHOWNORMAL);
  552. }
  553. break;
  554. }
  555. case WM_DRAGLOOP:
  556. MSG("SearchWndProc", "WM_DRAGLOOP");
  557. /* WM_DRAGLOOP is sent to the source window as the object is moved.
  558. *
  559. * wParam: TRUE if the object is currently over a droppable sink
  560. * lParam: LPDROPSTRUCT
  561. */
  562. /* DRAGLOOP is used to turn the source bitmaps on/off as we drag. */
  563. DSDragLoop(hwndLB, wParam, (LPDROPSTRUCT)lParam, TRUE);
  564. break;
  565. case WM_DRAGSELECT:
  566. MSG("SearchWndProc", "WM_DRAGSELECT");
  567. /* WM_DRAGSELECT is sent to a sink whenever an new object is dragged
  568. * inside of it.
  569. *
  570. * wParam: TRUE if the sink is being entered, FALSE if it's being
  571. * exited.
  572. * lParam: LPDROPSTRUCT
  573. */
  574. /* DRAGSELECT is used to turn our selection rectangle on or off. */
  575. #define lpds ((LPDROPSTRUCT)lParam)
  576. iSelHilite = LOWORD(lpds->dwControlData);
  577. DSRectItem(hwndLB, iSelHilite, (BOOL)wParam, TRUE);
  578. break;
  579. case WM_DRAGMOVE:
  580. MSG("SearchWndProc", "WM_DRAGMOVE");
  581. /* WM_DRAGMOVE is sent to a sink as the object is being dragged
  582. * within it.
  583. *
  584. * wParam: Unused
  585. * lParam: LPDROPSTRUCT
  586. */
  587. /* DRAGMOVE is used to move our selection rectangle among sub-items. */
  588. #define lpds ((LPDROPSTRUCT)lParam)
  589. /* Get the subitem we are over. */
  590. iSel = LOWORD(lpds->dwControlData);
  591. /* Is it a new one? */
  592. if (iSel == iSelHilite)
  593. break;
  594. /* Yup, un-select the old item. */
  595. DSRectItem(hwndLB, iSelHilite, FALSE, TRUE);
  596. /* Select the new one. */
  597. iSelHilite = iSel;
  598. DSRectItem(hwndLB, iSel, TRUE, TRUE);
  599. break;
  600. case WM_DRAWITEM:
  601. MSG("SearchWndProc", "WM_DRAWITEM");
  602. {
  603. LPDRAWITEMSTRUCT lpLBItem;
  604. HANDLE hMem;
  605. LPDTASEARCH lpdtasch;
  606. lpLBItem = (LPDRAWITEMSTRUCT)lParam;
  607. iSel = lpLBItem->itemID;
  608. if (iSel < 0)
  609. break;
  610. SendMessage(hwndLB, LB_GETTEXT, iSel, (LPARAM)szPath);
  611. hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTASEARCH);
  612. lpdtasch = (LPDTASEARCH)LocalLock(hMem);
  613. iSel = (INT)SendMessage(hwndLB, LB_GETITEMDATA, iSel, 0L);
  614. CreateLine((WORD)GetWindowLong(hWnd, GWL_VIEW), szPath, &(lpdtasch[iSel]), szTemp);
  615. DrawItem(lpLBItem, szTemp, lpdtasch[iSel].sch_dwAttrs, TRUE,
  616. (WORD *)GetWindowLongPtr(hWnd,GWLP_TABARRAYSEARCH));
  617. LocalUnlock(hMem);
  618. break;
  619. }
  620. case WM_DROPOBJECT:
  621. MSG("SearchWndProc", "WM_DROPOBJECT");
  622. {
  623. LPSTR pFrom;
  624. WORD ret;
  625. WORD iSelSink;
  626. HANDLE hMem;
  627. LPDTASEARCH lpdtasch;
  628. DWORD attrib;
  629. /* WM_DROPOBJECT is sent to a sink when the user releases an
  630. * acceptable object over it
  631. *
  632. * wParam: TRUE if over the non-client area, FALSE if over the
  633. * client area.
  634. * lParam: LPDROPSTRUCT
  635. */
  636. #define lpds ((LPDROPSTRUCT)lParam)
  637. iSelSink = LOWORD(lpds->dwControlData);
  638. /* Are we dropping onto ourselves? (i.e. a selected item in the
  639. * source listbox OR an unused area of the source listbox) If
  640. * so, don't do anything.
  641. */
  642. if (hWnd == lpds->hwndSource) {
  643. if ((iSelSink == 0xFFFF) || (SendMessage(hwndLB, LB_GETSEL, iSelSink, 0L)))
  644. return TRUE;
  645. }
  646. /* Are we dropping on a unused portion of the listbox? */
  647. if (iSelSink == 0xFFFF)
  648. return TRUE;
  649. /* Get the sink's filename. */
  650. SendMessage(hwndLB, LB_GETTEXT, iSelSink, (LPARAM)szPath);
  651. hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTASEARCH);
  652. lpdtasch = (LPDTASEARCH)LocalLock(hMem);
  653. attrib = lpdtasch[(INT)SendMessage(hwndLB, LB_GETITEMDATA, iSelSink, 0L)].sch_dwAttrs;
  654. LocalUnlock(hMem);
  655. /* Are we dropping on a subdirectory? */
  656. if (attrib & ATTR_DIR)
  657. goto DirMoveCopy;
  658. /* Are we not dropping on a Program file? */
  659. if (!IsProgramFile(szPath))
  660. return TRUE;
  661. if (lpds->wFmt == DOF_DIRECTORY) {
  662. goto DODone;
  663. }
  664. /* We're dropping a file onto a program.
  665. * Exec the program using the source file as the parameter.
  666. */
  667. /* Should we confirm it first? */
  668. if (bConfirmMouse) {
  669. LoadString(hAppInstance, IDS_MOUSECONFIRM, szTitle, MAXTITLELEN);
  670. LoadString(hAppInstance, IDS_EXECMOUSECONFIRM, szTemp, sizeof(szTemp));
  671. wsprintf(szMessage, szTemp, (LPSTR)szPath, (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch));
  672. if (MessageBox(hwndFrame, szMessage, szTitle, MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
  673. goto DODone;
  674. }
  675. /* If we dragged from a Dir Window, add path information. */
  676. if (lpds->hwndSource == hWnd)
  677. szTemp[0] = TEXT('\0');
  678. else
  679. SendMessage(lpds->hwndSource, FS_GETDIRECTORY, sizeof(szTemp), (LPARAM)szTemp);
  680. lstrcat(szTemp, (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch));
  681. // put a "." extension on if none found
  682. if (*GetExtension(szTemp) == 0)
  683. lstrcat(szTemp, ".");
  684. FixAnsiPathForDos(szTemp);
  685. FixAnsiPathForDos(szPath);
  686. ret = ExecProgram(szPath,szTemp,NULL,FALSE);
  687. if (ret)
  688. MyMessageBox(hwndFrame, IDS_EXECERRTITLE, ret, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  689. DODone:
  690. DSRectItem(hwndLB, iSelHilite, FALSE, TRUE);
  691. return TRUE;
  692. DirMoveCopy:
  693. pFrom = (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch);
  694. AddBackslash(szPath); // add filespec filter
  695. lstrcat(szPath, szStarDotStar);
  696. DMMoveCopyHelper(pFrom, szPath, fShowSourceBitmaps);
  697. DSRectItem(hwndLB, iSelHilite, FALSE, TRUE);
  698. return TRUE;
  699. }
  700. case WM_LBTRACKPOINT:
  701. MSG("SearchWndProc", "WM_LBTRACKPOINT");
  702. return(DSTrackPoint(hWnd, hwndLB, wParam, lParam, TRUE));
  703. case WM_MEASUREITEM:
  704. MSG("SearchWndProc", "WM_MEASUREITEM");
  705. {
  706. #define pLBMItem ((LPMEASUREITEMSTRUCT)lParam)
  707. pLBMItem->itemHeight = dyFileName;
  708. break;
  709. }
  710. case WM_QUERYDROPOBJECT:
  711. MSG("SearchWndProc", "WM_QUERYDROPOBJECT");
  712. /* Ensure that we are dropping on the client area of the listbox. */
  713. #define lpds ((LPDROPSTRUCT)lParam)
  714. /* Ensure that we can accept the format. */
  715. switch (lpds->wFmt) {
  716. case DOF_EXECUTABLE:
  717. case DOF_DIRECTORY:
  718. case DOF_DOCUMENT:
  719. case DOF_MULTIPLE:
  720. if (lpds->hwndSink == hWnd)
  721. lpds->dwControlData = -1L;
  722. return TRUE;
  723. }
  724. return FALSE;
  725. case WM_SIZE:
  726. MSG("SearchWndProc", "WM_SIZE");
  727. if (wParam != SIZEICONIC) {
  728. MoveWindow(GetDlgItem(hWnd, IDCW_LISTBOX),
  729. -1, -1,
  730. LOWORD(lParam)+2,
  731. HIWORD(lParam)+2,
  732. TRUE);
  733. }
  734. /*** FALL THRU ***/
  735. default:
  736. DefChildProc:
  737. DEFMSG("SearchWndProc", (WORD)wMsg);
  738. return(DefMDIChildProc(hWnd, wMsg, wParam, lParam));
  739. }
  740. return(0L);
  741. }