Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

391 lines
10 KiB

//---------------------------------------------------------------------------
// Support routines for the drivelist dropdown.
//---------------------------------------------------------------------------
#include "cabinet.h"
#include "drivlist.h"
#include "rcids.h"
#include "dlgprocs.h"
#include "tree.h"
#define MAX_DRIVELIST_STRING_LEN (64+4)
#define MINIDRIVE_MARGIN 4
#define MINIDRIVE_WIDTH g_cxSmIcon
#define MINIDRIVE_HEIGHT g_cySmIcon
#define DRIVELIST_BORDER 3
// Change the state of a drive list
//
void DriveList_OpenClose(UINT uAction, HWND hwndDriveList)
{
if (!hwndDriveList || !IsWindowVisible(hwndDriveList))
{
return;
}
TryAgain:
switch (uAction)
{
case OCDL_TOGGLE:
uAction = SendMessage(hwndDriveList, CB_GETDROPPEDSTATE, 0, 0L)
? OCDL_CLOSE : OCDL_OPEN;
goto TryAgain;
break;
case OCDL_OPEN:
SetFocus(hwndDriveList);
SendMessage(hwndDriveList, CB_SHOWDROPDOWN, TRUE, 0);
break;
case OCDL_CLOSE:
if (GetFocus() == hwndDriveList)
{
SendMessage(hwndDriveList, CB_SHOWDROPDOWN, FALSE, 0);
}
break;
}
}
void DriveList_GetText(PFileCabinet pfc, int iItem, LPTSTR szText, int cbText)
{
LPOneTreeNode lpnd;
SendMessage(pfc->hwndDrives, CB_GETLBTEXT, iItem, (LPARAM)(LPOneTreeNode *)&lpnd);
OTGetNodeName(lpnd, szText, cbText);
}
LPITEMIDLIST DriveList_GetFullIDList(PFileCabinet pfc, int iItem)
{
LPOneTreeNode lpnd;
SendMessage(pfc->hwndDrives, CB_GETLBTEXT, iItem, (LPARAM)(LPOneTreeNode *)&lpnd);
return OTCreateIDListFromNode(lpnd);
}
extern LPOneTreeNode s_lpnRoot;
int DriveList_DepthFromRoot(PFileCabinet pfc, int iItem)
{
int i;
LPOneTreeNode lpnd;
SendMessage(pfc->hwndDrives, CB_GETLBTEXT, iItem, (LPARAM)(LPOneTreeNode *)&lpnd);
for (i = 0; lpnd && (lpnd != s_lpnRoot) ; i++ ,lpnd = OTGetParent(lpnd), OTRelease(lpnd));
return i;
}
void DriveList_Reset(PFileCabinet pfc)
{
if (pfc->hwndDrives) {
int i;
LPOneTreeNode lpnd;
int iMax = SendMessage(pfc->hwndDrives, CB_GETCOUNT, 0, 0);
for (i = 0 ; i < iMax; i++) {
SendMessage(pfc->hwndDrives, CB_GETLBTEXT, i, (LPARAM)(LPOneTreeNode *)&lpnd);
OTRelease(lpnd);
}
}
}
//
// build a path into the combo box.
//
// Arguments:
// hItem -- Specified the selected tree item
// htiRoot -- Specifies the root folder
// (the cabinet for local folder, the server for UNC)
//
// return: combobox index of the end of the path
//
int DriveList_InsertPath(PFileCabinet pfc,
LPOneTreeNode lpnd,
LPOneTreeNode lpndRoot)
{
LPOneTreeNode lpndDrive = NULL, lpndParent;
int iRoot, iRet;
//
// Find the "drive" node (or "share" node for UNC)
//
// Just find the top level item
for (lpndParent = lpnd;
lpndParent && lpndParent != lpndRoot && lpndParent != s_lpnRoot;
lpndParent = OTGetParent(lpndDrive), OTRelease(lpndParent))
{
lpndDrive = lpndParent;
}
if (lpndDrive == NULL)
lpndDrive = lpnd;
iRoot = (int)SendMessage(pfc->hwndDrives, CB_FINDSTRING, (WPARAM)-1,
(LPARAM)lpndDrive);
if (iRoot < 0)
{
// We're bummed
return(-1);
}
iRet = iRoot;
++iRoot;
for ( ; lpnd != lpndDrive; lpnd = OTGetParent(lpnd), OTRelease(lpnd))
{
++iRet;
OTAddRef(lpnd);
SendMessage(pfc->hwndDrives, CB_INSERTSTRING, iRoot, (LPARAM)lpnd);
}
return(iRet);
}
int CALLBACK _CompareNodeID(LPVOID p1, LPVOID p2, LPARAM lParam)
{
LPOneTreeNode lpnd1 = (LPOneTreeNode)p1;
LPOneTreeNode lpnd2 = (LPOneTreeNode)p2;
LPSHELLFOLDER psf = (LPSHELLFOLDER)lParam;
HRESULT hres = psf->lpVtbl->CompareIDs(psf, 0, OTGetFolderID(lpnd1), OTGetFolderID(lpnd2));
return (short)SCODE_CODE(hres);
}
// taken from onetree.c
HDPA _GetSortedNodeList(PFileCabinet pfc, LPOneTreeNode lpndParent)
{
UINT cnode;
OTSubNodeCount(pfc->hwndMain, lpndParent, pfc, &cnode, FALSE);
if (lpndParent->hdpaKids != NOKIDS)
return lpndParent->hdpaKids;
else
return NULL;
}
/*
** set a new path in the drivelist.
**
** clean out the old built path and make a new one.
*/
//
// BUGBUG: This code does not support UNC name.
//
void DriveList_UpdatePath(PFileCabinet pfc, BOOL fInvalidate)
{
LPITEMIDLIST pidl;
LPOneTreeNode lpndDrives;
HDPA hdpa;
//
// BUGBUG: Is this right? I need to skip this for the recycle bin
// since it doesn't have a drive list.
//
// bugbug, can this ever be null?
if (!pfc->hwndDrives)
return;
DriveList_Reset(pfc);
SendMessage(pfc->hwndDrives, CB_RESETCONTENT, 0, 0L);
if (OTIsDesktopRoot())
{
pidl = SHCloneSpecialIDList(pfc->hwndMain, CSIDL_DRIVES, FALSE);
if (!pidl)
return;
lpndDrives = OTGetNodeFromIDList(pidl, OTGNF_NEARESTMATCH | OTGNF_VALIDATE | OTGNF_TRYADD);
if (!lpndDrives)
return;
ILFree(pidl);
if (fInvalidate)
OTInvalidateNode(lpndDrives);
}
else
{
lpndDrives = NULL;
}
//
// Add all of the drives
//
// add desktop
SendMessage(pfc->hwndDrives, CB_ADDSTRING, 0, (LPARAM)OTGetRootNode());
// Get the sorted list of all the folder node under the desktop.
ENTERCRITICAL;
hdpa = _GetSortedNodeList(pfc, s_lpnRoot);
if (hdpa)
{
int i;
for (i=0; i<DPA_GetPtrCount(hdpa); i++)
{
LPOneTreeNode lpnd = (LPOneTreeNode)DPA_GetPtr(hdpa, i);
OTAddRef( lpnd );
SendMessage(pfc->hwndDrives, CB_ADDSTRING, 0, (LPARAM)lpnd);
if (lpnd == lpndDrives)
{
// Get the sorted list of all the folder node under MyComputer.
HDPA hdpaDrv = _GetSortedNodeList(pfc, lpnd);
if (hdpaDrv)
{
int j;
for (j=0; j<DPA_GetPtrCount(hdpaDrv); j++)
{
lpnd = (LPOneTreeNode)DPA_GetPtr(hdpaDrv, j);
OTAddRef( lpnd );
SendMessage(pfc->hwndDrives, CB_ADDSTRING, 0, (LPARAM)lpnd);
}
}
}
}
}
LEAVECRITICAL;
if (pfc->lpndOpen != NULL)
{
int iNow = DriveList_InsertPath(pfc, pfc->lpndOpen, lpndDrives);
SendMessage(pfc->hwndDrives, CB_SETCURSEL, iNow, 0L);
pfc->iNow = iNow;
}
OTRelease(lpndDrives);
}
void DriveList_MeasureItem(PFileCabinet pfc, MEASUREITEMSTRUCT *lpmi)
{
HDC hdc;
HFONT hfontOld;
int dyDriveItem;
SIZE siz;
Assert(pfc);
hdc = GetDC(NULL);
hfontOld = SelectObject(hdc, (HFONT)SendMessage(pfc->hwndToolbar, WM_GETFONT, 0, 0));
GetTextExtentPoint(hdc, TEXT("W"), 1, &siz);
dyDriveItem = siz.cy;
if (hfontOld)
SelectObject(hdc, hfontOld);
ReleaseDC(NULL, hdc);
dyDriveItem += DRIVELIST_BORDER;
if (dyDriveItem < MINIDRIVE_HEIGHT)
dyDriveItem = MINIDRIVE_HEIGHT;
lpmi->itemHeight = dyDriveItem;
}
void DriveList_DrawItem(PFileCabinet pfc, const DRAWITEMSTRUCT *lpdis)
{
HDC hdc = lpdis->hDC;
RECT rc = lpdis->rcItem;
TCHAR szText[MAX_DRIVELIST_STRING_LEN];
int offset = 0;
int xString, yString, xMiniDrive, dyString;
SIZE siz;
if ((int)lpdis->itemID < 0)
{
return;
}
DriveList_GetText(pfc, lpdis->itemID, szText, ARRAYSIZE(szText));
// before doing anything, calculate the actual rectangle for
// the text.
if (!(lpdis->itemState & ODS_COMBOBOXEDIT))
{
offset = DriveList_DepthFromRoot(pfc, lpdis->itemID) * 10;
}
xMiniDrive = rc.left + DRIVELIST_BORDER + offset;
rc.left = xString = xMiniDrive + MINIDRIVE_WIDTH + MINIDRIVE_MARGIN;
GetTextExtentPoint(hdc, szText, lstrlen(szText), &siz);
dyString = siz.cy;
rc.right = rc.left + siz.cx;
rc.left--;
rc.right++;
if (lpdis->itemAction != ODA_FOCUS)
{
int iImage, iSelectedImage;
LPOneTreeNode lpnd;
yString = rc.top + (rc.bottom - rc.top - dyString)/2;
SetBkColor(hdc, GetSysColor((lpdis->itemState & ODS_SELECTED) ?
COLOR_HIGHLIGHT : COLOR_WINDOW));
SetTextColor(hdc, GetSysColor((lpdis->itemState & ODS_SELECTED) ?
COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT));
if ((lpdis->itemState & ODS_COMBOBOXEDIT) &&
(rc.right > lpdis->rcItem.right))
{
// Need to clip as user does not!
rc.right = lpdis->rcItem.right;
}
ExtTextOut(hdc, xString, yString, ETO_OPAQUE | ETO_CLIPPED, &rc, szText, lstrlen(szText), NULL);
lpnd = (LPOneTreeNode)lpdis->itemData;
OTGetImageIndex(lpnd, &iImage, &iSelectedImage);
ImageList_Draw(g_himlSysSmall,
(lpnd == pfc->lpndOpen) ? iSelectedImage : iImage,
hdc, xMiniDrive,
rc.top + (rc.bottom - rc.top - MINIDRIVE_HEIGHT)/2,
(OTIsShared(lpnd) ? INDEXTOOVERLAYMASK(IDOI_SHARE) : 0) | /// add the sharing hand if appro.
((lpdis->itemState & ODS_SELECTED) ? (ILD_SELECTED | ILD_FOCUS) : ILD_NORMAL));
}
if (lpdis->itemAction == ODA_FOCUS ||
(lpdis->itemState & ODS_FOCUS))
{
DrawFocusRect(hdc, &rc);
}
}
void DriveList_Command(PFileCabinet pfc, UINT idCmd)
{
switch (idCmd)
{
case CBN_SETFOCUS:
pfc->iOldSel = pfc->iNewSel = (int)SendMessage(pfc->hwndDrives, CB_GETCURSEL, 0, 0L);
break;
case CBN_KILLFOCUS:
if (pfc->iNewSel != pfc->iOldSel)
{
LPITEMIDLIST pidl = DriveList_GetFullIDList(pfc, pfc->iNewSel);
if (pidl)
{
Cabinet_SetPath(pfc, CSP_REPOST, pidl);
ILFree(pidl);
}
}
else
{
SendMessage(pfc->hwndDrives, CB_SETCURSEL, pfc->iOldSel, 0L);
}
break;
case CBN_CLOSEUP:
if (GetFocus() == pfc->hwndDrives)
{
SetFocus(pfc->hwndMain);
}
break;
case CBN_SELENDOK:
pfc->iNewSel = (int)SendMessage(pfc->hwndDrives, CB_GETCURSEL, 0, 0L);
break;
}
}