Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2612 lines
75 KiB

  1. #include "pch.hxx"
  2. #include <iert.h>
  3. #include <store.h>
  4. #include <storecb.h>
  5. #include "resource.h"
  6. #include "ourguid.h"
  7. #include "thormsgs.h"
  8. #include "goptions.h"
  9. #include "strconst.h"
  10. #include <inetcfg.h>
  11. #include <fonts.h>
  12. #include <columns.h>
  13. #include <imagelst.h>
  14. #include <instance.h>
  15. #include <spoolui.h>
  16. #include <options.h>
  17. #include <acctutil.h>
  18. #include "shlwapip.h"
  19. #include <menuutil.h>
  20. #include "storutil.h"
  21. #include <outbar.h>
  22. #include <subscr.h>
  23. #include "newsutil.h"
  24. #include "acctview.h"
  25. #include <newfldr.h>
  26. #include <mailutil.h>
  27. #include "menures.h"
  28. #include "demand.h"
  29. ASSERTDATA
  30. #define SUBSCRIBE_BORDER 7
  31. #define CALLOCIDBUF 256
  32. #define IDC_SUBSCRIBE_LIST (ID_FIRST - 4)
  33. #define FOLDER_SYNCMASK (FOLDER_DOWNLOADHEADERS | FOLDER_DOWNLOADNEW | FOLDER_DOWNLOADALL)
  34. static const char c_szAcctViewWndClass[] = "Outlook Express AcctView";
  35. int __cdecl GroupCompare(const void *lParam1, const void *lParam2) ;
  36. void DrawSettingsButton(HWND hwnd, LPDRAWITEMSTRUCT pdi);
  37. #define C_RGBCOLORS 16
  38. extern const DWORD rgrgbColors16[C_RGBCOLORS];
  39. typedef struct tagACCTVIEWBTN
  40. {
  41. int idsText;
  42. int cmd;
  43. } ACCTVIEWBTN;
  44. static const ACCTVIEWBTN c_rgMailBtns[] =
  45. {
  46. { idsDeliverMailTT, ID_SEND_RECEIVE }
  47. };
  48. static const ACCTVIEWBTN c_rgImapBtns[] =
  49. {
  50. { idsSynchronizeNowBtn, ID_SYNC_THIS_NOW },
  51. { idsIMAPFoldersBtn, ID_IMAP_FOLDERS },
  52. { idsSettingsBtn, ID_POPUP_SYNCHRONIZE }
  53. };
  54. static const ACCTVIEWBTN c_rgNewsBtns[] =
  55. {
  56. { idsSynchronizeNowBtn, ID_SYNC_THIS_NOW },
  57. { idsNewsgroupsBtn, ID_NEWSGROUPS },
  58. { idsSettingsBtn, ID_POPUP_SYNCHRONIZE }
  59. };
  60. static const ACCTVIEWBTN c_rgHttpBtns[] =
  61. {
  62. { idsSynchronizeNowBtn, ID_SYNC_THIS_NOW },
  63. { idsSettingsBtn, ID_POPUP_SYNCHRONIZE }
  64. };
  65. CAccountView::CAccountView()
  66. {
  67. m_cRef = 1;
  68. // m_ftType
  69. m_pShellBrowser = NULL;
  70. m_fFirstActive = FALSE;
  71. m_pColumns = NULL;
  72. m_uActivation = SVUIA_DEACTIVATE;
  73. m_hwndOwner = NULL;
  74. m_hwnd = NULL;
  75. m_idFolder = FOLDERID_INVALID;
  76. m_fRegistered = FALSE;
  77. m_hwndList = NULL;
  78. m_pszMajor = NULL;
  79. m_pszMinor = NULL;
  80. m_cBtns = 0;
  81. m_cnode = 0;
  82. m_cnodeBuf = 0;
  83. m_rgnode = NULL;
  84. m_himlFolders = NULL;
  85. m_pEmptyList = NULL;
  86. m_pGroups = NULL;
  87. m_clrWatched = 0;
  88. }
  89. CAccountView::~CAccountView()
  90. {
  91. if (m_pGroups != NULL)
  92. {
  93. m_pGroups->Close();
  94. m_pGroups->Release();
  95. }
  96. if (m_rgnode != NULL)
  97. MemFree(m_rgnode);
  98. SafeRelease(m_pShellBrowser);
  99. SafeRelease(m_pColumns);
  100. if (m_pEmptyList != NULL)
  101. delete m_pEmptyList;
  102. if (m_himlFolders != NULL)
  103. ImageList_Destroy(m_himlFolders);
  104. if (m_pszMajor != NULL)
  105. MemFree(m_pszMajor);
  106. if (m_pszMinor != NULL)
  107. MemFree(m_pszMinor);
  108. }
  109. HRESULT CAccountView::HrInit(FOLDERID idFolder)
  110. {
  111. WNDCLASS wc;
  112. if (!GetClassInfo(g_hInst, c_szAcctViewWndClass, &wc))
  113. {
  114. wc.style = 0;
  115. wc.lpfnWndProc = CAccountView::AcctViewWndProc;
  116. wc.cbClsExtra = 0;
  117. wc.cbWndExtra = 0;
  118. wc.hInstance = g_hInst;
  119. wc.hIcon = NULL;
  120. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  121. wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  122. wc.lpszMenuName = NULL;
  123. wc.lpszClassName = c_szAcctViewWndClass;
  124. if (RegisterClass(&wc) == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
  125. return E_FAIL;
  126. }
  127. m_idFolder = idFolder;
  128. m_ftType = GetFolderType(idFolder);
  129. m_dwDownloadDef = (m_ftType == FOLDER_NEWS) ? FOLDER_DOWNLOADNEW : FOLDER_DOWNLOADALL;
  130. // Set the image lists for the listview
  131. Assert(m_himlFolders == NULL);
  132. m_himlFolders = InitImageList(16, 16, MAKEINTRESOURCE(idbFolders), cFolderIcon, RGB(255, 0, 255));
  133. Assert(m_himlFolders);
  134. m_pEmptyList = new CEmptyList;
  135. if (m_pEmptyList == NULL)
  136. return(E_OUTOFMEMORY);
  137. return S_OK;
  138. }
  139. /////////////////////////////////////////////////////////////////////////
  140. //
  141. // OLE Interfaces
  142. //
  143. ////////////////////////////////////////////////////////////////////////
  144. //
  145. // IUnknown
  146. //
  147. ////////////////////////////////////////////////////////////////////////
  148. HRESULT STDMETHODCALLTYPE CAccountView::QueryInterface(REFIID riid, void **ppvObj)
  149. {
  150. if (IsEqualIID(riid, IID_IUnknown))
  151. *ppvObj = (void*) (IUnknown *)(IViewWindow *)this;
  152. else if (IsEqualIID(riid, IID_IViewWindow))
  153. *ppvObj = (void*) (IViewWindow *) this;
  154. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  155. *ppvObj = (void*) (IOleCommandTarget *) this;
  156. else
  157. {
  158. *ppvObj = NULL;
  159. return E_NOINTERFACE;
  160. }
  161. AddRef();
  162. return S_OK;
  163. }
  164. ULONG STDMETHODCALLTYPE CAccountView::AddRef()
  165. {
  166. DOUT(TEXT("CAccountView::AddRef() - m_cRef = %d"), m_cRef + 1);
  167. return ++m_cRef;
  168. }
  169. ULONG STDMETHODCALLTYPE CAccountView::Release()
  170. {
  171. DOUT(TEXT("CAccountView::Release() - m_cRef = %d"), m_cRef - 1);
  172. if (--m_cRef == 0)
  173. {
  174. delete this;
  175. return 0;
  176. }
  177. return m_cRef;
  178. }
  179. ////////////////////////////////////////////////////////////////////////
  180. //
  181. // IOleWindow
  182. //
  183. ////////////////////////////////////////////////////////////////////////
  184. HRESULT STDMETHODCALLTYPE CAccountView::GetWindow(HWND * lphwnd)
  185. {
  186. *lphwnd = m_hwnd;
  187. return (m_hwnd ? S_OK : E_FAIL);
  188. }
  189. HRESULT STDMETHODCALLTYPE CAccountView::ContextSensitiveHelp(BOOL fEnterMode)
  190. {
  191. return E_NOTIMPL;
  192. }
  193. ////////////////////////////////////////////////////////////////////////
  194. //
  195. // IAthenaView
  196. //
  197. ////////////////////////////////////////////////////////////////////////
  198. HRESULT STDMETHODCALLTYPE CAccountView::TranslateAccelerator(LPMSG lpmsg)
  199. {
  200. return(S_FALSE);
  201. }
  202. HRESULT STDMETHODCALLTYPE CAccountView::UIActivate(UINT uActivation)
  203. {
  204. if (uActivation != SVUIA_DEACTIVATE)
  205. _OnActivate(uActivation);
  206. else
  207. _OnDeactivate();
  208. return S_OK;
  209. }
  210. HRESULT STDMETHODCALLTYPE CAccountView::CreateViewWindow(IViewWindow *lpPrevView, IAthenaBrowser *psb,
  211. RECT *prcView, HWND *phWnd)
  212. {
  213. FOLDERINFO info;
  214. m_pShellBrowser = psb;
  215. Assert(m_pShellBrowser);
  216. m_pShellBrowser->AddRef();
  217. m_pShellBrowser->GetWindow(&m_hwndOwner);
  218. Assert(IsWindow(m_hwndOwner));
  219. m_pColumns = new CColumns;
  220. if (m_pColumns == NULL)
  221. return(E_OUTOFMEMORY);
  222. m_hwnd = CreateWindowEx(WS_EX_CONTROLPARENT|WS_EX_CLIENTEDGE,
  223. c_szAcctViewWndClass,
  224. NULL,
  225. WS_VISIBLE|WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
  226. prcView->left,
  227. prcView->top,
  228. prcView->right - prcView->left,
  229. prcView->bottom - prcView->top,
  230. m_hwndOwner,
  231. NULL,
  232. g_hInst,
  233. (LPVOID)this);
  234. if (!m_hwnd)
  235. return E_FAIL;
  236. *phWnd = m_hwnd;
  237. return(S_OK);
  238. }
  239. HRESULT STDMETHODCALLTYPE CAccountView::DestroyViewWindow()
  240. {
  241. HRESULT hr;
  242. HWND hwndDest;
  243. if (m_fRegistered)
  244. g_pStore->UnregisterNotify((IDatabaseNotify *)this);
  245. if (m_hwnd)
  246. {
  247. hwndDest = m_hwnd;
  248. m_hwnd = NULL;
  249. DestroyWindow(hwndDest);
  250. }
  251. return S_OK;
  252. }
  253. HRESULT STDMETHODCALLTYPE CAccountView::SaveViewState()
  254. {
  255. Assert(m_pColumns != NULL);
  256. m_pColumns->Save(NULL, NULL);
  257. OptionUnadvise(m_hwnd);
  258. return S_OK;
  259. }
  260. //
  261. // FUNCTION: CAccountView::OnInitMenuPopup
  262. //
  263. // PURPOSE: Called when the user is about to display a menu. We use this
  264. // to update the enabled or disabled status of many of the
  265. // commands on each menu.
  266. //
  267. // PARAMETERS:
  268. // hmenu - Handle of the main menu.
  269. // hmenuPopup - Handle of the popup menu being displayed.
  270. // uID - Specifies the id of the menu item that
  271. // invoked the popup.
  272. //
  273. // RETURN VALUE:
  274. // Returns S_OK if we process the message.
  275. //
  276. //
  277. HRESULT CAccountView::OnPopupMenu(HMENU hmenu, HMENU hmenuPopup, UINT uID)
  278. {
  279. return(S_OK);
  280. }
  281. DWORD CAccountView::_GetDownloadCmdStatus(int iSel, FLDRFLAGS dwFlags)
  282. {
  283. DWORD cmdf;
  284. cmdf = OLECMDF_SUPPORTED;
  285. if (m_ftType != FOLDER_LOCAL)
  286. {
  287. if (iSel != -1)
  288. {
  289. if (_IsSelectedFolder(FOLDER_SUBSCRIBED, TRUE, FALSE))
  290. {
  291. cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  292. if (_IsSelectedFolder(dwFlags, TRUE, TRUE))
  293. cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED;
  294. }
  295. }
  296. }
  297. return(cmdf);
  298. }
  299. HRESULT CAccountView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
  300. {
  301. ULONG i;
  302. BOOL fTree, fSpecial;
  303. FOLDERID idFolder;
  304. FOLDERINFO info;
  305. HRESULT hr;
  306. int iSel, cSel, cItems, iSelT;
  307. OLECMD *pcmd;
  308. Assert(prgCmds != NULL);
  309. cSel = ListView_GetSelectedCount(m_hwndList);
  310. cItems = ListView_GetItemCount(m_hwndList);
  311. iSel = ListView_GetNextItem(m_hwndList, -1, LVNI_ALL | LVNI_SELECTED | LVNI_FOCUSED);
  312. if (iSel != -1 && (DWORD)iSel >= m_cnode)
  313. iSel = -1;
  314. fTree = !(S_OK == m_pShellBrowser->HasFocus(ITB_OEVIEW));
  315. for (i = 0, pcmd = prgCmds; i < cCmds; i++, pcmd++)
  316. {
  317. if (pcmd->cmdf == 0)
  318. {
  319. switch (pcmd->cmdID)
  320. {
  321. case ID_POPUP_SYNCHRONIZE:
  322. pcmd->cmdf = OLECMDF_SUPPORTED;
  323. if (m_ftType != FOLDER_LOCAL && iSel != -1)
  324. {
  325. if (_IsSelectedFolder(FOLDER_SUBSCRIBED, TRUE, FALSE))
  326. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  327. }
  328. break;
  329. case ID_MARK_RETRIEVE_FLD_NEW_HDRS:
  330. pcmd->cmdf = _GetDownloadCmdStatus(iSel, FOLDER_DOWNLOADHEADERS);
  331. break;
  332. case ID_MARK_RETRIEVE_FLD_NEW_MSGS:
  333. pcmd->cmdf = _GetDownloadCmdStatus(iSel, FOLDER_DOWNLOADNEW);
  334. break;
  335. case ID_MARK_RETRIEVE_FLD_ALL_MSGS:
  336. pcmd->cmdf = _GetDownloadCmdStatus(iSel, FOLDER_DOWNLOADALL);
  337. break;
  338. case ID_UNMARK_RETRIEVE_FLD:
  339. pcmd->cmdf = OLECMDF_SUPPORTED;
  340. if (iSel != -1)
  341. {
  342. if (_IsSelectedFolder(FOLDER_SUBSCRIBED, TRUE, FALSE))
  343. {
  344. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  345. if (_IsSelectedFolder(FOLDER_SYNCMASK, FALSE, TRUE))
  346. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED | OLECMDF_NINCHED;
  347. }
  348. }
  349. break;
  350. case ID_SUBSCRIBE:
  351. case ID_UNSUBSCRIBE:
  352. pcmd->cmdf = OLECMDF_SUPPORTED;
  353. if ((m_ftType == FOLDER_IMAP || m_ftType == FOLDER_NEWS) && iSel != -1)
  354. {
  355. if (_IsSelectedFolder(FOLDER_SUBSCRIBED, pcmd->cmdID == ID_UNSUBSCRIBE, FALSE, TRUE))
  356. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  357. }
  358. break;
  359. case ID_SELECT_ALL:
  360. case ID_COLUMNS:
  361. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  362. break;
  363. case ID_CATCH_UP:
  364. if (m_ftType == FOLDER_NEWS && iSel != -1)
  365. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  366. else
  367. pcmd->cmdf = OLECMDF_SUPPORTED;
  368. break;
  369. case ID_OPEN_FOLDER:
  370. case ID_OPEN:
  371. case ID_GO_SELECTED:
  372. case ID_COMPACT:
  373. case ID_MARK_ALL_READ:
  374. if (iSel == -1)
  375. pcmd->cmdf = OLECMDF_SUPPORTED;
  376. else
  377. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  378. break;
  379. // TODO: support ID_PURGE_DELETED???
  380. // commands below are handled by the treeview if it has the focus
  381. // otherwise we'll handle them based on what is selected in us
  382. case ID_PROPERTIES:
  383. case ID_ADD_SHORTCUT:
  384. if (!fTree)
  385. {
  386. if (iSel != -1)
  387. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  388. else
  389. pcmd->cmdf = OLECMDF_SUPPORTED;
  390. }
  391. break;
  392. case ID_NEW_FOLDER:
  393. case ID_NEW_FOLDER2:
  394. if (!fTree)
  395. {
  396. pcmd->cmdf = OLECMDF_SUPPORTED;
  397. if (m_ftType != FOLDER_NEWS && iSel != -1)
  398. {
  399. hr = g_pStore->GetFolderInfo(_IdFromIndex(iSel), &info);
  400. if (SUCCEEDED(hr))
  401. {
  402. if (info.tySpecial != FOLDER_DELETED)
  403. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  404. g_pStore->FreeRecord(&info);
  405. }
  406. }
  407. }
  408. break;
  409. case ID_DELETE:
  410. case ID_DELETE_FOLDER:
  411. if (!fTree)
  412. {
  413. pcmd->cmdf = OLECMDF_SUPPORTED;
  414. if (iSel != -1 && m_ftType != FOLDER_NEWS)
  415. {
  416. iSelT = iSel;
  417. while (iSelT != -1)
  418. {
  419. hr = g_pStore->GetFolderInfo(_IdFromIndex(iSelT), &info);
  420. if (SUCCEEDED(hr))
  421. {
  422. fSpecial = (info.tySpecial != FOLDER_NOTSPECIAL);
  423. g_pStore->FreeRecord(&info);
  424. if (!fSpecial)
  425. {
  426. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  427. break;
  428. }
  429. }
  430. iSelT = ListView_GetNextItem(m_hwndList, iSelT, LVNI_SELECTED);
  431. }
  432. }
  433. }
  434. break;
  435. case ID_MOVE:
  436. case ID_RENAME:
  437. if (!fTree)
  438. {
  439. pcmd->cmdf = OLECMDF_SUPPORTED;
  440. if (m_ftType != FOLDER_NEWS && iSel != -1)
  441. {
  442. hr = g_pStore->GetFolderInfo(_IdFromIndex(iSel), &info);
  443. if (SUCCEEDED(hr))
  444. {
  445. if (info.tySpecial == FOLDER_NOTSPECIAL)
  446. pcmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
  447. g_pStore->FreeRecord(&info);
  448. }
  449. }
  450. }
  451. break;
  452. }
  453. }
  454. }
  455. return(S_OK);
  456. }
  457. HRESULT CAccountView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  458. {
  459. int iSel;
  460. BOOL fTree;
  461. HRESULT hr;
  462. FOLDERID id;
  463. iSel = ListView_GetNextItem(m_hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
  464. if (iSel != -1)
  465. {
  466. if (MenuUtil_HandleNewMessageIDs(nCmdID, m_hwndOwner, _IdFromIndex((DWORD)iSel), m_ftType != FOLDER_NEWS, FALSE, NULL))
  467. return(S_OK);
  468. }
  469. fTree = !(S_OK == m_pShellBrowser->HasFocus(ITB_OEVIEW));
  470. hr = OLECMDERR_E_NOTSUPPORTED;
  471. switch (nCmdID)
  472. {
  473. case ID_MARK_RETRIEVE_FLD_NEW_HDRS:
  474. case ID_MARK_RETRIEVE_FLD_NEW_MSGS:
  475. case ID_MARK_RETRIEVE_FLD_ALL_MSGS:
  476. case ID_UNMARK_RETRIEVE_FLD:
  477. _MarkForDownload(nCmdID);
  478. hr = S_OK;
  479. break;
  480. case ID_COLUMNS:
  481. m_pColumns->ColumnsDialog(m_hwndOwner);
  482. hr = S_OK;
  483. break;
  484. case ID_SUBSCRIBE:
  485. case ID_UNSUBSCRIBE:
  486. _Subscribe(nCmdID == ID_SUBSCRIBE);
  487. hr = S_OK;
  488. break;
  489. case ID_COMPACT:
  490. if (iSel != -1)
  491. CompactFolders(m_hwndOwner, RECURSE_INCLUDECURRENT, _IdFromIndex((DWORD)iSel));
  492. hr = S_OK;
  493. break;
  494. case ID_CATCH_UP:
  495. iSel = -1;
  496. while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
  497. MenuUtil_OnCatchUp(_IdFromIndex((DWORD)iSel));
  498. hr = S_OK;
  499. break;
  500. case ID_GO_SELECTED:
  501. case ID_OPEN:
  502. case ID_OPEN_FOLDER:
  503. if (iSel != -1)
  504. g_pInstance->BrowseToObject(SW_SHOWNORMAL, _IdFromIndex((DWORD)iSel));
  505. hr = S_OK;
  506. break;
  507. case ID_SELECT_ALL:
  508. ListView_SelectAll(m_hwndList);
  509. if (m_hwndList != GetFocus())
  510. SetFocus(m_hwndList);
  511. hr = S_OK;
  512. break;
  513. case ID_MARK_ALL_READ:
  514. _MarkAllRead();
  515. hr = S_OK;
  516. break;
  517. // commands below are handled by the treeview if it has the focus
  518. // otherwise we'll handle them based on what is selected in us
  519. case ID_ADD_SHORTCUT:
  520. if (!fTree)
  521. {
  522. if (iSel != -1)
  523. OutlookBar_AddShortcut(_IdFromIndex((DWORD)iSel));
  524. hr = S_OK;
  525. }
  526. break;
  527. case ID_PROPERTIES:
  528. if (!fTree)
  529. {
  530. if (iSel != -1)
  531. MenuUtil_OnProperties(m_hwndOwner, _IdFromIndex(iSel));
  532. hr = S_OK;
  533. }
  534. break;
  535. case ID_NEW_FOLDER:
  536. case ID_NEW_FOLDER2:
  537. if (!fTree)
  538. {
  539. if (iSel != -1)
  540. SelectFolderDialog(m_hwndOwner, SFD_NEWFOLDER, _IdFromIndex((DWORD)iSel), TREEVIEW_NONEWS | TREEVIEW_DIALOG | FD_DISABLEROOT | FD_FORCEINITSELFOLDER,
  541. NULL, NULL, NULL);
  542. hr = S_OK;
  543. }
  544. break;
  545. case ID_MOVE:
  546. if (!fTree)
  547. {
  548. if (iSel != -1)
  549. {
  550. // TODO: move all selected folders, not just the one with focus
  551. SelectFolderDialog(m_hwndOwner, SFD_MOVEFOLDER, _IdFromIndex((DWORD)iSel), TREEVIEW_NONEWS | TREEVIEW_DIALOG | FD_DISABLEROOT,
  552. MAKEINTRESOURCE(idsMove), MAKEINTRESOURCE(idsMoveCaption), NULL);
  553. }
  554. hr = S_OK;
  555. }
  556. break;
  557. case ID_RENAME:
  558. if (!fTree)
  559. {
  560. if (iSel != -1)
  561. RenameFolderDlg(m_hwndOwner, _IdFromIndex((DWORD)iSel));
  562. hr = S_OK;
  563. }
  564. break;
  565. case ID_DELETE:
  566. case ID_DELETE_NO_TRASH:
  567. case ID_DELETE_FOLDER:
  568. if (!fTree)
  569. {
  570. if (iSel != -1)
  571. _HandleDelete(nCmdID == ID_DELETE_NO_TRASH);
  572. hr = S_OK;
  573. }
  574. break;
  575. }
  576. return(hr);
  577. }
  578. void CAccountView::_HandleSettingsButton(HWND hwndBtn)
  579. {
  580. HRESULT hr;
  581. HMENU hMenu;
  582. HWND hwndBrowser;
  583. RECT rc;
  584. DWORD state;
  585. hMenu = LoadPopupMenu(IDR_SYNCHRONIZE_POPUP);
  586. if (hMenu != NULL)
  587. {
  588. // Enable / disable
  589. MenuUtil_EnablePopupMenu(hMenu, (IOleCommandTarget *)this);
  590. GetWindowRect(hwndBtn, &rc);
  591. m_pShellBrowser->GetWindow(&hwndBrowser);
  592. TrackPopupMenu(hMenu, TPM_NONOTIFY | TPM_LEFTALIGN | TPM_TOPALIGN,
  593. rc.left, rc.bottom, 0, hwndBrowser, NULL);
  594. DestroyMenu(hMenu);
  595. }
  596. }
  597. void CAccountView::_HandleDelete(BOOL fNoTrash)
  598. {
  599. FOLDERID *pid;
  600. int iSel, cSel, cid;
  601. cSel = ListView_GetSelectedCount(m_hwndList);
  602. if (cSel > 0)
  603. {
  604. if (MemAlloc((void **)&pid, cSel * sizeof(FOLDERID)))
  605. {
  606. cid = cSel;
  607. iSel = -1;
  608. while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
  609. {
  610. cid--;
  611. Assert(cid >= 0);
  612. pid[cid] = _IdFromIndex(iSel);
  613. }
  614. Assert(cid == 0);
  615. if (m_ftType == FOLDER_NEWS)
  616. {
  617. MenuUtil_OnSubscribeGroups(m_hwndOwner, pid, cSel, FALSE);
  618. }
  619. else
  620. {
  621. MenuUtil_DeleteFolders(m_hwndOwner, pid, cSel, fNoTrash);
  622. }
  623. MemFree(pid);
  624. }
  625. }
  626. }
  627. BOOL CAccountView::_IsSelectedFolder(FLDRFLAGS dwFlags, BOOL fCondition, BOOL fAll, BOOL fIgnoreSpecial)
  628. {
  629. BOOL fSpecial;
  630. HRESULT hr;
  631. FLDRFLAGS dw;
  632. FOLDERINFO info;
  633. DWORD iItem = -1;
  634. BOOL fHTTPFolder = FALSE;
  635. while (-1 != (iItem = ListView_GetNextItem(m_hwndList, iItem, LVNI_SELECTED)))
  636. {
  637. hr = g_pStore->GetFolderInfo(_IdFromIndex(iItem), &info);
  638. if (SUCCEEDED(hr))
  639. {
  640. dw = info.dwFlags;
  641. fHTTPFolder = (BOOL) (info.tyFolder & FOLDER_HTTPMAIL);
  642. fSpecial = fIgnoreSpecial && (info.tySpecial != FOLDER_NOTSPECIAL);
  643. g_pStore->FreeRecord(&info);
  644. if (fSpecial)
  645. continue;
  646. if (fAll)
  647. {
  648. // If all must match and this one doesn't, then we can quit now.
  649. if (!(fCondition == !!(dw & dwFlags)))
  650. return (FALSE);
  651. }
  652. else
  653. {
  654. // If only one needs to match and this one does, then we can
  655. // quit now.
  656. if (fCondition == !!(dw & dwFlags))
  657. {
  658. if(fHTTPFolder)
  659. {
  660. FOLDERINFO SvrFolderInfo = {0};
  661. IImnAccount *pAccount = NULL;
  662. CHAR szAccountId[CCHMAX_ACCOUNT_NAME];
  663. HRESULT hr = S_OK;
  664. DWORD dwShow = 0;
  665. // Get the server for this folder
  666. IF_FAILEXIT(hr = GetFolderServer(_IdFromIndex(iItem), &SvrFolderInfo));
  667. // Get the account ID for the server
  668. *szAccountId = 0;
  669. IF_FAILEXIT(hr = GetFolderAccountId(&SvrFolderInfo, szAccountId, ARRAYSIZE(szAccountId)));
  670. // Get the account interface
  671. IF_FAILEXIT(hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, szAccountId, &pAccount));
  672. IF_FAILEXIT(hr = pAccount->GetPropDw(AP_HTTPMAIL_DOMAIN_MSN, &dwShow));
  673. if(dwShow)
  674. {
  675. if(HideHotmail())
  676. return (FALSE);
  677. }
  678. }
  679. exit:
  680. return (TRUE);
  681. }
  682. }
  683. }
  684. }
  685. // If the user wanted all to match, and we get here all did match. If the
  686. // user wanted only one to match and we get here, then none matched and we
  687. // fail.
  688. return (fAll);
  689. }
  690. LRESULT CALLBACK CAccountView::AcctViewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  691. {
  692. LRESULT lRet;
  693. CAccountView *pThis;
  694. if (msg == WM_NCCREATE)
  695. {
  696. pThis = (CAccountView *)((LPCREATESTRUCT)lParam)->lpCreateParams;
  697. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pThis);
  698. }
  699. else
  700. pThis = (CAccountView *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  701. Assert(pThis);
  702. return pThis->_WndProc(hwnd, msg, wParam, lParam);
  703. }
  704. LRESULT CAccountView::_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  705. {
  706. HWND hwndFocus, hwndBrowser;
  707. BOOL fTip;
  708. RECT rc;
  709. switch (msg)
  710. {
  711. HANDLE_MSG(hwnd, WM_CREATE, _OnCreate);
  712. HANDLE_MSG(hwnd, WM_SIZE, _OnSize);
  713. HANDLE_MSG(hwnd, WM_NOTIFY, _OnNotify);
  714. HANDLE_MSG(hwnd, WM_SETFOCUS, _OnSetFocus);
  715. case WM_MENUSELECT:
  716. CStatusBar *pStatusBar;
  717. m_pShellBrowser->GetStatusBar(&pStatusBar);
  718. HandleMenuSelect(pStatusBar, wParam, lParam);
  719. pStatusBar->Release();
  720. return 0;
  721. case WM_COMMAND:
  722. _OnCommand(wParam, lParam);
  723. break;
  724. case WM_PAINT:
  725. return(_OnPaint(hwnd, (HDC)wParam));
  726. case WM_DRAWITEM:
  727. if (wParam == ID_POPUP_SYNCHRONIZE)
  728. {
  729. DrawSettingsButton(hwnd, (LPDRAWITEMSTRUCT)lParam);
  730. return(TRUE);
  731. }
  732. break;
  733. case WM_CONTEXTMENU:
  734. _OnContextMenu(hwnd, (HWND)wParam, (int)(short)LOWORD(lParam), (int)(short)HIWORD(lParam));
  735. return(0);
  736. case NVM_INITHEADERS:
  737. _PostCreate();
  738. return 0;
  739. case WM_ACTIVATE:
  740. _HandleItemStateChange();
  741. if (LOWORD(wParam) != WA_INACTIVE)
  742. {
  743. // DefWindowProc will set the focus to our view window, which
  744. // is not what we want. Instead, we will let the explorer set
  745. // the focus to our view window if we should get it, at which
  746. // point we will set it to the proper control.
  747. return 0;
  748. }
  749. break;
  750. case WM_SYSCOLORCHANGE:
  751. SendMessage(m_hwndList, msg, wParam, lParam);
  752. break;
  753. case WM_WININICHANGE:
  754. SendMessage(m_hwndList, msg, wParam, lParam);
  755. // reposition and resize things with the new font
  756. _OnWinIniChange(hwnd);
  757. break;
  758. case NVM_GETNEWGROUPS:
  759. if (m_pGroups != NULL)
  760. {
  761. m_pGroups->HandleGetNewGroups();
  762. m_pGroups->Release();
  763. m_pGroups = NULL;
  764. }
  765. return(0);
  766. case CM_OPTIONADVISE:
  767. m_clrWatched = DwGetOption(OPT_WATCHED_COLOR);
  768. return (0);
  769. default:
  770. if (g_msgMSWheel && (msg == g_msgMSWheel))
  771. {
  772. hwndFocus = GetFocus();
  773. if (IsChild(hwnd, hwndFocus))
  774. return SendMessage(hwndFocus, msg, wParam, lParam);
  775. }
  776. break;
  777. }
  778. return DefWindowProc(hwnd, msg, wParam, lParam);
  779. }
  780. void CAccountView::_OnCommand(WPARAM wParam, LPARAM lParam)
  781. {
  782. HWND hwndBrowser;
  783. HRESULT hr;
  784. if (HIWORD(wParam) == BN_CLICKED)
  785. {
  786. switch (LOWORD(wParam))
  787. {
  788. case ID_SEND_RECEIVE:
  789. case ID_SYNC_THIS_NOW:
  790. case ID_IMAP_FOLDERS:
  791. case ID_NEWSGROUPS:
  792. m_pShellBrowser->GetWindow(&hwndBrowser);
  793. SendMessage(hwndBrowser, WM_COMMAND, wParam, lParam);
  794. break;
  795. case ID_POPUP_SYNCHRONIZE:
  796. _HandleSettingsButton((HWND)lParam);
  797. break;
  798. default:
  799. Assert(FALSE);
  800. break;
  801. }
  802. }
  803. }
  804. //
  805. // FUNCTION: CAccountView::OnCreate
  806. //
  807. // PURPOSE: Creates the child windows necessary for the view and
  808. // initializes the data in those child windows.
  809. //
  810. // PARAMETERS:
  811. // hwnd - Handle of the view being created.
  812. // lpCreateStruct - Pointer to the creation params passed to
  813. // CreateWindow().
  814. //
  815. // RETURN VALUE:
  816. // Returns TRUE if the initialization is successful.
  817. //
  818. BOOL CAccountView::_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
  819. {
  820. HRESULT hr;
  821. DWORD style;
  822. FOLDERINFO info;
  823. COLUMN_SET_TYPE set;
  824. const ACCTVIEWBTN *pBtn;
  825. int i, cBtn, idsMajor, idsMinor;
  826. char sz[CCHMAX_STRINGRES];
  827. switch (m_ftType)
  828. {
  829. case FOLDER_LOCAL:
  830. set = COLUMN_SET_LOCAL_STORE;
  831. pBtn = c_rgMailBtns;
  832. cBtn = ARRAYSIZE(c_rgMailBtns);
  833. idsMajor = 0;
  834. idsMinor = idsLocalFoldersMinor;
  835. break;
  836. case FOLDER_IMAP:
  837. set = COLUMN_SET_IMAP_ACCOUNT;
  838. pBtn = c_rgImapBtns;
  839. cBtn = ARRAYSIZE(c_rgImapBtns);
  840. idsMajor = idsSyncManager;
  841. idsMinor = idsSetSyncSettings;
  842. break;
  843. case FOLDER_HTTPMAIL:
  844. set = COLUMN_SET_HTTPMAIL_ACCOUNT;
  845. pBtn = c_rgHttpBtns;
  846. cBtn = ARRAYSIZE(c_rgHttpBtns);
  847. idsMajor = idsSyncManager;
  848. idsMinor = idsSetSyncSettings;
  849. break;
  850. case FOLDER_NEWS:
  851. set = COLUMN_SET_NEWS_ACCOUNT;
  852. pBtn = c_rgNewsBtns;
  853. cBtn = ARRAYSIZE(c_rgNewsBtns);
  854. idsMajor = idsSyncManagerNews;
  855. idsMinor = idsSetNewsSyncSettings;
  856. break;
  857. default:
  858. Assert(FALSE);
  859. break;
  860. }
  861. for (i = 0; i < cBtn; i++, pBtn++)
  862. {
  863. if (pBtn->cmd == ID_POPUP_SYNCHRONIZE)
  864. style = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_NOTIFY | BS_OWNERDRAW | WS_DISABLED;
  865. else
  866. style = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_NOTIFY;
  867. AthLoadString(pBtn->idsText, sz, ARRAYSIZE(sz));
  868. m_rgBtns[m_cBtns] = CreateWindow("button", sz, style,
  869. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  870. hwnd, (HMENU)LongToHandle(pBtn->cmd), g_hInst, 0);
  871. if (m_rgBtns[m_cBtns] != NULL)
  872. m_cBtns++;
  873. }
  874. m_hwndList = CreateWindowEx(0, WC_LISTVIEW, c_szEmpty,
  875. WS_VISIBLE | WS_TABSTOP | WS_CHILD | LVS_REPORT | LVS_NOSORTHEADER |
  876. LVS_OWNERDATA | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS,
  877. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  878. hwnd, (HMENU)IDC_SUBSCRIBE_LIST, g_hInst, 0);
  879. Assert(m_hwndList != NULL);
  880. hr = m_pColumns->Initialize(m_hwndList, set);
  881. Assert(SUCCEEDED(hr));
  882. hr = m_pColumns->ApplyColumns(COLUMN_LOAD_REGISTRY, 0, 0);
  883. Assert(SUCCEEDED(hr));
  884. m_hwndHeader = ListView_GetHeader(m_hwndList);
  885. Assert(m_hwndHeader != NULL);
  886. // Initialize the extended styles so we get full row select. Just because
  887. // it looks better.
  888. ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES);
  889. Assert(m_himlFolders != NULL);
  890. ListView_SetImageList(m_hwndList, m_himlFolders, LVSIL_SMALL);
  891. SetIntlFont(m_hwndList);
  892. hr = g_pStore->GetFolderInfo(m_idFolder, &info);
  893. if (SUCCEEDED(hr))
  894. {
  895. if (MemAlloc((void **)&m_pszMajor, CCHMAX_STRINGRES))
  896. {
  897. if (idsMajor != 0)
  898. {
  899. AthLoadString(idsMajor, sz, ARRAYSIZE(sz));
  900. wnsprintf(m_pszMajor, CCHMAX_STRINGRES, sz, info.pszName);
  901. }
  902. else
  903. {
  904. StrCpyN(m_pszMajor, info.pszName, CCHMAX_STRINGRES);
  905. }
  906. }
  907. if (idsMinor != 0)
  908. m_pszMinor = AthLoadString(idsMinor, NULL, 0);
  909. g_pStore->FreeRecord(&info);
  910. }
  911. m_clrWatched = DwGetOption(OPT_WATCHED_COLOR);
  912. OptionAdvise(hwnd);
  913. _OnWinIniChange(hwnd);
  914. return TRUE;
  915. }
  916. BOOL CAccountView::_OnWinIniChange(HWND hwnd)
  917. {
  918. char sz[CCHMAX_STRINGRES];
  919. TEXTMETRIC tm;
  920. HDC hdc;
  921. int i, cch, cxMax;
  922. SIZE size;
  923. HFONT hfont, hfontBold, hfontOld;
  924. RECT rc, rcBtn;
  925. GetClientRect(hwnd, &rc);
  926. hfont = HGetCharSetFont(FNT_SYS_ICON, NULL);
  927. hfontBold = HGetCharSetFont(FNT_SYS_ICON_BOLD, NULL);
  928. hdc = GetDC(hwnd);
  929. hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
  930. Assert(m_pszMajor != NULL);
  931. GetTextExtentPoint32(hdc, m_pszMajor, lstrlen(m_pszMajor), &size);
  932. m_rcMajor.left = SUBSCRIBE_BORDER;
  933. m_rcMajor.top = SUBSCRIBE_BORDER;
  934. m_rcMajor.right = m_rcMajor.left + size.cx;
  935. m_rcMajor.bottom = m_rcMajor.top + size.cy;
  936. m_rcMinor.left = m_rcMajor.left;
  937. m_rcMinor.top = m_rcMajor.bottom + 1;
  938. if (m_pszMinor != NULL)
  939. {
  940. SelectObject(hdc, (HGDIOBJ)hfont);
  941. GetTextExtentPoint32(hdc, m_pszMinor, lstrlen(m_pszMinor), &size);
  942. }
  943. m_rcMinor.right = m_rcMinor.left + size.cx;
  944. m_rcMinor.bottom = m_rcMinor.top + size.cy;
  945. m_rcHeader.left = 0;
  946. m_rcHeader.top = 0;
  947. m_rcHeader.right = rc.right;
  948. m_rcHeader.bottom = m_rcMinor.bottom + SUBSCRIBE_BORDER;
  949. m_rcButtons.left = m_rcHeader.left;
  950. m_rcButtons.top = m_rcHeader.bottom + 1;
  951. m_rcButtons.right = m_rcHeader.right;
  952. m_rcButtons.bottom = m_rcButtons.top + m_rcHeader.bottom;
  953. SelectObject(hdc, hfont);
  954. cxMax = 0;
  955. for (i = 0; i < m_cBtns; i++)
  956. {
  957. cch = GetWindowText(m_rgBtns[i], sz, ARRAYSIZE(sz));
  958. GetTextExtentPoint32(hdc, sz, cch, &size);
  959. if (size.cx > cxMax)
  960. cxMax = size.cx;
  961. }
  962. SelectObject(hdc, hfontOld);
  963. ReleaseDC(hwnd, hdc);
  964. rcBtn.top = m_rcButtons.top + SUBSCRIBE_BORDER;
  965. rcBtn.bottom = rcBtn.top + (m_rcMinor.bottom - m_rcMajor.top);
  966. rcBtn.left = m_rcMajor.left;
  967. rcBtn.right = cxMax + 2 * GetSystemMetrics(SM_CXEDGE) + 6 + (rcBtn.bottom - rcBtn.top);
  968. cxMax = SUBSCRIBE_BORDER + (rcBtn.right - rcBtn.left);
  969. for (i = 0; i < m_cBtns; i++)
  970. {
  971. SendMessage(m_rgBtns[i], WM_SETFONT, (WPARAM)hfont, 0);
  972. SetWindowPos(m_rgBtns[i], NULL, rcBtn.left, rcBtn.top,
  973. rcBtn.right - rcBtn.left, rcBtn.bottom - rcBtn.top,
  974. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
  975. rcBtn.left += cxMax;
  976. rcBtn.right += cxMax;
  977. }
  978. rc.top = m_rcButtons.bottom + 1;
  979. SendMessage(m_hwndList, WM_SETFONT, (WPARAM)hfont, 0);
  980. SetWindowPos(m_hwndList, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
  981. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
  982. return(TRUE);
  983. }
  984. //
  985. // FUNCTION: CAccountView::OnSize
  986. //
  987. // PURPOSE: Notification that the view window has been resized. In
  988. // response we update the positions of our child windows and
  989. // controls.
  990. //
  991. // PARAMETERS:
  992. // hwnd - Handle of the view window being resized.
  993. // state - Type of resizing requested.
  994. // cxClient - New width of the client area.
  995. // cyClient - New height of the client area.
  996. //
  997. void CAccountView::_OnSize(HWND hwnd, UINT state, int cxClient, int cyClient)
  998. {
  999. int cy;
  1000. BOOL fUpdate;
  1001. fUpdate = (cxClient > m_rcHeader.right);
  1002. m_rcHeader.right = cxClient;
  1003. m_rcMajor.right = m_rcHeader.right - SUBSCRIBE_BORDER;
  1004. m_rcMinor.right = m_rcMajor.right;
  1005. m_rcButtons.right = m_rcHeader.right;
  1006. if ((m_rcButtons.bottom + 1) < cyClient)
  1007. cy = cyClient - (m_rcButtons.bottom + 1);
  1008. else
  1009. cy = 1;
  1010. SetWindowPos(m_hwndList, NULL, 0, 0, cxClient, cy,
  1011. SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOMOVE);
  1012. if (fUpdate)
  1013. {
  1014. InvalidateRect(hwnd, NULL, FALSE);
  1015. UpdateWindow(hwnd);
  1016. }
  1017. }
  1018. LRESULT CAccountView::_OnPaint(HWND hwnd, HDC hdc)
  1019. {
  1020. HFONT hfont, hfontBold, hfontOld;
  1021. RECT rc, rcT;
  1022. PAINTSTRUCT ps;
  1023. COLORREF crText, crBackground;
  1024. HBRUSH hBrush, hBrushOld;
  1025. if (0 != GetUpdateRect(hwnd, &rc, FALSE))
  1026. {
  1027. hdc = BeginPaint(hwnd, &ps);
  1028. if (IntersectRect(&rcT, &rc, &m_rcHeader))
  1029. {
  1030. crText = GetSysColor(COLOR_WINDOW);
  1031. crBackground = GetSysColor(COLOR_3DSHADOW);
  1032. hBrush = CreateSolidBrush(crBackground);
  1033. hBrushOld = SelectBrush(hdc, hBrush);
  1034. PatBlt(hdc, rcT.left, rcT.top, rcT.right - rcT.left, rcT.bottom - rcT.top, PATCOPY);
  1035. SelectBrush(hdc, hBrushOld);
  1036. DeleteBrush(hBrush);
  1037. SetBkColor(hdc, crBackground);
  1038. SetTextColor(hdc, crText);
  1039. if (m_pszMajor != NULL &&
  1040. IntersectRect(&rcT, &rc, &m_rcMajor))
  1041. {
  1042. hfontBold = HGetCharSetFont(FNT_SYS_ICON_BOLD, NULL);
  1043. hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
  1044. DrawText(hdc, m_pszMajor, lstrlen(m_pszMajor), &m_rcMajor, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX);
  1045. SelectObject(hdc, (HGDIOBJ)hfontOld);
  1046. }
  1047. if (m_pszMinor != NULL &&
  1048. IntersectRect(&rcT, &rc, &m_rcMinor))
  1049. {
  1050. hfontBold = HGetCharSetFont(FNT_SYS_ICON, NULL);
  1051. hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
  1052. DrawText(hdc, m_pszMinor, lstrlen(m_pszMinor), &m_rcMinor, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_NOPREFIX);
  1053. SelectObject(hdc, (HGDIOBJ)hfontOld);
  1054. }
  1055. }
  1056. rc.bottom = m_rcButtons.bottom;
  1057. DrawEdge(hdc, &rc, EDGE_ETCHED, BF_BOTTOM);
  1058. EndPaint(hwnd, &ps);
  1059. }
  1060. return(0);
  1061. }
  1062. BOOL DrawArrow(HDC hdc, LPARAM x, WPARAM y, int dx, int dy)
  1063. {
  1064. int i, iCount;
  1065. iCount = (dx + 1) / 2;
  1066. // draw arrow head
  1067. for (i = 0; i < iCount; i++, dx -= 2, x += 1)
  1068. PatBlt(hdc, (int) x, (int) y++, dx, 1, PATCOPY);
  1069. return(TRUE);
  1070. }
  1071. #define CXARROW 9
  1072. #define CYARROW 5
  1073. void DrawSettingsButton(HWND hwnd, LPDRAWITEMSTRUCT pdi)
  1074. {
  1075. BOOL fPushed, fDisabled;
  1076. TCHAR sz[CCHMAX_STRINGRES];
  1077. RECT rcFocus;
  1078. int d, cch, x, y, xArrow, yArrow;
  1079. SIZE size;
  1080. UINT dsFlags;
  1081. HGDIOBJ hbrOld;
  1082. Assert(pdi->CtlType == ODT_BUTTON);
  1083. Assert(pdi->CtlID == ID_POPUP_SYNCHRONIZE);
  1084. if (!!(pdi->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
  1085. {
  1086. fPushed = !!(pdi->itemState & ODS_SELECTED);
  1087. fDisabled = !!(pdi->itemState & ODS_DISABLED);
  1088. if (fPushed)
  1089. dsFlags = DFCS_BUTTONPUSH | DFCS_PUSHED;
  1090. else
  1091. dsFlags = DFCS_BUTTONPUSH;
  1092. DrawFrameControl(pdi->hDC, &pdi->rcItem, DFC_BUTTON, dsFlags);
  1093. cch = GetWindowText(pdi->hwndItem, sz, ARRAYSIZE(sz));
  1094. GetTextExtentPoint32(pdi->hDC, sz, cch, &size);
  1095. size.cy++;
  1096. x = (pdi->rcItem.left + pdi->rcItem.right - size.cx) / 2;
  1097. y = (pdi->rcItem.top + pdi->rcItem.bottom - size.cy) / 2;
  1098. if (fPushed)
  1099. {
  1100. x++;
  1101. y++;
  1102. }
  1103. xArrow = x + size.cx + 7;
  1104. yArrow = (pdi->rcItem.top + pdi->rcItem.bottom - CYARROW) / 2;
  1105. yArrow++;
  1106. if (fPushed)
  1107. yArrow++;
  1108. if (fDisabled)
  1109. {
  1110. DrawState(pdi->hDC, NULL, DrawArrow, 0, 0,
  1111. xArrow, yArrow, CXARROW, CYARROW, DST_COMPLEX | DSS_DISABLED);
  1112. }
  1113. else
  1114. {
  1115. hbrOld = SelectObject(pdi->hDC, GetSysColorBrush(COLOR_BTNTEXT));
  1116. DrawArrow(pdi->hDC, xArrow, yArrow, CXARROW, CYARROW);
  1117. SelectObject(pdi->hDC, hbrOld);
  1118. }
  1119. if (fDisabled)
  1120. dsFlags = DST_TEXT | DSS_DISABLED;
  1121. else
  1122. dsFlags = DST_TEXT | DSS_NORMAL;
  1123. DrawState(pdi->hDC, NULL, NULL, (LPARAM)sz, (WPARAM)cch,
  1124. x, y, size.cx, size.cy, dsFlags);
  1125. }
  1126. if (!!(pdi->itemAction & ODA_FOCUS) || !!(pdi->itemState & ODS_FOCUS))
  1127. {
  1128. rcFocus = pdi->rcItem;
  1129. d = GetSystemMetrics(SM_CXEDGE) + 1;
  1130. rcFocus.left += d;
  1131. rcFocus.right -= d;
  1132. d = GetSystemMetrics(SM_CYEDGE) + 1;
  1133. rcFocus.top += d;
  1134. rcFocus.bottom -= d;
  1135. DrawFocusRect(pdi->hDC, &rcFocus);
  1136. }
  1137. }
  1138. //
  1139. // FUNCTION: CAccountView::OnSetFocus
  1140. //
  1141. // PURPOSE: If the focus ever is set to the view window, we want to
  1142. // make sure it goes to one of our child windows. Preferably
  1143. // the focus will go to the last child to have the focus.
  1144. //
  1145. // PARAMETERS:
  1146. // hwnd - Handle of the view window.
  1147. // hwndOldFocus - Handle of the window losing focus.
  1148. //
  1149. void CAccountView::_OnSetFocus(HWND hwnd, HWND hwndOldFocus)
  1150. {
  1151. SetFocus(m_hwndList);
  1152. }
  1153. //
  1154. // FUNCTION: CAccountView::OnNotify
  1155. //
  1156. // PURPOSE: Processes the various notifications we receive from our child
  1157. // controls.
  1158. //
  1159. // PARAMETERS:
  1160. // hwnd - Handle of the view window.
  1161. // idCtl - identifies the control sending the notification
  1162. // pnmh - points to a NMHDR struct with more information regarding the
  1163. // notification
  1164. //
  1165. // RETURN VALUE:
  1166. // Dependant on the specific notification.
  1167. //
  1168. LRESULT CAccountView::_OnNotify(HWND hwnd, int idFrom, LPNMHDR pnmhdr)
  1169. {
  1170. LRESULT lRes=0;
  1171. HD_NOTIFY *phdn;
  1172. int iSel;
  1173. DWORD dwPos;
  1174. UINT uChanged;
  1175. FOLDERINFO info;
  1176. LV_HITTESTINFO lvhti;
  1177. NM_LISTVIEW *pnmlv;
  1178. LV_DISPINFO *pDispInfo;
  1179. DWORD cColumns;
  1180. NMCUSTOMDRAW *pnmcd;
  1181. COLUMN_ID id;
  1182. FOLDERID idFolder;
  1183. COLUMN_SET *rgColumns;
  1184. HRESULT hr;
  1185. FNTSYSTYPE fntType;
  1186. if (pnmhdr->hwndFrom != m_hwndList &&
  1187. pnmhdr->hwndFrom != m_hwndHeader)
  1188. return(0);
  1189. switch (pnmhdr->code)
  1190. {
  1191. case NM_SETFOCUS:
  1192. m_pShellBrowser->OnViewWindowActive(this);
  1193. _HandleItemStateChange();
  1194. break;
  1195. case LVN_ITEMACTIVATE:
  1196. // Tell our host to open the selected items
  1197. iSel = ListView_GetNextItem(m_hwndList, -1, LVNI_ALL | LVNI_SELECTED | LVNI_FOCUSED);
  1198. if (iSel >= 0)
  1199. g_pInstance->BrowseToObject(SW_SHOWNORMAL, _IdFromIndex(iSel));
  1200. break;
  1201. case LVN_GETDISPINFO:
  1202. pDispInfo = (LV_DISPINFO *)pnmhdr;
  1203. id = m_pColumns->GetId(pDispInfo->item.iSubItem);
  1204. if ((DWORD)pDispInfo->item.iItem < m_cnode)
  1205. _GetDisplayInfo(pDispInfo, id);
  1206. break;
  1207. case NM_CLICK:
  1208. dwPos = GetMessagePos();
  1209. lvhti.pt.x = (int)(short)LOWORD(dwPos);
  1210. lvhti.pt.y = (int)(short)HIWORD(dwPos);
  1211. ScreenToClient(m_hwndList, &(lvhti.pt));
  1212. // Ask the ListView where this is
  1213. if (-1 == ListView_SubItemHitTest(m_hwndList, &lvhti))
  1214. break;
  1215. id = m_pColumns->GetId(lvhti.iSubItem);
  1216. if (lvhti.flags == LVHT_ONITEMICON)
  1217. {
  1218. if (id == COLUMN_DOWNLOAD)
  1219. {
  1220. _ToggleDownload(lvhti.iItem);
  1221. }
  1222. }
  1223. break;
  1224. case NM_CUSTOMDRAW:
  1225. pnmcd = (NMCUSTOMDRAW *)pnmhdr;
  1226. // If this is a prepaint notification, we tell the control we're interested
  1227. // in further notfications.
  1228. if (pnmcd->dwDrawStage == CDDS_PREPAINT)
  1229. {
  1230. lRes = CDRF_NOTIFYITEMDRAW;
  1231. break;
  1232. }
  1233. // Do some extra work here to not show the selection on the priority or
  1234. // attachment sub columns.
  1235. // $REVIEW - Why?
  1236. if ((pnmcd->dwDrawStage == CDDS_ITEMPREPAINT) || (pnmcd->dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM)))
  1237. {
  1238. fntType = FNT_SYS_ICON;
  1239. if (pnmcd->dwItemSpec >= m_cnode)
  1240. {
  1241. lRes = CDRF_DODEFAULT;
  1242. break;
  1243. }
  1244. if (SUCCEEDED(g_pStore->GetFolderInfo(_IdFromIndex((DWORD)(pnmcd->dwItemSpec)), &info)))
  1245. {
  1246. if (pnmcd->dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
  1247. {
  1248. if ((info.cWatchedUnread) && (m_clrWatched > 0 && m_clrWatched < 16))
  1249. {
  1250. LPNMLVCUSTOMDRAW(pnmcd)->clrText = rgrgbColors16[m_clrWatched - 1];
  1251. }
  1252. else
  1253. {
  1254. id = m_pColumns->GetId(LPNMLVCUSTOMDRAW(pnmcd)->iSubItem);
  1255. if (id == COLUMN_DOWNLOAD && 0 == (info.dwFlags & FOLDER_SYNCMASK))
  1256. {
  1257. LPNMLVCUSTOMDRAW(pnmcd)->clrText = GetSysColor(COLOR_GRAYTEXT);
  1258. }
  1259. }
  1260. }
  1261. if (info.cUnread > 0 ||
  1262. (info.tyFolder == FOLDER_NEWS && info.dwNotDownloaded > 0))
  1263. fntType = FNT_SYS_ICON_BOLD;
  1264. g_pStore->FreeRecord(&info);
  1265. }
  1266. SelectObject(pnmcd->hdc, HGetCharSetFont(fntType, GetListViewCharset()));
  1267. lRes = CDRF_NEWFONT | CDRF_NOTIFYSUBITEMDRAW;
  1268. break;
  1269. }
  1270. lRes = CDRF_DODEFAULT;
  1271. break;
  1272. case LVN_ITEMCHANGED:
  1273. pnmlv = (NM_LISTVIEW *)pnmhdr;
  1274. if (!!(pnmlv->uChanged & LVIF_STATE) &&
  1275. !!((LVIS_SELECTED | LVIS_FOCUSED) & (pnmlv->uOldState ^ pnmlv->uNewState)))
  1276. {
  1277. _HandleItemStateChange();
  1278. }
  1279. break;
  1280. case HDN_ENDTRACK:
  1281. phdn = (HD_NOTIFY *)pnmhdr;
  1282. m_pColumns->SetColumnWidth(phdn->iItem, phdn->pitem->cxy);
  1283. break;
  1284. case HDN_DIVIDERDBLCLICK:
  1285. phdn = (HD_NOTIFY *)pnmhdr;
  1286. // When the user double clicks on a header divider, we're supposed to
  1287. // autosize that column.
  1288. m_pColumns->SetColumnWidth(phdn->iItem, ListView_GetColumnWidth(m_hwndList, phdn->iItem));
  1289. break;
  1290. default:
  1291. lRes = 0;
  1292. break;
  1293. }
  1294. return(lRes);
  1295. }
  1296. void CAccountView::_HandleItemStateChange()
  1297. {
  1298. OLECMD rgCmds[3];
  1299. HRESULT hr;
  1300. IOleCommandTarget *pTarget;
  1301. int i;
  1302. hr = m_pShellBrowser->QueryInterface(IID_IOleCommandTarget, (void **)&pTarget);
  1303. if (SUCCEEDED(hr))
  1304. {
  1305. for (i = 0; i < m_cBtns; i++)
  1306. {
  1307. rgCmds[i].cmdID = GetWindowLong(m_rgBtns[i], GWL_ID);
  1308. rgCmds[i].cmdf = 0;
  1309. }
  1310. hr = pTarget->QueryStatus(NULL, m_cBtns, rgCmds, NULL);
  1311. if (SUCCEEDED(hr))
  1312. {
  1313. for (i = 0; i < m_cBtns; i++)
  1314. {
  1315. EnableWindow(m_rgBtns[i], !!(rgCmds[i].cmdf & OLECMDF_ENABLED));
  1316. Assert(0 == (rgCmds[i].cmdf & OLECMDF_LATCHED));
  1317. Assert(0 == (rgCmds[i].cmdf & OLECMDF_NINCHED));
  1318. }
  1319. }
  1320. pTarget->Release();
  1321. }
  1322. m_pShellBrowser->UpdateToolbar();
  1323. }
  1324. HRESULT CAccountView::_GetDisplayInfo(LV_DISPINFO *pDispInfo, COLUMN_ID id)
  1325. {
  1326. DWORD dwFlags;
  1327. int count;
  1328. FOLDERINFO info;
  1329. HRESULT hr;
  1330. FLDRNODE *pNode;
  1331. pNode = _NodeFromIndex((DWORD)pDispInfo->item.iItem);
  1332. if (pNode == NULL)
  1333. return(S_OK);
  1334. hr = g_pStore->GetFolderInfo(pNode->id, &info);
  1335. if (FAILED(hr))
  1336. return(hr);
  1337. if (!!(pDispInfo->item.mask & LVIF_TEXT))
  1338. {
  1339. if (id == COLUMN_NEWSGROUP || id == COLUMN_FOLDER)
  1340. {
  1341. StrCpyN(pDispInfo->item.pszText, info.pszName, pDispInfo->item.cchTextMax);
  1342. }
  1343. else if (id == COLUMN_DOWNLOAD)
  1344. {
  1345. if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
  1346. {
  1347. if (0 == (info.dwFlags & FOLDER_SYNCMASK))
  1348. dwFlags = pNode->dwDownload;
  1349. else
  1350. dwFlags = info.dwFlags;
  1351. Assert(!!(dwFlags & FOLDER_SYNCMASK));
  1352. if (!!(dwFlags & FOLDER_DOWNLOADALL))
  1353. AthLoadString(idsAllMessages, pDispInfo->item.pszText, pDispInfo->item.cchTextMax);
  1354. else if (!!(dwFlags & FOLDER_DOWNLOADNEW))
  1355. AthLoadString(idsNewMessages, pDispInfo->item.pszText, pDispInfo->item.cchTextMax);
  1356. else if (!!(dwFlags & FOLDER_DOWNLOADHEADERS))
  1357. AthLoadString(idsNewHeaders, pDispInfo->item.pszText, pDispInfo->item.cchTextMax);
  1358. }
  1359. }
  1360. else if (id == COLUMN_TOTAL || id == COLUMN_UNREAD)
  1361. {
  1362. if (id == COLUMN_UNREAD)
  1363. count = info.cUnread;
  1364. else
  1365. count = info.cMessages;
  1366. if (FOLDER_NEWS == info.tyFolder)
  1367. count += info.dwNotDownloaded;
  1368. if (count < 0)
  1369. count = 0;
  1370. wnsprintf(pDispInfo->item.pszText, pDispInfo->item.cchTextMax, "%d", count);
  1371. }
  1372. }
  1373. if (!!(pDispInfo->item.mask & LVIF_IMAGE))
  1374. {
  1375. if (id == COLUMN_NEWSGROUP)
  1376. {
  1377. pDispInfo->item.iImage = iNullBitmap;
  1378. if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
  1379. {
  1380. pDispInfo->item.iImage = iNewsGroup;
  1381. if (!!(info.dwFlags & FOLDER_SYNCMASK))
  1382. pDispInfo->item.iImage = iNewsGroupSync;
  1383. }
  1384. }
  1385. else if (COLUMN_FOLDER == id)
  1386. {
  1387. pDispInfo->item.iImage = iNullBitmap;
  1388. if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
  1389. {
  1390. if (info.tySpecial == FOLDER_NOTSPECIAL)
  1391. pDispInfo->item.iImage = iFolderClosed;
  1392. else
  1393. pDispInfo->item.iImage = (iInbox + (((info.tySpecial == FOLDER_BULKMAIL) ? FOLDER_JUNK : info.tySpecial) - 1));
  1394. }
  1395. }
  1396. else if (COLUMN_DOWNLOAD == id)
  1397. {
  1398. pDispInfo->item.iImage = iNullBitmap;
  1399. if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
  1400. {
  1401. if (!!(info.dwFlags & FOLDER_SYNCMASK))
  1402. pDispInfo->item.iImage = iChecked;
  1403. else
  1404. pDispInfo->item.iImage = iUnchecked;
  1405. }
  1406. }
  1407. }
  1408. if (!!(pDispInfo->item.mask & LVIF_INDENT))
  1409. {
  1410. if (COLUMN_FOLDER == id)
  1411. pDispInfo->item.iIndent = pNode->indent;
  1412. }
  1413. g_pStore->FreeRecord(&info);
  1414. return(S_OK);
  1415. }
  1416. BOOL CAccountView::_OnActivate(UINT uActivation)
  1417. {
  1418. // if focus stays within the frame, but goes outside our view.
  1419. // ie.. TreeView gets focus then we get an activate nofocus. Be sure
  1420. // to UIDeactivate the docobj in this case
  1421. if (uActivation == SVUIA_ACTIVATE_NOFOCUS)
  1422. {
  1423. }
  1424. if (m_uActivation != uActivation)
  1425. {
  1426. _OnDeactivate();
  1427. m_uActivation = uActivation;
  1428. if (!m_fFirstActive)
  1429. {
  1430. PostMessage(m_hwnd, NVM_INITHEADERS, 0, 0L);
  1431. m_fFirstActive = TRUE;
  1432. }
  1433. }
  1434. return TRUE;
  1435. }
  1436. BOOL CAccountView::_OnDeactivate()
  1437. {
  1438. return TRUE;
  1439. }
  1440. HRESULT CAccountView::_InsertChildren(FOLDERID idFolder, DWORD indent, DWORD *piNode)
  1441. {
  1442. DWORD cnode;
  1443. ULONG cFolders;
  1444. IEnumerateFolders *pEnum;
  1445. FOLDERINFO info;
  1446. HRESULT hr;
  1447. Assert(piNode != NULL);
  1448. Assert(*piNode <= m_cnode);
  1449. hr = g_pStore->EnumChildren(idFolder, TRUE, &pEnum);
  1450. if (SUCCEEDED(hr))
  1451. {
  1452. hr = pEnum->Count(&cFolders);
  1453. if (SUCCEEDED(hr) && cFolders > 0)
  1454. {
  1455. while (S_OK == pEnum->Next(1, &info, NULL))
  1456. {
  1457. Assert(m_cnode <= m_cnodeBuf);
  1458. // Skip folders which are hidden
  1459. if (ISFLAGSET(info.dwFlags, FOLDER_HIDDEN))
  1460. continue;
  1461. if (m_cnode == m_cnodeBuf)
  1462. {
  1463. cnode = m_cnode + cFolders + CALLOCIDBUF;
  1464. if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
  1465. {
  1466. pEnum->Release();
  1467. return(E_OUTOFMEMORY);
  1468. }
  1469. m_cnodeBuf = cnode;
  1470. }
  1471. if (*piNode < m_cnode)
  1472. MoveMemory(&m_rgnode[*piNode + 1], &m_rgnode[*piNode], (m_cnode - *piNode) * sizeof(FLDRNODE));
  1473. m_rgnode[*piNode].id = info.idFolder;
  1474. m_rgnode[*piNode].indent = indent;
  1475. m_rgnode[*piNode].dwDownload = m_dwDownloadDef;
  1476. (*piNode)++;
  1477. m_cnode++;
  1478. if (!!(info.dwFlags & FOLDER_HASCHILDREN))
  1479. hr = _InsertChildren(info.idFolder, indent + 1, piNode);
  1480. g_pStore->FreeRecord(&info);
  1481. if (FAILED(hr))
  1482. break;
  1483. }
  1484. }
  1485. pEnum->Release();
  1486. }
  1487. return(hr);
  1488. }
  1489. HRESULT CAccountView::_InsertChildrenSpecial(FOLDERID idFolder, DWORD indent, DWORD *piNode)
  1490. {
  1491. DWORD cnode;
  1492. ULONG iFolder, cFolders;
  1493. IEnumerateFolders *pEnum;
  1494. FOLDERINFO info;
  1495. HRESULT hr;
  1496. FLDRNODE *rgNode, *pNode;
  1497. Assert(piNode != NULL);
  1498. Assert(*piNode <= m_cnode);
  1499. Assert(indent == 0);
  1500. rgNode = NULL;
  1501. hr = g_pStore->EnumChildren(idFolder, TRUE, &pEnum);
  1502. if (SUCCEEDED(hr))
  1503. {
  1504. hr = pEnum->Count(&cFolders);
  1505. if (SUCCEEDED(hr) && cFolders > 0)
  1506. {
  1507. if (!MemAlloc((void **)&rgNode, cFolders * sizeof(FLDRNODE)))
  1508. {
  1509. hr = E_OUTOFMEMORY;
  1510. }
  1511. else
  1512. {
  1513. pNode = rgNode;
  1514. cFolders = 0;
  1515. while (S_OK == pEnum->Next(1, &info, NULL))
  1516. {
  1517. if ((!(g_dwAthenaMode & MODE_NEWSONLY) || (info.tySpecial != FOLDER_INBOX)) &&
  1518. ISFLAGCLEAR(info.dwFlags, FOLDER_HIDDEN))
  1519. {
  1520. pNode->id = info.idFolder;
  1521. pNode->indent = !!(info.dwFlags & FOLDER_HASCHILDREN) ? 1 : 0;
  1522. pNode->dwDownload = m_dwDownloadDef;
  1523. pNode++;
  1524. cFolders++;
  1525. }
  1526. g_pStore->FreeRecord(&info);
  1527. }
  1528. qsort(rgNode, cFolders, sizeof(FLDRNODE), GroupCompare);
  1529. }
  1530. }
  1531. pEnum->Release();
  1532. }
  1533. if (rgNode != NULL)
  1534. {
  1535. Assert(SUCCEEDED(hr));
  1536. Assert(cFolders > 0);
  1537. Assert(m_cnode == 0);
  1538. Assert(m_cnodeBuf == 0);
  1539. for (iFolder = 0, pNode = rgNode; iFolder < cFolders; iFolder++, pNode++)
  1540. {
  1541. if (m_cnode == m_cnodeBuf)
  1542. {
  1543. cnode = m_cnode + cFolders + CALLOCIDBUF;
  1544. if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
  1545. {
  1546. hr = E_OUTOFMEMORY;
  1547. break;
  1548. }
  1549. m_cnodeBuf = cnode;
  1550. }
  1551. m_rgnode[*piNode].id = pNode->id;
  1552. m_rgnode[*piNode].indent = indent;
  1553. m_rgnode[*piNode].dwDownload = m_dwDownloadDef;
  1554. (*piNode)++;
  1555. m_cnode++;
  1556. if (pNode->indent == 1)
  1557. {
  1558. hr = _InsertChildren(pNode->id, indent + 1, piNode);
  1559. if (FAILED(hr))
  1560. break;
  1561. }
  1562. }
  1563. MemFree(rgNode);
  1564. }
  1565. return(hr);
  1566. }
  1567. void CAccountView::_PostCreate()
  1568. {
  1569. HRESULT hr;
  1570. DWORD iNode;
  1571. BOOL fNews, fSub;
  1572. Assert(m_cnode == 0);
  1573. ProcessICW(m_hwndOwner, m_ftType);
  1574. fNews = m_ftType == FOLDER_NEWS;
  1575. iNode = 0;
  1576. if (fNews)
  1577. hr = _InsertChildren(m_idFolder, 0, &iNode);
  1578. else
  1579. hr = _InsertChildrenSpecial(m_idFolder, 0, &iNode);
  1580. if (FAILED(hr))
  1581. {
  1582. if (m_rgnode != NULL)
  1583. {
  1584. MemFree(m_rgnode);
  1585. m_rgnode = NULL;
  1586. }
  1587. m_cnode = 0;
  1588. m_cnodeBuf = 0;
  1589. }
  1590. else
  1591. {
  1592. Assert(iNode == m_cnode);
  1593. }
  1594. ListView_SetItemCount(m_hwndList, m_cnode);
  1595. if (m_cnode > 0)
  1596. {
  1597. ListView_SetItemState(m_hwndList, -1, 0, LVIS_SELECTED | LVIS_FOCUSED);
  1598. ListView_SetItemState(m_hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  1599. }
  1600. if (m_cnode == 0)
  1601. m_pEmptyList->Show(m_hwndList, m_ftType == FOLDER_NEWS ? (LPSTR)idsEmptyNewsAcct : (LPSTR)idsEmptyMailAcct);
  1602. UpdateWindow(m_hwndList);
  1603. g_pStore->RegisterNotify(IINDEX_SUBSCRIBED, REGISTER_NOTIFY_NOADDREF, 0, (IDatabaseNotify *)this);
  1604. m_fRegistered = TRUE;
  1605. fSub = FALSE;
  1606. if (m_cnode == 0 && (fNews || m_ftType == FOLDER_IMAP || m_ftType == FOLDER_HTTPMAIL))
  1607. {
  1608. if (IDYES == AthMessageBoxW(m_hwndOwner, MAKEINTRESOURCEW(idsAthena),
  1609. fNews ? MAKEINTRESOURCEW(idsErrNoSubscribedGroups) : MAKEINTRESOURCEW(idsErrNoSubscribedFolders),
  1610. 0, MB_YESNO))
  1611. {
  1612. if (m_ftType == FOLDER_HTTPMAIL)
  1613. DownloadNewsgroupList(m_hwndOwner, m_idFolder);
  1614. else
  1615. DoSubscriptionDialog(m_hwndOwner, fNews, m_idFolder);
  1616. fSub = TRUE;
  1617. }
  1618. }
  1619. else if (m_ftType == FOLDER_IMAP && NULL != g_pStore)
  1620. {
  1621. FOLDERINFO fiServer;
  1622. if (SUCCEEDED(g_pStore->GetFolderInfo(m_idFolder, &fiServer)))
  1623. {
  1624. CheckIMAPDirty(fiServer.pszAccountId, m_hwnd, fiServer.idFolder, NOFLAGS);
  1625. g_pStore->FreeRecord(&fiServer);
  1626. }
  1627. }
  1628. if (!fSub && fNews)
  1629. hr = NewsUtil_CheckForNewGroups(m_hwnd, m_idFolder, &m_pGroups);
  1630. }
  1631. void CAccountView::_OnContextMenu(HWND hwnd, HWND hwndFrom, int x, int y)
  1632. {
  1633. HRESULT hr;
  1634. int iSel, i, id;
  1635. HMENU hmenu;
  1636. FOLDERID idFolder;
  1637. LV_HITTESTINFO lvhti;
  1638. POINT pt = {x, y};
  1639. // We only have context menus for the ListView
  1640. if (hwndFrom != m_hwndList)
  1641. return;
  1642. if (MAKELPARAM(x, y) == -1) // invoked from keyboard: figure out pos.
  1643. {
  1644. Assert(hwndFrom == m_hwndList);
  1645. i = ListView_GetFirstSel(m_hwndList);
  1646. if (i == -1)
  1647. return;
  1648. ListView_GetItemPosition(m_hwndList, i, &pt);
  1649. ClientToScreen(m_hwndList, &pt);
  1650. x = pt.x;
  1651. y = pt.y;
  1652. }
  1653. id = 0;
  1654. if (WindowFromPoint(pt) == m_hwndHeader)
  1655. {
  1656. // Pop up the context menu.
  1657. hmenu = LoadPopupMenu(IDR_COLUMNS_POPUP);
  1658. if (hmenu != NULL)
  1659. {
  1660. // Disable sort options because we don't support sorting
  1661. EnableMenuItem(hmenu, ID_SORT_ASCENDING, MF_GRAYED|MF_DISABLED);
  1662. EnableMenuItem(hmenu, ID_SORT_ASCENDING, MF_GRAYED|MF_DISABLED);
  1663. id = TrackPopupMenuEx(hmenu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
  1664. x, y, m_hwnd, NULL);
  1665. DestroyMenu(hmenu);
  1666. }
  1667. }
  1668. else
  1669. {
  1670. // Find out where the click happened
  1671. lvhti.pt.x = x;
  1672. lvhti.pt.y = y;
  1673. ScreenToClient(m_hwndList, &lvhti.pt);
  1674. // Have the ListView tell us what element this was on
  1675. iSel = ListView_HitTest(m_hwndList, &lvhti);
  1676. if (iSel >= 0)
  1677. {
  1678. idFolder = _IdFromIndex((DWORD)iSel);
  1679. hr = MenuUtil_GetContextMenu(idFolder, (IOleCommandTarget *)this, &hmenu);
  1680. if (SUCCEEDED(hr))
  1681. {
  1682. id = TrackPopupMenuEx(hmenu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
  1683. x, y, m_hwnd, NULL);
  1684. DestroyMenu(hmenu);
  1685. }
  1686. }
  1687. }
  1688. if (id != 0)
  1689. Exec(NULL, id, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  1690. }
  1691. int __cdecl GroupCompare(const void *lParam1, const void *lParam2)
  1692. {
  1693. int cmp;
  1694. HRESULT hr;
  1695. FOLDERINFO info1, info2;
  1696. IxpAssert(lParam1 != NULL);
  1697. IxpAssert(lParam2 != NULL);
  1698. if (FAILED(g_pStore->GetFolderInfo(((FLDRNODE *)lParam1)->id, &info1)))
  1699. return -1;
  1700. if (FAILED(g_pStore->GetFolderInfo(((FLDRNODE *)lParam2)->id, &info2)))
  1701. {
  1702. g_pStore->FreeRecord(&info1);
  1703. return 1;
  1704. }
  1705. IxpAssert(0 == (info1.dwFlags & FOLDER_SERVER));
  1706. IxpAssert(0 == (info2.dwFlags & FOLDER_SERVER));
  1707. IxpAssert(info1.idParent == info2.idParent);
  1708. if (info1.tySpecial != FOLDER_NOTSPECIAL)
  1709. {
  1710. if (info2.tySpecial != FOLDER_NOTSPECIAL)
  1711. cmp = info1.tySpecial - info2.tySpecial;
  1712. else
  1713. cmp = -1;
  1714. }
  1715. else
  1716. {
  1717. if (info2.tySpecial != FOLDER_NOTSPECIAL)
  1718. cmp = 1;
  1719. else
  1720. cmp = lstrcmpi(info1.pszName, info2.pszName);
  1721. }
  1722. g_pStore->FreeRecord(&info1);
  1723. g_pStore->FreeRecord(&info2);
  1724. return(cmp);
  1725. }
  1726. HRESULT CAccountView::_InsertFolder(LPFOLDERINFO pFolder)
  1727. {
  1728. BOOL fHide;
  1729. DWORD cnode, cSibs, indent, index, iFirstSib, iSib, iEnd;
  1730. HRESULT hr;
  1731. LV_ITEM lvi;
  1732. FLDRNODE *rgNodeSib, *pNode;
  1733. Assert(!!(pFolder->dwFlags & FOLDER_SUBSCRIBED));
  1734. // Check if folder is hidden
  1735. if (pFolder->dwFlags & FOLDER_HIDDEN)
  1736. return S_OK; // Do not display to user
  1737. if (pFolder->tyFolder == FOLDER_NEWS)
  1738. return(_InsertFolderNews(pFolder));
  1739. fHide = (m_cnode == 0);
  1740. index = _GetFolderIndex(pFolder->idFolder);
  1741. if (index != -1)
  1742. {
  1743. // TODO: are we safe to assume that this one doesn't have subscribed
  1744. // children that we aren't aware of????
  1745. return(S_OK);
  1746. }
  1747. // figure out which folder the new folder is being inserted under
  1748. if (pFolder->idParent == m_idFolder)
  1749. {
  1750. iFirstSib = 0;
  1751. indent = 0;
  1752. }
  1753. else
  1754. {
  1755. index = _GetFolderIndex(pFolder->idParent);
  1756. if (index == -1)
  1757. return(S_OK);
  1758. indent = m_rgnode[index].indent + 1;
  1759. iFirstSib = index + 1;
  1760. }
  1761. // get all of the siblings of the new folder
  1762. if (!MemAlloc((void **)&rgNodeSib, (m_cnode - iFirstSib + 1) * sizeof(FLDRNODE)))
  1763. return(E_OUTOFMEMORY);
  1764. cSibs = 0;
  1765. for (iSib = iFirstSib, pNode = &m_rgnode[iSib]; iSib < m_cnode; iSib++, pNode++)
  1766. {
  1767. if (pNode->indent < indent)
  1768. {
  1769. break;
  1770. }
  1771. else if (pNode->indent == indent)
  1772. {
  1773. rgNodeSib[cSibs].id = pNode->id;
  1774. cSibs++;
  1775. }
  1776. }
  1777. iEnd = iSib;
  1778. // sort the new folder and its siblings, so we know where the new one needs
  1779. // to be inserted
  1780. rgNodeSib[cSibs].id = pFolder->idFolder;
  1781. cSibs++;
  1782. qsort(rgNodeSib, cSibs, sizeof(FLDRNODE), GroupCompare);
  1783. // find out where we're sticking the new folder
  1784. for (iSib = 0, pNode = rgNodeSib; iSib < cSibs; iSib++, pNode++)
  1785. {
  1786. if (pNode->id == pFolder->idFolder)
  1787. break;
  1788. }
  1789. Assert(iSib < cSibs);
  1790. if (iSib + 1 < cSibs)
  1791. index = _GetFolderIndex(rgNodeSib[iSib + 1].id);
  1792. else
  1793. index = iEnd;
  1794. MemFree(rgNodeSib);
  1795. if (m_cnode == m_cnodeBuf)
  1796. {
  1797. cnode = m_cnodeBuf + CALLOCIDBUF;
  1798. if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
  1799. return(E_OUTOFMEMORY);
  1800. m_cnodeBuf = cnode;
  1801. }
  1802. SetWindowRedraw(m_hwndList, FALSE);
  1803. if (index < m_cnode)
  1804. MoveMemory(&m_rgnode[index + 1], &m_rgnode[index], (m_cnode - index) * sizeof(FLDRNODE));
  1805. m_rgnode[index].id = pFolder->idFolder;
  1806. m_rgnode[index].indent = indent;
  1807. m_rgnode[index].dwDownload = m_dwDownloadDef;
  1808. m_cnode++;
  1809. iEnd = index + 1;
  1810. if (!!(pFolder->dwFlags & FOLDER_HASCHILDREN))
  1811. {
  1812. hr = _InsertChildren(pFolder->idFolder, indent + 1, &iEnd);
  1813. // TODO: error handling
  1814. Assert(SUCCEEDED(hr));
  1815. }
  1816. ZeroMemory(&lvi, sizeof(LV_ITEM));
  1817. while (index < iEnd)
  1818. {
  1819. lvi.iItem = index++;
  1820. ListView_InsertItem(m_hwndList, &lvi);
  1821. }
  1822. if (fHide)
  1823. m_pEmptyList->Hide();
  1824. SetWindowRedraw(m_hwndList, TRUE);
  1825. UpdateWindow(m_hwndList);
  1826. return(S_OK);
  1827. }
  1828. HRESULT CAccountView::_InsertFolderNews(LPFOLDERINFO pFolder)
  1829. {
  1830. DWORD cnode;
  1831. HRESULT hr;
  1832. LV_ITEM lvi;
  1833. if (m_cnode == m_cnodeBuf)
  1834. {
  1835. cnode = m_cnodeBuf + CALLOCIDBUF;
  1836. if (!MemRealloc((void **)&m_rgnode, cnode * sizeof(FLDRNODE)))
  1837. return(E_OUTOFMEMORY);
  1838. m_cnodeBuf = cnode;
  1839. }
  1840. m_rgnode[m_cnode].id = pFolder->idFolder;
  1841. m_rgnode[m_cnode].indent = 0;
  1842. m_rgnode[m_cnode].dwDownload = m_dwDownloadDef;
  1843. m_cnode++;
  1844. qsort(m_rgnode, m_cnode, sizeof(FLDRNODE), GroupCompare);
  1845. ZeroMemory(&lvi, sizeof(LV_ITEM));
  1846. lvi.iItem = _GetFolderIndex(pFolder->idFolder);
  1847. Assert(lvi.iItem != -1);
  1848. ListView_InsertItem(m_hwndList, &lvi);
  1849. if (m_cnode == 1)
  1850. m_pEmptyList->Hide();
  1851. return(S_OK);
  1852. }
  1853. int CAccountView::_GetFolderIndex(FOLDERID id)
  1854. {
  1855. int i;
  1856. FLDRNODE *pnode;
  1857. for (i = 0, pnode = m_rgnode; (DWORD)i < m_cnode; i++, pnode++)
  1858. {
  1859. if (id == pnode->id)
  1860. break;
  1861. }
  1862. if ((DWORD)i == m_cnode)
  1863. i = -1;
  1864. return(i);
  1865. }
  1866. HRESULT CAccountView::_UpdateFolder(LPFOLDERINFO pFolder1, LPFOLDERINFO pFolder2)
  1867. {
  1868. HRESULT hr;
  1869. int iItem;
  1870. // Visibility change (FOLDER_SUBSCRIBED or FOLDER_HIDDEN)
  1871. if (ISFLAGSET(pFolder1->dwFlags, FOLDER_SUBSCRIBED) != ISFLAGSET(pFolder2->dwFlags, FOLDER_SUBSCRIBED) ||
  1872. ISFLAGSET(pFolder1->dwFlags, FOLDER_HIDDEN) != ISFLAGSET(pFolder2->dwFlags, FOLDER_HIDDEN))
  1873. {
  1874. if (ISFLAGSET(pFolder2->dwFlags, FOLDER_SUBSCRIBED) && ISFLAGCLEAR(pFolder2->dwFlags, FOLDER_HIDDEN))
  1875. {
  1876. hr = _InsertFolder(pFolder2);
  1877. }
  1878. else
  1879. {
  1880. hr = _DeleteFolder(pFolder2);
  1881. }
  1882. return(hr);
  1883. }
  1884. // Moved or renamed
  1885. if (pFolder1->idParent != pFolder2->idParent ||
  1886. 0 != lstrcmpi(pFolder1->pszName, pFolder2->pszName))
  1887. {
  1888. Assert(m_ftType != FOLDER_NEWS);
  1889. hr = _DeleteFolder(pFolder1);
  1890. hr = _InsertFolder(pFolder2);
  1891. return(hr);
  1892. }
  1893. // State change
  1894. if (pFolder1->cUnread != pFolder2->cUnread ||
  1895. pFolder1->cMessages != pFolder2->cMessages ||
  1896. (pFolder1->dwFlags & FOLDER_SYNCMASK) != (pFolder2->dwFlags & FOLDER_SYNCMASK) ||
  1897. 0 != lstrcmp(pFolder1->pszName, pFolder2->pszName) ||
  1898. // news only
  1899. (pFolder1->tyFolder == FOLDER_NEWS &&
  1900. (pFolder1->dwServerCount != pFolder2->dwServerCount ||
  1901. pFolder1->dwServerHigh != pFolder2->dwServerHigh ||
  1902. pFolder1->dwServerLow != pFolder2->dwServerLow)))
  1903. {
  1904. iItem = _GetFolderIndex(pFolder1->idFolder);
  1905. if (iItem != -1)
  1906. ListView_RedrawItems(m_hwndList, iItem, iItem);
  1907. }
  1908. return(S_OK);
  1909. }
  1910. int CAccountView::_GetSubFolderCount(int index)
  1911. {
  1912. DWORD indent;
  1913. int indexT;
  1914. Assert((DWORD)index < m_cnode);
  1915. indent = m_rgnode[index].indent;
  1916. index++;
  1917. indexT = index;
  1918. while ((DWORD)index < m_cnode)
  1919. {
  1920. if (m_rgnode[index].indent <= indent)
  1921. break;
  1922. index++;
  1923. }
  1924. return(index - indexT);
  1925. }
  1926. HRESULT CAccountView::_DeleteFolder(LPFOLDERINFO pFolder)
  1927. {
  1928. HRESULT hr;
  1929. int iItem, cSub;
  1930. iItem = _GetFolderIndex(pFolder->idFolder);
  1931. if (iItem == -1)
  1932. return(S_OK);
  1933. SetWindowRedraw(m_hwndList, FALSE);
  1934. cSub = _GetSubFolderCount(iItem);
  1935. if ((DWORD)(iItem + cSub) < (m_cnode - 1))
  1936. MoveMemory(&m_rgnode[iItem], &m_rgnode[iItem + cSub + 1], (m_cnode - (iItem + cSub + 1)) * sizeof(FLDRNODE));
  1937. m_cnode -= cSub + 1;
  1938. while (cSub >= 0)
  1939. {
  1940. ListView_DeleteItem(m_hwndList, iItem + cSub);
  1941. cSub--;
  1942. }
  1943. if (m_cnode == 0)
  1944. m_pEmptyList->Show(m_hwndList, m_ftType == FOLDER_NEWS ? (LPSTR)idsEmptyNewsAcct : (LPSTR)idsEmptyMailAcct);
  1945. SetWindowRedraw(m_hwndList, TRUE);
  1946. UpdateWindow(m_hwndList);
  1947. return(S_OK);
  1948. }
  1949. HRESULT CAccountView::_HandleAccountRename(LPFOLDERINFO pFolder)
  1950. {
  1951. char sz[CCHMAX_STRINGRES];
  1952. HDC hdc;
  1953. SIZE size;
  1954. HFONT hfontBold, hfontOld;
  1955. Assert(m_pszMajor != NULL);
  1956. Assert(pFolder != NULL);
  1957. AthLoadString(idsSyncManager, sz, ARRAYSIZE(sz));
  1958. wnsprintf(m_pszMajor, CCHMAX_STRINGRES, sz, pFolder->pszName);
  1959. hfontBold = HGetCharSetFont(FNT_SYS_ICON_BOLD, NULL);
  1960. hdc = GetDC(m_hwnd);
  1961. hfontOld = (HFONT)SelectObject(hdc, (HGDIOBJ)hfontBold);
  1962. GetTextExtentPoint32(hdc, m_pszMajor, lstrlen(m_pszMajor), &size);
  1963. m_rcMajor.left = SUBSCRIBE_BORDER;
  1964. m_rcMajor.top = SUBSCRIBE_BORDER;
  1965. m_rcMajor.right = m_rcMajor.left + size.cx;
  1966. m_rcMajor.bottom = m_rcMajor.top + size.cy;
  1967. SelectObject(hdc, hfontOld);
  1968. ReleaseDC(m_hwnd, hdc);
  1969. InvalidateRect(m_hwnd, NULL, FALSE);
  1970. UpdateWindow(m_hwnd);
  1971. return(S_OK);
  1972. }
  1973. STDMETHODIMP CAccountView::OnTransaction(HTRANSACTION hTransaction, DWORD_PTR dwCookie, IDatabase *pDB)
  1974. {
  1975. BOOL fMatch;
  1976. DWORD i;
  1977. FOLDERINFO Folder1={0};
  1978. FOLDERINFO Folder2={0};
  1979. FOLDERINFO Server;
  1980. ORDINALLIST Ordinals;
  1981. TRANSACTIONTYPE tyTransaction;
  1982. INDEXORDINAL iIndex;
  1983. HRESULT hr;
  1984. while (hTransaction)
  1985. {
  1986. hr = pDB->GetTransaction(&hTransaction, &tyTransaction, &Folder1, &Folder2, &iIndex, &Ordinals);
  1987. if (FAILED(hr))
  1988. break;
  1989. if (Folder1.idFolder == m_idFolder)
  1990. {
  1991. if (TRANSACTION_UPDATE == tyTransaction &&
  1992. 0 != lstrcmp(Folder1.pszName, Folder2.pszName))
  1993. {
  1994. hr = _HandleAccountRename(&Folder2);
  1995. }
  1996. }
  1997. else if (Folder1.tyFolder == m_ftType && 0 == (Folder1.dwFlags & FOLDER_SERVER))
  1998. {
  1999. fMatch = FALSE;
  2000. if (m_ftType == FOLDER_LOCAL)
  2001. {
  2002. if (Folder1.tyFolder == FOLDER_LOCAL)
  2003. fMatch = TRUE;
  2004. }
  2005. else
  2006. {
  2007. hr = GetFolderServer(Folder1.idParent, &Server);
  2008. if (SUCCEEDED(hr))
  2009. {
  2010. fMatch = (Server.idFolder == m_idFolder);
  2011. g_pStore->FreeRecord(&Server);
  2012. }
  2013. }
  2014. if (fMatch)
  2015. {
  2016. // Insert (new Folder notification)
  2017. if (TRANSACTION_INSERT == tyTransaction)
  2018. {
  2019. hr = _InsertFolder(&Folder1);
  2020. }
  2021. // Update
  2022. else if (TRANSACTION_UPDATE == tyTransaction)
  2023. {
  2024. hr = _UpdateFolder(&Folder1, &Folder2);
  2025. }
  2026. // Delete
  2027. else if (TRANSACTION_DELETE == tyTransaction)
  2028. {
  2029. hr = _DeleteFolder(&Folder1);
  2030. }
  2031. }
  2032. }
  2033. }
  2034. g_pStore->FreeRecord(&Folder1);
  2035. g_pStore->FreeRecord(&Folder2);
  2036. return(S_OK);
  2037. }
  2038. HRESULT CAccountView::_ToggleDownload(int iItem)
  2039. {
  2040. FLDRNODE *pnode;
  2041. FOLDERINFO info;
  2042. HRESULT hr;
  2043. pnode = _NodeFromIndex(iItem);
  2044. Assert(pnode != NULL);
  2045. hr = g_pStore->GetFolderInfo(pnode->id, &info);
  2046. if (SUCCEEDED(hr))
  2047. {
  2048. if (!!(info.dwFlags & FOLDER_SUBSCRIBED))
  2049. {
  2050. if (!!(info.dwFlags & FOLDER_SYNCMASK))
  2051. {
  2052. pnode->dwDownload = (info.dwFlags & FOLDER_SYNCMASK);
  2053. info.dwFlags &= ~FOLDER_SYNCMASK;
  2054. }
  2055. else
  2056. {
  2057. Assert(0 == (pnode->dwDownload & ~FOLDER_SYNCMASK));
  2058. info.dwFlags |= pnode->dwDownload;
  2059. }
  2060. hr = g_pStore->UpdateRecord(&info);
  2061. }
  2062. g_pStore->FreeRecord(&info);
  2063. }
  2064. return(S_OK);
  2065. }
  2066. HRESULT CAccountView::_MarkForDownload(DWORD nCmdID)
  2067. {
  2068. int iSel;
  2069. FLDRFLAGS flag;
  2070. FOLDERINFO info;
  2071. HRESULT hr;
  2072. FLDRNODE *pnode;
  2073. switch (nCmdID)
  2074. {
  2075. case ID_MARK_RETRIEVE_FLD_NEW_HDRS:
  2076. flag = FOLDER_DOWNLOADHEADERS;
  2077. break;
  2078. case ID_MARK_RETRIEVE_FLD_NEW_MSGS:
  2079. flag = FOLDER_DOWNLOADNEW;
  2080. break;
  2081. case ID_MARK_RETRIEVE_FLD_ALL_MSGS:
  2082. flag = FOLDER_DOWNLOADALL;
  2083. break;
  2084. case ID_UNMARK_RETRIEVE_FLD:
  2085. flag = 0;
  2086. break;
  2087. default:
  2088. Assert(FALSE);
  2089. break;
  2090. }
  2091. iSel = -1;
  2092. while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
  2093. {
  2094. pnode = _NodeFromIndex(iSel);
  2095. hr = g_pStore->GetFolderInfo(pnode->id, &info);
  2096. if (SUCCEEDED(hr))
  2097. {
  2098. if (!!(info.dwFlags & FOLDER_SUBSCRIBED) &&
  2099. (info.dwFlags & FOLDER_SYNCMASK) != flag)
  2100. {
  2101. if (flag == 0)
  2102. pnode->dwDownload = (info.dwFlags & FOLDER_SYNCMASK);
  2103. info.dwFlags &= ~FOLDER_SYNCMASK;
  2104. if (flag != 0)
  2105. info.dwFlags |= flag;
  2106. hr = g_pStore->UpdateRecord(&info);
  2107. }
  2108. g_pStore->FreeRecord(&info);
  2109. }
  2110. }
  2111. return(S_OK);
  2112. }
  2113. HRESULT CAccountView::_Subscribe(BOOL fSubscribe)
  2114. {
  2115. FOLDERID *pid;
  2116. int iSel, cSel, cid;
  2117. cSel = ListView_GetSelectedCount(m_hwndList);
  2118. if (cSel > 0)
  2119. {
  2120. if (!MemAlloc((void **)&pid, cSel * sizeof(FOLDERID)))
  2121. return(E_OUTOFMEMORY);
  2122. cid = 0;
  2123. iSel = -1;
  2124. while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
  2125. {
  2126. Assert(cid < cSel);
  2127. pid[cid] = _IdFromIndex(iSel);
  2128. cid++;
  2129. }
  2130. MenuUtil_OnSubscribeGroups(m_hwndOwner, pid, cid, fSubscribe);
  2131. MemFree(pid);
  2132. }
  2133. return(S_OK);
  2134. }
  2135. HRESULT CAccountView::_MarkAllRead()
  2136. {
  2137. int iSel;
  2138. IMessageFolder *pFolder;
  2139. ADJUSTFLAGS flags;
  2140. FOLDERID idFolder;
  2141. CStoreCB *pCB;
  2142. HRESULT hr;
  2143. pCB = new CStoreCB;
  2144. if (pCB == NULL)
  2145. return(E_OUTOFMEMORY);
  2146. hr = pCB->Initialize(m_hwndOwner, MAKEINTRESOURCE(idsSettingMessageFlags), FALSE);
  2147. if (SUCCEEDED(hr))
  2148. {
  2149. flags.dwAdd = ARF_READ;
  2150. flags.dwRemove = 0;
  2151. iSel = -1;
  2152. while (-1 != (iSel = ListView_GetNextItem(m_hwndList, iSel, LVNI_SELECTED | LVNI_ALL)))
  2153. {
  2154. idFolder = _IdFromIndex(iSel);
  2155. if (SUCCEEDED(g_pStore->OpenFolder(idFolder, NULL, NOFLAGS, &pFolder)))
  2156. {
  2157. hr = pFolder->SetMessageFlags(NULL, &flags, NULL, (IStoreCallback *)pCB);
  2158. if (hr == E_PENDING)
  2159. {
  2160. hr = pCB->Block();
  2161. pCB->Reset();
  2162. }
  2163. pFolder->Release();
  2164. }
  2165. if (FAILED(hr))
  2166. break;
  2167. }
  2168. pCB->Close();
  2169. }
  2170. pCB->Release();
  2171. return(S_OK);
  2172. }