Source code of Windows XP (NT5)
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.

971 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: histlist.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "histlist.h"
  12. #include "cstr.h"
  13. #include "amcmsgid.h"
  14. #include "websnk.h"
  15. #include "webctrl.h"
  16. //############################################################################
  17. //############################################################################
  18. //
  19. // Traces
  20. //
  21. //############################################################################
  22. //############################################################################
  23. #ifdef DBG
  24. CTraceTag tagHistory(TEXT("History"), TEXT("History"));
  25. LPCTSTR SzHistoryEntryType(CHistoryEntry &entry)
  26. {
  27. if(entry.IsListEntry())
  28. return TEXT("ListView");
  29. else if(entry.IsOCXEntry())
  30. return TEXT("OCXView ");
  31. else if(entry.IsWebEntry())
  32. return TEXT("WebView ");
  33. else
  34. ASSERT(0 && "Should not come here");
  35. return TEXT("Illegal entry");
  36. }
  37. #define TraceHistory(Name, iter) \
  38. { \
  39. USES_CONVERSION; \
  40. Trace(tagHistory, TEXT("%s hNode = %d, %s, viewMode = %d, strOCX = \"%s\" iterator = %d "), \
  41. Name, iter->hnode, SzHistoryEntryType(*iter), iter->viewMode, \
  42. TEXT(""), (LPARAM) &*iter); \
  43. }
  44. #else // DBG
  45. #define TraceHistory(Name, iter)
  46. #endif // DBG
  47. //############################################################################
  48. //############################################################################
  49. //
  50. // Implementation of class CHistoryEntry
  51. //
  52. //############################################################################
  53. //############################################################################
  54. bool
  55. CHistoryEntry::operator == (const CHistoryEntry &other) const
  56. {
  57. if( hnode != other.hnode)
  58. return false;
  59. if( guidTaskpad != other.guidTaskpad)
  60. return false;
  61. if(resultViewType != other.resultViewType) // NOTE: implement operator == for CResultViewType.
  62. return false;
  63. return true;
  64. }
  65. bool
  66. CHistoryEntry::operator != (const CHistoryEntry &other) const
  67. {
  68. return !operator == (other);
  69. }
  70. //############################################################################
  71. //############################################################################
  72. //
  73. // Implementation of class CHistoryList
  74. //
  75. //############################################################################
  76. //############################################################################
  77. CHistoryList::CHistoryList(CAMCView* pAMCView)
  78. : m_bBrowserBackEnabled(false),
  79. m_bBrowserForwardEnabled(false),
  80. m_pWebViewCtrl(NULL),
  81. m_bPageBreak(false),
  82. m_bWithin_CHistoryList_Back(false),
  83. m_bWithin_CHistoryList_Forward(false)
  84. {
  85. m_pView = pAMCView;
  86. m_iterCurrent = m_entries.begin();
  87. m_navState = MMC_HISTORY_READY; // not busy
  88. }
  89. CHistoryList::~CHistoryList()
  90. {
  91. }
  92. SC
  93. CHistoryList::ScOnPageBreak()
  94. {
  95. DECLARE_SC(sc, TEXT("CHistoryList::ScOnPageBreak"));
  96. // handle recursion
  97. if(MMC_HISTORY_PAGE_BREAK == m_navState)
  98. {
  99. Trace(tagHistory, _T("OnPageBreak() - while inserting pagebreak"));
  100. m_navState = MMC_HISTORY_READY;
  101. return sc;
  102. }
  103. bool bHandled = false;
  104. if(m_bCurrentStateIsForward)
  105. {
  106. Trace(tagHistory, _T("OnPageBreak() - while going Forward"));
  107. Forward(bHandled, false);
  108. }
  109. else
  110. {
  111. Trace(tagHistory, _T("OnPageBreak() - while going Back"));
  112. Back(bHandled, false);
  113. }
  114. if(!bHandled)
  115. {
  116. Trace(tagHistory, _T("OnPageBreak() - unhandled, passing back to web browser"));
  117. m_bCurrentStateIsForward ? GetWebViewCtrl()->Forward() : GetWebViewCtrl()->Back();
  118. }
  119. return sc;
  120. }
  121. void
  122. CHistoryList::OnPageBreakStateChange(bool bPageBreak)
  123. {
  124. m_bPageBreak = bPageBreak;
  125. return;
  126. }
  127. /*+-------------------------------------------------------------------------*
  128. *
  129. * CHistoryList::OnBrowserStateChange
  130. *
  131. * PURPOSE: Callback that receives events from the IE control that the
  132. * forward/back button needs to be enabled/disabled. A
  133. * combination of this information with any non-HTML states in the
  134. * history list is used to enable/disable the actual UI.
  135. *
  136. * PARAMETERS:
  137. * bool bForward :
  138. * bool bEnable :
  139. *
  140. * RETURNS:
  141. * void
  142. *
  143. *+-------------------------------------------------------------------------*/
  144. void
  145. CHistoryList::OnBrowserStateChange(bool bEnableForward, bool bEnableBack)
  146. {
  147. #if DBG
  148. CStr strTrace;
  149. strTrace.Format(_T("OnBrowserStateChange() - bEnableForward = %s, bEnableBack = %s"),
  150. bEnableForward ? _T("true") : _T("false"),
  151. bEnableBack ? _T("true") : _T("false"));
  152. Trace(tagHistory, strTrace);
  153. #endif
  154. // handle the forward case.
  155. if(m_bBrowserForwardEnabled && !bEnableForward && !m_bPageBreak)
  156. {
  157. // the button was originally enabled but is now disabled.
  158. // This means that the user branched forward. So we need to throw away
  159. // any history ahead of the present time.
  160. if(m_iterCurrent != m_entries.end())
  161. {
  162. iterator iterTemp = m_iterCurrent;
  163. TraceHistory(TEXT("CHistoryList::Deleting all subsequent entries after"), iterTemp);
  164. ++iterTemp;
  165. m_entries.erase(iterTemp, m_entries.end());
  166. }
  167. }
  168. m_bBrowserForwardEnabled = bEnableForward;
  169. m_bBrowserBackEnabled = bEnableBack;
  170. MaintainWebBar();
  171. }
  172. /*+-------------------------------------------------------------------------*
  173. *
  174. * CHistoryList::IsFirst
  175. *
  176. * PURPOSE:
  177. *
  178. * RETURNS:
  179. * BOOL: TRUE if we should not light up the "Back" button.
  180. *
  181. *+-------------------------------------------------------------------------*/
  182. BOOL
  183. CHistoryList::IsFirst()
  184. {
  185. return (m_iterCurrent == m_entries.begin());
  186. }
  187. /*+-------------------------------------------------------------------------*
  188. *
  189. * CHistoryList::IsLast
  190. *
  191. * PURPOSE:
  192. *
  193. * RETURNS:
  194. * BOOL : TRUE if we should not light up the "Forward" button
  195. *
  196. *+-------------------------------------------------------------------------*/
  197. BOOL
  198. CHistoryList::IsLast()
  199. {
  200. // see notes above
  201. if(m_iterCurrent == m_entries.end())
  202. return TRUE;
  203. // find next unique entry, if any
  204. iterator iter = m_iterCurrent;
  205. ++iter; // this must exist, we've already taken care of the end case.
  206. return(iter == m_entries.end());
  207. }
  208. SC
  209. CHistoryList::ScDoPageBreak()
  210. {
  211. DECLARE_SC(sc, TEXT("CHistoryList::ScDoPageBreak"));
  212. sc = ScCheckPointers(GetWebViewCtrl());
  213. if(sc)
  214. return sc;
  215. Trace(tagHistory, _T("ScDoPageBreak()"));
  216. // navigate to the "break" page.
  217. m_navState = MMC_HISTORY_PAGE_BREAK;
  218. CStr strResultPane;
  219. sc = ScGetPageBreakURL (strResultPane);
  220. if (sc)
  221. return (sc);
  222. GetWebViewCtrl()->Navigate(strResultPane, NULL);
  223. //wait for the navigate to complete.
  224. while (1)
  225. {
  226. READYSTATE state;
  227. sc = GetWebViewCtrl()->ScGetReadyState (state);
  228. if (sc)
  229. return (sc);
  230. if ((state == READYSTATE_COMPLETE) || (state == READYSTATE_LOADED))
  231. break;
  232. MSG msg;
  233. if(!GetMessage( &msg, NULL, 0, 0 )) // the WM_QUIT message.
  234. {
  235. PostQuitMessage (msg.wParam);
  236. return sc;
  237. }
  238. // If it is view close message make sure it gets posted (async) again.
  239. if ( (msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_CLOSE))
  240. {
  241. // Make sure the message is intended for this view.
  242. CWnd *pWnd = m_pView->GetParent();
  243. if ( msg.hwnd == pWnd->GetSafeHwnd())
  244. {
  245. // DeleteView does PostMessage(WM_SYSCOMMAND, SC_CLOSE)
  246. m_pView->DeleteView();
  247. return sc;
  248. }
  249. }
  250. TranslateMessage( &msg );
  251. DispatchMessage( &msg );
  252. }
  253. // m_navState = MMC_HISTORY_READY; // don't set the here. Will be set in OnPageBreak().
  254. return sc;
  255. }
  256. /*+-------------------------------------------------------------------------*
  257. *
  258. * CHistoryList::ScAddEntry
  259. *
  260. * PURPOSE: Adds a history entry
  261. *
  262. * PARAMETERS:
  263. * CResultViewType & rvt :
  264. * int viewMode: The list view mode (large icon, etc)
  265. * GUID & guidTaskpad :
  266. *
  267. * RETURNS:
  268. * SC
  269. *
  270. *+-------------------------------------------------------------------------*/
  271. SC
  272. CHistoryList::ScAddEntry(CResultViewType &rvt, int viewMode, GUID &guidTaskpad)
  273. {
  274. DECLARE_SC(sc, TEXT("CHistoryList::ScAddEntry"));
  275. if(m_navState != MMC_HISTORY_READY)
  276. {
  277. #ifdef DBG
  278. CHistoryEntry entry;
  279. entry.viewMode = viewMode;
  280. entry.resultViewType = rvt;
  281. entry.guidTaskpad = guidTaskpad;
  282. TraceHistory(TEXT("CHistoryList::Busy-RejectEntry"), (&entry));
  283. #endif //DBG
  284. MaintainWebBar();
  285. return sc;
  286. }
  287. BOOL bIsWebEntry = rvt.HasWebBrowser();
  288. // must be in the MMC_HISTORY_READY state at this point, ie not busy.
  289. // figure out current node
  290. HNODE hnode = m_pView->GetSelectedNode();
  291. if(hnode == NULL)
  292. return sc; // not initialized yet
  293. /* if selection change includes the web page (either as 'from' or 'to' node)
  294. * we need to perform proper separation of the webentries by inserting the pagebreaks.
  295. * This is to be done to ensure 2 goals:
  296. * - to detect when navigation should leave the IE history and use MMC history navigation
  297. * - to ensure we always leave IE only after navigating to a pagebreak - to stop the
  298. * scripts on the page as soon as we hide it. to achieve that we need pagebreaks
  299. * before every web page and after every web page.
  300. *
  301. * to do so we need one of the following:
  302. *
  303. * 1. Add a pagebreak (used when selection changes from the web page to non-web view)
  304. * 2. Add a pagebreak and navigate
  305. * (a. when selection changes from web page to another web page)
  306. * (b. when selection changes from non-web view to the webpage
  307. * and it is the first web page in the history)
  308. * 3. Navigate only. ( when selection changes from non-web view to the
  309. * webpage [except #2.b case] - pagebreak had to be added when leaving the
  310. * previous web page)
  311. *
  312. * inverting the said will result in:
  313. * - add a pagebreak if :
  314. * C1: web page is a 'from' node (#1. and #2.a.)
  315. * C2: web page is a 'to' node
  316. * && no previous web pages
  317. * && 'from' node is a non-web view (#2.b)
  318. * - navigate to web page if:
  319. * C3: "to' node is the web page
  320. */
  321. // see if we were in the web before this
  322. // Note: both following variables may be false (in case it there are no entries)
  323. bool bPreviousPageWasWeb = (m_entries.size() != 0) && m_iterCurrent->IsWebEntry();
  324. bool bPreviousPageWasNonWeb = (m_entries.size() != 0) && !bPreviousPageWasWeb;
  325. // see if we need a pagebreak
  326. bool bNeedAPageBreak = false;
  327. if ( bPreviousPageWasWeb )
  328. {
  329. // condition C1 in the comment above
  330. bNeedAPageBreak = true;
  331. }
  332. else if ( bIsWebEntry && !PreviousWebPagesExist() && bPreviousPageWasNonWeb )
  333. {
  334. // condition C2 in the comment above
  335. bNeedAPageBreak = true;
  336. }
  337. // conditions C1 || C2 || C3 in the comment above
  338. if (bIsWebEntry || bNeedAPageBreak)
  339. {
  340. USES_CONVERSION;
  341. LPCTSTR szURL = bIsWebEntry ? (OLE2CT( rvt.GetURL() )) : NULL;
  342. sc = m_pView->ScAddPageBreakAndNavigate (bNeedAPageBreak, bIsWebEntry, szURL);
  343. if(sc)
  344. return sc;
  345. }
  346. DeleteSubsequentEntries();
  347. // add an entry to the end of the list.
  348. CHistoryEntry entry;
  349. ZeroMemory(&entry, sizeof(entry));
  350. m_entries.push_back(entry);
  351. m_iterCurrent = m_entries.end();
  352. --m_iterCurrent; // points to the newly inserted item.
  353. m_iterCurrent->viewMode = viewMode;
  354. m_iterCurrent->guidTaskpad = guidTaskpad;
  355. m_iterCurrent->hnode = hnode;
  356. m_iterCurrent->resultViewType = rvt;
  357. TraceHistory(TEXT("CHistoryList::AddEntry"), m_iterCurrent);
  358. Compact();
  359. MaintainWebBar();
  360. return sc;
  361. }
  362. /*+-------------------------------------------------------------------------*
  363. *
  364. * CHistoryList::DeleteSubsequentEntries
  365. *
  366. * PURPOSE: When a new entry is inserted, all subsequent entries need to be
  367. * deleted, because a new branch has been taken.
  368. *
  369. * RETURNS:
  370. * void
  371. *
  372. *+-------------------------------------------------------------------------*/
  373. void
  374. CHistoryList::DeleteSubsequentEntries()
  375. {
  376. if(m_iterCurrent == m_entries.end())
  377. return; // nothing to do.
  378. iterator iterTemp = m_iterCurrent;
  379. ++iterTemp;
  380. while(iterTemp != m_entries.end())
  381. {
  382. iterator iterNext = iterTemp;
  383. ++iterNext; // point to the next element.
  384. TraceHistory(TEXT("CHistoryList::DeleteSubsequentEntries"), iterTemp);
  385. m_entries.erase(iterTemp);
  386. iterTemp = iterNext;
  387. }
  388. // the current entry must be the last at this stage.
  389. #ifdef DBG
  390. {
  391. iterator iterTemp = m_iterCurrent;
  392. ++iterTemp;
  393. ASSERT(iterTemp == m_entries.end());
  394. }
  395. #endif
  396. }
  397. /*+-------------------------------------------------------------------------*
  398. *
  399. * CHistoryList::Back
  400. *
  401. * PURPOSE:
  402. *
  403. * PARAMETERS:
  404. * bool & bHandled :
  405. *
  406. * RETURNS:
  407. * HRESULT
  408. *
  409. *+-------------------------------------------------------------------------*/
  410. HRESULT
  411. CHistoryList::Back(bool &bHandled, bool bUseBrowserHistory)
  412. {
  413. Trace(tagHistory, TEXT("Back()"));
  414. // change the state to indicate we are navigating back.
  415. // and assure it is reset on function exit
  416. m_bWithin_CHistoryList_Back = true;
  417. CAutoAssignOnExit<bool, false> auto_reset( m_bWithin_CHistoryList_Back );
  418. // if we're in browser mode AND
  419. // if the back button is enabled by the browser use browser history.
  420. m_bCurrentStateIsForward = false;
  421. if( (m_iterCurrent->IsWebEntry()) && bUseBrowserHistory)
  422. {
  423. if(m_bBrowserBackEnabled)
  424. {
  425. Trace(tagHistory, TEXT("Back() web entry - not handling"));
  426. bHandled = false;
  427. return S_OK;
  428. }
  429. }
  430. bHandled = true;
  431. // BOGUS assert - amcview calls Back when ALT <- is pressed
  432. // regardless of the state of the button.
  433. //ASSERT (m_iterCurrent != m_entries.begin());
  434. if(m_iterCurrent == m_entries.begin())
  435. return S_FALSE;
  436. --m_iterCurrent;
  437. HRESULT hr = ExecuteCurrent();
  438. if(FAILED(hr))
  439. return hr;
  440. if(m_iterCurrent->IsWebEntry())
  441. {
  442. if(m_bPageBreak) // if we're at a page break, go past it.
  443. {
  444. Trace(tagHistory, TEXT("Back() - stepped on the pagebreak"));
  445. bHandled = false; // this tells the caller to use the Browser's Back button.
  446. }
  447. }
  448. return hr;
  449. }
  450. /*+-------------------------------------------------------------------------*
  451. *
  452. * CHistoryList::Forward
  453. *
  454. * PURPOSE:
  455. *
  456. * PARAMETERS:
  457. * bool & bHandled :
  458. *
  459. * RETURNS:
  460. * HRESULT
  461. *
  462. *+-------------------------------------------------------------------------*/
  463. HRESULT
  464. CHistoryList::Forward(bool &bHandled, bool bUseBrowserHistory)
  465. {
  466. // change the state to indicate we are navigating forward.
  467. // and assure it is reset on function exit
  468. m_bWithin_CHistoryList_Forward = true;
  469. CAutoAssignOnExit<bool, false> auto_reset( m_bWithin_CHistoryList_Forward );
  470. // if we're in browser mode AND
  471. // if the forward button is enabled by the browser use browser history.
  472. m_bCurrentStateIsForward = true;
  473. if( (m_iterCurrent->IsWebEntry()) && bUseBrowserHistory)
  474. {
  475. if(m_bBrowserForwardEnabled)
  476. {
  477. bHandled = false;
  478. return S_OK;
  479. }
  480. }
  481. bHandled = true;
  482. // BOGUS assert - amcview calls Forward when ALT -> is pressed
  483. // regardless of the state of the Forward button.
  484. //ASSERT (m_iterCurrent != m_entries.end());
  485. if(m_iterCurrent == m_entries.end())
  486. return S_FALSE;
  487. ++m_iterCurrent;
  488. if(m_iterCurrent == m_entries.end())
  489. return S_FALSE;
  490. HRESULT hr = ExecuteCurrent();
  491. if(FAILED(hr))
  492. return hr;
  493. if(m_iterCurrent->IsWebEntry())
  494. {
  495. if(m_bPageBreak) // if we're at a page break, go past it.
  496. bHandled = false; // this tells the caller to use the Browser's Forward button.
  497. }
  498. return hr;
  499. }
  500. /*+-------------------------------------------------------------------------*
  501. *
  502. * CHistoryList::ExecuteCurrent
  503. *
  504. * PURPOSE: Sets the state of MMC to that of the current History entry. Called
  505. * by Back() and Forward().
  506. *
  507. * RETURNS:
  508. * HRESULT
  509. *
  510. *+-------------------------------------------------------------------------*/
  511. HRESULT
  512. CHistoryList::ExecuteCurrent()
  513. {
  514. DECLARE_SC(sc, TEXT("CHistoryList::ExecuteCurrent"));
  515. INodeCallback* pNC = m_pView->GetNodeCallback();
  516. MTNODEID id;
  517. TraceHistory(TEXT("CHistoryList::ExecuteCurrent"), m_iterCurrent);
  518. pNC->GetMTNodeID (m_iterCurrent->hnode, &id);
  519. m_navState = MMC_HISTORY_NAVIGATING;
  520. // store values to local variables to avoid losing them
  521. // when an entry is removed from history
  522. GUID guidTaskpad = m_iterCurrent->guidTaskpad;
  523. bool bIsListEntry = m_iterCurrent->IsListEntry();
  524. DWORD viewMode = m_iterCurrent->viewMode;
  525. m_pView->SelectNode (id, guidTaskpad);
  526. if(bIsListEntry)
  527. {
  528. sc = m_pView->ScChangeViewMode(viewMode);
  529. if (sc)
  530. sc.TraceAndClear();
  531. }
  532. m_navState = MMC_HISTORY_READY;
  533. MaintainWebBar();
  534. return sc.ToHr();
  535. }
  536. void CHistoryList::MaintainWebBar()
  537. {
  538. bool bWebEntry = ((m_entries.size() != 0) && m_iterCurrent->IsWebEntry());
  539. UpdateWebBar ( HB_BACK, ( bWebEntry && m_bBrowserBackEnabled ) || !IsFirst()); // back
  540. UpdateWebBar ( HB_FORWARD, ( bWebEntry && m_bBrowserForwardEnabled ) || !IsLast () ); // forward
  541. }
  542. void CHistoryList::UpdateWebBar (HistoryButton button, BOOL bOn)
  543. {
  544. DECLARE_SC (sc, _T("CHistoryList::UpdateWebBar"));
  545. if (NULL == m_pView)
  546. {
  547. sc = E_UNEXPECTED;
  548. return;
  549. }
  550. CStandardToolbar* pStandardToolbar = m_pView->GetStdToolbar();
  551. if (NULL == pStandardToolbar)
  552. {
  553. sc = E_UNEXPECTED;
  554. return;
  555. }
  556. switch (button)
  557. {
  558. case HB_BACK:
  559. sc = pStandardToolbar->ScEnableButton(IDS_MMC_WEB_BACK, bOn);
  560. break;
  561. case HB_STOP:
  562. sc = pStandardToolbar->ScEnableButton(IDS_MMC_WEB_STOP, bOn);
  563. break;
  564. case HB_FORWARD:
  565. sc = pStandardToolbar->ScEnableButton(IDS_MMC_WEB_FORWARD, bOn);
  566. break;
  567. }
  568. }
  569. /*+-------------------------------------------------------------------------*
  570. *
  571. * CHistoryList::ScGetCurrentResultViewType
  572. *
  573. * PURPOSE: Returns the current history entry.
  574. *
  575. * PARAMETERS:
  576. * CResultViewType & rvt :
  577. * int& viewMode :
  578. * GUID & guidTaskpad :
  579. *
  580. * RETURNS:
  581. * SC
  582. *
  583. *+-------------------------------------------------------------------------*/
  584. SC
  585. CHistoryList::ScGetCurrentResultViewType (CResultViewType &rvt, int& viewMode, GUID &guidTaskpad)
  586. {
  587. DECLARE_SC(sc, TEXT("CHistoryList::ScGetCurrentResultViewType"));
  588. if(m_iterCurrent == m_entries.end())
  589. return (sc = E_FAIL); // should never happen
  590. rvt = m_iterCurrent->resultViewType;
  591. viewMode = m_iterCurrent->viewMode;
  592. guidTaskpad = m_iterCurrent->guidTaskpad;
  593. return sc;
  594. }
  595. void CHistoryList::SetCurrentViewMode (long nViewMode)
  596. {
  597. if(m_navState != MMC_HISTORY_READY)
  598. return;
  599. if(m_iterCurrent == m_entries.end())
  600. return;
  601. m_iterCurrent->viewMode = nViewMode;
  602. }
  603. void CHistoryList::Clear()
  604. {
  605. Trace(tagHistory, TEXT("Clear"));
  606. m_entries.erase(m_entries.begin(), m_entries.end());
  607. m_iterCurrent = m_entries.begin();
  608. MaintainWebBar();
  609. }
  610. /*+-------------------------------------------------------------------------*
  611. *
  612. * CHistoryList::ScModifyViewTab
  613. *
  614. * PURPOSE: Adds an entry to the history list, which is the same as the current
  615. * entry, except that the changes specified by the dwFlags and history
  616. * entry parameters are applied
  617. *
  618. * PARAMETERS:
  619. * const GUID& guidTab : Specifies guid of selected view tab
  620. *
  621. * RETURNS:
  622. * SC
  623. *
  624. *+-------------------------------------------------------------------------*/
  625. SC
  626. CHistoryList::ScModifyViewTab(const GUID& guidTab)
  627. {
  628. DECLARE_SC(sc, TEXT("CHistoryList::ScAddModifiedEntry"));
  629. // we are not going to modify anything if we navigating "Back" or ""Forward"
  630. // thru the history enries
  631. if ( m_bWithin_CHistoryList_Back || m_bWithin_CHistoryList_Forward )
  632. return sc;
  633. if( m_iterCurrent == m_entries.end() )
  634. {
  635. return (sc = E_UNEXPECTED);
  636. }
  637. // for web we cannot add new entries without reselecting the node
  638. // (same is true about deleting subsequen entries)
  639. // since that would make MMC and IE histories out of sync
  640. // instead we just modify the current history entry
  641. if ( !m_iterCurrent->IsWebEntry() ) // in case it is a regular entry
  642. {
  643. DeleteSubsequentEntries(); // delete everything ahead of this one.
  644. // add an entry to the end of the list.
  645. CHistoryEntry entry;
  646. ZeroMemory(&entry, sizeof(entry));
  647. m_entries.push_back(entry);
  648. iterator iterNew = m_entries.end();
  649. --iterNew; // point to the new entry.
  650. // create a duplicate of the current entry.
  651. *iterNew = *m_iterCurrent;
  652. //set the pointer.
  653. m_iterCurrent = iterNew;
  654. }
  655. // change the guid of the tab.
  656. m_iterCurrent->guidTaskpad = guidTab;
  657. // we're done.
  658. Compact();
  659. MaintainWebBar();
  660. return sc;
  661. }
  662. /*+-------------------------------------------------------------------------*
  663. *
  664. * CHistoryList::ScChangeViewMode
  665. *
  666. * PURPOSE: Changes the view mode of the current entry. Changing the view
  667. * mode does not add a new entry. Instead, history remembers the last
  668. * view mode that a node was at and always restores to that
  669. *
  670. * PARAMETERS:
  671. * int viewMode :
  672. *
  673. * RETURNS:
  674. * SC
  675. *
  676. *+-------------------------------------------------------------------------*/
  677. SC
  678. CHistoryList::ScChangeViewMode(int viewMode)
  679. {
  680. DECLARE_SC(sc, TEXT("CHistoryList::ScChangeViewMode"));
  681. if( m_iterCurrent == m_entries.end() )
  682. {
  683. return (sc = E_UNEXPECTED);
  684. }
  685. m_iterCurrent->viewMode = viewMode; // set the view mode.
  686. return sc;
  687. }
  688. /*+-------------------------------------------------------------------------*
  689. *
  690. * CHistoryList::DeleteEntry
  691. *
  692. * PURPOSE: Deletes all entries for a node from the history list.
  693. *
  694. * PARAMETERS:
  695. * HNODE hnode :
  696. *
  697. * RETURNS:
  698. * void
  699. *
  700. *+-------------------------------------------------------------------------*/
  701. void
  702. CHistoryList::DeleteEntry (HNODE hnode)
  703. {
  704. for(iterator i= m_entries.begin(); i != m_entries.end(); )
  705. {
  706. if(i->hnode == hnode)
  707. {
  708. iterator iNext = i;
  709. ++iNext;
  710. if(m_iterCurrent==i)
  711. m_iterCurrent=iNext;
  712. TraceHistory(TEXT("CHistoryList::Deleting entry"), i);
  713. m_entries.erase(i);
  714. i= iNext;
  715. }
  716. else
  717. {
  718. ++i;
  719. }
  720. }
  721. Compact();
  722. MaintainWebBar();
  723. }
  724. /*+-------------------------------------------------------------------------*
  725. *
  726. * CHistoryList::Compact
  727. *
  728. * PURPOSE: 1) Removes redundancies in the history list by eliminating duplicates.
  729. * 2) Ensures that a maximum of MAX_HISTORY_ENTRIES entries is retained.
  730. *
  731. * RETURNS:
  732. * void
  733. *
  734. *+-------------------------------------------------------------------------*/
  735. void
  736. CHistoryList::Compact()
  737. {
  738. if (m_entries.size() == 0)
  739. return;
  740. // discard duplicates.
  741. for (iterator i= m_entries.begin(); i != m_entries.end(); )
  742. {
  743. iterator iNext = i;
  744. ++iNext;
  745. if(iNext == m_entries.end())
  746. break;
  747. // do not delete if it is a webentry (there is no way for us to tell IE
  748. // to delete that history entry).
  749. if ( (i->IsWebEntry() == false) && ( *i == *iNext))
  750. {
  751. if(m_iterCurrent==i)
  752. m_iterCurrent=iNext;
  753. TraceHistory(TEXT("CHistoryList::Deleting entry"), i);
  754. m_entries.erase(i);
  755. i = iNext;
  756. }
  757. else
  758. {
  759. ++i;
  760. }
  761. }
  762. iterator iter = m_entries.begin();
  763. iterator iterNext = iter;
  764. int nExcess = m_entries.size() - MAX_HISTORY_ENTRIES;
  765. while(nExcess-- > 0)
  766. {
  767. iterNext = iter;
  768. ++iterNext;
  769. if(iter == m_iterCurrent) // make sure we don't delete the current entry.
  770. break;
  771. TraceHistory(TEXT("CHistoryList::Deleting entry"), i);
  772. m_entries.erase(iter);
  773. iter = iterNext;
  774. }
  775. }
  776. /***************************************************************************\
  777. *
  778. * METHOD: CHistoryList::PreviousWebPagesExist
  779. *
  780. * PURPOSE: looks back to see if there are any web pages in the history
  781. * up to the current mark (including it)
  782. *
  783. * PARAMETERS:
  784. *
  785. * RETURNS:
  786. * bool - result true = there is web pages
  787. *
  788. \***************************************************************************/
  789. bool CHistoryList::PreviousWebPagesExist()
  790. {
  791. if ( m_entries.size() && m_iterCurrent == m_entries.end() )
  792. {
  793. ASSERT(FALSE); // need to point to a valid entry !!!
  794. return false;
  795. }
  796. // will loop past the current entry.
  797. iterator end = m_iterCurrent;
  798. ++end;
  799. for ( iterator it = m_entries.begin(); it != end; ++it )
  800. {
  801. if ( it->IsWebEntry() )
  802. return true;
  803. }
  804. return false;
  805. }
  806. /*+-------------------------------------------------------------------------*
  807. * ScGetPageBreakURL
  808. *
  809. * Returns the URL for MMC's HTML page containing a page break.
  810. *--------------------------------------------------------------------------*/
  811. SC ScGetPageBreakURL(CStr& strPageBreakURL)
  812. {
  813. DECLARE_SC (sc, _T("GetPageBreakURL"));
  814. /*
  815. * clear out the old value, if any
  816. */
  817. strPageBreakURL.Empty();
  818. // generate new pagebreak URL every time ( prevent web browser from compacting it)
  819. static int nPageBreak = 0;
  820. strPageBreakURL.Format( _T("%s%d"), PAGEBREAK_URL, ++nPageBreak );
  821. return (sc);
  822. }