Leaked source code of windows server 2003
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.

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