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.

4374 lines
104 KiB

  1. // FolderListView.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #define __FILE_ID__ 22
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. #include <dlgprnt2.cpp>
  11. extern CClientConsoleApp theApp;
  12. //
  13. // Static members:
  14. //
  15. CFolderListView * CFolderListView::m_psCurrentViewBeingSorted = NULL;
  16. CImageList CFolderListView::m_sImgListDocIcon;
  17. CImageList CFolderListView::m_sReportIcons;
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CFolderListView
  20. IMPLEMENT_DYNCREATE(CFolderListView, CListView)
  21. BEGIN_MESSAGE_MAP(CFolderListView, CListView)
  22. //{{AFX_MSG_MAP(CFolderListView)
  23. ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
  24. ON_WM_SETCURSOR()
  25. ON_MESSAGE (WM_FOLDER_REFRESH_ENDED, OnFolderRefreshEnded)
  26. ON_MESSAGE (WM_FOLDER_ADD_CHUNK, OnFolderAddChunk)
  27. ON_MESSAGE (WM_FOLDER_INVALIDATE, OnFolderInvalidate)
  28. ON_NOTIFY_REFLECT(NM_RCLICK, OnItemRightClick)
  29. ON_WM_CONTEXTMENU()
  30. ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemChanged)
  31. ON_WM_SETCURSOR()
  32. ON_WM_CHAR()
  33. //}}AFX_MSG_MAP
  34. ON_UPDATE_COMMAND_UI(ID_SELECT_ALL, OnUpdateSelectAll)
  35. ON_UPDATE_COMMAND_UI(ID_SELECT_NONE, OnUpdateSelectNone)
  36. ON_UPDATE_COMMAND_UI(ID_SELECT_INVERT, OnUpdateSelectInvert)
  37. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_VIEW, OnUpdateFolderItemView)
  38. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_PRINT, OnUpdateFolderItemPrint)
  39. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_COPY, OnUpdateFolderItemCopy)
  40. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_MAIL_TO, OnUpdateFolderItemSendMail)
  41. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_PROPERTIES, OnUpdateFolderItemProperties)
  42. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_DELETE, OnUpdateFolderItemDelete)
  43. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_PAUSE, OnUpdateFolderItemPause)
  44. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_RESUME, OnUpdateFolderItemResume)
  45. ON_UPDATE_COMMAND_UI(ID_FOLDER_ITEM_RESTART, OnUpdateFolderItemRestart)
  46. ON_COMMAND(ID_SELECT_ALL, OnSelectAll)
  47. ON_COMMAND(ID_SELECT_NONE, OnSelectNone)
  48. ON_COMMAND(ID_SELECT_INVERT, OnSelectInvert)
  49. ON_COMMAND(ID_FOLDER_ITEM_VIEW, OnFolderItemView)
  50. ON_COMMAND(ID_FOLDER_ITEM_PRINT, OnFolderItemPrint)
  51. ON_COMMAND(ID_FOLDER_ITEM_COPY, OnFolderItemCopy)
  52. ON_COMMAND(ID_FOLDER_ITEM_MAIL_TO, OnFolderItemMail)
  53. ON_COMMAND(ID_FOLDER_ITEM_PRINT, OnFolderItemPrint)
  54. ON_COMMAND(ID_FOLDER_ITEM_PROPERTIES, OnFolderItemProperties)
  55. ON_COMMAND(ID_FOLDER_ITEM_DELETE, OnFolderItemDelete)
  56. ON_COMMAND(ID_FOLDER_ITEM_PAUSE, OnFolderItemPause)
  57. ON_COMMAND(ID_FOLDER_ITEM_RESUME, OnFolderItemResume)
  58. ON_COMMAND(ID_FOLDER_ITEM_RESTART, OnFolderItemRestart)
  59. ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblClk)
  60. END_MESSAGE_MAP()
  61. BOOL CFolderListView::PreCreateWindow(CREATESTRUCT& cs)
  62. {
  63. return CListView::PreCreateWindow(cs);
  64. }
  65. BOOL
  66. CFolderListView::OnSetCursor(
  67. CWnd* pWnd,
  68. UINT nHitTest,
  69. UINT message
  70. )
  71. {
  72. if (m_bInMultiItemsOperation || m_bSorting)
  73. {
  74. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
  75. return TRUE;
  76. }
  77. CClientConsoleDoc* pDoc = GetDocument();
  78. if (pDoc && pDoc->IsFolderRefreshing(m_Type))
  79. {
  80. ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_APPSTARTING));
  81. return TRUE;
  82. }
  83. else
  84. {
  85. return CView::OnSetCursor(pWnd, nHitTest, message);
  86. }
  87. } // CFolderListView::OnSetCursor
  88. BOOL
  89. CFolderListView::IsSelected (
  90. int iItem
  91. )
  92. /*++
  93. Routine name : CFolderListView::IsSelected
  94. Routine description:
  95. Checks if an item is selected in the list
  96. Author:
  97. Eran Yariv (EranY), Jan, 2000
  98. Arguments:
  99. iItem [in] - Item index
  100. Return Value:
  101. TRUE if item is selected in the list, FALSE otherwise.
  102. --*/
  103. {
  104. BOOL bRes = FALSE;
  105. DBG_ENTER(TEXT("CFolderListView::IsSelected"), bRes);
  106. CListCtrl &refCtrl = GetListCtrl();
  107. ASSERTION (refCtrl.GetItemCount() > iItem);
  108. DWORD dwState = refCtrl.GetItemState (iItem , LVIS_SELECTED);
  109. if (LVIS_SELECTED & dwState)
  110. {
  111. bRes = TRUE;
  112. }
  113. return bRes;
  114. }
  115. void
  116. CFolderListView::Select (
  117. int iItem,
  118. BOOL bSelect
  119. )
  120. /*++
  121. Routine name : CFolderListView::Select
  122. Routine description:
  123. Selects / unselects an item in the list
  124. Author:
  125. Eran Yariv (EranY), Jan, 2000
  126. Arguments:
  127. iItem [in] - Item index
  128. bSelect [in] - TRUE if select, FALSE unselect
  129. Return Value:
  130. None.
  131. --*/
  132. {
  133. DBG_ENTER(TEXT("CFolderListView::Select"), TEXT("%d"), bSelect);
  134. CListCtrl &refCtrl = GetListCtrl();
  135. ASSERTION (refCtrl.GetItemCount() > iItem);
  136. refCtrl.SetItemState (iItem,
  137. bSelect ? (LVIS_SELECTED | LVIS_FOCUSED) : 0,
  138. LVIS_SELECTED | LVIS_FOCUSED);
  139. }
  140. void
  141. CFolderListView::OnSelectAll ()
  142. /*++
  143. Routine name : CFolderListView::OnSelectAll
  144. Routine description:
  145. Select all list items
  146. Author:
  147. Eran Yariv (EranY), Jan, 2000
  148. Arguments:
  149. Return Value:
  150. None.
  151. --*/
  152. {
  153. DBG_ENTER(TEXT("CFolderListView::OnSelectAll"),
  154. TEXT("Type=%d"),
  155. m_Type);
  156. LV_ITEM lvItem;
  157. CListCtrl &refCtrl = GetListCtrl();
  158. ASSERTION (refCtrl.GetItemCount() > refCtrl.GetSelectedCount());
  159. lvItem.mask = LVIF_STATE;
  160. lvItem.iItem = -1; // Specifies "All items"
  161. lvItem.iSubItem = 0;
  162. lvItem.state = LVIS_SELECTED;
  163. lvItem.stateMask= LVIS_SELECTED;
  164. m_bInMultiItemsOperation = TRUE;
  165. refCtrl.SetItemState(-1, &lvItem);
  166. m_bInMultiItemsOperation = FALSE;
  167. RecalcPossibleOperations();
  168. } // CFolderListView::OnSelectAll
  169. void
  170. CFolderListView::OnSelectNone ()
  171. /*++
  172. Routine name : CFolderListView::OnSelectNone
  173. Routine description:
  174. Unselect all list items
  175. Author:
  176. Eran Yariv (EranY), Jan, 2000
  177. Arguments:
  178. Return Value:
  179. None.
  180. --*/
  181. {
  182. DBG_ENTER(TEXT("CFolderListView::OnSelectNone"),
  183. TEXT("Type=%d"),
  184. m_Type);
  185. LV_ITEM lvItem;
  186. CListCtrl &refCtrl = GetListCtrl();
  187. lvItem.mask = LVIF_STATE;
  188. lvItem.iItem = -1; // Specifies "All items"
  189. lvItem.iSubItem = 0;
  190. lvItem.state = 0;
  191. lvItem.stateMask= LVIS_SELECTED;
  192. m_bInMultiItemsOperation = TRUE;
  193. refCtrl.SetItemState(-1, &lvItem);
  194. m_bInMultiItemsOperation = FALSE;
  195. RecalcPossibleOperations();
  196. } // CFolderListView::OnSelectNone
  197. void
  198. CFolderListView::OnSelectInvert ()
  199. /*++
  200. Routine name : CFolderListView::OnSelectInvert
  201. Routine description:
  202. Invert list items selection
  203. Author:
  204. Eran Yariv (EranY), Jan, 2000
  205. Arguments:
  206. Return Value:
  207. None.
  208. --*/
  209. {
  210. DBG_ENTER(TEXT("CFolderListView::OnSelectInvert"),
  211. TEXT("Type=%d"),
  212. m_Type);
  213. CListCtrl &refCtrl = GetListCtrl();
  214. DWORD dwItemsCount = refCtrl.GetItemCount();
  215. m_bInMultiItemsOperation = TRUE;
  216. for (DWORD dw = 0; dw < dwItemsCount; dw++)
  217. {
  218. Select (dw, !IsSelected (dw));
  219. }
  220. m_bInMultiItemsOperation = FALSE;
  221. RecalcPossibleOperations();
  222. } // CFolderListView::OnSelectInvert
  223. void CFolderListView::OnDraw(CDC* pDC)
  224. {
  225. CListView::OnDraw (pDC);
  226. }
  227. void CFolderListView::OnInitialUpdate()
  228. {
  229. //
  230. // Refresh the image list (only if they are empty)
  231. //
  232. RefreshImageLists(FALSE);
  233. CListView::OnInitialUpdate();
  234. }
  235. /////////////////////////////////////////////////////////////////////////////
  236. // CFolderListView diagnostics
  237. #ifdef _DEBUG
  238. void CFolderListView::AssertValid() const
  239. {
  240. CListView::AssertValid();
  241. }
  242. void CFolderListView::Dump(CDumpContext& dc) const
  243. {
  244. CListView::Dump(dc);
  245. }
  246. CClientConsoleDoc* CFolderListView::GetDocument() // non-debug version is inline
  247. {
  248. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CClientConsoleDoc)));
  249. return (CClientConsoleDoc*)m_pDocument;
  250. }
  251. #endif //_DEBUG
  252. /////////////////////////////////////////////////////////////////////////////
  253. // CFolderListView message handlers
  254. DWORD
  255. CFolderListView::InitColumns (
  256. int *pColumnsUsed,
  257. DWORD dwDefaultColNum
  258. )
  259. /*++
  260. Routine name : CFolderListView::InitColumns
  261. Routine description:
  262. Inits the columns of the view.
  263. Author:
  264. Eran Yariv (EranY), Jan, 2000
  265. Arguments:
  266. pColumnsUsed [in] - Pointer to the list of ids to place in the columns.
  267. Must be a statically allocated list.
  268. dwDefaultColNum [in] - default column number
  269. Return Value:
  270. Standard Win32 error code
  271. --*/
  272. {
  273. DWORD dwRes = ERROR_SUCCESS;
  274. DBG_ENTER(TEXT("CFolderListView::InitColumns"), dwRes);
  275. if (m_bColumnsInitialized)
  276. {
  277. return dwRes;
  278. }
  279. m_dwDefaultColNum = dwDefaultColNum;
  280. //
  281. // Count the number of columns provided
  282. //
  283. CountColumns (pColumnsUsed);
  284. int nItemIndex, nRes;
  285. CString cstrColumnText;
  286. DWORD dwCount = GetLogicalColumnsCount();
  287. for (DWORD dw = 0; dw < dwCount; ++dw)
  288. {
  289. nItemIndex = ItemIndexFromLogicalColumnIndex(dw);
  290. if(IsItemIcon(nItemIndex))
  291. {
  292. //
  293. // Init icon column - insert an empty string
  294. //
  295. nRes = GetListCtrl().InsertColumn (dw, TEXT(""), LVCFMT_LEFT);
  296. if (nRes < 0)
  297. {
  298. dwRes = ERROR_GEN_FAILURE;
  299. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::InsertColumn"), dwRes);
  300. return dwRes;
  301. }
  302. //
  303. // Set the header control's bitmap
  304. //
  305. CHeaderCtrl *pHeader = GetListCtrl().GetHeaderCtrl();
  306. HDITEM hdItem;
  307. hdItem.mask = HDI_IMAGE | HDI_FORMAT;
  308. hdItem.fmt = HDF_LEFT | HDF_IMAGE;
  309. hdItem.iImage = 0; // Use first (and only) image from image list
  310. if (!pHeader->SetItem (dw, &hdItem))
  311. {
  312. dwRes = ERROR_GEN_FAILURE;
  313. CALL_FAIL (WINDOW_ERR, TEXT("CHeaderCtrl::SetItem"), dwRes);
  314. return dwRes;
  315. }
  316. }
  317. else
  318. {
  319. //
  320. // init string column
  321. //
  322. dwRes = GetColumnHeaderString (cstrColumnText, nItemIndex);
  323. if (ERROR_SUCCESS != dwRes)
  324. { return dwRes; }
  325. nRes = GetListCtrl().InsertColumn (dw,
  326. cstrColumnText,
  327. GetColumnHeaderAlignment (nItemIndex));
  328. }
  329. if (nRes < 0)
  330. {
  331. dwRes = ERROR_GEN_FAILURE;
  332. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::InsertColumn"), dwRes);
  333. return dwRes;
  334. }
  335. }
  336. m_bColumnsInitialized = TRUE;
  337. return dwRes;
  338. } // CFolderListView::InitColumns
  339. void
  340. CFolderListView::AutoFitColumns ()
  341. /*++
  342. Routine name : CFolderListView::AutoFitColumns
  343. Routine description:
  344. Sets the column width to fit the contents of the column and the header
  345. Author:
  346. Eran Yariv (EranY), Jan, 2000
  347. Arguments:
  348. Return Value:
  349. None.
  350. --*/
  351. {
  352. DBG_ENTER(TEXT("CFolderListView::AutoFitColumns"));
  353. CHeaderCtrl *pHeader = GetListCtrl().GetHeaderCtrl ();
  354. ASSERTION (pHeader);
  355. DWORD dwCount = pHeader->GetItemCount();
  356. for (DWORD dwCol = 0; dwCol <= dwCount; dwCol++)
  357. {
  358. GetListCtrl().SetColumnWidth (dwCol, LVSCW_AUTOSIZE);
  359. int wc1 = GetListCtrl().GetColumnWidth (dwCol);
  360. GetListCtrl().SetColumnWidth (dwCol, LVSCW_AUTOSIZE_USEHEADER);
  361. int wc2 = GetListCtrl().GetColumnWidth (dwCol);
  362. int wc = max(20,max(wc1,wc2));
  363. GetListCtrl().SetColumnWidth (dwCol, wc);
  364. }
  365. } // CFolderListView::AutoFitColumns
  366. DWORD
  367. CFolderListView::UpdateLineTextAndIcon (
  368. DWORD dwLineIndex,
  369. CViewRow &row
  370. )
  371. /*++
  372. Routine name : CFolderListView::UpdateLineTextAndIcon
  373. Routine description:
  374. Updates the icon and text in each column of a line item in the list
  375. Author:
  376. Eran Yariv (EranY), Feb, 2000
  377. Arguments:
  378. dwLineIndex [in] - Line index
  379. row [in] - Display information
  380. Return Value:
  381. Standard Win32 error code
  382. --*/
  383. {
  384. DWORD dwRes = ERROR_SUCCESS;
  385. DBG_ENTER(TEXT("CFolderListView::UpdateLineTextAndIcon"), dwRes);
  386. //
  387. // Start by setting the icon
  388. //
  389. LVITEM lvItem = {0};
  390. lvItem.mask = LVIF_IMAGE;
  391. lvItem.iItem = dwLineIndex;
  392. lvItem.iSubItem = 0;
  393. lvItem.state = 0;
  394. lvItem.stateMask = 0;
  395. lvItem.pszText = NULL;
  396. lvItem.cchTextMax = 0;
  397. lvItem.lParam = NULL;
  398. lvItem.iImage = row.GetIcon();
  399. lvItem.iIndent = 0;
  400. CListCtrl &refCtrl = GetListCtrl();
  401. if (!refCtrl.SetItem (&lvItem))
  402. {
  403. dwRes = ERROR_GEN_FAILURE;
  404. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::SetItem"), dwRes);
  405. return dwRes;
  406. }
  407. //
  408. // Set columns text
  409. //
  410. DWORD dwItemIndex;
  411. DWORD dwCount = GetLogicalColumnsCount();
  412. for (DWORD dwCol = 0; dwCol < dwCount; ++dwCol)
  413. {
  414. dwItemIndex = ItemIndexFromLogicalColumnIndex (dwCol);
  415. if(IsItemIcon(dwItemIndex))
  416. {
  417. continue;
  418. }
  419. //
  420. // Get text from column
  421. //
  422. const CString &cstrColumn = row.GetItemString (dwItemIndex);
  423. //
  424. // Set the text in the control
  425. //
  426. if (!refCtrl.SetItemText (dwLineIndex, dwCol, cstrColumn))
  427. {
  428. dwRes = ERROR_GEN_FAILURE;
  429. CALL_FAIL (WINDOW_ERR, TEXT("ListCtrl::SetItemText"), dwRes);
  430. return dwRes;
  431. }
  432. }
  433. ASSERTION (ERROR_SUCCESS == dwRes);
  434. return dwRes;
  435. } // CFolderListView::UpdateLineTextAndIcon
  436. DWORD
  437. CFolderListView::AddItem (
  438. DWORD dwLineIndex,
  439. CViewRow &row,
  440. LPARAM lparamItemData,
  441. PINT pintItemIndex
  442. )
  443. /*++
  444. Routine name : CFolderListView::AddItem
  445. Routine description:
  446. Adds an item to the list
  447. Author:
  448. Eran Yariv (EranY), Jan, 2000
  449. Arguments:
  450. dwLineIndex [in] - Index of addition
  451. row [in] - Row of item view information
  452. lparamItemData [in] - Item associated data
  453. pintItemIndex [out] - Item index in the list
  454. Return Value:
  455. Standard Win32 error code
  456. --*/
  457. {
  458. DWORD dwRes = ERROR_SUCCESS;
  459. DBG_ENTER(TEXT("CFolderListView::AddItem"), dwRes, TEXT("%ld"), dwLineIndex);
  460. //
  461. // Insert the item: only state, indention and lParam are set.
  462. //
  463. LVITEM lvItem = {0};
  464. lvItem.mask = LVIF_PARAM | LVIF_STATE | LVIF_INDENT;
  465. lvItem.iItem = dwLineIndex;
  466. lvItem.iSubItem = 0;
  467. lvItem.state = 0;
  468. lvItem.stateMask = 0;
  469. lvItem.pszText = NULL;
  470. lvItem.cchTextMax = 0;
  471. lvItem.lParam = lparamItemData;
  472. lvItem.iImage = 0;
  473. lvItem.iIndent = 0;
  474. *pintItemIndex = ListView_InsertItem (GetListCtrl().m_hWnd, &lvItem);
  475. if (-1 == *pintItemIndex)
  476. {
  477. dwRes = ERROR_GEN_FAILURE;
  478. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::InsertItem"), dwRes);
  479. return dwRes;
  480. }
  481. dwRes = UpdateLineTextAndIcon (*pintItemIndex, row);
  482. if (ERROR_SUCCESS != dwRes)
  483. {
  484. CALL_FAIL (GENERAL_ERR, TEXT("UpdateLineTextAndIcon"), dwRes);
  485. return dwRes;
  486. }
  487. ASSERTION (ERROR_SUCCESS == dwRes);
  488. return dwRes;
  489. } // CFolderListView::AddItem
  490. LRESULT
  491. CFolderListView::OnFolderAddChunk(
  492. WPARAM wParam, // Error code
  493. LPARAM lParam // MSGS_MAP pointer
  494. )
  495. /*++
  496. Routine name : CFolderListView::OnFolderAddChunk
  497. Routine description:
  498. Called when a background folder thread brings a chunk of messages
  499. Arguments:
  500. wParam [in] - Thread error code
  501. lParam [in] - Pointer to MSGS_MAP.
  502. Return Value:
  503. Standard result code
  504. --*/
  505. {
  506. DBG_ENTER(TEXT("CFolderListView::OnFolderAddChunk"));
  507. DWORD dwRes = (DWORD) wParam;
  508. CObject* pObj = (CObject*)lParam;
  509. if (ERROR_SUCCESS == dwRes)
  510. {
  511. OnUpdate (NULL, UPDATE_HINT_ADD_CHUNK, pObj);
  512. }
  513. else
  514. {
  515. PopupError (dwRes);
  516. }
  517. return 0;
  518. }
  519. LRESULT
  520. CFolderListView::OnFolderRefreshEnded (
  521. WPARAM wParam, // Error code
  522. LPARAM lParam // CFolder pointer
  523. )
  524. /*++
  525. Routine name : CFolderListView::OnFolderRefreshEnded
  526. Routine description:
  527. Called when a background folder thread finishes its work.
  528. Author:
  529. Eran Yariv (EranY), Jan, 2000
  530. Arguments:
  531. wParam [in] - Thread error code
  532. lParam [in] - Pointer to CFolder that started the thread.
  533. Return Value:
  534. Standard result code
  535. --*/
  536. {
  537. DBG_ENTER(TEXT("CFolderListView::OnFolderRefreshEnded"));
  538. DWORD dwRes = (DWORD) wParam;
  539. CFolder *pFolder = (CFolder *) lParam;
  540. if (ERROR_SUCCESS == dwRes)
  541. {
  542. CListCtrl &refCtrl = GetListCtrl();
  543. m_HeaderCtrl.SetListControl (refCtrl.m_hWnd);
  544. DoSort();
  545. if(refCtrl.GetItemCount() > 0)
  546. {
  547. int iIndex = refCtrl.GetNextItem (-1, LVNI_SELECTED);
  548. if (-1 == iIndex)
  549. {
  550. //
  551. // If there is no selection, set focus on the first item.
  552. //
  553. refCtrl.SetItemState (0, LVIS_FOCUSED, LVIS_FOCUSED);
  554. }
  555. else
  556. {
  557. //
  558. // After sort, ensure the first selected item is visible
  559. //
  560. refCtrl.EnsureVisible (iIndex, FALSE);
  561. }
  562. }
  563. }
  564. else
  565. {
  566. PopupError (dwRes);
  567. }
  568. return 0;
  569. } // CFolderListView::OnFolderRefreshEnded
  570. LRESULT
  571. CFolderListView::OnFolderInvalidate (
  572. WPARAM wParam, // not in use
  573. LPARAM lParam // CFolder pointer
  574. )
  575. /*++
  576. Routine name : CFolderListView::OnFolderRefreshEnded
  577. Routine description:
  578. Called by a background folder thread in order to remove the all its fax messages.
  579. Arguments:
  580. wParam [in] - Not in use
  581. lParam [in] - Pointer to CFolder that started the thread.
  582. Return Value:
  583. Standard result code
  584. --*/
  585. {
  586. DBG_ENTER(TEXT("CFolderListView::OnFolderInvalidate"));
  587. CFolder *pFolder = (CFolder *) lParam;
  588. if(!pFolder)
  589. {
  590. ASSERTION_FAILURE;
  591. return 0;
  592. }
  593. int iIndex; // View item index
  594. CListCtrl &refCtrl = GetListCtrl();
  595. LVFINDINFO lvfi = {0};
  596. lvfi.flags = LVFI_PARAM;
  597. CFaxMsg* pMsg;
  598. MSGS_MAP &msgMap = pFolder->GetData ();
  599. pFolder->EnterData ();
  600. //
  601. // Go through the folder's message map
  602. //
  603. for (MSGS_MAP::iterator it = msgMap.begin(); it != msgMap.end(); ++it)
  604. {
  605. pMsg = (*it).second;
  606. //
  607. // Delete the fax message from the view
  608. //
  609. lvfi.lParam = (LPARAM)pMsg;
  610. iIndex = refCtrl.FindItem (&lvfi);
  611. if(-1 != iIndex)
  612. {
  613. refCtrl.DeleteItem (iIndex);
  614. }
  615. //
  616. // Delete a fax message object
  617. //
  618. SAFE_DELETE (pMsg);
  619. }
  620. msgMap.clear();
  621. pFolder->LeaveData ();
  622. RecalcPossibleOperations ();
  623. return 0;
  624. } // CFolderListView::OnFolderInvalidate
  625. /***********************************
  626. * *
  627. * Columns sort support *
  628. * *
  629. ***********************************/
  630. int
  631. CFolderListView::CompareListItems (
  632. CFaxMsg* pFaxMsg1,
  633. CFaxMsg* pFaxMsg2
  634. )
  635. /*++
  636. Routine name : CFolderListView::CompareListItems
  637. Routine description:
  638. Compares two items in the list (callback)
  639. Author:
  640. Eran Yariv (EranY), Jan, 2000
  641. Arguments:
  642. pFaxMsg1 [in] - Item 1
  643. pFaxMsg2 [in] - Item 2
  644. Return Value:
  645. -1 if item1 is smaler than item2
  646. 0 if identical
  647. +1 if item1 is bigger than item2
  648. --*/
  649. {
  650. DBG_ENTER(TEXT("CFolderListView::CompareListItems"));
  651. //
  652. // Make sure the we're sorting a valid column here
  653. //
  654. ASSERTION (m_nSortedCol >= 0);
  655. ASSERTION (m_nSortedCol <= GetLogicalColumnsCount());
  656. //
  657. // Get item index to sort by
  658. //
  659. DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (m_nSortedCol);
  660. //
  661. // Get comparison result
  662. //
  663. int iRes = m_bSortAscending ? CompareItems (pFaxMsg1, pFaxMsg2, dwItemIndex) :
  664. CompareItems (pFaxMsg2, pFaxMsg1, dwItemIndex);
  665. return iRes;
  666. }
  667. void CFolderListView::OnColumnClick(
  668. NMHDR* pNMHDR,
  669. LRESULT* pResult
  670. )
  671. /*++
  672. Routine name : CFolderListView::OnColumnClick
  673. Routine description:
  674. Handle mouse click on list header column (sort)
  675. Author:
  676. Eran Yariv (EranY), Jan, 2000
  677. Arguments:
  678. pNMHDR [in] - Header column information
  679. pResult [out] - Result
  680. Return Value:
  681. None.
  682. --*/
  683. {
  684. DBG_ENTER(TEXT("CFolderListView::OnColumnClick"),
  685. TEXT("Type=%d"),
  686. m_Type);
  687. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  688. DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (pNMListView->iSubItem);
  689. if(IsItemIcon(dwItemIndex))
  690. {
  691. //
  692. // no sort by icon
  693. //
  694. return;
  695. }
  696. if( pNMListView->iSubItem == m_nSortedCol )
  697. {
  698. m_bSortAscending = !m_bSortAscending;
  699. }
  700. else
  701. {
  702. m_bSortAscending = TRUE;
  703. }
  704. m_nSortedCol = pNMListView->iSubItem;
  705. DoSort();
  706. *pResult = 0;
  707. } // CFolderListView::OnColumnClick
  708. int
  709. CALLBACK
  710. CFolderListView::ListViewItemsCompareProc (
  711. LPARAM lParam1,
  712. LPARAM lParam2,
  713. LPARAM lParamSort
  714. )
  715. {
  716. DBG_ENTER(TEXT("CFolderListView::ListViewItemsCompareProc"));
  717. ASSERTION(m_psCurrentViewBeingSorted);
  718. ASSERTION(lParam1);
  719. ASSERTION(lParam2);
  720. CFaxMsg* pFaxMsg1 = (CFaxMsg*)lParam1;
  721. CFaxMsg* pFaxMsg2 = (CFaxMsg*)lParam2;
  722. DWORDLONG dwlId;
  723. try
  724. {
  725. dwlId = pFaxMsg1->GetId();
  726. dwlId = pFaxMsg2->GetId();
  727. }
  728. catch(...)
  729. {
  730. //
  731. // The list control has invalid item
  732. //
  733. VERBOSE (DBG_MSG, TEXT("List control has invalid item"));
  734. ASSERTION(FALSE);
  735. return 0;
  736. }
  737. return m_psCurrentViewBeingSorted->CompareListItems (pFaxMsg1, pFaxMsg2);
  738. }
  739. DWORD
  740. CFolderListView::RefreshImageLists (
  741. BOOL bForce
  742. )
  743. /*++
  744. Routine name : CFolderListView::RefreshImageLists
  745. Routine description:
  746. Loads the static list of images (icons) for the list control
  747. Author:
  748. Eran Yariv (EranY), Jan, 2000
  749. Arguments:
  750. bForce - [in] If TRUE, any existing image list is destroyed and replaced with new ones.
  751. If FALSE, existing image lists remain unchanged.
  752. Return Value:
  753. Standard Win32 error code
  754. --*/
  755. {
  756. DWORD dwRes = ERROR_SUCCESS;
  757. DBG_ENTER(TEXT("CFolderListView::RefreshImageLists"), dwRes);
  758. CListCtrl& refCtrl = GetListCtrl();
  759. if (bForce || (NULL == m_sReportIcons.m_hImageList))
  760. {
  761. //
  762. // Load image list of list view icons - 256 colors, pixel at 0,0 is mapped to background color during load
  763. //
  764. if(m_sReportIcons.m_hImageList)
  765. {
  766. ImageList_Destroy(m_sReportIcons.Detach());
  767. }
  768. HIMAGELIST himl = ImageList_LoadImage(
  769. AfxGetResourceHandle(),
  770. MAKEINTRESOURCE(IDB_LIST_IMAGES),
  771. 16,
  772. 0,
  773. RGB(0, 255, 0),
  774. IMAGE_BITMAP,
  775. LR_LOADTRANSPARENT | LR_CREATEDIBSECTION);
  776. if (NULL == himl)
  777. {
  778. dwRes = GetLastError();
  779. CALL_FAIL (RESOURCE_ERR, TEXT("ImageList_LoadImage"), dwRes);
  780. PopupError (dwRes);
  781. return dwRes;
  782. }
  783. m_sReportIcons.Attach (himl);
  784. }
  785. if (bForce || (NULL == m_sImgListDocIcon.m_hImageList))
  786. {
  787. //
  788. // Load the image list for the icons column and the up/down sort images - 16 colors.
  789. //
  790. if(m_sImgListDocIcon.m_hImageList)
  791. {
  792. ImageList_Destroy(m_sImgListDocIcon.Detach());
  793. }
  794. dwRes = LoadDIBImageList (m_sImgListDocIcon,
  795. IDB_DOC_ICON,
  796. 16,
  797. RGB (214, 214, 214));
  798. if (ERROR_SUCCESS != dwRes)
  799. {
  800. CALL_FAIL (RESOURCE_ERR, TEXT("LoadDIBImageList"), dwRes);
  801. PopupError (dwRes);
  802. return dwRes;
  803. }
  804. }
  805. refCtrl.SetExtendedStyle (LVS_EX_FULLROWSELECT | // Entire row is selected
  806. LVS_EX_INFOTIP);
  807. refCtrl.SetImageList (&m_sReportIcons, LVSIL_SMALL);
  808. //
  809. // Attach our custom header-control to the window of the list's header.
  810. //
  811. m_HeaderCtrl.SubclassWindow(refCtrl.GetHeaderCtrl()->m_hWnd);
  812. m_HeaderCtrl.SetImageList (&m_sImgListDocIcon);
  813. m_HeaderCtrl.SetListControl (refCtrl.m_hWnd);
  814. COLORREF crBkColor = ::GetSysColor(COLOR_WINDOW);
  815. refCtrl.SetBkColor(crBkColor);
  816. return dwRes;
  817. } // CFolderListView::RefreshImageLists
  818. void
  819. CFolderListView::OnItemRightClick(
  820. NMHDR* pNMHDR,
  821. LRESULT* pResult
  822. )
  823. /*++
  824. Routine name : CFolderListView::OnItemRightClick
  825. Routine description:
  826. Handle mouse right-click on list items (popup context sensitive menu)
  827. Author:
  828. Eran Yariv (EranY), Jan, 2000
  829. Arguments:
  830. pNMHDR [in] - Item information
  831. pResult [out] - Result
  832. Return Value:
  833. None.
  834. --*/
  835. {
  836. DBG_ENTER(TEXT("CFolderListView::OnItemRightClick"),
  837. TEXT("Type=%d"),
  838. m_Type);
  839. //
  840. // Send WM_CONTEXTMENU to self
  841. //
  842. SendMessage(WM_CONTEXTMENU, (WPARAM) m_hWnd, GetMessagePos());
  843. //
  844. // Mark message as handled and suppress default handling
  845. //
  846. *pResult = 1;
  847. } // CFolderListView::OnItemRightClick
  848. DWORD
  849. CFolderListView::GetServerPossibleOperations (
  850. CFaxMsg* pMsg
  851. )
  852. /*++
  853. Routine name : CFolderListView::GetServerPossibleOperations
  854. Routine description:
  855. Retrieves operations possible on items according to server's security configuration.
  856. Author:
  857. Eran Yariv (EranY), Feb, 2000
  858. Arguments:
  859. Return Value:
  860. Possible operations (JOB_OP*)
  861. --*/
  862. {
  863. DWORD dwRes = FAX_JOB_OP_ALL;
  864. DBG_ENTER(TEXT("CFolderListView::GetServerPossibleOperations"), dwRes);
  865. ASSERTION(pMsg);
  866. CServerNode* pServer = pMsg->GetServer();
  867. ASSERTION (pServer);
  868. switch (m_Type)
  869. {
  870. case FOLDER_TYPE_INBOX:
  871. if (!pServer->CanManageInbox())
  872. {
  873. //
  874. // User cannot perform operations on the inbox
  875. //
  876. dwRes &= ~FAX_JOB_OP_DELETE;
  877. }
  878. break;
  879. case FOLDER_TYPE_INCOMING:
  880. if (!pServer->CanManageAllJobs ())
  881. {
  882. //
  883. // User cannot perform operations on the incoming queue folder
  884. //
  885. dwRes &= ~(FAX_JOB_OP_DELETE | FAX_JOB_OP_PAUSE |
  886. FAX_JOB_OP_RESUME | FAX_JOB_OP_RESTART);
  887. }
  888. break;
  889. case FOLDER_TYPE_OUTBOX:
  890. case FOLDER_TYPE_SENT_ITEMS:
  891. //
  892. // User can do anything here
  893. //
  894. break;
  895. default:
  896. ASSERTION_FAILURE;
  897. dwRes = 0;
  898. }
  899. return dwRes;
  900. } // CFolderListView::GetServerPossibleOperations
  901. void CFolderListView::OnItemChanged(
  902. NMHDR* pNMHDR,
  903. LRESULT* pResult
  904. )
  905. /*++
  906. Routine name : CFolderListView::OnItemChanged
  907. Routine description:
  908. Handle selection changes of on list items
  909. Author:
  910. Eran Yariv (EranY), Jan, 2000
  911. Arguments:
  912. pNMHDR [in] - Item information
  913. pResult [out] - Result
  914. Return Value:
  915. None.
  916. --*/
  917. {
  918. DBG_ENTER(TEXT("CFolderListView::OnItemChanged"),
  919. TEXT("Type=%d"),
  920. m_Type);
  921. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
  922. *pResult = 0;
  923. if(m_bInMultiItemsOperation)
  924. {
  925. return;
  926. }
  927. //
  928. // Find out if a new item is selected or unselected.
  929. //
  930. if (pNMListView->iItem < 0)
  931. {
  932. //
  933. // No item reported
  934. //
  935. return;
  936. }
  937. if (!(LVIF_STATE & (pNMListView->uChanged)))
  938. {
  939. //
  940. // This is not a selection change report
  941. //
  942. return;
  943. }
  944. if ( ((pNMListView->uNewState) & LVIS_SELECTED) &&
  945. !((pNMListView->uOldState) & LVIS_SELECTED))
  946. {
  947. //
  948. // Item changed from not-selected to selected.
  949. // Change the possible operations the user can perform on selected items.
  950. //
  951. OnItemSelected((CFaxMsg*)pNMListView->lParam);
  952. //
  953. // If the folder is still refreshing and a command line argument asks for a specific
  954. // message to be selected in this folder, then we mark that message in m_dwlMsgToSelect.
  955. // Since the user just performed a manual selection of items, we no longer have to select anything for him.
  956. //
  957. m_dwlMsgToSelect = 0;
  958. }
  959. else if (!((pNMListView->uNewState) & LVIS_SELECTED) &&
  960. ((pNMListView->uOldState) & LVIS_SELECTED))
  961. {
  962. //
  963. // Item changed from selected to not-selected
  964. // Recalculate the possible operations the user can do on selected item.
  965. OnItemUnSelected((CFaxMsg*)pNMListView->lParam);
  966. //
  967. // If the folder is still refreshing and a command line argument asks for a specific
  968. // message to be selected in this folder, then we mark that message in m_dwlMsgToSelect.
  969. // Since the user just performed a manual selection of items, we no longer have to select anything for him.
  970. //
  971. m_dwlMsgToSelect = 0;
  972. }
  973. } // CFolderListView::OnItemChanged
  974. void
  975. CFolderListView::RecalcPossibleOperations ()
  976. /*++
  977. Routine name : CFolderListView::RecalcPossibleOperations
  978. Routine description:
  979. Recalculates the possible operation on the set of currently selected items.
  980. Author:
  981. Eran Yariv (EranY), Jan, 2000
  982. Arguments:
  983. Return Value:
  984. None.
  985. --*/
  986. {
  987. DBG_ENTER(TEXT("CFolderListView::RecalcPossibleOperations"));
  988. CListCtrl &refCtrl = GetListCtrl();
  989. int iInd = -1;
  990. DWORD dwSelectedCount = refCtrl.GetSelectedCount ();
  991. m_dwPossibleOperationsOnSelectedItems = 0;
  992. ZeroMemory((PVOID)m_nImpossibleOperationsCounts, sizeof(m_nImpossibleOperationsCounts));
  993. CFaxMsg* pFaxMsg = NULL;
  994. for (DWORD dwItems = 0; dwItems < dwSelectedCount; dwItems++)
  995. {
  996. iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
  997. if(iInd < 0)
  998. {
  999. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
  1000. break;
  1001. }
  1002. LPARAM lparam = (LPARAM) refCtrl.GetItemData (iInd);
  1003. OnItemSelected((CFaxMsg*)lparam);
  1004. }
  1005. } // CFolderListView::RecalcPossibleOperations
  1006. void
  1007. CFolderListView::OnItemSelected(CFaxMsg* pFaxMsg)
  1008. /*++
  1009. Routine name : CFolderListView::OnItemSelected
  1010. Routine description:
  1011. Recalculates the possible operation due to item selection
  1012. Arguments:
  1013. pFaxMsg [in] selected fax message
  1014. Return Value:
  1015. None.
  1016. --*/
  1017. {
  1018. DBG_ENTER(TEXT("CFolderListView::OnItemSelected"));
  1019. //
  1020. // Item changed from not-selected to selected.
  1021. // Change the possible operations the user can perform on selected items.
  1022. //
  1023. if(0 == m_dwPossibleOperationsOnSelectedItems)
  1024. {
  1025. m_dwPossibleOperationsOnSelectedItems = 0xFFFF;
  1026. }
  1027. DWORD dwItemOperations = GetServerPossibleOperations(pFaxMsg) &
  1028. pFaxMsg->GetPossibleOperations();
  1029. if (GetListCtrl().GetSelectedCount() > 1)
  1030. {
  1031. //
  1032. // If more than one item is selected, disable view and properties.
  1033. //
  1034. dwItemOperations &= ~(FAX_JOB_OP_VIEW | FAX_JOB_OP_PROPERTIES);
  1035. }
  1036. m_dwPossibleOperationsOnSelectedItems &= dwItemOperations;
  1037. //
  1038. // Update impossible operations counts
  1039. //
  1040. DWORD dw;
  1041. for(dw=0; dw < ARR_SIZE(m_nImpossibleOperationsCounts); ++dw)
  1042. {
  1043. if((dwItemOperations & 1) == 0)
  1044. {
  1045. //
  1046. // The operation is disabled.
  1047. //
  1048. m_nImpossibleOperationsCounts[dw]++;
  1049. }
  1050. dwItemOperations = dwItemOperations >> 1;
  1051. }
  1052. } // CFolderListView::OnItemSelected
  1053. void
  1054. CFolderListView::OnItemUnSelected(CFaxMsg* pFaxMsg)
  1055. /*++
  1056. Routine name : CFolderListView::OnItemUnSelected
  1057. Routine description:
  1058. Recalculates the possible operation due to item unselect
  1059. Arguments:
  1060. pFaxMsg [in] unselected fax message
  1061. Return Value:
  1062. None.
  1063. --*/
  1064. {
  1065. DBG_ENTER(TEXT("CFolderListView::OnItemUnSelected"));
  1066. CListCtrl &refCtrl = GetListCtrl();
  1067. DWORD dwSelectedCount = refCtrl.GetSelectedCount ();
  1068. if(dwSelectedCount <= 1)
  1069. {
  1070. m_dwPossibleOperationsOnSelectedItems = 0;
  1071. ZeroMemory((PVOID)m_nImpossibleOperationsCounts, sizeof(m_nImpossibleOperationsCounts));
  1072. if(1 == dwSelectedCount)
  1073. {
  1074. int iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
  1075. OnItemSelected((CFaxMsg*)refCtrl.GetItemData (iInd));
  1076. }
  1077. return;
  1078. }
  1079. DWORD dwItemOperations = GetServerPossibleOperations(pFaxMsg) &
  1080. pFaxMsg->GetPossibleOperations();
  1081. DWORD dw;
  1082. for(dw=0; dw < ARR_SIZE(m_nImpossibleOperationsCounts); ++dw)
  1083. {
  1084. if((dwItemOperations & 1) == 0)
  1085. {
  1086. //
  1087. // The operation is disabled for unselected item.
  1088. //
  1089. m_nImpossibleOperationsCounts[dw]--;
  1090. ASSERTION(m_nImpossibleOperationsCounts[dw] >= 0);
  1091. if(m_nImpossibleOperationsCounts[dw] == 0)
  1092. {
  1093. //
  1094. // Enable this operation
  1095. //
  1096. m_dwPossibleOperationsOnSelectedItems |= (1 << dw);
  1097. }
  1098. }
  1099. dwItemOperations = dwItemOperations >> 1;
  1100. }
  1101. } // CFolderListView::OnItemUnSelected
  1102. void
  1103. CFolderListView::OnFolderItemView ()
  1104. /*++
  1105. Routine name : CFolderListView::OnFolderItemView
  1106. Routine description:
  1107. Handles message view commands
  1108. Author:
  1109. Eran Yariv (EranY), Jan, 2000
  1110. Arguments:
  1111. Return Value:
  1112. None.
  1113. --*/
  1114. {
  1115. DBG_ENTER(TEXT("CFolderListView::OnFolderItemView"),
  1116. TEXT("Type=%d"),
  1117. m_Type);
  1118. if(!(m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW))
  1119. {
  1120. //
  1121. // there is no TIF associated application
  1122. //
  1123. return;
  1124. }
  1125. CString cstrTiff;
  1126. DWORD dwRes = FetchTiff (cstrTiff);
  1127. if (ERROR_SUCCESS != dwRes)
  1128. {
  1129. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
  1130. PopupError (dwRes);
  1131. return;
  1132. }
  1133. //
  1134. // Open the TIFF with associated application.
  1135. // All preview files are automatically removed once the application is shut down.
  1136. //
  1137. dwRes = ViewFile(cstrTiff);
  1138. if (ERROR_SUCCESS != dwRes)
  1139. {
  1140. CALL_FAIL (GENERAL_ERR, TEXT("ViewFile"), dwRes);
  1141. if(ERROR_NO_ASSOCIATION == dwRes)
  1142. {
  1143. AlignedAfxMessageBox(IDS_NO_OPEN_ASSOCIATION, MB_ICONSTOP);
  1144. }
  1145. else
  1146. {
  1147. PopupError (dwRes);
  1148. }
  1149. }
  1150. else
  1151. {
  1152. if(FOLDER_TYPE_INBOX == m_Type)
  1153. {
  1154. theApp.InboxViewed();
  1155. }
  1156. }
  1157. } // CFolderListView::OnFolderItemView
  1158. void
  1159. CFolderListView::OnFolderItemPrint ()
  1160. /*++
  1161. Routine name : CFolderListView::OnFolderItemPrint
  1162. Routine description:
  1163. Handles message print commands
  1164. Author:
  1165. Eran Yariv (EranY), Jan, 2000
  1166. Arguments:
  1167. Return Value:
  1168. None.
  1169. --*/
  1170. {
  1171. DWORD dwRes;
  1172. DBG_ENTER(TEXT("CFolderListView::OnFolderItemPrint"),
  1173. TEXT("Type=%d"),
  1174. m_Type);
  1175. HDC hPrinter;
  1176. if (IsWinXPOS())
  1177. {
  1178. //
  1179. // Use new look of printer selection dialog
  1180. //
  1181. C_PrintDialogEx prnDlg(FALSE,
  1182. PD_ALLPAGES |
  1183. PD_USEDEVMODECOPIES |
  1184. PD_NOPAGENUMS |
  1185. PD_NOSELECTION |
  1186. PD_RETURNDC);
  1187. if(IDOK != prnDlg.DoModal())
  1188. {
  1189. CALL_FAIL (GENERAL_ERR, TEXT("C_PrintDialogEx::DoModal"), CommDlgExtendedError());
  1190. return;
  1191. }
  1192. hPrinter = prnDlg.GetPrinterDC();
  1193. if(!hPrinter)
  1194. {
  1195. dwRes = ERROR_CAN_NOT_COMPLETE;
  1196. CALL_FAIL (GENERAL_ERR, TEXT("C_PrintDialogEx::GetPrinterDC"), dwRes);
  1197. return;
  1198. }
  1199. }
  1200. else
  1201. {
  1202. //
  1203. // Use legacy printer selection dialog
  1204. //
  1205. CPrintDialog prnDlg(FALSE);
  1206. if(IDOK != prnDlg.DoModal())
  1207. {
  1208. return;
  1209. }
  1210. hPrinter = prnDlg.GetPrinterDC();
  1211. if(!hPrinter)
  1212. {
  1213. dwRes = ERROR_CAN_NOT_COMPLETE;
  1214. CALL_FAIL (GENERAL_ERR, TEXT("CPrintDialog::GetPrinterDC"), dwRes);
  1215. return;
  1216. }
  1217. }
  1218. CString cstrTiff;
  1219. dwRes = FetchTiff (cstrTiff);
  1220. if (ERROR_SUCCESS != dwRes)
  1221. {
  1222. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
  1223. PopupError (dwRes);
  1224. return;
  1225. }
  1226. if(!TiffPrintDC(cstrTiff, hPrinter))
  1227. {
  1228. dwRes = GetLastError();
  1229. CALL_FAIL (GENERAL_ERR, TEXT("TiffPrintDC"), dwRes);
  1230. goto exit;
  1231. }
  1232. exit:
  1233. if(hPrinter)
  1234. {
  1235. CDC::FromHandle(hPrinter)->DeleteDC();
  1236. }
  1237. if (!DeleteFile (cstrTiff))
  1238. {
  1239. dwRes = GetLastError ();
  1240. CALL_FAIL (FILE_ERR, TEXT("DeleteFile"), dwRes);
  1241. }
  1242. } // CFolderListView::OnFolderItemPrint
  1243. void
  1244. CFolderListView::OnFolderItemCopy ()
  1245. /*++
  1246. Routine name : CFolderListView::OnFolderItemCopy
  1247. Routine description:
  1248. Handles message copy commands
  1249. Author:
  1250. Eran Yariv (EranY), Jan, 2000
  1251. Arguments:
  1252. Return Value:
  1253. None.
  1254. --*/
  1255. {
  1256. DBG_ENTER(TEXT("CFolderListView::OnFolderItemCopy"),
  1257. TEXT("Type=%d"),
  1258. m_Type);
  1259. CString cstrTiff;
  1260. DWORD dwRes = FetchTiff (cstrTiff);
  1261. if (ERROR_SUCCESS != dwRes)
  1262. {
  1263. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
  1264. PopupError (dwRes);
  1265. return;
  1266. }
  1267. CString cstrFileName;
  1268. CString cstrFilterFormat;
  1269. TCHAR szFile[MAX_PATH] = {0};
  1270. TCHAR szFilter[MAX_PATH] = {0};
  1271. OPENFILENAME ofn = {0};
  1272. //
  1273. // get tif file name
  1274. //
  1275. int nFileNamePos = cstrTiff.ReverseFind(TEXT('\\'));
  1276. ASSERTION(nFileNamePos > 0);
  1277. nFileNamePos++;
  1278. try
  1279. {
  1280. cstrFileName = cstrTiff.Right(cstrTiff.GetLength() - nFileNamePos);
  1281. }
  1282. catch(...)
  1283. {
  1284. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1285. CALL_FAIL (MEM_ERR, TEXT("CString::operator="), dwRes);
  1286. PopupError (dwRes);
  1287. goto del_file;
  1288. }
  1289. _tcscpy(szFile, cstrFileName);
  1290. dwRes = LoadResourceString(cstrFilterFormat, IDS_SAVE_AS_FILTER_FORMAT);
  1291. if (ERROR_SUCCESS != dwRes)
  1292. {
  1293. ASSERTION_FAILURE;
  1294. CALL_FAIL (RESOURCE_ERR, TEXT("LoadResourceString"), dwRes);
  1295. goto del_file;
  1296. }
  1297. _stprintf(szFilter, cstrFilterFormat, FAX_TIF_FILE_MASK, 0, FAX_TIF_FILE_MASK, 0);
  1298. ofn.lStructSize = GetOpenFileNameStructSize();
  1299. ofn.hwndOwner = m_hWnd;
  1300. ofn.lpstrFilter = szFilter;
  1301. ofn.lpstrFile = szFile;
  1302. ofn.nMaxFile = ARR_SIZE(szFile);
  1303. ofn.lpstrDefExt = FAX_TIF_FILE_EXT;
  1304. ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
  1305. ofn.lpfnHook = OFNHookProc;
  1306. if(!GetSaveFileName(&ofn))
  1307. {
  1308. goto del_file;
  1309. }
  1310. {
  1311. //
  1312. // SHFILEOPSTRUCT::pFrom should ends with double NULL
  1313. //
  1314. TCHAR tszSrcFile[MAX_PATH+1] = {0};
  1315. _tcsncpy(tszSrcFile, cstrTiff, MAX_PATH);
  1316. //
  1317. // move the file
  1318. //
  1319. SHFILEOPSTRUCT shFileOpStruct = {0};
  1320. shFileOpStruct.wFunc = FO_MOVE;
  1321. shFileOpStruct.fFlags = FOF_SILENT; // Don't display file move progress dialog
  1322. shFileOpStruct.pFrom = tszSrcFile;
  1323. shFileOpStruct.pTo = szFile;
  1324. if(!SHFileOperation(&shFileOpStruct))
  1325. {
  1326. //
  1327. // success
  1328. //
  1329. return;
  1330. }
  1331. else
  1332. {
  1333. dwRes = ERROR_CAN_NOT_COMPLETE;
  1334. CALL_FAIL (GENERAL_ERR, TEXT("SHFileOperation"), dwRes);
  1335. goto del_file;
  1336. }
  1337. }
  1338. del_file:
  1339. if (!DeleteFile (cstrTiff))
  1340. {
  1341. dwRes = GetLastError ();
  1342. CALL_FAIL (FILE_ERR, TEXT("DeleteFile"), dwRes);
  1343. }
  1344. } // CFolderListView::OnFolderItemCopy
  1345. void
  1346. CFolderListView::OnUpdateFolderItemSendMail(
  1347. CCmdUI* pCmdUI
  1348. )
  1349. {
  1350. pCmdUI->Enable( (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW) &&
  1351. (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_PROPERTIES) &&
  1352. theApp.IsMapiEnable());
  1353. }
  1354. void
  1355. CFolderListView::OnUpdateFolderItemView(
  1356. CCmdUI* pCmdUI
  1357. )
  1358. {
  1359. OnUpdateFolderItemPrint(pCmdUI);
  1360. }
  1361. void
  1362. CFolderListView::OnUpdateFolderItemPrint(
  1363. CCmdUI* pCmdUI
  1364. )
  1365. {
  1366. pCmdUI->Enable( (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW) &&
  1367. (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_PROPERTIES));
  1368. }
  1369. void
  1370. CFolderListView::OnUpdateFolderItemCopy(
  1371. CCmdUI* pCmdUI
  1372. )
  1373. {
  1374. pCmdUI->Enable( (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_VIEW) &&
  1375. (m_dwPossibleOperationsOnSelectedItems & FAX_JOB_OP_PROPERTIES));
  1376. }
  1377. void
  1378. CFolderListView::OnFolderItemMail ()
  1379. /*++
  1380. Routine name : CFolderListView::OnFolderItemMail
  1381. Routine description:
  1382. Handles message mail commands
  1383. Author:
  1384. Eran Yariv (EranY), Jan, 2000
  1385. Arguments:
  1386. Return Value:
  1387. None.
  1388. --*/
  1389. {
  1390. DBG_ENTER(TEXT("CFolderListView::OnFolderItemMail"),
  1391. TEXT("Type=%d"),
  1392. m_Type);
  1393. CString cstrTiff;
  1394. DWORD dwRes = FetchTiff (cstrTiff);
  1395. if (ERROR_SUCCESS != dwRes)
  1396. {
  1397. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::FetchTiff"), dwRes);
  1398. PopupError (dwRes);
  1399. return;
  1400. }
  1401. //
  1402. // create a new mail message with tif file attached
  1403. //
  1404. dwRes = theApp.SendMail(cstrTiff);
  1405. if (ERROR_SUCCESS != dwRes)
  1406. {
  1407. CALL_FAIL (GENERAL_ERR, TEXT("CClientConsoleApp::SendMail"), dwRes);
  1408. PopupError (dwRes);
  1409. }
  1410. if (!DeleteFile (cstrTiff))
  1411. {
  1412. dwRes = GetLastError ();
  1413. CALL_FAIL (FILE_ERR, TEXT("DeleteFile"), dwRes);
  1414. }
  1415. } // CFolderListView::OnFolderItemMail
  1416. void
  1417. CFolderListView::OnFolderItemProperties ()
  1418. /*++
  1419. Routine name : CFolderListView::OnFolderItemProperties
  1420. Routine description:
  1421. Handles message properties commands
  1422. Author:
  1423. Eran Yariv (EranY), Jan, 2000
  1424. Arguments:
  1425. Return Value:
  1426. None.
  1427. --*/
  1428. {
  1429. DBG_ENTER(TEXT("CFolderListView::OnFolderItemProperties"),
  1430. TEXT("Type=%d"),
  1431. m_Type);
  1432. //
  1433. // Make sure there's exaclty one elemented selected
  1434. //
  1435. CListCtrl &refCtrl = GetListCtrl();
  1436. ASSERTION (1 == refCtrl.GetSelectedCount());
  1437. int iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
  1438. ASSERTION (0 <= iInd);
  1439. CFaxMsg* pMsg = (CFaxMsg*)(refCtrl.GetItemData (iInd));
  1440. ASSERTION (pMsg);
  1441. CServerNode* pServer = pMsg->GetServer();
  1442. ASSERTION (pServer);
  1443. CItemPropSheet propSheet(IDS_PROPERTIES_SHEET_CAPTION);
  1444. DWORD dwRes = propSheet.Init(pServer->GetFolder(m_Type), pMsg);
  1445. if(ERROR_SUCCESS != dwRes)
  1446. {
  1447. PopupError (dwRes);
  1448. return;
  1449. }
  1450. dwRes = propSheet.DoModal();
  1451. if(IDABORT == dwRes)
  1452. {
  1453. PopupError (propSheet.GetLastError());
  1454. }
  1455. } // CFolderListView::OnFolderItemProperties
  1456. DWORD
  1457. CFolderListView::OpenSelectColumnsDlg()
  1458. /*++
  1459. Routine name : CFolderListView::OpenSelectColumnsDlg
  1460. Routine description:
  1461. opens column select dialog and reorders the columns
  1462. Author:
  1463. Alexander Malysh (AlexMay), Jan, 2000
  1464. Arguments:
  1465. Return Value:
  1466. Error code
  1467. --*/
  1468. {
  1469. DWORD dwRes = ERROR_SUCCESS;
  1470. DBG_ENTER(TEXT("CFolderListView::OpenSelectColumnsDlg"),
  1471. TEXT("Type=%d"),
  1472. m_Type);
  1473. ASSERTION(NULL != m_pnColumnsOrder);
  1474. ASSERTION(NULL != m_pViewColumnInfo);
  1475. DWORD dwCount = GetLogicalColumnsCount();
  1476. //
  1477. // init header string array
  1478. //
  1479. CString* pcstrHeaders;
  1480. try
  1481. {
  1482. pcstrHeaders = new CString[dwCount];
  1483. }
  1484. catch (...)
  1485. {
  1486. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1487. CALL_FAIL (MEM_ERR, TEXT ("new CString[dwCount]"), dwRes);
  1488. return dwRes;
  1489. }
  1490. int nItemIndex;
  1491. for (DWORD dw = 0; dw < dwCount; ++dw)
  1492. {
  1493. nItemIndex = ItemIndexFromLogicalColumnIndex(dw);
  1494. dwRes = GetColumnHeaderString (pcstrHeaders[dw], nItemIndex);
  1495. if (ERROR_SUCCESS != dwRes)
  1496. {
  1497. CALL_FAIL (GENERAL_ERR, TEXT("GetColumnHeaderString"), dwRes);
  1498. delete[] pcstrHeaders;
  1499. return dwRes;
  1500. }
  1501. }
  1502. //
  1503. // save width
  1504. //
  1505. int nIndex;
  1506. for (dw = 0; dw < m_dwDisplayedColumns; ++dw)
  1507. {
  1508. nIndex = m_pnColumnsOrder[dw];
  1509. ASSERTION(nIndex >= 0 && nIndex < dwCount);
  1510. m_pViewColumnInfo[nIndex].nWidth = GetListCtrl().GetColumnWidth(nIndex);
  1511. }
  1512. //
  1513. // start column select dialog
  1514. //
  1515. CColumnSelectDlg dlg(pcstrHeaders, m_pnColumnsOrder, dwCount, m_dwDisplayedColumns);
  1516. if(IDOK == dlg.DoModal())
  1517. {
  1518. for (dw = 0; dw < dwCount; ++dw)
  1519. {
  1520. nIndex = m_pnColumnsOrder[dw];
  1521. ASSERTION(nIndex >= 0 && nIndex < dwCount);
  1522. m_pViewColumnInfo[nIndex].dwOrder = dw;
  1523. m_pViewColumnInfo[nIndex].bShow = (dw < m_dwDisplayedColumns);
  1524. }
  1525. //
  1526. // if sorted column is hidden then no sort
  1527. //
  1528. if(m_nSortedCol >= 0)
  1529. {
  1530. ASSERTION(m_nSortedCol < dwCount);
  1531. if(!m_pViewColumnInfo[m_nSortedCol].bShow)
  1532. {
  1533. m_nSortedCol = -1;
  1534. }
  1535. }
  1536. ColumnsToLayout();
  1537. }
  1538. delete[] pcstrHeaders;
  1539. return dwRes;
  1540. } // CFolderListView::OpenSelectColumnsDlg
  1541. DWORD
  1542. CFolderListView::ColumnsToLayout()
  1543. /*++
  1544. Routine name : CFolderListView::ColumnsToLayout
  1545. Routine description:
  1546. reorders columns according to saved layout
  1547. Author:
  1548. Alexander Malysh (AlexMay), Jan, 2000
  1549. Arguments:
  1550. Return Value:
  1551. Standard Win32 error code
  1552. --*/
  1553. {
  1554. DWORD dwRes = ERROR_SUCCESS;
  1555. DBG_ENTER(TEXT("CFolderListView::ColumnsToLayout"), dwRes);
  1556. ASSERTION(NULL != m_pnColumnsOrder);
  1557. ASSERTION(NULL != m_pViewColumnInfo);
  1558. CListCtrl &refCtrl = GetListCtrl();
  1559. DWORD dwCount = GetLogicalColumnsCount();
  1560. CSize size;
  1561. CDC* pHdrDc = refCtrl.GetHeaderCtrl()->GetDC();
  1562. //
  1563. // set column order
  1564. //
  1565. if(!refCtrl.SetColumnOrderArray(dwCount, m_pnColumnsOrder))
  1566. {
  1567. dwRes = ERROR_GEN_FAILURE;
  1568. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::SetColumnOrderArray"), dwRes);
  1569. return dwRes;
  1570. }
  1571. //
  1572. // set column width
  1573. //
  1574. DWORD dwItemIndex;
  1575. CString cstrColumnText;
  1576. for (DWORD dwCol = 0; dwCol < dwCount; ++dwCol)
  1577. {
  1578. if(m_pViewColumnInfo[dwCol].bShow)
  1579. {
  1580. if(m_pViewColumnInfo[dwCol].nWidth < 0)
  1581. {
  1582. dwItemIndex = ItemIndexFromLogicalColumnIndex(dwCol);
  1583. dwRes = GetColumnHeaderString (cstrColumnText, dwItemIndex);
  1584. if(ERROR_SUCCESS != dwRes)
  1585. {
  1586. CALL_FAIL (GENERAL_ERR, TEXT("GetColumnHeaderString"), dwRes);
  1587. return dwRes;
  1588. }
  1589. size = pHdrDc->GetTextExtent(cstrColumnText);
  1590. refCtrl.SetColumnWidth (dwCol, size.cx * 1.5);
  1591. }
  1592. else
  1593. {
  1594. refCtrl.SetColumnWidth (dwCol, m_pViewColumnInfo[dwCol].nWidth);
  1595. }
  1596. }
  1597. else
  1598. {
  1599. refCtrl.SetColumnWidth (dwCol, 0);
  1600. }
  1601. }
  1602. Invalidate();
  1603. return dwRes;
  1604. } // CFolderListView::ColumnsToLayout
  1605. DWORD
  1606. CFolderListView::ReadLayout(
  1607. LPCTSTR lpszViewName
  1608. )
  1609. /*++
  1610. Routine name : CFolderListView::ReadLayout
  1611. Routine description:
  1612. reads column layout from registry
  1613. Author:
  1614. Alexander Malysh (AlexMay), Jan, 2000
  1615. Arguments:
  1616. lpszSection [in] - registry section
  1617. Return Value:
  1618. Standard Win32 error code
  1619. --*/
  1620. {
  1621. DWORD dwRes = ERROR_SUCCESS;
  1622. DBG_ENTER(TEXT("CFolderListView::ReadLayout"),
  1623. dwRes,
  1624. TEXT("Type=%d"),
  1625. m_Type);
  1626. ASSERTION(NULL == m_pnColumnsOrder);
  1627. ASSERTION(NULL == m_pViewColumnInfo);
  1628. //
  1629. // columns order array allocation
  1630. //
  1631. DWORD dwCount = GetLogicalColumnsCount();
  1632. try
  1633. {
  1634. m_pnColumnsOrder = new int[dwCount];
  1635. }
  1636. catch (...)
  1637. {
  1638. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1639. CALL_FAIL (MEM_ERR, TEXT ("m_pdwColumnsOrder = new int[dwCount]"), dwRes);
  1640. return dwRes;
  1641. }
  1642. for(DWORD dw=0; dw < dwCount; ++dw)
  1643. {
  1644. m_pnColumnsOrder[dw] = -1;
  1645. }
  1646. //
  1647. // columns info array allocation
  1648. //
  1649. try
  1650. {
  1651. m_pViewColumnInfo = new TViewColumnInfo[dwCount];
  1652. }
  1653. catch (...)
  1654. {
  1655. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1656. CALL_FAIL (MEM_ERR, TEXT ("new CString[dwCount]"), dwRes);
  1657. return dwRes;
  1658. }
  1659. //
  1660. // reads columns layout from registry
  1661. //
  1662. CString cstrSection;
  1663. m_dwDisplayedColumns = 0;
  1664. for(dw=0; dw < dwCount; ++dw)
  1665. {
  1666. try
  1667. {
  1668. cstrSection.Format(TEXT("%s\\%s\\%02d"), lpszViewName, CLIENT_VIEW_COLUMNS, dw);
  1669. }
  1670. catch(...)
  1671. {
  1672. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1673. CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
  1674. return dwRes;
  1675. }
  1676. m_pViewColumnInfo[dw].bShow = theApp.GetProfileInt(cstrSection,
  1677. CLIENT_VIEW_COL_SHOW,
  1678. (dw < m_dwDefaultColNum) ? 1 : 0);
  1679. if(m_pViewColumnInfo[dw].bShow)
  1680. {
  1681. ++m_dwDisplayedColumns;
  1682. }
  1683. m_pViewColumnInfo[dw].nWidth = theApp.GetProfileInt(cstrSection,
  1684. CLIENT_VIEW_COL_WIDTH, -1);
  1685. m_pViewColumnInfo[dw].dwOrder = theApp.GetProfileInt(cstrSection,
  1686. CLIENT_VIEW_COL_ORDER, dw);
  1687. if(m_pViewColumnInfo[dw].dwOrder < dwCount)
  1688. {
  1689. m_pnColumnsOrder[m_pViewColumnInfo[dw].dwOrder] = dw;
  1690. }
  1691. else
  1692. {
  1693. ASSERTION_FAILURE;
  1694. }
  1695. }
  1696. //
  1697. // check column order consistence
  1698. //
  1699. for(dw=0; dw < dwCount; ++dw)
  1700. {
  1701. ASSERTION(m_pnColumnsOrder[dw] >= 0);
  1702. }
  1703. //
  1704. // read sort parameters
  1705. //
  1706. m_bSortAscending = theApp.GetProfileInt(lpszViewName, CLIENT_VIEW_SORT_ASCENDING, 1);
  1707. m_nSortedCol = theApp.GetProfileInt(lpszViewName, CLIENT_VIEW_SORT_COLUMN, 1);
  1708. if(m_nSortedCol >= dwCount)
  1709. {
  1710. m_nSortedCol = 0;
  1711. }
  1712. return dwRes;
  1713. } // CFolderListView::ReadLayout
  1714. DWORD
  1715. CFolderListView::SaveLayout(
  1716. LPCTSTR lpszViewName
  1717. )
  1718. /*++
  1719. Routine name : CFolderListView::SaveLayout
  1720. Routine description:
  1721. saves column layout to registry
  1722. Author:
  1723. Alexander Malysh (AlexMay), Jan, 2000
  1724. Arguments:
  1725. lpszSection [in] - registry section
  1726. Return Value:
  1727. Standard Win32 error code
  1728. --*/
  1729. {
  1730. DWORD dwRes = ERROR_SUCCESS;
  1731. DBG_ENTER(TEXT("CFolderListView::SaveLayout"),
  1732. dwRes,
  1733. TEXT("Type=%d"),
  1734. m_Type);
  1735. if(!m_bColumnsInitialized)
  1736. {
  1737. return dwRes;
  1738. }
  1739. ASSERTION(m_pViewColumnInfo != NULL);
  1740. //
  1741. // save column layout to registry
  1742. //
  1743. BOOL bRes;
  1744. DWORD dwWidth;
  1745. CString cstrSection;
  1746. DWORD dwCount = GetLogicalColumnsCount();
  1747. for(DWORD dw=0; dw < dwCount; ++dw)
  1748. {
  1749. try
  1750. {
  1751. cstrSection.Format(TEXT("%s\\%s\\%02d"), lpszViewName, CLIENT_VIEW_COLUMNS, dw);
  1752. }
  1753. catch(...)
  1754. {
  1755. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1756. CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
  1757. return dwRes;
  1758. }
  1759. bRes = theApp.WriteProfileInt(cstrSection, CLIENT_VIEW_COL_SHOW,
  1760. m_pViewColumnInfo[dw].bShow);
  1761. bRes = theApp.WriteProfileInt(cstrSection, CLIENT_VIEW_COL_ORDER,
  1762. m_pViewColumnInfo[dw].dwOrder);
  1763. dwWidth = m_pViewColumnInfo[dw].bShow ? GetListCtrl().GetColumnWidth(dw) : -1;
  1764. bRes = theApp.WriteProfileInt(cstrSection, CLIENT_VIEW_COL_WIDTH, dwWidth);
  1765. }
  1766. //
  1767. // save sort parameters
  1768. //
  1769. bRes = theApp.WriteProfileInt(lpszViewName, CLIENT_VIEW_SORT_ASCENDING, m_bSortAscending);
  1770. bRes = theApp.WriteProfileInt(lpszViewName, CLIENT_VIEW_SORT_COLUMN, m_nSortedCol);
  1771. return dwRes;
  1772. } // CFolderListView::SaveLayout
  1773. BOOL
  1774. CFolderListView::OnNotify(
  1775. WPARAM wParam,
  1776. LPARAM lParam,
  1777. LRESULT* pResult
  1778. )
  1779. /*++
  1780. Routine name : CFolderListView::OnNotify
  1781. Routine description:
  1782. disables resizing of hidden columns
  1783. Author:
  1784. Alexander Malysh (AlexMay), Jan, 2000
  1785. Arguments:
  1786. wParam [in] - Identifies the control that sends the message
  1787. lParam [in] - NMHEADER*
  1788. pResult [out] - result
  1789. Return Value:
  1790. TRUE if message processed, FALSE otherwise.
  1791. --*/
  1792. {
  1793. int i=0;
  1794. switch (((NMHEADER*)lParam)->hdr.code)
  1795. {
  1796. case HDN_BEGINTRACKA:
  1797. case HDN_BEGINTRACKW:
  1798. case HDN_DIVIDERDBLCLICKA:
  1799. case HDN_DIVIDERDBLCLICKW:
  1800. DBG_ENTER(TEXT("CFolderListView::OnNotify"));
  1801. //
  1802. // get column index
  1803. //
  1804. DWORD dwIndex = ((NMHEADER*)lParam)->iItem;
  1805. ASSERTION(NULL != m_pViewColumnInfo);
  1806. ASSERTION(dwIndex < GetLogicalColumnsCount());
  1807. //
  1808. // ignore if hidden column
  1809. //
  1810. if(!m_pViewColumnInfo[dwIndex].bShow )
  1811. {
  1812. *pResult = TRUE;
  1813. return TRUE;
  1814. }
  1815. }
  1816. return CListView::OnNotify(wParam, lParam, pResult );
  1817. } // CFolderListView::OnNotify
  1818. void
  1819. CFolderListView::DoSort()
  1820. {
  1821. if (m_bSorting || m_nSortedCol < 0)
  1822. {
  1823. //
  1824. // Already sorting or no sorting column
  1825. //
  1826. return;
  1827. }
  1828. CWaitCursor waitCursor;
  1829. m_bSorting = TRUE;
  1830. CMainFrame *pFrm = GetFrm();
  1831. if (!pFrm)
  1832. {
  1833. //
  1834. // Shutdown in progress
  1835. //
  1836. }
  1837. else
  1838. {
  1839. pFrm->RefreshStatusBar ();
  1840. }
  1841. m_psCurrentViewBeingSorted = this;
  1842. GetListCtrl().SortItems (ListViewItemsCompareProc, 0);
  1843. m_HeaderCtrl.SetSortImage( m_nSortedCol, m_bSortAscending );
  1844. m_bSorting = FALSE;
  1845. }
  1846. DWORD
  1847. CFolderListView::RemoveItem (
  1848. LPARAM lparam,
  1849. int iIndex /* = -1 */
  1850. )
  1851. /*++
  1852. Routine name : CFolderListView::RemoveItem
  1853. Routine description:
  1854. Removes an item from the list by its message / job pointer
  1855. Author:
  1856. Eran Yariv (EranY), Feb, 2000
  1857. Arguments:
  1858. lparam [in] - Message / Job pointer
  1859. iIndex [in] - Optional item index in the control (for optimization)
  1860. Return Value:
  1861. Standard Win32 error code
  1862. --*/
  1863. {
  1864. DWORD dwRes = ERROR_SUCCESS;
  1865. DBG_ENTER(TEXT("CFolderListView::RemoveItem"),
  1866. dwRes,
  1867. TEXT("Type=%d"),
  1868. m_Type);
  1869. CListCtrl &refCtrl = GetListCtrl();
  1870. if (-1 == iIndex)
  1871. {
  1872. //
  1873. // Item index no supplied - search for it
  1874. //
  1875. LVFINDINFO lvfi;
  1876. lvfi.flags = LVFI_PARAM;
  1877. lvfi.lParam = lparam;
  1878. iIndex = refCtrl.FindItem (&lvfi);
  1879. }
  1880. if (-1 == iIndex)
  1881. {
  1882. //
  1883. // item already removed
  1884. //
  1885. CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::FindItem"), dwRes);
  1886. return dwRes;
  1887. }
  1888. BOOL bItemSelected = IsSelected (iIndex);
  1889. //
  1890. // Now erase the item
  1891. //
  1892. if (!refCtrl.DeleteItem (iIndex))
  1893. {
  1894. //
  1895. // Failed to delete the item
  1896. //
  1897. dwRes = ERROR_GEN_FAILURE;
  1898. CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::DeleteItem"), dwRes);
  1899. return dwRes;
  1900. }
  1901. if (bItemSelected)
  1902. {
  1903. //
  1904. // If the item that we just removed was selected, we have to re-compute
  1905. // the possible operations on the rest of the selected items.
  1906. //
  1907. if (!m_bInMultiItemsOperation)
  1908. {
  1909. //
  1910. // Only recalc if we operate on few items.
  1911. //
  1912. RecalcPossibleOperations ();
  1913. }
  1914. }
  1915. ASSERTION (ERROR_SUCCESS == dwRes);
  1916. return dwRes;
  1917. } // CFolderListView::RemoveItem
  1918. DWORD
  1919. CFolderListView::FindInsertionIndex (
  1920. LPARAM lparamItemData,
  1921. DWORD &dwResultIndex
  1922. )
  1923. /*++
  1924. Routine name : CFolderListView::FindInsertionIndex
  1925. Routine description:
  1926. Finds an insertion index for a new item to the list, according to sort settings.
  1927. This function must be called when the data critical section is held.
  1928. Author:
  1929. Eran Yariv (EranY), Feb, 2000
  1930. Arguments:
  1931. lparamItemData [in] - Pointer to item
  1932. dwResultIndex [out] - Insertion index
  1933. Return Value:
  1934. Standard Win32 error code
  1935. --*/
  1936. {
  1937. DWORD dwRes = ERROR_SUCCESS;
  1938. DBG_ENTER(TEXT("CFolderListView::FindInsertionIndex"),
  1939. dwRes,
  1940. TEXT("Type=%d"),
  1941. m_Type);
  1942. CListCtrl &refCtrl = GetListCtrl();
  1943. DWORD dwNumItems = refCtrl.GetItemCount ();
  1944. if (!dwNumItems || (-1 == m_nSortedCol))
  1945. {
  1946. //
  1947. // List is not sorted or is empty, always add at the end
  1948. //
  1949. VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
  1950. dwResultIndex = dwNumItems;
  1951. return dwRes;
  1952. }
  1953. //
  1954. // Get item index to sort by
  1955. //
  1956. DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (m_nSortedCol);
  1957. //
  1958. // Check if item can be placed in beginning of list (no search required)
  1959. //
  1960. LPARAM lparamTop = refCtrl.GetItemData (0); // Pointer to item in top index
  1961. LPARAM lparamBottom = refCtrl.GetItemData (dwNumItems - 1); // Pointer to item in bottom index
  1962. ASSERTION (lparamTop && lparamBottom);
  1963. //
  1964. // Get comparison result against top index
  1965. //
  1966. int iRes = CompareItems ((CFaxMsg*)lparamItemData, (CFaxMsg*)lparamTop, dwItemIndex);
  1967. ASSERTION ((-1 <= iRes) && (+1 >= iRes));
  1968. if (!m_bSortAscending)
  1969. {
  1970. iRes *= -1;
  1971. }
  1972. switch (iRes)
  1973. {
  1974. case -1: // Item is smaller than top
  1975. case 0: // Item is identical to top
  1976. //
  1977. // Insert new item before top index
  1978. //
  1979. dwResultIndex = 0;
  1980. VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
  1981. return dwRes;
  1982. default: // Item is bigger than top
  1983. //
  1984. // Do nothing
  1985. //
  1986. break;
  1987. }
  1988. //
  1989. // Check if item can be placed in bottom of list (no search required)
  1990. //
  1991. //
  1992. // Get comparison result against bottom index
  1993. //
  1994. iRes = CompareItems ((CFaxMsg*)lparamItemData, (CFaxMsg*)lparamBottom, dwItemIndex);
  1995. ASSERTION ((-1 <= iRes) && (+1 >= iRes));
  1996. if (!m_bSortAscending)
  1997. {
  1998. iRes *= -1;
  1999. }
  2000. switch (iRes)
  2001. {
  2002. case +1: // Item is bigger than bottom
  2003. case 0: // Item is identical to bottom
  2004. //
  2005. // Insert new item at the bottom index
  2006. //
  2007. dwResultIndex = dwNumItems;
  2008. VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
  2009. return dwRes;
  2010. default: // Item is smaller than bottom
  2011. //
  2012. // Do nothing
  2013. //
  2014. break;
  2015. }
  2016. //
  2017. // Search for insertion point
  2018. //
  2019. dwRes = BooleanSearchInsertionPoint (0,
  2020. dwNumItems - 1,
  2021. lparamItemData,
  2022. dwItemIndex,
  2023. dwResultIndex);
  2024. if (ERROR_SUCCESS != dwRes)
  2025. {
  2026. CALL_FAIL (GENERAL_ERR, TEXT("BooleanSearchInsertionPoint"), dwRes);
  2027. return dwRes;
  2028. }
  2029. return dwRes;
  2030. } // CFolderListView::FindInsertionIndex
  2031. DWORD
  2032. CFolderListView::BooleanSearchInsertionPoint (
  2033. DWORD dwTopIndex,
  2034. DWORD dwBottomIndex,
  2035. LPARAM lparamItemData,
  2036. DWORD dwItemIndex,
  2037. DWORD &dwResultIndex
  2038. )
  2039. /*++
  2040. Routine name : CFolderListView::BooleanSearchInsertionPoint
  2041. Routine description:
  2042. Recursively searches an insertion point for a list item.
  2043. Performs a boolean search.
  2044. This function must be called when the data critical section is held.
  2045. Author:
  2046. Eran Yariv (EranY), Feb, 2000
  2047. Arguments:
  2048. dwTopIndex [in] - Top list index
  2049. dwBottomIndex [in] - Bottom list index
  2050. lparamItemData [in] - Pointer to item
  2051. dwItemIndex [in] - Logical column item to compare by
  2052. dwResultIndex [out] - Insertion index
  2053. Return Value:
  2054. Standard Win32 error code
  2055. --*/
  2056. {
  2057. DWORD dwRes = ERROR_SUCCESS;
  2058. DBG_ENTER(TEXT("CFolderListView::BooleanSearchInsertionPoint"), dwRes);
  2059. ASSERTION (dwTopIndex <= dwBottomIndex);
  2060. if ((dwTopIndex == dwBottomIndex) || (dwTopIndex + 1 == dwBottomIndex))
  2061. {
  2062. dwResultIndex = dwBottomIndex;
  2063. VERBOSE (DBG_MSG, TEXT("Insertion point at index %ld"), dwResultIndex);
  2064. return dwRes;
  2065. }
  2066. DWORD dwMiddleIndex = dwTopIndex + (dwBottomIndex - dwTopIndex) / 2;
  2067. ASSERTION ((dwMiddleIndex != dwBottomIndex) && (dwMiddleIndex != dwTopIndex));
  2068. CListCtrl &refCtrl = GetListCtrl();
  2069. LPARAM lparamMiddle = refCtrl.GetItemData (dwMiddleIndex); // Pointer to item in middle index
  2070. ASSERTION (lparamMiddle);
  2071. //
  2072. // Get comparison result against middle index
  2073. //
  2074. int iRes = CompareItems ((CFaxMsg*)lparamItemData, (CFaxMsg*)lparamMiddle, dwItemIndex);
  2075. ASSERTION ((-1 <= iRes) && (+1 >= iRes));
  2076. if (!m_bSortAscending)
  2077. {
  2078. iRes *= -1;
  2079. }
  2080. switch (iRes)
  2081. {
  2082. case -1: // Item is smaller than middle
  2083. case 0: // Item is identical to middle
  2084. //
  2085. // Search between top and middle
  2086. //
  2087. dwRes = BooleanSearchInsertionPoint (dwTopIndex,
  2088. dwMiddleIndex,
  2089. lparamItemData,
  2090. dwItemIndex,
  2091. dwResultIndex);
  2092. break;
  2093. default: // Item is bigger than middle
  2094. //
  2095. // Search between middle and bottom
  2096. //
  2097. dwRes = BooleanSearchInsertionPoint (dwMiddleIndex,
  2098. dwBottomIndex,
  2099. lparamItemData,
  2100. dwItemIndex,
  2101. dwResultIndex);
  2102. break;
  2103. }
  2104. if (ERROR_SUCCESS != dwRes)
  2105. {
  2106. CALL_FAIL (GENERAL_ERR, TEXT("BooleanSearchInsertionPoint"), dwRes);
  2107. }
  2108. return dwRes;
  2109. } // CFolderListView::BooleanSearchInsertionPoint
  2110. DWORD
  2111. CFolderListView::AddSortedItem (
  2112. CViewRow &row,
  2113. LPARAM lparamItemData
  2114. )
  2115. /*++
  2116. Routine name : CFolderListView::AddSortedItem
  2117. Routine description:
  2118. Adds an item to the list, preserving list sort order.
  2119. This function must be called when the data critical section is held.
  2120. Author:
  2121. Eran Yariv (EranY), Jan, 2000
  2122. Arguments:
  2123. row [in] - Row of item view information
  2124. lparamItemData [in] - Item associated data
  2125. Return Value:
  2126. Standard Win32 error code
  2127. --*/
  2128. {
  2129. DWORD dwRes = ERROR_SUCCESS;
  2130. DBG_ENTER(TEXT("CFolderListView::AddSortedItem"),
  2131. dwRes,
  2132. TEXT("Type=%d"),
  2133. m_Type);
  2134. DWORD dwResultIndex;
  2135. //
  2136. // Find insertion index according to sort order
  2137. //
  2138. dwRes = FindInsertionIndex (lparamItemData, dwResultIndex);
  2139. if (ERROR_SUCCESS != dwRes)
  2140. {
  2141. CALL_FAIL (GENERAL_ERR, TEXT("FindInsertionIndex"), dwRes);
  2142. return dwRes;
  2143. }
  2144. //
  2145. // Add new item in insertion index
  2146. //
  2147. int iItemIndex;
  2148. dwRes = AddItem (dwResultIndex, row, lparamItemData, &iItemIndex);
  2149. if (ERROR_SUCCESS != dwRes)
  2150. {
  2151. CALL_FAIL (GENERAL_ERR, TEXT("AddItem"), dwRes);
  2152. return dwRes;
  2153. }
  2154. ASSERTION (ERROR_SUCCESS == dwRes);
  2155. return dwRes;
  2156. } // CFolderListView::AddSortedItem
  2157. DWORD
  2158. CFolderListView::UpdateSortedItem (
  2159. CViewRow &row,
  2160. LPARAM lparamItemData
  2161. )
  2162. /*++
  2163. Routine name : CFolderListView::UpdateSortedItem
  2164. Routine description:
  2165. Updates an item in the list, preserving list sort order.
  2166. This function must be called when the data critical section is held.
  2167. Author:
  2168. Eran Yariv (EranY), Jan, 2000
  2169. Arguments:
  2170. row [in] - Row of item view information
  2171. lparamItemData [in] - Item associated data
  2172. Return Value:
  2173. Standard Win32 error code
  2174. --*/
  2175. {
  2176. DWORD dwRes = ERROR_SUCCESS;
  2177. DBG_ENTER(TEXT("CFolderListView::UpdateSortedItem"),
  2178. dwRes,
  2179. TEXT("Type=%d"),
  2180. m_Type);
  2181. //
  2182. // Find the item in the list
  2183. //
  2184. CListCtrl &refCtrl = GetListCtrl();
  2185. LVFINDINFO lvfi;
  2186. lvfi.flags = LVFI_PARAM;
  2187. lvfi.lParam = lparamItemData;
  2188. int iCurIndex = refCtrl.FindItem (&lvfi);
  2189. if (-1 == iCurIndex)
  2190. {
  2191. dwRes = ERROR_NOT_FOUND;
  2192. CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::FindItem"), dwRes);
  2193. return dwRes;
  2194. }
  2195. #ifdef _DEBUG
  2196. LPARAM lparamCurrentItem = refCtrl.GetItemData (iCurIndex);
  2197. ASSERTION (lparamCurrentItem == lparamItemData);
  2198. #endif
  2199. BOOL bJustUpdate = TRUE; // If TRUE, we don't move the item in the list
  2200. if (0 <= m_nSortedCol)
  2201. {
  2202. //
  2203. // List is sorted.
  2204. // See if the displayed text is different than the updated text
  2205. //
  2206. CString cstrDisplayedCell;
  2207. try
  2208. {
  2209. cstrDisplayedCell = refCtrl.GetItemText (iCurIndex, m_nSortedCol);
  2210. }
  2211. catch (...)
  2212. {
  2213. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  2214. CALL_FAIL (MEM_ERR, TEXT ("CString::operator ="), dwRes);
  2215. return dwRes;
  2216. }
  2217. //
  2218. // Get item index to sort by
  2219. //
  2220. DWORD dwItemIndex = ItemIndexFromLogicalColumnIndex (m_nSortedCol);
  2221. const CString &cstrUpdatedString = row.GetItemString(dwItemIndex);
  2222. if (cstrUpdatedString.Compare (cstrDisplayedCell))
  2223. {
  2224. //
  2225. // Text in the sorted column is about to change.
  2226. // Sorry, but we must:
  2227. // 1. Remove old item from list
  2228. // 2. Insert new item (sorted)
  2229. //
  2230. bJustUpdate = FALSE;
  2231. }
  2232. }
  2233. if (bJustUpdate)
  2234. {
  2235. //
  2236. // All we need to do is update the text of the list item (all sub items) and its icon
  2237. //
  2238. dwRes = UpdateLineTextAndIcon (iCurIndex, row);
  2239. if (ERROR_SUCCESS != dwRes)
  2240. {
  2241. CALL_FAIL (RESOURCE_ERR, TEXT("UpdateLineTextAndIcon"), dwRes);
  2242. return dwRes;
  2243. }
  2244. }
  2245. else
  2246. {
  2247. //
  2248. // Since the text in the sorted column is different than the new text,
  2249. // we must remove the current item and insert a new (sorted) item.
  2250. //
  2251. BOOL bItemSelected = IsSelected (iCurIndex);
  2252. refCtrl.SetRedraw (FALSE);
  2253. if (!refCtrl.DeleteItem (iCurIndex))
  2254. {
  2255. //
  2256. // Failed to delete the item
  2257. //
  2258. dwRes = ERROR_GEN_FAILURE;
  2259. refCtrl.SetRedraw (TRUE);
  2260. CALL_FAIL (RESOURCE_ERR, TEXT("CListCtrl::DeleteItem"), dwRes);
  2261. return dwRes;
  2262. }
  2263. dwRes = AddSortedItem (row, lparamItemData);
  2264. if (ERROR_SUCCESS != dwRes)
  2265. {
  2266. CALL_FAIL (RESOURCE_ERR, TEXT("AddSortedItem"), dwRes);
  2267. refCtrl.SetRedraw (TRUE);
  2268. return dwRes;
  2269. }
  2270. if (bItemSelected)
  2271. {
  2272. //
  2273. // Since the item we removed was selected, we must also selected the new item
  2274. // we just added.
  2275. // Recalculate the possible operations the user can do on selected item.
  2276. //
  2277. Select (iCurIndex, TRUE);
  2278. RecalcPossibleOperations ();
  2279. }
  2280. refCtrl.SetRedraw (TRUE);
  2281. }
  2282. ASSERTION (ERROR_SUCCESS == dwRes);
  2283. return dwRes;
  2284. } // CFolderListView::UpdateSortedItem
  2285. DWORD
  2286. CFolderListView::ConfirmItemDelete(
  2287. BOOL& bConfirm
  2288. )
  2289. {
  2290. DWORD dwRes = ERROR_SUCCESS;
  2291. DBG_ENTER(TEXT("CFolderListView::ConfirmItemDelete"), dwRes);
  2292. //
  2293. // do we should ask to confirm ?
  2294. //
  2295. BOOL bAsk = theApp.GetProfileInt(CLIENT_CONFIRM_SEC, CLIENT_CONFIRM_ITEM_DEL, 1);
  2296. if(!bAsk)
  2297. {
  2298. bConfirm = TRUE;
  2299. return dwRes;
  2300. }
  2301. CListCtrl &refCtrl = GetListCtrl();
  2302. DWORD dwSelected = refCtrl.GetSelectedCount();
  2303. ASSERTION (dwSelected > 0);
  2304. //
  2305. // prepare message string
  2306. //
  2307. CString cstrMsg;
  2308. if(1 == dwSelected)
  2309. {
  2310. dwRes = LoadResourceString(cstrMsg, IDS_SURE_DELETE_ONE);
  2311. if (ERROR_SUCCESS != dwRes)
  2312. {
  2313. CALL_FAIL (RESOURCE_ERR, TEXT("LoadResourceString"), dwRes);
  2314. return dwRes;
  2315. }
  2316. }
  2317. else
  2318. {
  2319. //
  2320. // more then 1 selected
  2321. //
  2322. CString cstrCount;
  2323. try
  2324. {
  2325. cstrCount.Format(TEXT("%d"), dwSelected);
  2326. }
  2327. catch(...)
  2328. {
  2329. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  2330. CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
  2331. return dwRes;
  2332. }
  2333. try
  2334. {
  2335. AfxFormatString1(cstrMsg, IDS_SURE_DELETE_MANY, cstrCount);
  2336. }
  2337. catch(...)
  2338. {
  2339. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  2340. CALL_FAIL (MEM_ERR, TEXT("AfxFormatString1"), dwRes);
  2341. return dwRes;
  2342. }
  2343. }
  2344. //
  2345. // are you sure ?
  2346. //
  2347. DWORD dwAskRes = AlignedAfxMessageBox(cstrMsg, MB_YESNO | MB_ICONQUESTION);
  2348. bConfirm = (IDYES == dwAskRes);
  2349. return dwRes;
  2350. } // CFolderListView::ConfirmItemDelete
  2351. void
  2352. CFolderListView::OnDblClk(
  2353. NMHDR* pNMHDR,
  2354. LRESULT* pResult
  2355. )
  2356. {
  2357. DWORD nItem = ((NM_LISTVIEW*)pNMHDR)->iItem;
  2358. CListCtrl &refCtrl = GetListCtrl();
  2359. DWORD dwSelected = refCtrl.GetSelectedCount();
  2360. DWORD dwSelItem = refCtrl.GetNextItem (-1, LVNI_SELECTED);
  2361. if(1 == dwSelected && dwSelItem == nItem)
  2362. {
  2363. OnFolderItemView();
  2364. }
  2365. *pResult = 0;
  2366. }
  2367. DWORD
  2368. CFolderListView::FetchTiff (
  2369. CString &cstrTiff
  2370. )
  2371. /*++
  2372. Routine name : CFolderListView::FetchTiff
  2373. Routine description:
  2374. Fetches the TIFF image of the selected list item
  2375. Author:
  2376. Eran Yariv (EranY), Jan, 2000
  2377. Arguments:
  2378. cstrTiff [out] - Name of local TIFF file
  2379. Return Value:
  2380. Standard Win32 error code
  2381. --*/
  2382. {
  2383. DWORD dwRes = ERROR_SUCCESS;
  2384. DBG_ENTER(TEXT("CFolderListView::FetchTiff"), dwRes);
  2385. //
  2386. // Make sure there's exaclty one elemented selected
  2387. //
  2388. CListCtrl &refCtrl = GetListCtrl();
  2389. if (1 != refCtrl.GetSelectedCount())
  2390. {
  2391. return ERROR_CANTOPEN;
  2392. }
  2393. int iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
  2394. if (0 > iInd)
  2395. {
  2396. return ERROR_CANTOPEN;
  2397. }
  2398. CFaxMsg *pMsg = (CFaxMsg *) refCtrl.GetItemData (iInd);
  2399. if (pMsg == NULL)
  2400. {
  2401. return ERROR_CANTOPEN;
  2402. }
  2403. //
  2404. // Ask message to fetch the TIFF
  2405. //
  2406. dwRes = pMsg->GetTiff (cstrTiff);
  2407. if (ERROR_SUCCESS != dwRes)
  2408. {
  2409. CALL_FAIL (RPC_ERR, TEXT("CFaxMsg::GetTIFF"), dwRes);
  2410. }
  2411. return dwRes;
  2412. } // CFolderListView::FetchTiff
  2413. void
  2414. CFolderListView::OnFolderItemDelete ()
  2415. /*++
  2416. Routine name : CFolderListView::OnFolderItemDelete
  2417. Routine description:
  2418. Handles message delete commands
  2419. Author:
  2420. Eran Yariv (EranY), Jan, 2000
  2421. Arguments:
  2422. Return Value:
  2423. None.
  2424. --*/
  2425. {
  2426. DBG_ENTER(TEXT("CFolderListView::OnFolderItemDelete"),
  2427. TEXT("Type=%d"),
  2428. m_Type);
  2429. //
  2430. // are you sure ?
  2431. //
  2432. BOOL bConfirm;
  2433. DWORD dwRes = ConfirmItemDelete(bConfirm);
  2434. if (ERROR_SUCCESS != dwRes)
  2435. {
  2436. PopupError (dwRes);
  2437. CALL_FAIL (GENERAL_ERR, TEXT("ConfirmItemDelete"), dwRes);
  2438. return;
  2439. }
  2440. if(!bConfirm)
  2441. {
  2442. //
  2443. // not sure.
  2444. //
  2445. return;
  2446. }
  2447. CWaitCursor waitCursor;
  2448. CClientConsoleDoc* pDoc = GetDocument();
  2449. ASSERTION (pDoc);
  2450. CServerNode* pServer = NULL;
  2451. CFolder* pFolder = NULL;
  2452. //
  2453. // Iterate set of selected messages, deleting each message in the set
  2454. //
  2455. CListCtrl &refCtrl = GetListCtrl();
  2456. DWORD dwSelected = refCtrl.GetSelectedCount();
  2457. if(0 == dwSelected)
  2458. {
  2459. return;
  2460. }
  2461. if (dwSelected > 1)
  2462. {
  2463. //
  2464. // Disable refresh while deleting
  2465. //
  2466. refCtrl.SetRedraw (FALSE);
  2467. //
  2468. // Prevent costy re-calc on every deletion
  2469. //
  2470. m_bInMultiItemsOperation = TRUE;
  2471. JobOpProgressDlgStart(FAX_JOB_OP_DELETE, dwSelected);
  2472. }
  2473. int iInd;
  2474. CFaxMsg* pMsg;
  2475. DWORDLONG dwlMsgId;
  2476. for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
  2477. {
  2478. iInd = refCtrl.GetNextItem (-1, LVNI_SELECTED);
  2479. if(iInd < 0)
  2480. {
  2481. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
  2482. break;
  2483. }
  2484. pMsg = (CFaxMsg *) refCtrl.GetItemData (iInd);
  2485. ASSERTION (pMsg);
  2486. dwlMsgId = pMsg->GetId();
  2487. //
  2488. // Ask message to delete
  2489. //
  2490. dwRes = pMsg->Delete ();
  2491. if (ERROR_SUCCESS != dwRes)
  2492. {
  2493. PopupError (dwRes);
  2494. CALL_FAIL (RPC_ERR, TEXT("CArchiveMsg::Delete"), dwRes);
  2495. //
  2496. // We exit upon first error
  2497. //
  2498. goto exit;
  2499. }
  2500. //
  2501. // delete a message from the data map and from the view
  2502. //
  2503. pServer = pMsg->GetServer();
  2504. ASSERTION (pServer);
  2505. pFolder = pServer->GetFolder(m_Type);
  2506. ASSERTION (pFolder);
  2507. dwRes = pFolder->OnJobRemoved(dwlMsgId, pMsg);
  2508. if (ERROR_SUCCESS != dwRes)
  2509. {
  2510. PopupError (dwRes);
  2511. CALL_FAIL (RPC_ERR, TEXT("CMessageFolder::OnJobRemoved"), dwRes);
  2512. goto exit;
  2513. }
  2514. if(m_bInMultiItemsOperation)
  2515. {
  2516. JobOpProgressDlgInc();
  2517. }
  2518. }
  2519. exit:
  2520. if (m_bInMultiItemsOperation)
  2521. {
  2522. JobOpProgressDlgStop();
  2523. //
  2524. // Re-enable redraw
  2525. //
  2526. refCtrl.SetRedraw (TRUE);
  2527. //
  2528. // Ask for visual refresh of view
  2529. //
  2530. refCtrl.Invalidate ();
  2531. m_bInMultiItemsOperation = FALSE;
  2532. RecalcPossibleOperations ();
  2533. }
  2534. if(FOLDER_TYPE_INBOX == m_Type)
  2535. {
  2536. theApp.InboxViewed();
  2537. }
  2538. } // CFolderListView::OnFolderItemDelete
  2539. void
  2540. CFolderListView::CountColumns (
  2541. int *lpItems
  2542. )
  2543. /*++
  2544. Routine name : CFolderListView::CountColumns
  2545. Routine description:
  2546. Sets the items to be seen in the view.
  2547. Author:
  2548. Eran Yariv (EranY), Jan, 2000
  2549. Arguments:
  2550. lpItems [in] - List of items. ends with MSG_VIEW_ITEM_END
  2551. Return Value:
  2552. None.
  2553. --*/
  2554. {
  2555. DBG_ENTER(TEXT("CFolderListView::CountColumns"));
  2556. m_dwAvailableColumnsNum = 0;
  2557. MsgViewItemType *pItems = (MsgViewItemType *)lpItems;
  2558. m_pAvailableColumns = pItems;
  2559. while (MSG_VIEW_ITEM_END != *pItems)
  2560. {
  2561. ASSERTION (*pItems < MSG_VIEW_ITEM_END);
  2562. ++m_dwAvailableColumnsNum;
  2563. ++pItems;
  2564. }
  2565. ASSERTION (m_dwAvailableColumnsNum);
  2566. } // CFolderListView::CountColumns
  2567. int
  2568. CFolderListView::CompareItems (
  2569. CFaxMsg* pFaxMsg1,
  2570. CFaxMsg* pFaxMsg2,
  2571. DWORD dwItemIndex
  2572. ) const
  2573. /*++
  2574. Routine name : CFolderListView::CompareItems
  2575. Routine description:
  2576. Compares two archive items
  2577. Author:
  2578. Eran Yariv (EranY), Jan, 2000
  2579. Arguments:
  2580. pFaxMsg1 [in] - Pointer to 1st message
  2581. pFaxMsg2 [in] - Pointer to 2nd message
  2582. dwItemIndex [in] - Item (in the message) to comapre by
  2583. Return Value:
  2584. -1 if message1 < message2, 0 if identical, +1 if message1 > message2
  2585. --*/
  2586. {
  2587. DBG_ENTER(TEXT("CFolderListView::CompareItems"));
  2588. ASSERTION (dwItemIndex < MSG_VIEW_ITEM_END);
  2589. static CViewRow rowView1;
  2590. static CViewRow rowView2;
  2591. DWORD dwRes = rowView1.AttachToMsg (pFaxMsg1, FALSE);
  2592. if (ERROR_SUCCESS != dwRes)
  2593. {
  2594. CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
  2595. return 0;
  2596. }
  2597. dwRes = rowView2.AttachToMsg (pFaxMsg2, FALSE);
  2598. if (ERROR_SUCCESS != dwRes)
  2599. {
  2600. CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
  2601. return 0;
  2602. }
  2603. return rowView1.CompareByItem (rowView2, dwItemIndex);
  2604. }
  2605. DWORD
  2606. CFolderListView::AddMsgMapToView(
  2607. MSGS_MAP* pMap
  2608. )
  2609. /*++
  2610. Routine name : CFolderListView::AddMsgMapToView
  2611. Routine description:
  2612. Add messages from the map to the view
  2613. Arguments:
  2614. pMap [in] - masage map
  2615. Return Value:
  2616. error code
  2617. --*/
  2618. {
  2619. DWORD dwRes = ERROR_SUCCESS;
  2620. DBG_ENTER(TEXT("CFolderListView::AddMsgMapToView"));
  2621. ASSERTION(pMap);
  2622. CListCtrl &listCtrl = GetListCtrl();
  2623. DWORD dwCount = listCtrl.GetItemCount();
  2624. listCtrl.SetRedraw (FALSE);
  2625. CFaxMsg* pMsg;
  2626. CViewRow viewRow;
  2627. int iIndexToSelect = -1;
  2628. for (MSGS_MAP::iterator it = pMap->begin(); it != pMap->end(); ++it)
  2629. {
  2630. int iItemIndex;
  2631. pMsg = (*it).second;
  2632. dwRes = viewRow.AttachToMsg (pMsg);
  2633. if (ERROR_SUCCESS != dwRes)
  2634. {
  2635. CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
  2636. break;
  2637. }
  2638. dwRes = AddItem (dwCount++, viewRow, (LPARAM)pMsg, &iItemIndex);
  2639. if (ERROR_SUCCESS != dwRes)
  2640. {
  2641. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddItem"), dwRes);
  2642. break;
  2643. }
  2644. if ((-1 == iIndexToSelect) && // No item selected yet and
  2645. m_dwlMsgToSelect && // We should keep our eyes open for an item to select and
  2646. (pMsg->GetId () == m_dwlMsgToSelect)) // Match found !!
  2647. {
  2648. //
  2649. // This is the startup selected item.
  2650. // Save the item index
  2651. //
  2652. iIndexToSelect = iItemIndex;
  2653. }
  2654. }
  2655. if (-1 != iIndexToSelect)
  2656. {
  2657. //
  2658. // We have the user-specified-item-to-select in the list now
  2659. //
  2660. SelectItemByIndex (iIndexToSelect);
  2661. }
  2662. listCtrl.SetRedraw ();
  2663. return dwRes;
  2664. } // CFolderListView::AddMsgMapToView
  2665. void
  2666. CFolderListView::OnUpdate (
  2667. CView* pSender,
  2668. LPARAM lHint,
  2669. CObject* pHint
  2670. )
  2671. /*++
  2672. Routine name : CFolderListView::OnUpdate
  2673. Routine description:
  2674. Receives a notification that the view should update itself
  2675. Author:
  2676. Eran Yariv (EranY), Jan, 2000
  2677. Arguments:
  2678. pSender [in] - Unused
  2679. lHint [in] - Hint of update operation
  2680. pHint [in] - If lHint is UPDATE_HINT_CLEAR_VIEW or UPDATE_HINT_FILL_VIEW
  2681. then pHint is a pointer to the folder that requested an update.
  2682. If lHint is UPDATE_HINT_REMOVE_ITEM, UPDATE_HINT_ADD_ITEM, or
  2683. UPDATE_HINT_UPDATE_ITEM,
  2684. then pHint is a pointer to the job to remove / add / update.
  2685. Otherwise, pHint is undefined.
  2686. Return Value:
  2687. None.
  2688. --*/
  2689. {
  2690. DBG_ENTER(TEXT("CFolderListView::OnUpdate"),
  2691. TEXT("Hint=%ld, Type=%d"),
  2692. lHint,
  2693. m_Type);
  2694. OnUpdateHintType hint = (OnUpdateHintType) lHint;
  2695. DWORD dwRes;
  2696. CListCtrl &listCtrl = GetListCtrl();
  2697. switch (hint)
  2698. {
  2699. case UPDATE_HINT_CREATION:
  2700. //
  2701. // Do nothing
  2702. //
  2703. break;
  2704. case UPDATE_HINT_CLEAR_VIEW:
  2705. //
  2706. // Clear the entire list control now
  2707. //
  2708. if (!listCtrl.DeleteAllItems ())
  2709. {
  2710. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::DeleteAllItems"), ERROR_GEN_FAILURE);
  2711. }
  2712. ClearPossibleOperations ();
  2713. break;
  2714. case UPDATE_HINT_ADD_CHUNK:
  2715. {
  2716. ASSERTION (pHint);
  2717. MSGS_MAP* pMap = (MSGS_MAP*) pHint;
  2718. dwRes = AddMsgMapToView(pMap);
  2719. if (ERROR_SUCCESS != dwRes)
  2720. {
  2721. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddMsgMapToView"), dwRes);
  2722. }
  2723. }
  2724. break;
  2725. case UPDATE_HINT_FILL_VIEW:
  2726. //
  2727. // Fill the list control with my parents data
  2728. //
  2729. {
  2730. ASSERTION (pHint);
  2731. CFolder *pFolder = (CFolder *) pHint;
  2732. pFolder->EnterData ();
  2733. MSGS_MAP &ParentMap = pFolder->GetData ();
  2734. dwRes = AddMsgMapToView(&ParentMap);
  2735. if (ERROR_SUCCESS != dwRes)
  2736. {
  2737. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddMsgMapToView"), dwRes);
  2738. }
  2739. pFolder->LeaveData ();
  2740. }
  2741. break;
  2742. case UPDATE_HINT_REMOVE_ITEM:
  2743. //
  2744. // The data critical section must be held.
  2745. //
  2746. {
  2747. CFaxMsg* pMsg = (CFaxMsg*)pHint;
  2748. ASSERTION(pMsg);
  2749. dwRes = RemoveItem ((LPARAM)pMsg);
  2750. if (ERROR_SUCCESS != dwRes)
  2751. {
  2752. //
  2753. // Failed to remove item from list
  2754. //
  2755. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::RemoveItem"), dwRes);
  2756. ASSERTION_FAILURE;
  2757. }
  2758. }
  2759. break;
  2760. case UPDATE_HINT_ADD_ITEM:
  2761. //
  2762. // The data critical section must be held.
  2763. //
  2764. {
  2765. CFaxMsg* pMsg = (CFaxMsg*)pHint;
  2766. ASSERTION(pMsg);
  2767. CViewRow viewRow;
  2768. dwRes = viewRow.AttachToMsg (pMsg);
  2769. if (ERROR_SUCCESS != dwRes)
  2770. {
  2771. CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
  2772. return;
  2773. }
  2774. dwRes = AddSortedItem (viewRow, (LPARAM)pMsg);
  2775. if (ERROR_SUCCESS != dwRes)
  2776. {
  2777. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::AddSortedItem"), dwRes);
  2778. return;
  2779. }
  2780. }
  2781. break;
  2782. case UPDATE_HINT_UPDATE_ITEM:
  2783. //
  2784. // The data critical section must be held.
  2785. //
  2786. {
  2787. CFaxMsg* pMsg = (CFaxMsg*)pHint;
  2788. ASSERTION(pMsg);
  2789. CViewRow viewRow;
  2790. dwRes = viewRow.AttachToMsg (pMsg);
  2791. if (ERROR_SUCCESS != dwRes)
  2792. {
  2793. CALL_FAIL (GENERAL_ERR, TEXT("CViewRow::AttachToMsg"), dwRes);
  2794. return;
  2795. }
  2796. dwRes = UpdateSortedItem (viewRow, (LPARAM)pMsg);
  2797. if (ERROR_SUCCESS != dwRes)
  2798. {
  2799. CALL_FAIL (GENERAL_ERR, TEXT("CFolderListView::UpdateSortedItem"), dwRes);
  2800. return;
  2801. }
  2802. }
  2803. break;
  2804. default:
  2805. //
  2806. // Unsupported hint
  2807. //
  2808. ASSERTION_FAILURE;
  2809. }
  2810. if(!m_bInMultiItemsOperation)
  2811. {
  2812. RecalcPossibleOperations ();
  2813. }
  2814. CMainFrame *pFrm = GetFrm();
  2815. if (pFrm)
  2816. {
  2817. pFrm->RefreshStatusBar();
  2818. }
  2819. } // CFolderListView::OnUpdate
  2820. int
  2821. CFolderListView::GetPopupMenuResource () const
  2822. {
  2823. DBG_ENTER(TEXT("CFolderListView::GetPopupMenuResource"));
  2824. int nMenuRes=0;
  2825. switch(m_Type)
  2826. {
  2827. case FOLDER_TYPE_INCOMING:
  2828. nMenuRes = IDM_INCOMING;
  2829. break;
  2830. case FOLDER_TYPE_INBOX:
  2831. nMenuRes = IDM_INBOX;
  2832. break;
  2833. case FOLDER_TYPE_SENT_ITEMS:
  2834. nMenuRes = IDM_SENTITEMS;
  2835. break;
  2836. case FOLDER_TYPE_OUTBOX:
  2837. nMenuRes = IDM_OUTBOX;
  2838. break;
  2839. default:
  2840. ASSERTION_FAILURE
  2841. break;
  2842. }
  2843. return nMenuRes;
  2844. }
  2845. void
  2846. CFolderListView::OnFolderItemPause ()
  2847. /*++
  2848. Routine name : CFolderListView::OnFolderItemPause
  2849. Routine description:
  2850. Handles job pause commands
  2851. Author:
  2852. Eran Yariv (EranY), Jan, 2000
  2853. Arguments:
  2854. Return Value:
  2855. None.
  2856. --*/
  2857. {
  2858. DBG_ENTER(TEXT("CFolderListView::OnFolderItemPause"),
  2859. TEXT("Type=%d"),
  2860. m_Type);
  2861. CWaitCursor waitCursor;
  2862. //
  2863. // Iterate set of selected jobs, pausing each job in the set
  2864. //
  2865. CListCtrl &refCtrl = GetListCtrl();
  2866. DWORD dwSelected = refCtrl.GetSelectedCount();
  2867. ASSERTION (dwSelected);
  2868. int iInd = -1;
  2869. if(dwSelected > 1)
  2870. {
  2871. m_bInMultiItemsOperation = TRUE;
  2872. JobOpProgressDlgStart(FAX_JOB_OP_PAUSE, dwSelected);
  2873. }
  2874. for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
  2875. {
  2876. iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
  2877. if(iInd < 0)
  2878. {
  2879. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
  2880. break;
  2881. }
  2882. CFaxMsg* pJob = (CFaxMsg*) refCtrl.GetItemData (iInd);
  2883. ASSERT_KINDOF(CJob, pJob);
  2884. //
  2885. // Ask job to pause
  2886. //
  2887. DWORD dwRes = pJob->Pause ();
  2888. if (ERROR_SUCCESS != dwRes)
  2889. {
  2890. PopupError (dwRes);
  2891. CALL_FAIL (RPC_ERR, TEXT("CJob::Pause"), dwRes);
  2892. //
  2893. // We exit upon first error
  2894. //
  2895. goto exit;
  2896. }
  2897. //
  2898. // update the view
  2899. //
  2900. OnUpdate (NULL, UPDATE_HINT_UPDATE_ITEM, pJob);
  2901. if(m_bInMultiItemsOperation)
  2902. {
  2903. JobOpProgressDlgInc();
  2904. }
  2905. }
  2906. exit:
  2907. if(m_bInMultiItemsOperation)
  2908. {
  2909. m_bInMultiItemsOperation = FALSE;
  2910. JobOpProgressDlgStop();
  2911. RecalcPossibleOperations();
  2912. }
  2913. } // CFolderListView::OnFolderItemPause
  2914. void CFolderListView::OnFolderItemResume ()
  2915. /*++
  2916. Routine name : CFolderListView::OnFolderItemResume
  2917. Routine description:
  2918. Handles job resume commands
  2919. Author:
  2920. Eran Yariv (EranY), Jan, 2000
  2921. Arguments:
  2922. Return Value:
  2923. None.
  2924. --*/
  2925. {
  2926. DBG_ENTER(TEXT("CFolderListView::OnFolderItemResume"),
  2927. TEXT("Type=%d"),
  2928. m_Type);
  2929. CWaitCursor waitCursor;
  2930. //
  2931. // Iterate set of selected jobs, resuming each job in the set
  2932. //
  2933. CListCtrl &refCtrl = GetListCtrl();
  2934. DWORD dwSelected = refCtrl.GetSelectedCount();
  2935. ASSERTION (dwSelected);
  2936. if(dwSelected > 1)
  2937. {
  2938. m_bInMultiItemsOperation = TRUE;
  2939. JobOpProgressDlgStart(FAX_JOB_OP_RESUME, dwSelected);
  2940. }
  2941. int iInd = -1;
  2942. for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
  2943. {
  2944. iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
  2945. if(iInd < 0)
  2946. {
  2947. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
  2948. break;
  2949. }
  2950. CFaxMsg* pJob = (CFaxMsg*) refCtrl.GetItemData (iInd);
  2951. ASSERT_KINDOF(CJob, pJob);
  2952. //
  2953. // Ask job to resume
  2954. //
  2955. DWORD dwRes = pJob->Resume ();
  2956. if (ERROR_SUCCESS != dwRes)
  2957. {
  2958. PopupError (dwRes);
  2959. CALL_FAIL (RPC_ERR, TEXT("CJob::Resume"), dwRes);
  2960. //
  2961. // We exit upon first error
  2962. //
  2963. goto exit;
  2964. }
  2965. //
  2966. // update the view
  2967. //
  2968. OnUpdate (NULL, UPDATE_HINT_UPDATE_ITEM, pJob);
  2969. if(m_bInMultiItemsOperation)
  2970. {
  2971. JobOpProgressDlgInc();
  2972. }
  2973. }
  2974. exit:
  2975. if(m_bInMultiItemsOperation)
  2976. {
  2977. m_bInMultiItemsOperation = FALSE;
  2978. JobOpProgressDlgStop();
  2979. RecalcPossibleOperations();
  2980. }
  2981. } // CFolderListView::OnFolderItemResume
  2982. void
  2983. CFolderListView::OnFolderItemRestart ()
  2984. /*++
  2985. Routine name : CFolderListView::OnFolderItemRestart
  2986. Routine description:
  2987. Handles job restart commands
  2988. Author:
  2989. Eran Yariv (EranY), Jan, 2000
  2990. Arguments:
  2991. Return Value:
  2992. None.
  2993. --*/
  2994. {
  2995. DBG_ENTER(TEXT("CFolderListView::OnFolderItemRestart"),
  2996. TEXT("Type=%d"),
  2997. m_Type);
  2998. CWaitCursor waitCursor;
  2999. //
  3000. // Iterate set of selected jobs, restarting each job in the set
  3001. //
  3002. CListCtrl &refCtrl = GetListCtrl();
  3003. DWORD dwSelected = refCtrl.GetSelectedCount();
  3004. ASSERTION (dwSelected);
  3005. if(dwSelected > 1)
  3006. {
  3007. m_bInMultiItemsOperation = TRUE;
  3008. JobOpProgressDlgStart(FAX_JOB_OP_RESTART, dwSelected);
  3009. }
  3010. int iInd = -1;
  3011. for (DWORD dwItem = 0; dwItem < dwSelected && !m_bJobOpCancel; ++dwItem)
  3012. {
  3013. iInd = refCtrl.GetNextItem (iInd, LVNI_SELECTED);
  3014. if(iInd < 0)
  3015. {
  3016. CALL_FAIL (WINDOW_ERR, TEXT("CListCtrl::GetNextItem"), 0);
  3017. break;
  3018. }
  3019. CFaxMsg* pJob = (CFaxMsg*) refCtrl.GetItemData (iInd);
  3020. ASSERT_KINDOF(CJob, pJob);
  3021. //
  3022. // Ask job to restart
  3023. //
  3024. DWORD dwRes = pJob->Restart ();
  3025. if (ERROR_SUCCESS != dwRes)
  3026. {
  3027. PopupError (dwRes);
  3028. CALL_FAIL (RPC_ERR, TEXT("CJob::Restart"), dwRes);
  3029. //
  3030. // We exit upon first error
  3031. //
  3032. goto exit;
  3033. }
  3034. //
  3035. // update the view
  3036. //
  3037. OnUpdate (NULL, UPDATE_HINT_UPDATE_ITEM, pJob);
  3038. if(m_bInMultiItemsOperation)
  3039. {
  3040. JobOpProgressDlgInc();
  3041. }
  3042. }
  3043. exit:
  3044. if(m_bInMultiItemsOperation)
  3045. {
  3046. m_bInMultiItemsOperation = FALSE;
  3047. JobOpProgressDlgStop();
  3048. RecalcPossibleOperations();
  3049. }
  3050. } // CFolderListView::OnFolderItemRestart
  3051. void
  3052. CFolderListView::OnChar(
  3053. UINT nChar,
  3054. UINT nRepCnt,
  3055. UINT nFlags
  3056. )
  3057. /*++
  3058. Routine name : CFolderListView::OnChar
  3059. Routine description:
  3060. The framework calls this member function when a keystroke translates
  3061. to a nonsystem character
  3062. Arguments:
  3063. nChar [in] - Contains the character code value of the key.
  3064. nRepCnt [in] - Contains the repeat count
  3065. nFlags [in] - Contains the scan code
  3066. Return Value:
  3067. None.
  3068. --*/
  3069. {
  3070. if(VK_TAB == nChar)
  3071. {
  3072. CMainFrame *pFrm = GetFrm();
  3073. if (!pFrm)
  3074. {
  3075. //
  3076. // Shutdown in progress
  3077. //
  3078. return;
  3079. }
  3080. CLeftView* pLeftView = pFrm->GetLeftView();
  3081. if(pLeftView)
  3082. {
  3083. pLeftView->SetFocus();
  3084. }
  3085. }
  3086. else
  3087. {
  3088. CListView::OnChar(nChar, nRepCnt, nFlags);
  3089. }
  3090. }
  3091. afx_msg void
  3092. CFolderListView::OnContextMenu(
  3093. CWnd *pWnd,
  3094. CPoint pos
  3095. )
  3096. {
  3097. DBG_ENTER(TEXT("CFolderListView::OnContextMenu"),
  3098. TEXT("Type=%d"),
  3099. m_Type);
  3100. CListCtrl &refCtrl = GetListCtrl();
  3101. DWORD dwSelected = refCtrl.GetSelectedCount();
  3102. if (!dwSelected)
  3103. {
  3104. //
  3105. // If no item is selected, this is equivalent to right-clicking an empty area in the list view
  3106. // which does nothing.
  3107. //
  3108. return;
  3109. }
  3110. if (pos.x == -1 && pos.y == -1)
  3111. {
  3112. //
  3113. // Keyboard (VK_APP or Shift + F10)
  3114. //
  3115. //
  3116. // Pop the context menu near the mouse cursor
  3117. //
  3118. pos = (CPoint) GetMessagePos();
  3119. }
  3120. int iMenuResource = GetPopupMenuResource ();
  3121. if(0 == iMenuResource)
  3122. {
  3123. ASSERTION_FAILURE;
  3124. return;
  3125. }
  3126. ScreenToClient(&pos);
  3127. CMenu mnuContainer;
  3128. if (!mnuContainer.LoadMenu (iMenuResource))
  3129. {
  3130. CALL_FAIL (RESOURCE_ERR, TEXT("CMenu::LoadMenu"), ERROR_GEN_FAILURE);
  3131. return;
  3132. }
  3133. CMenu *pmnuPopup = mnuContainer.GetSubMenu (0);
  3134. ASSERTION (pmnuPopup);
  3135. ClientToScreen(&pos);
  3136. if (!pmnuPopup->TrackPopupMenu (TPM_LEFTALIGN,
  3137. pos.x,
  3138. pos.y,
  3139. theApp.m_pMainWnd))
  3140. {
  3141. CALL_FAIL (RESOURCE_ERR, TEXT("CMenu::TrackPopupMenu"), ERROR_GEN_FAILURE);
  3142. }
  3143. } // CFolderListView::OnContextMenu
  3144. void
  3145. CFolderListView::SelectItemById (
  3146. DWORDLONG dwlMsgId
  3147. )
  3148. /*++
  3149. Routine name : CFolderListView::SelectItemById
  3150. Routine description:
  3151. Selects an item in the list control, by its message id
  3152. Author:
  3153. Eran Yariv (EranY), May, 2001
  3154. Arguments:
  3155. dwlMsgId [in] - Message id
  3156. Return Value:
  3157. None.
  3158. --*/
  3159. {
  3160. DBG_ENTER(TEXT("CFolderListView::SelectItemById"),
  3161. TEXT("Message id=%0xI64d"),
  3162. dwlMsgId);
  3163. ASSERTION (dwlMsgId);
  3164. int iMsgIndex = FindItemIndexFromID (dwlMsgId);
  3165. if (-1 == iMsgIndex)
  3166. {
  3167. //
  3168. // Message could not be found in the list.
  3169. // This usually happens when we handle a WM_CONSOLE_SELECT_ITEM message sent to the main frame
  3170. // but the folder is in the middle of refresh and the requested message might not be there yet.
  3171. //
  3172. // By setting m_dwlMsgToSelect = dwlMsgId we signal the OnFolderRefreshEnded() funtion to call us again
  3173. // once refresh has ended.
  3174. //
  3175. VERBOSE (DBG_MSG, TEXT("Item not found - doing nothing"));
  3176. m_dwlMsgToSelect = dwlMsgId;
  3177. return;
  3178. }
  3179. SelectItemByIndex (iMsgIndex);
  3180. } // CFolderListView::SelectItemById
  3181. void
  3182. CFolderListView::SelectItemByIndex (
  3183. int iMsgIndex
  3184. )
  3185. /*++
  3186. Routine name : CFolderListView::SelectItemByIndex
  3187. Routine description:
  3188. Selects an item in the list control, by its list item index
  3189. Author:
  3190. Eran Yariv (EranY), May, 2001
  3191. Arguments:
  3192. dwlMsgId [in] - List item index
  3193. Return Value:
  3194. None.
  3195. --*/
  3196. {
  3197. DBG_ENTER(TEXT("CFolderListView::SelectItemByIndex"),
  3198. TEXT("Index = %ld"),
  3199. iMsgIndex);
  3200. CListCtrl &refCtrl = GetListCtrl();
  3201. ASSERTION (iMsgIndex >= 0 && iMsgIndex < refCtrl.GetItemCount());
  3202. OnSelectNone();
  3203. refCtrl.SetItemState (iMsgIndex,
  3204. LVIS_SELECTED | LVIS_FOCUSED,
  3205. LVIS_SELECTED | LVIS_FOCUSED);
  3206. refCtrl.EnsureVisible (iMsgIndex, FALSE);
  3207. refCtrl.SetFocus();
  3208. //
  3209. // Make sure this item won't be selected again
  3210. //
  3211. m_dwlMsgToSelect = 0;
  3212. } // CFolderListView::SelectItemByIndex
  3213. int
  3214. CFolderListView::FindItemIndexFromID (
  3215. DWORDLONG dwlMsgId
  3216. )
  3217. /*++
  3218. Routine name : CFolderListView::FindItemIndexFromID
  3219. Routine description:
  3220. Finds the list view item index of a message by a message id
  3221. Author:
  3222. Eran Yariv (EranY), May, 2001
  3223. Arguments:
  3224. dwlMsgId [in] - Message id
  3225. Return Value:
  3226. Item index. -1 if not found
  3227. --*/
  3228. {
  3229. DBG_ENTER(TEXT("CFolderListView::FindItemIndexFromID"),
  3230. TEXT("Message id=%0xI64d"),
  3231. dwlMsgId);
  3232. CListCtrl &refCtrl = GetListCtrl();
  3233. int iItemCount = refCtrl.GetItemCount();
  3234. //
  3235. // We must traverse the entire list and look for the message that matches the id.
  3236. //
  3237. for (int iIndex = 0; iIndex < iItemCount; iIndex++)
  3238. {
  3239. CFaxMsg *pMsg = (CFaxMsg*)refCtrl.GetItemData (iIndex);
  3240. if (dwlMsgId == pMsg->GetId())
  3241. {
  3242. //
  3243. // Found it
  3244. //
  3245. return iIndex;
  3246. }
  3247. }
  3248. return -1;
  3249. } // CFolderListView::FindItemIndexFromID
  3250. INT_PTR
  3251. CALLBACK
  3252. CFolderListView::JobOpProgressDlgProc(
  3253. HWND hwndDlg, // handle to dialog box
  3254. UINT uMsg, // message
  3255. WPARAM wParam, // first message parameter
  3256. LPARAM lParam // second message parameter
  3257. )
  3258. /*++
  3259. Routine description:
  3260. Job operation progress dialog
  3261. Arguments:
  3262. HWND hwndDlg, // handle to dialog box
  3263. UINT uMsg, // message
  3264. WPARAM wParam, // first message parameter
  3265. LPARAM lParam // second message parameter
  3266. Return Value:
  3267. return TRUE if it processed the message
  3268. --*/
  3269. {
  3270. static CFolderListView* pFolderView = NULL;
  3271. switch (uMsg)
  3272. {
  3273. case WM_INITDIALOG:
  3274. pFolderView = (CFolderListView*)lParam;
  3275. return FALSE;
  3276. case WM_COMMAND:
  3277. switch (LOWORD(wParam))
  3278. {
  3279. case IDCANCEL:
  3280. pFolderView->m_bJobOpCancel = TRUE;
  3281. ::EnableWindow(::GetDlgItem(hwndDlg, IDCANCEL), FALSE);
  3282. return TRUE;
  3283. }
  3284. break;
  3285. }
  3286. return FALSE;
  3287. } // CFolderListView::JobOpProgressDlgProc
  3288. BOOL
  3289. CFolderListView::JobOpProgressDlgStart(
  3290. FAX_ENUM_JOB_OP opJob,
  3291. DWORD dwItems
  3292. )
  3293. /*++
  3294. Routine name : CFolderListView::JobOpProgressDlgStart
  3295. Routine description:
  3296. Open and initialize multi job operation dialog
  3297. Arguments:
  3298. opJob [in]- operation type FAX_ENUM_JOB_OP enum
  3299. dwItems [in]- number of iterations
  3300. Return Value:
  3301. TRUE if success
  3302. FALSE otherwise
  3303. --*/
  3304. {
  3305. DBG_ENTER(TEXT("CFolderListView::JobOpProgressDlgStart"));
  3306. HWND hProgressDlg = CreateDialogParam(GetResourceHandle(), // handle to module
  3307. MAKEINTRESOURCE(IDD_FAX_PROGRESS), // dialog box template name
  3308. theApp.m_pMainWnd->m_hWnd, // handle to owner window
  3309. JobOpProgressDlgProc, // dialog box procedure
  3310. (LPARAM)this); // initialization value
  3311. if(!hProgressDlg)
  3312. {
  3313. CALL_FAIL (WINDOW_ERR, TEXT("CreateDialog"), GetLastError());
  3314. return FALSE;
  3315. }
  3316. //
  3317. // Set title string
  3318. //
  3319. DWORD dwTitleID=0;
  3320. TCHAR szTitle[MAX_PATH]={0};
  3321. switch(opJob)
  3322. {
  3323. case FAX_JOB_OP_PAUSE:
  3324. dwTitleID = IDS_PROGRESS_PAUSE;
  3325. break;
  3326. case FAX_JOB_OP_RESUME:
  3327. dwTitleID = IDS_PROGRESS_RESUME;
  3328. break;
  3329. case FAX_JOB_OP_RESTART:
  3330. dwTitleID = IDS_PROGRESS_RESTART;
  3331. break;
  3332. case FAX_JOB_OP_DELETE:
  3333. dwTitleID = IDS_PROGRESS_DELETE;
  3334. break;
  3335. default:
  3336. ASSERTION_FAILURE;
  3337. break;
  3338. }
  3339. if(LoadString(GetResourceHandle(), dwTitleID, szTitle, ARR_SIZE(szTitle)))
  3340. {
  3341. ::SetDlgItemText(hProgressDlg, IDC_PROGRESS_TITLE, szTitle);
  3342. }
  3343. else
  3344. {
  3345. CALL_FAIL (RESOURCE_ERR, TEXT("LoadString"), GetLastError());
  3346. }
  3347. //
  3348. // Init progress bar
  3349. //
  3350. m_dwJobOpPos = 0;
  3351. m_dwJobOpItems = dwItems;
  3352. ::SendDlgItemMessage(hProgressDlg, IDC_PROGRESS_BAR, PBM_SETRANGE32, 0, dwItems);
  3353. ::SendDlgItemMessage(hProgressDlg, IDC_PROGRESS_BAR, PBM_SETSTEP, 1, 0);
  3354. theApp.m_pMainWnd->EnableWindow(FALSE);
  3355. m_hJobOpProgressDlg = hProgressDlg;
  3356. return TRUE;
  3357. } // CFolderListView::JobOpProgressDlgStart
  3358. void
  3359. CFolderListView::JobOpProgressDlgInc()
  3360. /*++
  3361. Routine name : CFolderListView::JobOpProgressDlgInc
  3362. Routine description:
  3363. Multi job operation progress dialog increment
  3364. Return Value:
  3365. None.
  3366. --*/
  3367. {
  3368. DBG_ENTER(TEXT("CFolderListView::JobOpProgressDlgInc"));
  3369. if(!m_hJobOpProgressDlg)
  3370. {
  3371. return;
  3372. }
  3373. ++m_dwJobOpPos;
  3374. //
  3375. // Increment progress bar
  3376. //
  3377. ::SendDlgItemMessage(m_hJobOpProgressDlg, IDC_PROGRESS_BAR, PBM_STEPIT, 0, 0);
  3378. //
  3379. // Compose and set progress string
  3380. //
  3381. TCHAR szFormat[MAX_PATH] = {0};
  3382. TCHAR szText[MAX_PATH] = {0};
  3383. DWORD dwParam[2];
  3384. dwParam[0] = m_dwJobOpPos;
  3385. dwParam[1] = m_dwJobOpItems;
  3386. if(LoadString(GetResourceHandle(),
  3387. IDS_PROGRESS_NUMBER,
  3388. szFormat,
  3389. ARR_SIZE(szFormat)))
  3390. {
  3391. if(FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3392. (LPCVOID)szFormat,
  3393. 0,
  3394. 0,
  3395. szText,
  3396. ARR_SIZE(szText),
  3397. (va_list*)dwParam))
  3398. {
  3399. ::SetDlgItemText(m_hJobOpProgressDlg, IDC_PROGRESS_NUMBER, szText);
  3400. }
  3401. else
  3402. {
  3403. CALL_FAIL (GENERAL_ERR, TEXT ("FormatMessage"), GetLastError());
  3404. }
  3405. }
  3406. else
  3407. {
  3408. CALL_FAIL (RESOURCE_ERR, TEXT ("LoadString(IDS_PROGRESS_NUMBER)"), GetLastError());
  3409. }
  3410. //
  3411. // MFC message pump
  3412. // Taken from MSDN Q99999
  3413. // INFO: Background Processing in an MFC Application
  3414. //
  3415. MSG msg;
  3416. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  3417. {
  3418. if (!theApp.PreTranslateMessage(&msg))
  3419. {
  3420. ::TranslateMessage(&msg);
  3421. ::DispatchMessage(&msg);
  3422. }
  3423. theApp.OnIdle(0); // updates user interface
  3424. theApp.OnIdle(1); // frees temporary objects
  3425. }
  3426. } // CFolderListView::JobOpProgressDlgInc
  3427. void
  3428. CFolderListView::JobOpProgressDlgStop()
  3429. /*++
  3430. Routine name : CFolderListView::JobOpProgressDlgStop
  3431. Routine description:
  3432. Close multi job operation progress dialog
  3433. Return Value:
  3434. None.
  3435. --*/
  3436. {
  3437. DBG_ENTER(TEXT("CFolderListView::JobOpProgressDlgStop"));
  3438. if(!m_hJobOpProgressDlg)
  3439. {
  3440. return;
  3441. }
  3442. ::DestroyWindow(m_hJobOpProgressDlg);
  3443. m_hJobOpProgressDlg = NULL;
  3444. m_bJobOpCancel = FALSE;
  3445. m_dwJobOpItems = 0;
  3446. m_dwJobOpPos = 0;
  3447. theApp.ReturnFromModal();
  3448. } // CFolderListView::JobOpProgressDlgStop