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.

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