2613 lines
75 KiB
C++
2613 lines
75 KiB
C++
#include "pch.hxx"
|
|
#include <iert.h>
|
|
#include <store.h>
|
|
#include <storecb.h>
|
|
#include "resource.h"
|
|
#include "ourguid.h"
|
|
#include "thormsgs.h"
|
|
#include "goptions.h"
|
|
#include "strconst.h"
|
|
#include <inetcfg.h>
|
|
#include <fonts.h>
|
|
#include <columns.h>
|
|
#include <imagelst.h>
|
|
#include <instance.h>
|
|
#include <spoolui.h>
|
|
#include <options.h>
|
|
#include <acctutil.h>
|
|
#include "shlwapip.h"
|
|
#include <menuutil.h>
|
|
#include "storutil.h"
|
|
#include <outbar.h>
|
|
#include <subscr.h>
|
|
#include "newsutil.h"
|
|
#include "acctview.h"
|
|
#include <newfldr.h>
|
|
#include <mailutil.h>
|
|
#include "menures.h"
|
|
#include "demand.h"
|
|
|
|
ASSERTDATA
|
|
|
|
#define SUBSCRIBE_BORDER 7
|
|
#define CALLOCIDBUF 256
|
|
#define IDC_SUBSCRIBE_LIST (ID_FIRST - 4)
|
|
#define FOLDER_SYNCMASK (FOLDER_DOWNLOADHEADERS | FOLDER_DOWNLOADNEW | FOLDER_DOWNLOADALL)
|
|
|
|
static const char c_szAcctViewWndClass[] = "Outlook Express AcctView";
|
|
|
|
int __cdecl GroupCompare(const void *lParam1, const void *lParam2) ;
|
|
void DrawSettingsButton(HWND hwnd, LPDRAWITEMSTRUCT pdi);
|
|
#define C_RGBCOLORS 16
|
|
extern const DWORD rgrgbColors16[C_RGBCOLORS];
|
|
|
|
typedef struct tagACCTVIEWBTN
|
|
{
|
|
int idsText;
|
|
int cmd;
|
|
} ACCTVIEWBTN;
|
|
|
|
static const ACCTVIEWBTN c_rgMailBtns[] =
|
|
{
|
|
{ idsDeliverMailTT, ID_SEND_RECEIVE }
|
|
};
|
|
|
|
static const ACCTVIEWBTN c_rgImapBtns[] =
|
|
{
|
|
{ idsSynchronizeNowBtn, ID_SYNC_THIS_NOW },
|
|
{ idsIMAPFoldersBtn, ID_IMAP_FOLDERS },
|
|
{ idsSettingsBtn, ID_POPUP_SYNCHRONIZE }
|
|
};
|
|
|
|
static const ACCTVIEWBTN c_rgNewsBtns[] =
|
|
{
|
|
{ idsSynchronizeNowBtn, ID_SYNC_THIS_NOW },
|
|
{ idsNewsgroupsBtn, ID_NEWSGROUPS },
|
|
{ idsSettingsBtn, ID_POPUP_SYNCHRONIZE }
|
|
};
|
|
|
|
static const ACCTVIEWBTN c_rgHttpBtns[] =
|
|
{
|
|
{ idsSynchronizeNowBtn, ID_SYNC_THIS_NOW },
|
|
{ idsSettingsBtn, ID_POPUP_SYNCHRONIZE }
|
|
};
|
|
|
|
CAccountView::CAccountView()
|
|
{
|
|
m_cRef = 1;
|
|
// m_ftType
|
|
m_pShellBrowser = NULL;
|
|
m_fFirstActive = FALSE;
|
|
m_pColumns = NULL;
|
|
m_uActivation = SVUIA_DEACTIVATE;
|
|
m_hwndOwner = NULL;
|
|
m_hwnd = NULL;
|
|
m_idFolder = FOLDERID_INVALID;
|
|
m_fRegistered = FALSE;
|
|
|
|
m_hwndList = NULL;
|
|
m_pszMajor = NULL;
|
|
m_pszMinor = NULL;
|
|
m_cBtns = 0;
|
|
|
|
m_cnode = 0;
|
|
m_cnodeBuf = 0;
|
|
m_rgnode = NULL;
|
|
|
|
m_himlFolders = NULL;
|
|
m_pEmptyList = NULL;
|
|
|
|
m_pGroups = NULL;
|
|
m_clrWatched = 0;
|
|
}
|
|
|
|
CAccountView::~CAccountView()
|
|
{
|
|
if (m_pGroups != NULL)
|
|
{
|
|
m_pGroups->Close();
|
|
m_pGroups->Release();
|
|
}
|
|
|
|
if (m_rgnode != NULL)
|
|
MemFree(m_rgnode);
|
|
|
|
SafeRelease(m_pShellBrowser);
|
|
SafeRelease(m_pColumns);
|
|
|
|
if (m_pEmptyList != NULL)
|
|
delete m_pEmptyList;
|
|
|
|
if (m_himlFolders != NULL)
|
|
ImageList_Destroy(m_himlFolders);
|
|
|
|
if (m_pszMajor != NULL)
|
|
MemFree(m_pszMajor);
|
|
if (m_pszMinor != NULL)
|
|
MemFree(m_pszMinor);
|
|
}
|
|
|
|
HRESULT CAccountView::HrInit(FOLDERID idFolder)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
if (!GetClassInfo(g_hInst, c_szAcctViewWndClass, &wc))
|
|
{
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = CAccountView::AcctViewWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = g_hInst;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = c_szAcctViewWndClass;
|
|
if (RegisterClass(&wc) == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
|
|
return E_FAIL;
|
|
}
|
|
|
|
m_idFolder = idFolder;
|
|
m_ftType = GetFolderType(idFolder);
|
|
|
|
m_dwDownloadDef = (m_ftType == FOLDER_NEWS) ? FOLDER_DOWNLOADNEW : FOLDER_DOWNLOADALL;
|
|
|
|
// Set the image lists for the listview
|
|
Assert(m_himlFolders == NULL);
|
|
m_himlFolders = InitImageList(16, 16, MAKEINTRESOURCE(idbFolders), cFolderIcon, RGB(255, 0, 255));
|
|
Assert(m_himlFolders);
|
|
|
|
m_pEmptyList = new CEmptyList;
|
|
if (m_pEmptyList == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OLE Interfaces
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IUnknown
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (void*) (IUnknown *)(IViewWindow *)this;
|
|
else if (IsEqualIID(riid, IID_IViewWindow))
|
|
*ppvObj = (void*) (IViewWindow *) this;
|
|
else if (IsEqualIID(riid, IID_IOleCommandTarget))
|
|
*ppvObj = (void*) (IOleCommandTarget *) this;
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CAccountView::AddRef()
|
|
{
|
|
DOUT(TEXT("CAccountView::AddRef() - m_cRef = %d"), m_cRef + 1);
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CAccountView::Release()
|
|
{
|
|
DOUT(TEXT("CAccountView::Release() - m_cRef = %d"), m_cRef - 1);
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IOleWindow
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::GetWindow(HWND * lphwnd)
|
|
{
|
|
*lphwnd = m_hwnd;
|
|
return (m_hwnd ? S_OK : E_FAIL);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::ContextSensitiveHelp(BOOL fEnterMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IAthenaView
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::TranslateAccelerator(LPMSG lpmsg)
|
|
{
|
|
return(S_FALSE);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::UIActivate(UINT uActivation)
|
|
{
|
|
if (uActivation != SVUIA_DEACTIVATE)
|
|
_OnActivate(uActivation);
|
|
else
|
|
_OnDeactivate();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::CreateViewWindow(IViewWindow *lpPrevView, IAthenaBrowser *psb,
|
|
RECT *prcView, HWND *phWnd)
|
|
{
|
|
FOLDERINFO info;
|
|
|
|
m_pShellBrowser = psb;
|
|
Assert(m_pShellBrowser);
|
|
m_pShellBrowser->AddRef();
|
|
|
|
m_pShellBrowser->GetWindow(&m_hwndOwner);
|
|
Assert(IsWindow(m_hwndOwner));
|
|
|
|
m_pColumns = new CColumns;
|
|
if (m_pColumns == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
m_hwnd = CreateWindowEx(WS_EX_CONTROLPARENT|WS_EX_CLIENTEDGE,
|
|
c_szAcctViewWndClass,
|
|
NULL,
|
|
WS_VISIBLE|WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
|
|
prcView->left,
|
|
prcView->top,
|
|
prcView->right - prcView->left,
|
|
prcView->bottom - prcView->top,
|
|
m_hwndOwner,
|
|
NULL,
|
|
g_hInst,
|
|
(LPVOID)this);
|
|
|
|
if (!m_hwnd)
|
|
return E_FAIL;
|
|
|
|
*phWnd = m_hwnd;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::DestroyViewWindow()
|
|
{
|
|
HRESULT hr;
|
|
HWND hwndDest;
|
|
|
|
if (m_fRegistered)
|
|
g_pStore->UnregisterNotify((IDatabaseNotify *)this);
|
|
|
|
if (m_hwnd)
|
|
{
|
|
hwndDest = m_hwnd;
|
|
m_hwnd = NULL;
|
|
|
|
DestroyWindow(hwndDest);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CAccountView::SaveViewState()
|
|
{
|
|
Assert(m_pColumns != NULL);
|
|
m_pColumns->Save(NULL, NULL);
|
|
|
|
OptionUnadvise(m_hwnd);
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CAccountView::OnInitMenuPopup
|
|
//
|
|
// PURPOSE: Called when the user is about to display a menu. We use this
|
|
// to update the enabled or disabled status of many of the
|
|
// commands on each menu.
|
|
//
|
|
// PARAMETERS:
|
|
// hmenu - Handle of the main menu.
|
|
// hmenuPopup - Handle of the popup menu being displayed.
|
|
// uID - Specifies the id of the menu item that
|
|
// invoked the popup.
|
|
//
|
|
// RETURN VALUE:
|
|
// Returns S_OK if we process the message.
|
|
//
|
|
//
|
|
HRESULT CAccountView::OnPopupMenu(HMENU hmenu, HMENU hmenuPopup, UINT uID)
|
|
{
|
|
return(S_OK);
|
|
}
|
|
|
|
DWORD CAccountView::_GetDownloadCmdStatus(int iSel, FLDRFLAGS dwFlags)
|
|
{
|
|
DWORD cmdf;
|
|
|
|
cmdf = OLECMDF_SUPPORTED;
|
|
if (m_ftType != FOLDER_LOCAL)
|
|
{
|
|
if (iSel != -1)
|
|
{
|
|
if (_IsSelectedFolder(FOLDER_SUBSCRIBED, TRUE, FALSE))
|
|
{
|
|
cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
|
|
if (_IsSelectedFolder(dwFlags, TRUE, TRUE))
|
|
cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(cmdf);
|
|
}
|
|
|
|
HRESULT CAccountView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
|
|
{
|
|
ULONG i;
|
|
BOOL fTree, fSpecial;
|
|
FOLDERID idFolder;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
int iSel, cSel, cItems, iSelT;
|
|
OLECMD *pcmd;
|
|
|
|
Assert(prgCmds != NULL);
|
|
|
|
cSel = ListView_GetSelectedCount(m_hwndList);
|
|
cItems = ListView_GetItemCount(m_hwndList);
|
|
iSel = ListView_GetNextItem(m_hwndList, -1, LVNI_ALL | LVNI_SELECTED | LVNI_FOCUSED);
|
|
if (iSel != -1 && (DWORD)iSel >= m_cnode)
|
|
iSel = -1;
|
|
fTree = !(S_OK == m_pShellBrowser->HasFocus(ITB_OEVIEW));
|
|
|
|
for (i = 0, pcmd = prgCmds; i < cCmds; i++, pcmd++)
|
|
{
|
|
if (pcmd->cmdf == 0)
|
|
{
|
|
switch (pcmd->cmdID)
|
|
{
|
|
case ID_POPUP_SYNCHRONIZE:
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
if (m_ftType != FOLDER_LOCAL && iSel != -1)
|
|
{
|
|
if (_IsSelectedFolder(FOLDER_SUBSCRIBED, TRUE, FALSE))
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
}
|
|
break;
|
|
|
|
case ID_MARK_RETRIEVE_FLD_NEW_HDRS:
|
|
pcmd->cmdf = _GetDownloadCmdStatus(iSel, FOLDER_DOWNLOADHEADERS);
|
|
break;
|
|
|
|
case ID_MARK_RETRIEVE_FLD_NEW_MSGS:
|
|
pcmd->cmdf = _GetDownloadCmdStatus(iSel, FOLDER_DOWNLOADNEW);
|
|
break;
|
|
|
|
case ID_MARK_RETRIEVE_FLD_ALL_MSGS:
|
|
pcmd->cmdf = _GetDownloadCmdStatus(iSel, FOLDER_DOWNLOADALL);
|
|
break;
|
|
|
|
case ID_UNMARK_RETRIEVE_FLD:
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
if (iSel != -1)
|
|
{
|
|
if (_IsSelectedFolder(FOLDER_SUBSCRIBED, TRUE, FALSE))
|
|
{
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
|
|
if (_IsSelectedFolder(FOLDER_SYNCMASK, FALSE, TRUE))
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_SUBSCRIBE:
|
|
case ID_UNSUBSCRIBE:
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
if ((m_ftType == FOLDER_IMAP || m_ftType == FOLDER_NEWS) && iSel != -1)
|
|
{
|
|
if (_IsSelectedFolder(FOLDER_SUBSCRIBED, pcmd->cmdID == ID_UNSUBSCRIBE, FALSE, TRUE))
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
}
|
|
break;
|
|
|
|
case ID_SELECT_ALL:
|
|
case ID_COLUMNS:
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case ID_CATCH_UP:
|
|
if (m_ftType == FOLDER_NEWS && iSel != -1)
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
break;
|
|
|
|
case ID_OPEN_FOLDER:
|
|
case ID_OPEN:
|
|
case ID_GO_SELECTED:
|
|
case ID_COMPACT:
|
|
case ID_MARK_ALL_READ:
|
|
if (iSel == -1)
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
else
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
break;
|
|
|
|
// TODO: support ID_PURGE_DELETED???
|
|
|
|
// commands below are handled by the treeview if it has the focus
|
|
// otherwise we'll handle them based on what is selected in us
|
|
|
|
case ID_PROPERTIES:
|
|
case ID_ADD_SHORTCUT:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
else
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
}
|
|
break;
|
|
|
|
case ID_NEW_FOLDER:
|
|
case ID_NEW_FOLDER2:
|
|
if (!fTree)
|
|
{
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
if (m_ftType != FOLDER_NEWS && iSel != -1)
|
|
{
|
|
hr = g_pStore->GetFolderInfo(_IdFromIndex(iSel), &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (info.tySpecial != FOLDER_DELETED)
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_DELETE:
|
|
case ID_DELETE_FOLDER:
|
|
if (!fTree)
|
|
{
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
if (iSel != -1 && m_ftType != FOLDER_NEWS)
|
|
{
|
|
iSelT = iSel;
|
|
while (iSelT != -1)
|
|
{
|
|
hr = g_pStore->GetFolderInfo(_IdFromIndex(iSelT), &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fSpecial = (info.tySpecial != FOLDER_NOTSPECIAL);
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
|
|
if (!fSpecial)
|
|
{
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
iSelT = ListView_GetNextItem(m_hwndList, iSelT, LVNI_SELECTED);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ID_MOVE:
|
|
case ID_RENAME:
|
|
if (!fTree)
|
|
{
|
|
pcmd->cmdf = OLECMDF_SUPPORTED;
|
|
if (m_ftType != FOLDER_NEWS && iSel != -1)
|
|
{
|
|
hr = g_pStore->GetFolderInfo(_IdFromIndex(iSel), &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (info.tySpecial == FOLDER_NOTSPECIAL)
|
|
pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
|
|
{
|
|
int iSel;
|
|
BOOL fTree;
|
|
HRESULT hr;
|
|
FOLDERID id;
|
|
|
|
iSel = ListView_GetNextItem(m_hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
|
|
if (iSel != -1)
|
|
{
|
|
if (MenuUtil_HandleNewMessageIDs(nCmdID, m_hwndOwner, _IdFromIndex((DWORD)iSel), m_ftType != FOLDER_NEWS, FALSE, NULL))
|
|
return(S_OK);
|
|
}
|
|
|
|
fTree = !(S_OK == m_pShellBrowser->HasFocus(ITB_OEVIEW));
|
|
|
|
hr = OLECMDERR_E_NOTSUPPORTED;
|
|
|
|
switch (nCmdID)
|
|
{
|
|
case ID_MARK_RETRIEVE_FLD_NEW_HDRS:
|
|
case ID_MARK_RETRIEVE_FLD_NEW_MSGS:
|
|
case ID_MARK_RETRIEVE_FLD_ALL_MSGS:
|
|
case ID_UNMARK_RETRIEVE_FLD:
|
|
_MarkForDownload(nCmdID);
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_COLUMNS:
|
|
m_pColumns->ColumnsDialog(m_hwndOwner);
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_SUBSCRIBE:
|
|
case ID_UNSUBSCRIBE:
|
|
_Subscribe(nCmdID == ID_SUBSCRIBE);
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_COMPACT:
|
|
if (iSel != -1)
|
|
CompactFolders(m_hwndOwner, RECURSE_INCLUDECURRENT, _IdFromIndex((DWORD)iSel));
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_CATCH_UP:
|
|
iSel = -1;
|
|
while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
|
|
MenuUtil_OnCatchUp(_IdFromIndex((DWORD)iSel));
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_GO_SELECTED:
|
|
case ID_OPEN:
|
|
case ID_OPEN_FOLDER:
|
|
if (iSel != -1)
|
|
g_pInstance->BrowseToObject(SW_SHOWNORMAL, _IdFromIndex((DWORD)iSel));
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_SELECT_ALL:
|
|
ListView_SelectAll(m_hwndList);
|
|
if (m_hwndList != GetFocus())
|
|
SetFocus(m_hwndList);
|
|
hr = S_OK;
|
|
break;
|
|
|
|
case ID_MARK_ALL_READ:
|
|
_MarkAllRead();
|
|
hr = S_OK;
|
|
break;
|
|
|
|
// commands below are handled by the treeview if it has the focus
|
|
// otherwise we'll handle them based on what is selected in us
|
|
|
|
case ID_ADD_SHORTCUT:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
OutlookBar_AddShortcut(_IdFromIndex((DWORD)iSel));
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
case ID_PROPERTIES:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
MenuUtil_OnProperties(m_hwndOwner, _IdFromIndex(iSel));
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
case ID_NEW_FOLDER:
|
|
case ID_NEW_FOLDER2:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
SelectFolderDialog(m_hwndOwner, SFD_NEWFOLDER, _IdFromIndex((DWORD)iSel), TREEVIEW_NONEWS | TREEVIEW_DIALOG | FD_DISABLEROOT | FD_FORCEINITSELFOLDER,
|
|
NULL, NULL, NULL);
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
case ID_MOVE:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
{
|
|
// TODO: move all selected folders, not just the one with focus
|
|
SelectFolderDialog(m_hwndOwner, SFD_MOVEFOLDER, _IdFromIndex((DWORD)iSel), TREEVIEW_NONEWS | TREEVIEW_DIALOG | FD_DISABLEROOT,
|
|
MAKEINTRESOURCE(idsMove), MAKEINTRESOURCE(idsMoveCaption), NULL);
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
case ID_RENAME:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
RenameFolderDlg(m_hwndOwner, _IdFromIndex((DWORD)iSel));
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
|
|
case ID_DELETE:
|
|
case ID_DELETE_NO_TRASH:
|
|
case ID_DELETE_FOLDER:
|
|
if (!fTree)
|
|
{
|
|
if (iSel != -1)
|
|
_HandleDelete(nCmdID == ID_DELETE_NO_TRASH);
|
|
|
|
hr = S_OK;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
void CAccountView::_HandleSettingsButton(HWND hwndBtn)
|
|
{
|
|
HRESULT hr;
|
|
HMENU hMenu;
|
|
HWND hwndBrowser;
|
|
RECT rc;
|
|
DWORD state;
|
|
|
|
hMenu = LoadPopupMenu(IDR_SYNCHRONIZE_POPUP);
|
|
if (hMenu != NULL)
|
|
{
|
|
// Enable / disable
|
|
MenuUtil_EnablePopupMenu(hMenu, (IOleCommandTarget *)this);
|
|
|
|
GetWindowRect(hwndBtn, &rc);
|
|
m_pShellBrowser->GetWindow(&hwndBrowser);
|
|
|
|
TrackPopupMenu(hMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN,
|
|
rc.left, rc.bottom, 0, hwndBrowser, NULL);
|
|
|
|
DestroyMenu(hMenu);
|
|
}
|
|
}
|
|
|
|
void CAccountView::_HandleDelete(BOOL fNoTrash)
|
|
{
|
|
FOLDERID *pid;
|
|
int iSel, cSel, cid;
|
|
|
|
cSel = ListView_GetSelectedCount(m_hwndList);
|
|
if (cSel > 0)
|
|
{
|
|
if (MemAlloc((void **)&pid, cSel * sizeof(FOLDERID)))
|
|
{
|
|
cid = cSel;
|
|
iSel = -1;
|
|
while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
|
|
{
|
|
cid--;
|
|
Assert(cid >= 0);
|
|
pid[cid] = _IdFromIndex(iSel);
|
|
}
|
|
|
|
Assert(cid == 0);
|
|
|
|
if (m_ftType == FOLDER_NEWS)
|
|
{
|
|
MenuUtil_OnSubscribeGroups(m_hwndOwner, pid, cSel, FALSE);
|
|
}
|
|
else
|
|
{
|
|
MenuUtil_DeleteFolders(m_hwndOwner, pid, cSel, fNoTrash);
|
|
}
|
|
|
|
MemFree(pid);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CAccountView::_IsSelectedFolder(FLDRFLAGS dwFlags, BOOL fCondition, BOOL fAll, BOOL fIgnoreSpecial)
|
|
{
|
|
BOOL fSpecial;
|
|
HRESULT hr;
|
|
FLDRFLAGS dw;
|
|
FOLDERINFO info;
|
|
DWORD iItem = -1;
|
|
BOOL fHTTPFolder = FALSE;
|
|
|
|
while (-1 != (iItem = ListView_GetNextItem(m_hwndList, iItem, LVNI_SELECTED)))
|
|
{
|
|
hr = g_pStore->GetFolderInfo(_IdFromIndex(iItem), &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dw = info.dwFlags;
|
|
fHTTPFolder = (BOOL) (info.tyFolder & FOLDER_HTTPMAIL);
|
|
|
|
fSpecial = fIgnoreSpecial && (info.tySpecial != FOLDER_NOTSPECIAL);
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
|
|
if (fSpecial)
|
|
continue;
|
|
|
|
if (fAll)
|
|
{
|
|
// If all must match and this one doesn't, then we can quit now.
|
|
if (!(fCondition == !!(dw & dwFlags)))
|
|
return (FALSE);
|
|
}
|
|
else
|
|
{
|
|
// If only one needs to match and this one does, then we can
|
|
// quit now.
|
|
if (fCondition == !!(dw & dwFlags))
|
|
{
|
|
if(fHTTPFolder)
|
|
{
|
|
FOLDERINFO SvrFolderInfo = {0};
|
|
IImnAccount *pAccount = NULL;
|
|
CHAR szAccountId[CCHMAX_ACCOUNT_NAME];
|
|
HRESULT hr = S_OK;
|
|
DWORD dwShow = 0;
|
|
|
|
// Get the server for this folder
|
|
IF_FAILEXIT(hr = GetFolderServer(_IdFromIndex(iItem), &SvrFolderInfo));
|
|
|
|
// Get the account ID for the server
|
|
*szAccountId = 0;
|
|
IF_FAILEXIT(hr = GetFolderAccountId(&SvrFolderInfo, szAccountId, ARRAYSIZE(szAccountId)));
|
|
|
|
// Get the account interface
|
|
IF_FAILEXIT(hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAccountId, &pAccount));
|
|
|
|
IF_FAILEXIT(hr = pAccount->GetPropDw(AP_HTTPMAIL_DOMAIN_MSN, &dwShow));
|
|
if(dwShow)
|
|
{
|
|
if(HideHotmail())
|
|
return (FALSE);
|
|
}
|
|
}
|
|
exit:
|
|
return (TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the user wanted all to match, and we get here all did match. If the
|
|
// user wanted only one to match and we get here, then none matched and we
|
|
// fail.
|
|
return (fAll);
|
|
}
|
|
|
|
LRESULT CALLBACK CAccountView::AcctViewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT lRet;
|
|
CAccountView *pThis;
|
|
|
|
if (msg == WM_NCCREATE)
|
|
{
|
|
pThis = (CAccountView *)((LPCREATESTRUCT)lParam)->lpCreateParams;
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pThis);
|
|
}
|
|
else
|
|
pThis = (CAccountView *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
Assert(pThis);
|
|
|
|
return pThis->_WndProc(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
LRESULT CAccountView::_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hwndFocus, hwndBrowser;
|
|
BOOL fTip;
|
|
RECT rc;
|
|
|
|
switch (msg)
|
|
{
|
|
HANDLE_MSG(hwnd, WM_CREATE, _OnCreate);
|
|
HANDLE_MSG(hwnd, WM_SIZE, _OnSize);
|
|
HANDLE_MSG(hwnd, WM_NOTIFY, _OnNotify);
|
|
HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus);
|
|
|
|
case WM_MENUSELECT:
|
|
CStatusBar *pStatusBar;
|
|
m_pShellBrowser->GetStatusBar(&pStatusBar);
|
|
HandleMenuSelect(pStatusBar, wParam, lParam);
|
|
pStatusBar->Release();
|
|
return 0;
|
|
|
|
case WM_COMMAND:
|
|
_OnCommand(wParam, lParam);
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
return(_OnPaint(hwnd, (HDC)wParam));
|
|
|
|
case WM_DRAWITEM:
|
|
if (wParam == ID_POPUP_SYNCHRONIZE)
|
|
{
|
|
DrawSettingsButton(hwnd, (LPDRAWITEMSTRUCT)lParam);
|
|
return(TRUE);
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
_OnContextMenu(hwnd, (HWND)wParam, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
|
|
return(0);
|
|
|
|
case NVM_INITHEADERS:
|
|
_PostCreate();
|
|
return 0;
|
|
|
|
case WM_ACTIVATE:
|
|
_HandleItemStateChange();
|
|
|
|
if (LOWORD(wParam) != WA_INACTIVE)
|
|
{
|
|
// DefWindowProc will set the focus to our view window, which
|
|
// is not what we want. Instead, we will let the explorer set
|
|
// the focus to our view window if we should get it, at which
|
|
// point we will set it to the proper control.
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
SendMessage(m_hwndList, msg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_WININICHANGE:
|
|
SendMessage(m_hwndList, msg, wParam, lParam);
|
|
|
|
// reposition and resize things with the new font
|
|
_OnWinIniChange(hwnd);
|
|
break;
|
|
|
|
case NVM_GETNEWGROUPS:
|
|
if (m_pGroups != NULL)
|
|
{
|
|
m_pGroups->HandleGetNewGroups();
|
|
m_pGroups->Release();
|
|
m_pGroups = NULL;
|
|
}
|
|
return(0);
|
|
|
|
case CM_OPTIONADVISE:
|
|
m_clrWatched = DwGetOption(OPT_WATCHED_COLOR);
|
|
return (0);
|
|
|
|
default:
|
|
if (g_msgMSWheel && (msg == g_msgMSWheel))
|
|
{
|
|
hwndFocus = GetFocus();
|
|
if (IsChild(hwnd, hwndFocus))
|
|
return SendMessage(hwndFocus, msg, wParam, lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
|
}
|
|
|
|
void CAccountView::_OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hwndBrowser;
|
|
HRESULT hr;
|
|
|
|
if (HIWORD(wParam) == BN_CLICKED)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ID_SEND_RECEIVE:
|
|
case ID_SYNC_THIS_NOW:
|
|
case ID_IMAP_FOLDERS:
|
|
case ID_NEWSGROUPS:
|
|
m_pShellBrowser->GetWindow(&hwndBrowser);
|
|
SendMessage(hwndBrowser, WM_COMMAND, wParam, lParam);
|
|
break;
|
|
|
|
case ID_POPUP_SYNCHRONIZE:
|
|
_HandleSettingsButton((HWND)lParam);
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CAccountView::OnCreate
|
|
//
|
|
// PURPOSE: Creates the child windows necessary for the view and
|
|
// initializes the data in those child windows.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the view being created.
|
|
// lpCreateStruct - Pointer to the creation params passed to
|
|
// CreateWindow().
|
|
//
|
|
// RETURN VALUE:
|
|
// Returns TRUE if the initialization is successful.
|
|
//
|
|
BOOL CAccountView::_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
HRESULT hr;
|
|
DWORD style;
|
|
FOLDERINFO info;
|
|
COLUMN_SET_TYPE set;
|
|
const ACCTVIEWBTN *pBtn;
|
|
int i, cBtn, idsMajor, idsMinor;
|
|
char sz[CCHMAX_STRINGRES];
|
|
|
|
switch (m_ftType)
|
|
{
|
|
case FOLDER_LOCAL:
|
|
set = COLUMN_SET_LOCAL_STORE;
|
|
pBtn = c_rgMailBtns;
|
|
cBtn = ARRAYSIZE(c_rgMailBtns);
|
|
idsMajor = 0;
|
|
idsMinor = idsLocalFoldersMinor;
|
|
break;
|
|
case FOLDER_IMAP:
|
|
set = COLUMN_SET_IMAP_ACCOUNT;
|
|
pBtn = c_rgImapBtns;
|
|
cBtn = ARRAYSIZE(c_rgImapBtns);
|
|
idsMajor = idsSyncManager;
|
|
idsMinor = idsSetSyncSettings;
|
|
break;
|
|
case FOLDER_HTTPMAIL:
|
|
set = COLUMN_SET_HTTPMAIL_ACCOUNT;
|
|
pBtn = c_rgHttpBtns;
|
|
cBtn = ARRAYSIZE(c_rgHttpBtns);
|
|
idsMajor = idsSyncManager;
|
|
idsMinor = idsSetSyncSettings;
|
|
break;
|
|
case FOLDER_NEWS:
|
|
set = COLUMN_SET_NEWS_ACCOUNT;
|
|
pBtn = c_rgNewsBtns;
|
|
cBtn = ARRAYSIZE(c_rgNewsBtns);
|
|
idsMajor = idsSyncManagerNews;
|
|
idsMinor = idsSetNewsSyncSettings;
|
|
break;
|
|
default:
|
|
Assert(FALSE);
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < cBtn; i++, pBtn++)
|
|
{
|
|
if (pBtn->cmd == ID_POPUP_SYNCHRONIZE)
|
|
style = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_NOTIFY | BS_OWNERDRAW | WS_DISABLED;
|
|
else
|
|
style = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_NOTIFY;
|
|
AthLoadString(pBtn->idsText, sz, ARRAYSIZE(sz));
|
|
m_rgBtns[m_cBtns] = CreateWindow("button", sz, style,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
hwnd, (HMENU)LongToHandle(pBtn->cmd), g_hInst, 0);
|
|
if (m_rgBtns[m_cBtns] != NULL)
|
|
m_cBtns++;
|
|
}
|
|
|
|
m_hwndList = CreateWindowEx(0, WC_LISTVIEW, c_szEmpty,
|
|
WS_VISIBLE | WS_TABSTOP | WS_CHILD | LVS_REPORT | LVS_NOSORTHEADER |
|
|
LVS_OWNERDATA | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
hwnd, (HMENU)IDC_SUBSCRIBE_LIST, g_hInst, 0);
|
|
Assert(m_hwndList != NULL);
|
|
|
|
hr = m_pColumns->Initialize(m_hwndList, set);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
hr = m_pColumns->ApplyColumns(COLUMN_LOAD_REGISTRY, 0, 0);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
m_hwndHeader = ListView_GetHeader(m_hwndList);
|
|
Assert(m_hwndHeader != NULL);
|
|
|
|
// Initialize the extended styles so we get full row select. Just because
|
|
// it looks better.
|
|
ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);
|
|
|
|
Assert(m_himlFolders != NULL);
|
|
ListView_SetImageList(m_hwndList, m_himlFolders, LVSIL_SMALL);
|
|
|
|
SetIntlFont(m_hwndList);
|
|
|
|
hr = g_pStore->GetFolderInfo(m_idFolder, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (MemAlloc((void **)&m_pszMajor, CCHMAX_STRINGRES))
|
|
{
|
|
if (idsMajor != 0)
|
|
{
|
|
AthLoadString(idsMajor, sz, ARRAYSIZE(sz));
|
|
wnsprintf(m_pszMajor, CCHMAX_STRINGRES, sz, info.pszName);
|
|
}
|
|
else
|
|
{
|
|
StrCpyN(m_pszMajor, info.pszName, CCHMAX_STRINGRES);
|
|
}
|
|
}
|
|
|
|
if (idsMinor != 0)
|
|
m_pszMinor = AthLoadString(idsMinor, NULL, 0);
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
m_clrWatched = DwGetOption(OPT_WATCHED_COLOR);
|
|
OptionAdvise(hwnd);
|
|
_OnWinIniChange(hwnd);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CAccountView::_OnWinIniChange(HWND hwnd)
|
|
{
|
|
char sz[CCHMAX_STRINGRES];
|
|
TEXTMETRIC tm;
|
|
HDC hdc;
|
|
int i, cch, cxMax;
|
|
SIZE size;
|
|
HFONT hfont, hfontBold, hfontOld;
|
|
RECT rc, rcBtn;
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
|
|
hfont = HGetCharSetFont(FNT_SYS_ICON, NULL);
|
|
hfontBold = HGetCharSetFont(FNT_SYS_ICON_BOLD, NULL);
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
|
|
|
|
Assert(m_pszMajor != NULL);
|
|
GetTextExtentPoint32(hdc, m_pszMajor, lstrlen(m_pszMajor), &size);
|
|
m_rcMajor.left = SUBSCRIBE_BORDER;
|
|
m_rcMajor.top = SUBSCRIBE_BORDER;
|
|
m_rcMajor.right = m_rcMajor.left + size.cx;
|
|
m_rcMajor.bottom = m_rcMajor.top + size.cy;
|
|
|
|
m_rcMinor.left = m_rcMajor.left;
|
|
m_rcMinor.top = m_rcMajor.bottom + 1;
|
|
if (m_pszMinor != NULL)
|
|
{
|
|
SelectObject(hdc, (HGDIOBJ)hfont);
|
|
GetTextExtentPoint32(hdc, m_pszMinor, lstrlen(m_pszMinor), &size);
|
|
}
|
|
m_rcMinor.right = m_rcMinor.left + size.cx;
|
|
m_rcMinor.bottom = m_rcMinor.top + size.cy;
|
|
|
|
m_rcHeader.left = 0;
|
|
m_rcHeader.top = 0;
|
|
m_rcHeader.right = rc.right;
|
|
m_rcHeader.bottom = m_rcMinor.bottom + SUBSCRIBE_BORDER;
|
|
|
|
m_rcButtons.left = m_rcHeader.left;
|
|
m_rcButtons.top = m_rcHeader.bottom + 1;
|
|
m_rcButtons.right = m_rcHeader.right;
|
|
m_rcButtons.bottom = m_rcButtons.top + m_rcHeader.bottom;
|
|
|
|
SelectObject(hdc, hfont);
|
|
|
|
cxMax = 0;
|
|
for (i = 0; i < m_cBtns; i++)
|
|
{
|
|
cch = GetWindowText(m_rgBtns[i], sz, ARRAYSIZE(sz));
|
|
GetTextExtentPoint32(hdc, sz, cch, &size);
|
|
if (size.cx > cxMax)
|
|
cxMax = size.cx;
|
|
}
|
|
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
rcBtn.top = m_rcButtons.top + SUBSCRIBE_BORDER;
|
|
rcBtn.bottom = rcBtn.top + (m_rcMinor.bottom - m_rcMajor.top);
|
|
rcBtn.left = m_rcMajor.left;
|
|
rcBtn.right = cxMax + 2 * GetSystemMetrics(SM_CXEDGE) + 6 + (rcBtn.bottom - rcBtn.top);
|
|
|
|
cxMax = SUBSCRIBE_BORDER + (rcBtn.right - rcBtn.left);
|
|
|
|
for (i = 0; i < m_cBtns; i++)
|
|
{
|
|
SendMessage(m_rgBtns[i], WM_SETFONT, (WPARAM)hfont, 0);
|
|
|
|
SetWindowPos(m_rgBtns[i], NULL, rcBtn.left, rcBtn.top,
|
|
rcBtn.right - rcBtn.left, rcBtn.bottom - rcBtn.top,
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
|
|
|
|
rcBtn.left += cxMax;
|
|
rcBtn.right += cxMax;
|
|
}
|
|
|
|
rc.top = m_rcButtons.bottom + 1;
|
|
SendMessage(m_hwndList, WM_SETFONT, (WPARAM)hfont, 0);
|
|
SetWindowPos(m_hwndList, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CAccountView::OnSize
|
|
//
|
|
// PURPOSE: Notification that the view window has been resized. In
|
|
// response we update the positions of our child windows and
|
|
// controls.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the view window being resized.
|
|
// state - Type of resizing requested.
|
|
// cxClient - New width of the client area.
|
|
// cyClient - New height of the client area.
|
|
//
|
|
void CAccountView::_OnSize(HWND hwnd, UINT state, int cxClient, int cyClient)
|
|
{
|
|
int cy;
|
|
BOOL fUpdate;
|
|
|
|
fUpdate = (cxClient > m_rcHeader.right);
|
|
|
|
m_rcHeader.right = cxClient;
|
|
m_rcMajor.right = m_rcHeader.right - SUBSCRIBE_BORDER;
|
|
m_rcMinor.right = m_rcMajor.right;
|
|
m_rcButtons.right = m_rcHeader.right;
|
|
|
|
if ((m_rcButtons.bottom + 1) < cyClient)
|
|
cy = cyClient - (m_rcButtons.bottom + 1);
|
|
else
|
|
cy = 1;
|
|
|
|
SetWindowPos(m_hwndList, NULL, 0, 0, cxClient, cy,
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
|
|
|
|
if (fUpdate)
|
|
{
|
|
InvalidateRect(hwnd, NULL, FALSE);
|
|
UpdateWindow(hwnd);
|
|
}
|
|
}
|
|
|
|
LRESULT CAccountView::_OnPaint(HWND hwnd, HDC hdc)
|
|
{
|
|
HFONT hfont, hfontBold, hfontOld;
|
|
RECT rc, rcT;
|
|
PAINTSTRUCT ps;
|
|
COLORREF crText, crBackground;
|
|
HBRUSH hBrush, hBrushOld;
|
|
|
|
if (0 != GetUpdateRect(hwnd, &rc, FALSE))
|
|
{
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
|
|
if (IntersectRect(&rcT, &rc, &m_rcHeader))
|
|
{
|
|
crText = GetSysColor(COLOR_WINDOW);
|
|
crBackground = GetSysColor(COLOR_3DSHADOW);
|
|
|
|
hBrush = CreateSolidBrush(crBackground);
|
|
hBrushOld = SelectBrush(hdc, hBrush);
|
|
PatBlt(hdc, rcT.left, rcT.top, rcT.right - rcT.left, rcT.bottom - rcT.top, PATCOPY);
|
|
SelectBrush(hdc, hBrushOld);
|
|
DeleteBrush(hBrush);
|
|
|
|
SetBkColor(hdc, crBackground);
|
|
SetTextColor(hdc, crText);
|
|
|
|
if (m_pszMajor != NULL &&
|
|
IntersectRect(&rcT, &rc, &m_rcMajor))
|
|
{
|
|
hfontBold = HGetCharSetFont(FNT_SYS_ICON_BOLD, NULL);
|
|
hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
|
|
|
|
DrawText(hdc, m_pszMajor, lstrlen(m_pszMajor), &m_rcMajor, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX);
|
|
|
|
SelectObject(hdc, (HGDIOBJ)hfontOld);
|
|
}
|
|
|
|
if (m_pszMinor != NULL &&
|
|
IntersectRect(&rcT, &rc, &m_rcMinor))
|
|
{
|
|
hfontBold = HGetCharSetFont(FNT_SYS_ICON, NULL);
|
|
hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
|
|
|
|
DrawText(hdc, m_pszMinor, lstrlen(m_pszMinor), &m_rcMinor, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX);
|
|
|
|
SelectObject(hdc, (HGDIOBJ)hfontOld);
|
|
}
|
|
}
|
|
|
|
rc.bottom = m_rcButtons.bottom;
|
|
DrawEdge(hdc, &rc, EDGE_ETCHED, BF_BOTTOM);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
BOOL DrawArrow(HDC hdc, LPARAM x, WPARAM y, int dx, int dy)
|
|
{
|
|
int i, iCount;
|
|
|
|
iCount = (dx + 1) / 2;
|
|
|
|
// draw arrow head
|
|
for (i = 0; i < iCount; i++, dx -= 2, x += 1)
|
|
PatBlt(hdc, (int) x, (int) y++, dx, 1, PATCOPY);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
#define CXARROW 9
|
|
#define CYARROW 5
|
|
|
|
void DrawSettingsButton(HWND hwnd, LPDRAWITEMSTRUCT pdi)
|
|
{
|
|
BOOL fPushed, fDisabled;
|
|
TCHAR sz[CCHMAX_STRINGRES];
|
|
RECT rcFocus;
|
|
int d, cch, x, y, xArrow, yArrow;
|
|
SIZE size;
|
|
UINT dsFlags;
|
|
HGDIOBJ hbrOld;
|
|
|
|
Assert(pdi->CtlType == ODT_BUTTON);
|
|
Assert(pdi->CtlID == ID_POPUP_SYNCHRONIZE);
|
|
|
|
if (!!(pdi->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
|
|
{
|
|
fPushed = !!(pdi->itemState & ODS_SELECTED);
|
|
fDisabled = !!(pdi->itemState & ODS_DISABLED);
|
|
|
|
if (fPushed)
|
|
dsFlags = DFCS_BUTTONPUSH | DFCS_PUSHED;
|
|
else
|
|
dsFlags = DFCS_BUTTONPUSH;
|
|
|
|
DrawFrameControl(pdi->hDC, &pdi->rcItem, DFC_BUTTON, dsFlags);
|
|
|
|
cch = GetWindowText(pdi->hwndItem, sz, ARRAYSIZE(sz));
|
|
GetTextExtentPoint32(pdi->hDC, sz, cch, &size);
|
|
|
|
size.cy++;
|
|
x = (pdi->rcItem.left + pdi->rcItem.right - size.cx) / 2;
|
|
y = (pdi->rcItem.top + pdi->rcItem.bottom - size.cy) / 2;
|
|
if (fPushed)
|
|
{
|
|
x++;
|
|
y++;
|
|
}
|
|
|
|
xArrow = x + size.cx + 7;
|
|
yArrow = (pdi->rcItem.top + pdi->rcItem.bottom - CYARROW) / 2;
|
|
yArrow++;
|
|
if (fPushed)
|
|
yArrow++;
|
|
|
|
if (fDisabled)
|
|
{
|
|
DrawState(pdi->hDC, NULL, DrawArrow, 0, 0,
|
|
xArrow, yArrow, CXARROW, CYARROW, DST_COMPLEX | DSS_DISABLED);
|
|
}
|
|
else
|
|
{
|
|
hbrOld = SelectObject(pdi->hDC, GetSysColorBrush(COLOR_BTNTEXT));
|
|
DrawArrow(pdi->hDC, xArrow, yArrow, CXARROW, CYARROW);
|
|
SelectObject(pdi->hDC, hbrOld);
|
|
}
|
|
|
|
|
|
if (fDisabled)
|
|
dsFlags = DST_TEXT | DSS_DISABLED;
|
|
else
|
|
dsFlags = DST_TEXT | DSS_NORMAL;
|
|
|
|
DrawState(pdi->hDC, NULL, NULL, (LPARAM)sz, (WPARAM)cch,
|
|
x, y, size.cx, size.cy, dsFlags);
|
|
}
|
|
|
|
if (!!(pdi->itemAction & ODA_FOCUS) || !!(pdi->itemState & ODS_FOCUS))
|
|
{
|
|
rcFocus = pdi->rcItem;
|
|
|
|
d = GetSystemMetrics(SM_CXEDGE) + 1;
|
|
rcFocus.left += d;
|
|
rcFocus.right -= d;
|
|
|
|
d = GetSystemMetrics(SM_CYEDGE) + 1;
|
|
rcFocus.top += d;
|
|
rcFocus.bottom -= d;
|
|
|
|
DrawFocusRect(pdi->hDC, &rcFocus);
|
|
}
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CAccountView::OnSetFocus
|
|
//
|
|
// PURPOSE: If the focus ever is set to the view window, we want to
|
|
// make sure it goes to one of our child windows. Preferably
|
|
// the focus will go to the last child to have the focus.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the view window.
|
|
// hwndOldFocus - Handle of the window losing focus.
|
|
//
|
|
void CAccountView::_OnSetFocus(HWND hwnd, HWND hwndOldFocus)
|
|
{
|
|
SetFocus(m_hwndList);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CAccountView::OnNotify
|
|
//
|
|
// PURPOSE: Processes the various notifications we receive from our child
|
|
// controls.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the view window.
|
|
// idCtl - identifies the control sending the notification
|
|
// pnmh - points to a NMHDR struct with more information regarding the
|
|
// notification
|
|
//
|
|
// RETURN VALUE:
|
|
// Dependant on the specific notification.
|
|
//
|
|
LRESULT CAccountView::_OnNotify(HWND hwnd, int idFrom, LPNMHDR pnmhdr)
|
|
{
|
|
LRESULT lRes=0;
|
|
HD_NOTIFY *phdn;
|
|
int iSel;
|
|
DWORD dwPos;
|
|
UINT uChanged;
|
|
FOLDERINFO info;
|
|
LV_HITTESTINFO lvhti;
|
|
NM_LISTVIEW *pnmlv;
|
|
LV_DISPINFO *pDispInfo;
|
|
DWORD cColumns;
|
|
NMCUSTOMDRAW *pnmcd;
|
|
COLUMN_ID id;
|
|
FOLDERID idFolder;
|
|
COLUMN_SET *rgColumns;
|
|
HRESULT hr;
|
|
FNTSYSTYPE fntType;
|
|
|
|
if (pnmhdr->hwndFrom != m_hwndList &&
|
|
pnmhdr->hwndFrom != m_hwndHeader)
|
|
return(0);
|
|
|
|
switch (pnmhdr->code)
|
|
{
|
|
case NM_SETFOCUS:
|
|
m_pShellBrowser->OnViewWindowActive(this);
|
|
_HandleItemStateChange();
|
|
break;
|
|
|
|
case LVN_ITEMACTIVATE:
|
|
// Tell our host to open the selected items
|
|
iSel = ListView_GetNextItem(m_hwndList, -1, LVNI_ALL | LVNI_SELECTED | LVNI_FOCUSED);
|
|
if (iSel >= 0)
|
|
g_pInstance->BrowseToObject(SW_SHOWNORMAL, _IdFromIndex(iSel));
|
|
break;
|
|
|
|
case LVN_GETDISPINFO:
|
|
pDispInfo = (LV_DISPINFO *)pnmhdr;
|
|
id = m_pColumns->GetId(pDispInfo->item.iSubItem);
|
|
|
|
if ((DWORD)pDispInfo->item.iItem < m_cnode)
|
|
_GetDisplayInfo(pDispInfo, id);
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
dwPos = GetMessagePos();
|
|
lvhti.pt.x = (int)(short)LOWORD(dwPos);
|
|
lvhti.pt.y = (int)(short)HIWORD(dwPos);
|
|
ScreenToClient(m_hwndList, &(lvhti.pt));
|
|
|
|
// Ask the ListView where this is
|
|
if (-1 == ListView_SubItemHitTest(m_hwndList, &lvhti))
|
|
break;
|
|
|
|
id = m_pColumns->GetId(lvhti.iSubItem);
|
|
if (lvhti.flags == LVHT_ONITEMICON)
|
|
{
|
|
if (id == COLUMN_DOWNLOAD)
|
|
{
|
|
_ToggleDownload(lvhti.iItem);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_CUSTOMDRAW:
|
|
pnmcd = (NMCUSTOMDRAW *)pnmhdr;
|
|
|
|
// If this is a prepaint notification, we tell the control we're interested
|
|
// in further notfications.
|
|
if (pnmcd->dwDrawStage == CDDS_PREPAINT)
|
|
{
|
|
lRes = CDRF_NOTIFYITEMDRAW;
|
|
break;
|
|
}
|
|
|
|
// Do some extra work here to not show the selection on the priority or
|
|
// attachment sub columns.
|
|
// $REVIEW - Why?
|
|
if ((pnmcd->dwDrawStage == CDDS_ITEMPREPAINT) || (pnmcd->dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM)))
|
|
{
|
|
fntType = FNT_SYS_ICON;
|
|
|
|
if (pnmcd->dwItemSpec >= m_cnode)
|
|
{
|
|
lRes = CDRF_DODEFAULT;
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(g_pStore->GetFolderInfo(_IdFromIndex((DWORD)(pnmcd->dwItemSpec)), &info)))
|
|
{
|
|
if (pnmcd->dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
|
|
{
|
|
if ((info.cWatchedUnread) && (m_clrWatched > 0 && m_clrWatched < 16))
|
|
{
|
|
LPNMLVCUSTOMDRAW(pnmcd)->clrText = rgrgbColors16[m_clrWatched - 1];
|
|
}
|
|
else
|
|
{
|
|
id = m_pColumns->GetId(LPNMLVCUSTOMDRAW(pnmcd)->iSubItem);
|
|
if (id == COLUMN_DOWNLOAD && 0 == (info.dwFlags & FOLDER_SYNCMASK))
|
|
{
|
|
LPNMLVCUSTOMDRAW(pnmcd)->clrText = GetSysColor(COLOR_GRAYTEXT);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (info.cUnread > 0 ||
|
|
(info.tyFolder == FOLDER_NEWS && info.dwNotDownloaded > 0))
|
|
fntType = FNT_SYS_ICON_BOLD;
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
SelectObject(pnmcd->hdc, HGetCharSetFont(fntType, GetListViewCharset()));
|
|
lRes = CDRF_NEWFONT | CDRF_NOTIFYSUBITEMDRAW;
|
|
break;
|
|
}
|
|
|
|
lRes = CDRF_DODEFAULT;
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
pnmlv = (NM_LISTVIEW *)pnmhdr;
|
|
if (!!(pnmlv->uChanged & LVIF_STATE) &&
|
|
!!((LVIS_SELECTED | LVIS_FOCUSED) & (pnmlv->uOldState ^ pnmlv->uNewState)))
|
|
{
|
|
_HandleItemStateChange();
|
|
}
|
|
break;
|
|
|
|
case HDN_ENDTRACK:
|
|
phdn = (HD_NOTIFY *)pnmhdr;
|
|
m_pColumns->SetColumnWidth(phdn->iItem, phdn->pitem->cxy);
|
|
break;
|
|
|
|
case HDN_DIVIDERDBLCLICK:
|
|
phdn = (HD_NOTIFY *)pnmhdr;
|
|
// When the user double clicks on a header divider, we're supposed to
|
|
// autosize that column.
|
|
m_pColumns->SetColumnWidth(phdn->iItem, ListView_GetColumnWidth(m_hwndList, phdn->iItem));
|
|
break;
|
|
|
|
default:
|
|
lRes = 0;
|
|
break;
|
|
}
|
|
|
|
return(lRes);
|
|
}
|
|
|
|
void CAccountView::_HandleItemStateChange()
|
|
{
|
|
OLECMD rgCmds[3];
|
|
HRESULT hr;
|
|
IOleCommandTarget *pTarget;
|
|
int i;
|
|
|
|
hr = m_pShellBrowser->QueryInterface(IID_IOleCommandTarget, (void **)&pTarget);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (i = 0; i < m_cBtns; i++)
|
|
{
|
|
rgCmds[i].cmdID = GetWindowLong(m_rgBtns[i], GWL_ID);
|
|
rgCmds[i].cmdf = 0;
|
|
}
|
|
|
|
hr = pTarget->QueryStatus(NULL, m_cBtns, rgCmds, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (i = 0; i < m_cBtns; i++)
|
|
{
|
|
EnableWindow(m_rgBtns[i], !!(rgCmds[i].cmdf & OLECMDF_ENABLED));
|
|
|
|
Assert(0 == (rgCmds[i].cmdf & OLECMDF_LATCHED));
|
|
Assert(0 == (rgCmds[i].cmdf & OLECMDF_NINCHED));
|
|
}
|
|
}
|
|
|
|
pTarget->Release();
|
|
}
|
|
|
|
m_pShellBrowser->UpdateToolbar();
|
|
}
|
|
|
|
HRESULT CAccountView::_GetDisplayInfo(LV_DISPINFO *pDispInfo, COLUMN_ID id)
|
|
{
|
|
DWORD dwFlags;
|
|
int count;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
FLDRNODE *pNode;
|
|
|
|
pNode = _NodeFromIndex((DWORD)pDispInfo->item.iItem);
|
|
if (pNode == NULL)
|
|
return(S_OK);
|
|
|
|
hr = g_pStore->GetFolderInfo(pNode->id, &info);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (!!(pDispInfo->item.mask & LVIF_TEXT))
|
|
{
|
|
if (id == COLUMN_NEWSGROUP || id == COLUMN_FOLDER)
|
|
{
|
|
StrCpyN(pDispInfo->item.pszText, info.pszName, pDispInfo->item.cchTextMax);
|
|
}
|
|
else if (id == COLUMN_DOWNLOAD)
|
|
{
|
|
if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
|
|
{
|
|
if (0 == (info.dwFlags & FOLDER_SYNCMASK))
|
|
dwFlags = pNode->dwDownload;
|
|
else
|
|
dwFlags = info.dwFlags;
|
|
|
|
Assert(!!(dwFlags & FOLDER_SYNCMASK));
|
|
|
|
if (!!(dwFlags & FOLDER_DOWNLOADALL))
|
|
AthLoadString(idsAllMessages, pDispInfo->item.pszText, pDispInfo->item.cchTextMax);
|
|
else if (!!(dwFlags & FOLDER_DOWNLOADNEW))
|
|
AthLoadString(idsNewMessages, pDispInfo->item.pszText, pDispInfo->item.cchTextMax);
|
|
else if (!!(dwFlags & FOLDER_DOWNLOADHEADERS))
|
|
AthLoadString(idsNewHeaders, pDispInfo->item.pszText, pDispInfo->item.cchTextMax);
|
|
}
|
|
}
|
|
else if (id == COLUMN_TOTAL || id == COLUMN_UNREAD)
|
|
{
|
|
if (id == COLUMN_UNREAD)
|
|
count = info.cUnread;
|
|
else
|
|
count = info.cMessages;
|
|
|
|
if (FOLDER_NEWS == info.tyFolder)
|
|
count += info.dwNotDownloaded;
|
|
|
|
if (count < 0)
|
|
count = 0;
|
|
wnsprintf(pDispInfo->item.pszText, pDispInfo->item.cchTextMax, "%d", count);
|
|
}
|
|
}
|
|
|
|
if (!!(pDispInfo->item.mask & LVIF_IMAGE))
|
|
{
|
|
if (id == COLUMN_NEWSGROUP)
|
|
{
|
|
pDispInfo->item.iImage = iNullBitmap;
|
|
if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
|
|
{
|
|
pDispInfo->item.iImage = iNewsGroup;
|
|
if (!!(info.dwFlags & FOLDER_SYNCMASK))
|
|
pDispInfo->item.iImage = iNewsGroupSync;
|
|
}
|
|
}
|
|
else if (COLUMN_FOLDER == id)
|
|
{
|
|
pDispInfo->item.iImage = iNullBitmap;
|
|
if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
|
|
{
|
|
if (info.tySpecial == FOLDER_NOTSPECIAL)
|
|
pDispInfo->item.iImage = iFolderClosed;
|
|
else
|
|
pDispInfo->item.iImage = (iInbox + (((info.tySpecial == FOLDER_BULKMAIL) ? FOLDER_JUNK : info.tySpecial) - 1));
|
|
}
|
|
}
|
|
else if (COLUMN_DOWNLOAD == id)
|
|
{
|
|
pDispInfo->item.iImage = iNullBitmap;
|
|
if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
|
|
{
|
|
if (!!(info.dwFlags & FOLDER_SYNCMASK))
|
|
pDispInfo->item.iImage = iChecked;
|
|
else
|
|
pDispInfo->item.iImage = iUnchecked;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!!(pDispInfo->item.mask & LVIF_INDENT))
|
|
{
|
|
if (COLUMN_FOLDER == id)
|
|
pDispInfo->item.iIndent = pNode->indent;
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
return(S_OK);
|
|
}
|
|
|
|
BOOL CAccountView::_OnActivate(UINT uActivation)
|
|
{
|
|
// if focus stays within the frame, but goes outside our view.
|
|
// ie.. TreeView gets focus then we get an activate nofocus. Be sure
|
|
// to UIDeactivate the docobj in this case
|
|
if (uActivation == SVUIA_ACTIVATE_NOFOCUS)
|
|
{
|
|
|
|
}
|
|
|
|
if (m_uActivation != uActivation)
|
|
{
|
|
_OnDeactivate();
|
|
m_uActivation = uActivation;
|
|
|
|
if (!m_fFirstActive)
|
|
{
|
|
PostMessage(m_hwnd, NVM_INITHEADERS, 0, 0L);
|
|
m_fFirstActive = TRUE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CAccountView::_OnDeactivate()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT CAccountView::_InsertChildren(FOLDERID idFolder, DWORD indent, DWORD *piNode)
|
|
{
|
|
DWORD cnode;
|
|
ULONG cFolders;
|
|
IEnumerateFolders *pEnum;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
|
|
Assert(piNode != NULL);
|
|
Assert(*piNode <= m_cnode);
|
|
|
|
hr = g_pStore->EnumChildren(idFolder, TRUE, &pEnum);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pEnum->Count(&cFolders);
|
|
if (SUCCEEDED(hr) && cFolders > 0)
|
|
{
|
|
while (S_OK == pEnum->Next(1, &info, NULL))
|
|
{
|
|
Assert(m_cnode <= m_cnodeBuf);
|
|
|
|
// Skip folders which are hidden
|
|
if (ISFLAGSET(info.dwFlags, FOLDER_HIDDEN))
|
|
continue;
|
|
|
|
if (m_cnode == m_cnodeBuf)
|
|
{
|
|
cnode = m_cnode + cFolders + CALLOCIDBUF;
|
|
if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
|
|
{
|
|
pEnum->Release();
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
m_cnodeBuf = cnode;
|
|
}
|
|
|
|
if (*piNode < m_cnode)
|
|
MoveMemory(&m_rgnode[*piNode + 1], &m_rgnode[*piNode], (m_cnode - *piNode) * sizeof(FLDRNODE));
|
|
|
|
m_rgnode[*piNode].id = info.idFolder;
|
|
m_rgnode[*piNode].indent = indent;
|
|
m_rgnode[*piNode].dwDownload = m_dwDownloadDef;
|
|
(*piNode)++;
|
|
m_cnode++;
|
|
|
|
if (!!(info.dwFlags & FOLDER_HASCHILDREN))
|
|
hr = _InsertChildren(info.idFolder, indent + 1, piNode);
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
}
|
|
|
|
pEnum->Release();
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CAccountView::_InsertChildrenSpecial(FOLDERID idFolder, DWORD indent, DWORD *piNode)
|
|
{
|
|
DWORD cnode;
|
|
ULONG iFolder, cFolders;
|
|
IEnumerateFolders *pEnum;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
FLDRNODE *rgNode, *pNode;
|
|
|
|
Assert(piNode != NULL);
|
|
Assert(*piNode <= m_cnode);
|
|
Assert(indent == 0);
|
|
|
|
rgNode = NULL;
|
|
|
|
hr = g_pStore->EnumChildren(idFolder, TRUE, &pEnum);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pEnum->Count(&cFolders);
|
|
if (SUCCEEDED(hr) && cFolders > 0)
|
|
{
|
|
if (!MemAlloc((void **)&rgNode, cFolders * sizeof(FLDRNODE)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pNode = rgNode;
|
|
cFolders = 0;
|
|
while (S_OK == pEnum->Next(1, &info, NULL))
|
|
{
|
|
if ((!(g_dwAthenaMode & MODE_NEWSONLY) || (info.tySpecial != FOLDER_INBOX)) &&
|
|
ISFLAGCLEAR(info.dwFlags, FOLDER_HIDDEN))
|
|
{
|
|
pNode->id = info.idFolder;
|
|
pNode->indent = !!(info.dwFlags & FOLDER_HASCHILDREN) ? 1 : 0;
|
|
pNode->dwDownload = m_dwDownloadDef;
|
|
|
|
pNode++;
|
|
cFolders++;
|
|
}
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
qsort(rgNode, cFolders, sizeof(FLDRNODE), GroupCompare);
|
|
}
|
|
}
|
|
|
|
pEnum->Release();
|
|
}
|
|
|
|
if (rgNode != NULL)
|
|
{
|
|
Assert(SUCCEEDED(hr));
|
|
Assert(cFolders > 0);
|
|
Assert(m_cnode == 0);
|
|
Assert(m_cnodeBuf == 0);
|
|
|
|
for (iFolder = 0, pNode = rgNode; iFolder < cFolders; iFolder++, pNode++)
|
|
{
|
|
if (m_cnode == m_cnodeBuf)
|
|
{
|
|
cnode = m_cnode + cFolders + CALLOCIDBUF;
|
|
if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
m_cnodeBuf = cnode;
|
|
}
|
|
|
|
m_rgnode[*piNode].id = pNode->id;
|
|
m_rgnode[*piNode].indent = indent;
|
|
m_rgnode[*piNode].dwDownload = m_dwDownloadDef;
|
|
(*piNode)++;
|
|
m_cnode++;
|
|
|
|
if (pNode->indent == 1)
|
|
{
|
|
hr = _InsertChildren(pNode->id, indent + 1, piNode);
|
|
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
}
|
|
|
|
MemFree(rgNode);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
void CAccountView::_PostCreate()
|
|
{
|
|
HRESULT hr;
|
|
DWORD iNode;
|
|
BOOL fNews, fSub;
|
|
|
|
Assert(m_cnode == 0);
|
|
|
|
ProcessICW(m_hwndOwner, m_ftType);
|
|
|
|
fNews = m_ftType == FOLDER_NEWS;
|
|
|
|
iNode = 0;
|
|
if (fNews)
|
|
hr = _InsertChildren(m_idFolder, 0, &iNode);
|
|
else
|
|
hr = _InsertChildrenSpecial(m_idFolder, 0, &iNode);
|
|
if (FAILED(hr))
|
|
{
|
|
if (m_rgnode != NULL)
|
|
{
|
|
MemFree(m_rgnode);
|
|
m_rgnode = NULL;
|
|
}
|
|
m_cnode = 0;
|
|
m_cnodeBuf = 0;
|
|
}
|
|
else
|
|
{
|
|
Assert(iNode == m_cnode);
|
|
}
|
|
|
|
ListView_SetItemCount(m_hwndList, m_cnode);
|
|
if (m_cnode > 0)
|
|
{
|
|
ListView_SetItemState(m_hwndList, -1, 0, LVIS_SELECTED | LVIS_FOCUSED);
|
|
ListView_SetItemState(m_hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
|
}
|
|
|
|
if (m_cnode == 0)
|
|
m_pEmptyList->Show(m_hwndList, m_ftType == FOLDER_NEWS ? (LPSTR)idsEmptyNewsAcct : (LPSTR)idsEmptyMailAcct);
|
|
|
|
UpdateWindow(m_hwndList);
|
|
|
|
g_pStore->RegisterNotify(IINDEX_SUBSCRIBED, REGISTER_NOTIFY_NOADDREF, 0, (IDatabaseNotify *)this);
|
|
m_fRegistered = TRUE;
|
|
|
|
fSub = FALSE;
|
|
|
|
if (m_cnode == 0 && (fNews || m_ftType == FOLDER_IMAP || m_ftType == FOLDER_HTTPMAIL))
|
|
{
|
|
if (IDYES == AthMessageBoxW(m_hwndOwner, MAKEINTRESOURCEW(idsAthena),
|
|
fNews ? MAKEINTRESOURCEW(idsErrNoSubscribedGroups) : MAKEINTRESOURCEW(idsErrNoSubscribedFolders),
|
|
0, MB_YESNO))
|
|
{
|
|
if (m_ftType == FOLDER_HTTPMAIL)
|
|
DownloadNewsgroupList(m_hwndOwner, m_idFolder);
|
|
else
|
|
DoSubscriptionDialog(m_hwndOwner, fNews, m_idFolder);
|
|
fSub = TRUE;
|
|
}
|
|
}
|
|
else if (m_ftType == FOLDER_IMAP && NULL != g_pStore)
|
|
{
|
|
FOLDERINFO fiServer;
|
|
|
|
if (SUCCEEDED(g_pStore->GetFolderInfo(m_idFolder, &fiServer)))
|
|
{
|
|
CheckIMAPDirty(fiServer.pszAccountId, m_hwnd, fiServer.idFolder, NOFLAGS);
|
|
g_pStore->FreeRecord(&fiServer);
|
|
}
|
|
}
|
|
|
|
if (!fSub && fNews)
|
|
hr = NewsUtil_CheckForNewGroups(m_hwnd, m_idFolder, &m_pGroups);
|
|
}
|
|
|
|
void CAccountView::_OnContextMenu(HWND hwnd, HWND hwndFrom, int x, int y)
|
|
{
|
|
HRESULT hr;
|
|
int iSel, i, id;
|
|
HMENU hmenu;
|
|
FOLDERID idFolder;
|
|
LV_HITTESTINFO lvhti;
|
|
POINT pt = {x, y};
|
|
|
|
// We only have context menus for the ListView
|
|
if (hwndFrom != m_hwndList)
|
|
return;
|
|
|
|
if (MAKELPARAM(x, y) == -1) // invoked from keyboard: figure out pos.
|
|
{
|
|
Assert(hwndFrom == m_hwndList);
|
|
i = ListView_GetFirstSel(m_hwndList);
|
|
if (i == -1)
|
|
return;
|
|
|
|
ListView_GetItemPosition(m_hwndList, i, &pt);
|
|
ClientToScreen(m_hwndList, &pt);
|
|
x = pt.x;
|
|
y = pt.y;
|
|
}
|
|
|
|
id = 0;
|
|
|
|
if (WindowFromPoint(pt) == m_hwndHeader)
|
|
{
|
|
// Pop up the context menu.
|
|
hmenu = LoadPopupMenu(IDR_COLUMNS_POPUP);
|
|
if (hmenu != NULL)
|
|
{
|
|
// Disable sort options because we don't support sorting
|
|
EnableMenuItem(hmenu, ID_SORT_ASCENDING, MF_GRAYED|MF_DISABLED);
|
|
EnableMenuItem(hmenu, ID_SORT_ASCENDING, MF_GRAYED|MF_DISABLED);
|
|
|
|
id = TrackPopupMenuEx(hmenu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
|
|
x, y, m_hwnd, NULL);
|
|
|
|
DestroyMenu(hmenu);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Find out where the click happened
|
|
lvhti.pt.x = x;
|
|
lvhti.pt.y = y;
|
|
ScreenToClient(m_hwndList, &lvhti.pt);
|
|
|
|
// Have the ListView tell us what element this was on
|
|
iSel = ListView_HitTest(m_hwndList, &lvhti);
|
|
if (iSel >= 0)
|
|
{
|
|
idFolder = _IdFromIndex((DWORD)iSel);
|
|
|
|
hr = MenuUtil_GetContextMenu(idFolder, (IOleCommandTarget *)this, &hmenu);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
id = TrackPopupMenuEx(hmenu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
|
|
x, y, m_hwnd, NULL);
|
|
DestroyMenu(hmenu);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (id != 0)
|
|
Exec(NULL, id, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
|
|
}
|
|
|
|
int __cdecl GroupCompare(const void *lParam1, const void *lParam2)
|
|
{
|
|
int cmp;
|
|
HRESULT hr;
|
|
FOLDERINFO info1, info2;
|
|
|
|
IxpAssert(lParam1 != NULL);
|
|
IxpAssert(lParam2 != NULL);
|
|
|
|
if (FAILED(g_pStore->GetFolderInfo(((FLDRNODE *)lParam1)->id, &info1)))
|
|
return -1;
|
|
if (FAILED(g_pStore->GetFolderInfo(((FLDRNODE *)lParam2)->id, &info2)))
|
|
{
|
|
g_pStore->FreeRecord(&info1);
|
|
return 1;
|
|
}
|
|
|
|
IxpAssert(0 == (info1.dwFlags & FOLDER_SERVER));
|
|
IxpAssert(0 == (info2.dwFlags & FOLDER_SERVER));
|
|
IxpAssert(info1.idParent == info2.idParent);
|
|
|
|
if (info1.tySpecial != FOLDER_NOTSPECIAL)
|
|
{
|
|
if (info2.tySpecial != FOLDER_NOTSPECIAL)
|
|
cmp = info1.tySpecial - info2.tySpecial;
|
|
else
|
|
cmp = -1;
|
|
}
|
|
else
|
|
{
|
|
if (info2.tySpecial != FOLDER_NOTSPECIAL)
|
|
cmp = 1;
|
|
else
|
|
cmp = lstrcmpi(info1.pszName, info2.pszName);
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info1);
|
|
g_pStore->FreeRecord(&info2);
|
|
|
|
return(cmp);
|
|
}
|
|
|
|
HRESULT CAccountView::_InsertFolder(LPFOLDERINFO pFolder)
|
|
{
|
|
BOOL fHide;
|
|
DWORD cnode, cSibs, indent, index, iFirstSib, iSib, iEnd;
|
|
HRESULT hr;
|
|
LV_ITEM lvi;
|
|
FLDRNODE *rgNodeSib, *pNode;
|
|
|
|
Assert(!!(pFolder->dwFlags & FOLDER_SUBSCRIBED));
|
|
|
|
// Check if folder is hidden
|
|
if (pFolder->dwFlags & FOLDER_HIDDEN)
|
|
return S_OK; // Do not display to user
|
|
|
|
if (pFolder->tyFolder == FOLDER_NEWS)
|
|
return(_InsertFolderNews(pFolder));
|
|
|
|
fHide = (m_cnode == 0);
|
|
|
|
index = _GetFolderIndex(pFolder->idFolder);
|
|
if (index != -1)
|
|
{
|
|
// TODO: are we safe to assume that this one doesn't have subscribed
|
|
// children that we aren't aware of????
|
|
return(S_OK);
|
|
}
|
|
|
|
// figure out which folder the new folder is being inserted under
|
|
if (pFolder->idParent == m_idFolder)
|
|
{
|
|
iFirstSib = 0;
|
|
indent = 0;
|
|
}
|
|
else
|
|
{
|
|
index = _GetFolderIndex(pFolder->idParent);
|
|
if (index == -1)
|
|
return(S_OK);
|
|
indent = m_rgnode[index].indent + 1;
|
|
iFirstSib = index + 1;
|
|
}
|
|
|
|
// get all of the siblings of the new folder
|
|
if (!MemAlloc((void **)&rgNodeSib, (m_cnode - iFirstSib + 1) * sizeof(FLDRNODE)))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
cSibs = 0;
|
|
for (iSib = iFirstSib, pNode = &m_rgnode[iSib]; iSib < m_cnode; iSib++, pNode++)
|
|
{
|
|
if (pNode->indent < indent)
|
|
{
|
|
break;
|
|
}
|
|
else if (pNode->indent == indent)
|
|
{
|
|
rgNodeSib[cSibs].id = pNode->id;
|
|
cSibs++;
|
|
}
|
|
}
|
|
iEnd = iSib;
|
|
|
|
// sort the new folder and its siblings, so we know where the new one needs
|
|
// to be inserted
|
|
rgNodeSib[cSibs].id = pFolder->idFolder;
|
|
cSibs++;
|
|
qsort(rgNodeSib, cSibs, sizeof(FLDRNODE), GroupCompare);
|
|
|
|
// find out where we're sticking the new folder
|
|
for (iSib = 0, pNode = rgNodeSib; iSib < cSibs; iSib++, pNode++)
|
|
{
|
|
if (pNode->id == pFolder->idFolder)
|
|
break;
|
|
}
|
|
Assert(iSib < cSibs);
|
|
|
|
if (iSib + 1 < cSibs)
|
|
index = _GetFolderIndex(rgNodeSib[iSib + 1].id);
|
|
else
|
|
index = iEnd;
|
|
|
|
MemFree(rgNodeSib);
|
|
|
|
if (m_cnode == m_cnodeBuf)
|
|
{
|
|
cnode = m_cnodeBuf + CALLOCIDBUF;
|
|
if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
m_cnodeBuf = cnode;
|
|
}
|
|
|
|
SetWindowRedraw(m_hwndList, FALSE);
|
|
|
|
if (index < m_cnode)
|
|
MoveMemory(&m_rgnode[index + 1], &m_rgnode[index], (m_cnode - index) * sizeof(FLDRNODE));
|
|
|
|
m_rgnode[index].id = pFolder->idFolder;
|
|
m_rgnode[index].indent = indent;
|
|
m_rgnode[index].dwDownload = m_dwDownloadDef;
|
|
m_cnode++;
|
|
|
|
iEnd = index + 1;
|
|
if (!!(pFolder->dwFlags & FOLDER_HASCHILDREN))
|
|
{
|
|
hr = _InsertChildren(pFolder->idFolder, indent + 1, &iEnd);
|
|
// TODO: error handling
|
|
Assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
ZeroMemory(&lvi, sizeof(LV_ITEM));
|
|
while (index < iEnd)
|
|
{
|
|
lvi.iItem = index++;
|
|
ListView_InsertItem(m_hwndList, &lvi);
|
|
}
|
|
|
|
if (fHide)
|
|
m_pEmptyList->Hide();
|
|
|
|
SetWindowRedraw(m_hwndList, TRUE);
|
|
UpdateWindow(m_hwndList);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::_InsertFolderNews(LPFOLDERINFO pFolder)
|
|
{
|
|
DWORD cnode;
|
|
HRESULT hr;
|
|
LV_ITEM lvi;
|
|
|
|
if (m_cnode == m_cnodeBuf)
|
|
{
|
|
cnode = m_cnodeBuf + CALLOCIDBUF;
|
|
if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
m_cnodeBuf = cnode;
|
|
}
|
|
|
|
m_rgnode[m_cnode].id = pFolder->idFolder;
|
|
m_rgnode[m_cnode].indent = 0;
|
|
m_rgnode[m_cnode].dwDownload = m_dwDownloadDef;
|
|
m_cnode++;
|
|
|
|
qsort(m_rgnode, m_cnode, sizeof(FLDRNODE), GroupCompare);
|
|
|
|
ZeroMemory(&lvi, sizeof(LV_ITEM));
|
|
lvi.iItem = _GetFolderIndex(pFolder->idFolder);
|
|
Assert(lvi.iItem != -1);
|
|
ListView_InsertItem(m_hwndList, &lvi);
|
|
|
|
if (m_cnode == 1)
|
|
m_pEmptyList->Hide();
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
int CAccountView::_GetFolderIndex(FOLDERID id)
|
|
{
|
|
int i;
|
|
FLDRNODE *pnode;
|
|
|
|
for (i = 0, pnode = m_rgnode; (DWORD)i < m_cnode; i++, pnode++)
|
|
{
|
|
if (id == pnode->id)
|
|
break;
|
|
}
|
|
|
|
if ((DWORD)i == m_cnode)
|
|
i = -1;
|
|
|
|
return(i);
|
|
}
|
|
|
|
HRESULT CAccountView::_UpdateFolder(LPFOLDERINFO pFolder1, LPFOLDERINFO pFolder2)
|
|
{
|
|
HRESULT hr;
|
|
int iItem;
|
|
|
|
// Visibility change (FOLDER_SUBSCRIBED or FOLDER_HIDDEN)
|
|
if (ISFLAGSET(pFolder1->dwFlags, FOLDER_SUBSCRIBED) != ISFLAGSET(pFolder2->dwFlags, FOLDER_SUBSCRIBED) ||
|
|
ISFLAGSET(pFolder1->dwFlags, FOLDER_HIDDEN) != ISFLAGSET(pFolder2->dwFlags, FOLDER_HIDDEN))
|
|
{
|
|
if (ISFLAGSET(pFolder2->dwFlags, FOLDER_SUBSCRIBED) && ISFLAGCLEAR(pFolder2->dwFlags, FOLDER_HIDDEN))
|
|
{
|
|
hr = _InsertFolder(pFolder2);
|
|
}
|
|
else
|
|
{
|
|
hr = _DeleteFolder(pFolder2);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
// Moved or renamed
|
|
if (pFolder1->idParent != pFolder2->idParent ||
|
|
0 != lstrcmpi(pFolder1->pszName, pFolder2->pszName))
|
|
{
|
|
Assert(m_ftType != FOLDER_NEWS);
|
|
|
|
hr = _DeleteFolder(pFolder1);
|
|
|
|
hr = _InsertFolder(pFolder2);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
// State change
|
|
if (pFolder1->cUnread != pFolder2->cUnread ||
|
|
pFolder1->cMessages != pFolder2->cMessages ||
|
|
(pFolder1->dwFlags & FOLDER_SYNCMASK) != (pFolder2->dwFlags & FOLDER_SYNCMASK) ||
|
|
0 != lstrcmp(pFolder1->pszName, pFolder2->pszName) ||
|
|
|
|
// news only
|
|
(pFolder1->tyFolder == FOLDER_NEWS &&
|
|
(pFolder1->dwServerCount != pFolder2->dwServerCount ||
|
|
pFolder1->dwServerHigh != pFolder2->dwServerHigh ||
|
|
pFolder1->dwServerLow != pFolder2->dwServerLow)))
|
|
{
|
|
iItem = _GetFolderIndex(pFolder1->idFolder);
|
|
if (iItem != -1)
|
|
ListView_RedrawItems(m_hwndList, iItem, iItem);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
int CAccountView::_GetSubFolderCount(int index)
|
|
{
|
|
DWORD indent;
|
|
int indexT;
|
|
|
|
Assert((DWORD)index < m_cnode);
|
|
|
|
indent = m_rgnode[index].indent;
|
|
|
|
index++;
|
|
indexT = index;
|
|
while ((DWORD)index < m_cnode)
|
|
{
|
|
if (m_rgnode[index].indent <= indent)
|
|
break;
|
|
index++;
|
|
}
|
|
|
|
return(index - indexT);
|
|
}
|
|
|
|
HRESULT CAccountView::_DeleteFolder(LPFOLDERINFO pFolder)
|
|
{
|
|
HRESULT hr;
|
|
int iItem, cSub;
|
|
|
|
iItem = _GetFolderIndex(pFolder->idFolder);
|
|
if (iItem == -1)
|
|
return(S_OK);
|
|
|
|
SetWindowRedraw(m_hwndList, FALSE);
|
|
|
|
cSub = _GetSubFolderCount(iItem);
|
|
|
|
if ((DWORD)(iItem + cSub) < (m_cnode - 1))
|
|
MoveMemory(&m_rgnode[iItem], &m_rgnode[iItem + cSub + 1], (m_cnode - (iItem + cSub + 1)) * sizeof(FLDRNODE));
|
|
m_cnode -= cSub + 1;
|
|
|
|
while (cSub >= 0)
|
|
{
|
|
ListView_DeleteItem(m_hwndList, iItem + cSub);
|
|
cSub--;
|
|
}
|
|
|
|
if (m_cnode == 0)
|
|
m_pEmptyList->Show(m_hwndList, m_ftType == FOLDER_NEWS ? (LPSTR)idsEmptyNewsAcct : (LPSTR)idsEmptyMailAcct);
|
|
|
|
SetWindowRedraw(m_hwndList, TRUE);
|
|
UpdateWindow(m_hwndList);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::_HandleAccountRename(LPFOLDERINFO pFolder)
|
|
{
|
|
char sz[CCHMAX_STRINGRES];
|
|
HDC hdc;
|
|
SIZE size;
|
|
HFONT hfontBold, hfontOld;
|
|
|
|
Assert(m_pszMajor != NULL);
|
|
Assert(pFolder != NULL);
|
|
|
|
AthLoadString(idsSyncManager, sz, ARRAYSIZE(sz));
|
|
wnsprintf(m_pszMajor, CCHMAX_STRINGRES, sz, pFolder->pszName);
|
|
|
|
hfontBold = HGetCharSetFont(FNT_SYS_ICON_BOLD, NULL);
|
|
|
|
hdc = GetDC(m_hwnd);
|
|
|
|
hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
|
|
|
|
GetTextExtentPoint32(hdc, m_pszMajor, lstrlen(m_pszMajor), &size);
|
|
m_rcMajor.left = SUBSCRIBE_BORDER;
|
|
m_rcMajor.top = SUBSCRIBE_BORDER;
|
|
m_rcMajor.right = m_rcMajor.left + size.cx;
|
|
m_rcMajor.bottom = m_rcMajor.top + size.cy;
|
|
|
|
SelectObject(hdc, hfontOld);
|
|
ReleaseDC(m_hwnd, hdc);
|
|
|
|
InvalidateRect(m_hwnd, NULL, FALSE);
|
|
UpdateWindow(m_hwnd);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CAccountView::OnTransaction(HTRANSACTION hTransaction, DWORD_PTR dwCookie, IDatabase *pDB)
|
|
{
|
|
BOOL fMatch;
|
|
DWORD i;
|
|
FOLDERINFO Folder1={0};
|
|
FOLDERINFO Folder2={0};
|
|
FOLDERINFO Server;
|
|
ORDINALLIST Ordinals;
|
|
TRANSACTIONTYPE tyTransaction;
|
|
INDEXORDINAL iIndex;
|
|
HRESULT hr;
|
|
|
|
while (hTransaction)
|
|
{
|
|
hr = pDB->GetTransaction(&hTransaction, &tyTransaction, &Folder1, &Folder2, &iIndex, &Ordinals);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
if (Folder1.idFolder == m_idFolder)
|
|
{
|
|
if (TRANSACTION_UPDATE == tyTransaction &&
|
|
0 != lstrcmp(Folder1.pszName, Folder2.pszName))
|
|
{
|
|
hr = _HandleAccountRename(&Folder2);
|
|
}
|
|
}
|
|
else if (Folder1.tyFolder == m_ftType && 0 == (Folder1.dwFlags & FOLDER_SERVER))
|
|
{
|
|
fMatch = FALSE;
|
|
|
|
if (m_ftType == FOLDER_LOCAL)
|
|
{
|
|
if (Folder1.tyFolder == FOLDER_LOCAL)
|
|
fMatch = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hr = GetFolderServer(Folder1.idParent, &Server);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fMatch = (Server.idFolder == m_idFolder);
|
|
g_pStore->FreeRecord(&Server);
|
|
}
|
|
}
|
|
|
|
if (fMatch)
|
|
{
|
|
// Insert (new Folder notification)
|
|
if (TRANSACTION_INSERT == tyTransaction)
|
|
{
|
|
hr = _InsertFolder(&Folder1);
|
|
}
|
|
// Update
|
|
else if (TRANSACTION_UPDATE == tyTransaction)
|
|
{
|
|
hr = _UpdateFolder(&Folder1, &Folder2);
|
|
}
|
|
|
|
// Delete
|
|
else if (TRANSACTION_DELETE == tyTransaction)
|
|
{
|
|
hr = _DeleteFolder(&Folder1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
g_pStore->FreeRecord(&Folder1);
|
|
g_pStore->FreeRecord(&Folder2);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::_ToggleDownload(int iItem)
|
|
{
|
|
FLDRNODE *pnode;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
|
|
pnode = _NodeFromIndex(iItem);
|
|
Assert(pnode != NULL);
|
|
|
|
hr = g_pStore->GetFolderInfo(pnode->id, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
|
|
{
|
|
if (!!(info.dwFlags & FOLDER_SYNCMASK))
|
|
{
|
|
pnode->dwDownload = (info.dwFlags & FOLDER_SYNCMASK);
|
|
info.dwFlags &= ~FOLDER_SYNCMASK;
|
|
}
|
|
else
|
|
{
|
|
Assert(0 == (pnode->dwDownload & ~FOLDER_SYNCMASK));
|
|
info.dwFlags |= pnode->dwDownload;
|
|
}
|
|
|
|
hr = g_pStore->UpdateRecord(&info);
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::_MarkForDownload(DWORD nCmdID)
|
|
{
|
|
int iSel;
|
|
FLDRFLAGS flag;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
FLDRNODE *pnode;
|
|
|
|
switch (nCmdID)
|
|
{
|
|
case ID_MARK_RETRIEVE_FLD_NEW_HDRS:
|
|
flag = FOLDER_DOWNLOADHEADERS;
|
|
break;
|
|
|
|
case ID_MARK_RETRIEVE_FLD_NEW_MSGS:
|
|
flag = FOLDER_DOWNLOADNEW;
|
|
break;
|
|
|
|
case ID_MARK_RETRIEVE_FLD_ALL_MSGS:
|
|
flag = FOLDER_DOWNLOADALL;
|
|
break;
|
|
|
|
case ID_UNMARK_RETRIEVE_FLD:
|
|
flag = 0;
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
break;
|
|
}
|
|
|
|
iSel = -1;
|
|
while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
|
|
{
|
|
pnode = _NodeFromIndex(iSel);
|
|
|
|
hr = g_pStore->GetFolderInfo(pnode->id, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!!(info.dwFlags & FOLDER_SUBSCRIBED) &&
|
|
(info.dwFlags & FOLDER_SYNCMASK) != flag)
|
|
{
|
|
if (flag == 0)
|
|
pnode->dwDownload = (info.dwFlags & FOLDER_SYNCMASK);
|
|
info.dwFlags &= ~FOLDER_SYNCMASK;
|
|
if (flag != 0)
|
|
info.dwFlags |= flag;
|
|
|
|
hr = g_pStore->UpdateRecord(&info);
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::_Subscribe(BOOL fSubscribe)
|
|
{
|
|
FOLDERID *pid;
|
|
int iSel, cSel, cid;
|
|
|
|
cSel = ListView_GetSelectedCount(m_hwndList);
|
|
if (cSel > 0)
|
|
{
|
|
if (!MemAlloc((void **)&pid, cSel * sizeof(FOLDERID)))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
cid = 0;
|
|
iSel = -1;
|
|
while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
|
|
{
|
|
Assert(cid < cSel);
|
|
pid[cid] = _IdFromIndex(iSel);
|
|
cid++;
|
|
}
|
|
|
|
MenuUtil_OnSubscribeGroups(m_hwndOwner, pid, cid, fSubscribe);
|
|
|
|
MemFree(pid);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CAccountView::_MarkAllRead()
|
|
{
|
|
int iSel;
|
|
IMessageFolder *pFolder;
|
|
ADJUSTFLAGS flags;
|
|
FOLDERID idFolder;
|
|
CStoreCB *pCB;
|
|
HRESULT hr;
|
|
|
|
pCB = new CStoreCB;
|
|
if (pCB == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
hr = pCB->Initialize(m_hwndOwner, MAKEINTRESOURCE(idsSettingMessageFlags), FALSE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
flags.dwAdd = ARF_READ;
|
|
flags.dwRemove = 0;
|
|
|
|
iSel = -1;
|
|
while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
|
|
{
|
|
idFolder = _IdFromIndex(iSel);
|
|
|
|
if (SUCCEEDED(g_pStore->OpenFolder(idFolder, NULL, NOFLAGS, &pFolder)))
|
|
{
|
|
hr = pFolder->SetMessageFlags(NULL, &flags, NULL, (IStoreCallback *)pCB);
|
|
if (hr == E_PENDING)
|
|
{
|
|
hr = pCB->Block();
|
|
|
|
pCB->Reset();
|
|
}
|
|
|
|
pFolder->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
|
|
pCB->Close();
|
|
}
|
|
|
|
pCB->Release();
|
|
|
|
return(S_OK);
|
|
}
|