#include "pch.hxx" #include #include #include #include "resource.h" #include "ourguid.h" #include "thormsgs.h" #include "goptions.h" #include "strconst.h" #include #include #include #include #include #include #include #include #include "shlwapip.h" #include #include "storutil.h" #include #include #include "newsutil.h" #include "acctview.h" #include #include #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); }