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.

638 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: favorite.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // favorite.cpp
  11. #include "stdafx.h"
  12. #include "amcdoc.h"
  13. #include "favorite.h"
  14. #include "favui.h"
  15. //############################################################################
  16. //############################################################################
  17. //
  18. // Implementation of class CFavObject
  19. //
  20. //############################################################################
  21. //############################################################################
  22. CFavObject::CFavObject(bool bIsGroup)
  23. : m_pFavParent(NULL), m_pFavNext(NULL), m_pFavChild(NULL), m_bIsGroup(bIsGroup), m_strName(_T("")),
  24. m_strPath(_T(""))
  25. {
  26. }
  27. CFavObject::~CFavObject()
  28. {
  29. // delete siblings iteratively
  30. CFavObject* pFavSib = GetNext();
  31. while(pFavSib)
  32. {
  33. CFavObject* pFavNext = pFavSib->GetNext();
  34. pFavSib->SetNext(NULL);
  35. delete pFavSib;
  36. pFavSib = pFavNext;
  37. }
  38. // delete children recursively
  39. if (GetChild())
  40. delete GetChild();
  41. }
  42. int
  43. CFavObject::GetImage()
  44. {
  45. return ( IsGroup() ? eStockImage_Folder : eStockImage_Favorite);
  46. }
  47. int
  48. CFavObject::GetOpenImage()
  49. {
  50. return ( IsGroup() ? eStockImage_OpenFolder: eStockImage_Favorite);
  51. }
  52. DWORD
  53. CFavObject::GetChildCount()
  54. {
  55. ASSERT(IsGroup());
  56. DWORD dwCount = 0;
  57. CFavObject *pObject = m_pFavChild;
  58. while(pObject != NULL)
  59. {
  60. dwCount++;
  61. pObject = pObject->GetNext();
  62. }
  63. return dwCount;
  64. }
  65. void CFavObject::AddChild(CFavObject* pFavNew, CFavObject* pFavPrev)
  66. {
  67. ASSERT(IsGroup());
  68. ASSERT(pFavNew != NULL);
  69. // if adding to end, locate last child
  70. if (pFavPrev == LAST_FAVORITE)
  71. {
  72. pFavPrev = GetChild();
  73. if (pFavPrev != NULL)
  74. while (pFavPrev->GetNext()) pFavPrev = pFavPrev->GetNext();
  75. }
  76. // if no previous object
  77. if (pFavPrev == NULL)
  78. {
  79. // add as first child
  80. pFavNew->SetNext(GetChild());
  81. SetChild(pFavNew);
  82. }
  83. else
  84. {
  85. // add after previous
  86. pFavNew->SetNext(pFavPrev->GetNext());
  87. pFavPrev->SetNext(pFavNew);
  88. }
  89. // always set self as parent
  90. pFavNew->SetParent(this);
  91. }
  92. void CFavObject::RemoveChild(CFavObject* pFavDelete)
  93. {
  94. ASSERT(pFavDelete != NULL);
  95. ASSERT(pFavDelete->GetParent() == this);
  96. if (GetChild() == pFavDelete)
  97. {
  98. SetChild(pFavDelete->GetNext());
  99. }
  100. else
  101. {
  102. CFavObject* pFavPrev = GetChild();
  103. while(pFavPrev != NULL && pFavPrev->GetNext() != pFavDelete)
  104. pFavPrev = pFavPrev->GetNext();
  105. ASSERT(pFavPrev != NULL);
  106. pFavPrev->SetNext(pFavDelete->GetNext());
  107. }
  108. pFavDelete->SetNext(NULL);
  109. }
  110. void CFavObject::SetPath(LPCTSTR pszPath)
  111. {
  112. // Drop first part of path (because it is always the console root)
  113. // unless the shortcut is to the root itself
  114. TCHAR* pSep = _tcschr(pszPath, _T('\\'));
  115. m_strPath = (pSep != NULL) ? CharNext(pSep) : pszPath;
  116. }
  117. HRESULT
  118. CFavObject::ReadSerialObject (IStream &stm, UINT nVersion)
  119. {
  120. HRESULT hr = S_FALSE; // assume bad version
  121. if (nVersion == 1)
  122. {
  123. try
  124. {
  125. stm >> m_bIsGroup;
  126. stm >> m_strName;
  127. if(IsGroup())
  128. {
  129. DWORD cChildren = 0;
  130. stm >> cChildren;
  131. for(int i = 0; i< cChildren; i++)
  132. {
  133. CFavObject *pObject = new CFavObject(true); // the true parameter gets overwritten.
  134. hr = pObject->ReadSerialObject(stm, nVersion);
  135. if(FAILED(hr))
  136. {
  137. delete pObject;
  138. pObject = NULL;
  139. return hr;
  140. }
  141. AddChild(pObject);
  142. }
  143. hr = S_OK;
  144. }
  145. else // is an item
  146. {
  147. hr = m_memento.Read(stm);
  148. stm >> m_strPath;
  149. }
  150. }
  151. catch (_com_error& err)
  152. {
  153. hr = err.Error();
  154. ASSERT (false && "Caught _com_error");
  155. }
  156. }
  157. return hr;
  158. }
  159. //############################################################################
  160. //############################################################################
  161. //
  162. // Implementation of class CFavorites
  163. //
  164. //############################################################################
  165. //############################################################################
  166. CFavorites::CFavorites() : m_pFavRoot(NULL)
  167. {
  168. // create root group
  169. CString strName;
  170. LoadString(strName, IDS_FAVORITES);
  171. m_pFavRoot = new CFavObject(true /*bIsGroup*/);
  172. m_pFavRoot->m_strName = strName;
  173. }
  174. CFavorites::~CFavorites()
  175. {
  176. // delete the entire tree
  177. if (m_pFavRoot != NULL)
  178. delete m_pFavRoot;
  179. }
  180. /////////////////////////////////////////////////////////
  181. // CTreeSource methods
  182. TREEITEMID CFavorites::GetRootItem()
  183. {
  184. return TIDFromFavObj(m_pFavRoot);
  185. }
  186. TREEITEMID CFavorites::GetParentItem(TREEITEMID tid)
  187. {
  188. CFavObject* pFav = FavObjFromTID(tid);
  189. return TIDFromFavObj(pFav->GetParent());
  190. }
  191. TREEITEMID CFavorites::GetChildItem(TREEITEMID tid)
  192. {
  193. CFavObject* pFav = FavObjFromTID(tid);
  194. return TIDFromFavObj(pFav->GetChild());
  195. }
  196. TREEITEMID CFavorites::GetNextSiblingItem(TREEITEMID tid)
  197. {
  198. CFavObject* pFav = FavObjFromTID(tid);
  199. return TIDFromFavObj(pFav->GetNext());
  200. }
  201. LPARAM CFavorites::GetItemParam(TREEITEMID tid)
  202. {
  203. return 0;
  204. }
  205. void CFavorites::GetItemName(TREEITEMID tid, LPTSTR pszName, int cchMaxName)
  206. {
  207. DECLARE_SC(sc, TEXT("CFavorites::GetItemName"));
  208. sc = ScCheckPointers(pszName);
  209. if (sc)
  210. return;
  211. CFavObject* pFav = FavObjFromTID(tid);
  212. sc = StringCchCopy(pszName, cchMaxName, pFav->GetName());
  213. if (sc)
  214. return;
  215. }
  216. void CFavorites::GetItemPath(TREEITEMID tid, LPTSTR pszPath, int cchMaxPath)
  217. {
  218. DECLARE_SC(sc, TEXT("CFavorites::GetItemPath"));
  219. sc = ScCheckPointers(pszPath);
  220. if (sc)
  221. return;
  222. CFavObject* pFav = FavObjFromTID(tid);
  223. sc = StringCchCopy(pszPath, cchMaxPath, pFav->GetPath());
  224. if (sc)
  225. return;
  226. }
  227. int CFavorites::GetItemImage(TREEITEMID tid)
  228. {
  229. CFavObject* pFav = FavObjFromTID(tid);
  230. return pFav->GetImage();
  231. }
  232. int CFavorites::GetItemOpenImage(TREEITEMID tid)
  233. {
  234. CFavObject* pFav = FavObjFromTID(tid);
  235. return pFav->GetOpenImage();
  236. }
  237. BOOL CFavorites::IsFolderItem(TREEITEMID tid)
  238. {
  239. CFavObject* pFav = FavObjFromTID(tid);
  240. return pFav->IsGroup();
  241. }
  242. ///////////////////////////////////////////////////////////////////////////
  243. // CFavorites methods
  244. HRESULT CFavorites::AddFavorite(TREEITEMID tidParent, LPCTSTR strName,
  245. CFavObject** ppFavRet)
  246. {
  247. ASSERT(tidParent != NULL && strName != NULL);
  248. ASSERT(FavObjFromTID(tidParent)->IsGroup());
  249. CFavObject* pFavParent = reinterpret_cast<CFavObject*>(tidParent);
  250. // Create a favorite item
  251. CFavObject* pFavItem = new CFavObject(false /*bIsGroup*/);
  252. if (pFavItem == NULL)
  253. return E_OUTOFMEMORY;
  254. pFavItem->m_strName = strName;
  255. // Add to end of group
  256. pFavParent->AddChild(pFavItem);
  257. // Notify all observers of addition
  258. FOR_EACH_OBSERVER(CTreeObserver, iter)
  259. {
  260. (*iter)->ItemAdded(TIDFromFavObj(pFavItem));
  261. }
  262. if (ppFavRet)
  263. *ppFavRet = pFavItem;
  264. return S_OK;
  265. }
  266. HRESULT CFavorites::AddGroup(TREEITEMID tidParent, LPCTSTR strName, CFavObject** ppFavRet)
  267. {
  268. ASSERT(tidParent != NULL && strName != NULL);
  269. ASSERT(FavObjFromTID(tidParent)->IsGroup());
  270. CFavObject* pFavParent = reinterpret_cast<CFavObject*>(tidParent);
  271. CFavObject* pFavGrp = new CFavObject(true /*bIsGroup*/);
  272. if (pFavGrp == NULL)
  273. return E_OUTOFMEMORY;
  274. pFavGrp->m_strName = strName;
  275. pFavParent->AddChild(pFavGrp);
  276. // Notify all observers of addition
  277. FOR_EACH_OBSERVER(CTreeObserver, iter)
  278. {
  279. (*iter)->ItemAdded(TIDFromFavObj(pFavGrp));
  280. }
  281. if (ppFavRet)
  282. *ppFavRet = pFavGrp;
  283. return S_OK;
  284. }
  285. HRESULT CFavorites::DeleteItem(TREEITEMID tid)
  286. {
  287. CFavObject* pFav = FavObjFromTID(tid);
  288. CFavObject* pFavParent = pFav->GetParent();
  289. if (pFavParent)
  290. pFavParent->RemoveChild(pFav);
  291. else
  292. m_pFavRoot = NULL;
  293. delete pFav;
  294. // Notify all observers of deletion
  295. FOR_EACH_OBSERVER(CTreeObserver, iter)
  296. {
  297. (*iter)->ItemRemoved((TREEITEMID)pFavParent, tid);
  298. }
  299. return S_OK;
  300. }
  301. HRESULT CFavorites::MoveItem(TREEITEMID tid, TREEITEMID tidNewGroup, TREEITEMID tidPrev)
  302. {
  303. CFavObject* pFav = FavObjFromTID(tid);
  304. CFavObject* pFavPrev = FavObjFromTID(tidPrev);
  305. ASSERT(FavObjFromTID(tidNewGroup)->IsGroup());
  306. CFavObject* pFavNewGroup = reinterpret_cast<CFavObject*>(tidNewGroup);
  307. // Verify not moving item into itself or under itself
  308. CFavObject* pFavTemp = pFavNewGroup;
  309. while (pFavTemp != NULL)
  310. {
  311. if (pFavTemp == pFav)
  312. return E_FAIL;
  313. pFavTemp = pFavTemp->GetParent();
  314. }
  315. // Remove object from current group
  316. CFavObject* pFavParent = pFav->GetParent();
  317. ASSERT(pFavParent != NULL);
  318. pFavParent->RemoveChild(pFav);
  319. // Notify all observers of removal
  320. FOR_EACH_OBSERVER(CTreeObserver, iter)
  321. {
  322. (*iter)->ItemRemoved((TREEITEMID)pFavParent, tid);
  323. }
  324. // Insert item into the new group
  325. pFavNewGroup->AddChild(pFav, pFavPrev);
  326. // Notify all observers of addition
  327. FOR_EACH_OBSERVER(CTreeObserver, iter1)
  328. {
  329. (*iter1)->ItemAdded(tid);
  330. }
  331. return S_OK;
  332. }
  333. HRESULT CFavorites::SetItemName(TREEITEMID tid, LPCTSTR pszName)
  334. {
  335. CFavObject* pFav = FavObjFromTID(tid);
  336. ASSERT(pszName != NULL && pszName[0] != 0);
  337. // Change item name
  338. pFav->m_strName = pszName;
  339. // Notify all observers of change
  340. FOR_EACH_OBSERVER(CTreeObserver, iter)
  341. {
  342. (*iter)->ItemChanged(tid, TIA_NAME);
  343. }
  344. return S_OK;
  345. }
  346. HRESULT CFavorites::AddToFavorites(LPCTSTR szName, LPCTSTR szPath, CMemento &memento, CWnd* pwndHost)
  347. {
  348. DECLARE_SC (sc, _T("CFavorites::AddToFavorites"));
  349. CAddFavDialog dlg(szName, this, pwndHost);
  350. CFavObject* pFavItem = NULL;
  351. sc = dlg.CreateFavorite(&pFavItem);
  352. // Note: S_FALSE is returned if user cancels dialog
  353. if (sc.ToHr() != S_OK)
  354. return (sc.ToHr());
  355. sc = ScCheckPointers (pFavItem, E_UNEXPECTED);
  356. if (sc)
  357. return (sc.ToHr());
  358. pFavItem->SetPath(szPath);
  359. pFavItem->SetMemento(memento);
  360. return S_OK;
  361. }
  362. CImageList* CFavorites::GetImageList()
  363. {
  364. if (m_ImageList != NULL)
  365. return CImageList::FromHandle (m_ImageList);
  366. do
  367. {
  368. BOOL bStat = m_ImageList.Create(16, 16, ILC_COLORDDB | ILC_MASK, 20, 10);
  369. if (!bStat)
  370. break;
  371. CBitmap bmap;
  372. bStat = bmap.LoadBitmap(IDB_AMC_NODES16);
  373. if (!bStat)
  374. break;
  375. int ipos = m_ImageList.Add(bmap, RGB(255,0,255));
  376. if (ipos == -1)
  377. break;
  378. }
  379. while (0);
  380. return CImageList::FromHandle (m_ImageList);
  381. }
  382. HRESULT CFavorites::OrganizeFavorites(CWnd* pwndHost)
  383. {
  384. COrganizeFavDialog dlg(this, pwndHost);
  385. dlg.DoModal();
  386. return S_OK;
  387. }
  388. HRESULT
  389. CFavorites::ReadSerialObject (IStream &stm, UINT nVersion)
  390. {
  391. HRESULT hr = m_pFavRoot->ReadSerialObject(stm, nVersion);
  392. if(FAILED(hr))
  393. return hr;
  394. // Notify all observers of addition
  395. FOR_EACH_OBSERVER(CTreeObserver, iter)
  396. {
  397. (*iter)->ItemRemoved(NULL, TIDFromFavObj(m_pFavRoot));
  398. (*iter)->ItemAdded(TIDFromFavObj(m_pFavRoot));
  399. }
  400. return hr;
  401. }
  402. bool
  403. CFavorites::IsEmpty()
  404. {
  405. // the list is empty if the root has no children.
  406. return (m_pFavRoot->GetChild()==NULL);
  407. }
  408. /*****************************************************************\
  409. | METHOD: CFavorites::Persist
  410. | DESCR: Persists favorites, by delegating to root item
  411. \*****************************************************************/
  412. void
  413. CFavorites::Persist(CPersistor &persistor)
  414. {
  415. DECLARE_SC(sc, TEXT("CFavorites::Persist"));
  416. sc = ScCheckPointers(m_pFavRoot, E_POINTER);
  417. if (sc)
  418. sc.Throw();
  419. persistor.Persist(*m_pFavRoot);
  420. }
  421. /*****************************************************************\
  422. | METHOD: CFavoriteXMLList::PersistItself
  423. | DESCR: "soft" version of Persist - ignores missing element
  424. | RETURN: true == element exists and persistence succeeded
  425. \*****************************************************************/
  426. bool
  427. CFavoriteXMLList::PersistItself(CPersistor& persistor)
  428. {
  429. DECLARE_SC(sc, TEXT("CFavoriteXMLList::PersistItself"));
  430. if (persistor.IsLoading())
  431. {
  432. if (!persistor.HasElement(GetXMLType(), NULL))
  433. return false;
  434. }
  435. persistor.Persist(*this);
  436. return true;
  437. }
  438. /*****************************************************************\
  439. | METHOD: CFavoriteXMLList::Persist
  440. | DESCR: Perists collection (linked list) contents
  441. \*****************************************************************/
  442. void
  443. CFavoriteXMLList::Persist(CPersistor& persistor)
  444. {
  445. if (persistor.IsStoring())
  446. {
  447. for (CFavObject *pObj = m_rpRoot; pObj; pObj = pObj->GetNext())
  448. {
  449. persistor.Persist(*pObj);
  450. }
  451. }
  452. else
  453. {
  454. ASSERT(m_rpRoot == NULL); // this is to upload new entries only!!!
  455. m_rpRoot = NULL;
  456. XMLListCollectionBase::Persist(persistor);
  457. }
  458. }
  459. /*****************************************************************\
  460. | METHOD: CFavoriteXMLList::OnNewElement
  461. | DESCR: called for every new element when loading
  462. \*****************************************************************/
  463. void
  464. CFavoriteXMLList::OnNewElement(CPersistor& persistor)
  465. {
  466. DECLARE_SC(sc, TEXT("CFavoriteXMLList::OnNewElement"));
  467. CFavObject **pObj = &m_rpRoot;
  468. while (*pObj)
  469. pObj = &(*pObj)->m_pFavNext;
  470. CFavObject *pNewObj = new CFavObject(false);
  471. *pObj = pNewObj;
  472. sc = ScCheckPointers(pNewObj, E_OUTOFMEMORY);
  473. if (sc)
  474. sc.Throw();
  475. pNewObj->SetParent(m_Parent);
  476. persistor.Persist(*pNewObj);
  477. }
  478. /*****************************************************************\
  479. | METHOD: CFavObject::Persist
  480. | DESCR: Persists Favorites item.
  481. \*****************************************************************/
  482. void
  483. CFavObject::Persist(CPersistor &persistor)
  484. {
  485. persistor.PersistString(XML_ATTR_NAME, m_strName);
  486. // persist the type of favorite
  487. CStr strType(IsGroup() ? XML_VAL_FAVORITE_GROUP : XML_VAL_FAVORITE_SINGLE);
  488. persistor.PersistAttribute(XML_ATTR_FAVORITE_TYPE, strType);
  489. m_bIsGroup = (0 == strType.CompareNoCase(XML_VAL_FAVORITE_GROUP));
  490. // its either group or memento.
  491. if (IsGroup())
  492. {
  493. CFavoriteXMLList children(m_pFavChild, this);
  494. children.PersistItself(persistor);
  495. }
  496. else // if (!IsGroup())
  497. {
  498. persistor.Persist(m_memento);
  499. }
  500. }