943 lines
30 KiB
C
943 lines
30 KiB
C
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* WFSEARCH.C - */
|
||
|
/* */
|
||
|
/* File System Search Routines */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
#include "winfile.h"
|
||
|
#include "lfn.h"
|
||
|
|
||
|
INT maxExt;
|
||
|
INT iDirsRead;
|
||
|
DWORD LastUpdateTime;
|
||
|
|
||
|
|
||
|
WORD APIENTRY StackAvail(VOID);
|
||
|
INT FillSearchLB(HWND hwndLB, LPSTR szSearchFileSpec, BOOL bSubDirOnly);
|
||
|
INT SearchList(HWND hwndLB, LPSTR szPath, LPSTR szFileSpec, BOOL bRecurse, LPHANDLE lphMem, INT iFileCount);
|
||
|
LPSTR SearchGetSelection(HWND hwndLB, BOOL bMostRecent, BOOL *pfDir);
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* SearchList() - */
|
||
|
/* */
|
||
|
/* This is a recursive routine. It returns the number of files found. */
|
||
|
// szPath OEM
|
||
|
// szFileSpec OEM
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
#define DTA_GRANULARITY 20
|
||
|
|
||
|
INT
|
||
|
SearchList(
|
||
|
HWND hwndLB,
|
||
|
LPSTR szPath,
|
||
|
LPSTR szFileSpec,
|
||
|
BOOL bRecurse,
|
||
|
LPHANDLE lphMem,
|
||
|
INT iFileCount
|
||
|
)
|
||
|
{
|
||
|
INT iRetVal;
|
||
|
INT cxExt;
|
||
|
BOOL bFound;
|
||
|
LPSTR pszNewPath;
|
||
|
LPSTR pszNextFile;
|
||
|
LFNDTA lfndta;
|
||
|
LPDTASEARCH lpdtasch;
|
||
|
HDC hdc;
|
||
|
HANDLE hOld;
|
||
|
HANDLE hMem, hMemT;
|
||
|
DWORD TimeNow;
|
||
|
|
||
|
STKCHK();
|
||
|
|
||
|
hMem = *lphMem;
|
||
|
|
||
|
/* Just return 0 files so parent dirs will still be searched
|
||
|
*/
|
||
|
if (StackAvail() < 1024)
|
||
|
return(iFileCount);
|
||
|
|
||
|
TimeNow = GetTickCount();
|
||
|
|
||
|
if (TimeNow > LastUpdateTime+1000) {
|
||
|
LastUpdateTime = TimeNow;
|
||
|
if (LoadString(hAppInstance, IDS_DIRSREAD, szMessage, sizeof(szMessage)))
|
||
|
wsprintf(szStatusTree, szMessage, iDirsRead);
|
||
|
|
||
|
InvalidateRect(hwndFrame, NULL, FALSE);
|
||
|
UpdateWindow(hwndFrame);
|
||
|
}
|
||
|
|
||
|
iDirsRead++;
|
||
|
|
||
|
if (!hMem) {
|
||
|
hMem = LocalAlloc(LPTR, (DWORD)DTA_GRANULARITY * sizeof(DTASEARCH));
|
||
|
if (!hMem)
|
||
|
return -1;
|
||
|
*lphMem = hMem;
|
||
|
}
|
||
|
lpdtasch = (LPDTASEARCH)LocalLock(hMem);
|
||
|
|
||
|
// allocate the buffer for this level
|
||
|
pszNewPath = (LPSTR)LocalAlloc(LPTR, lstrlen(szPath) + MAXFILENAMELEN + 2);
|
||
|
if (!pszNewPath)
|
||
|
return -1;
|
||
|
|
||
|
lstrcpy(pszNewPath, szPath);
|
||
|
AddBackslash(pszNewPath);
|
||
|
pszNextFile = pszNewPath + lstrlen(pszNewPath);
|
||
|
lstrcpy(pszNextFile, szFileSpec);
|
||
|
|
||
|
bFound = WFFindFirst(&lfndta, pszNewPath, ATTR_ALL);
|
||
|
|
||
|
hdc = GetDC(hwndLB);
|
||
|
hOld = SelectObject(hdc, hFont);
|
||
|
|
||
|
while (bFound) {
|
||
|
|
||
|
// alow escape to exit
|
||
|
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
|
||
|
bRecurse = FALSE;
|
||
|
iFileCount = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Make sure this is not a "." or ".." directory
|
||
|
|
||
|
if (lfndta.fd.cFileName[0] != '.') {
|
||
|
BOOL bLFN;
|
||
|
|
||
|
lstrcpy(pszNextFile, lfndta.fd.cFileName);
|
||
|
OemToAnsi(pszNewPath, szMessage);
|
||
|
|
||
|
bLFN = IsLFN(lfndta.fd.cFileName);
|
||
|
|
||
|
iRetVal = (INT)SendMessage(hwndLB, LB_ADDSTRING, 0, (LPARAM)szMessage);
|
||
|
|
||
|
MGetTextExtent(hdc, szMessage, lstrlen(szMessage), &cxExt, NULL);
|
||
|
maxExt = max(maxExt, cxExt);
|
||
|
|
||
|
if (iRetVal >= 0) {
|
||
|
|
||
|
if (iFileCount && ((iFileCount % DTA_GRANULARITY) == 0)) {
|
||
|
LocalUnlock(hMem);
|
||
|
|
||
|
if (!(hMemT = LocalReAlloc(hMem, (DWORD)((iFileCount + DTA_GRANULARITY) * sizeof(DTASEARCH)), LMEM_MOVEABLE))) {
|
||
|
LocalLock(hMem);
|
||
|
bRecurse = FALSE; // simulate an abort
|
||
|
iFileCount = -1;
|
||
|
break;
|
||
|
} else {
|
||
|
hMem = hMemT;
|
||
|
*lphMem = hMemT;
|
||
|
}
|
||
|
|
||
|
lpdtasch = (LPDTASEARCH)LocalLock(hMem);
|
||
|
}
|
||
|
lpdtasch[iFileCount] = *((LPDTASEARCH)(&lfndta.fd));
|
||
|
if (bLFN)
|
||
|
lpdtasch[iFileCount].sch_dwAttrs |= ATTR_LFN;
|
||
|
SendMessage(hwndLB, LB_SETITEMDATA, iRetVal, (LONG)iFileCount);
|
||
|
iFileCount++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Search for more files in the current directory */
|
||
|
bFound = WFFindNext(&lfndta);
|
||
|
}
|
||
|
|
||
|
WFFindClose(&lfndta);
|
||
|
|
||
|
if (hOld)
|
||
|
SelectObject(hdc, hOld);
|
||
|
ReleaseDC(hwndLB, hdc);
|
||
|
|
||
|
LocalUnlock(hMem);
|
||
|
SetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH, (LONG_PTR)hMem);
|
||
|
|
||
|
if (!bRecurse)
|
||
|
goto SearchEnd;
|
||
|
|
||
|
/* Now see if there are any subdirectories here */
|
||
|
lstrcpy(pszNextFile, szStarDotStar);
|
||
|
|
||
|
bFound = WFFindFirst(&lfndta, pszNewPath, ATTR_DIR | ATTR_HS);
|
||
|
|
||
|
while (bFound) {
|
||
|
|
||
|
// alow escape to exit
|
||
|
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
|
||
|
bRecurse = FALSE;
|
||
|
iFileCount = -1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Make sure this is not a "." or ".." directory. */
|
||
|
if ((lfndta.fd.cFileName[0] != '.') && (lfndta.fd.dwFileAttributes & ATTR_DIR)) {
|
||
|
/* Yes, search and add files in this directory */
|
||
|
lstrcpy(pszNextFile, lfndta.fd.cFileName);
|
||
|
|
||
|
/* Add all files in this subdirectory. */
|
||
|
if ((iRetVal = SearchList(hwndLB, pszNewPath, szFileSpec, bRecurse, lphMem, iFileCount)) < 0) {
|
||
|
iFileCount = iRetVal;
|
||
|
break;
|
||
|
}
|
||
|
iFileCount = iRetVal;
|
||
|
|
||
|
}
|
||
|
bFound = WFFindNext(&lfndta);
|
||
|
}
|
||
|
|
||
|
WFFindClose(&lfndta);
|
||
|
|
||
|
SearchEnd:
|
||
|
|
||
|
LocalFree((HANDLE)pszNewPath);
|
||
|
return iFileCount;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FixUpFileSpec(
|
||
|
LPSTR szFileSpec
|
||
|
)
|
||
|
{
|
||
|
CHAR szTemp[MAXPATHLEN+1];
|
||
|
register LPSTR p;
|
||
|
|
||
|
if (*szFileSpec == '.') {
|
||
|
lstrcpy(szTemp, "*");
|
||
|
lstrcat(szTemp, szFileSpec);
|
||
|
lstrcpy(szFileSpec, szTemp);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* HACK: If there isn't a dot and the last char is a *, append ".*" */
|
||
|
p = szFileSpec;
|
||
|
while ((*p) && (*p != '.'))
|
||
|
p = AnsiNext(p);
|
||
|
|
||
|
if ((!*p) && (p != szFileSpec)) {
|
||
|
p = AnsiPrev(szFileSpec, p);
|
||
|
if (*p == '*')
|
||
|
lstrcat(p, ".*");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* FillSearchLB() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
/* This parses the given string for Drive, PathName, FileSpecs and
|
||
|
* calls SearchList() with proper parameters;
|
||
|
*
|
||
|
* hwndLB : List box where files are to be displayed;
|
||
|
* szSearchFileSpec : ANSI path to search
|
||
|
* bSubDirOnly : TRUE, if only subdirectories are to be searched;
|
||
|
*/
|
||
|
|
||
|
INT
|
||
|
FillSearchLB(
|
||
|
HWND hwndLB,
|
||
|
LPSTR szSearchFileSpec,
|
||
|
BOOL bRecurse
|
||
|
)
|
||
|
{
|
||
|
INT iRet;
|
||
|
HCURSOR hCursor;
|
||
|
CHAR szFileSpec[MAXPATHLEN+1];
|
||
|
CHAR szPathName[MAXPATHLEN+1];
|
||
|
HANDLE hMemIn = NULL;
|
||
|
|
||
|
FixAnsiPathForDos(szSearchFileSpec);
|
||
|
/* Get the file specification part of the string. */
|
||
|
lstrcpy(szFileSpec, szSearchFileSpec);
|
||
|
lstrcpy(szPathName, szSearchFileSpec);
|
||
|
StripPath(szFileSpec);
|
||
|
StripFilespec(szPathName);
|
||
|
|
||
|
FixUpFileSpec(szFileSpec);
|
||
|
|
||
|
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
|
ShowCursor(TRUE);
|
||
|
maxExt = 0;
|
||
|
iDirsRead = 1;
|
||
|
LastUpdateTime = 0;
|
||
|
iRet = SearchList(hwndLB, szPathName, szFileSpec, bRecurse, &hMemIn, 0);
|
||
|
ShowCursor(FALSE);
|
||
|
SetCursor(hCursor);
|
||
|
|
||
|
SendMessage(hwndLB, LB_SETSEL, TRUE, 0L);
|
||
|
|
||
|
return(iRet);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* SearchGetSelection() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
/* Returns a string containing the names of the selected
|
||
|
* files seperated by spaces. If bMostRecent is TRUE, it only returns the
|
||
|
* most recently selected file.
|
||
|
*
|
||
|
* The string is returned and a *pfDir is set indicating if it points
|
||
|
* to a directory.
|
||
|
*
|
||
|
* NOTE: The caller must free the returned pointer!
|
||
|
*/
|
||
|
|
||
|
LPSTR
|
||
|
SearchGetSelection(
|
||
|
HWND hwndLB,
|
||
|
BOOL bMostRecent,
|
||
|
BOOL *pfDir
|
||
|
)
|
||
|
{
|
||
|
register LPSTR p;
|
||
|
LPSTR pT;
|
||
|
register WORD i;
|
||
|
WORD iMac;
|
||
|
WORD cch = 1;
|
||
|
BOOL bDir;
|
||
|
HANDLE hMem;
|
||
|
LPDTASEARCH lpdtasch;
|
||
|
CHAR szTemp[MAXPATHLEN];
|
||
|
|
||
|
BOOL bLFNTest;
|
||
|
|
||
|
if (bLFNTest = (bMostRecent == 2)) {
|
||
|
bMostRecent = FALSE;
|
||
|
} else {
|
||
|
p = (LPSTR)LocalAlloc(LPTR, 1);
|
||
|
if (!p)
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (bMostRecent == 3)
|
||
|
bMostRecent = 0;
|
||
|
|
||
|
bDir = TRUE;
|
||
|
|
||
|
iMac = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
|
||
|
|
||
|
hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH);
|
||
|
|
||
|
lpdtasch = (LPDTASEARCH)LocalLock(hMem);
|
||
|
|
||
|
for (i=0; i < iMac; i++) {
|
||
|
if (!(BOOL)SendMessage(hwndLB, LB_GETSEL, i, 0L))
|
||
|
continue;
|
||
|
|
||
|
cch += (WORD)SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)szTemp);
|
||
|
cch++;
|
||
|
|
||
|
if (bLFNTest) {
|
||
|
if (IsLFN(szTemp)) {
|
||
|
if (pfDir)
|
||
|
*pfDir = TRUE;
|
||
|
return NULL;
|
||
|
}
|
||
|
} else {
|
||
|
pT = (LPSTR)LocalReAlloc((HANDLE)p, cch, LMEM_MOVEABLE | LMEM_ZEROINIT);
|
||
|
if (!pT)
|
||
|
goto SGSExit;
|
||
|
p = pT;
|
||
|
lstrcat(p, szTemp);
|
||
|
|
||
|
bDir = lpdtasch[(INT)SendMessage(hwndLB, LB_GETITEMDATA, i, 0L)].sch_dwAttrs & ATTR_DIR;
|
||
|
|
||
|
if (bMostRecent)
|
||
|
break;
|
||
|
|
||
|
lstrcat(p, szBlank);
|
||
|
}
|
||
|
}
|
||
|
SGSExit:
|
||
|
LocalUnlock(hMem);
|
||
|
|
||
|
if (bLFNTest) {
|
||
|
if (pfDir)
|
||
|
*pfDir = FALSE;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (pfDir)
|
||
|
*pfDir = bDir;
|
||
|
return(p);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
CreateLine(
|
||
|
WORD wLineFormat,
|
||
|
LPSTR szFile,
|
||
|
LPDTASEARCH lpdtasch,
|
||
|
LPSTR szBuffer
|
||
|
)
|
||
|
{
|
||
|
LPSTR pch;
|
||
|
BYTE chAttribute;
|
||
|
|
||
|
pch = szBuffer;
|
||
|
|
||
|
chAttribute = (BYTE)lpdtasch->sch_dwAttrs;
|
||
|
|
||
|
/* Copy the file name. */
|
||
|
lstrcpy(pch, szFile);
|
||
|
pch += lstrlen(pch);
|
||
|
|
||
|
*pch = TEXT('\0');
|
||
|
|
||
|
/* Should we show the size? */
|
||
|
if (wLineFormat & VIEW_SIZE) {
|
||
|
*pch++ = TABCHAR;
|
||
|
if (!(chAttribute & ATTR_DIR))
|
||
|
pch += PutSize(lpdtasch->sch_nFileSizeLow, pch);
|
||
|
}
|
||
|
|
||
|
/* Should we show the date? */
|
||
|
if (wLineFormat & VIEW_DATE) {
|
||
|
*pch++ = TABCHAR;
|
||
|
pch += PutDate(&lpdtasch->sch_ftLastWriteTime, pch);
|
||
|
}
|
||
|
|
||
|
/* Should we show the time? */
|
||
|
if (wLineFormat & VIEW_TIME) {
|
||
|
*pch++ = TABCHAR;
|
||
|
pch += PutTime(&lpdtasch->sch_ftLastWriteTime, pch);
|
||
|
}
|
||
|
|
||
|
/* Should we show the attributes? */
|
||
|
if (wLineFormat & VIEW_FLAGS) {
|
||
|
*pch++ = TABCHAR;
|
||
|
pch += PutAttributes((WORD)chAttribute, pch);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// the window text looks like "Search Window: C:\FOO\BAR\*.*"
|
||
|
|
||
|
VOID
|
||
|
GetSearchPath(
|
||
|
HWND hWnd,
|
||
|
LPSTR pszPath
|
||
|
)
|
||
|
{
|
||
|
LPSTR p;
|
||
|
|
||
|
CHAR szTemp[MAXPATHLEN+32];
|
||
|
|
||
|
// the search window doesn't have a current directory
|
||
|
GetWindowText(hWnd, szTemp, sizeof(szTemp));
|
||
|
|
||
|
// the window text looks like "Search Window: C:\FOO\BAR\*.*"
|
||
|
p = szTemp;
|
||
|
while (*p && *p != ':') // find the :
|
||
|
p = AnsiNext(p);
|
||
|
|
||
|
p += 2; // skip the ": "
|
||
|
|
||
|
lstrcpy(pszPath, p);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* UpdateSearchStatus() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
VOID
|
||
|
UpdateSearchStatus(
|
||
|
HWND hwndLB
|
||
|
)
|
||
|
{
|
||
|
INT nCount;
|
||
|
|
||
|
nCount = (INT)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
|
||
|
if (LoadString(hAppInstance, IDS_SEARCHMSG, szMessage, sizeof(szMessage)))
|
||
|
wsprintf(szStatusTree, szMessage, nCount);
|
||
|
szStatusDir[0] = '\0';
|
||
|
InvalidateRect(hwndFrame, NULL, FALSE);
|
||
|
}
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* SearchWndProc() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
INT_PTR
|
||
|
APIENTRY
|
||
|
SearchWndProc(
|
||
|
register HWND hWnd,
|
||
|
UINT wMsg,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
INT iRet;
|
||
|
INT iSel;
|
||
|
HWND hwndLB;
|
||
|
CHAR szTemp[MAXPATHLEN + 32];
|
||
|
CHAR szPath[MAXPATHLEN];
|
||
|
|
||
|
STKCHK();
|
||
|
|
||
|
hwndLB = GetDlgItem(hWnd, IDCW_LISTBOX);
|
||
|
|
||
|
switch (wMsg) {
|
||
|
case FS_GETDRIVE:
|
||
|
MSG("SearchWndProc", "FS_GETDRIVE");
|
||
|
// Returns the letter of the corresponding directory
|
||
|
|
||
|
SendMessage(hWnd, FS_GETDIRECTORY, sizeof(szPath), (LPARAM)szPath);
|
||
|
return szPath[0]; // first character
|
||
|
|
||
|
case FS_GETDIRECTORY:
|
||
|
MSG("SearchWndProc", "FS_GETDIRECTORY");
|
||
|
|
||
|
GetSearchPath(hWnd, szPath);
|
||
|
|
||
|
StripFilespec(szPath); // remove the filespec
|
||
|
AddBackslash(szPath); // to be the same as DirWndProc
|
||
|
lstrcpy((LPSTR)lParam, szPath);
|
||
|
break;
|
||
|
|
||
|
case FS_GETFILESPEC:
|
||
|
|
||
|
MSG("SearchWndProc", "FS_GETFILESPEC");
|
||
|
// the search window doesn't have a current directory
|
||
|
GetSearchPath(hWnd, szPath);
|
||
|
StripPath(szPath); // remove the path (leave the filespec)
|
||
|
lstrcpy((LPSTR)lParam, szPath);
|
||
|
break;
|
||
|
|
||
|
case FS_SETSELECTION:
|
||
|
MSG("SearchWndProc", "FS_SETSELECTION");
|
||
|
// wParam is the select(TRUE)/unselect(FALSE) param
|
||
|
// lParam is the filespec to match against
|
||
|
|
||
|
SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);
|
||
|
DSSetSelection(hwndLB, wParam ? TRUE : FALSE, (LPSTR)lParam, TRUE);
|
||
|
SendMessage(hwndLB, WM_SETREDRAW, TRUE, 0L);
|
||
|
InvalidateRect(hwndLB, NULL, TRUE);
|
||
|
break;
|
||
|
|
||
|
case FS_GETSELECTION:
|
||
|
MSG("SearchWndProc", "FS_GETSELECTION");
|
||
|
return (INT_PTR)SearchGetSelection(hwndLB, wParam ? TRUE : FALSE, (BOOL *)lParam);
|
||
|
break;
|
||
|
|
||
|
case WM_MDIACTIVATE:
|
||
|
if (wParam) {
|
||
|
UpdateSearchStatus(hwndLB);
|
||
|
|
||
|
// if we are dirty, ask if we should update
|
||
|
|
||
|
if (GetWindowLong(hWnd, GWL_FSCFLAG))
|
||
|
PostMessage(hWnd, FS_CHANGEDISPLAY, CD_SEARCHUPDATE, 0L);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_FILESYSCHANGE:
|
||
|
SetWindowLong(hWnd, GWL_FSCFLAG, TRUE); // I need updating
|
||
|
|
||
|
// if the search window is not active or FSCs are disabled
|
||
|
// don't prompt now, wait till we get the end FSC or are
|
||
|
// activated (above in WM_ACTIVATE)
|
||
|
if (cDisableFSC ||
|
||
|
(hWnd != (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L)) &&
|
||
|
(GetActiveWindow() != hwndFrame))
|
||
|
break;
|
||
|
|
||
|
PostMessage(hWnd, FS_CHANGEDISPLAY, CD_SEARCHUPDATE, 0L);
|
||
|
break;
|
||
|
|
||
|
case FS_CHANGEDISPLAY:
|
||
|
MSG("SearchWndProc", "FS_CHANGEDISPLAY");
|
||
|
|
||
|
SetWindowLong(hWnd, GWL_FSCFLAG, FALSE); // I am clean
|
||
|
|
||
|
if (wParam == CD_SEARCHUPDATE) {
|
||
|
LoadString(hAppInstance, IDS_SEARCHTITLE, szTitle, sizeof(szTitle));
|
||
|
LoadString(hAppInstance, IDS_SEARCHREFRESH, szMessage, sizeof(szMessage));
|
||
|
if (MessageBox(hWnd, szMessage, szTitle, MB_YESNO | MB_ICONQUESTION) != IDYES)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// is this a refresh?
|
||
|
|
||
|
if (!lParam) {
|
||
|
GetSearchPath(hWnd, szPath);
|
||
|
} else {
|
||
|
lstrcpy(szPath, (LPSTR)lParam); // explicit re-search
|
||
|
}
|
||
|
|
||
|
LoadString(hAppInstance, IDS_SEARCHTITLE, szMessage, 32);
|
||
|
lstrcat(szMessage, szPath);
|
||
|
SetWindowText(hWnd, szMessage);
|
||
|
|
||
|
SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);
|
||
|
SendMessage(hwndLB, LB_RESETCONTENT, 0, 0L);
|
||
|
|
||
|
iRet = FillSearchLB(hwndLB, szPath, bSearchSubs);
|
||
|
|
||
|
FixTabsAndThings(hwndLB,(WORD *)GetWindowLongPtr(hWnd, GWLP_TABARRAYSEARCH), maxExt + dxText,wNewView);
|
||
|
|
||
|
SendMessage(hwndLB, WM_SETREDRAW, TRUE, 0L);
|
||
|
InvalidateRect(hwndLB, NULL, TRUE);
|
||
|
if (iRet == 0) {
|
||
|
LoadString(hAppInstance, IDS_SEARCHTITLE, szTitle, sizeof(szTitle));
|
||
|
LoadString(hAppInstance, IDS_SEARCHNOMATCHES, szMessage, sizeof(szMessage));
|
||
|
MessageBox(hwndFrame, szMessage, szTitle, MB_OK | MB_ICONINFORMATION);
|
||
|
|
||
|
ShowWindow(hWnd, SW_HIDE);
|
||
|
PostMessage(hWnd, WM_CLOSE, 0, 0L);
|
||
|
return FALSE;
|
||
|
} else {
|
||
|
UpdateSearchStatus(hwndLB);
|
||
|
}
|
||
|
|
||
|
if (GetFocus() != hwndLB)
|
||
|
return(iRet);
|
||
|
|
||
|
/*** FALL THRU ***/
|
||
|
|
||
|
case WM_SETFOCUS:
|
||
|
MSG("SearchWndProc", "WM_SETFOCUS");
|
||
|
|
||
|
SetFocus(hwndLB);
|
||
|
return (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
|
||
|
|
||
|
case WM_CLOSE:
|
||
|
MSG("SearchWndProc", "WM_CLOSE");
|
||
|
hwndSearch = NULL;
|
||
|
goto DefChildProc;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
/* Was this a double-click? */
|
||
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_DBLCLK)
|
||
|
SendMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_OPEN, 0, 0));
|
||
|
else if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) {
|
||
|
INT i;
|
||
|
for (i = 0; i < iNumExtensions; i++) {
|
||
|
(extensions[i].ExtProc)(hwndFrame, FMEVENT_SELCHANGE, 0L);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
MSG("SearchWndProc", "WM_DESTROY");
|
||
|
{
|
||
|
HANDLE hMem;
|
||
|
|
||
|
if (hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTASEARCH))
|
||
|
LocalFree(hMem);
|
||
|
|
||
|
if (hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_TABARRAYSEARCH))
|
||
|
LocalFree(hMem);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_CREATE:
|
||
|
TRACE(BF_WM_CREATE, "SearchWndProc - WM_CREATE");
|
||
|
{
|
||
|
// globals used:
|
||
|
// szSearch path to start search at
|
||
|
// bSearchSubs tells us to do a recursive search
|
||
|
|
||
|
RECT rc;
|
||
|
WORD *pwTabs;
|
||
|
|
||
|
GetClientRect(hWnd, &rc);
|
||
|
hwndLB = CreateWindowEx(0, szListbox, NULL,
|
||
|
WS_CHILD | WS_BORDER | LBS_SORT | LBS_NOTIFY |
|
||
|
LBS_OWNERDRAWFIXED | LBS_EXTENDEDSEL |
|
||
|
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
|
||
|
LBS_HASSTRINGS | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
|
||
|
-1, -1, rc.right+2, rc.bottom+2,
|
||
|
hWnd, (HMENU)IDCW_LISTBOX,
|
||
|
hAppInstance, NULL);
|
||
|
if (!hwndLB)
|
||
|
return -1L;
|
||
|
|
||
|
if ((pwTabs = (WORD *)LocalAlloc(LPTR,sizeof(WORD) * 4)) == NULL)
|
||
|
return -1L;
|
||
|
|
||
|
hwndSearch = hWnd;
|
||
|
SetWindowLong(hWnd, GWL_TYPE, TYPE_SEARCH);
|
||
|
SetWindowLong(hWnd, GWL_VIEW, wNewView);
|
||
|
SetWindowLong(hWnd, GWL_SORT, IDD_NAME);
|
||
|
SetWindowLong(hWnd, GWL_ATTRIBS,ATTR_DEFAULT);
|
||
|
SetWindowLong(hWnd, GWL_FSCFLAG, FALSE);
|
||
|
SetWindowLongPtr(hWnd, GWLP_HDTASEARCH, 0);
|
||
|
SetWindowLongPtr(hWnd, GWLP_TABARRAYSEARCH, (LONG_PTR)pwTabs);
|
||
|
SetWindowLongPtr(hWnd, GWLP_LASTFOCUSSEARCH, (LONG_PTR)hwndLB);
|
||
|
|
||
|
// Fill the listbox
|
||
|
if (!FillSearchLB(hwndLB, szSearch, bSearchSubs)) {
|
||
|
LoadString(hAppInstance, IDS_SEARCHTITLE, szTitle, sizeof(szTitle));
|
||
|
LoadString(hAppInstance, IDS_SEARCHNOMATCHES, szMessage, sizeof(szMessage));
|
||
|
MessageBox(hwndFrame, szMessage, szTitle, MB_OK | MB_ICONINFORMATION);
|
||
|
hwndSearch = NULL;
|
||
|
return -1L;
|
||
|
} else {
|
||
|
FixTabsAndThings(hwndLB,pwTabs, maxExt + dxText,wNewView);
|
||
|
SendMessage(hwndLB, WM_SETFONT, (WPARAM)hFont, 0L);
|
||
|
ShowWindow(hwndSearch, SW_SHOWNORMAL);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_DRAGLOOP:
|
||
|
MSG("SearchWndProc", "WM_DRAGLOOP");
|
||
|
/* WM_DRAGLOOP is sent to the source window as the object is moved.
|
||
|
*
|
||
|
* wParam: TRUE if the object is currently over a droppable sink
|
||
|
* lParam: LPDROPSTRUCT
|
||
|
*/
|
||
|
|
||
|
/* DRAGLOOP is used to turn the source bitmaps on/off as we drag. */
|
||
|
|
||
|
DSDragLoop(hwndLB, wParam, (LPDROPSTRUCT)lParam, TRUE);
|
||
|
break;
|
||
|
|
||
|
case WM_DRAGSELECT:
|
||
|
MSG("SearchWndProc", "WM_DRAGSELECT");
|
||
|
/* WM_DRAGSELECT is sent to a sink whenever an new object is dragged
|
||
|
* inside of it.
|
||
|
*
|
||
|
* wParam: TRUE if the sink is being entered, FALSE if it's being
|
||
|
* exited.
|
||
|
* lParam: LPDROPSTRUCT
|
||
|
*/
|
||
|
|
||
|
/* DRAGSELECT is used to turn our selection rectangle on or off. */
|
||
|
#define lpds ((LPDROPSTRUCT)lParam)
|
||
|
|
||
|
iSelHilite = LOWORD(lpds->dwControlData);
|
||
|
DSRectItem(hwndLB, iSelHilite, (BOOL)wParam, TRUE);
|
||
|
break;
|
||
|
|
||
|
case WM_DRAGMOVE:
|
||
|
MSG("SearchWndProc", "WM_DRAGMOVE");
|
||
|
/* WM_DRAGMOVE is sent to a sink as the object is being dragged
|
||
|
* within it.
|
||
|
*
|
||
|
* wParam: Unused
|
||
|
* lParam: LPDROPSTRUCT
|
||
|
*/
|
||
|
|
||
|
/* DRAGMOVE is used to move our selection rectangle among sub-items. */
|
||
|
|
||
|
#define lpds ((LPDROPSTRUCT)lParam)
|
||
|
|
||
|
/* Get the subitem we are over. */
|
||
|
iSel = LOWORD(lpds->dwControlData);
|
||
|
|
||
|
/* Is it a new one? */
|
||
|
if (iSel == iSelHilite)
|
||
|
break;
|
||
|
|
||
|
/* Yup, un-select the old item. */
|
||
|
DSRectItem(hwndLB, iSelHilite, FALSE, TRUE);
|
||
|
|
||
|
/* Select the new one. */
|
||
|
iSelHilite = iSel;
|
||
|
DSRectItem(hwndLB, iSel, TRUE, TRUE);
|
||
|
break;
|
||
|
|
||
|
case WM_DRAWITEM:
|
||
|
MSG("SearchWndProc", "WM_DRAWITEM");
|
||
|
{
|
||
|
LPDRAWITEMSTRUCT lpLBItem;
|
||
|
HANDLE hMem;
|
||
|
LPDTASEARCH lpdtasch;
|
||
|
|
||
|
lpLBItem = (LPDRAWITEMSTRUCT)lParam;
|
||
|
iSel = lpLBItem->itemID;
|
||
|
|
||
|
if (iSel < 0)
|
||
|
break;
|
||
|
|
||
|
SendMessage(hwndLB, LB_GETTEXT, iSel, (LPARAM)szPath);
|
||
|
|
||
|
hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTASEARCH);
|
||
|
lpdtasch = (LPDTASEARCH)LocalLock(hMem);
|
||
|
|
||
|
iSel = (INT)SendMessage(hwndLB, LB_GETITEMDATA, iSel, 0L);
|
||
|
CreateLine((WORD)GetWindowLong(hWnd, GWL_VIEW), szPath, &(lpdtasch[iSel]), szTemp);
|
||
|
DrawItem(lpLBItem, szTemp, lpdtasch[iSel].sch_dwAttrs, TRUE,
|
||
|
(WORD *)GetWindowLongPtr(hWnd,GWLP_TABARRAYSEARCH));
|
||
|
LocalUnlock(hMem);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_DROPOBJECT:
|
||
|
MSG("SearchWndProc", "WM_DROPOBJECT");
|
||
|
{
|
||
|
LPSTR pFrom;
|
||
|
WORD ret;
|
||
|
WORD iSelSink;
|
||
|
HANDLE hMem;
|
||
|
LPDTASEARCH lpdtasch;
|
||
|
DWORD attrib;
|
||
|
|
||
|
/* WM_DROPOBJECT is sent to a sink when the user releases an
|
||
|
* acceptable object over it
|
||
|
*
|
||
|
* wParam: TRUE if over the non-client area, FALSE if over the
|
||
|
* client area.
|
||
|
* lParam: LPDROPSTRUCT
|
||
|
*/
|
||
|
|
||
|
#define lpds ((LPDROPSTRUCT)lParam)
|
||
|
|
||
|
iSelSink = LOWORD(lpds->dwControlData);
|
||
|
|
||
|
/* Are we dropping onto ourselves? (i.e. a selected item in the
|
||
|
* source listbox OR an unused area of the source listbox) If
|
||
|
* so, don't do anything.
|
||
|
*/
|
||
|
if (hWnd == lpds->hwndSource) {
|
||
|
if ((iSelSink == 0xFFFF) || (SendMessage(hwndLB, LB_GETSEL, iSelSink, 0L)))
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/* Are we dropping on a unused portion of the listbox? */
|
||
|
if (iSelSink == 0xFFFF)
|
||
|
return TRUE;
|
||
|
|
||
|
/* Get the sink's filename. */
|
||
|
SendMessage(hwndLB, LB_GETTEXT, iSelSink, (LPARAM)szPath);
|
||
|
|
||
|
hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTASEARCH);
|
||
|
lpdtasch = (LPDTASEARCH)LocalLock(hMem);
|
||
|
attrib = lpdtasch[(INT)SendMessage(hwndLB, LB_GETITEMDATA, iSelSink, 0L)].sch_dwAttrs;
|
||
|
LocalUnlock(hMem);
|
||
|
|
||
|
/* Are we dropping on a subdirectory? */
|
||
|
if (attrib & ATTR_DIR)
|
||
|
goto DirMoveCopy;
|
||
|
|
||
|
/* Are we not dropping on a Program file? */
|
||
|
if (!IsProgramFile(szPath))
|
||
|
return TRUE;
|
||
|
|
||
|
if (lpds->wFmt == DOF_DIRECTORY) {
|
||
|
goto DODone;
|
||
|
}
|
||
|
|
||
|
/* We're dropping a file onto a program.
|
||
|
* Exec the program using the source file as the parameter.
|
||
|
*/
|
||
|
|
||
|
/* Should we confirm it first? */
|
||
|
if (bConfirmMouse) {
|
||
|
LoadString(hAppInstance, IDS_MOUSECONFIRM, szTitle, MAXTITLELEN);
|
||
|
LoadString(hAppInstance, IDS_EXECMOUSECONFIRM, szTemp, sizeof(szTemp));
|
||
|
|
||
|
wsprintf(szMessage, szTemp, (LPSTR)szPath, (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch));
|
||
|
if (MessageBox(hwndFrame, szMessage, szTitle, MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
|
||
|
goto DODone;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* If we dragged from a Dir Window, add path information. */
|
||
|
if (lpds->hwndSource == hWnd)
|
||
|
szTemp[0] = TEXT('\0');
|
||
|
else
|
||
|
SendMessage(lpds->hwndSource, FS_GETDIRECTORY, sizeof(szTemp), (LPARAM)szTemp);
|
||
|
|
||
|
lstrcat(szTemp, (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch));
|
||
|
// put a "." extension on if none found
|
||
|
if (*GetExtension(szTemp) == 0)
|
||
|
lstrcat(szTemp, ".");
|
||
|
FixAnsiPathForDos(szTemp);
|
||
|
|
||
|
FixAnsiPathForDos(szPath);
|
||
|
ret = ExecProgram(szPath,szTemp,NULL,FALSE);
|
||
|
if (ret)
|
||
|
MyMessageBox(hwndFrame, IDS_EXECERRTITLE, ret, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
|
||
|
DODone:
|
||
|
DSRectItem(hwndLB, iSelHilite, FALSE, TRUE);
|
||
|
return TRUE;
|
||
|
|
||
|
DirMoveCopy:
|
||
|
pFrom = (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch);
|
||
|
|
||
|
AddBackslash(szPath); // add filespec filter
|
||
|
lstrcat(szPath, szStarDotStar);
|
||
|
|
||
|
DMMoveCopyHelper(pFrom, szPath, fShowSourceBitmaps);
|
||
|
|
||
|
DSRectItem(hwndLB, iSelHilite, FALSE, TRUE);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
case WM_LBTRACKPOINT:
|
||
|
MSG("SearchWndProc", "WM_LBTRACKPOINT");
|
||
|
return(DSTrackPoint(hWnd, hwndLB, wParam, lParam, TRUE));
|
||
|
|
||
|
case WM_MEASUREITEM:
|
||
|
MSG("SearchWndProc", "WM_MEASUREITEM");
|
||
|
{
|
||
|
#define pLBMItem ((LPMEASUREITEMSTRUCT)lParam)
|
||
|
|
||
|
pLBMItem->itemHeight = dyFileName;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_QUERYDROPOBJECT:
|
||
|
MSG("SearchWndProc", "WM_QUERYDROPOBJECT");
|
||
|
/* Ensure that we are dropping on the client area of the listbox. */
|
||
|
#define lpds ((LPDROPSTRUCT)lParam)
|
||
|
|
||
|
/* Ensure that we can accept the format. */
|
||
|
switch (lpds->wFmt) {
|
||
|
case DOF_EXECUTABLE:
|
||
|
case DOF_DIRECTORY:
|
||
|
case DOF_DOCUMENT:
|
||
|
case DOF_MULTIPLE:
|
||
|
if (lpds->hwndSink == hWnd)
|
||
|
lpds->dwControlData = -1L;
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
|
||
|
case WM_SIZE:
|
||
|
MSG("SearchWndProc", "WM_SIZE");
|
||
|
if (wParam != SIZEICONIC) {
|
||
|
MoveWindow(GetDlgItem(hWnd, IDCW_LISTBOX),
|
||
|
-1, -1,
|
||
|
LOWORD(lParam)+2,
|
||
|
HIWORD(lParam)+2,
|
||
|
TRUE);
|
||
|
}
|
||
|
/*** FALL THRU ***/
|
||
|
|
||
|
default:
|
||
|
DefChildProc:
|
||
|
DEFMSG("SearchWndProc", (WORD)wMsg);
|
||
|
return(DefMDIChildProc(hWnd, wMsg, wParam, lParam));
|
||
|
}
|
||
|
return(0L);
|
||
|
}
|