|
|
/****************************************************************************/ /* */ /* 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; }
|