|
|
/****************************************************************************/ /* */ /* WFDIRSRC.C - */ /* */ /* Routines Common to the Directory and Search Windows */ /* */ /****************************************************************************/
#include "winfile.h"
#define DO_DROPFILE 0x454C4946L
#define DO_PRINTFILE 0x544E5250L
#define DO_DROPONDESKTOP 0x504D42L
HWND hwndGlobalSink = NULL;
VOID SelectItem(HWND hwndLB, WPARAM wParam, BOOL bSel); VOID ShowItemBitmaps(HWND hwndLB, BOOL bShow); DWORD GetSearchAttribs(HWND hwndLB, WORD wIndex);
HCURSOR APIENTRY GetMoveCopyCursor() { if (fShowSourceBitmaps) // copy
return LoadCursor(hAppInstance, MAKEINTRESOURCE(iCurDrag | 1)); else // move
return LoadCursor(hAppInstance, MAKEINTRESOURCE(iCurDrag & 0xFFFE)); }
DWORD GetSearchAttribs( HWND hwndLB, WORD wIndex ) { DWORD dwAttribs; HANDLE hDTA; LPDTASEARCH lpschdta;
hDTA = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH); lpschdta = (LPDTASEARCH)LocalLock(hDTA); dwAttribs = lpschdta[(INT)SendMessage(hwndLB, LB_GETITEMDATA, wIndex, 0L)].sch_dwAttrs; LocalUnlock(hDTA);
return dwAttribs; }
// match a DOS wild card spec against a dos file name
// both strings are ANSI and Upper case
BOOL MatchFile( LPSTR szFile, LPSTR szSpec ) { ENTER("MatchFile"); PRINT(BF_PARMTRACE, "IN:szFile=%s", szFile); PRINT(BF_PARMTRACE, "IN:szSpec=%s", szSpec);
#define IS_DOTEND(ch) ((ch) == '.' || (ch) == 0)
if (!lstrcmp(szSpec, "*") || // "*" matches everything
!lstrcmp(szSpec, szStarDotStar)) // so does "*.*"
return TRUE;
while (*szFile && *szSpec) {
switch (*szSpec) { case '?': szFile++; szSpec++; break;
case '*':
while (!IS_DOTEND(*szSpec)) // got till a terminator
szSpec = AnsiNext(szSpec);
if (*szSpec == '.') szSpec++;
while (!IS_DOTEND(*szFile)) // got till a terminator
szFile = AnsiNext(szFile);
if (*szFile == '.') szFile++;
break;
default: if (*szSpec == *szFile) { if (IsDBCSLeadByte(*szSpec)) { szFile++; szSpec++; if (*szFile != *szSpec) return FALSE; } szFile++; szSpec++; } else return FALSE; } } return !*szFile && !*szSpec; }
VOID APIENTRY DSSetSelection( HWND hwndLB, BOOL bSelect, LPSTR szSpec, BOOL bSearch ) { WORD i; WORD iMac; HANDLE hMem; LPMYDTA lpmydta; CHAR szTemp[MAXPATHLEN];
AnsiUpper(szSpec);
iMac = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
if (bSearch) hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH); else hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTA);
LocalLock(hMem);
for (i = 0; i < iMac; i++) {
if (bSearch) { SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)szTemp); StripPath(szTemp); } else {
SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)&lpmydta);
if (lpmydta->my_dwAttrs & ATTR_PARENT) continue;
lstrcpy(szTemp, lpmydta->my_cFileName); }
AnsiUpper(szTemp);
if (MatchFile(szTemp, szSpec)) SendMessage(hwndLB, LB_SETSEL, bSelect, MAKELONG(i, 0)); }
LocalUnlock(hMem); }
/*--------------------------------------------------------------------------*/ /* */ /* ShowItemBitmaps() - */ /* */ /*--------------------------------------------------------------------------*/
VOID ShowItemBitmaps( HWND hwndLB, BOOL bShow ) { INT iSel; RECT rc;
if (bShow == fShowSourceBitmaps) return;
fShowSourceBitmaps = bShow;
/* Invalidate the bitmap parts of all visible, selected items. */ iSel = (WORD)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
while (SendMessage(hwndLB, LB_GETITEMRECT, iSel, (LPARAM)&rc) != LB_ERR) { /* Is this item selected? */ if ((BOOL)SendMessage(hwndLB, LB_GETSEL, iSel, 0L)) { /* Invalidate the bitmap area. */ rc.right = rc.left + dxFolder + dyBorderx2 + dyBorder; InvalidateRect(hwndLB, &rc, FALSE); } iSel++; } UpdateWindow(hwndLB); }
INT CharCountToTab( LPSTR pStr ) { LPSTR pTmp = pStr;
while (*pStr && *pStr != '\t') { pStr = AnsiNext(pStr); }
return (INT)(pStr-pTmp); }
// this only deals with opaque text for now
VOID RightTabbedTextOut( HDC hdc, INT x, INT y, LPSTR pLine, WORD *pTabStops, INT x_offset ) { INT len, cch; INT x_ext; INT x_initial; RECT rc;
len = lstrlen(pLine);
// setup opaquing rect (we adjust the right border as we
// output the string)
rc.left = x; rc.top = y; rc.bottom = y + dyText; // global max char height
x_initial = x;
cch = CharCountToTab(pLine); MGetTextExtent(hdc, pLine, cch, &x_ext, NULL);
// first position is left alligned so bias initial x value
x += x_ext;
while (len) {
len -= cch + 1;
rc.right = x; ExtTextOut(hdc, x - x_ext, y, ETO_OPAQUE, &rc, pLine, cch, NULL);
if (len <= 0) return;
rc.left = rc.right; pLine += cch + 1;
cch = CharCountToTab(pLine); MGetTextExtent(hdc, pLine, cch, &x_ext, NULL);
x = *pTabStops + x_offset; pTabStops++; } }
/*--------------------------------------------------------------------------*/ /* */ /* DrawItem() - */ /* */ /*--------------------------------------------------------------------------*/
VOID APIENTRY DrawItem( LPDRAWITEMSTRUCT lpLBItem, LPSTR szLine, DWORD dwAttrib, BOOL bHasFocus, WORD *pTabs ) { INT x, y; CHAR ch; LPSTR psz; HDC hDC; BOOL bDrawSelected; HWND hwndLB; INT iBitmap;
hwndLB = lpLBItem->hwndItem;
bDrawSelected = (lpLBItem->itemState & ODS_SELECTED);
hDC = lpLBItem->hDC;
if (bHasFocus && bDrawSelected) { SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT)); }
if (lpLBItem->itemAction == ODA_FOCUS) goto FocusOnly;
/* Draw the black/white background. */ ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lpLBItem->rcItem, NULL, 0, NULL);
x = lpLBItem->rcItem.left + 1; y = lpLBItem->rcItem.top + (dyFileName/2);
if (fShowSourceBitmaps || (hwndDragging != hwndLB) || !bDrawSelected) {
if (dwAttrib & ATTR_DIR) { if (dwAttrib & ATTR_PARENT) { iBitmap = BM_IND_DIRUP; szLine = szNULL; // no date/size stuff!
} else iBitmap = BM_IND_CLOSE; } else {
// isolate the name so we can see what type of file this is
psz = szLine + CharCountToTab(szLine); ch = *psz; *psz = 0;
if (dwAttrib & (ATTR_HIDDEN | ATTR_SYSTEM)) iBitmap = BM_IND_RO; else if (IsProgramFile(szLine)) iBitmap = BM_IND_APP; else if (IsDocument(szLine)) iBitmap = BM_IND_DOC; else iBitmap = BM_IND_FIL;
*psz = ch; // resore the old character
}
BitBlt(hDC, x + dyBorder, y-(dyFolder/2), dxFolder, dyFolder, hdcMem, iBitmap * dxFolder, (bHasFocus && bDrawSelected) ? dyFolder : 0, SRCCOPY); }
x += dxFolder + dyBorderx2;
if ((wTextAttribs & TA_LOWERCASE) && !(dwAttrib & ATTR_LFN)) AnsiLower(szLine);
RightTabbedTextOut(hDC, x, y-(dyText/2), szLine, (WORD *)pTabs, x);
if (lpLBItem->itemState & ODS_FOCUS) FocusOnly: DrawFocusRect(hDC, &lpLBItem->rcItem); // toggles focus (XOR)
if (bDrawSelected) { if (bHasFocus) { SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); SetBkColor(hDC, GetSysColor(COLOR_WINDOW)); } else { HBRUSH hbr; RECT rc;
if (hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT))) { rc = lpLBItem->rcItem; rc.right = rc.left + (INT)SendMessage(hwndLB, LB_GETHORIZONTALEXTENT, 0, 0L);
if (lpLBItem->itemID > 0 && (BOOL)SendMessage(hwndLB, LB_GETSEL, lpLBItem->itemID - 1, 0L)) rc.top -= dyBorder;
FrameRect(hDC, &rc, hbr); DeleteObject(hbr); } } } }
/*--------------------------------------------------------------------------*/ /* */ /* SelectItem() - */ /* */ /*--------------------------------------------------------------------------*/
VOID SelectItem( HWND hwndLB, WPARAM wParam, BOOL bSel ) { /* Add the current item to the selection. */ SendMessage(hwndLB, LB_SETSEL, bSel, (DWORD)wParam);
/* Give the selected item the focus rect and anchor pt. */ SendMessage(hwndLB, LB_SETCARETINDEX, wParam, 0L); SendMessage(hwndLB, LB_SETANCHORINDEX, wParam, 0L); }
//
// void APIENTRY DSDragLoop(register HWND hwndLB, WPARAM wParam, LPDROPSTRUCT lpds, BOOL bSearch)
//
// called by for the directory and search drag loops. this must handle
// detecting all kinds of different destinations.
//
// in:
// hwndLB source listbox (either the dir or the sort)
// wParam same as sent for WM_DRAGLOOP (TRUE if we are on a dropable sink)
// lpds drop struct sent with the message
// bSearch TRUE if we are in the search listbox
//
VOID APIENTRY DSDragLoop( HWND hwndLB, WPARAM wParam, LPDROPSTRUCT lpds, BOOL bSearch ) { BOOL bTemp; BOOL bShowBitmap; LPMYDTA lpmydta; HWND hwndMDIChildSink, hwndDir;
// bShowBitmap is used to turn the source bitmaps on or off to distinguish
// between a move and a copy or to indicate that a drop can
// occur (exec and app)
// hack: keep around for drop files!
hwndGlobalSink = lpds->hwndSink;
bShowBitmap = TRUE; // default to copy
if (!wParam) goto DragLoopCont; // can't drop here
// Is the user holding down the CTRL key (which forces a copy)?
if (GetKeyState(VK_CONTROL) < 0) { bShowBitmap = TRUE; goto DragLoopCont; }
// Is the user holding down the ALT or SHIFT key (which forces a move)?
if (GetKeyState(VK_MENU)<0 || GetKeyState(VK_SHIFT)<0) { bShowBitmap = FALSE; goto DragLoopCont; }
hwndMDIChildSink = GetMDIChildFromDecendant(lpds->hwndSink);
// Are we over the source listbox? (sink and source the same)
if (lpds->hwndSink == hwndLB) {
// Are we over a valid listbox entry?
if (LOWORD(lpds->dwControlData) == 0xFFFF) { goto DragLoopCont; } else { /* Yup, are we over a directory entry? */ if (bSearch) {
bTemp = (GetSearchAttribs(hwndLB, (WORD)(lpds->dwControlData)) & ATTR_DIR) != 0L;
} else {
SendMessage(hwndLB, LB_GETTEXT, (WORD)(lpds->dwControlData), (LPARAM)&lpmydta);
bTemp = lpmydta->my_dwAttrs & ATTR_DIR;
} if (!bTemp) goto DragLoopCont; } }
/* Now we need to see if we are over an Executable file. If so, we
* need to force the Bitmaps to draw. */
/* Are we over a directory window? */
if (hwndMDIChildSink) hwndDir = HasDirWindow(hwndMDIChildSink); else hwndDir = NULL;
if (hwndDir && (hwndDir == GetParent(lpds->hwndSink))) {
// Are we over an occupided part of the list box?
if (LOWORD(lpds->dwControlData) != 0xFFFF) {
// Are we over an Executable?
SendMessage(lpds->hwndSink, LB_GETTEXT, (WORD)(lpds->dwControlData), (LPARAM)&lpmydta);
bTemp = IsProgramFile(lpmydta->my_cFileName);
if (bTemp) goto DragLoopCont; } }
// Are we dropping into the same drive (check the source and dest drives)
bShowBitmap = ((INT)SendMessage(GetParent(hwndLB), FS_GETDRIVE, 0, 0L) != GetDrive(lpds->hwndSink, lpds->ptDrop));
DragLoopCont:
ShowItemBitmaps(hwndLB, bShowBitmap);
// hack, set the cursor to match the move/copy state
if (wParam) SetCursor(GetMoveCopyCursor()); }
/*--------------------------------------------------------------------------*/ /* */ /* DSRectItem() - */ /* */ /*--------------------------------------------------------------------------*/
VOID APIENTRY DSRectItem( HWND hwndLB, INT iItem, BOOL bFocusOn, BOOL bSearch ) { RECT rc; RECT rcT; HDC hDC; BOOL bSel; WORD wColor; HBRUSH hBrush; LPMYDTA lpmydta; CHAR szTemp[MAXPATHLEN];
/* Are we over an unused part of the listbox? */ if (iItem == 0xFFFF) return;
/* Are we over ourselves? (i.e. a selected item in the source listbox) */ bSel = (BOOL)SendMessage(hwndLB, LB_GETSEL, iItem, 0L); if (bSel && (hwndDragging == hwndLB)) return;
/* We only put rectangles around directories and program items. */ if (bSearch) { SendMessage(hwndLB, LB_GETTEXT, iItem, (LPARAM)szTemp);
// this is bused, we must test this as attributes
if (!(BOOL)(GetSearchAttribs(hwndLB, (WORD)iItem) & ATTR_DIR) && !IsProgramFile((LPSTR)szTemp)) return; } else { SendMessage(hwndLB, LB_GETTEXT, iItem, (LPARAM)&lpmydta);
if (!(lpmydta->my_dwAttrs & ATTR_DIR) && !IsProgramFile(lpmydta->my_cFileName)) { return; } }
/* Turn the item's rectangle on or off. */
SendMessage(hwndLB, LB_GETITEMRECT, iItem, (LPARAM)&rc); GetClientRect(hwndLB,&rcT); IntersectRect(&rc,&rc,&rcT);
if (bFocusOn) { hDC = GetDC(hwndLB); if (bSel) { wColor = COLOR_WINDOW; InflateRect(&rc, -1, -1); } else wColor = COLOR_WINDOWFRAME;
if (hBrush = CreateSolidBrush(GetSysColor(wColor))) { FrameRect(hDC, &rc, hBrush); DeleteObject(hBrush); } ReleaseDC(hwndLB, hDC); } else { InvalidateRect(hwndLB, &rc, FALSE); UpdateWindow(hwndLB); } }
/*--------------------------------------------------------------------------*/ /* */ /* DropFilesOnApplication() - */ /* */ /*--------------------------------------------------------------------------*/
/* this function will determine whether the application we are currently
* over is a valid drop point and drop the files */
WORD DropFilesOnApplication( LPSTR pszFiles ) { POINT pt; HWND hwnd; RECT rc; HANDLE hDrop,hT; LPSTR lpList; WORD cbList = 2; OFSTRUCT ofT; WORD cbT; LPDROPFILESTRUCT lpdfs; CHAR szFile[MAXPATHLEN];
if (!(hwnd = hwndGlobalSink)) return 0;
hwndGlobalSink = NULL;
GetCursorPos(&pt);
cbList = 2 + sizeof (DROPFILESTRUCT); hDrop = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,cbList); if (!hDrop) return 0;
lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop);
GetClientRect(hwnd,&rc); ScreenToClient(hwnd,&pt); lpdfs->pt = pt; lpdfs->fNC = !PtInRect(&rc,pt); lpdfs->pFiles = sizeof(DROPFILESTRUCT);
GlobalUnlock(hDrop);
while (pszFiles = GetNextFile(pszFiles, szFile, sizeof(szFile))) {
MOpenFile(szFile, &ofT, OF_PARSE);
cbT = (WORD)(lstrlen(ofT.szPathName)+1); hT = GlobalReAlloc(hDrop,cbList+cbT,GMEM_MOVEABLE|GMEM_ZEROINIT); if (!hT) break; hDrop = hT; lpList = GlobalLock(hDrop); OemToAnsi(ofT.szPathName, lpList+cbList-2); GlobalUnlock(hDrop); cbList += cbT; }
PostMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0L);
return 1; }
/*--------------------------------------------------------------------------*/ /* */ /* DSTrackPoint() - */ /* */ /*--------------------------------------------------------------------------*/
/* Return 0 for normal mouse tracking, 1 for no mouse single-click processing,
* and 2 for no mouse single- or double-click tracking. */
INT APIENTRY DSTrackPoint( HWND hWnd, HWND hwndLB, WPARAM wParam, LPARAM lParam, BOOL bSearch ) { UINT iSel; MSG msg; RECT rc; WORD wAnchor; DWORD dwTemp; LPSTR pch; BOOL bDir; BOOL bSelected; BOOL bSelectOneItem; BOOL bUnselectIfNoDrag; CHAR szFileName[MAXPATHLEN+1]; INT iNoYieldCount; WORD wYieldFlags; POINT pt; HANDLE hHackForHDC = NULL; // hDC Express editor relies on this
DRAGOBJECTDATA dodata;
bSelectOneItem = FALSE; bUnselectIfNoDrag = FALSE;
bSelected = (BOOL)SendMessage(hwndLB, LB_GETSEL, wParam, 0L);
if (GetKeyState(VK_SHIFT) < 0) { /* What is the state of the Anchor point? */ wAnchor = (WORD)SendMessage(hwndLB, LB_GETANCHORINDEX, 0, 0L); bSelected = (BOOL)SendMessage(hwndLB, LB_GETSEL, wAnchor, 0L);
/* If Control is up, turn everything off. */ if (!(GetKeyState(VK_CONTROL) < 0)) SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
/* Select everything between the Anchor point and the item. */ SendMessage(hwndLB, LB_SELITEMRANGE, bSelected, MAKELONG(wParam, wAnchor));
/* Give the selected item the focus rect. */ SendMessage(hwndLB, LB_SETCARETINDEX, wParam, 0L); } else if (GetKeyState(VK_CONTROL) < 0) { if (bSelected) bUnselectIfNoDrag = TRUE; else SelectItem(hwndLB, wParam, TRUE); } else { if (bSelected) bSelectOneItem = TRUE; else { /* Deselect everything. */ SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
/* Select the current item. */ SelectItem(hwndLB, wParam, TRUE); } }
if (!bSearch) UpdateStatus(GetParent(hWnd));
LONG2POINT(lParam, pt); ClientToScreen(hwndLB, (LPPOINT)&pt); ScreenToClient(hWnd, (LPPOINT)&pt);
// See if the user moves a certain number of pixels in any direction
SetRect(&rc, pt.x - dxClickRect, pt.y - dyClickRect, pt.x + dxClickRect, pt.y + dyClickRect);
SetCapture(hWnd); wYieldFlags = PM_NOYIELD | PM_REMOVE; iNoYieldCount = 50; for (;;) { #if 0
{ CHAR szBuf[80];
wsprintf(szBuf, "Message %4.4X\r\n", msg.message); OutputDebugString(szBuf); } #endif
if (PeekMessage(&msg, NULL, 0, 0, wYieldFlags)) DispatchMessage(&msg);
if (iNoYieldCount <= 0) wYieldFlags = PM_REMOVE; else iNoYieldCount--;
// WM_CANCELMODE messages will unset the capture, in that
// case I want to exit this loop
if (GetCapture() != hWnd) { msg.message = WM_LBUTTONUP; // don't proceed below
break; }
if (msg.message == WM_LBUTTONUP) break;
LONG2POINT(msg.lParam, pt); if ((msg.message == WM_MOUSEMOVE) && !(PtInRect(&rc, pt))) break; } ReleaseCapture();
/* Did the guy NOT drag anything? */ if (msg.message == WM_LBUTTONUP) { if (bSelectOneItem) { /* Deselect everything. */ SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
/* Select the current item. */ SelectItem(hwndLB, wParam, TRUE); }
if (bUnselectIfNoDrag) SelectItem(hwndLB, wParam, FALSE);
// notify the appropriate people
SendMessage(hWnd, WM_COMMAND, GET_WM_COMMAND_MPS(0, hwndLB, LBN_SELCHANGE));
return 1; }
/* Enter Danger Mouse's BatCave. */ if ((WORD)SendMessage(hwndLB, LB_GETSELCOUNT, 0, 0L) == 1) { /* There is only one thing selected.
* Figure out which cursor to use. */ if (bSearch) { SendMessage(hwndLB, LB_GETTEXT, wParam, (LPARAM)szFileName); bDir = (BOOL)(GetSearchAttribs(hwndLB, (WORD)wParam) & ATTR_DIR); } else { LPMYDTA lpmydta;
SendMessage(hwndLB, LB_GETTEXT, wParam, (LPARAM)&lpmydta);
lstrcpy(szFileName, lpmydta->my_cFileName); bDir = lpmydta->my_dwAttrs & ATTR_DIR;
// avoid dragging the parrent dir
if (lpmydta->my_dwAttrs & ATTR_PARENT) { return 1; } }
if (bDir) { iSel = DOF_DIRECTORY; } else if (IsProgramFile(szFileName)) { iSel = DOF_EXECUTABLE; goto HDC_HACK_FROM_HELL; } else if (IsDocument(szFileName)) { iSel = DOF_DOCUMENT; HDC_HACK_FROM_HELL: hHackForHDC = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(OFSTRUCT)); if (hHackForHDC) { LPOFSTRUCT lpof;
lpof = (LPOFSTRUCT)GlobalLock(hHackForHDC); QualifyPath(szFileName); lstrcpy(lpof->szPathName, szFileName); GlobalUnlock(hHackForHDC); } } else iSel = DOF_DOCUMENT;
iCurDrag = SINGLECOPYCURSOR; } else { /* Multiple files are selected. */ iSel = DOF_MULTIPLE; iCurDrag = MULTCOPYCURSOR; }
/* Get the list of selected things. */ pch = (LPSTR)SendMessage(hWnd, FS_GETSELECTION, FALSE, 0L);
/* Wiggle things around. */ hwndDragging = hwndLB; dodata.pch = pch; dodata.hMemGlobal = hHackForHDC; dwTemp = DragObject(GetDesktopWindow(),hWnd,(UINT)iSel,(DWORD)(ULONG_PTR)&dodata,GetMoveCopyCursor());
if (hHackForHDC) GlobalFree(hHackForHDC);
SetWindowDirectory();
if (dwTemp == DO_PRINTFILE) { // print these
hdlgProgress = NULL; WFPrint(pch); } else if (dwTemp == DO_DROPFILE) { // try and drop them on an application
DropFilesOnApplication(pch); }
LocalFree((HANDLE)pch);
if (IsWindow(hWnd)) ShowItemBitmaps(hwndLB, TRUE);
hwndDragging = NULL;
if (!bSearch && IsWindow(hWnd)) UpdateStatus(GetParent(hWnd));
return 2; }
|