windows-nt/Source/XPSP1/NT/sdktools/winobj/wfdir.c
2020-09-26 16:20:57 +08:00

2719 lines
80 KiB
C

/****************************************************************************/
/* */
/* WFDIR.C - */
/* */
/* Windows File System Directory Window Proc Routines */
/* */
/****************************************************************************/
#include "winfile.h"
#include "winnet.h"
#include "lfn.h"
#include "wfcopy.h"
#define MAXDIGITSINSIZE 8
#define DATEMASK 0x001F
#define MONTHMASK 0x01E0
#define MINUTEMASK 0x07E0
#define SECONDSMASK 0x001F
#define DATESEPERATOR '-'
#define TIMESEPERATOR ':'
CHAR szAttr[] = "RHSA";
INT iLastSel = -1;
INT_PTR APIENTRY DirWndProc(register HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
LPSTR DirGetSelection(HWND hwndDir, HWND hwndLB, INT iSelType, BOOL *pfDir);
VOID DirGetAnchorFocus(register HWND hwndLB, HANDLE hDTA, LPSTR szAnchor, LPSTR szCaret, LPSTR szTopIndex);
VOID FillDirList(HWND hWnd, HANDLE hDirEntries);
VOID DrawItemFast(HWND hWnd, LPDRAWITEMSTRUCT lpLBItem, LPMYDTA lpmydta, BOOL bHasFocus);
INT GetPict(CHAR ch, LPSTR szStr);
INT DirFindIndex(HWND hwndLB, HANDLE hDTA, LPSTR szFile);
INT CompareDTA(register LPMYDTA item1, LPMYDTA item2, WORD wSort);
VOID CreateLBLine(register WORD wLineFormat, LPMYDTA lpmydta, LPSTR szBuffer);
HANDLE CreateDTABlock(HWND hWnd, LPSTR pPath, DWORD dwAttribs, BOOL bAllowAbort, BOOL bDontSteal);
BOOL SetSelection(HWND hwndLB, HANDLE hDTA, LPSTR pSel);
INT CreateDate(WORD *wValArray, LPSTR szOutStr);
INT CreateTime(WORD * wValArray, LPSTR szOutStr);
VOID GetDirStatus(HWND hWnd, LPSTR szMsg1, LPSTR szMsg2);
INT GetMaxExtent(HWND hwndLB, HANDLE hDTA);
BOOL CheckEarlyAbort(VOID);
BOOL SetDirFocus(HWND hwndDir);
VOID APIENTRY CheckEscapes(LPSTR);
VOID SortDirList(HWND, LPMYDTA, WORD ,LPMYDTA *);
/*--------------------------------------------------------------------------*/
/* */
/* DrawItemFast() - */
/* */
/*--------------------------------------------------------------------------*/
VOID
DrawItemFast(
HWND hWnd,
LPDRAWITEMSTRUCT lpLBItem,
LPMYDTA lpmydta,
BOOL bHasFocus
)
{
INT x, y, i;
HDC hDC;
BOOL bDrawSelected;
HWND hwndLB;
RECT rc;
DWORD rgbText, rgbBackground;
CHAR szBuf[MAXFILENAMELEN+2];
hWnd;
ENTER("DrawItemFast");
hDC = lpLBItem->hDC;
hwndLB = lpLBItem->hwndItem;
bDrawSelected = (lpLBItem->itemState & ODS_SELECTED);
if (bHasFocus && bDrawSelected) {
rgbText = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
rgbBackground = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
}
if (lpLBItem->itemAction == ODA_FOCUS)
goto FocusOnly;
/* Draw the black/white background. */
x = lpLBItem->rcItem.left + 1;
y = lpLBItem->rcItem.top + (dyFileName/2);
lstrcpy(szBuf, lpmydta->my_cFileName);
if ((wTextAttribs & TA_LOWERCASE) && !(lpmydta->my_dwAttrs & ATTR_LFN))
AnsiLower(szBuf);
ExtTextOut(hDC, x + dxFolder + dyBorderx2 + dyBorder, y-(dyText/2),
ETO_OPAQUE, &lpLBItem->rcItem, szBuf, lstrlen(szBuf), NULL);
if (fShowSourceBitmaps || (hwndDragging != hwndLB) || !bDrawSelected) {
LONG ySrc;
i = lpmydta->iBitmap;
if (i & 0x40) {
// It's an object type bitmap
ySrc = (dyFolder * 2) + dyDriveBitmap;
i = i & (~0x40);
while (i >= 16) {
i -= 16;
ySrc += (dyFolder * 2);
}
} else {
ySrc = 0;
}
ySrc += (bHasFocus && bDrawSelected) ? dyFolder : 0;
BitBlt(hDC, x + dyBorderx2, y-(dyFolder/2), dxFolder, dyFolder, hdcMem,
i * dxFolder, ySrc, SRCCOPY);
}
if (lpLBItem->itemState & ODS_FOCUS)
FocusOnly:
DrawFocusRect(hDC, &lpLBItem->rcItem); // toggles focus (XOR)
/* Restore the normal drawing colors. */
if (bDrawSelected) {
if (bHasFocus) {
SetTextColor(hDC, rgbText);
SetBkColor(hDC, rgbBackground);
} else {
HBRUSH hbr;
if (hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT))) {
rc = lpLBItem->rcItem;
rc.left += dyBorder;
rc.right -= dyBorder;
if (lpLBItem->itemID > 0 &&
(BOOL)SendMessage(hwndLB, LB_GETSEL, lpLBItem->itemID - 1, 0L))
rc.top -= dyBorder;
FrameRect(hDC, &rc, hbr);
DeleteObject(hbr);
}
}
}
LEAVE("DrawItemFast");
}
/*--------------------------------------------------------------------------*/
/* */
/* FillDirList() - */
/* */
/* HANDLE hDirEntries; Array of directory entries */
/*--------------------------------------------------------------------------*/
VOID
FillDirList(
HWND hWnd,
HANDLE hDTA
)
{
register WORD count;
LPMYDTA lpmydta;
LPMYDTA *alpmydtaSorted;
WORD i;
lpmydta = (LPMYDTA)LocalLock(hDTA);
count = (WORD)lpmydta->my_nFileSizeLow;
if (count == 0) {
SendMessage(hWnd, LB_ADDSTRING, 0, 0L); // tolken for no items
} else {
alpmydtaSorted = (LPMYDTA *)LocalAlloc(LMEM_FIXED,
sizeof(LPMYDTA) * count);
if (alpmydtaSorted != NULL) {
SortDirList(hWnd, lpmydta, count, alpmydtaSorted);
for (i = 0; i < count; i++) {
alpmydtaSorted[i]->nIndex = i;
SendMessage(hWnd, LB_INSERTSTRING,(WPARAM)-1, (LPARAM)alpmydtaSorted[i]);
}
LocalFree((HANDLE)alpmydtaSorted);
}
}
LocalUnlock(hDTA);
}
BOOL
CheckEarlyAbort()
{
MSG msg;
if (PeekMessage(&msg, NULL, WM_KEYDOWN, WM_KEYDOWN, PM_NOREMOVE | PM_NOYIELD)) {
if (msg.wParam == VK_UP ||
msg.wParam == VK_DOWN) {
return TRUE;
}
}
return FALSE;
}
HANDLE
CopyDTABlock(
HANDLE hDTASrc
)
{
LPMYDTA lpmydtaSrc, lpmydtaDst;
HANDLE hDTADst;
SIZE_T dwSize;
lpmydtaSrc = (LPMYDTA)LocalLock(hDTASrc);
dwSize = LocalSize(hDTASrc);
if (hDTADst = LocalAlloc(LPTR, dwSize)) {
lpmydtaDst = (LPMYDTA)LocalLock(hDTADst);
memcpy(lpmydtaDst, lpmydtaSrc, (size_t)dwSize);
LocalUnlock(hDTASrc);
LocalUnlock(hDTADst);
return hDTADst;
} else {
LocalUnlock(hDTASrc);
return NULL;
}
}
HANDLE
StealDTABlock(
HWND hWnd,
LPSTR pPath,
DWORD dwAttribs
)
{
HWND hwnd;
HWND hwndDir;
HANDLE hDTA;
CHAR szPath[MAXPATHLEN];
ENTER("StealDTABlock");
for (hwnd = GetWindow(hwndMDIClient, GW_CHILD); hwnd;
hwnd = GetWindow(hwnd, GW_HWNDNEXT)) {
if ((hwndDir = HasDirWindow(hwnd)) && (hwndDir != hWnd)) {
GetMDIWindowText(hwnd, szPath, sizeof(szPath));
if ((dwAttribs == (DWORD)GetWindowLong(hwnd, GWL_ATTRIBS)) &&
!lstrcmpi(pPath, szPath) &&
(hDTA = (HANDLE)GetWindowLongPtr(hwndDir, GWLP_HDTA))) {
LEAVE("StealDTABlock");
return CopyDTABlock(hDTA);
}
}
}
LEAVE("StealDTABlock");
return NULL;
}
/*--------------------------------------------------------------------------*/
/* */
/* CreateDTABlock() - */
/* */
/*--------------------------------------------------------------------------*/
/* Builds a global memory block full of DTAs for the path 'pPath'. */
/* Returns:
* An unlocked global memory handle to DTA block with first DTA
* my_nFileSizeLow field indicating the number of DTA blocks that follow
*
* This builds a global memory block that has DTA entries for all
* of the files with dwAttributes in pPath. The first DTA entry's
* my_nFileSizeLow field indicates the number of actual DTA areas found
*/
HANDLE
CreateDTABlock(
HWND hWnd,
LPSTR pPath,
DWORD dwAttribs,
BOOL bAllowAbort,
BOOL bDontSteal
)
{
register LPSTR pName;
WORD wPathLen;
BOOL bDoc, bProgram;
DWORD dwCurrentSize, dwBlockSize;
WORD wSize, wLastSize;
LFNDTA lfndta;
HANDLE hMem;
LPMYDTA lpmydta, lpStart;
CHAR szPathOEM[MAXPATHLEN];
DWORD iBitmap;
WORD wDrive;
ENTER("CreateDTABlock");
PRINT(BF_PARMTRACE, "IN: pPath=%s", pPath);
PRINT(BF_PARMTRACE, "IN: dwAttribs=0x%lx", UlongToPtr(dwAttribs));
PRINT(BF_PARMTRACE, "IN: bDontSteal=%d", IntToPtr(bDontSteal));
#define BLOCK_SIZE_GRANULARITY 512 // must be larger than MYDTA
// get the drive index assuming path is
// fully qualified...
wDrive = (WORD)((*pPath - 'A') & 31);
if (bAllowAbort && CheckEarlyAbort()) {
PRINT(BF_PARMTRACE, "OUT: hDTA=-1", 0);
LEAVE("CreateDTABlock");
return (HANDLE)-1;
}
if (!bDontSteal && (hMem = StealDTABlock(hWnd, pPath, dwAttribs))) {
PRINT(BF_PARMTRACE, "OUT: hDTA=0x%lx", hMem);
LEAVE("CreateDTABlock");
return hMem;
}
dwBlockSize = BLOCK_SIZE_GRANULARITY;
hMem = LocalAlloc(LPTR, (DWORD)dwBlockSize);
if (!hMem) {
PRINT(BF_PARMTRACE, "OUT: hDTA=NULL", 0);
LEAVE("CreateDTABlock");
return NULL;
}
lpmydta = lpStart = (LPMYDTA)LocalLock(hMem);
lpStart->my_nFileSizeLow = 0;
wLastSize = sizeof(MYDTA) * sizeof(CHAR);
wLastSize = (WORD)DwordAlign(wLastSize);
lpStart->wSize = wLastSize;
dwCurrentSize = (DWORD)wLastSize;
lstrcpy(szPathOEM, pPath);
FixAnsiPathForDos(szPathOEM);
wPathLen = (WORD)(lstrlen(szPathOEM)-3); /* Ignore '*.*' */
if (!WFFindFirst(&lfndta, szPathOEM, (dwAttribs | ATTR_DIR) & ATTR_ALL)) {
// Try again if the disk is available
if (!IsTheDiskReallyThere(hWnd, pPath, FUNC_EXPAND) ||
!WFFindFirst(&lfndta, szPathOEM, (dwAttribs | ATTR_DIR) & ATTR_ALL))
goto CDBDone;
}
while (TRUE) {
pName = lfndta.fd.cFileName;
OemToAnsi(pName, pName);
// be safe, zero unused DOS dta bits
lfndta.fd.dwFileAttributes &= ATTR_USED;
// filter unwanted stuff here based on current view settings
if (!(lfndta.fd.dwFileAttributes & ATTR_DIR)) {
bProgram = IsProgramFile(pName);
bDoc = IsDocument(pName);
}
// figure out the bitmap type here
if (lfndta.fd.dwFileAttributes & ATTR_DIR) {
// ignore the "." directory
if (pName[0] == '.' && pName[1] != '.')
goto CDBCont;
// parent ".." dir
if (pName[0] == '.') {
pName = szNULL;
iBitmap = BM_IND_DIRUP;
lfndta.fd.dwFileAttributes |= ATTR_PARENT; // mark this!
} else {
// We always include DIRs so that the .. is
// included. Now we filter other dirs off.
if (!(dwAttribs & ATTR_DIR))
goto CDBCont;
iBitmap = BM_IND_CLOSE;
}
} else if (lfndta.fd.dwFileAttributes & ATTR_TYPES) {
iBitmap = ((lfndta.fd.dwFileAttributes & ATTR_TYPES) >> 16) | 0x40;
} else {
iBitmap = BM_IND_DOC;
}
//
// calc the size of this portion
//
// pName is assumed to be ANSI re: OemToAnsi() call,
// so lstrlen() should be size in bytes. We just need to add one
// for the terminating NULL
wSize = (WORD)(sizeof(MYDTA) + lstrlen(pName) + sizeof('\0'));
wSize = (WORD)DwordAlign(wSize);
if ((wSize + dwCurrentSize) > dwBlockSize) {
DWORD dwDelta;
// grow the block
dwBlockSize += BLOCK_SIZE_GRANULARITY;
LocalUnlock(hMem);
dwDelta = (DWORD)((LPBYTE)lpmydta - (LPBYTE)lpStart);
if (!(hMem = LocalReAlloc(hMem, dwBlockSize, LMEM_MOVEABLE)))
goto CDBMemoryErr;
lpStart = (LPMYDTA)LocalLock(hMem);
lpmydta = (LPMYDTA)((LPBYTE)lpStart + dwDelta);
}
lpStart->my_nFileSizeLow++;
dwCurrentSize += wSize;
// now it is safe to advance the pointer
lpmydta = GETDTAPTR(lpmydta, wLastSize);
wLastSize = lpmydta->wSize = wSize;
lpmydta->my_dwAttrs = lfndta.fd.dwFileAttributes;
lpmydta->my_ftLastWriteTime = lfndta.fd.ftLastWriteTime;
lpmydta->my_nFileSizeLow = lfndta.fd.nFileSizeLow;
lpmydta->my_nFileSizeHigh = lfndta.fd.nFileSizeHigh;
lpmydta->iBitmap = (SHORT)iBitmap;
if (IsLFN(pName)) {
lpmydta->my_dwAttrs |= ATTR_LFN;
}
lstrcpy(lpmydta->my_cFileName, pName);
CDBCont:
if (bAllowAbort && CheckEarlyAbort()) {
LocalUnlock(hMem);
LocalFree(hMem);
WFFindClose(&lfndta);
PRINT(BF_PARMTRACE, "OUT: hDTA=-1", 0);
LEAVE("CreateDTABlock");
return (HANDLE)-1;
}
if (!WFFindNext(&lfndta)) {
break;
}
}
CDBDone:
LocalUnlock(hMem);
WFFindClose(&lfndta);
PRINT(BF_PARMTRACE, "OUT: hDTA=0x%lx", hMem);
LEAVE("CreateDTABlock");
return hMem;
CDBMemoryErr:
WFFindClose(&lfndta);
MyMessageBox(hwndFrame, IDS_OOMTITLE, IDS_OOMREADINGDIRMSG, MB_OK | MB_ICONEXCLAMATION);
PRINT(BF_PARMTRACE, "OUT: hDTA=0x%lx", hMem);
LEAVE("CreateDTABlock");
return hMem;
}
/*--------------------------------------------------------------------------*/
/* */
/* DirGetSelection() - */
/* */
/*--------------------------------------------------------------------------*/
/* Takes a Listbox and returns a string containing the names of the selected
* files seperated by spaces.
*
* bSingle == 1 return only the first file
* bSingle == 2 test for LFN files in the selection, doesn't return string
* bSingle == 3 return fully qualified names
*
* returns:
* if (bSingle == 1)
* TRUE/FALSE if LFN is in the selection
* else
* pointer to the list of names (ANSI strings)
* (must be freed by caller!)
* *pfDir -> bool indicating directories are
* contained in the selection (or that LFN names are present)
*
* NOTE: The caller must free the returned pointer!
*/
LPSTR
DirGetSelection(
HWND hwndDir,
HWND hwndLB,
INT iSelType,
BOOL *pfDir
)
{
LPSTR p, pT;
WORD i;
WORD cch;
WORD iMac;
LPMYDTA lpmydta;
CHAR szFile[MAXPATHLEN];
CHAR szPath[MAXPATHLEN];
BOOL bDir, bPropertyDialog;
LPINT lpSelItems;
BOOL bLFNTest;
if (bLFNTest = (iSelType == 2)) {
// determine if the directory it self is long...
iSelType = FALSE;
SendMessage(hwndDir, FS_GETDIRECTORY, sizeof(szPath), (LPARAM)szPath);
StripBackslash(szPath);
if (IsLFN(szPath))
if (pfDir) {
*pfDir = TRUE;
}
return NULL;
}
if (bPropertyDialog = (iSelType == 3)) {
iSelType = FALSE;
}
bDir = FALSE;
if (!bLFNTest) {
cch = 1;
p = (LPSTR)LocalAlloc(LPTR, cch);
if (!p)
return NULL;
*p = '\0';
}
#ifdef DEBUG
else
p = (LPSTR)0xFFFF; // force a GP fault with bogus p use below
#endif
iLastSel = -1;
iMac = (WORD)SendMessage(hwndLB, LB_GETSELCOUNT, 0, 0L);
lpSelItems = LocalAlloc(LMEM_FIXED, sizeof(INT) * iMac);
if (lpSelItems == NULL)
return NULL;
iMac = (WORD)SendMessage(hwndLB, LB_GETSELITEMS, (WPARAM)iMac, (LPARAM)lpSelItems);
for (i=0; i < iMac; i++) {
if (iLastSel == -1) // remember the first selection
iLastSel = lpSelItems[i];
SendMessage(hwndLB, LB_GETTEXT, lpSelItems[i], (LPARAM)&lpmydta);
if (!lpmydta)
break;
lstrcpy(szFile, (LPSTR)lpmydta->my_cFileName);
if (lpmydta->my_dwAttrs & ATTR_DIR) { // is this a dir
SendMessage(hwndDir, FS_GETDIRECTORY, sizeof(szPath), (LPARAM)szPath);
if (lpmydta->my_dwAttrs & ATTR_PARENT) { // parent dir?
// if we are getting a full selection don't
// return the parent ".." entry (avoid deleting
// and other nasty operations on the parent)
if (!iSelType)
continue;
StripBackslash(szPath); // trim it down
StripFilespec(szPath);
} else {
lstrcat(szPath, szFile); // fully qualified
}
lstrcpy(szFile, szPath);
bDir = TRUE;
}
if (bPropertyDialog)
QualifyPath(szFile);
if (bLFNTest && lpmydta->my_dwAttrs & ATTR_LFN) {
return (LPSTR)TRUE;
}
CheckEscapes(szFile);
if (!bLFNTest) {
cch += lstrlen(szFile) + 1;
pT = (LPSTR)LocalReAlloc((HANDLE)p, cch, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (!pT)
goto GDSExit;
p = pT;
lstrcat(p, szFile);
}
if (iSelType)
goto GDSExit;
if (!bLFNTest)
lstrcat(p, szBlank);
}
GDSExit:
LocalFree(lpSelItems);
if (bLFNTest) {
if (pfDir) {
*pfDir = FALSE;
}
return NULL;
}
if (pfDir) {
*pfDir = bDir;
}
return p;
}
// compute the max extent of all the files in this DTA block
// and update the case to match (wTextAttribs & TA_LOWERCASE)
INT
GetMaxExtent(
HWND hwndLB,
HANDLE hDTA
)
{
LPMYDTA lpmydta;
HDC hdc;
INT nItems;
INT maxWidth = 0;
INT wWidth;
HFONT hOld;
CHAR szPath[MAXPATHLEN];
lpmydta = (LPMYDTA)LocalLock(hDTA);
nItems = (INT)lpmydta->my_nFileSizeLow;
hdc = GetDC(hwndLB);
hOld = SelectObject(hdc, hFont);
while (nItems-- > 0) {
lpmydta = GETDTAPTR(lpmydta, lpmydta->wSize);
lstrcpy(szPath, lpmydta->my_cFileName);
// set the case of the file names here!
if (!(lpmydta->my_dwAttrs & ATTR_LFN)) {
if (wTextAttribs & TA_LOWERCASE)
AnsiLower(szPath);
else
AnsiUpper(szPath);
}
MGetTextExtent(hdc, szPath, lstrlen(szPath), &wWidth, NULL);
maxWidth = max(wWidth, maxWidth);
}
if (hOld)
SelectObject(hdc, hOld);
ReleaseDC(hwndLB, hdc);
LocalUnlock(hDTA);
return maxWidth + 3; // pad it out
}
/*--------------------------------------------------------------------------*/
/* */
/* DirFindIndex() - */
/* */
/*--------------------------------------------------------------------------*/
INT
DirFindIndex(
HWND hwndLB,
HANDLE hDTA,
LPSTR szFile
)
{
register INT i;
INT nSel;
LPMYDTA lpmydta;
lpmydta = (LPMYDTA)LocalLock(hDTA);
nSel = (INT)lpmydta->my_nFileSizeLow;
for (i = 0; i < nSel; i++) {
SendMessage(hwndLB, LB_GETTEXT, (WORD)i, (LPARAM)&lpmydta);
if (!lstrcmpi(szFile, (LPSTR)lpmydta->my_cFileName))
goto DFIExit;
}
i = -1; // not found, return this
DFIExit:
LocalUnlock(hDTA);
return i;
}
/*--------------------------------------------------------------------------*/
/* */
/* DirGetAnchorFocus() - */
/* */
/*--------------------------------------------------------------------------*/
VOID
DirGetAnchorFocus(
register HWND hwndLB,
HANDLE hDTA,
LPSTR szAnchor,
LPSTR szCaret,
LPSTR szTopIndex
)
{
register INT iSel, iCount;
LPMYDTA lpmydta;
hDTA; // fix compiler warning
iSel = (INT)SendMessage(hwndLB, LB_GETANCHORINDEX, 0, 0L);
iCount = (INT)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
if (iCount == 1) {
SendMessage(hwndLB, LB_GETTEXT, (WORD)iSel, (LPARAM)&lpmydta);
if (!lpmydta) {
*szAnchor = 0L;
*szCaret = 0L;
*szTopIndex = 0L;
return;
}
}
if (iSel >= 0 && iSel < iCount) {
SendMessage(hwndLB, LB_GETTEXT, (WORD)iSel, (LPARAM)&lpmydta);
lstrcpy(szAnchor, (LPSTR)lpmydta->my_cFileName);
} else
*szAnchor = 0L;
iSel = (INT)SendMessage(hwndLB, LB_GETCARETINDEX, 0, 0L);
if (iSel >= 0 && iSel < iCount) {
SendMessage(hwndLB, LB_GETTEXT, (WORD)iSel, (LPARAM)&lpmydta);
lstrcpy(szCaret, (LPSTR)lpmydta->my_cFileName);
} else
*szCaret = 0L;
iSel = (WORD)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
if (iSel >= 0 && iSel < iCount) {
SendMessage(hwndLB, LB_GETTEXT, (WORD)iSel, (LPARAM)&lpmydta);
lstrcpy(szTopIndex, (LPSTR)lpmydta->my_cFileName);
} else
*szTopIndex = 0L;
}
/*--------------------------------------------------------------------------*/
/* */
/* SetSelection() - */
/* */
/*--------------------------------------------------------------------------*/
BOOL
SetSelection(
HWND hwndLB,
HANDLE hDTA,
LPSTR pSel
)
{
INT i;
CHAR szFile[MAXPATHLEN];
BOOL bDidSomething = FALSE;
while (pSel = GetNextFile(pSel, szFile, sizeof(szFile))) {
i = DirFindIndex(hwndLB, hDTA, (LPSTR)szFile);
if (i != -1) {
SendMessage(hwndLB, LB_SETSEL, TRUE, (DWORD)i);
bDidSomething = TRUE;
}
}
return bDidSomething;
}
/*** FIX30: Why do we use LONG buffer ptrs here? ***/
/*--------------------------------------------------------------------------*/
/* */
/* GetPict() - */
/* */
/*--------------------------------------------------------------------------*/
/* This gets the number of consecutive chrs of the same kind. This is used
* to parse the time picture. Returns 0 on error.
*/
INT
GetPict(
CHAR ch,
LPSTR szStr
)
{
register INT count;
count = 0;
while (ch == *szStr++)
count++;
return(count);
}
/*--------------------------------------------------------------------------*/
/* */
/* CreateDate() - */
/* */
/*--------------------------------------------------------------------------*/
/* This picks up the values in wValArray, converts them
* in a string containing the formatted date.
* wValArray should contain Month-Day-Year (in that order).
*/
INT
CreateDate(
WORD *wValArray,
LPSTR szOutStr
)
{
INT i;
INT cchPictPart;
WORD wDigit;
WORD wIndex;
WORD wTempVal;
register LPSTR pszPict;
register LPSTR pszInStr;
pszPict = szShortDate;
pszInStr = szOutStr;
for (i=0; i < 3; i++) {
cchPictPart = GetPict(*pszPict, pszPict);
switch (*pszPict) {
case 'M':
wIndex = 0;
goto CDDoIt;
case 'D':
wIndex = 1;
goto CDDoIt;
case 'Y':
wIndex = 2;
if (cchPictPart == 4) {
*pszInStr++ = '1';
*pszInStr++ = '9';
}
CDDoIt:
/* This assumes that the values are of two digits only. */
wTempVal = wValArray[wIndex];
wDigit = wTempVal / (WORD)10;
if (wDigit)
*pszInStr++ = (CHAR)(wDigit + '0');
else if (cchPictPart > 1)
*pszInStr++ = '0';
#if 0
else {
*pszInStr++ = ' ';
*pszInStr++ = ' ';
}
#endif
*pszInStr++ = (CHAR)((wTempVal % 10) + '0');
pszPict += cchPictPart;
/* Add the separator. */
if (*pszPict)
*pszInStr++ = *pszPict;
break;
}
pszPict++;
}
*pszInStr = 0L;
return(lstrlen(szOutStr));
}
/*--------------------------------------------------------------------------*/
/* */
/* CreateTime() - */
/* */
/*--------------------------------------------------------------------------*/
/* This picks up the values in wValArray, converts them
* in a string containing the formatted time.
* wValArray should contain Hour-Min-Sec (in that order).
*/
INT
CreateTime(
WORD * wValArray,
LPSTR szOutStr
)
{
INT i;
BOOL bAM;
WORD wHourMinSec;
register WORD wDigit;
register LPSTR pszInStr;
pszInStr = szOutStr;
wDigit = wValArray[0];
bAM = (wDigit < 12);
if (!iTime) {
if (wDigit >= 12)
wDigit -= 12;
if (!wDigit)
wDigit = 12;
}
wValArray[0] = wDigit;
for (i=0; i < 3; i++) {
wHourMinSec = wValArray[i];
/* This assumes that the values are of two digits only. */
wDigit = wHourMinSec / (WORD)10;
if (i > 0)
*pszInStr++ = (CHAR)(wDigit + '0');
else if (wDigit || iTLZero)
*pszInStr++ = (CHAR)(wDigit + '0');
#if 0
else {
/* NOTE: 2 blanks is the same width as one digit. */
// wrong!
*pszInStr++ = ' ';
*pszInStr++ = ' ';
}
#endif
*pszInStr++ = (CHAR)((wHourMinSec % 10) + '0');
if (i < 2)
*pszInStr++ = *szTime; /* Assumes time sep. is 1 char long */
}
// *pszInStr++ = ' ';
if (bAM)
lstrcpy(pszInStr, sz1159);
else
lstrcpy(pszInStr, sz2359);
return lstrlen(szOutStr);
}
/*--------------------------------------------------------------------------*/
/* */
/* PutSize() - */
/* */
/*--------------------------------------------------------------------------*/
INT
APIENTRY
PutSize(
DWORD dwSize,
LPSTR szOutStr
)
{
// LPSTR szStr;
// int cBlanks;
// char szTemp[30];
// Convert it into string
return wsprintf(szOutStr, "%lu", dwSize);
}
/*--------------------------------------------------------------------------*/
/* */
/* PutDate() - */
/* */
/*--------------------------------------------------------------------------*/
INT
APIENTRY
PutDate(
LPFILETIME lpftDate,
LPSTR szStr
)
{
WORD wValArray[3];
WORD wDate, wTime;
if (FileTimeToDosDateTime(lpftDate, &wDate, &wTime)) {
wValArray[0] = (WORD)((wDate & MONTHMASK) >> 5); /* Month */
wValArray[1] = (WORD)((wDate & DATEMASK)); /* Date */
wValArray[2] = (WORD)((wDate >> 9) + 80); /* Year */
return(CreateDate((WORD *)wValArray, szStr));
} else {
return 0;
}
}
/*--------------------------------------------------------------------------*/
/* */
/* PutTime() - */
/* */
/*--------------------------------------------------------------------------*/
INT
APIENTRY
PutTime(
LPFILETIME lpftTime,
LPSTR szStr
)
{
WORD wValArray[3];
WORD wDate, wTime;
if (FileTimeToDosDateTime(lpftTime, &wDate, &wTime)) {
wValArray[0] = (wTime >> 0x0B);
wValArray[1] = (WORD)((wTime & MINUTEMASK) >> 5);
wValArray[2] = (WORD)((wTime & SECONDSMASK) << 1);
return(CreateTime((WORD *)wValArray, szStr));
} else {
return 0;
}
}
/*--------------------------------------------------------------------------*/
/* */
/* PutAttributes() - */
/* */
/*--------------------------------------------------------------------------*/
INT
APIENTRY
PutAttributes(
register DWORD dwAttribute,
register LPSTR pszStr
)
{
WORD i;
INT cch = 0;
for (i=0; i < 4; i++) {
if (dwAttribute & 1) { // BUG hardcoded.
*pszStr++ = szAttr[i];
cch++;
} else {
#if 0
*pszStr++ = '-';
*pszStr++ = '-';
cch += 2;
#endif
}
if (i == 2)
dwAttribute >>= 3; /* Skip next two bits */
else
dwAttribute >>= 1; /* Goto next bit */
}
*pszStr = 0;
return(cch);
}
/*--------------------------------------------------------------------------*/
/* */
/* CreateLBLine() - */
/* */
/*--------------------------------------------------------------------------*/
/* This creates a character string that contains all the required
* details of a file; (Name, Size, Date, Time, Attr)
*/
VOID
CreateLBLine(
register WORD wLineFormat,
LPMYDTA lpmydta,
LPSTR szBuffer
)
{
register LPSTR pch;
DWORD dwAttr;
pch = szBuffer;
dwAttr = lpmydta->my_dwAttrs;
/* Copy the file name. */
lstrcpy(pch, lpmydta->my_cFileName);
pch += lstrlen(pch);
*pch = 0L;
/* Should we show the size? */
if (wLineFormat & VIEW_SIZE) {
*pch++ = TABCHAR;
if (!(dwAttr & ATTR_DIR))
pch += PutSize(lpmydta->my_nFileSizeLow, pch);
else
*pch = 0;
}
/* Should we show the date? */
if (wLineFormat & VIEW_DATE) {
*pch++ = TABCHAR;
pch += PutDate(&lpmydta->my_ftLastWriteTime, pch);
}
/* Should we show the time? */
if (wLineFormat & VIEW_TIME) {
*pch++ = TABCHAR;
pch += PutTime(&lpmydta->my_ftLastWriteTime, pch);
}
/* Should we show the attributes? */
if (wLineFormat & VIEW_FLAGS) {
*pch++ = TABCHAR;
pch += PutAttributes(dwAttr, pch);
}
// *pch = 0L;
}
/*--------------------------------------------------------------------------*/
/* */
/* CompareDTA() - */
/* */
/*--------------------------------------------------------------------------*/
INT
CompareDTA(
register LPMYDTA lpItem1,
LPMYDTA lpItem2,
WORD wSort
)
{
register INT ret;
if (lpItem1->my_dwAttrs & ATTR_PARENT) {
ret = -1;
goto CDDone;
}
if (lpItem2->my_dwAttrs & ATTR_PARENT) {
ret = 1;
goto CDDone;
}
if ((lpItem1->my_dwAttrs & ATTR_DIR) > (lpItem2->my_dwAttrs & ATTR_DIR)) {
ret = -1;
goto CDDone;
} else if ((lpItem1->my_dwAttrs & ATTR_DIR) < (lpItem2->my_dwAttrs & ATTR_DIR)) {
ret = 1;
goto CDDone;
}
switch (wSort) {
case IDD_TYPE:
{
LPSTR ptr1;
LPSTR ptr2;
// BUG: should use strrchr for long file names.
for (ptr1 = lpItem1->my_cFileName; *ptr1 && *ptr1 != '.'; ptr1++)
;
for (ptr2 = lpItem2->my_cFileName; *ptr2 && *ptr2 != '.'; ptr2++)
;
ret = lstrcmpi(ptr1, ptr2);
if (ret == 0)
goto CompareNames;
break;
}
case IDD_SIZE:
if (lpItem1->my_nFileSizeLow > lpItem2->my_nFileSizeLow)
ret = -1;
else if (lpItem1->my_nFileSizeLow < lpItem2->my_nFileSizeLow)
ret = 1;
else
goto CompareNames;
break;
case IDD_DATE:
{
DWORD d1High, d1Low;
DWORD d2High, d2Low;
d1High = lpItem1->my_ftLastWriteTime.dwHighDateTime;
d2High = lpItem2->my_ftLastWriteTime.dwHighDateTime;
if (d1High > d2High) {
ret = -1;
} else if (d1High < d2High) {
ret = 1;
} else {
d1Low = lpItem1->my_ftLastWriteTime.dwLowDateTime;
d2Low = lpItem2->my_ftLastWriteTime.dwLowDateTime;
if (d1Low > d2Low)
ret = -1;
else if (d1Low < d2Low)
ret = 1;
else
goto CompareNames;
}
break;
}
case IDD_NAME:
CompareNames:
ret = lstrcmpi(lpItem1->my_cFileName, lpItem2->my_cFileName);
break;
}
CDDone:
return ret;
}
// load the status buffers with the appropriate stuff and invalidates
// the status area causing it to repaint.
VOID
APIENTRY
UpdateStatus(
HWND hWnd
)
{
CHAR szTemp[128];
WCHAR szNumBuf1[40];
WCHAR szNumBuf2[40];
WORD wDrive;
HWND hwndDir;
RECT rc;
if (!bStatusBar)
return;
if (hWnd != (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L))
return;
hwndDir = HasDirWindow(hWnd);
szStatusTree[0] = 0L;
if (hwndDir)
GetDirStatus(hwndDir, szStatusTree, szStatusDir);
else
szStatusDir[0] = 0L;
// force the status area to update
GetClientRect(hwndFrame, &rc);
rc.top = rc.bottom - dyStatus;
InvalidateRect(hwndFrame, &rc, FALSE);
}
HWND
GetDirSelData(
HWND hWnd,
DWORD *pdwSelSize,
INT *piSelCount,
DWORD *pdwTotalSize,
INT *piTotalCount
)
{
INT i;
LPMYDTA lpmydta;
HWND hwndLB;
INT countSel, countTotal;
LPINT lpSelItems, lpSelItemsT;
HANDLE hDTA;
if (!(hwndLB = GetDlgItem(hWnd, IDCW_LISTBOX))) { // fast scroll
return NULL;
}
*pdwSelSize = *pdwTotalSize = 0L;
*piSelCount = *piTotalCount = 0;
countSel = (INT)SendMessage(hwndLB, LB_GETSELCOUNT, 0, 0L);
lpSelItems = LocalAlloc(LMEM_FIXED, sizeof(INT) * countSel);
if (lpSelItems == NULL)
return NULL;
countSel = (INT)SendMessage(hwndLB, LB_GETSELITEMS, (WPARAM)countSel, (LPARAM)lpSelItems);
hDTA = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTA);
if (hDTA == NULL)
return NULL;
lpmydta = (LPMYDTA)LocalLock(hDTA);
countTotal = (INT)lpmydta->my_nFileSizeLow;
lpSelItemsT = lpSelItems;
for (i = 0; i < countTotal; i++) {
lpmydta = GETDTAPTR(lpmydta, lpmydta->wSize);
if (lpmydta->my_dwAttrs & ATTR_PARENT)
continue;
if (countSel && *lpSelItems == lpmydta->nIndex) {
(*piSelCount)++;
*pdwSelSize += lpmydta->my_nFileSizeLow;
countSel--;
lpSelItems++;
}
(*piTotalCount)++;
*pdwTotalSize += lpmydta->my_nFileSizeLow;
}
LocalUnlock(hDTA);
LocalFree(lpSelItemsT);
return hwndLB;
}
VOID
GetDirStatus(
HWND hWnd,
LPSTR szMessage1,
LPSTR szMessage2
)
{
INT iSelCount, iCount;
DWORD dwSelSize, dwSize;
CHAR szNumBuf[40];
HWND hwndLB;
szMessage2[0] = 0;
hwndLB = GetDirSelData(hWnd, &dwSelSize, &iSelCount, &dwSize, &iCount);
if (LoadString(hAppInstance, IDS_STATUSMSG, szMessage, sizeof(szMessage)))
wsprintf(szMessage2, szMessage, iCount);
if ((HWND)GetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS) == hwndLB) {
if (LoadString(hAppInstance, IDS_STATUSMSG2, szMessage, sizeof(szMessage)))
wsprintf(szMessage1, szMessage, iSelCount);
}
}
// given a descendant of an MDI child (or an MDI child) return
// the MDI child in the descendant chain. returns NULL if not
// found.
HWND
APIENTRY
GetMDIChildFromDecendant(
HWND hwnd
)
{
HWND hwndT;
while (hwnd && ((hwndT = GetParent(hwnd)) != hwndMDIClient))
hwnd = hwndT;
return hwnd;
}
// setup the defTabStops[] array for subsequent TabbedTextOut() calls.
//
// in:
// iMaxWidthFileName the largest dx width of files to be
// displayed
//
// returns:
// total extent of the "File Details" view. used to
// set scroll extents
INT
APIENTRY
FixTabsAndThings(
HWND hwndLB,
WORD *pwTabs,
INT iMaxWidthFileName,
WORD wViewOpts
)
{
INT i;
HDC hdc;
HFONT hOld;
CHAR szBuf[30];
INT ixExtent = 0;
i = iMaxWidthFileName; // the widest filename
if (pwTabs == NULL)
return i;
hdc = GetDC(NULL);
hOld = SelectObject(hdc, hFont);
// max size digits field
if (wViewOpts & VIEW_SIZE) {
MGetTextExtent(hdc, "99999999", 8, &ixExtent, NULL);
i += ixExtent + dxText;
*pwTabs++ = (WORD)i; // Size
}
if (wViewOpts & VIEW_DATE) {
FILETIME filetime;
DosDateTimeToFileTime((WORD)((19 << 9) | (12 << 5) | 30), (WORD)0xFFFF, &filetime);
PutDate(&filetime, szBuf);
// max date digits
MGetTextExtent(hdc, szBuf, lstrlen(szBuf), &ixExtent, NULL);
i += ixExtent + dxText;
*pwTabs++ = (WORD)i; // Date
}
// max time digits
if (wViewOpts & VIEW_TIME) {
FILETIME filetime;
DosDateTimeToFileTime((WORD)((19 << 9) | (12 << 5) | 30), (WORD)0xFFFF, &filetime);
PutTime(&filetime, szBuf);
MGetTextExtent(hdc, szBuf, lstrlen(szBuf), &ixExtent, NULL);
i += ixExtent + dxText;
*pwTabs++ = (WORD)i; // Time
}
// max attris digits
if (wViewOpts & VIEW_FLAGS) {
PutAttributes(ATTR_ALL, szBuf);
MGetTextExtent(hdc, szBuf, lstrlen(szBuf), &ixExtent, NULL);
i += ixExtent + dxText;
*pwTabs++ = (WORD)i; // Attributes
}
if (hOld)
SelectObject(hdc, hOld);
ReleaseDC(NULL, hdc);
SendMessage(hwndLB, LB_SETHORIZONTALEXTENT,
i + dxFolder + 4 * dyBorderx2, 0L);
return i; // total extent
}
// sets the font and adjusts the dimension parameters for the
// new font
//
// in:
// hWnd hwnd of a dir window
// hwndLB and it's listbox
// hFont the font to set
//
// uses:
// dyFileName GLOBAL; set based on new font height
// GWL_VIEW window word of hWnd for either full or name view
// GWL_HDTA to compute the max extent given the new font
//
// sets:
// Listbox tabs array
// LB_SETCOLUMNWIDTH
// or
// LB_SETHORIZONTALEXTENT
VOID
APIENTRY
SetLBFont(
HWND hWnd,
HWND hwndLB,
HANDLE hNewFont
)
{
INT dxMaxExtent;
HANDLE hDTA;
WORD wViewFlags = (WORD)GetWindowLong(GetParent(hWnd), GWL_VIEW);
SendMessage(hwndLB, WM_SETFONT, (WPARAM)hNewFont, 0L);
// this is needed when changing the font. when creating
// the return from WM_MEASUREITEM will set the cell height
SendMessage(hwndLB, LB_SETITEMHEIGHT, 0, (LONG)dyFileName);
hDTA = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTA);
dxMaxExtent = (INT)GetMaxExtent(hwndLB, hDTA);
// if we are in name only view we change the width
if ((VIEW_EVERYTHING & wViewFlags) == VIEW_NAMEONLY) {
SendMessage(hwndLB, LB_SETCOLUMNWIDTH, dxMaxExtent + dxFolder + dyBorderx2, 0L);
} else {
FixTabsAndThings(hwndLB,(WORD *)GetWindowLongPtr(hWnd, GWLP_TABARRAY),
dxMaxExtent, wViewFlags);
}
}
VOID
APIENTRY
UpdateSelection(
HWND hwndLB
)
{
INT count, i;
RECT rc;
count = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
for (i=0; i < count; i++) {
if ((BOOL)SendMessage(hwndLB, LB_GETSEL, i, 0L)) {
SendMessage(hwndLB, LB_GETITEMRECT, i, (LPARAM)&rc);
InvalidateRect(hwndLB, &rc, TRUE);
}
}
}
LONG
CreateFSCChangeDisplayMess(
HWND hWnd,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
{
CHAR szCaret[MAXFILENAMELEN+1];
CHAR szAnchor[MAXFILENAMELEN+1];
CHAR szTopIndex[MAXFILENAMELEN+1];
CHAR szPath[256];
HCURSOR hCursor;
HWND hwndLB, hwndT;
HANDLE hDTA;
LPMYDTA lpmydta;
DWORD ws;
LPSTR pSel;
INT iSel, iTop=0;
RECT rc;
BOOL bResetFocus;
WORD *pwTabs;
hwndLB = GetDlgItem(hWnd, IDCW_LISTBOX);
switch (wMsg) {
case WM_FILESYSCHANGE:
if (cDisableFSC) {
// I need to be updated
SetWindowLong(GetParent(hWnd), GWL_FSCFLAG, TRUE);
break;
}
wParam = CD_PATH;
lParam = 0L;
/*** FALL THRU ***/
case FS_CHANGEDISPLAY:
// We dont want to reset the flag, if the operation is not CD_PATH.
// This is because, only the operation CD_PATH implies a true
// refresh. The operations CD_VEIW and CD_SORT are not refresh
// operations. They merely reformat the existing contents of a dir
// window. The flag is now reset in 'case CD_PATH:'.
//SetWindowLong(GetParent(hWnd), GWL_FSCFLAG, FALSE);
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
pSel = NULL; // init this
bResetFocus = (GetFocus() == hwndLB);
hDTA = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTA);
switch (wParam) {
case CD_SORT:
// change the sort order of the listbox
// we want to save the current selection and things here
// and restore them once the listbox has been rebuilt
// But first, save a list of the selected items FIX31
pSel = (LPSTR)DirGetSelection(hWnd, hwndLB, 0, NULL);
DirGetAnchorFocus(hwndLB, hDTA, szAnchor, szCaret, szTopIndex);
iTop = (INT)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
SetWindowLong(GetParent(hWnd), GWL_SORT, LOWORD(lParam));
SendMessage(hwndLB, LB_RESETCONTENT, 0, 0L);
SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);
FillDirList(hwndLB, hDTA);
goto ResetSelection;
case CD_VIEW:
{
WORD wCurView;
// change the view type (name only, vs full details)
// Warning! Convoluted Code! We want to destroy the
// listbox only if we are going between Name Only view
// and Details view.
wNewView = LOWORD(lParam);
wCurView = (WORD)GetWindowLong(GetParent(hWnd), GWL_VIEW);
if (wNewView == wCurView)
break; // NOP
// special case the long and partial view change
// this doesn't require us to recreate the listbox
if ((VIEW_EVERYTHING & wNewView) && (VIEW_EVERYTHING & wCurView)) {
SetWindowLong(GetParent(hWnd), GWL_VIEW, wNewView);
FixTabsAndThings(hwndLB,(WORD *)GetWindowLongPtr(hWnd, GWLP_TABARRAY),
GetMaxExtent(hwndLB, hDTA), wNewView);
InvalidateRect(hwndLB, NULL, TRUE);
break;
}
/* Things are a changing radically. Destroy the listbox. */
// But first, save a list of the selected items
pSel = (LPSTR)DirGetSelection(hWnd, hwndLB, 0, NULL);
DirGetAnchorFocus(hwndLB, hDTA, szAnchor, szCaret, szTopIndex);
iTop = (INT)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
lstrcpy(szTopIndex, szCaret);
if ((HWND)GetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS) == hwndLB)
SetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS, 0L);
DestroyWindow(hwndLB);
/* Create a new one (preserving the Sort setting). */
wNewSort = (WORD)GetWindowLong(GetParent(hWnd), GWL_SORT);
dwNewAttribs = (DWORD)GetWindowLong(GetParent(hWnd), GWL_ATTRIBS);
goto CreateLB;
}
case CD_PATH | CD_ALLOWABORT:
case CD_PATH:
case CD_PATH_FORCE:
// bad things happens if we change the path
// while we are reading the tree. bounch this
// in that case. this causes the steal data
// code in the tree to barf because we would
// free the hDTA while it is being traversed
// (very bad thing)
// we set the GWL_FSCFLAG to true, if we could not refresh.
// else we set it to FALSE. However if the flag was previously
// TRUE we set lParam to NULL. lParam = NULL implies 'forced'
// refresh.
hwndT = HasTreeWindow(GetParent(hWnd));
if (hwndT && GetWindowLong(hwndT, GWL_READLEVEL)) {
SetWindowLong(GetParent(hWnd), GWL_FSCFLAG, TRUE);
break;
} else {
if (SetWindowLong(GetParent(hWnd), GWL_FSCFLAG, FALSE))
lParam = 0L;
}
// change the path of the current directory window (basically
// recreate the whole thing)
// if lParam == NULL this is a refresh, otherwise
// check for short circut case to avoid rereading
// the directory
GetMDIWindowText(GetParent(hWnd), szPath, sizeof(szPath));
if (lParam) {
// get out early if this is a NOP
if ((wParam != CD_PATH_FORCE) &&
!lstrcmpi(szPath, (LPSTR)lParam))
break;
lstrcpy(szPath, (LPSTR)lParam);
iLastSel = -1; // invalidate the last selection
}
// if this is a refresh save the current selection, anchor stuff, etc
if (!lParam) {
pSel = (LPSTR)DirGetSelection(hWnd, hwndLB, 0, NULL);
iTop = (INT)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
DirGetAnchorFocus(hwndLB, hDTA, szAnchor, szCaret, szTopIndex);
}
// Create a new one (preserving the Sort setting)
wNewSort = (WORD)GetWindowLong(GetParent(hWnd), GWL_SORT);
wNewView = (WORD)GetWindowLong(GetParent(hWnd), GWL_VIEW);
dwNewAttribs = GetWindowLong(GetParent(hWnd), GWL_ATTRIBS);
if (hDTA) { // fast scroll case
LocalFree(hDTA);
hDTA = NULL;
SendMessage(hwndLB, LB_RESETCONTENT, 0, 0L);
}
goto CreateNewPath;
}
SetCursor(hCursor);
ShowCursor(FALSE);
break;
case WM_CREATE:
TRACE(BF_WM_CREATE, "CreateFSCChangeDisplayMess - WM_CREATE");
// wNewView, wNewSort and dwNewAddribs define the viewing
// parameters of the new window (GLOBALS)
// the window text of the parent window defines the
// filespec and the directory to open up
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
wParam = 0; // don't allow abort in CreateDTABlock()
lParam = 1L; // allow DTA steal optimization
pSel = NULL; // no selection to restore
bResetFocus = FALSE; // no focus to restore
// get the dir to open from our parent window text
GetMDIWindowText(GetParent(hWnd), szPath, sizeof(szPath));
if ((pwTabs = (WORD *)LocalAlloc(LPTR,sizeof(WORD) * 4)) == NULL)
return -1L;
SetWindowLongPtr(hWnd, GWLP_TABARRAY, (ULONG_PTR)pwTabs);
CreateNewPath:
// at this point szPath has the directory to read. this
// either came from the WM_CREATE case or the
// FS_CHANGEDISPLAY (CD_PATH) directory reset
#ifdef DEBUG
{
char buf[80];
wsprintf(buf, "attribs %4.4X\r\n", dwNewAttribs);
OutputDebugString(buf);
}
#endif
if (!dwNewAttribs)
dwNewAttribs = ATTR_DEFAULT;
hDTA = CreateDTABlock(hWnd, szPath, dwNewAttribs, wParam & CD_ALLOWABORT ? TRUE : FALSE, lParam == 0L);
// check for user abort (fast scroll case)
if (hDTA == (HANDLE)-1) {
SetWindowLongPtr(hWnd, GWLP_HDTA, 0L);
goto FastScrollExit;
}
// for the FS_CHANGEDISPLAY case we set this now, to avoid
// multiple title repaints when the user is fast scrolling
if (wMsg != WM_CREATE)
SetMDIWindowText(GetParent(hWnd), szPath);
SetWindowLongPtr(hWnd, GWLP_HDTA, (LONG_PTR)hDTA);
if (!hDTA)
goto CDAbort;
if (wMsg != WM_CREATE)
goto SkipWindowCreate;
CreateLB:
if ((wNewView & VIEW_EVERYTHING) == VIEW_NAMEONLY)
ws = WS_DIRSTYLE | LBS_MULTICOLUMN | WS_HSCROLL | WS_VISIBLE | WS_BORDER | LBS_DISABLENOSCROLL;
else
ws = WS_DIRSTYLE | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE | WS_BORDER | LBS_DISABLENOSCROLL;
GetClientRect(hWnd, &rc);
// the border stuff is for the non initial create case
// I don't know why
hwndLB = CreateWindowEx(0L, szListbox, NULL, ws,
dyBorder, dyBorder,
rc.right - 2*dyBorder, rc.bottom - 2*dyBorder,
hWnd, (HMENU)IDCW_LISTBOX,
hAppInstance, NULL);
if (!hwndLB) {
if (hDTA)
LocalFree(hDTA);
if (wMsg != WM_CREATE)
SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
CDAbort:
ShowCursor(FALSE);
SetCursor(hCursor);
return -1L;
}
// set all the view/sort/include parameters here
SetWindowLong(GetParent(hWnd), GWL_VIEW, wNewView);
SetWindowLong(GetParent(hWnd), GWL_SORT, wNewSort);
SetWindowLong(GetParent(hWnd), GWL_ATTRIBS, dwNewAttribs);
// restore the last focus stuff if we are recreating here
if (!GetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS))
SetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS, (LONG_PTR)hwndLB);
// set the font and dimensions here
SkipWindowCreate:
SetLBFont(hWnd, hwndLB, hFont);
SendMessage(hwndLB, WM_SETREDRAW, FALSE, 0L);
FillDirList(hwndLB, hDTA);
if (pSel) {
BOOL bDidSomething;
ResetSelection:
/* Give the selected item the focus rect and anchor pt. */
bDidSomething = SetSelection(hwndLB, hDTA, pSel);
LocalFree((HANDLE)pSel);
if (!bDidSomething)
goto SelectFirst;
iSel = DirFindIndex(hwndLB, hDTA, szTopIndex);
if (iSel == -1)
iSel = 0;
SendMessage(hwndLB, LB_SETTOPINDEX, iSel, 0L);
iSel = DirFindIndex(hwndLB, hDTA, szAnchor);
if (iSel == -1)
iSel = 0;
SendMessage(hwndLB, LB_SETANCHORINDEX, iSel, 0L);
iSel = DirFindIndex(hwndLB, hDTA, szCaret);
if (iSel == -1)
iSel = 0;
/* SETCARETINDEX will scroll item into view */
SendMessage(hwndLB, LB_SETCARETINDEX, iSel, 0L);
} else {
INT iLBCount;
SelectFirst:
iLBCount = (INT)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
if (iLastSel != -1 && (iLastSel <= iLBCount)) {
iSel = iLastSel;
// check the case of the last item being deleted
if (iSel == iLBCount)
iSel--;
SendMessage(hwndLB, LB_SETSEL, TRUE, (DWORD)iSel);
} else {
// Select the first non-directory item
iSel = 0;
while (iSel < iLBCount) {
SendMessage(hwndLB, LB_GETTEXT, iSel, (LPARAM)&lpmydta);
if (!lpmydta)
break;
if (!(lpmydta->my_dwAttrs & ATTR_PARENT)) {
iTop = iSel;
break;
}
iSel++;
}
LocalUnlock(hDTA);
if (iSel == iLBCount)
iSel = 0;
}
SendMessage(hwndLB, LB_SETTOPINDEX, iTop, 0L);
// and select this item if no tree window
if (!HasTreeWindow(GetParent(hWnd)))
SendMessage(hwndLB, LB_SETSEL, TRUE, (DWORD)iSel);
SendMessage(hwndLB, LB_SETANCHORINDEX, iSel, 0L);
/* SETCARETINDEX will scroll item into view */
SendMessage(hwndLB, LB_SETCARETINDEX, iSel, 0L);
}
if (bResetFocus)
if (SetDirFocus(hWnd))
SetFocus(hWnd);
SendMessage(hwndLB, WM_SETREDRAW, TRUE, 0L);
InvalidateRect(hwndLB, NULL, TRUE);
lFreeSpace = -1; // force status update
UpdateStatus(GetParent(hWnd));
FastScrollExit:
ShowCursor(FALSE);
SetCursor(hCursor);
break;
}
return 0L;
}
INT_PTR
APIENTRY
DirWndProc(
HWND hWnd,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
{
INT iSel, i;
LPSTR pSel;
HWND hwndLB;
HANDLE hDTA;
LPMYDTA lpmydta;
CHAR szTemp[MAXPATHLEN] = {0};
CHAR szSourceFile[MAXPATHLEN];
static HWND hwndOwnerDraw = NULL;
STKCHK();
/* Here we generate OWNERDRAWBEGIN and OWNERDRAWEND messages
* to speed up the painting operations. We do the expensive stuff
* at the beginning instead of on every DRAWITEM message.
*/
if (hwndOwnerDraw == hWnd && wMsg != WM_DRAWITEM) {
hwndOwnerDraw = NULL;
SendMessage(hWnd, WM_OWNERDRAWEND, 0, 0L);
} else if (wMsg == WM_DRAWITEM && hwndOwnerDraw != hWnd) {
SendMessage(hWnd, WM_OWNERDRAWBEGIN, wParam, lParam);
hwndOwnerDraw = hWnd;
}
hwndLB = GetDlgItem(hWnd, IDCW_LISTBOX);
switch (wMsg) {
// returns in lParam upper case ANSI directory string with
// a trailing backslash. if you want to do a SetCurrentDirecotor()
// you must first StripBackslash() the thing!
case FS_GETDIRECTORY:
MSG("DirWndProc", "FS_GETDIRECTORY");
GetMDIWindowText(GetParent(hWnd), (LPSTR)lParam, (INT)wParam); // get the string
StripFilespec((LPSTR)lParam); // Remove the trailing extention
AddBackslash((LPSTR)lParam); // terminate with a backslash
//AnsiUpper((LPSTR)lParam); // and upper case
break;
case FS_GETDRIVE:
MSG("DirWndProc", "FS_GETDRIVE");
// Returns the letter of the corresponding directory
GetWindowText(GetParent(hWnd), szTemp, sizeof(szTemp));
AnsiUpper(szTemp);
return szTemp[0]; // first character
case FS_GETFILESPEC:
MSG("DirWndProc", "FS_GETFILESPEC");
// returns the current filespec (from View.Include...). this is
// an uppercase ANSI string
GetMDIWindowText(GetParent(hWnd), (LPSTR)lParam, (INT)wParam);
StripPath((LPSTR)lParam);
//AnsiUpper((LPSTR)lParam); // and upper case
break;
case FS_SETSELECTION:
MSG("DirWndProc", "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, FALSE);
SendMessage(hwndLB, WM_SETREDRAW, TRUE, 0L);
InvalidateRect(hwndLB, NULL, TRUE);
break;
case FS_GETSELECTION:
// return = pszDir
#define pfDir (BOOL *)lParam
#define fSingleSel (BOOL)wParam
MSG("DirWndProc", "FS_GETSELECTION");
return (INT_PTR)DirGetSelection(hWnd, hwndLB, fSingleSel, pfDir);
#undef pfDir
#undef fSingleSel
case WM_CREATE:
case WM_FILESYSCHANGE:
case FS_CHANGEDISPLAY:
TRACE(BF_WM_CREATE, "DirWndProc - WM_CREATE");
return CreateFSCChangeDisplayMess(hWnd, wMsg, wParam, lParam);
case WM_DESTROY:
MSG("DirWndProc", "WM_DESTROY");
{
HANDLE hMem;
HWND hwnd;
if (hwndLB == GetFocus())
if (hwnd = HasTreeWindow(GetParent(hWnd)))
SetFocus(hwnd);
if (hMem = (HANDLE)GetWindowLongPtr(hWnd, GWLP_TABARRAY))
LocalFree(hMem);
}
break;
case WM_CHARTOITEM:
MSG("DirWndProc", "WM_CHARTOITEM");
{
WORD i, j;
WORD cItems;
CHAR ch[2];
if ((ch[0] = GET_WM_CHARTOITEM_CHAR(wParam, lParam)) <= ' ')
return(-1L);
i = GET_WM_CHARTOITEM_POS(wParam, lParam);
cItems = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
szTemp[1] = 0L;
ch[0] &= 255;
ch[1] = '\0';
for (j=1; j <= cItems; j++) {
SendMessage(hwndLB, LB_GETTEXT, (i + j) % cItems, (LPARAM)&lpmydta);
szTemp[0] = lpmydta->my_cFileName[0];
/* Do it this way to be case insensitive. */
if (!lstrcmpi((LPSTR)ch, szTemp))
break;
}
if (j > cItems)
return -2L;
return(MAKELONG((i + j) % cItems, 0));
}
case WM_COMPAREITEM:
MSG("DirWndProc", "WM_COMPAREITEM");
{
#define lpci ((LPCOMPAREITEMSTRUCT)lParam)
return (LONG)CompareDTA((LPMYDTA)lpci->itemData1,
(LPMYDTA)lpci->itemData2,
(WORD)GetWindowLong(GetParent(hWnd), GWL_SORT));
}
case WM_NCDESTROY:
MSG("DirWndProc", "WM_NCDESTROY");
if (hDTA = (HANDLE)GetWindowLongPtr(hWnd, GWLP_HDTA)) {
LocalFree(hDTA);
}
break;
case WM_DRAGLOOP:
MSG("DirWndProc", "WM_DRAGDROP");
/* 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, FALSE);
break;
case WM_DRAGSELECT:
MSG("DirWndProc", "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, FALSE);
break;
case WM_DRAGMOVE:
MSG("DirWndProc", "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, FALSE);
/* Select the new one. */
iSelHilite = iSel;
DSRectItem(hwndLB, iSel, TRUE, FALSE);
break;
case WM_OWNERDRAWBEGIN:
#define lpLBItem ((LPDRAWITEMSTRUCT)lParam)
MSG("DirWndProc", "WM_OWNERDRAWBEGIN");
/* Set the default bk and text colors. */
SetTextColor(lpLBItem->hDC, GetSysColor(COLOR_WINDOWTEXT));
SetBkColor(lpLBItem->hDC, GetSysColor(COLOR_WINDOW));
#undef lpLBItem
break;
case WM_OWNERDRAWEND:
MSG("DirWndProc", "WM_OWNERDRAWEND");
break;
case WM_DRAWITEM:
#define lpLBItem ((LPDRAWITEMSTRUCT)lParam)
MSG("DirWndProc", "WM_DRAWITEM");
{
WORD wViewFlags;
LPMYDTA lpmydta;
/* Don't do anything to empty listboxes. */
if (lpLBItem->itemID == -1)
break;
if (lpLBItem->itemData == (DWORD)0) {
LoadString(hAppInstance, IDS_NOFILES, szTemp, sizeof(szTemp));
TextOut(lpLBItem->hDC,
lpLBItem->rcItem.left,
lpLBItem->rcItem.top,
szTemp, lstrlen(szTemp));
} else {
lpmydta = (LPMYDTA)lpLBItem->itemData;
wViewFlags = (WORD)GetWindowLong(GetParent(hWnd), GWL_VIEW);
if (wViewFlags & VIEW_EVERYTHING) {
// if any of the wViewFlags bits set, we are in slow mode
CreateLBLine(wViewFlags, lpmydta, szTemp);
DrawItem(lpLBItem, szTemp, lpmydta->my_dwAttrs, (HWND)GetFocus()==lpLBItem->hwndItem,
(WORD *)GetWindowLongPtr(hWnd, GWLP_TABARRAY));
} else
DrawItemFast(hWnd, lpLBItem, lpmydta,
(HWND)GetFocus()==lpLBItem->hwndItem);
}
}
#undef lpLBItem
break;
case WM_DROPOBJECT:
MSG("DirWndProc", "WM_DROPOBJECT");
{
WORD ret;
LPSTR pFrom;
DWORD dwAttrib = 0; // init this to not a dir
WORD iSelSink;
#define lpds ((LPDROPSTRUCT)lParam)
// Do nothing - but remove selection rectangle
DSRectItem(hwndLB, iSelHilite, FALSE, FALSE);
return(TRUE);
/* 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
*/
// this is the listbox index of the destination
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;
}
// set the destination, assume move/copy case below (c:\foo\)
SendMessage(hWnd, FS_GETDIRECTORY, sizeof(szTemp), (LPARAM)szTemp);
// Are we dropping on a unused portion of some listbox?
if (iSelSink == 0xFFFF)
goto NormalMoveCopy;
// check for drop on a directory
SendMessage(hwndLB, LB_GETTEXT, iSelSink, (LPARAM)&lpmydta);
lstrcpy(szSourceFile, lpmydta->my_cFileName);
dwAttrib = lpmydta->my_dwAttrs;
if (dwAttrib & ATTR_DIR) {
if (dwAttrib & ATTR_PARENT) { // special case the parent
StripBackslash(szTemp);
StripFilespec(szTemp);
} else {
lstrcat(szTemp, szSourceFile);
}
goto DirMoveCopy;
}
// dropping on a program?
if (!IsProgramFile(szSourceFile))
goto NormalMoveCopy; // no, normal stuff
// directory drop on a file? this is a NOP
if (lpds->wFmt == DOF_DIRECTORY) {
DSRectItem(hwndLB, iSelHilite, FALSE, FALSE);
break;
}
// We're dropping a file onto a program.
// Exec the program using the source file as the parameter.
// set the directory to that of the program to exec
SendMessage(hWnd, FS_GETDIRECTORY, sizeof(szTemp), (LPARAM)szTemp);
StripBackslash(szTemp);
FixAnsiPathForDos(szTemp);
SheChangeDir(szTemp);
// get the selected file
pSel = (LPSTR)SendMessage(lpds->hwndSource, FS_GETSELECTION, TRUE, 0L);
if (lstrlen(pSel) > MAXPATHLEN) // don't blow up below!
goto DODone;
if (bConfirmMouse) {
LoadString(hAppInstance, IDS_MOUSECONFIRM, szTitle, sizeof(szTitle));
LoadString(hAppInstance, IDS_EXECMOUSECONFIRM, szTemp, sizeof(szTemp));
wsprintf(szMessage, szTemp, (LPSTR)szSourceFile, (LPSTR)pSel);
if (MessageBox(hwndFrame, szMessage, szTitle, MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
goto DODone;
}
// create an absolute path to the argument (search window alaready
// is absolute)
if (lpds->hwndSource == hwndSearch) {
szTemp[0] = 0L;
} else {
SendMessage(lpds->hwndSource, FS_GETDIRECTORY, sizeof(szTemp), (LPARAM)szTemp);
}
lstrcat(szTemp, pSel); // this is the parameter to the exec
// put a "." extension on if none found
if (*GetExtension(szTemp) == 0)
lstrcat(szTemp, ".");
FixAnsiPathForDos(szSourceFile);
FixAnsiPathForDos(szTemp);
ret = ExecProgram(szSourceFile, szTemp, NULL, FALSE);
if (ret)
MyMessageBox(hwndFrame, IDS_EXECERRTITLE, ret, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
DODone:
DSRectItem(hwndLB, iSelHilite, FALSE, FALSE);
LocalFree((HANDLE)pSel);
return TRUE;
NormalMoveCopy:
/* Make sure that we don't move into same dir. */
if (GetParent(hWnd) == (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L))
return TRUE;
DirMoveCopy:
// the source filename is in the loword
pFrom = (LPSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch);
// SetSourceDir(lpds);
AddBackslash(szTemp);
lstrcat(szTemp, szStarDotStar); // put files in this dir
CheckEscapes(szTemp);
ret = DMMoveCopyHelper(pFrom, szTemp, fShowSourceBitmaps);
DSRectItem(hwndLB, iSelHilite, FALSE, FALSE);
if (ret)
return TRUE;
if (!fShowSourceBitmaps)
SendMessage(lpds->hwndSource, WM_FILESYSCHANGE, FSC_REFRESH, 0L);
// we got dropped on, but if this is a dir we don't need to refresh
if (!(dwAttrib & ATTR_DIR))
SendMessage(hWnd, WM_FILESYSCHANGE, FSC_REFRESH, 0L);
return TRUE;
}
#if 0
case WM_GETTEXT:
MSG("DirWndProc", "WM_GETTEXT");
{
HDC hDC;
RECT rc;
/* This is where we make sure that the Directory's caption fits
* inside the caption bar.
*/
/* Get the full path name. */
DefWindowProc(hWnd, wMsg, wParam, lParam);
GetClientRect(hWnd, (LPRECT)&rc);
hDC = GetDC(hWnd);
CompactPath(hDC, (LPSTR)lParam, rc.right-rc.left-(dxText * 6));
ReleaseDC(hWnd, hDC);
return((LONG)lstrlen((LPSTR)lParam)); /* Don't call DefWindowProc()! */
}
#endif
case WM_LBTRACKPOINT:
MSG("DirWndProc", "WM_LBTRACKPOINT");
return DSTrackPoint(hWnd, hwndLB, wParam, lParam, FALSE);
case WM_MEASUREITEM:
MSG("DirWndProc", "WM_MEASUREITEM");
#define pLBMItem ((LPMEASUREITEMSTRUCT)lParam)
pLBMItem->itemHeight = dyFileName; // the same as in SetLBFont()
break;
case WM_QUERYDROPOBJECT:
MSG("DirWndProc", "WM_QUERYDROPOBJECT");
// lParam LPDROPSTRUCT
//
// return values:
// 0 don't accept (use ghost buster)
// 1 accept, use cursor from DragObject()
// hCursor accept, change to this cursor
//
/* 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 = (DWORD)-1L;
return (INT_PTR)GetMoveCopyCursor();
}
return FALSE;
case WM_SETFOCUS:
// Fall through
case WM_LBUTTONDOWN:
MSG("DirWndProc", "WM_SETFOCUS/WM_LBUTTONDOWN");
SetFocus(hwndLB);
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
case LBN_DBLCLK:
MSG("DirWndProc", "LBN_DBLCLK");
/* Double-click... Open the blasted thing. */
SendMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_OPEN, 0, 0));
break;
case LBN_SELCHANGE:
MSG("DirWndProc", "LBN_SELCHANGE");
for (i = 0; i < iNumExtensions; i++) {
(extensions[i].ExtProc)(hwndFrame, FMEVENT_SELCHANGE, 0L);
}
UpdateStatus(GetParent(hWnd));
break;
case LBN_SETFOCUS:
MSG("DirWndProc", "LBN_SETFOCUS");
// Make sure there are files in this window. If not, set
// the focus to the tree or drives window. Note: This
// message was caused by a mouse click and not an
// accelerator, because these were handled in the window
// routine that was losing the focus.
if (SetDirFocus(hWnd)) {
SetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS, (LPARAM)GET_WM_COMMAND_HWND(wParam, lParam));
UpdateSelection(GET_WM_COMMAND_HWND(wParam, lParam));
}
break;
case LBN_KILLFOCUS:
MSG("DirWndProc", "LBN_KILLFOCUS");
SetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS, 0L);
UpdateSelection(GET_WM_COMMAND_HWND(wParam, lParam));
SetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS, (LPARAM)GET_WM_COMMAND_HWND(wParam, lParam));
break;
}
break;
case WM_VKEYTOITEM:
MSG("DirWndProc", "WM_VKEYTOITEM");
switch (GET_WM_VKEYTOITEM_ITEM(wParam, lParam)) {
case VK_ESCAPE:
bCancelTree = TRUE;
return -2L;
case 0xBF: /* Ctrl-/ */
SendMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_SELALL, 0, 0));
return -2;
case 0xDC: /* Ctrl-\ */
SendMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_DESELALL, 0, 0));
return -2;
case VK_F6: // like excel
case VK_TAB:
{
HWND hwndTree, hwndDrives;
GetTreeWindows(GetParent(hWnd), &hwndTree, NULL, &hwndDrives);
if (GetKeyState(VK_SHIFT) < 0)
SetFocus(hwndTree ? hwndTree : hwndDrives);
else
SetFocus(hwndDrives);
break;
}
case VK_BACK:
SendMessage(hWnd, FS_GETDIRECTORY, sizeof(szTemp), (LPARAM)szTemp);
// are we already at the root?
if (lstrlen(szTemp) <= 3)
return -1;
StripBackslash(szTemp);
StripFilespec(szTemp);
CreateDirWindow(szTemp, TRUE, GetParent(hWnd));
return -2;
default:
{
HWND hwndDrives;
// check for Ctrl-[DRIVE LETTER] and pass on to drives
// window
if ((GetKeyState(VK_CONTROL) < 0) && (hwndDrives = HasDrivesWindow(GetParent(hWnd)))) {
return SendMessage(hwndDrives, wMsg, wParam, lParam);
}
break;
}
}
return -1;
case WM_SIZE:
MSG("DirWndProc", "WM_SIZE");
if (!IsIconic(GetParent(hWnd))) {
INT iMax;
MoveWindow(hwndLB, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
iMax = (INT)SendMessage(hwndLB, LB_GETCARETINDEX, 0, 0L);
if (iMax >= 0) // scroll item into view
/* SETCARETINDEX will scroll item into view */
SendMessage(hwndLB, LB_SETCARETINDEX, iMax, 0L);
//MakeItemVisible(iMax, hwndLB);
}
break;
default:
DEFMSG("DirWndProc", (WORD)wMsg);
return DefWindowProc(hWnd, wMsg, wParam, lParam);
}
return 0L;
}
VOID
SortDirList(
HWND hWnd,
LPMYDTA lpmydta,
WORD count,
LPMYDTA *lplpmydta
)
{
INT i, j;
WORD wSort;
INT iMax, iMin, iMid;
wSort = (WORD)GetWindowLong(GetParent(GetParent(hWnd)), GWL_SORT);
for (i = 0; i < (INT)count; i++) {
// advance to next
lpmydta = GETDTAPTR(lpmydta, lpmydta->wSize);
if (i == 0) {
lplpmydta[i] = lpmydta;
} else {
// do a binary insert
iMin = 0;
iMax = i-1; // last index
do {
iMid = (iMax + iMin) / 2;
if (CompareDTA(lpmydta, lplpmydta[iMid], wSort) > 0)
iMin = iMid + 1;
else
iMax = iMid - 1;
} while (iMax > iMin);
if (iMax < 0)
iMax = 0;
if (CompareDTA(lpmydta, lplpmydta[iMax], wSort) > 0)
iMax++; // insert after this one
if (i != iMax) {
for (j = i; j > iMax; j--)
lplpmydta[j] = lplpmydta[j-1];
}
lplpmydta[iMax] = lpmydta;
}
}
}
BOOL
SetDirFocus(
HWND hwndDir
)
/*
Set the focus to whoever deserves it if not the directory window.
Return whether focus needs to be set to directory window.
*/
{
DWORD dwTemp;
HWND hwndLB = GetDlgItem(hwndDir, IDCW_LISTBOX);
SendMessage (hwndLB,LB_GETTEXT,0,(LPARAM) &dwTemp);
if (!dwTemp) {
HWND hwndFocus,hwndTree,hwndDrives,hwndParent = GetParent(hwndDir);
GetTreeWindows(hwndParent,&hwndTree,NULL,&hwndDrives);
if ((hwndFocus = GetTreeFocus(hwndParent)) == hwndDir)
SetFocus(hwndTree ? hwndTree : hwndDrives);
else
SetFocus(hwndFocus);
return FALSE;
} else
return TRUE;
}