|
|
#include "priv.h"
#include "fldset.h"
#define IShellView_CreateViewWindow(_pi, _piPrev, _pfs, _psb, _prc, _phw) \
(_pi)->CreateViewWindow(_piPrev, _pfs, _psb, _prc, _phw)
#define IShellView2_GetView(_pi, _pv, _flg) \
(_pi)->GetView(_pv, _flg) #define IShellView2_CreateViewWindow2(_pi, _cParams) \
(_pi)->CreateViewWindow2(_cParams)
#define IUnknown_QueryInterface(_pu, _riid, _pi) \
(_pu)->QueryInterface(_riid, (LPVOID*)_pi) #define IUnknown_AddRef(_pu) (_pu)->AddRef()
#define IUnknown_Release(_pu) (_pu)->Release()
typedef struct CViewSet { HDSA _dsaViews; } CViewSet;
CViewSet* CViewSet_New() { CViewSet* pThis = (CViewSet*)LocalAlloc(LPTR, SIZEOF(CViewSet)); if (!pThis) { return(NULL); }
pThis->_dsaViews = DSA_Create(SIZEOF(SHELLVIEWID), 8); if (!pThis->_dsaViews) { LocalFree(pThis); pThis = NULL; }
return(pThis); }
int CViewSet_Add(CViewSet* that, SHELLVIEWID const* pvid) { return(DSA_AppendItem(that->_dsaViews, (LPVOID)pvid)); }
void CViewSet_Delete(CViewSet* that) { DSA_Destroy(that->_dsaViews); that->_dsaViews = NULL; LocalFree((HLOCAL)that); that = NULL; }
void CViewSet_GetDefaultView(CViewSet* that, SHELLVIEWID* pvid) { DSA_GetItem(that->_dsaViews, 0, (LPVOID)pvid); }
void CViewSet_SetDefaultView(CViewSet* that, SHELLVIEWID const* pvid) { DSA_SetItem(that->_dsaViews, 0, (LPVOID)pvid); }
// PERF: A linear search for the view
BOOL CViewSet_IsViewSupported(CViewSet* that, SHELLVIEWID const* pvid) { int i;
// Only go down to 1 since item 0 is the default view
for (i=DSA_GetItemCount(that->_dsaViews)-1; i>=1; --i) { if (0 == memcmp(pvid, DSA_GetItemPtr(that->_dsaViews, i), SIZEOF(SHELLVIEWID))) { return(TRUE); } }
return(FALSE); }
// PERF: a linear check
BOOL CViewSet_IsSame(CViewSet* that, CViewSet* pThatView) { int iView = DSA_GetItemCount(pThatView->_dsaViews);
if (DSA_GetItemCount(that->_dsaViews) != iView) { return(FALSE); }
for (--iView; iView>=1; --iView) { if (!CViewSet_IsViewSupported(that, (SHELLVIEWID const*)DSA_GetItemPtr(pThatView->_dsaViews, iView))) { return(FALSE); } }
return(TRUE); }
BOOL CShellViews_Init(CShellViews* that) { if (that->_dpaViews) { return(TRUE); }
{ HDPA dpaViews = DPA_Create(4); if (!dpaViews) { return(FALSE); }
{ CViewSet* pCommViews = CViewSet_New(); if (!pCommViews) { DPA_Destroy(dpaViews); dpaViews = NULL; return(FALSE); }
// The first one is the last known view for that set
CViewSet_Add(pCommViews, &VID_LargeIcons); CViewSet_Add(pCommViews, &VID_LargeIcons); CViewSet_Add(pCommViews, &VID_SmallIcons); CViewSet_Add(pCommViews, &VID_Thumbnails); CViewSet_Add(pCommViews, &VID_List ); CViewSet_Add(pCommViews, &VID_Details ); CViewSet_Add(pCommViews, &VID_Tile );
if (0 != DPA_InsertPtr(dpaViews, 0, pCommViews)) { CViewSet_Delete(pCommViews); DPA_Destroy(dpaViews); dpaViews = NULL; return(FALSE); }
that->_dpaViews = dpaViews; return(TRUE); } } }
void CShellViews_GetDefaultView(CShellViews* that, UINT uViewSet, SHELLVIEWID* pvid) { CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet); if (!pViewSet) { pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, 0); if (!pViewSet) { *pvid = VID_LargeIcons; return; } }
CViewSet_GetDefaultView(pViewSet, pvid); }
void CShellViews_SetDefaultView(CShellViews* that, UINT uViewSet, SHELLVIEWID const* pvid) { CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet); if (!pViewSet) { return; }
CViewSet_SetDefaultView(pViewSet, pvid); }
// PERF: a linear search for the view set
int CShellViews_Add(CShellViews* that, CViewSet* pThisView, BOOL *pbNew) { int iViewSet;
*pbNew = FALSE;
for (iViewSet=0; ; ++iViewSet) { CViewSet* pThatView = (CViewSet*)DPA_GetPtr(that->_dpaViews, iViewSet); if (!pThatView) { break; }
if (CViewSet_IsSame(pThatView, pThisView)) { // Found the same set; delete the one passed in and hand back the
// existing one
CViewSet_Delete(pThisView); return(iViewSet); } }
// I guess we didn't find it
iViewSet = DPA_AppendPtr(that->_dpaViews, (LPVOID)pThisView); if (iViewSet < 0) { CViewSet_Delete(pThisView); return(0); }
*pbNew = TRUE; return(iViewSet); }
BOOL CShellViews_IsViewSupported(CShellViews* that, UINT uViewSet, SHELLVIEWID const*pvid) { CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet); if (!pViewSet) { return(FALSE); }
return(CViewSet_IsViewSupported(pViewSet, pvid)); }
int DPA_CViewSet_DeleteCallback(LPVOID p, LPVOID d) { if (p) CViewSet_Delete((CViewSet*)p); return 1; }
void CShellViews_Delete(CShellViews* that) { if (that && that->_dpaViews) { DPA_DestroyCallback(that->_dpaViews, DPA_CViewSet_DeleteCallback, 0); that->_dpaViews = NULL; } }
BOOL FileCabinet_GetDefaultViewID2(FOLDERSETDATABASE* that, SHELLVIEWID* pvid) { if (CShellViews_Init(&that->_cViews)) { CShellViews_GetDefaultView(&that->_cViews, that->_iViewSet, pvid); return(TRUE); }
return(FALSE); }
HRESULT FileCabinet_CreateViewWindow2(IShellBrowser* psb, FOLDERSETDATABASE* that, IShellView *psvNew, IShellView *psvOld, RECT *prcView, HWND *phWnd) { SHELLVIEWID vid, vidOld, vidRestore; IShellView2 *psv2New; CViewSet *pThisView; DWORD dwViewPriority; BOOL bCalledSV2 = FALSE; HRESULT hres = S_OK; // init to avoid a bogus C4701 warning
if (!CShellViews_Init(&that->_cViews)) { // Can't do anything with view sets; just do the old thing
goto OldStyle; }
// Default to whatever the last "old-style" view is
CShellViews_GetDefaultView(&that->_cViews, 0, &vidOld);
if (psvOld) { IShellView2 *psv2Old;
if (SUCCEEDED(IUnknown_QueryInterface(psvOld, IID_IShellView2, &psv2Old))) { // Try to get the current view
if (NOERROR == IShellView2_GetView(psv2Old, &vidOld, SV2GV_CURRENTVIEW)) { CShellViews_SetDefaultView(&that->_cViews, that->_iViewSet, &vidOld); }
IUnknown_Release(psv2Old); } else { // Get the view ID from the folder settings
ViewIDFromViewMode(that->_fld._fs.ViewMode, &vidOld); CShellViews_SetDefaultView(&that->_cViews, 0, &vidOld); } }
pThisView = CViewSet_New(); if (!pThisView) { goto OldStyle; }
if (SUCCEEDED(IUnknown_QueryInterface(psvNew, IID_IShellView2, &psv2New))) { SHELLVIEWID vidFolderDefault; if (NOERROR == IShellView2_GetView(psv2New, &vidFolderDefault, SV2GV_DEFAULTVIEW)) { // we can now make up a view set for that folder
if (CViewSet_Add(pThisView, &vidFolderDefault) >= 0) { int iViewSet; UINT uView; BOOL bNew;
// NOTE: This usage of IShellView2::GetView is not documented in MSDN...
for (uView=0; NOERROR==IShellView2_GetView(psv2New, &vid, uView); ++uView) { CViewSet_Add(pThisView, &vid); }
// Add that view set. we will get an existing view set if it is
// a duplicate
iViewSet = CShellViews_Add(&that->_cViews, pThisView, &bNew); // This is now owned by CShellViews
pThisView = NULL;
//
// Here is where we decide which view we want to use.
//
// Start with what came from the FOLDERSETDATABASE, then see if
// anyone else has a higher VIEW_PRIORITY_XXX that would override this one.
vidRestore = that->_fld._vidRestore; dwViewPriority = that->_fld._dwViewPriority;
// ToddB, 8-18-99:
// When we set the _fld._dwViewPriority in WebBrowserOc::Load(IPropertyBag *...) we want that ViewID to stick
// around. Only failing the CShellViews_IsViewSupported call below should set a different view. Even then
// we want to go back to this view on the next navigate. To accomplish this we need to keep the priority of
// that view at what it was originally set to. This can be done by removing the following line of code:
//
// that->_fld._dwViewPriority = VIEW_PRIORITY_NONE;
//
// However, its possible that the line of code above was there for a good reason. I suspect that line was
// originally added simply as a precaution or because the meaning of _vidRestore was not clearly defined in
// relation to navigation inside a WebBrowserOC. I'm leaving the line here and commented out just in case.
// If any new bugs arise about changing the view window and getting the wrong view I would look here first.
// Make sure that what we got is a supported view
if (!CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidRestore)) { // Oops, that view isn't supported by this shell ext.
// Set the priority to NONE so that one of the others will override it.
dwViewPriority = VIEW_PRIORITY_NONE; }
DWORD cbSize; DWORD dwValue; DWORD dwShellExtPriority; cbSize = SIZEOF(dwValue); if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"), TEXT("ClassicViewState"), NULL, &dwValue, &cbSize) && dwValue) { // We want to inherit from the previous folder if at all possible
// Otherwise, we will use the new shell extended view.
// To do this, we set the shell ext view priority lower than inherit
dwShellExtPriority = VIEW_PRIORITY_SHELLEXT_ASBACKUP; } else { dwShellExtPriority = VIEW_PRIORITY_SHELLEXT; }
// Let the shell ext select the view if it has higher priority than
// what we already have, and it is supported as well.
if (dwViewPriority <= dwShellExtPriority && ((GetUIVersion() >= 5) || (vidFolderDefault != VID_LargeIcons)) && // downlevel browser assumes VID_LargeIcons means "default"
CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidFolderDefault)) { // shell extension is more important
vidRestore = vidFolderDefault; dwViewPriority = dwShellExtPriority; } // Maybe we can inherit it from the previous view...
if (dwViewPriority <= VIEW_PRIORITY_INHERIT && psvOld && bNew && CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidOld)) { // We just navigated from another shell view. Use the same view as the last
// folder.
vidRestore = vidOld; dwViewPriority = VIEW_PRIORITY_INHERIT; }
// We're getting really desperate now...
if (dwViewPriority <= VIEW_PRIORITY_DESPERATE) { // Try the last view for the folders current viewset.
CShellViews_GetDefaultView(&that->_cViews, iViewSet, &vidRestore); dwViewPriority = VIEW_PRIORITY_DESPERATE; } // All finished trying to figure out what view to use
ASSERT(dwViewPriority > VIEW_PRIORITY_NONE);
// assure webview no in vid, it is persisted in shellstate now.
{ SV2CVW2_PARAMS cParams = { SIZEOF(SV2CVW2_PARAMS),
psvOld, &that->_fld._fs, psb, prcView, &vidRestore,
NULL, } ;
hres = IShellView2_CreateViewWindow2(psv2New, &cParams); bCalledSV2 = TRUE; *phWnd = cParams.hwndView; }
if (SUCCEEDED(hres)) { that->_iViewSet = iViewSet; } } }
IUnknown_Release(psv2New); }
if (pThisView) { CViewSet_Delete(pThisView); }
if (bCalledSV2) { return(hres); }
OldStyle: that->_iViewSet = 0; return IShellView_CreateViewWindow(psvNew, psvOld, &that->_fld._fs, (IShellBrowser*)psb, prcView, phWnd); }
|