|
|
/*****************************************************************************\
FILE: ftpdhlp.cpp DESCRIPTION: Replace strings in a dialog template with attributes about an FTP item (ftp server, ftp dir, or ftp file). \*****************************************************************************/
#include "priv.h"
#include "ftpurl.h"
#include "ftpdhlp.h"
#define SZ_WSPRINTFSTR_S TEXT("%s")
#define SZ_WSPRINTFSTR_U TEXT("%u")
class CSizeHolder { public: BOOL IsAllFolders(void) {return m_fAllFolders;}; void FoundNonFolder(void) {m_fAllFolders = FALSE;};
HRESULT GetError(void) {return m_hr;}; void SetError(HRESULT hr) {m_hr = hr;};
void AddSize(ULONGLONG ullSizeToAdd) { m_ullTotalSize += ullSizeToAdd;}; ULONGLONG GetTotalSize(void) {return m_ullTotalSize;};
CSizeHolder() {m_ullTotalSize = 0; m_fAllFolders = TRUE; m_hr = S_OK;}; ~CSizeHolder() {};
private: BOOL m_fAllFolders; HRESULT m_hr; ULONGLONG m_ullTotalSize; };
HRESULT CFtpDialogTemplate::_ReinsertDlgText(HWND hwnd, LPCVOID pv, LPCTSTR ptszFormat) { TCHAR szDlgTemplate[256]; TCHAR szFinalString[1024]; // wnsprintf maxes at 1024
GetWindowText(hwnd, szDlgTemplate, ARRAYSIZE(szDlgTemplate)); wnsprintf(szFinalString, ARRAYSIZE(szFinalString), szDlgTemplate, pv); // Are they the same?
if (!StrCmp(szDlgTemplate, szFinalString)) wnsprintf(szFinalString, ARRAYSIZE(szFinalString), ptszFormat, pv); // Yes
SetWindowText(hwnd, szFinalString); return S_OK; }
/*****************************************************************************\
FUNCTION: _ReplaceIcon DESCRIPTION: \*****************************************************************************/ HRESULT CFtpDialogTemplate::_ReplaceIcon(HWND hwnd, HICON hicon) { hicon = (HICON)SendMessage(hwnd, STM_SETICON, (WPARAM)hicon, 0L); if (hicon) { DestroyIcon(hicon); } return S_OK; }
/*****************************************************************************\
FUNCTION: _InitIcon DESCRIPTION: _HACKHACK_ We go straight to CFtpIcon to get the pxi instead of going through CFtpFolder. Same effect, but saves some memory allocations. What's more important, we don't necessarily have a psf to play with, so we really have no choice.
Yes, it's gross. \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitIcon(HWND hwnd, CFtpFolder * pff, CFtpPidlList * pflHfpl) { IExtractIcon * pxi; HRESULT hr; if (pflHfpl && pflHfpl->GetCount() == 1) { SHFILEINFO sfi; hr = FtpPidl_GetFileInfo(pflHfpl->GetPidl(0), &sfi, SHGFI_ICON | SHGFI_LARGEICON); if (SUCCEEDED(hr)) hr = _ReplaceIcon(hwnd, sfi.hIcon); } else { hr = CFtpIcon_Create(pff, pflHfpl, IID_IExtractIcon, (LPVOID *)&pxi); if (SUCCEEDED(hr)) { TCHAR szPath[MAX_PATH]; int i; UINT ui; hr = pxi->GetIconLocation(0, szPath, ARRAYSIZE(szPath), &i, &ui); if (EVAL(SUCCEEDED(hr))) { CHAR szPathAnsi[MAX_PATH]; SHTCharToAnsi(szPath, szPathAnsi, ARRAYSIZE(szPathAnsi)); hr = _ReplaceIcon(hwnd, ExtractIconA(g_hinst, szPathAnsi, i)); } ASSERT(pxi); pxi->Release(); } } return hr; }
void GetItemName(CFtpFolder * pff, CFtpPidlList * pflHfpl, LPWSTR pwzName, DWORD cchSize) { // Are multiple items selected?
if (1 < pflHfpl->GetCount()) LoadString(HINST_THISDLL, IDS_SEVERAL_SELECTED, pwzName, cchSize); else { LPCITEMIDLIST pidl; if (0 == pflHfpl->GetCount()) pidl = FtpID_GetLastIDReferense(pff->GetPrivatePidlReference()); else pidl = FtpID_GetLastIDReferense(pflHfpl->GetPidl(0));
if (pidl) FtpPidl_GetDisplayName(pidl, pwzName, cchSize); } }
BOOL CanEditName(CFtpFolder * pff, CFtpPidlList * pflHfpl) { int nNumItems = pflHfpl->GetCount(); BOOL fCanRename = TRUE;
// we can edit except for multiply selected items
if (2 <= nNumItems) fCanRename = FALSE; else { // If they chose the background properties for a server,
// we won't let the change the server name.
if (0 == nNumItems) { LPCITEMIDLIST pidlFolder = pff->GetPrivatePidlReference();
if (pidlFolder && (ILIsEmpty(pidlFolder) || (ILIsEmpty(_ILNext(pidlFolder))))) { fCanRename = FALSE; } } else if (1 == nNumItems) { // Now I'm worried that pflHfpl->GetPidl(0) is a PIDL pointing to
// an FTP Server.
LPCITEMIDLIST pidl = pflHfpl->GetPidl(0);
if (pidl && !ILIsEmpty(pidl) && FtpID_IsServerItemID(pidl) && ILIsEmpty(_ILNext(pidl))) { fCanRename = FALSE; } } }
return fCanRename; }
/*****************************************************************************\
FUNCTION: _InitName DESCRIPTION: Get the name of the object in the pflHfpl. If there is more than one thing, use ellipses. \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitName(HWND hwnd, CFtpFolder * pff, CFtpPidlList * pflHfpl) { HRESULT hr = S_OK; WCHAR wzName[MAX_PATH];
GetItemName(pff, pflHfpl, wzName, ARRAYSIZE(wzName)); hr = _ReinsertDlgText(hwnd, wzName, SZ_WSPRINTFSTR_S); // We only use the static filename when more than one item is selected
// because that is the case that we can't do a rename. Are there
// multiple items selected?
if (m_fEditable && CanEditName(pff, pflHfpl)) { // Hide because we will use IDC_FILENAME_EDITABLE instead.
ShowEnableWindow(hwnd, FALSE); }
return hr; }
/*****************************************************************************\
FUNCTION: _InitNameEditable DESCRIPTION: Get the name of the object in the pflHfpl. If there is more than one thing, use ellipses. \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitNameEditable(HWND hwnd, CFtpFolder * pff, CFtpPidlList * pflHfpl) { HRESULT hr = S_OK; TCHAR szName[MAX_PATH];
GetItemName(pff, pflHfpl, szName, ARRAYSIZE(szName)); hr = _ReinsertDlgText(hwnd, szName, SZ_WSPRINTFSTR_S);
// We only use the static filename when more than one item is selected
// because that is the case that we can't do a rename. Are there
// multiple items selected?
if (!m_fEditable || !CanEditName(pff, pflHfpl)) { // Hide because we will use IDC_FILENAME_EDITABLE instead.
ShowEnableWindow(hwnd, FALSE); }
return hr; }
void GetNameFromPidlList(CFtpFolder * pff, CFtpPidlList * pflHfpl, LPWSTR pwzName, DWORD cchSize) { LPCITEMIDLIST pidl; if (0 == pflHfpl->GetCount()) pidl = FtpID_GetLastIDReferense(pff->GetPrivatePidlReference()); else pidl = FtpID_GetLastIDReferense(pflHfpl->GetPidl(0));
if (pidl) { FtpPidl_GetLastItemDisplayName(pidl, pwzName, cchSize); } }
/*****************************************************************************\
FUNCTION: _InitType DESCRIPTION: Get the type of the pidls identified by pflHfpl. \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitType(HWND hwnd, CFtpFolder * pff, CFtpPidlList * pflHfpl) { TCHAR szType[MAX_URL_STRING]; szType[0] = 0; switch (pflHfpl->GetCount()) { case 0: { // Find out if it's a folder or an ftp server root.
LPCITEMIDLIST pidl = FtpID_GetLastIDReferense(pff->GetPrivatePidlReference()); if (pidl) LoadString(HINST_THISDLL, (FtpID_IsServerItemID(pidl) ? IDS_ITEMTYPE_SERVER : IDS_ITEMTYPE_FOLDER), szType, ARRAYSIZE(szType)); } break; case 1: // Just one item is selected, so get it's type.
FtpPidl_GetFileType(pflHfpl->GetPidl(0), szType, ARRAYSIZE(szType)); break; default: // Display "Several Selected" because they can span 1 type.
LoadString(HINST_THISDLL, IDS_SEVERAL_SELECTED, szType, ARRAYSIZE(szType)); break; } return _ReinsertDlgText(hwnd, szType, SZ_WSPRINTFSTR_S); }
/*****************************************************************************\
FUNCTION: _InitLocation DESCRIPTION: Get the name of the folder identified by pidl. \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitLocation(HWND hwnd, CFtpFolder * pff, CFtpPidlList * pidlList) { HRESULT hr = E_FAIL; TCHAR szUrl[MAX_PATH]; LPITEMIDLIST pidl = GetPidlFromFtpFolderAndPidlList(pff, pidlList);
ASSERT(pidlList && pff); if (pidl) { // If more than one items are selected, then we only want to
// show the common location.
if (1 < pidlList->GetCount()) ILRemoveLastID(pidl); hr = UrlCreateFromPidl(pidl, SHGDN_FORADDRESSBAR, szUrl, ARRAYSIZE(szUrl), 0, TRUE); if (SUCCEEDED(hr)) { hr = _ReinsertDlgText(hwnd, szUrl, SZ_WSPRINTFSTR_S); } ILFree(pidl); }
return hr; }
/*****************************************************************************\
FUNCTION: _InitSizeTally DESCRIPTION: Total up the size of each file referred to in the pidl. \*****************************************************************************/ int CFtpDialogTemplate::_InitSizeTally(LPVOID pvPidl, LPVOID pvSizeHolder) { BOOL fSuccess = TRUE; LPCITEMIDLIST pidl = (LPCITEMIDLIST) pvPidl; CSizeHolder * pSizeHolder = (CSizeHolder *) pvSizeHolder;
// Did we get a valid size and is pSizeHolder still valid?
if (SUCCEEDED(pSizeHolder->GetError())) { // Yes, so keep accumulating if it's a file.
if (!FtpID_IsServerItemID(pidl) && !FtpItemID_IsDirectory(pidl, FALSE)) { ULARGE_INTEGER uliPidlFileSize; uliPidlFileSize.QuadPart = FtpItemID_GetFileSize(pidl);
pSizeHolder->AddSize(uliPidlFileSize.QuadPart); pSizeHolder->FoundNonFolder(); // Show that at least one was a file.
if (!uliPidlFileSize.QuadPart) fSuccess = FALSE; } } else { pSizeHolder->SetError(E_FAIL); fSuccess = FALSE; }
return fSuccess; }
#define MAX_FILE_SIZE 64
HRESULT GetFileSizeFromULargeInteger(ULARGE_INTEGER uliSize, LPTSTR pszSizeStr, DWORD cchSize) { WCHAR wzSizeStr[MAX_FILE_SIZE]; LONGLONG llSize = (LONGLONG) uliSize.QuadPart;
if (StrFormatByteSizeW(llSize, wzSizeStr, ARRAYSIZE(wzSizeStr))) SHUnicodeToTChar(wzSizeStr, pszSizeStr, cchSize); else { CHAR szStrStrA[MAX_FILE_SIZE];
StrFormatByteSizeA(uliSize.LowPart, szStrStrA, ARRAYSIZE(szStrStrA)); SHAnsiToTChar(szStrStrA, pszSizeStr, cchSize); }
return S_OK; }
// From shlwapi.
void Int64ToStr(LONGLONG n, LPTSTR lpBuffer, DWORD cchSize) { TCHAR szTemp[40]; LONGLONG iChr = 0;
ASSERT(cchSize > ARRAYSIZE(szTemp)); do { szTemp[iChr++] = TEXT('0') + (TCHAR)(n % 10); n = n / 10; } while (n != 0);
do { iChr--; *lpBuffer++ = szTemp[iChr]; } while (iChr != 0);
*lpBuffer++ = TEXT('\0'); }
/*****************************************************************************\
FUNCTION: _InitSize DESCRIPTION: \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitSize(HWND hwnd, HWND hwndLabel, CFtpFolder * pff, CFtpPidlList * pflHfpl) { HRESULT hr; TCHAR szSizeStr[MAX_FILE_SIZE]; CSizeHolder sizeHolder;
szSizeStr[0] = 0; // GetCount maybe 0 if we are doing the background folder.
if (0 < pflHfpl->GetCount()) { pflHfpl->Enum(CFtpDialogTemplate::_InitSizeTally, (LPVOID) &sizeHolder); if (SUCCEEDED(sizeHolder.GetError())) { // Are there files sizes to display?
if (!sizeHolder.IsAllFolders()) { TCHAR szBytesStr[MAX_FILE_SIZE]; TCHAR szBytesStrFormatted[MAX_FILE_SIZE]; TCHAR szCondencedSizeStr[MAX_FILE_SIZE]; ULARGE_INTEGER uliTotal; uliTotal.QuadPart = sizeHolder.GetTotalSize();
NUMBERFMT numfmt = {0, 0, 3, TEXT(""), TEXT(","), 0};
EVAL(SUCCEEDED(GetFileSizeFromULargeInteger(uliTotal, szCondencedSizeStr, ARRAYSIZE(szCondencedSizeStr))));
Int64ToStr(uliTotal.QuadPart, szBytesStr, ARRAYSIZE(szBytesStr)); GetNumberFormat(LOCALE_USER_DEFAULT, 0, szBytesStr, &numfmt, szBytesStrFormatted, ARRAYSIZE(szBytesStrFormatted)); wnsprintf(szSizeStr, ARRAYSIZE(szSizeStr), TEXT("%s (%s bytes)"), szCondencedSizeStr, szBytesStrFormatted); } } }
if (szSizeStr[0]) { hr = _ReinsertDlgText(hwnd, szSizeStr, SZ_WSPRINTFSTR_S); } else { // If more than one item was selected...
// remove both the label and the value.
ShowEnableWindow(hwnd, FALSE); if (hwndLabel) ShowEnableWindow(hwndLabel, FALSE);
hr = S_OK; }
return hr; }
// WINVER 0x0500 definition
#ifndef WS_EX_LAYOUTRTL
#define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
#endif
/*****************************************************************************\
FUNCTION: _InitTime DESCRIPTION: \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitTime(HWND hwnd, HWND hwndLabel, CFtpFolder * pff, CFtpPidlList * pflHfpl) { TCHAR szDateTime[MAX_PATH]; HRESULT hr = E_FAIL; DWORD dwFlags = FDTF_SHORTTIME | FDTF_LONGDATE; LCID locale = GetUserDefaultLCID();
if ((PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_ARABIC) || (PRIMARYLANGID(LANGIDFROMLCID(locale)) == LANG_HEBREW)) { DWORD dwExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
if ((BOOLIFY(dwExStyle & WS_EX_RTLREADING)) != (BOOLIFY(dwExStyle & WS_EX_LAYOUTRTL))) dwFlags |= FDTF_RTLDATE; else dwFlags |= FDTF_LTRDATE; } switch (pflHfpl->GetCount()) { // one item was selected so get the time for that item.
case 1: if (!FtpID_IsServerItemID(pflHfpl->GetPidl(0))) { FILETIME ftLastModified = FtpPidl_GetFileTime(pflHfpl->GetPidl(0)); Misc_StringFromFileTime(szDateTime, ARRAYSIZE(szDateTime), &ftLastModified, dwFlags); hr = S_OK; } break;
// zero items selected means get the properties for the background folder
case 0: { LPCITEMIDLIST pidl = FtpID_GetLastIDReferense(pff->GetPrivatePidlReference()); // The user will get 'N/A' for the 'Server' folder. (i.e. ftp://ohserv/)
if (EVAL(pidl) && !FtpID_IsServerItemID(pidl)) { FILETIME ftLastModified = FtpPidl_GetFileTime(pidl); Misc_StringFromFileTime(szDateTime, ARRAYSIZE(szDateTime), &ftLastModified, dwFlags); hr = S_OK; } // Don't free pidl because we have a pointer to someone else's copy.
} }
if (SUCCEEDED(hr)) { hr = _ReinsertDlgText(hwnd, szDateTime, SZ_WSPRINTFSTR_S); } else { // If more than one item was selected...
// remove both the label and the value.
ShowEnableWindow(hwnd, FALSE); if (hwndLabel) ShowEnableWindow(hwndLabel, FALSE);
hr = S_OK; }
return hr; }
/*****************************************************************************\
FUNCTION: _InitCount DESCRIPTION: \*****************************************************************************/ HRESULT CFtpDialogTemplate::_InitCount(HWND hwnd, CFtpFolder * pff, CFtpPidlList * pflHfpl) { return _ReinsertDlgText(hwnd, IntToPtr(pflHfpl->GetCount()), SZ_WSPRINTFSTR_U); }
/*****************************************************************************\
FUNCTION: InitDialog DESCRIPTION: \*****************************************************************************/ HRESULT CFtpDialogTemplate::InitDialog(HWND hDlg, BOOL fEditable, UINT id, CFtpFolder * pff, CFtpPidlList * pPidlList) { HRESULT hr = S_OK; int nDlgTemlItem;
m_fEditable = fEditable; for (nDlgTemlItem = 0; nDlgTemlItem < DLGTEML_MAX; nDlgTemlItem++) { HRESULT hrTemp = S_OK;
HWND hwnd = GetDlgItem(hDlg, id + nDlgTemlItem); HWND hwndLabel = GetDlgItem(hDlg, id + nDlgTemlItem + DLGTEML_LABEL); if (hwnd) { switch (nDlgTemlItem) { case DLGTEML_FILENAME: hrTemp = _InitName(hwnd, pff, pPidlList); break; case DLGTEML_FILENAMEEDITABLE: hrTemp = _InitNameEditable(hwnd, pff, pPidlList); break; case DLGTEML_FILEICON: hrTemp = _InitIcon(hwnd, pff, pPidlList); break; case DLGTEML_FILESIZE: hrTemp = _InitSize(hwnd, hwndLabel, pff, pPidlList); break; case DLGTEML_FILETIME: hrTemp = _InitTime(hwnd, hwndLabel, pff, pPidlList); break; case DLGTEML_FILETYPE: hrTemp = _InitType(hwnd, pff, pPidlList); break; case DLGTEML_LOCATION: hrTemp = _InitLocation(hwnd, pff, pPidlList); break; case DLGTEML_COUNT: hrTemp = _InitCount(hwnd, pff, pPidlList); break; default: ASSERT(0); // What are you thinking?
break; } }
if (EVAL(SUCCEEDED(hr))) hr = hrTemp; // Propogate out the worst error.
}
return hr; }
/*****************************************************************************\
FUNCTION: OnClose DESCRIPTION: \*****************************************************************************/ BOOL CFtpDialogTemplate::OnClose(HWND hdlg, HWND hwndBrowser, CFtpFolder * pff, CFtpPidlList * pPidlList) { BOOL fCanClose = TRUE;
// If the IDC_FILENAME_EDITABLE field is showing, then the user may have done
// a rename. Check if that happened and if so, do it now.
if (IsWindowVisible(GetDlgItem(hdlg, IDC_FILENAME_EDITABLE))) { WCHAR wzOldName[MAX_PATH]; WCHAR wzNewName[MAX_PATH];
GetNameFromPidlList(pff, pPidlList, wzOldName, ARRAYSIZE(wzOldName)); EVAL(GetWindowTextW(GetDlgItem(hdlg, IDC_FILENAME_EDITABLE), wzNewName, ARRAYSIZE(wzNewName)));
// Was the name changed?
if (StrCmpW(wzOldName, wzNewName)) { // Yes, so change it.
IShellFolder * psfParent = NULL; CFtpFolder * pffParent = pff; LPCITEMIDLIST pidlItem;
if (0 == pPidlList->GetCount()) { // We use pidlTarget mainly because we want to assure that the
// ChangeNotifies are fired with pidlTarget.
LPITEMIDLIST pidlParent = pff->GetPublicTargetPidlClone();
if (pidlParent) { ILRemoveLastID(pidlParent); pidlItem = FtpID_GetLastIDReferense(pff->GetPrivatePidlReference()); IEBindToObject(pidlParent, &psfParent); ILFree(pidlParent); } } else { pidlItem = FtpID_GetLastIDReferense(pPidlList->GetPidl(0)); EVAL(SUCCEEDED(pff->QueryInterface(IID_IShellFolder, (void **) &psfParent))); }
if (psfParent) { if (EVAL(pidlItem)) fCanClose = ((S_OK == psfParent->SetNameOf(hwndBrowser, pidlItem, wzNewName, NULL, NULL)) ? TRUE : FALSE);
psfParent->Release(); } } }
return fCanClose; }
/*****************************************************************************\
FUNCTION: OnDestroy DESCRIPTION: \*****************************************************************************/ BOOL CFtpDialogTemplate::OnDestroy(HWND hDlg, BOOL fEditable, UINT id, CFtpFolder* pff, CFtpPidlList* pPidlList) { HRESULT hr = S_OK; int nDlgTemlItem;
for (nDlgTemlItem = 0; nDlgTemlItem < DLGTEML_MAX; nDlgTemlItem++) { HRESULT hrTemp = S_OK;
HWND hwnd = GetDlgItem(hDlg, id + nDlgTemlItem); HWND hwndLabel = GetDlgItem(hDlg, id + nDlgTemlItem + DLGTEML_LABEL); if (hwnd) { switch (nDlgTemlItem) {
case DLGTEML_FILEICON: hrTemp = _ReplaceIcon(hwnd, NULL); break;
case DLGTEML_FILENAME: case DLGTEML_FILENAMEEDITABLE: case DLGTEML_FILESIZE: case DLGTEML_FILETIME: case DLGTEML_FILETYPE: case DLGTEML_LOCATION: case DLGTEML_COUNT: break;
default: ASSERT(0); // What are you thinking?
break; } }
if (SUCCEEDED(hr)) { // Propogate out the worst error.
hr = hrTemp; } }
return hr; }
BOOL CFtpDialogTemplate::HasNameChanged(HWND hdlg, CFtpFolder * pff, CFtpPidlList * pPidlList) { BOOL fNameChanged = FALSE;
// If the IDC_FILENAME_EDITABLE field is showing, then the user may have done
// a rename. Check if that happened and if so, do it now.
if (IsWindowVisible(GetDlgItem(hdlg, IDC_FILENAME_EDITABLE))) { TCHAR szOldName[MAX_PATH]; TCHAR szNewName[MAX_PATH];
GetNameFromPidlList(pff, pPidlList, szOldName, ARRAYSIZE(szOldName)); EVAL(GetWindowText(GetDlgItem(hdlg, IDC_FILENAME_EDITABLE), szNewName, ARRAYSIZE(szNewName)));
// Was the name changed?
if (StrCmp(szOldName, szNewName)) { // Yes, so change it.
fNameChanged = TRUE; } }
return fNameChanged; }
HRESULT CFtpDialogTemplate::InitDialogWithFindData(HWND hDlg, UINT id, CFtpFolder * pff, const FTP_FIND_DATA * pwfd, LPCWIRESTR pwWirePath, LPCWSTR pwzDisplayPath) { FTP_FIND_DATA wfd = *pwfd; LPITEMIDLIST pidl; HRESULT hr; ASSERT(pwfd);
StrCpyNA(wfd.cFileName, pwWirePath, ARRAYSIZE(wfd.cFileName)); hr = FtpItemID_CreateReal(&wfd, pwzDisplayPath, &pidl); if (SUCCEEDED(hr)) { CFtpPidlList * pfpl = NULL; hr = CFtpPidlList_Create(1, (LPCITEMIDLIST *) &pidl, &pfpl); if (SUCCEEDED(hr)) { hr = InitDialog(hDlg, FALSE, id, pff, pfpl); pfpl->Release(); }
ILFree(pidl); } return hr; }
|