|
|
///////////////////////////////////////////////////////////////////////////////
//
// RulesUI.cpp
//
///////////////////////////////////////////////////////////////////////////////
#include <pch.hxx>
#include "rulesui.h"
#include "aplyrule.h"
#include "editrule.h"
#include "ruledesc.h"
#include "ruleutil.h"
#include "rulesmgr.h"
#include "rule.h"
#include "spamui.h"
#include "reutil.h"
#include <rulesdlg.h>
#include <imagelst.h>
#include <newfldr.h>
#include <instance.h>
#include "shlwapip.h"
#include <demand.h>
// Constants
class COEMailRulesPageUI : public COERulesPageUI { private: enum MOVE_DIR {MOVE_RULE_UP = 0, MOVE_RULE_DOWN = 1};
private: HWND m_hwndOwner; HWND m_hwndDlg; HWND m_hwndList; HWND m_hwndDescript; RULE_TYPE m_typeRule; CRuleDescriptUI * m_pDescriptUI;
public: COEMailRulesPageUI();
enum INIT_TYPE { INIT_MAIL = 0x00000000, INIT_NEWS = 0x00000001 }; COEMailRulesPageUI(DWORD dwFlagsInit) : COERulesPageUI(iddRulesMail, (0 != (dwFlagsInit & INIT_NEWS)) ? idsRulesNews : idsRulesMail, 0, 0), m_hwndOwner(NULL), m_hwndDlg(NULL), m_hwndList(NULL), m_hwndDescript(NULL), m_typeRule((0 != (dwFlagsInit & INIT_NEWS)) ? RULE_TYPE_NEWS : RULE_TYPE_MAIL), m_pDescriptUI(NULL) {} virtual ~COEMailRulesPageUI();
virtual HRESULT HrInit(HWND hwndOwner, DWORD dwFlags); virtual HRESULT HrCommitChanges(DWORD dwFlags, BOOL fClearDirty);
static INT_PTR CALLBACK FMailRulesPageDlgProc(HWND hwndDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
DLGPROC DlgProcGetPageDlgProc(VOID) {return FMailRulesPageDlgProc;}
BOOL FGetRules(RULE_TYPE typeRule, RULENODE ** pprnode); // Message handling methods
BOOL FOnInitDialog(HWND hwndDlg); BOOL FOnCommand(UINT uiNotify, INT iCtl, HWND hwndCtl); BOOL FOnNotify(INT iCtl, NMHDR * pnmhdr); BOOL FOnDestroy(VOID);
private: BOOL _FInitListCtrl(VOID); BOOL _FLoadListCtrl(VOID); BOOL _FAddRuleToList(DWORD dwIndex, RULEID ridRule, IOERule * pIRule); VOID _EnableButtons(INT iSelected); VOID _EnableRule(INT iSelected);
// For dealing with the description field
VOID _LoadRule(INT iSelected); BOOL _FSaveRule(INT iSelected);
// Functions to deal with the basic actions
VOID _NewRule(VOID); VOID _EditRule(INT iSelected); VOID _MoveRule(INT iSelected, MOVE_DIR dir); VOID _RemoveRule(INT iSelected); VOID _CopyRule(INT iSelected); VOID _OnApplyTo(INT iSelected);
BOOL _FOnLabelEdit(BOOL fBegin, NMLVDISPINFO * pdi); BOOL _FOnRuleDescValid(VOID); };
// Global data
const static HELPMAP g_rgCtxMapRulesMgr[] = { {0, 0}}; const static HELPMAP g_rgCtxMapMailRules[] = { {idbNewRule, idhNewRule}, {idbModifyRule, idhModifyRule}, {idbCopyRule, idhCopyRule}, {idbDeleteRule, idhRemoveRule}, {idbRulesApplyTo, idhRuleApply}, {idbMoveUpRule, idhRuleUp}, {idbMoveDownRule, idhRuleDown}, {idredtRuleDescription, idhRuleDescription}, {0, 0}}; COERulesMgrUI::COERulesMgrUI() : m_hwndOwner(NULL), m_dwFlags(0), m_dwState(0), m_hwndDlg(NULL), m_hwndTab(NULL) { ZeroMemory(m_rgRuleTab, sizeof(m_rgRuleTab)); }
COERulesMgrUI::~COERulesMgrUI() { ULONG ulIndex = 0; for (ulIndex = 0; ulIndex < RULE_PAGE_MAX; ulIndex++) { if (NULL != m_rgRuleTab[ulIndex]) { delete m_rgRuleTab[ulIndex]; } } }
HRESULT COERulesMgrUI::HrInit(HWND hwndOwner, DWORD dwFlags) { HRESULT hr = S_OK;
// Check incoming params
if (NULL == hwndOwner) { hr = E_INVALIDARG; goto exit; }
if (0 != (m_dwState & STATE_INITIALIZED)) { hr = E_UNEXPECTED; goto exit; } m_hwndOwner = hwndOwner;
m_dwFlags = dwFlags;
// Create each of the rule pages
if (!(g_dwAthenaMode & MODE_NEWSONLY)) { // Create the mail page
m_rgRuleTab[RULE_PAGE_MAIL] = new COEMailRulesPageUI(COEMailRulesPageUI::INIT_MAIL); if (NULL == m_rgRuleTab[RULE_PAGE_MAIL]) { hr = E_OUTOFMEMORY; goto exit; } }
// Create the news page
m_rgRuleTab[RULE_PAGE_NEWS] = new COEMailRulesPageUI(COEMailRulesPageUI::INIT_NEWS); if (NULL == m_rgRuleTab[RULE_PAGE_NEWS]) { hr = E_OUTOFMEMORY; goto exit; }
// Create the junk page
if ((0 == (g_dwAthenaMode & MODE_NEWSONLY)) && (0 != (g_dwAthenaMode & MODE_JUNKMAIL))) { m_rgRuleTab[RULE_PAGE_JUNK] = new COEJunkRulesPageUI(); if (NULL == m_rgRuleTab[RULE_PAGE_JUNK]) { hr = E_OUTOFMEMORY; goto exit; } }
// Create the senders page
m_rgRuleTab[RULE_PAGE_SENDERS] = new COESendersRulesPageUI(); if (NULL == m_rgRuleTab[RULE_PAGE_SENDERS]) { hr = E_OUTOFMEMORY; goto exit; }
m_dwState |= STATE_INITIALIZED; hr = S_OK; exit: return hr; }
HRESULT COERulesMgrUI::HrShow(VOID) { HRESULT hr = S_OK; int iRet = 0;
if (0 == (m_dwState & STATE_INITIALIZED)) { hr = E_UNEXPECTED; goto exit; }
// We need to load richedit
if (FALSE == FInitRichEdit(TRUE)) { hr = E_FAIL; goto exit; }
iRet = (INT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRulesManager), m_hwndOwner, COERulesMgrUI::FOERuleMgrDlgProc, (LPARAM) this); if (-1 == iRet) { hr = E_FAIL; goto exit; }
// Set the proper return code
hr = (IDOK == iRet) ? S_OK : S_FALSE; exit: return hr; }
INT_PTR CALLBACK COERulesMgrUI::FOERuleMgrDlgProc(HWND hwndDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { BOOL fRet = FALSE; COERulesMgrUI * pRulesUI = NULL;
pRulesUI = (COERulesMgrUI *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (uiMsg) { case WM_INITDIALOG: // Grab the UI object pointer
pRulesUI = (COERulesMgrUI *) lParam;
// Set it into the dialog so we can get it back
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pRulesUI);
if (FALSE == pRulesUI->FOnInitDialog(hwndDlg)) { EndDialog(hwndDlg, -1); fRet = TRUE; goto exit; } // We set the focus
fRet = FALSE; break;
case WM_COMMAND: fRet = pRulesUI->FOnCommand((UINT) HIWORD(wParam), (INT) LOWORD(wParam), (HWND) lParam); break;
case WM_NOTIFY: fRet = pRulesUI->FOnNotify((INT) LOWORD(wParam), (NMHDR *) lParam); break;
case WM_DESTROY: fRet = pRulesUI->FOnDestroy(); break; case WM_OE_GET_RULES: fRet = pRulesUI->FOnGetRules((RULE_TYPE) wParam, (RULENODE **) lParam); break; case WM_HELP: case WM_CONTEXTMENU: fRet = OnContextHelp(hwndDlg, uiMsg, wParam, lParam, g_rgCtxMapRulesMgr); break; } exit: return fRet; }
BOOL COERulesMgrUI::FOnInitDialog(HWND hwndDlg) { BOOL fRet = FALSE; HRESULT hr = S_OK; // Check incoming params
if (NULL == hwndDlg) { fRet = FALSE; goto exit; } // Save off the dialog window handle
m_hwndDlg = hwndDlg; // Set the default font onto the dialog
SetIntlFont(m_hwndDlg);
// Save off some of the controls
m_hwndTab = GetDlgItem(hwndDlg, idtbRulesTab); if (NULL == m_hwndTab) { fRet = FALSE; goto exit; } // Initialize tab control
fRet = _FInitTabCtrl(); if (FALSE == fRet) { goto exit; }
// Everything's AOK
fRet = TRUE; exit: return fRet; }
BOOL COERulesMgrUI::FOnCommand(UINT uiNotify, INT iCtl, HWND hwndCtl) { BOOL fRet = FALSE; INT iSel = 0; TCITEM tcitem = {0};
switch (iCtl) { case IDOK: if (FALSE != _FOnOK()) { EndDialog(m_hwndDlg, IDOK); fRet = TRUE; } break;
case IDCANCEL: EndDialog(m_hwndDlg, IDCANCEL); fRet = TRUE; break;
default: iSel = TabCtrl_GetCurSel(m_hwndTab); if (-1 == iSel) { fRet = FALSE; goto exit; }
tcitem.mask = TCIF_PARAM; if (FALSE == TabCtrl_GetItem(m_hwndTab, iSel, &tcitem)) { fRet = FALSE; goto exit; }
fRet = !!SendMessage((HWND) (tcitem.lParam), WM_COMMAND, MAKEWPARAM(iCtl, uiNotify), (LPARAM) hwndCtl); break; }
exit: return fRet; }
BOOL COERulesMgrUI::FOnNotify(INT iCtl, NMHDR * pnmhdr) { BOOL fRet = FALSE; INT iSel = 0; TCITEM tcitem = {0}; HWND hwndDlg = NULL; HWND hwndFocus = NULL;
switch (pnmhdr->code) { case TCN_SELCHANGING: // Get the window handle for the currently
// selected tab
iSel = TabCtrl_GetCurSel(m_hwndTab); if (-1 == iSel) { fRet = FALSE; goto exit; }
tcitem.mask = TCIF_PARAM; if (FALSE == TabCtrl_GetItem(m_hwndTab, iSel, &tcitem)) { fRet = FALSE; goto exit; }
hwndDlg = (HWND) tcitem.lParam; Assert(NULL != hwndDlg); // Hide and disable the current dialog
ShowWindow(hwndDlg, SW_HIDE); EnableWindow(hwndDlg, FALSE);
SetDlgMsgResult(hwndDlg, WM_NOTIFY, FALSE); fRet = TRUE; break;
case TCN_SELCHANGE: // Get the window handle for the currently
// selected tab
iSel = TabCtrl_GetCurSel(m_hwndTab); if (-1 == iSel) { fRet = FALSE; goto exit; }
tcitem.mask = TCIF_PARAM; if (FALSE == TabCtrl_GetItem(m_hwndTab, iSel, &tcitem)) { fRet = FALSE; goto exit; }
hwndDlg = (HWND) tcitem.lParam; Assert(NULL != hwndDlg); // Hide and disable the current dialog
ShowWindow(hwndDlg, SW_SHOW); EnableWindow(hwndDlg, TRUE);
// Set the focus to the first control
// if the focus isn't in the tab
hwndFocus = GetFocus(); if (hwndFocus != m_hwndTab) { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetNextDlgTabItem(hwndDlg, NULL, FALSE), (LPARAM) TRUE); } fRet = TRUE; break; }
exit: return fRet; }
BOOL COERulesMgrUI::FOnDestroy(VOID) { BOOL fRet = FALSE; UINT cTabs = 0; UINT uiIndex = 0; TC_ITEM tcitem; // Get the number of tabs
cTabs = TabCtrl_GetItemCount(m_hwndTab);
// Initialize the Tab control structure...
ZeroMemory(&tcitem, sizeof(tcitem)); tcitem.mask = TCIF_PARAM;
// Destroy the dialogs from each page
for (uiIndex = 0; uiIndex < cTabs; uiIndex++) { // Get the window handle for the dialog
if (FALSE != TabCtrl_GetItem(m_hwndTab, uiIndex, &tcitem)) { // Destroy the dialog
DestroyWindow((HWND) tcitem.lParam); } }
fRet = TRUE; return fRet; }
BOOL COERulesMgrUI::FOnGetRules(RULE_TYPE typeRule, RULENODE ** pprnode) { BOOL fRet = FALSE; RULENODE * prnodeList = NULL; RULENODE * prnodeSender = NULL; RULENODE * prnodeJunk = NULL; RULENODE * prnodeWalk = NULL; if (NULL == pprnode) { fRet = FALSE; goto exit; }
// Initialize the outgoing param
*pprnode = NULL; // Forward the message to the correct dialog
switch(typeRule) { case RULE_TYPE_MAIL: // Get the rules from the senders page
if (NULL != m_rgRuleTab[RULE_PAGE_SENDERS]) { fRet = m_rgRuleTab[RULE_PAGE_SENDERS]->FGetRules(RULE_TYPE_MAIL, &prnodeSender); } // Get the rules from the mail rules page
if (NULL != m_rgRuleTab[RULE_PAGE_MAIL]) { fRet = m_rgRuleTab[RULE_PAGE_MAIL]->FGetRules(RULE_TYPE_MAIL, &prnodeList); } // Get the rules from the junk mail page
if (NULL != m_rgRuleTab[RULE_PAGE_JUNK]) { fRet = m_rgRuleTab[RULE_PAGE_JUNK]->FGetRules(RULE_TYPE_MAIL, &prnodeJunk); }
break; case RULE_TYPE_NEWS: // Get the rules from the senders page
if (NULL != m_rgRuleTab[RULE_PAGE_SENDERS]) { fRet = m_rgRuleTab[RULE_PAGE_SENDERS]->FGetRules(RULE_TYPE_NEWS, &prnodeSender); }
// Get the rules from the news rules page
if (NULL != m_rgRuleTab[RULE_PAGE_NEWS]) { fRet = m_rgRuleTab[RULE_PAGE_NEWS]->FGetRules(RULE_TYPE_NEWS, &prnodeList); } break;
default: Assert(FALSE); fRet = FALSE; goto exit; break; }
// Set up the list
if (NULL != prnodeJunk) { Assert(NULL == prnodeJunk->pNext);
if (NULL == prnodeList) { prnodeList = prnodeJunk; } else { prnodeWalk = prnodeList; while (NULL != prnodeWalk->pNext) { prnodeWalk = prnodeWalk->pNext; }
prnodeWalk->pNext = prnodeJunk; } prnodeJunk = NULL; } if (NULL != prnodeSender) { Assert(NULL == prnodeSender->pNext);
prnodeSender->pNext = prnodeList; prnodeList = prnodeSender; prnodeSender = NULL; } // Set the outgoing param
*pprnode = prnodeList; prnodeList = NULL; // Tell the dialog it's aok to proceed
SetDlgMsgResult(m_hwndDlg, WM_OE_GET_RULES, TRUE);
fRet = TRUE;
exit: while (NULL != prnodeList) { prnodeWalk = prnodeList; if (NULL != prnodeWalk->pIRule) { prnodeWalk->pIRule->Release(); } prnodeList = prnodeList->pNext; delete prnodeWalk; //MemFree(prnodeWalk);
} if (NULL != prnodeJunk) { if (NULL != prnodeJunk->pIRule) { prnodeJunk->pIRule->Release(); } delete prnodeJunk; // MemFree(prnodeJunk);
} if (NULL != prnodeSender) { if (NULL != prnodeSender->pIRule) { prnodeSender->pIRule->Release(); } delete prnodeSender; //MemFree(prnodeSender);
} return fRet; }
BOOL COERulesMgrUI::_FOnOK(VOID) { BOOL fRet = FALSE; UINT uiRuleTab = 0; HRESULT hr = S_OK;
// Add the tabs to the tab control
for (uiRuleTab = 0; uiRuleTab < RULE_PAGE_MAX; uiRuleTab++) { if (NULL == m_rgRuleTab[uiRuleTab]) { continue; } hr = m_rgRuleTab[uiRuleTab]->HrCommitChanges(0, TRUE); if ((FAILED(hr)) && (E_UNEXPECTED != hr)) { fRet = FALSE; goto exit; } }
fRet = TRUE; exit: return fRet; }
BOOL COERulesMgrUI::_FOnCancel(VOID) { return TRUE; }
BOOL COERulesMgrUI::_FInitTabCtrl(VOID) { BOOL fRet = FALSE; TCITEM tcitem; TCHAR szRes[CCHMAX_STRINGRES]; UINT uiRuleTab = 0; HWND hwndDlg = NULL; UINT cRuleTab = 0; UINT uiDefaultTab = 0; NMHDR nmhdr;
// Make sure we have a resource dll
Assert(g_hLocRes); // Initialize the Tab control structure...
ZeroMemory(&tcitem, sizeof(tcitem)); tcitem.mask = TCIF_PARAM | TCIF_TEXT; tcitem.pszText = szRes; tcitem.iImage = -1;
// Add the tabs to the tab control
for (uiRuleTab = 0; uiRuleTab < RULE_PAGE_MAX; uiRuleTab++) { // Initialize each of the pages
if ((NULL == m_rgRuleTab[uiRuleTab]) || (FAILED(m_rgRuleTab[uiRuleTab]->HrInit(m_hwndDlg, m_dwFlags)))) { continue; } // Create the child dialog for the tab
hwndDlg = CreateDialogParam(g_hLocRes, MAKEINTRESOURCE(m_rgRuleTab[uiRuleTab]->UiGetDlgRscId()), m_hwndDlg, m_rgRuleTab[uiRuleTab]->DlgProcGetPageDlgProc(), (LPARAM) (m_rgRuleTab[uiRuleTab])); if (NULL == hwndDlg) { continue; } tcitem.lParam = (LPARAM) hwndDlg; // Load in the display string for the tab
LoadString(g_hLocRes, m_rgRuleTab[uiRuleTab]->UiGetTabLabelId(), szRes, ARRAYSIZE(szRes)); // Insert the tab
TabCtrl_InsertItem(m_hwndTab, cRuleTab, &tcitem);
// Save off the default tab
if (uiRuleTab == (m_dwFlags & RULE_PAGE_MASK)) { uiDefaultTab = cRuleTab; } cRuleTab++; }
if (0 == cRuleTab) { fRet = FALSE; goto exit; }
// Select the proper tab
if (-1 != TabCtrl_SetCurSel(m_hwndTab, uiDefaultTab)) { nmhdr.hwndFrom = m_hwndTab; nmhdr.idFrom = idtbRulesTab; nmhdr.code = TCN_SELCHANGE; SideAssert(FALSE != FOnNotify(idtbRulesTab, &nmhdr)); }
// Need to set the tab control to the bottom of the Z-order
// to prevent overlapping redraws
SetWindowPos(m_hwndTab, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
// We worked
fRet = TRUE;
exit: return fRet; }
// Default destructor for the Mail Rules UI
COEMailRulesPageUI::~COEMailRulesPageUI() { if (NULL != m_pDescriptUI) { delete m_pDescriptUI; } }
///////////////////////////////////////////////////////////////////////////////
//
// HrInit
//
// This initializes the mail rules UI dialog
//
// hwndOwner - the handle to the owner window of this dialog
// dwFlags - modifiers on how this dialog should act
//
// Returns: S_OK, if it was successfully initialized
//
///////////////////////////////////////////////////////////////////////////////
HRESULT COEMailRulesPageUI::HrInit(HWND hwndOwner, DWORD dwFlags) { HRESULT hr = S_OK;
// Check incoming params
if (NULL == hwndOwner) { hr = E_INVALIDARG; goto exit; }
if (0 != (m_dwState & STATE_INITIALIZED)) { hr = E_UNEXPECTED; goto exit; } m_hwndOwner = hwndOwner;
m_dwFlags = dwFlags;
// Setup the description field
m_pDescriptUI = new CRuleDescriptUI; if (NULL == m_pDescriptUI) { hr = E_OUTOFMEMORY; goto exit; }
m_dwState |= STATE_INITIALIZED; hr = S_OK; exit: return hr; }
///////////////////////////////////////////////////////////////////////////////
//
// HrCommitChanges
//
// This commits the changes to the rules
//
// dwFlags - modifiers on how we should commit the changes
// fClearDirty - should we clear the dirty state
//
// Returns: S_OK, if it was successfully committed
//
///////////////////////////////////////////////////////////////////////////////
HRESULT COEMailRulesPageUI::HrCommitChanges(DWORD dwFlags, BOOL fClearDirty) { HRESULT hr = S_OK; LONG cRules = 0; INT iSelected = 0; RULEINFO * pinfoRule = NULL; ULONG cpinfoRule = 0; LVITEM lvitem = {0};
Assert(NULL != m_hwndList); // Check incoming params
if (0 != dwFlags) { hr = E_INVALIDARG; goto exit; }
// Fail if we weren't initialized
if (0 == (m_dwState & STATE_INITIALIZED)) { hr = E_UNEXPECTED; goto exit; }
// If we aren't dirty, then there's
// nothing to do
if ((0 == (m_dwState & STATE_DIRTY)) && (S_OK != m_pDescriptUI->HrIsDirty())) { hr = S_FALSE; goto exit; }
// Get the number of rules in the list view
cRules = ListView_GetItemCount(m_hwndList);
if (0 != cRules) { // Let's make sure the selected rule is saved...
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { _FSaveRule(iSelected); }
// Allocate space to hold the rules
hr = HrAlloc( (void **) &pinfoRule, cRules * sizeof(*pinfoRule)); if (FAILED(hr)) { goto exit; }
ZeroMemory(pinfoRule, cRules * sizeof(*pinfoRule));
lvitem.mask = LVIF_PARAM; cpinfoRule = 0; for (lvitem.iItem = 0; lvitem.iItem < cRules; lvitem.iItem++) { // Grab the rule from the list view
if (FALSE != ListView_GetItem(m_hwndList, &lvitem)) { if (NULL == lvitem.lParam) { continue; } pinfoRule[cpinfoRule] = *((RULEINFO *) (lvitem.lParam)); cpinfoRule++; } } } // Set the rules into the rules manager
hr = g_pRulesMan->SetRules(SETF_CLEAR, m_typeRule, pinfoRule, cpinfoRule); if (FAILED(hr)) { goto exit; } // Should we clear the dirty state
if (FALSE != fClearDirty) { m_dwState &= ~STATE_DIRTY; } hr = S_OK; exit: SafeMemFree(pinfoRule); return hr; }
INT_PTR CALLBACK COEMailRulesPageUI::FMailRulesPageDlgProc(HWND hwndDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { BOOL fRet = FALSE; COEMailRulesPageUI * pMailUI = NULL; HWND hwndRE = 0;
pMailUI = (COEMailRulesPageUI *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (uiMsg) { case WM_INITDIALOG: // Grab the UI object pointer
pMailUI = (COEMailRulesPageUI *) lParam;
// Set it into the dialog so we can get it back
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) pMailUI);
hwndRE = CreateREInDialogA(hwndDlg, idredtRuleDescription);
if (!hwndRE || (FALSE == pMailUI->FOnInitDialog(hwndDlg))) { EndDialog(hwndDlg, -1); fRet = TRUE; goto exit; } // We didn't set the focus so return TRUE
fRet = TRUE; break;
case WM_COMMAND: fRet = pMailUI->FOnCommand((UINT) HIWORD(wParam), (INT) LOWORD(wParam), (HWND) lParam); break;
case WM_NOTIFY: fRet = pMailUI->FOnNotify((INT) LOWORD(wParam), (NMHDR *) lParam); break;
case WM_DESTROY: fRet = pMailUI->FOnDestroy(); break;
case WM_HELP: case WM_CONTEXTMENU: fRet = OnContextHelp(hwndDlg, uiMsg, wParam, lParam, g_rgCtxMapMailRules); break; } exit: return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// FGetRules
//
// This brings up the edit UI for the selected rule from the mail rules list
//
// fBegin - is this for the LVN_BEGINLABELEDIT notification
// pdi - the display info for the message
//
// Returns: TRUE, if the message was handled
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::FGetRules(RULE_TYPE typeRule, RULENODE ** pprnode) { BOOL fRet = FALSE; INT iSelected = 0; INT cRules = 0; LVITEM lvitem; IOERule * pIRule = NULL; RULENODE * prnodeNew = NULL; RULENODE * prnodeList = NULL; RULENODE * prnodeWalk = NULL; HRESULT hr = S_OK; RULEINFO * pinfoRule = NULL;
Assert(NULL != m_hwndList);
if (NULL == pprnode) { fRet = FALSE; goto exit; }
// Fail if we weren't initialized
if ((0 == (m_dwState & STATE_INITIALIZED)) || (NULL == m_hwndList)) { fRet = FALSE; goto exit; }
// Initialize the outgoing param
*pprnode = NULL; // Get the selected item
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED);
// Make sure we don't loose any changes
_FSaveRule(iSelected); // Check the count of items in the list view
cRules = ListView_GetItemCount(m_hwndList); if (0 == cRules) { fRet = TRUE; goto exit; } // Initialize the list view item
ZeroMemory(&lvitem, sizeof(lvitem)); lvitem.mask = LVIF_PARAM | LVIF_STATE; lvitem.stateMask = LVIS_STATEIMAGEMASK;
// Create the list of rules
for (lvitem.iItem = 0; lvitem.iItem < cRules; lvitem.iItem++) { // Grab the rule from the listview
if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { fRet = FALSE; goto exit; } pinfoRule = (RULEINFO *) (lvitem.lParam);
if ((NULL == pinfoRule) || (NULL == pinfoRule->pIRule)) { continue; }
// Skip over invalid rules
hr = pinfoRule->pIRule->Validate(0); if (FAILED(hr) || (S_FALSE == hr)) { continue; }
// Create a new rule node
prnodeNew = new RULENODE; if (NULL == prnodeNew) { fRet = FALSE; goto exit; }
prnodeNew->pNext = NULL; prnodeNew->pIRule = pinfoRule->pIRule; prnodeNew->pIRule->AddRef();
// Add the new node to the list
if (NULL == prnodeWalk) { prnodeList = prnodeNew; } else { prnodeWalk->pNext = prnodeNew; } prnodeWalk = prnodeNew; prnodeNew = NULL; }
// Set the outgoing param
*pprnode = prnodeList; prnodeList = NULL; fRet = TRUE; exit: while (NULL != prnodeList) { prnodeWalk = prnodeList; if (NULL != prnodeWalk->pIRule) { prnodeWalk->pIRule->Release(); } prnodeList = prnodeList->pNext; delete prnodeWalk; //MemFree(prnodeWalk);
} return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// FOnInitDialog
//
// This handles the WM_INITDIALOG message for the mail rules UI dialog
//
// hwndDlg - the handle to the dialog window
//
// Returns: TRUE, if it was successfully initialized
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::FOnInitDialog(HWND hwndDlg) { BOOL fRet = FALSE; HRESULT hr = S_OK; TCHAR szRes[CCHMAX_STRINGRES]; // Check incoming params
if (NULL == hwndDlg) { fRet = FALSE; goto exit; }
// If we haven't been initialized yet...
if (0 == (m_dwState & STATE_INITIALIZED)) { fRet = FALSE; goto exit; } // Save off the dialog window handle
m_hwndDlg = hwndDlg; // Set the default font onto the dialog
SetIntlFont(m_hwndDlg);
// Save off some of the controls
m_hwndList = GetDlgItem(hwndDlg, idlvRulesList); m_hwndDescript = GetDlgItem(hwndDlg, idredtRuleDescription); if ((NULL == m_hwndList) || (NULL == m_hwndDescript)) { fRet = FALSE; goto exit; }
// We need to change the title if we are a news page
if (RULE_TYPE_NEWS == m_typeRule) { if (0 == LoadString(g_hLocRes, idsRuleTitleNews, szRes, ARRAYSIZE(szRes))) { goto exit; }
SetDlgItemText(m_hwndDlg, idcRuleTitle, szRes); } else { if (FALSE != FIsIMAPOrHTTPAvailable()) { AthLoadString(idsRulesNoIMAP, szRes, sizeof(szRes));
SetDlgItemText(m_hwndDlg, idcRuleTitle, szRes); } } if (FAILED(m_pDescriptUI->HrInit(m_hwndDescript, 0))) { fRet = FALSE; goto exit; } // Initialize the list view
fRet = _FInitListCtrl(); if (FALSE == fRet) { goto exit; }
// Load the list view
fRet = _FLoadListCtrl(); if (FALSE == fRet) { goto exit; }
// Check to see if the list is empty
if (0 == ListView_GetItemCount(m_hwndList)) { if (((m_typeRule == RULE_TYPE_MAIL) && (RMF_MAIL == m_dwFlags)) || ((m_typeRule == RULE_TYPE_NEWS) && (RMF_NEWS == m_dwFlags))) { PostMessage(m_hwndDlg, WM_COMMAND, MAKEWPARAM(idbNewRule, 0), (LPARAM) (GetDlgItem(m_hwndDlg, idbNewRule))); } }
// Everything's AOK
fRet = TRUE; exit: return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// FOnCommand
//
// This handles the WM_COMMAND message for the mail rules UI dialog
//
// Returns: TRUE, if it was successfully handled
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::FOnCommand(UINT uiNotify, INT iCtl, HWND hwndCtl) { BOOL fRet = FALSE; LVITEM lvitem; INT iSelected = 0;
// We only handle menu and accelerator commands
if ((0 != uiNotify) && (1 != uiNotify)) { fRet = FALSE; goto exit; } switch (iCtl) { case idbNewRule: _NewRule(); fRet = TRUE; break;
case idbModifyRule: // Get the selected item from the rule list
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { // Bring up the rule editor for that item
_EditRule(iSelected); fRet = TRUE; } break;
case idbMoveUpRule: case idbMoveDownRule: // Get the selected item from the rule list
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { // Move the rule in the desired direction
_MoveRule(iSelected, (idbMoveUpRule == iCtl) ? MOVE_RULE_UP : MOVE_RULE_DOWN); fRet = TRUE; } break;
case idbDeleteRule: // Get the selected item from the rule list
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { // Remove the rule from the list
_RemoveRule(iSelected); fRet = TRUE; } break; case idbCopyRule: // Get the selected item from the rule list
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { // Copy the rule from the list
_CopyRule(iSelected); fRet = TRUE; } break; case idbRulesApplyTo: // Apply the rule from the list
_OnApplyTo(ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED)); fRet = TRUE; break; }
exit: return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// FOnNotify
//
// This handles the WM_NOTIFY message for the mail rules UI dialog
//
// Returns: TRUE, if it was successfully destroyed
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::FOnNotify(INT iCtl, NMHDR * pnmhdr) { BOOL fRet = FALSE; NMLISTVIEW * pnmlv = NULL; NMLVKEYDOWN * pnmlvkd = NULL; INT iSelected = 0; LVHITTESTINFO lvh;
// We only handle notifications for the list control
// or the desscription field
if ((idlvRulesList != pnmhdr->idFrom) && (idredtRuleDescription != pnmhdr->idFrom)) { fRet = FALSE; goto exit; } pnmlv = (LPNMLISTVIEW) pnmhdr;
switch (pnmlv->hdr.code) { case NM_CLICK: // Did we click on an item?
if (-1 != pnmlv->iItem) { ZeroMemory(&lvh, sizeof(lvh)); lvh.pt = pnmlv->ptAction; iSelected = ListView_HitTest(m_hwndList, &lvh); if (-1 != iSelected) { // Did we click on the enable field?
if ((0 != (lvh.flags & LVHT_ONITEMSTATEICON)) && (0 == (lvh.flags & LVHT_ONITEMLABEL))) { // Make sure this item is selected
ListView_SetItemState(m_hwndList, iSelected, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); // Set the proper enable state
_EnableRule(iSelected); } } } else { // We clicked outside the list
// Disable the buttons
_EnableButtons(pnmlv->iItem); } break; case NM_DBLCLK: // Did we click on an item?
if (-1 != pnmlv->iItem) { ZeroMemory(&lvh, sizeof(lvh)); lvh.pt = pnmlv->ptAction; iSelected = ListView_HitTest(pnmlv->hdr.hwndFrom, &lvh); if (-1 != iSelected) { // Did we click on the rule name?
if (0 != (lvh.flags & LVHT_ONITEMLABEL)) { // Edit the rule
_EditRule(iSelected); } } } else { // We clicked outside the list
// Disable the buttons
_EnableButtons(pnmlv->iItem); } break; case LVN_ITEMCHANGED: // If an item's state changed to selected..
if ((-1 != pnmlv->iItem) && (0 != (pnmlv->uChanged & LVIF_STATE)) && (0 == (pnmlv->uOldState & LVIS_SELECTED)) && (0 != (pnmlv->uNewState & LVIS_SELECTED))) { // Enable the buttons
_EnableButtons(pnmlv->iItem); } break; case LVN_ITEMCHANGING: // If an item's state changed to unselected..
if ((-1 != pnmlv->iItem) && (0 != (pnmlv->uChanged & LVIF_STATE)) && (0 != (pnmlv->uOldState & LVIS_SELECTED)) && (0 == (pnmlv->uNewState & LVIS_SELECTED))) { // Save off the rule changes
_FSaveRule(pnmlv->iItem); } break; case LVN_KEYDOWN: pnmlvkd = (NMLVKEYDOWN *) pnmhdr;
// The space key changes the enable state of a rule
if (VK_SPACE == pnmlvkd->wVKey) { // Are we on a rule?
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { // Change the enable state of the rule
_EnableRule(iSelected); } } // The delete key removes the rule from the list view
else if (VK_DELETE == pnmlvkd->wVKey) { // Are we on a rule?
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 != iSelected) { // Remove the rule from the list
_RemoveRule(iSelected); } } break; case LVN_BEGINLABELEDIT: case LVN_ENDLABELEDIT: fRet = _FOnLabelEdit((LVN_BEGINLABELEDIT == pnmlv->hdr.code), (NMLVDISPINFO *) pnmhdr); break;
case NM_RULE_CHANGED: fRet = _FOnRuleDescValid(); break; }
exit: return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// FOnDestroy
//
// This handles the WM_DESTROY message for the mail rules UI dialog
//
// Returns: TRUE, if it was successfully destroyed
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::FOnDestroy(VOID) { BOOL fRet = FALSE; UINT cRules = 0; UINT uiIndex = 0; LVITEM lvitem = {0}; UNALIGNED RULEINFO * pIRuleInfo = NULL;
Assert(m_hwndList); // Get the number of rules in the list view
cRules = ListView_GetItemCount(m_hwndList);
// Initialize to get the rule interface from the list view
lvitem.mask = LVIF_PARAM;
// Release each of the rules from the list view
for (uiIndex = 0; uiIndex < cRules; uiIndex++) { lvitem.iItem = uiIndex; // Get the rule interface
if (FALSE != ListView_GetItem(m_hwndList, &lvitem)) { pIRuleInfo = (UNALIGNED RULEINFO *) (lvitem.lParam);
if (NULL != pIRuleInfo) { // Release the rule
if (NULL != pIRuleInfo->pIRule) { pIRuleInfo->pIRule->Release(); } delete pIRuleInfo; // MemFree(pIRuleInfo);
} } }
fRet = TRUE; return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// _FInitListCtrl
//
// This initializes the list view control in the mail rules dialog
//
// Returns: TRUE, on successful initialization
// FALSE, otherwise.
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::_FInitListCtrl(VOID) { BOOL fRet = FALSE; LVCOLUMN lvc; RECT rc; HIMAGELIST himl = NULL;
Assert(NULL != m_hwndList); // Initialize the list view structure
ZeroMemory(&lvc, sizeof(lvc)); lvc.mask = LVCF_WIDTH;
// Calculate the size of the list view
GetClientRect(m_hwndList, &rc); lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
ListView_InsertColumn(m_hwndList, 0, &lvc); // Set the state image list
himl = ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idb16x16st), 16, 0, RGB(255, 0, 255)); if (NULL != himl) { ListView_SetImageList(m_hwndList, himl, LVSIL_STATE); }
// Full row selection on listview
ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT);
// We worked
fRet = TRUE; return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// _FLoadListCtrl
//
// This loads the list view with the current Mail rules
//
// Returns: TRUE, if it was successfully loaded
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::_FLoadListCtrl(VOID) { BOOL fRet = FALSE; HRESULT hr = S_OK; DWORD dwListIndex = 0; RULEINFO * pinfoRules = NULL; ULONG cpinfoRules = 0; ULONG ulIndex = 0; IOERule * pIRule = NULL;
Assert(NULL != m_hwndList);
// Get the Rules enumerator
Assert(NULL != g_pRulesMan); hr = g_pRulesMan->GetRules(GETF_EDIT, m_typeRule, &pinfoRules, &cpinfoRules); if (FAILED(hr)) { fRet = FALSE; goto exit; } // Remove all the items from the list control
ListView_DeleteAllItems(m_hwndList);
// Add each filter to the list
dwListIndex = 0;
for (ulIndex = 0; ulIndex < cpinfoRules; ulIndex++) { // Make a copy of the rule
hr = pinfoRules[ulIndex].pIRule->Clone(&pIRule); if (FAILED(hr)) { continue; } // Add filter to the list
if (FALSE != _FAddRuleToList(dwListIndex, pinfoRules[ulIndex].ridRule, pIRule)) { dwListIndex++; }
SafeRelease(pIRule); }
// Select the first item in the list
if (0 != dwListIndex) { ListView_SetItemState(m_hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); } // Enable the dialog buttons.
_EnableButtons((0 != dwListIndex) ? 0 : -1);
fRet = TRUE; exit: SafeRelease(pIRule); if (NULL != pinfoRules) { for (ulIndex = 0; ulIndex < cpinfoRules; ulIndex++) { pinfoRules[ulIndex].pIRule->Release(); } MemFree(pinfoRules); } return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// _FAddRuleToList
//
// This adds the filter passed in to the list view
//
// dwIndex - the index on where to add the filter to into the list
// rhdlTag - the rule handle for the new rule
// pIRule - the actual rule
//
// Returns: TRUE, if it was successfully added
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::_FAddRuleToList(DWORD dwIndex, RULEID ridRule, IOERule * pIRule) { BOOL fRet = FALSE; HRESULT hr = S_OK; PROPVARIANT propvar = {0}; LVITEM lvitem = {0}; BOOL fNotValid = FALSE; BOOL fDisabled = FALSE; RULEINFO * pinfoRule = NULL;
Assert(NULL != m_hwndList);
// If there's nothing to do...
if (NULL == pIRule) { fRet = FALSE; goto exit; } // Is it disabled?
hr = pIRule->GetProp(RULE_PROP_DISABLED, 0, &propvar); if (FAILED(hr)) { fRet = FALSE; goto exit; }
fDisabled = !!propvar.boolVal; // Need to check if the rule is valid
hr = pIRule->Validate(0); if (FAILED(hr)) { fRet = FALSE; goto exit; }
fNotValid = (hr == S_FALSE);
// Find out the name of the filter
hr = pIRule->GetProp(RULE_PROP_NAME , 0, &propvar); if (FAILED(hr)) { fRet = FALSE; goto exit; }
// Allocate space for the rule
pinfoRule = new RULEINFO; if (NULL == pinfoRule) { fRet = FALSE; goto exit; }
// Set up the value
pinfoRule->ridRule = ridRule; pinfoRule->pIRule = pIRule; pinfoRule->pIRule->AddRef(); // Add in the image and rule interface
lvitem.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; lvitem.iItem = dwIndex; // Need to change the state to mark the rule as invalid
if (FALSE != fNotValid) { lvitem.state = INDEXTOSTATEIMAGEMASK(iiconStateInvalid + 1); } else { lvitem.state = fDisabled ? INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1); } lvitem.stateMask = LVIS_STATEIMAGEMASK; lvitem.pszText = propvar.pszVal; lvitem.cchTextMax = lstrlen(propvar.pszVal) + 1; lvitem.lParam = (LPARAM) pinfoRule;
if (-1 == ListView_InsertItem(m_hwndList, &lvitem)) { fRet = FALSE; goto exit; }
fRet = TRUE; exit: PropVariantClear(&propvar); return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// _EnableButtons
//
// This enables or disables the buttons in the Mail rules UI dialog
// depending on what is selected.
//
// iSelected - the item that was selected,
// -1 means that nothing was selected
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
void COEMailRulesPageUI::_EnableButtons(INT iSelected) { int cRules = 0; BOOL fSelected = FALSE; BOOL fEnDisUp = FALSE; BOOL fEnDisDown = FALSE; LVITEM lvitem = {0}; IOERule * pIRule = NULL;
Assert(NULL != m_hwndList);
// Load the description field
_LoadRule(iSelected); // Check the count of items in the list view
cRules = ListView_GetItemCount(m_hwndList);
fSelected = (-1 != iSelected); // If we have rules and the top rule isn't selected
fEnDisUp = ((1 < cRules) && (0 != iSelected) && (FALSE != fSelected));
// If we have rules and the bottom rule ins't selected
fEnDisDown = ((1 < cRules) && ((cRules - 1) != iSelected) && (FALSE != fSelected));
// Enable the up/down buttons
RuleUtil_FEnDisDialogItem(m_hwndDlg, idbMoveDownRule, fEnDisDown); RuleUtil_FEnDisDialogItem(m_hwndDlg, idbMoveUpRule, fEnDisUp);
// Enable the rule action buttons
RuleUtil_FEnDisDialogItem(m_hwndDlg, idbDeleteRule, fSelected); RuleUtil_FEnDisDialogItem(m_hwndDlg, idbCopyRule, fSelected); RuleUtil_FEnDisDialogItem(m_hwndDlg, idbModifyRule, fSelected); return; }
///////////////////////////////////////////////////////////////////////////////
//
// _EnableRule
//
// This switches the current enabled state of the list view item
// and updates the UI
//
// iSelected - index of the item in the listview to work on
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
VOID COEMailRulesPageUI::_EnableRule(int iSelected) { HRESULT hr = S_OK; LVITEM lvi = {0}; IOERule * pIRule = NULL; BOOL fEnabled = FALSE; PROPVARIANT propvar;
// Grab the list view item
lvi.mask = LVIF_PARAM | LVIF_STATE; lvi.stateMask = LVIS_STATEIMAGEMASK; lvi.iItem = iSelected; if (FALSE == ListView_GetItem(m_hwndList, &lvi)) { goto exit; } pIRule = ((RULEINFO *) (lvi.lParam))->pIRule;
// Let's make sure we can enable this rule
hr = m_pDescriptUI->HrVerifyRule(); if (S_OK != hr) { // Put up a message saying something is busted
AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsRulesErrorEnable), NULL, MB_OK | MB_ICONINFORMATION); goto exit; }
// Get the new enabled value
fEnabled = (lvi.state != INDEXTOSTATEIMAGEMASK(iiconStateChecked+1));
// Set the UI to the opposite enabled state
ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_STATE; lvi.iItem = iSelected; lvi.state = fEnabled ? INDEXTOSTATEIMAGEMASK(iiconStateChecked+1) : INDEXTOSTATEIMAGEMASK(iiconStateUnchecked+1); lvi.stateMask = LVIS_STATEIMAGEMASK; ListView_SetItem(m_hwndList, &lvi); // Set the enabled property
ZeroMemory(&propvar, sizeof(propvar)); propvar.vt = VT_BOOL; propvar.boolVal = !fEnabled; hr = pIRule->SetProp(RULE_PROP_DISABLED, 0, &propvar); if (FAILED(hr)) { goto exit; }
// Tell the description field about it
m_pDescriptUI->HrSetEnabled(fEnabled); // Redraw the string the new rule
m_pDescriptUI->ShowDescriptionString(); // Mark the rule list as dirty
m_dwState |= STATE_DIRTY; exit: return; }
///////////////////////////////////////////////////////////////////////////////
//
// _LoadRule
//
// This loads the selected rule into the description field.
// If there isn't a selected rule, then the description field is cleared.
//
// iSelected - the item that was selected,
// -1 means that nothing was selected
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
void COEMailRulesPageUI::_LoadRule(INT iSelected) { LVITEM lvi = {0}; IOERule * pIRule = NULL;
Assert(NULL != m_hwndList); Assert(NULL != m_pDescriptUI);
// Grab the rule from the list view
if (-1 != iSelected) { lvi.iItem = iSelected; lvi.mask = LVIF_PARAM; if (FALSE != ListView_GetItem(m_hwndList, &lvi)) { pIRule = ((RULEINFO *) (lvi.lParam))->pIRule; } }
// Have the description field load this rule
m_pDescriptUI->HrSetRule(m_typeRule, pIRule);
// Display the new rule
m_pDescriptUI->ShowDescriptionString();
return; }
///////////////////////////////////////////////////////////////////////////////
//
// _FSaveRule
//
// This checks to see if the rule has been changed in the description
// area and if it has, then it warns the user and changes the text
//
// iSelected - index of the item in the listview to work on
//
// Returns: TRUE, if the rule either didn't change or did change without problems
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::_FSaveRule(int iSelected) { BOOL fRet = FALSE; HRESULT hr = S_OK; LVITEM lvi = {0}; IOERule * pIRule = NULL; PROPVARIANT propvar = {0}; CRIT_ITEM * pCritItem = NULL; ULONG cCritItem = 0; ACT_ITEM * pActItem = NULL; ULONG cActItem = 0;
// If the rule didn't change, then we're done
hr = m_pDescriptUI->HrIsDirty(); if (S_OK != hr) { fRet = (S_FALSE == hr); goto exit; } // Grab the list view item
lvi.mask = LVIF_PARAM; lvi.iItem = iSelected; if (FALSE == ListView_GetItem(m_hwndList, &lvi)) { fRet = FALSE; goto exit; } pIRule = ((RULEINFO *) (lvi.lParam))->pIRule;
// Get the criteria from the rule
hr = m_pDescriptUI->HrGetCriteria(&pCritItem, &cCritItem); if (FAILED(hr)) { fRet = FALSE; goto exit; } // Get the actions for the rule
hr = m_pDescriptUI->HrGetActions(&pActItem, &cActItem); if (FAILED(hr)) { fRet = FALSE; goto exit; } // Set the criteria from the rule
PropVariantClear(&propvar); propvar.vt = VT_BLOB; propvar.blob.cbSize = cCritItem * sizeof(CRIT_ITEM); propvar.blob.pBlobData = (BYTE *) pCritItem; hr = pIRule->SetProp(RULE_PROP_CRITERIA, 0, &propvar); ZeroMemory(&propvar, sizeof(propvar)); if (FAILED(hr)) { fRet = FALSE; goto exit; }
// Set the actions for the rule
PropVariantClear(&propvar); propvar.vt = VT_BLOB; propvar.blob.cbSize = cActItem * sizeof(ACT_ITEM); propvar.blob.pBlobData = (BYTE *) pActItem; hr = pIRule->SetProp(RULE_PROP_ACTIONS, 0, &propvar); ZeroMemory(&propvar, sizeof(propvar)); if (FAILED(hr)) { fRet = FALSE; goto exit; } // Mark the rule list as dirty
m_dwState |= STATE_DIRTY; // Make sure we clear out the fact that we saved the rule
m_pDescriptUI->HrClearDirty(); // Set the proper return value
fRet = TRUE;
exit: RuleUtil_HrFreeCriteriaItem(pCritItem, cCritItem); SafeMemFree(pCritItem); RuleUtil_HrFreeActionsItem(pActItem, cActItem); SafeMemFree(pActItem); return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// _NewRule
//
// This brings up a fresh rules editor
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
void COEMailRulesPageUI::_NewRule(VOID) { HRESULT hr = S_OK; IOERule * pIRule = NULL; TCHAR szRes[CCHMAX_STRINGRES + 5]; ULONG cchRes = 0; ULONG ulIndex = 0; TCHAR szName[CCHMAX_STRINGRES + 5]; LVFINDINFO lvfinfo = {0}; PROPVARIANT propvar = {0}; CEditRuleUI * pEditRuleUI = NULL; LONG cRules = 0; UINT uiStrId = 0; // Create a new rule object
if (FAILED(HrCreateRule(&pIRule))) { goto exit; }
// Figure out the string Id
if (RULE_TYPE_NEWS == m_typeRule) { uiStrId = idsRuleNewsDefaultName; } else { uiStrId = idsRuleMailDefaultName; } // Figure out the name of the new rule ...
cchRes = LoadString(g_hLocRes, uiStrId, szRes, ARRAYSIZE(szRes)); if (0 == cchRes) { goto exit; }
ulIndex = 1; wnsprintf(szName, ARRAYSIZE(szName), szRes, ulIndex);
lvfinfo.flags = LVFI_STRING; lvfinfo.psz = szName; while (-1 != ListView_FindItem(m_hwndList, -1, &lvfinfo)) { ulIndex++; wnsprintf(szName, ARRAYSIZE(szName), szRes, ulIndex); }
propvar.vt = VT_LPSTR; propvar.pszVal = szName;
hr = pIRule->SetProp(RULE_PROP_NAME, 0, &propvar); if (FAILED(hr)) { goto exit; }
// Create a rules editor object
pEditRuleUI = new CEditRuleUI; if (NULL == pEditRuleUI) { goto exit; }
// Initialize the editor object
if (FAILED(pEditRuleUI->HrInit(m_hwndDlg, ERF_NEWRULE, m_typeRule, pIRule, NULL))) { goto exit; }
// Bring up the rules editor UI
hr = pEditRuleUI->HrShow(); if (FAILED(hr)) { goto exit; }
if (S_OK == hr) { // Mark the rule list as dirty
m_dwState |= STATE_DIRTY; // Add the rule to the manager UI
cRules = ListView_GetItemCount(m_hwndList); _FAddRuleToList(cRules, RULEID_INVALID, pIRule);
// Make sure the new item is selected
ListView_SetItemState(m_hwndList, cRules, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
// Make sure the new item is visible
ListView_EnsureVisible(m_hwndList, cRules, FALSE); } exit: SafeRelease(pIRule); if (NULL != pEditRuleUI) { delete pEditRuleUI; } return; }
///////////////////////////////////////////////////////////////////////////////
//
// _EditRule
//
// This brings up the edit UI for the selected rule from the mail rules list
//
// iSelected - index of the item in the listview to work on
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
VOID COEMailRulesPageUI::_EditRule(int iSelected) { HRESULT hr = S_OK; LVITEM lvitem = {0}; IOERule * pIRule = NULL; CEditRuleUI * pEditRuleUI = NULL; PROPVARIANT propvar = {0}; BOOL fNotValid = FALSE; BOOL fDisabled = FALSE;
Assert(NULL != m_hwndList); // Make sure we don't loose any changes
_FSaveRule(iSelected);
// Grab the rule from the list view
lvitem.iItem = iSelected; lvitem.mask = LVIF_PARAM; if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { goto exit; }
pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule; if (NULL == pIRule) { goto exit; }
// Create the rules editor
pEditRuleUI = new CEditRuleUI; if (NULL == pEditRuleUI) { goto exit; }
// Initialize the editor object
if (FAILED(pEditRuleUI->HrInit(m_hwndDlg, 0, m_typeRule, pIRule, NULL))) { goto exit; }
// Bring up the rules editor UI
hr = pEditRuleUI->HrShow(); if (FAILED(hr)) { goto exit; }
// If the rule changed, make sure we reload the description field
if (S_OK == hr) { // Mark the rule list as dirty
m_dwState |= STATE_DIRTY;
ZeroMemory(&lvitem, sizeof(lvitem)); lvitem.mask = LVIF_STATE; lvitem.stateMask = LVIS_STATEIMAGEMASK; lvitem.iItem = iSelected; // Is it disabled?
hr = pIRule->GetProp(RULE_PROP_DISABLED , 0, &propvar); if (FAILED(hr)) { goto exit; }
fDisabled = !!propvar.boolVal; // Need to check if the rule is valid
hr = pIRule->Validate(0); if (FAILED(hr)) { goto exit; }
fNotValid = (hr == S_FALSE);
// Grab the rule name
PropVariantClear(&propvar); hr = pIRule->GetProp(RULE_PROP_NAME, 0, &propvar); if (FAILED(hr)) { goto exit; }
if ((VT_LPSTR == propvar.vt) && (NULL != propvar.pszVal) && ('\0' != propvar.pszVal[0])) { lvitem.mask |= LVIF_TEXT; lvitem.pszText = propvar.pszVal; lvitem.cchTextMax = lstrlen(propvar.pszVal) + 1; }
// Grab the rule state
// Need to change the state to mark the rule as invalid
if (FALSE != fNotValid) { lvitem.state = INDEXTOSTATEIMAGEMASK(iiconStateInvalid + 1); } else { lvitem.state = fDisabled ? INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1); } if (-1 == ListView_SetItem(m_hwndList, &lvitem)) { goto exit; } _EnableButtons(iSelected); } exit: PropVariantClear(&propvar); if (NULL != pEditRuleUI) { delete pEditRuleUI; } return; }
///////////////////////////////////////////////////////////////////////////////
//
// _MoveRule
//
// This moves the selected rule in the desired direction
//
// iSelected - index of the item in the listview to work on
// dir - the direction to move the item
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
void COEMailRulesPageUI::_MoveRule(INT iSelected, MOVE_DIR dir) { LVITEM lvitem = {0}; TCHAR szName[CCHMAX_STRINGRES]; IOERule * pIRule = NULL; int nIndexNew = 0; Assert(NULL != m_hwndList);
// Grab the rule from the list view
szName[0] = '\0'; lvitem.iItem = iSelected; lvitem.mask = LVIF_STATE | LVIF_PARAM | LVIF_TEXT; lvitem.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK; lvitem.pszText = szName; lvitem.cchTextMax = ARRAYSIZE(szName); if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { goto exit; }
pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule; // Update the item in the list view
// Get the info for the new index
nIndexNew = iSelected; nIndexNew += (MOVE_RULE_UP == dir) ? -1 : 2;
// Insert the new index
lvitem.iItem = nIndexNew; if (-1 == ListView_InsertItem(m_hwndList, &lvitem)) { goto exit; }
// Ensure the new item is visible
ListView_EnsureVisible(m_hwndList, nIndexNew, FALSE); ListView_RedrawItems(m_hwndList, nIndexNew, nIndexNew);
// If we moved up, then the old item is now one lower than before
if (MOVE_RULE_UP == dir) { iSelected++; }
// Remove the old item
if (FALSE == ListView_DeleteItem(m_hwndList, iSelected)) { goto exit; }
// Mark the rule list as dirty
m_dwState |= STATE_DIRTY; exit: return; }
///////////////////////////////////////////////////////////////////////////////
//
// _RemoveRule
//
// This removes the selected rule from the mail rules list
//
// iSelected - index of the item in the listview to work on
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
VOID COEMailRulesPageUI::_RemoveRule(int iSelected) { LVITEM lvitem = {0}; RULEINFO * pinfoRule = NULL; PROPVARIANT propvar = {0}; int cRules = 0; TCHAR szRes[CCHMAX_STRINGRES]; UINT cchRes = 0; LPTSTR pszMessage = NULL;
Assert(NULL != m_hwndList);
// Grab the rule from the list view
lvitem.iItem = iSelected; lvitem.mask = LVIF_PARAM; if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { goto exit; }
pinfoRule = (RULEINFO *) (lvitem.lParam); if ((NULL == pinfoRule) || (NULL == pinfoRule->pIRule)) { goto exit; } // Warn the user to make sure they know we are going to remove the rule
if (FAILED(pinfoRule->pIRule->GetProp(RULE_PROP_NAME, 0, &propvar))) { goto exit; }
// Get the string template to display
cchRes = LoadString(g_hLocRes, idsRulesWarnDelete, szRes, ARRAYSIZE(szRes)); if (0 == cchRes) { goto exit; }
// Allocate space to hold the final display string
DWORD cchSize = (cchRes + lstrlen(propvar.pszVal) + 1); if (FAILED(HrAlloc((void ** ) &pszMessage, cchSize))) { goto exit; }
// Build up the string and display it
wnsprintf(pszMessage, cchSize, szRes, propvar.pszVal); if (IDNO == AthMessageBox(m_hwndDlg, MAKEINTRESOURCE(idsAthenaMail), pszMessage, NULL, MB_YESNO | MB_ICONINFORMATION)) { goto exit; } // Remove the item from the list
ListView_DeleteItem(m_hwndList, iSelected);
// Let's make sure we have a selection in the list
cRules = ListView_GetItemCount(m_hwndList); if (cRules > 0) { // Did we delete the last item in the list
if (iSelected >= cRules) { // Move the selection to the new last item in the list
iSelected = cRules - 1; }
// Set the new selection
ListView_SetItemState(m_hwndList, iSelected, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
// Let's make sure we can see this new item
ListView_EnsureVisible(m_hwndList, iSelected, FALSE); } else { // Make sure we clear out all of the buttons
_EnableButtons(-1); }
// Release the rule
SafeRelease(pinfoRule->pIRule);
// Free up the memory
delete pinfoRule; // SafeMemFree(pinfoRule);
// Mark the rule list as dirty
m_dwState |= STATE_DIRTY; exit: PropVariantClear(&propvar); SafeMemFree(pszMessage); return; }
///////////////////////////////////////////////////////////////////////////////
//
// CopyRule
//
// This copies the selected rule from the rules manager
//
// iSelected - index of the item in the listview to work on
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
VOID COEMailRulesPageUI::_CopyRule(INT iSelected) { LVITEM lvitem = {0}; IOERule * pIRule = NULL; HRESULT hr = S_OK; IOERule * pIRuleNew = NULL; PROPVARIANT propvar = {0}; UINT cRules = 0; TCHAR szRes[CCHMAX_STRINGRES]; UINT cchRes = 0; LPTSTR pszName = NULL;
Assert(NULL != m_hwndList); // Make sure we don't loose any changes
_FSaveRule(iSelected); // Grab the rule from the list view
lvitem.iItem = iSelected; lvitem.mask = LVIF_PARAM; if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { goto exit; }
pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule; if (NULL == pIRule) { goto exit; }
// Create a new rule object
hr = pIRule->Clone(&pIRuleNew); if (FAILED(hr)) { goto exit; } // Let's set the name
// Get the name from the source rule
hr = pIRule->GetProp(RULE_PROP_NAME, 0, &propvar); if (FAILED(hr)) { goto exit; }
// Get the string template to display
cchRes = LoadString(g_hLocRes, idsRulesCopyName, szRes, ARRAYSIZE(szRes)); if (0 == cchRes) { goto exit; }
// Allocate space to hold the final display string
DWORD cchSize = (cchRes + lstrlen(propvar.pszVal) + 1); if (FAILED(HrAlloc((void ** ) &pszName, cchSize))) { goto exit; }
// Build up the string and set it
wnsprintf(pszName, cchSize, szRes, propvar.pszVal);
PropVariantClear(&propvar); propvar.vt = VT_LPSTR; propvar.pszVal = pszName; pszName = NULL; // Set the name into the new rule
Assert(VT_LPSTR == propvar.vt); Assert(NULL != propvar.pszVal); hr = pIRuleNew->SetProp(RULE_PROP_NAME, 0, &propvar); if (FAILED(hr)) { goto exit; } // Clear the version of the new rule
PropVariantClear(&propvar); propvar.vt = VT_UI4; propvar.ulVal = 0; hr = pIRuleNew->SetProp(RULE_PROP_VERSION, 0, &propvar); if (FAILED(hr)) { goto exit; } // Add the rule to the rules list right below
// the original rule
iSelected++; _FAddRuleToList(iSelected, RULEID_INVALID, pIRuleNew);
// Make sure the new item is selected
ListView_SetItemState(m_hwndList, iSelected, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
// Make sure the new item is visible
ListView_EnsureVisible(m_hwndList, iSelected, FALSE); // Mark the rule list as dirty
m_dwState |= STATE_DIRTY; exit: SafeMemFree(pszName); SafeRelease(pIRuleNew); PropVariantClear(&propvar); return; }
///////////////////////////////////////////////////////////////////////////////
//
// FOnApplyTo
//
// This applies the rules into a folder
//
// Returns: NONE
//
///////////////////////////////////////////////////////////////////////////////
VOID COEMailRulesPageUI::_OnApplyTo(INT iSelected) { COEApplyRulesUI * pApplyRulesUI = NULL; RULENODE * prnodeList = NULL; RULENODE * prnodeWalk = NULL; LVITEM lvitem = {0}; IOERule * pIRule = NULL; HRESULT hr = S_OK;
// Create the rules UI object
pApplyRulesUI = new COEApplyRulesUI; if (NULL == pApplyRulesUI) { goto exit; }
// Get the rules from the page
if (FALSE == SendMessage(m_hwndOwner, WM_OE_GET_RULES, (WPARAM) m_typeRule, (LPARAM) &prnodeList)) { goto exit; }
if (NULL == prnodeList) { AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthenaMail), (RULE_TYPE_NEWS == m_typeRule) ? MAKEINTRESOURCEW(idsErrorApplyRulesNews) : MAKEINTRESOURCEW(idsErrorApplyRulesMail), NULL, MB_OK | MB_ICONERROR); goto exit; } // Get the rule associated with the item
if (-1 != iSelected) { lvitem.iItem = iSelected; lvitem.mask = LVIF_PARAM; if (FALSE != ListView_GetItem(m_hwndList, &lvitem)) { pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule; if (NULL != pIRule) { // Verify that it is valid
hr = pIRule->Validate(0); if ((FAILED(hr)) || (S_FALSE == hr)) { pIRule = NULL; } } } } if (FAILED(pApplyRulesUI->HrInit(m_hwndDlg, 0, m_typeRule, prnodeList, pIRule))) { goto exit; } prnodeList = NULL; if (FAILED(pApplyRulesUI->HrShow())) { goto exit; } exit: while (NULL != prnodeList) { prnodeWalk = prnodeList; if (NULL != prnodeWalk->pIRule) { prnodeWalk->pIRule->Release(); } prnodeList = prnodeList->pNext; MemFree(prnodeWalk); } if (NULL != pApplyRulesUI) { delete pApplyRulesUI; } return; }
///////////////////////////////////////////////////////////////////////////////
//
// _FOnLabelEdit
//
// This brings up the edit UI for the selected rule from the mail rules list
//
// fBegin - is this for the LVN_BEGINLABELEDIT notification
// pdi - the display info for the message
//
// Returns: TRUE, if the message was handled
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::_FOnLabelEdit(BOOL fBegin, NMLVDISPINFO * pdi) { BOOL fRet = FALSE; HWND hwndEdit; ULONG cchName = 0; IOERule * pIRule = NULL; LVITEM lvitem; PROPVARIANT propvar;
Assert(NULL != m_hwndList);
if (NULL == pdi) { fRet = FALSE; goto exit; }
Assert(m_hwndList == pdi->hdr.hwndFrom); if (FALSE != fBegin) { // Get the edit control
hwndEdit = ListView_GetEditControl(m_hwndList);
if (NULL == hwndEdit) { fRet = FALSE; goto exit; } // Limit the amount of text for the name
SendMessage(hwndEdit, EM_LIMITTEXT, c_cchNameMax - 1, 0);
// Tell the dialog it's aok to proceed
SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE); } else { // Did something change?
if ((-1 != pdi->item.iItem) && (NULL != pdi->item.pszText)) { cchName = lstrlen(pdi->item.pszText); // Check to see if the rule name is valid
if ((0 == cchName) || (0 == UlStripWhitespace(pdi->item.pszText, TRUE, TRUE, &cchName))) { // Put up a message saying something is busted
AthMessageBoxW(m_hwndDlg, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsRulesErrorNoName), NULL, MB_OK | MB_ICONINFORMATION); SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE); fRet = TRUE; goto exit; } // Get the rule for the item
ZeroMemory(&lvitem, sizeof(lvitem)); lvitem.iItem = pdi->item.iItem; lvitem.mask = LVIF_PARAM; if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE); fRet = TRUE; goto exit; }
pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule; if (NULL == pIRule) { SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, FALSE); fRet = TRUE; goto exit; } // Set the new name into the rule
ZeroMemory(&propvar, sizeof(propvar)); propvar.vt = VT_LPSTR; propvar.pszVal = pdi->item.pszText; SideAssert(S_OK == pIRule->SetProp(RULE_PROP_NAME, 0, &propvar));
// Mark the rule list as dirty
m_dwState |= STATE_DIRTY; SetDlgMsgResult(m_hwndDlg, WM_NOTIFY, TRUE); } }
fRet = TRUE; exit: return fRet; }
///////////////////////////////////////////////////////////////////////////////
//
// _FOnRuleDescValid
//
// This brings up the edit UI for the selected rule from the mail rules list
//
// Returns: TRUE, if the message was handled
// FALSE, otherwise
//
///////////////////////////////////////////////////////////////////////////////
BOOL COEMailRulesPageUI::_FOnRuleDescValid(VOID) { BOOL fRet = FALSE; INT iSelected = 0; LVITEM lvitem; IOERule * pIRule = NULL; HRESULT hr = S_OK; PROPVARIANT propvar;
Assert(NULL != m_hwndList); // Get the selected item
iSelected = ListView_GetNextItem(m_hwndList, -1, LVNI_SELECTED); if (-1 == iSelected) { fRet = FALSE; goto exit; } // Get the current state of the rule
ZeroMemory(&lvitem, sizeof(lvitem)); lvitem.mask = LVIF_PARAM | LVIF_STATE; lvitem.stateMask = LVIS_STATEIMAGEMASK; lvitem.iItem = iSelected; if (FALSE == ListView_GetItem(m_hwndList, &lvitem)) { fRet = FALSE; goto exit; } pIRule = ((RULEINFO *) (lvitem.lParam))->pIRule; // If the rule already valid, then bail
if (lvitem.state != INDEXTOSTATEIMAGEMASK(iiconStateInvalid + 1)) { fRet = FALSE; goto exit; } // If we are still, invalid then bail
hr = m_pDescriptUI->HrVerifyRule(); if (S_OK != hr) { fRet = FALSE; goto exit; }
// Figure out the new enabled value
hr = pIRule->GetProp(RULE_PROP_DISABLED, 0, &propvar); if (FAILED(hr)) { fRet = FALSE; goto exit; }
// Set the UI to the proper enabled state
ZeroMemory(&lvitem, sizeof(lvitem)); lvitem.mask = LVIF_STATE; lvitem.iItem = iSelected; lvitem.state = (!!propvar.boolVal) ? INDEXTOSTATEIMAGEMASK(iiconStateUnchecked + 1) : INDEXTOSTATEIMAGEMASK(iiconStateChecked + 1); lvitem.stateMask = LVIS_STATEIMAGEMASK; ListView_SetItem(m_hwndList, &lvitem);
fRet = TRUE; exit: return fRet; }
|