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.

2363 lines
81 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "strtable.h"
  4. #include "hha_strtable.h"
  5. #include "hhctrl.h"
  6. #include "resource.h"
  7. #include <intshcut.h>
  8. #include "htmlhelp.h"
  9. #include "secwin.h"
  10. #include "cpaldc.h"
  11. #include "cprint.h"
  12. #include <wininet.h>
  13. #include "contain.h"
  14. #include "cdefinss.h"
  15. #include "cctlww.h"
  16. // Forward Declarations
  17. LRESULT WINAPI TreeViewProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  18. void LoadFirstLevel (CTreeNode *pRoot, HWND hwndTreeView, HTREEITEM * m_tiFirstVisible );
  19. HTREEITEM AddTitleChildren (CTreeNode *pNode, HTREEITEM hParent, HWND hwndTreeView);
  20. HTREEITEM AddNode (CTreeNode *pNode, HTREEITEM hParent, HWND hwndTreeView);
  21. BOOL HandleExpanding (TVITEMW* pTvi, HWND hwndTreeView, UINT action, BOOL *pSync);
  22. void AddChildren (TVITEMW* pTvi, HWND hwndTreeView);
  23. void DeleteChildren (TVITEMW* pTvi, HWND hwndTreeView);
  24. void FreeChildrenAllocations (HWND hwndTreeView, HTREEITEM ti);
  25. UINT cpTemp = CP_ACP;
  26. WNDPROC lpfnlTreeViewWndProc = NULL; // Initialize.
  27. // Constants
  28. const int SITEMAP_MAX_LEVELS = 50; // maximum nested folders
  29. CToc::CToc(CHtmlHelpControl* phhctrl, IUnknown* pUnkOuter, CHHWinType* phh)
  30. {
  31. m_phhctrl = phhctrl;
  32. m_pOuter = pUnkOuter;
  33. m_phh = phh;
  34. m_hwndTree = NULL;
  35. m_cntCurHighlight = m_cntFirstVisible = 0;
  36. m_fSuppressJump = FALSE;
  37. m_fIgnoreNextSelChange = FALSE;
  38. m_fHack = FALSE;
  39. m_exStyles = 0;
  40. m_dwStyles = 0;
  41. m_padding = 0; // padding to put around the TOC
  42. if (phh)
  43. m_NavTabPos = phh->tabpos;
  44. else
  45. m_NavTabPos = HHWIN_NAVTAB_TOP ;;
  46. m_fSuspendSync = FALSE;
  47. m_hbmpBackGround = NULL;
  48. m_hbrBackGround = NULL;
  49. m_cFonts = 0;
  50. m_fGlobal = FALSE;
  51. m_tiFirstVisible = NULL;
  52. m_pInfoType = NULL;
  53. m_pBinTOCRoot = NULL;
  54. m_fBinaryTOC = NULL;
  55. m_fSyncOnActivation = FALSE;
  56. m_phTreeItem = NULL ;
  57. m_hil = NULL;
  58. }
  59. CToc::~CToc()
  60. {
  61. #if 1
  62. if ( m_pInfoType )
  63. delete m_pInfoType;
  64. #endif
  65. if (m_fBinaryTOC)
  66. {
  67. // clean up memory for binary tree
  68. // get the root item
  69. TV_ITEMW hCur;
  70. HTREEITEM hNext;
  71. CTreeNode *pCurNode;
  72. hCur.hItem = W_TreeView_GetRoot(m_hwndTree);
  73. // this loop will iterate through the top level nodes
  74. //
  75. while(hCur.hItem)
  76. {
  77. FreeChildrenAllocations(m_hwndTree, hCur.hItem);
  78. // get the next sibling (if any)
  79. //
  80. hNext = TreeView_GetNextSibling(m_hwndTree, hCur.hItem);
  81. // free this nodes item data
  82. //
  83. hCur.mask = TVIF_PARAM;
  84. if (W_TreeView_GetItem(m_hwndTree, &hCur) == TRUE)
  85. {
  86. if (hCur.lParam)
  87. {
  88. // delete the node from the treeview
  89. //
  90. W_TreeView_DeleteItem(m_hwndTree, hCur.hItem);
  91. // free the node's data
  92. //
  93. pCurNode = (CTreeNode *)hCur.lParam;
  94. delete pCurNode;
  95. }
  96. }
  97. // on to the next top level node
  98. //
  99. hCur.hItem = hNext;
  100. }
  101. }
  102. // free the node
  103. if (m_pBinTOCRoot)
  104. delete m_pBinTOCRoot;
  105. if (IsValidWindow(m_hwndTree))
  106. {
  107. DestroyWindow(m_hwndTree);
  108. // Destroying the TreeView control, make sure we no longer point to it as a valid
  109. // subclassed window.
  110. if (NULL != lpfnlTreeViewWndProc)
  111. {
  112. lpfnlTreeViewWndProc = NULL;
  113. }
  114. }
  115. if (m_hbrBackGround)
  116. DeleteObject(m_hbrBackGround);
  117. if (m_cFonts) {
  118. for (int i = 0; i < m_cFonts; i++)
  119. DeleteObject(m_ahfonts[i]);
  120. lcFree(m_ahfonts);
  121. }
  122. if (m_hbmpBackGround)
  123. DeleteObject(m_hbmpBackGround);
  124. if (m_hil)
  125. {
  126. ImageList_Destroy(m_hil);
  127. m_hil = NULL;
  128. }
  129. if ( m_phTreeItem )
  130. lcFree(m_phTreeItem);
  131. }
  132. BOOL CToc::ReadFile(PCSTR pszFile)
  133. {
  134. if (m_phh && m_phh->m_phmData && m_phh->m_phmData->m_pTitleCollection &&
  135. HashFromSz(FindFilePortion(pszFile)) == m_phh->m_phmData->m_hashBinaryTocName) {
  136. m_pBinTOCRoot = m_phh->m_phmData->m_pTitleCollection->GetRootNode();
  137. m_fBinaryTOC = (m_pBinTOCRoot && m_phh->m_phmData->m_pTitleCollection->GetFirstTitle() != NULL) ? TRUE : FALSE;
  138. if (!m_fBinaryTOC) {
  139. delete m_pBinTOCRoot;
  140. m_pBinTOCRoot = NULL;
  141. }
  142. else
  143. return TRUE;
  144. }
  145. UINT CodePage = -1;
  146. if( m_phh && m_phh->m_phmData ) {
  147. CodePage = m_phh->m_phmData->GetInfo()->GetCodePage();
  148. }
  149. return m_sitemap.ReadFromFile(pszFile, FALSE, NULL, CodePage);
  150. }
  151. BOOL CToc::Create(HWND hwndParent)
  152. {
  153. RECT rcParent;
  154. GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  155. DWORD dwTempStyle = 0;
  156. // Disable tooltips for bi-di due to common control bug
  157. //
  158. // if(g_RTL_Mirror_Style)
  159. // dwTempStyle = TVS_NOTOOLTIPS;
  160. if(g_RTL_Style && !g_RTL_Mirror_Style)
  161. dwTempStyle |= TVS_RTLREADING;
  162. m_hwndTree = W_CreateControlWindow(
  163. m_exStyles | g_RTL_Mirror_Style,
  164. WS_CHILD | m_dwStyles | dwTempStyle,
  165. W_TreeView, L"",
  166. rcParent.left, rcParent.top, RECT_WIDTH(rcParent), RECT_HEIGHT(rcParent),
  167. hwndParent, NULL, _Module.GetModuleInstance(), NULL);
  168. return m_hwndTree != NULL; // REVIEW: notify here if failure?
  169. }
  170. void CToc::ResizeWindow()
  171. {
  172. ASSERT(::IsValidWindow(m_hwndTree)) ;
  173. // Resize to fit the client area of the parent.
  174. HWND hwndParent = GetParent(m_hwndTree) ;
  175. ASSERT(::IsValidWindow(hwndParent)) ;
  176. RECT rcParent;
  177. GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  178. MoveWindow(m_hwndTree, rcParent.left,
  179. rcParent.top, RECT_WIDTH(rcParent), RECT_HEIGHT(rcParent), TRUE);
  180. }
  181. void CToc::HideWindow(void)
  182. {
  183. ASSERT(::IsValidWindow(m_hwndTree)) ;
  184. ::ShowWindow(m_hwndTree, SW_HIDE);
  185. }
  186. void CToc::ShowWindow(void)
  187. {
  188. ASSERT(::IsValidWindow(m_hwndTree)) ;
  189. ::ShowWindow(m_hwndTree, SW_SHOW);
  190. SetFocus(m_hwndTree);
  191. }
  192. /***************************************************************************
  193. FUNCTION: LoadContentsFile
  194. PURPOSE: Load the Contents file, convert it into g_pbTree
  195. PARAMETERS:
  196. pszMasterFile
  197. RETURNS:
  198. TRUE if successfully loaded
  199. COMMENTS:
  200. Assumes we are being run from a thread without a message queue.
  201. MODIFICATION DATES:
  202. 09-Jul-1997 [ralphw]
  203. ***************************************************************************/
  204. BOOL CHtmlHelpControl::LoadContentsFile(PCSTR pszMasterFile)
  205. {
  206. TCHAR szPath[MAX_PATH];
  207. if (!ConvertToCacheFile(pszMasterFile, szPath)) {
  208. szPath[0] = '\0';
  209. if (!IsCompiledHtmlFile(pszMasterFile) && m_pWebBrowserApp) {
  210. CStr cszCurUrl;
  211. m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  212. cszCurUrl.ReSize(cszCurUrl.SizeAlloc() + (int)strlen(pszMasterFile));
  213. PSTR pszChmSep = strstr(cszCurUrl, txtDoubleColonSep);
  214. if (pszChmSep) { // this is a compiled HTML file
  215. strcpy(pszChmSep + 2, pszMasterFile);
  216. strcpy(szPath, cszCurUrl);
  217. }
  218. }
  219. if (!szPath[0]) {
  220. AuthorMsg(IDS_CANT_OPEN, pszMasterFile);
  221. strncpy(szPath, pszMasterFile, MAX_PATH); // BugFix: Don't over write buffer.
  222. szPath[MAX_PATH-1] = 0;
  223. }
  224. }
  225. // Even if we failed, we continue on to let ReadFromFile create
  226. // a dummy entry.
  227. m_ptoc= new CToc(this, m_pUnkOuter);
  228. UINT CodePage = -1;
  229. if( m_ptoc && m_ptoc->m_phh && m_ptoc->m_phh->m_phmData ) {
  230. CodePage = m_ptoc->m_phh->m_phmData->GetInfo()->GetCodePage();
  231. }
  232. if (!m_ptoc->m_sitemap.ReadFromFile(szPath, FALSE, this, CodePage))
  233. return FALSE;
  234. if (m_ptoc->m_sitemap.CountStrings())
  235. m_ptoc->m_cntCurHighlight = m_ptoc->m_cntFirstVisible = 1;
  236. // populate the InfoType member object of the CToc
  237. if ( !m_ptoc->m_pInfoType )
  238. {
  239. if (m_ptoc->m_phh && m_ptoc->m_phh->m_phmData && m_ptoc->m_phh->m_phmData->m_pdInfoTypes )
  240. { // load from the global IT store
  241. m_ptoc->m_pInfoType = new CInfoType;
  242. m_ptoc->m_pInfoType->CopyTo( m_ptoc->m_phh->m_phmData );
  243. // if there are info type bits set by the API assign them here
  244. if ( m_ptoc->m_phh->m_phmData->m_pAPIInfoTypes &&
  245. m_ptoc->m_pInfoType->AnyInfoTypes(m_ptoc->m_phh->m_phmData->m_pAPIInfoTypes) )
  246. {
  247. memcpy(m_ptoc->m_pInfoType->m_pInfoTypes,
  248. m_ptoc->m_phh->m_phmData->m_pAPIInfoTypes,
  249. m_ptoc->m_pInfoType->InfoTypeSize() );
  250. }
  251. }else
  252. {
  253. // no global IT's; load from the .hhc IT store
  254. m_ptoc->m_pInfoType = new CInfoType;
  255. *m_ptoc->m_pInfoType = m_ptoc->m_sitemap;
  256. }
  257. }
  258. return TRUE;
  259. }
  260. __inline HTREEITEM Tree_AddItem(HWND hwndTree,
  261. HTREEITEM htiParent, int iImage, UINT cChildren, LPARAM lParam,
  262. TV_INSERTSTRUCTW* ptcInsert)
  263. {
  264. ptcInsert->hParent = htiParent;
  265. ptcInsert->item.iImage = iImage;
  266. ptcInsert->item.iSelectedImage = iImage;
  267. ptcInsert->item.cChildren = cChildren;
  268. ptcInsert->item.lParam = lParam;
  269. return W_TreeView_InsertItem(hwndTree, ptcInsert);
  270. }
  271. BOOL CToc::InitTreeView()
  272. {
  273. // REVIEW: following line from WinHelp codebase. Do we need it?
  274. ASSERT(::IsValidWindow(m_hwndTree)) ;
  275. WORD dwImageListResource = IDBMP_CNT_IMAGE_LIST;
  276. if(g_RTL_Mirror_Style)
  277. dwImageListResource = IDBMP_IMAGE_LIST_BIDI;
  278. SetWindowPos(m_hwndTree, NULL, 0, 0, 1, 1,
  279. SWP_DRAWFRAME | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
  280. if (!m_fGlobal ) { // BUGBUG [Pat H] Binary TOC needs to be enhanced for ImageLists.
  281. if (!m_sitemap.m_pszImageList || m_fBinaryTOC)
  282. m_hil = ImageList_LoadImage(_Module.GetResourceInstance(),
  283. MAKEINTRESOURCE(dwImageListResource),
  284. CWIDTH_IMAGE_LIST, 0, 0x00FF00FF, IMAGE_BITMAP, 0);
  285. else {
  286. char szBitmap[MAX_PATH];
  287. BOOL fResult;
  288. if (m_phhctrl)
  289. fResult = m_phhctrl->ConvertToCacheFile(m_sitemap.m_pszImageList, szBitmap);
  290. else
  291. fResult = ConvertToCacheFile(m_sitemap.m_pszImageList, szBitmap);
  292. if (fResult)
  293. m_hil = ImageList_LoadImage(NULL, szBitmap,
  294. m_sitemap.m_cImageWidth, 0, m_sitemap.m_clrMask, IMAGE_BITMAP, LR_LOADFROMFILE);
  295. else
  296. m_hil = NULL;
  297. if (!m_hil) {
  298. AuthorMsg(IDS_CANT_OPEN, m_sitemap.m_pszImageList, FindMessageParent(m_hwndTree), m_phhctrl);
  299. m_hil = ImageList_LoadImage(_Module.GetResourceInstance(),
  300. MAKEINTRESOURCE(dwImageListResource),
  301. CWIDTH_IMAGE_LIST, 0, 0x00FF00FF, IMAGE_BITMAP, 0);
  302. }
  303. }
  304. }
  305. if ( !m_fBinaryTOC )
  306. m_sitemap.m_cImages = ImageList_GetImageCount(m_hil);
  307. W_TreeView_SetImageList(m_hwndTree, m_hil, TVSIL_NORMAL);
  308. SendMessage(m_hwndTree, WM_SETREDRAW, FALSE, 0);
  309. // BUGBUG [Pat H] Binary TOC needs to be enhanced for FONT information.
  310. if (!m_fBinaryTOC && m_sitemap.m_pszFont) {
  311. /*
  312. * If the TOC had a font, it will over-ride any font specified in
  313. * the CHM file.
  314. */
  315. if (!m_fGlobal) {
  316. m_cFonts++;
  317. if (m_cFonts == 1)
  318. m_ahfonts = (HFONT*) lcMalloc(m_cFonts * sizeof(HFONT));
  319. else
  320. m_ahfonts = (HFONT*) lcReAlloc(m_ahfonts, m_cFonts * sizeof(HFONT));
  321. //
  322. // Insure correct charset...
  323. //
  324. int iCharset = -1;
  325. if ( m_phh )
  326. iCharset = m_phh->GetContentCharset();
  327. else if ( m_phhctrl )
  328. iCharset = m_phhctrl->GetCharset();
  329. if(g_fSysWinNT)
  330. {
  331. UINT CodePage = CP_ACP;
  332. if( m_phh && m_phh->m_phmData )
  333. CodePage = m_phh->m_phmData->GetInfo()->GetCodePage();
  334. WCHAR *pwcLocal = MakeWideStr((char *)m_sitemap.m_pszFont, CodePage);
  335. if(pwcLocal)
  336. {
  337. m_ahfonts[m_cFonts - 1] = CreateUserFontW(pwcLocal, NULL, NULL, iCharset);
  338. free(pwcLocal);
  339. }
  340. else
  341. m_ahfonts[m_cFonts - 1] = CreateUserFont(m_sitemap.m_pszFont, NULL, NULL, iCharset);
  342. }
  343. else
  344. m_ahfonts[m_cFonts - 1] = CreateUserFont(m_sitemap.m_pszFont, NULL, NULL, iCharset);
  345. }
  346. if (m_ahfonts[m_cFonts - 1])
  347. SendMessage(m_hwndTree, WM_SETFONT, (WPARAM) m_ahfonts[m_cFonts - 1], 0);
  348. }
  349. else {
  350. if ( m_phh )
  351. SendMessage(m_hwndTree, WM_SETFONT, (WPARAM)m_phh->GetAccessableContentFont(), 0);
  352. else if ( m_phhctrl )
  353. SendMessage(m_hwndTree, WM_SETFONT, (WPARAM)m_phhctrl->GetContentFont(), 0);
  354. }
  355. // +1 because we are a 1-based table
  356. if (!m_fBinaryTOC )
  357. {
  358. m_phTreeItem = (HTREEITEM*) lcCalloc((m_sitemap.CountStrings() + 1) * sizeof(HTREEITEM));
  359. TV_INSERTSTRUCTW tcAdd;
  360. tcAdd.hInsertAfter = TVI_LAST;
  361. tcAdd.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM;
  362. tcAdd.item.hItem = NULL;
  363. tcAdd.item.pszText = LPSTR_TEXTCALLBACKW;
  364. HTREEITEM ahtiParents[SITEMAP_MAX_LEVELS + 1];
  365. HTREEITEM hti = NULL;
  366. HTREEITEM htiParent = TVI_ROOT;
  367. int curLevel = 0;
  368. ahtiParents[0] = TVI_ROOT;
  369. int pos;
  370. CSubSets *pSSs = NULL;
  371. if ( m_phh && m_phh->m_phmData && m_phh->m_phmData->m_pTitleCollection &&
  372. m_phh->m_phmData->m_pTitleCollection->m_pSubSets )
  373. pSSs = m_phh->m_phmData->m_pTitleCollection->m_pSubSets;
  374. for (pos = 1; pos <= m_sitemap.CountStrings(); pos++)
  375. {
  376. dontAdd:
  377. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(pos);
  378. // the m_pInfoType member is set by the customize
  379. // option on the right click menu.
  380. if (!pSiteMapEntry->fShowToEveryOne && pSiteMapEntry->cUrls &&
  381. #if 0 // enable for subset filtering.
  382. m_pInfoType && !m_pInfoType->IsEntryInCurTypeList(pSiteMapEntry, pSSs ) )
  383. #else
  384. m_pInfoType && !m_pInfoType->IsEntryInCurTypeList(pSiteMapEntry ) )
  385. #endif
  386. //!m_sitemap.IsEntryInCurTypeList(pSiteMapEntry))
  387. {
  388. continue;
  389. }
  390. if (pSiteMapEntry->IsTopic()) {
  391. if (pSiteMapEntry->level > 0 && pSiteMapEntry->level <= curLevel) {
  392. // if (pSiteMapEntry->level < 1)
  393. // pSiteMapEntry->level = 1;
  394. htiParent = ahtiParents[curLevel = pSiteMapEntry->level - 1];
  395. }
  396. pSiteMapEntry->iImage = (BYTE)m_sitemap.GetImageNumber(pSiteMapEntry);
  397. // Add the topic to the treeview control
  398. HTREEITEM hItem = Tree_AddItem(m_hwndTree,
  399. htiParent, // parent
  400. pSiteMapEntry->iImage - 1,
  401. 0, // has kids
  402. (LPARAM) pos, // extra data
  403. &tcAdd);
  404. m_phTreeItem[pos] = hItem;
  405. }
  406. else {
  407. int i=0;
  408. SITEMAP_ENTRY *pSME;
  409. do {
  410. i++;
  411. pSME = m_sitemap.GetSiteMapEntry(pos+i);
  412. if ( (pSME>0) && (pSME->level <= pSiteMapEntry->level) )
  413. {
  414. pos+=i;
  415. goto dontAdd; // don't add the node with no topics to the TV.
  416. }
  417. }
  418. while( pSME > 0 && !pSME->fTopic );
  419. // *** FOLDER LINE ***
  420. if (pSiteMapEntry->level > curLevel + 1) // can't skip levels
  421. pSiteMapEntry->level = curLevel + 1;
  422. int this_level = pSiteMapEntry->level;
  423. if (this_level < 1)
  424. this_level = 1;
  425. // -1 to get a closed book
  426. pSiteMapEntry->iImage = (BYTE)m_sitemap.GetImageNumber(pSiteMapEntry);
  427. // switch to closed image
  428. if (pSiteMapEntry->iImage == IMAGE_OPEN_BOOK ||
  429. pSiteMapEntry->iImage == IMAGE_OPEN_BOOK_NEW ||
  430. pSiteMapEntry->iImage == IMAGE_OPEN_FOLDER ||
  431. pSiteMapEntry->iImage == IMAGE_OPEN_FOLDER_NEW)
  432. pSiteMapEntry->iImage--;
  433. htiParent = Tree_AddItem(m_hwndTree,
  434. ahtiParents[this_level - 1],
  435. pSiteMapEntry->iImage - 1,
  436. TRUE, (DWORD) pos, &tcAdd);
  437. m_phTreeItem[pos] = htiParent;
  438. ahtiParents[curLevel = this_level] = htiParent;
  439. }
  440. }
  441. }
  442. else
  443. LoadFirstLevel( m_pBinTOCRoot, m_hwndTree, &m_tiFirstVisible ); // binary TOC, load the first level of the tree view.
  444. #if 0
  445. 12-Aug-1997 [ralphw] This code is only useful if we are restoring
  446. a treeview control that was closed but not deleted.
  447. // REVIEW: this was in WinHelp code base
  448. // FlushMessageQueue(WM_USER);
  449. for (pos = 1; pos <= CountStrings(); pos++) {
  450. SITEMAP_ENTRY* pSiteMapEntry = GetSiteMapEntry(pos);
  451. // Restore our position
  452. if (pSiteMapEntry->iImage == IMAGE_OPEN_FOLDER) {
  453. W_TreeView_Expand(m_hwndTree, m_phTreeItem[pos],
  454. TVE_EXPAND);
  455. // REVIEW: this was in WinHelp code base
  456. // FlushMessageQueue(WM_USER);
  457. }
  458. }
  459. #endif
  460. // BUGBUG [Pat H] Binary TOC needs to be enhanced to support colors and background bitmaps
  461. if (!m_fBinaryTOC && !m_fGlobal) {
  462. if (m_sitemap.m_clrBackground != -1 && m_sitemap.m_clrForeground != -1) {
  463. HDC hdc = GetWindowDC(m_hwndTree);
  464. // If the colors are the same, then ignore them both
  465. if (GetHighContrastFlag() ||
  466. GetNearestColor(hdc, m_sitemap.m_clrBackground) ==
  467. GetNearestColor(hdc, m_sitemap.m_clrForeground))
  468. m_sitemap.m_clrBackground = m_sitemap.m_clrForeground = (COLORREF) -1;
  469. ReleaseDC(m_hwndTree, hdc);
  470. }
  471. if (m_sitemap.m_clrBackground != -1)
  472. m_hbrBackGround = CreateSolidBrush(m_sitemap.m_clrBackground);
  473. if (m_sitemap.m_pszBackBitmap && !m_hbmpBackGround) {
  474. char szBitmap[MAX_PATH];
  475. if (ConvertToCacheFile(m_sitemap.m_pszBackBitmap, szBitmap) &&
  476. LoadGif(szBitmap, &m_hbmpBackGround, &m_hpalBackGround, NULL)) {
  477. BITMAP bmp;
  478. GetObject(m_hbmpBackGround, sizeof(BITMAP), &bmp);
  479. m_cxBackBmp = bmp.bmWidth;
  480. m_cyBackBmp = bmp.bmHeight;
  481. }
  482. }
  483. }
  484. if (m_phh || m_hbrBackGround || m_hbmpBackGround)
  485. {
  486. BOOL fUni = IsWindowUnicode(m_hwndTree);
  487. if (lpfnlTreeViewWndProc == NULL)
  488. lpfnlTreeViewWndProc = W_GetWndProc(m_hwndTree, fUni);
  489. W_SubClassWindow(m_hwndTree, (LONG_PTR) TreeViewProc, fUni);
  490. SETTHIS(m_hwndTree);
  491. }
  492. SendMessage(m_hwndTree, WM_SETREDRAW, TRUE, 0);
  493. m_fSuppressJump = TRUE;
  494. if ( !m_fBinaryTOC )
  495. {
  496. ASSERT(m_cntFirstVisible <= m_sitemap.CountStrings());
  497. if (m_cntFirstVisible && m_phTreeItem)
  498. W_TreeView_Select(m_hwndTree, m_phTreeItem[m_cntFirstVisible],
  499. TVGN_FIRSTVISIBLE);
  500. }
  501. else
  502. {
  503. if ( m_tiFirstVisible )
  504. {
  505. W_TreeView_Select(m_hwndTree, m_tiFirstVisible, TVGN_FIRSTVISIBLE);
  506. m_hitemCurHighlight = m_tiFirstVisible;
  507. }
  508. }
  509. #ifdef _DEBUG
  510. HTREEITEM hItemFirstVisible = W_TreeView_GetFirstVisible(m_hwndTree);
  511. #endif
  512. if (!m_fBinaryTOC && m_cntCurHighlight && m_phTreeItem)
  513. W_TreeView_SelectItem(m_hwndTree, m_phTreeItem[m_cntCurHighlight]);
  514. m_hitemCurHighlight = W_TreeView_GetSelection(m_hwndTree);
  515. m_fSuppressJump = FALSE;
  516. if (m_fGlobal && !m_cszCurUrl.IsEmpty()) {
  517. m_fSuspendSync = FALSE;
  518. Synchronize(m_cszCurUrl);
  519. }
  520. ::ShowWindow(m_hwndTree, SW_SHOW);
  521. return TRUE;
  522. }
  523. __inline void Tree_SetImage(HWND hwndTree, int iImage, HTREEITEM hItem)
  524. {
  525. ASSERT(::IsValidWindow(hwndTree)) ;
  526. TV_ITEMW tvinfo;
  527. ZeroMemory(&tvinfo, sizeof(tvinfo));
  528. tvinfo.hItem = hItem;
  529. tvinfo.iImage = iImage - 1;
  530. tvinfo.iSelectedImage = iImage - 1;
  531. tvinfo.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  532. W_TreeView_SetItem(hwndTree, &tvinfo);
  533. }
  534. LRESULT CToc::OnSiteMapTVMsg( NM_TREEVIEW *pnmhdr )
  535. {
  536. SITEMAP_ENTRY* pSiteMapEntry;
  537. TV_HITTESTINFO ht;
  538. switch(pnmhdr->hdr.code) {
  539. case TVN_GETDISPINFOA:
  540. #define pdi ((TV_DISPINFOA*) pnmhdr)
  541. if (pdi->item.mask & TVIF_TEXT)
  542. {
  543. pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)pdi->item.lParam);
  544. strncpy(pdi->item.pszText, pSiteMapEntry->pszText, pdi->item.cchTextMax);
  545. }
  546. break;
  547. #undef pdi
  548. case TVN_GETDISPINFOW:
  549. #define pdi ((TV_DISPINFOW*) pnmhdr)
  550. if (pdi->item.mask & TVIF_TEXT)
  551. {
  552. pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)pdi->item.lParam);
  553. if (FAILED(pSiteMapEntry->GetKeyword(pdi->item.pszText, pdi->item.cchTextMax)))
  554. _wcsncpy(pdi->item.pszText, GetStringResourceW(IDS_UNTITLED), pdi->item.cchTextMax);
  555. }
  556. break;
  557. #undef pdi
  558. case NM_RETURN:
  559. case NM_DBLCLK:
  560. {
  561. TV_ITEMW tvi;
  562. ASSERT(::IsValidWindow(m_hwndTree)) ;
  563. tvi.hItem = W_TreeView_GetSelection(m_hwndTree);
  564. if (!tvi.hItem)
  565. break; // probably ENTER with no selection
  566. tvi.mask = TVIF_PARAM;
  567. W_TreeView_GetItem(m_hwndTree, &tvi);
  568. pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)tvi.lParam);
  569. if (pSiteMapEntry->pUrls) {
  570. m_fSuspendSync = TRUE;
  571. if (pSiteMapEntry->fSendEvent && m_phhctrl) {
  572. m_phhctrl->SendEvent(m_sitemap.GetUrlString(pSiteMapEntry->pUrls->urlPrimary));
  573. return NULL;
  574. }
  575. JumpToUrl(m_pOuter, m_hwndTree, pSiteMapEntry, m_pInfoType, &(this->m_sitemap), NULL);
  576. if (m_phh)
  577. {
  578. m_phh->m_hwndControl = m_hwndTree;
  579. }
  580. }
  581. // The treeview does not automatically expand the node with the enter key.
  582. // so we do it here.
  583. if ( pnmhdr->hdr.code == NM_RETURN )
  584. {
  585. if ( tvi.state & TVIS_EXPANDED )
  586. {
  587. W_TreeView_Expand( m_hwndTree, tvi.hItem, TVE_COLLAPSE );
  588. ASSERT(pSiteMapEntry->iImage);
  589. if ( (pSiteMapEntry->iImage>1) && (pSiteMapEntry->iImage <= IMAGE_OPEN_FOLDER_NEW) )
  590. {
  591. pSiteMapEntry->iImage--;
  592. }
  593. }
  594. else
  595. {
  596. W_TreeView_Expand( m_hwndTree, tvi.hItem, TVE_EXPAND );
  597. // The first time we send the TVE_EXPAND message we get a TVIS_ITEMEXPANDING message for the item.
  598. // The TVIS_ITEMEXPANDING message is not sent on subsequent expands of the same item.
  599. if ( tvi.state & TVIS_EXPANDEDONCE )
  600. {
  601. if (pSiteMapEntry->iImage == 0)
  602. pSiteMapEntry->iImage = (BYTE)m_sitemap.GetImageNumber(pSiteMapEntry);
  603. if (pSiteMapEntry->iImage < IMAGE_OPEN_FOLDER_NEW)
  604. pSiteMapEntry->iImage++;
  605. }
  606. }
  607. // Set the correct image
  608. Tree_SetImage(m_hwndTree, pSiteMapEntry->iImage, tvi.hItem);
  609. }
  610. }
  611. break;
  612. case TVN_SELCHANGING:
  613. m_hitemCurHighlight = pnmhdr->itemNew.hItem;
  614. break;
  615. case TVN_SELCHANGED:
  616. m_hitemCurHighlight = pnmhdr->itemNew.hItem;
  617. break;
  618. case NM_CLICK:
  619. /*
  620. * We want a single click to open a topic. We already process
  621. * the case where the selection changes, and we jump if it does.
  622. * However, the user may click an existing selection, in which
  623. * case we want to jump (because the jump may have failed when
  624. * the item was first selected. However, we need to post the
  625. * message so that the treeview control will finish processing
  626. * the click (which could result in a selection change.
  627. */
  628. if (!m_fSuppressJump) {
  629. ASSERT(::IsValidWindow(m_hwndTree)) ;
  630. TV_HITTESTINFO ht;
  631. GetCursorPos(&ht.pt);
  632. ScreenToClient(m_hwndTree, &ht.pt);
  633. W_TreeView_HitTest(m_hwndTree, &ht);
  634. if (ht.flags & TVHT_ONITEMBUTTON)
  635. break; // just clicking the button, so ignore
  636. TV_ITEMW tvi;
  637. tvi.hItem = ht.hItem;
  638. if (!tvi.hItem)
  639. break; // probably ENTER with no selection
  640. m_hitemCurHighlight = tvi.hItem;
  641. tvi.mask = TVIF_PARAM;
  642. W_TreeView_GetItem(m_hwndTree, &tvi);
  643. pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)tvi.lParam);
  644. PostMessage(FindMessageParent(m_hwndTree), WM_COMMAND, ID_TV_SINGLE_CLICK,
  645. (LPARAM) W_TreeView_GetSelection(m_hwndTree));
  646. }
  647. break;
  648. case TVN_ITEMEXPANDINGA:
  649. case TVN_ITEMEXPANDINGW:
  650. {
  651. if (m_fHack) {
  652. m_fHack = FALSE;
  653. break;
  654. }
  655. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)pnmhdr->itemNew.lParam);
  656. // if click on vacant area of TOC Tree view there is no sitemap entry.
  657. if ( pSiteMapEntry == NULL )
  658. break;
  659. // REVIEW: need to update this to support multiple images
  660. // for multiple levels, and also to support "new" images
  661. if (pnmhdr->action & TVE_EXPAND) {
  662. if ( !(pnmhdr->itemNew.state & TVIS_EXPANDED) )
  663. {
  664. if (pSiteMapEntry->iImage == 0)
  665. pSiteMapEntry->iImage = (BYTE)m_sitemap.GetImageNumber(pSiteMapEntry);
  666. if (pSiteMapEntry->iImage < IMAGE_OPEN_FOLDER_NEW)
  667. pSiteMapEntry->iImage++;
  668. }
  669. else
  670. break;
  671. }
  672. else {
  673. ASSERT(pnmhdr->action & TVE_COLLAPSE);
  674. ASSERT(pSiteMapEntry->iImage);
  675. if ( pnmhdr->itemNew.state & TVIS_EXPANDED )
  676. {
  677. if ( (pSiteMapEntry->iImage>1) && (pSiteMapEntry->iImage <= IMAGE_OPEN_FOLDER_NEW) )
  678. pSiteMapEntry->iImage--;
  679. }
  680. else
  681. break;
  682. }
  683. // Set the correct image
  684. ASSERT(::IsValidWindow(m_hwndTree)) ;
  685. Tree_SetImage(m_hwndTree, pSiteMapEntry->iImage, pnmhdr->itemNew.hItem);
  686. }
  687. break;
  688. case TVN_KEYDOWN:
  689. TV_KEYDOWN* ptvkd;
  690. ptvkd = (TV_KEYDOWN*)pnmhdr;
  691. if ( ptvkd->wVKey != VK_F10 )
  692. break;
  693. else if ( GetKeyState(VK_SHIFT) >= 0 )
  694. break;
  695. else
  696. {
  697. ht.pt.x = ht.pt.y = 0;
  698. ClientToScreen(m_hwndTree, &ht.pt);
  699. goto sim_rclick;
  700. }
  701. break;
  702. case NM_RCLICK:
  703. {
  704. GetCursorPos(&ht.pt);
  705. ScreenToClient(m_hwndTree, &ht.pt);
  706. W_TreeView_HitTest(m_hwndTree, &ht);
  707. if ( ht.hItem )
  708. W_TreeView_Select(m_hwndTree, ht.hItem, TVGN_CARET);
  709. ClientToScreen(m_hwndTree, &ht.pt);
  710. sim_rclick:
  711. HMENU hmenu = CreatePopupMenu();
  712. if (!hmenu)
  713. break;
  714. ASSERT(::IsValidWindow(m_hwndTree)) ;
  715. // NOTICE: Changes here must be reflected in the binary toc verison of this menu
  716. if (!(m_dwStyles & TVS_SINGLEEXPAND)) {
  717. HxAppendMenu(hmenu, MF_STRING, ID_EXPAND_ALL, GetStringResource(IDS_EXPAND_ALL));
  718. HxAppendMenu(hmenu, MF_STRING, ID_CONTRACT_ALL, GetStringResource(IDS_CONTRACT_ALL));
  719. }
  720. if ((m_phh == NULL) || (m_phh && m_phh->m_pCIExpContainer))
  721. HxAppendMenu(hmenu, MF_STRING, ID_PRINT, GetStringResource(IDS_PRINT));
  722. ASSERT( m_pInfoType );
  723. // populate the InfoType member object of the CToc
  724. if ( !m_pInfoType )
  725. {
  726. if (m_phh && m_phh->m_phmData && m_phh->m_phmData->m_pdInfoTypes )
  727. { // load from the global IT store
  728. m_pInfoType = new CInfoType;
  729. m_pInfoType->CopyTo( m_phh->m_phmData );
  730. // if there are info type bits set by the API assign them here
  731. if ( m_phh->m_phmData->m_pAPIInfoTypes &&
  732. m_pInfoType->AnyInfoTypes(m_phh->m_phmData->m_pAPIInfoTypes) )
  733. {
  734. memcpy(m_pInfoType->m_pInfoTypes,
  735. m_phh->m_phmData->m_pAPIInfoTypes,
  736. m_pInfoType->InfoTypeSize() );
  737. }
  738. }else
  739. {
  740. // no global IT's; load from the .hhc IT store
  741. m_pInfoType = new CInfoType;
  742. *m_pInfoType = m_sitemap;
  743. }
  744. }
  745. else
  746. {
  747. // Set the infotypes bits to set all the types
  748. }
  749. // If there are infotypes add the "customize" option to the popup menu
  750. if (m_pInfoType && m_pInfoType->HowManyInfoTypes() && m_pInfoType->GetFirstHidden() != 1)
  751. HxAppendMenu(hmenu, MF_STRING, ID_CUSTOMIZE_INFO_TYPES,
  752. GetStringResource(IDS_CUSTOMIZE_INFO_TYPES));
  753. if (IsHelpAuthor(FindMessageParent(m_hwndTree))) {
  754. AppendMenu(hmenu, MF_SEPARATOR, 0, 0);
  755. HxAppendMenu(hmenu, MF_STRING, ID_VIEW_ENTRY, pGetDllStringResource(IDS_VIEW_ENTRY));
  756. if (NoRun() == FALSE)
  757. HxAppendMenu(hmenu, MF_STRING, ID_JUMP_URL, GetStringResource(IDS_JUMP_URL));
  758. }
  759. #ifdef _DEBUG
  760. HxAppendMenu(hmenu, MF_STRING, ID_VIEW_MEMORY,
  761. "Debug: memory usage...");
  762. #endif
  763. TrackPopupMenu(hmenu,
  764. TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
  765. ht.pt.x, ht.pt.y, 0, FindMessageParent(m_hwndTree), NULL);
  766. DestroyMenu(hmenu);
  767. return TRUE;
  768. }
  769. break;
  770. case NM_CUSTOMDRAW:
  771. return OnCustomDraw((LPNMTVCUSTOMDRAW) pnmhdr);
  772. }
  773. return FALSE;
  774. }
  775. // This is the message handler for the Tree View containing the Table of Contents.
  776. LRESULT CToc::TreeViewMsg(NM_TREEVIEW* pnmhdr)
  777. {
  778. if ( !m_fBinaryTOC )
  779. return OnSiteMapTVMsg( pnmhdr );
  780. else
  781. return OnBinaryTOCTVMsg ( pnmhdr );
  782. }
  783. BOOL (STDCALL *pResetTocAppearance)(HWND hwndParent, HHA_TOC_APPEARANCE* pappear);
  784. LRESULT CToc::OnCommand(HWND /*hwnd*/, UINT id, UINT uNotifiyCode, LPARAM lParam)
  785. {
  786. if ( m_fBinaryTOC )
  787. return OnBinTOCContentsCommand(id, uNotifiyCode, lParam);
  788. else
  789. return OnSiteMapContentsCommand(id, uNotifiyCode, lParam);
  790. }
  791. LRESULT CToc::OnSiteMapContentsCommand(UINT id, UINT uNotifyCode, LPARAM lParam)
  792. {
  793. ASSERT(::IsValidWindow(m_hwndTree)) ;
  794. switch (id) {
  795. case ID_EXPAND_ALL:
  796. {
  797. ASSERT(::IsValidWindow(m_hwndTree)) ;
  798. m_hitemCurHighlight = W_TreeView_GetSelection(m_hwndTree);
  799. CHourGlass hourglass;
  800. SendMessage(m_hwndTree, WM_SETREDRAW, FALSE, 0);
  801. for (int pos = 1; pos <= m_sitemap.CountStrings(); pos++) {
  802. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(pos);
  803. // If it is not a topic, and the book is closed
  804. TV_ITEMW tvi;
  805. tvi.hItem = m_phTreeItem[pos];
  806. tvi.mask = TVIF_STATE;
  807. W_TreeView_GetItem(m_hwndTree, &tvi);
  808. if (!pSiteMapEntry->IsTopic() && !(tvi.state & TVIS_EXPANDED)) {
  809. m_fHack = TRUE; // ignore expansion notice
  810. W_TreeView_Expand(m_hwndTree, m_phTreeItem[pos], TVE_EXPAND);
  811. if (pSiteMapEntry->iImage < IMAGE_OPEN_FOLDER_NEW)
  812. pSiteMapEntry->iImage++;
  813. Tree_SetImage(m_hwndTree, pSiteMapEntry->iImage, m_phTreeItem[pos]);
  814. }
  815. }
  816. SendMessage(m_hwndTree, WM_SETREDRAW, TRUE, 0);
  817. if (m_hitemCurHighlight) {
  818. m_fSuppressJump = TRUE;
  819. m_fHack = TRUE; // ignore expansion notice
  820. W_TreeView_Select(m_hwndTree, m_hitemCurHighlight, TVGN_FIRSTVISIBLE);
  821. W_TreeView_SelectItem(m_hwndTree, m_hitemCurHighlight);
  822. m_fSuppressJump = FALSE;
  823. }
  824. }
  825. m_fHack = FALSE; // process expansion/contraction normally
  826. return 0;
  827. case ID_CONTRACT_ALL:
  828. {
  829. ASSERT(::IsValidWindow(m_hwndTree)) ;
  830. m_hitemCurHighlight = W_TreeView_GetSelection(m_hwndTree);
  831. SendMessage(m_hwndTree, WM_SETREDRAW, FALSE, 0);
  832. for (int pos = 1; pos <= m_sitemap.CountStrings(); pos++) {
  833. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(pos);
  834. // If it is not a topic, and the book is open
  835. TV_ITEMW tvi;
  836. tvi.hItem = m_phTreeItem[pos];
  837. tvi.mask = TVIF_STATE;
  838. W_TreeView_GetItem(m_hwndTree, &tvi);
  839. if (!pSiteMapEntry->IsTopic() && (tvi.state & TVIS_EXPANDED)) {
  840. m_fHack = TRUE; // ignore contraction notice
  841. W_TreeView_Expand(m_hwndTree, m_phTreeItem[pos], TVE_COLLAPSE);
  842. if (pSiteMapEntry->iImage <= IMAGE_OPEN_FOLDER_NEW)
  843. pSiteMapEntry->iImage--;
  844. Tree_SetImage(m_hwndTree, pSiteMapEntry->iImage, m_phTreeItem[pos]);
  845. }
  846. }
  847. SendMessage(m_hwndTree, WM_SETREDRAW, TRUE, 0);
  848. }
  849. m_fHack = FALSE; // process expansion/contraction normally
  850. return 0;
  851. #ifndef CHIINDEX
  852. case ID_PRINT:
  853. {
  854. if (m_phh) {
  855. if (m_phh->OnTrackNotifyCaller(HHACT_PRINT))
  856. break;
  857. m_phh->OnPrint();
  858. break;
  859. }
  860. CPrint prt(GetParent(m_hwndTree));
  861. prt.SetAction(PRINT_CUR_HEADING);
  862. if (!prt.DoModal())
  863. break;
  864. int action = prt.GetAction();
  865. ASSERT(m_phhctrl);
  866. PrintTopics(action, this,
  867. m_phhctrl->m_pWebBrowserApp, m_phhctrl->m_hwndHelp);
  868. }
  869. return 0;
  870. #endif
  871. case ID_CUSTOMIZE_INFO_TYPES:
  872. {
  873. if ( m_phh && m_phh->m_phmData->m_pTitleCollection->m_pSubSets->GetTocSubset() )
  874. m_phh->m_phmData->m_pTitleCollection->m_pSubSets->m_cur_Set = m_phh->m_phmData->m_pTitleCollection->m_pSubSets->GetTocSubset(); // set this so the wizard knows which subset to load the combo box with.
  875. #if 0 // enable for subset filtering
  876. if (ChooseInformationTypes(m_pInfoType, &(this->m_sitemap),
  877. m_hwndTree, m_phhctrl, m_phh)) {
  878. #else
  879. if (ChooseInformationTypes(m_pInfoType, &(this->m_sitemap),
  880. m_hwndTree, m_phhctrl)) {
  881. #endif
  882. if (m_phh)
  883. m_phh->UpdateInformationTypes();
  884. else {
  885. HWND hwndParent = GetParent(m_hwndTree);
  886. DestroyWindow(m_hwndTree);
  887. // Destroying the TreeView control, make sure we no longer point to it as a valid
  888. // subclassed window.
  889. if (NULL != lpfnlTreeViewWndProc)
  890. {
  891. lpfnlTreeViewWndProc = NULL;
  892. }
  893. Create(hwndParent);
  894. InitTreeView();
  895. }
  896. }
  897. }
  898. break;
  899. case ID_VIEW_ENTRY:
  900. {
  901. TV_ITEMW tvi;
  902. tvi.hItem = W_TreeView_GetSelection(m_hwndTree);
  903. if (!tvi.hItem)
  904. return 0; // no current selection
  905. tvi.mask = TVIF_PARAM;
  906. W_TreeView_GetItem(m_hwndTree, &tvi);
  907. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)tvi.lParam);
  908. DisplayAuthorInfo(m_pInfoType, &(this->m_sitemap), pSiteMapEntry, FindMessageParent(m_hwndTree), m_phhctrl);
  909. }
  910. return 0;
  911. case ID_JUMP_URL:
  912. {
  913. char szDstUrl[INTERNET_MAX_URL_LENGTH];
  914. CStr cszCurUrl;
  915. if (m_phhctrl)
  916. m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  917. else
  918. m_phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  919. if (doJumpUrl(GetParent(m_hwndTree), cszCurUrl, szDstUrl) && szDstUrl[0]) {
  920. if (m_phhctrl) {
  921. CWStr cwJump(szDstUrl);
  922. HlinkSimpleNavigateToString(cwJump, NULL,
  923. NULL, m_phhctrl->GetIUnknown(), NULL, NULL, 0, NULL);
  924. }
  925. else {
  926. ChangeHtmlTopic(szDstUrl, GetParent(m_hwndTree));
  927. }
  928. }
  929. }
  930. break;
  931. #ifdef _DEBUG
  932. case ID_VIEW_MEMORY:
  933. OnReportMemoryUsage();
  934. return 0;
  935. #endif
  936. case ID_TV_SINGLE_CLICK:
  937. {
  938. TV_ITEMW tvi;
  939. tvi.mask = TVIF_PARAM;
  940. if (m_hitemCurHighlight == 0 )
  941. break;
  942. tvi.hItem = m_hitemCurHighlight;
  943. W_TreeView_GetItem(m_hwndTree, &tvi);
  944. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)tvi.lParam);
  945. // if (pSiteMapEntry->fShortCut) {
  946. if (pSiteMapEntry->pUrls) {
  947. m_fIgnoreNextSelChange = TRUE;
  948. m_fSuspendSync = TRUE;
  949. if (pSiteMapEntry->fSendEvent && m_phhctrl)
  950. m_phhctrl->SendEvent(m_sitemap.GetUrlString(pSiteMapEntry->pUrls->urlPrimary));
  951. else {
  952. SaveCurUrl(); // so we can restore our state
  953. JumpToUrl(m_pOuter, m_hwndTree, pSiteMapEntry,
  954. m_pInfoType, &(this->m_sitemap), NULL);
  955. }
  956. }
  957. if (m_phh)
  958. {
  959. m_phh->m_hwndControl = m_hwndTree;
  960. }
  961. }
  962. break;
  963. }
  964. return 0;
  965. }
  966. BOOL CToc::Synchronize(LPCSTR pszURL)
  967. {
  968. HRESULT hr;
  969. CTreeNode* pSyncNode, *pCurNode;
  970. if (m_phh && m_phh->curNavType != HHWIN_NAVTYPE_TOC) {
  971. m_fSyncOnActivation = TRUE;
  972. return TRUE; // don't sync if we're not the active tab
  973. }
  974. ASSERT(::IsValidWindow(m_hwndTree)) ;
  975. if (m_fBinaryTOC)
  976. {
  977. BOOL bSynced = FALSE;
  978. CPointerList hier;
  979. LISTITEM *pItem;
  980. ASSERT(m_phh->m_phmData);
  981. ASSERT(!IsBadReadPtr(m_phh->m_phmData, sizeof(CHmData)));
  982. hr = m_phh->m_phmData->m_pTitleCollection->Sync(&hier, pszURL);
  983. if ( SUCCEEDED(hr) )
  984. {
  985. TV_ITEMW hCur;
  986. hCur.hItem = W_TreeView_GetRoot(m_hwndTree);
  987. pItem = hier.First();
  988. pSyncNode = (CTreeNode *)pItem->pItem;
  989. while (hCur.hItem && pSyncNode)
  990. {
  991. hCur.mask = TVIF_PARAM | TVIF_IMAGE;
  992. if (W_TreeView_GetItem(m_hwndTree, &hCur) == FALSE)
  993. break;
  994. pCurNode = (CTreeNode *)hCur.lParam;
  995. if (pSyncNode->Compare(pCurNode) == TRUE)
  996. {
  997. pItem = hier.Next(pItem);
  998. if (pItem == NULL)
  999. {
  1000. // just found it
  1001. bSynced = TRUE;
  1002. break;
  1003. }
  1004. // found a parent node, expand and find next item
  1005. if (pCurNode->m_Expanded == FALSE)
  1006. {
  1007. if (HandleExpanding(&hCur, m_hwndTree, TVE_EXPAND, &m_fSuspendSync) == FALSE)
  1008. break;
  1009. if (W_TreeView_Expand(m_hwndTree, hCur.hItem, TVE_EXPAND) == FALSE)
  1010. break;
  1011. }
  1012. hCur.hItem = W_TreeView_GetChild(m_hwndTree, hCur.hItem);
  1013. pSyncNode = (CTreeNode *)pItem->pItem;
  1014. }
  1015. else
  1016. hCur.hItem = W_TreeView_GetNextSibling(m_hwndTree, hCur.hItem);
  1017. }
  1018. if (bSynced == TRUE)
  1019. {
  1020. W_TreeView_SelectItem(m_hwndTree, hCur.hItem);
  1021. }
  1022. // clean up memory
  1023. for (pItem = hier.First(); pItem; )
  1024. {
  1025. if (pItem->pItem)
  1026. delete pItem->pItem;
  1027. pItem = hier.Next(pItem);
  1028. }
  1029. return bSynced;
  1030. }
  1031. return FALSE;
  1032. }
  1033. //
  1034. // sitmap syncing code...
  1035. //
  1036. if (m_fSuspendSync) {
  1037. m_fSuspendSync = FALSE;
  1038. return TRUE;
  1039. }
  1040. TCHAR szUrl[MAX_URL];
  1041. PSTR pszUrl = szUrl;
  1042. if (IsEmptyString(pszURL)) // Avoid crash.
  1043. {
  1044. return FALSE ;
  1045. }
  1046. strcpy(pszUrl, pszURL);
  1047. PSTR pszSep = strstr(pszUrl, txtDoubleColonSep);
  1048. if (pszSep)
  1049. strcpy(pszUrl, pszSep + 2);
  1050. m_hitemCurHighlight = W_TreeView_GetSelection(m_hwndTree);
  1051. TV_ITEMW tvi;
  1052. if (m_hitemCurHighlight) {
  1053. tvi.mask = TVIF_PARAM;
  1054. tvi.hItem = m_hitemCurHighlight;
  1055. W_TreeView_GetItem(m_hwndTree, &tvi);
  1056. }
  1057. else
  1058. tvi.lParam = 0;
  1059. BOOL fFoundMatch = FALSE;
  1060. ConvertBackSlashToForwardSlash(pszUrl);
  1061. if (IsCompiledURL(pszUrl)) {
  1062. PSTR psz = strstr(pszUrl, txtDoubleColonSep);
  1063. ASSERT(psz);
  1064. pszUrl = psz + 2;
  1065. }
  1066. if (pszUrl[0] == '/' && pszUrl[1] != '/')
  1067. pszUrl++; // remove the root directive
  1068. PSTR pszUrlBookMark = StrChr(pszUrl, '#');
  1069. if (pszUrlBookMark)
  1070. *pszUrlBookMark++ = '\0';
  1071. CStr cszSiteUrl;
  1072. // Start from our current position and go forward
  1073. for (int pos = (int)tvi.lParam + 1; pos <= m_sitemap.CountStrings(); pos++) {
  1074. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(pos);
  1075. for (int i = 0; i < pSiteMapEntry->cUrls; i++) {
  1076. SITE_ENTRY_URL* pUrl = m_sitemap.GetUrlEntry(pSiteMapEntry, i);
  1077. if (pUrl->urlPrimary) {
  1078. cszSiteUrl = m_sitemap.GetUrlString(pUrl->urlPrimary);
  1079. PSTR pszSiteUrl = cszSiteUrl.psz;
  1080. ConvertBackSlashToForwardSlash(pszSiteUrl);
  1081. // Bug 2362 we are syncing to a htm file where the same file and path exist
  1082. // in two or more other merged chms we could sync to the wrong one. This is
  1083. // an acceptable trade off to the reams of changes require to fully fix the bug
  1084. PSTR pszSep = strstr(pszSiteUrl, txtDoubleColonSep);
  1085. if (pszSep)
  1086. strcpy(pszSiteUrl, pszSep + 2);
  1087. if (pszSiteUrl[0] == '/' && pszSiteUrl[1] != '/')
  1088. pszSiteUrl++; // remove the root directive
  1089. PSTR pszSiteBookMark = StrChr(pszSiteUrl, '#');
  1090. if (pszSiteBookMark)
  1091. *pszSiteBookMark++ = '\0';
  1092. if (lstrcmpi(pszUrl, pszSiteUrl) == 0) {
  1093. // If both URLS have bookmarks, then they must match
  1094. if (pszSiteBookMark && pszUrlBookMark) {
  1095. if (lstrcmpi(pszSiteBookMark, pszUrlBookMark) != 0)
  1096. continue;
  1097. }
  1098. fFoundMatch = TRUE;
  1099. break;
  1100. }
  1101. }
  1102. }
  1103. if (fFoundMatch)
  1104. break;
  1105. }
  1106. // Start from current position - 1, and go backwards
  1107. if (!fFoundMatch) {
  1108. for (pos = (int)tvi.lParam; pos > 1; pos--) {
  1109. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(pos);
  1110. for (int i = 0; i < pSiteMapEntry->cUrls; i++) {
  1111. SITE_ENTRY_URL* pUrl = m_sitemap.GetUrlEntry(pSiteMapEntry, i);
  1112. if (pUrl->urlPrimary) {
  1113. cszSiteUrl = m_sitemap.GetUrlString(pUrl->urlPrimary);
  1114. PSTR pszSiteUrl = cszSiteUrl.psz;
  1115. ConvertBackSlashToForwardSlash(pszSiteUrl);
  1116. // Bug 2362 we are syncing to a htm file where the same file and path exist
  1117. // in two or more other merged chms we could sync to the wrong one. This is
  1118. // an acceptable trade off to the reams of changes require to fully fix the bug
  1119. PSTR pszSep = strstr(pszSiteUrl, txtDoubleColonSep);
  1120. if (pszSep)
  1121. strcpy(pszSiteUrl, pszSep + 2);
  1122. if (pszSiteUrl[0] == '/' && pszSiteUrl[1] != '/')
  1123. pszSiteUrl++; // remove the root directive
  1124. PSTR pszSiteBookMark = StrChr(pszSiteUrl, '#');
  1125. if (pszSiteBookMark)
  1126. *pszSiteBookMark++ = '\0';
  1127. if (lstrcmpi(pszUrl, pszSiteUrl) == 0) {
  1128. // If both URLS have bookmarks, then they must match
  1129. if (pszSiteBookMark && pszUrlBookMark) {
  1130. if (lstrcmpi(pszSiteBookMark, pszUrlBookMark) != 0)
  1131. continue;
  1132. }
  1133. fFoundMatch = TRUE;
  1134. break;
  1135. }
  1136. }
  1137. }
  1138. if (fFoundMatch)
  1139. break;
  1140. }
  1141. }
  1142. if (fFoundMatch) {
  1143. m_fSuppressJump = TRUE;
  1144. if (m_phTreeItem)
  1145. {
  1146. W_TreeView_SelectItem(m_hwndTree, m_phTreeItem[pos]);
  1147. // For an unknown reason (we suspect a bug in the common control)
  1148. // the treeview control does not always paint properly under Thai
  1149. // this situation. This code forces a repaint (corrects the
  1150. // problem). See HH Bug #5581.
  1151. //
  1152. if(g_langSystem == LANG_THAI && !g_fSysWinNT)
  1153. InvalidateRect(GetParent(m_hwndTree), NULL, FALSE);
  1154. }
  1155. m_fSuppressJump = FALSE;
  1156. }
  1157. return fFoundMatch;
  1158. }
  1159. DWORD CToc::OnCustomDraw(LPNMTVCUSTOMDRAW pnmcdrw)
  1160. {
  1161. switch (pnmcdrw->nmcd.dwDrawStage) {
  1162. case CDDS_PREPAINT:
  1163. return CDRF_NOTIFYITEMDRAW;
  1164. case CDDS_ITEMPREPAINT:
  1165. if (m_sitemap.m_clrBackground != (COLORREF) -1 && !(pnmcdrw->nmcd.uItemState & CDIS_SELECTED))
  1166. pnmcdrw->clrTextBk = m_sitemap.m_clrBackground;
  1167. if (m_sitemap.m_clrForeground != (COLORREF) -1 && !(pnmcdrw->nmcd.uItemState & CDIS_SELECTED))
  1168. pnmcdrw->clrText = m_sitemap.m_clrForeground;
  1169. // SetBkMode(pnmcdrw->nmcd.hdc, TRANSPARENT);
  1170. break;
  1171. }
  1172. return CDRF_DODEFAULT;
  1173. }
  1174. LRESULT WINAPI TreeViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1175. {
  1176. switch (msg) {
  1177. case WM_CHAR: //Process this message to avoid beeps.
  1178. if ((wParam == VK_RETURN) || (wParam == VK_TAB))
  1179. return 0;
  1180. return W_DelegateWindowProc(lpfnlTreeViewWndProc, hwnd, msg, wParam, lParam);
  1181. case WM_KEYDOWN:
  1182. if (wParam == VK_MULTIPLY)
  1183. return 0;
  1184. break;
  1185. case WM_SYSKEYDOWN:
  1186. if ( wParam == VK_LEFT || wParam == VK_RIGHT || wParam == VK_UP || wParam == VK_DOWN )
  1187. {
  1188. return TRUE;
  1189. }
  1190. break;
  1191. case WM_ERASEBKGND:
  1192. {
  1193. CToc* pThis = (CToc*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1194. ASSERT(pThis);
  1195. if (pThis && pThis->m_hbmpBackGround) {
  1196. RECT rc;
  1197. HDC hdc = (HDC) wParam;
  1198. GetClientRect(hwnd, &rc);
  1199. // GetClipBox(hdc, &rc);
  1200. CPalDC dc(pThis->m_hbmpBackGround);
  1201. HPALETTE hpalTmp = NULL;
  1202. if (pThis->m_hpalBackGround) {
  1203. hpalTmp = SelectPalette(hdc,
  1204. pThis->m_hpalBackGround, FALSE);
  1205. RealizePalette(hdc);
  1206. }
  1207. for (int left = 0; left <= rc.right; left += pThis->m_cxBackBmp) {
  1208. for (int top = 0; top <= rc.bottom; top += pThis->m_cyBackBmp) {
  1209. BitBlt((HDC) wParam, left, top, pThis->m_cxBackBmp,
  1210. pThis->m_cyBackBmp, dc,
  1211. 0, 0, SRCCOPY);
  1212. }
  1213. }
  1214. if (hpalTmp)
  1215. SelectPalette(hdc, hpalTmp, FALSE);
  1216. }
  1217. else if (pThis && pThis->m_hbrBackGround) {
  1218. RECT rc;
  1219. GetClipBox((HDC) wParam, &rc);
  1220. FillRect((HDC) wParam, &rc, pThis->m_hbrBackGround);
  1221. return TRUE;
  1222. }
  1223. else
  1224. break;
  1225. }
  1226. return TRUE;
  1227. }
  1228. return W_DelegateWindowProc(lpfnlTreeViewWndProc, hwnd, msg, wParam, lParam);
  1229. }
  1230. void CToc::SaveCurUrl(void)
  1231. {
  1232. ASSERT(::IsValidWindow(m_hwndTree)) ;
  1233. TV_ITEMW tvi;
  1234. tvi.hItem = W_TreeView_GetSelection(m_hwndTree);
  1235. if (!tvi.hItem)
  1236. return; // no current selection
  1237. tvi.mask = TVIF_PARAM;
  1238. W_TreeView_GetItem(m_hwndTree, &tvi);
  1239. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry((int)tvi.lParam);
  1240. ASSERT(pSiteMapEntry);
  1241. SITE_ENTRY_URL* pUrl = m_sitemap.GetUrlEntry(pSiteMapEntry, 0);
  1242. if (pUrl) { // a book/folder may not have an URL to save
  1243. if (pUrl->urlPrimary)
  1244. m_cszCurUrl = m_sitemap.GetUrlString(pUrl->urlPrimary);
  1245. else
  1246. m_cszCurUrl = m_sitemap.GetUrlString(pUrl->urlSecondary);
  1247. }
  1248. }
  1249. BOOL HandleExpanding(TVITEMW* pTvi, HWND hwndTreeView, UINT action, BOOL *pSync)
  1250. {
  1251. CTreeNode* pNode;
  1252. ASSERT(::IsValidWindow(hwndTreeView)) ;
  1253. if (! (pNode = (CTreeNode *)pTvi->lParam) ) // A pointer into the binary TOC; a CTreeNode
  1254. return FALSE;
  1255. int iImage = pTvi->iImage;
  1256. if (action & TVE_EXPAND)
  1257. {
  1258. if (pNode->m_Expanded == TRUE)
  1259. return TRUE;
  1260. pNode->m_Expanded = TRUE;
  1261. AddChildren(pTvi, hwndTreeView); // Add the items below the expanding parent
  1262. iImage++;
  1263. }
  1264. else
  1265. {
  1266. *pSync = FALSE;
  1267. pNode->m_Expanded = FALSE;
  1268. ASSERT(action & TVE_COLLAPSE);
  1269. DeleteChildren(pTvi, hwndTreeView);
  1270. if ( iImage )
  1271. iImage--;
  1272. }
  1273. // Set the correct image for the expanding/contracting node
  1274. TV_ITEMW tvinfo;
  1275. ZeroMemory(&tvinfo, sizeof(tvinfo));
  1276. tvinfo.hItem = pTvi->hItem;
  1277. tvinfo.iImage = tvinfo.iSelectedImage = iImage;
  1278. tvinfo.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1279. W_TreeView_SetItem(hwndTreeView, &tvinfo);
  1280. return TRUE;
  1281. }
  1282. LRESULT CToc::OnBinaryTOCTVMsg( NM_TREEVIEW *pnmhdr )
  1283. {
  1284. CTreeNode* pNode;
  1285. TV_ITEMW tvItem;
  1286. char szTempURL[MAX_URL];
  1287. TV_DISPINFO* pdi;
  1288. TV_HITTESTINFO ht;
  1289. switch(pnmhdr->hdr.code) {
  1290. case TVN_GETDISPINFOA: // Tree view wants to draw an item.
  1291. case TVN_GETDISPINFOW:
  1292. pdi = (TV_DISPINFO*)pnmhdr;
  1293. pNode = (CTreeNode *)pdi->item.lParam; // This is a pointer into the binary TOC it is a CTreeNode of some type
  1294. if (! pNode )
  1295. break;
  1296. tvItem.mask = 0;
  1297. if( pdi->item.mask & TVIF_CHILDREN )
  1298. {
  1299. tvItem.cChildren = (pNode->HasChildren())?1:0;
  1300. tvItem.mask |= TVIF_CHILDREN;
  1301. }
  1302. if (pdi->item.mask & TVIF_TEXT)
  1303. {
  1304. if ( pnmhdr->hdr.code == TVN_GETDISPINFOW )
  1305. {
  1306. if ( !SUCCEEDED(pNode->GetTopicName((WCHAR*)pdi->item.pszText, pdi->item.cchTextMax)) )
  1307. _wcsncpy((WCHAR*)pdi->item.pszText, GetStringResourceW(IDS_UNTITLED), pdi->item.cchTextMax);
  1308. }
  1309. else
  1310. {
  1311. if ( !SUCCEEDED(pNode->GetTopicName(pdi->item.pszText, pdi->item.cchTextMax)) )
  1312. lstrcpy(pdi->item.pszText, GetStringResource(IDS_UNTITLED));
  1313. }
  1314. }
  1315. break;
  1316. case TVN_DELETEITEMA:
  1317. case TVN_DELETEITEMW:
  1318. break;
  1319. case NM_RETURN:
  1320. case NM_DBLCLK:
  1321. ASSERT(::IsValidWindow(m_hwndTree)) ;
  1322. tvItem.hItem = W_TreeView_GetSelection(m_hwndTree);
  1323. if (!tvItem.hItem)
  1324. break; // probably ENTER with no selection
  1325. tvItem.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ; // Get the pointer into the Binary TOC stored in the Tree View
  1326. W_TreeView_GetItem(m_hwndTree, &tvItem);
  1327. pNode = (CTreeNode *)tvItem.lParam;
  1328. if (pNode && pNode->GetURL(szTempURL, sizeof(szTempURL)) )
  1329. {
  1330. m_fSuspendSync = TRUE;
  1331. if ( m_phhctrl )
  1332. {
  1333. m_phhctrl->SendEvent( szTempURL );
  1334. return NULL;
  1335. }
  1336. UpdateTOCSlot(pNode);
  1337. ChangeHtmlTopic(szTempURL, m_hwndTree);
  1338. if (m_phh)
  1339. {
  1340. m_phh->m_hwndControl = m_hwndTree;
  1341. }
  1342. }
  1343. // The treeview does not automatically expand the node with the enter key.
  1344. // so we do it here.
  1345. if ( !g_fIE3 && pnmhdr->hdr.code == NM_RETURN && pNode->HasChildren() )
  1346. {
  1347. if ( tvItem.state & TVIS_EXPANDED )
  1348. {
  1349. if (HandleExpanding(&tvItem, m_hwndTree,TVE_COLLAPSE , &m_fSuspendSync))
  1350. W_TreeView_Expand( m_hwndTree, tvItem.hItem, TVE_COLLAPSE );
  1351. }
  1352. else
  1353. {
  1354. if (HandleExpanding(&tvItem, m_hwndTree,TVE_EXPAND , &m_fSuspendSync))
  1355. W_TreeView_Expand( m_hwndTree, tvItem.hItem, TVE_EXPAND );
  1356. }
  1357. }
  1358. break;
  1359. case TVN_SELCHANGING:
  1360. m_hitemCurHighlight = pnmhdr->itemNew.hItem;
  1361. break;
  1362. case TVN_SELCHANGED:
  1363. m_hitemCurHighlight = pnmhdr->itemNew.hItem;
  1364. break;
  1365. case NM_CLICK:
  1366. /*
  1367. * We want a single click to open a topic. We already process
  1368. * the case where the selection changes, and we jump if it does.
  1369. * However, the user may click an existing selection, in which
  1370. * case we want to jump (because the jump may have failed when
  1371. * the item was first selected. However, we need to post the
  1372. * message so that the treeview control will finish processing
  1373. * the click (which could result in a selection change.
  1374. */
  1375. if (!m_fSuppressJump)
  1376. {
  1377. TV_HITTESTINFO ht;
  1378. GetCursorPos(&ht.pt);
  1379. ASSERT(::IsValidWindow(m_hwndTree)) ;
  1380. ScreenToClient(m_hwndTree, &ht.pt);
  1381. W_TreeView_HitTest(m_hwndTree, &ht);
  1382. if (ht.flags & TVHT_ONITEMBUTTON)
  1383. break; // just clicking the button, so ignore
  1384. tvItem.hItem = ht.hItem;
  1385. if (!tvItem.hItem)
  1386. break; // probably ENTER with no selection
  1387. tvItem.mask = TVIF_PARAM; // Get the pointer into the Binary TOC stored in the Tree View
  1388. W_TreeView_GetItem(m_hwndTree, &tvItem);
  1389. pNode = (CTreeNode *)tvItem.lParam;
  1390. if (pNode && pNode->GetURL(szTempURL, sizeof(szTempURL)) )
  1391. {
  1392. m_fSuspendSync = TRUE;
  1393. if ( m_phhctrl )
  1394. {
  1395. m_phhctrl->SendEvent( szTempURL );
  1396. return NULL;
  1397. }
  1398. UpdateTOCSlot(pNode);
  1399. ChangeHtmlTopic(szTempURL, GetParent(m_hwndTree));
  1400. if (m_phh)
  1401. {
  1402. m_phh->m_hwndControl = m_hwndTree;
  1403. }
  1404. }
  1405. #if 0
  1406. W_TreeView_Select(m_hwndTree, ht.hItem, TVGN_CARET);
  1407. tvItem.mask = TVIF_PARAM; // Get the pointer into the binary TOC stored in the Tree View.
  1408. W_TreeView_GetItem(m_hwndTree, &tvItem);
  1409. // pSiteMapEntry = m_sitemap.GetSiteMapEntry(tvItem.lParam);
  1410. PostMessage(FindMessageParent(m_hwndTree), WM_COMMAND, ID_TV_SINGLE_CLICK,
  1411. (LPARAM) W_TreeView_GetSelection(m_hwndTree));
  1412. #endif
  1413. }
  1414. break;
  1415. case TVN_ITEMEXPANDINGA:
  1416. case TVN_ITEMEXPANDINGW:
  1417. {
  1418. ASSERT(::IsValidWindow(m_hwndTree)) ;
  1419. SendMessage(m_hwndTree, WM_SETREDRAW, FALSE, 0);
  1420. TV_ITEMW * pitem = (TV_ITEMW *)&pnmhdr->itemNew;
  1421. HandleExpanding(pitem, m_hwndTree, pnmhdr->action, &m_fSuspendSync);
  1422. }
  1423. break;
  1424. case TVN_ITEMEXPANDEDA:
  1425. case TVN_ITEMEXPANDEDW:
  1426. {
  1427. SendMessage(m_hwndTree, WM_SETREDRAW, TRUE, 0);
  1428. }
  1429. break;
  1430. case TVN_KEYDOWN:
  1431. TV_KEYDOWN* ptvkd;
  1432. ptvkd = (TV_KEYDOWN*)pnmhdr;
  1433. if ( ptvkd->wVKey != VK_F10 )
  1434. break;
  1435. else if ( GetKeyState(VK_SHIFT) >= 0 )
  1436. break;
  1437. else
  1438. {
  1439. ht.pt.x = ht.pt.y = 0;
  1440. ClientToScreen(m_hwndTree, &ht.pt);
  1441. goto sim_rclick;
  1442. }
  1443. break;
  1444. case NM_RCLICK:
  1445. {
  1446. GetCursorPos(&ht.pt);
  1447. ScreenToClient(m_hwndTree, &ht.pt);
  1448. W_TreeView_HitTest(m_hwndTree, &ht);
  1449. if ( ht.hItem )
  1450. W_TreeView_Select(m_hwndTree, ht.hItem, TVGN_CARET);
  1451. ClientToScreen(m_hwndTree, &ht.pt);
  1452. sim_rclick:
  1453. HMENU hmenu = CreatePopupMenu();
  1454. if (!hmenu)
  1455. break;
  1456. if (!(m_dwStyles & TVS_SINGLEEXPAND)) {
  1457. if (m_phh->m_phmData->m_pTitleCollection->IsSingleTitle()) // no expand all for collections
  1458. HxAppendMenu(hmenu, MF_STRING, ID_EXPAND_ALL, GetStringResource(IDS_EXPAND_ALL));
  1459. HxAppendMenu(hmenu, MF_STRING, ID_CONTRACT_ALL, GetStringResource(IDS_CONTRACT_ALL));
  1460. }
  1461. if (m_phh->m_pCIExpContainer)
  1462. HxAppendMenu(hmenu, MF_STRING, ID_PRINT, GetStringResource(IDS_PRINT));
  1463. ASSERT( m_pInfoType );
  1464. // populate the InfoType member object of the CToc
  1465. if ( !m_pInfoType )
  1466. {
  1467. if (m_phh && m_phh->m_phmData && m_phh->m_phmData->m_pdInfoTypes )
  1468. { // load from the global IT store
  1469. m_pInfoType = new CInfoType;
  1470. m_pInfoType->CopyTo( m_phh->m_phmData );
  1471. // if there are info type bits set by the API assign them here
  1472. if ( m_phh->m_phmData->m_pAPIInfoTypes &&
  1473. m_pInfoType->AnyInfoTypes(m_phh->m_phmData->m_pAPIInfoTypes))
  1474. {
  1475. memcpy(m_pInfoType->m_pInfoTypes,
  1476. m_phh->m_phmData->m_pAPIInfoTypes,
  1477. m_pInfoType->InfoTypeSize() );
  1478. }
  1479. }else
  1480. {
  1481. // no global IT's; load from the .hhc IT store
  1482. m_pInfoType = new CInfoType;
  1483. *m_pInfoType = m_sitemap;
  1484. }
  1485. }
  1486. else
  1487. {
  1488. // Set the infotypes bits to set all the types
  1489. }
  1490. #if 0 // not in 1.1b
  1491. // If there are infotypes add the "customize" option to the popup menu
  1492. if (m_pInfoType && m_pInfoType->HowManyInfoTypes() && m_pInfoType->GetFirstHidden() != 1)
  1493. HxAppendMenu(hmenu, MF_STRING, ID_CUSTOMIZE_INFO_TYPES, GetStringResource(IDS_CUSTOMIZE_INFO_TYPES));
  1494. #endif
  1495. ASSERT(::IsValidWindow(m_hwndTree)) ;
  1496. if (NoRun() == FALSE)
  1497. {
  1498. AppendMenu(hmenu, MF_SEPARATOR, 0, 0);
  1499. HxAppendMenu(hmenu, MF_STRING, ID_JUMP_URL, GetStringResource(IDS_JUMP_URL));
  1500. }
  1501. // AppendMenu(hmenu, MF_STRING, ID_VIEW_ENTRY, pGetDllStringResource(IDS_VIEW_ENTRY));
  1502. #ifdef _DEBUG
  1503. HxAppendMenu(hmenu, MF_STRING, ID_VIEW_MEMORY, "Debug: memory usage...");
  1504. #endif
  1505. TrackPopupMenu(hmenu,
  1506. TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
  1507. ht.pt.x, ht.pt.y, 0, FindMessageParent(m_hwndTree), NULL);
  1508. DestroyMenu(hmenu);
  1509. return TRUE;
  1510. }
  1511. break;
  1512. case NM_CUSTOMDRAW:
  1513. return OnCustomDraw((LPNMTVCUSTOMDRAW) pnmhdr);
  1514. }
  1515. return FALSE;
  1516. }
  1517. void CToc::UpdateTOCSlot(CTreeNode* pNode)
  1518. {
  1519. DWORD dwSlot = 0;
  1520. CTreeNode* pTmpNode, *pTmpNode2;
  1521. CExTitle* pTitle;
  1522. //
  1523. // What a damn hack I've had to put in below. Somehow I had to get a slot number for these nodes in order to get
  1524. // topic centricity working 100% correctly. Should we ever decide to to the binary TOC UI code right we really
  1525. // should only store slots in the tree control and we could do away with all the silly new and deletes on tree
  1526. // nodes. oh well...
  1527. //
  1528. if (m_phh && m_phh->m_phmData && m_phh->m_phmData->m_pTitleCollection )
  1529. {
  1530. if ( (pTmpNode = m_phh->m_phmData->m_pTitleCollection->GetPrev(pNode)) )
  1531. {
  1532. if ( (pTmpNode2 = m_phh->m_phmData->m_pTitleCollection->GetNextTopicNode(pTmpNode, &dwSlot)) )
  1533. {
  1534. if ( dwSlot && pTmpNode2->GetObjType() == EXNODE)
  1535. {
  1536. if ( (pTitle = ((CExNode*)pTmpNode2)->GetTitle()) )
  1537. m_phh->m_phmData->m_pTitleCollection->SetTopicSlot(dwSlot,((CExNode*)pTmpNode2)->m_Node.dwOffsTopic, pTitle);
  1538. }
  1539. delete pTmpNode2;
  1540. }
  1541. delete pTmpNode;
  1542. }
  1543. }
  1544. }
  1545. // Public class member called to refresh the TOC view.
  1546. //
  1547. void CToc::Refresh(void)
  1548. {
  1549. HTREEITEM hNode;
  1550. TVITEMW Tvi;
  1551. if (! m_hwndTree )
  1552. return;
  1553. if ( m_fBinaryTOC )
  1554. {
  1555. //
  1556. // First, free all the CTreeNodes...
  1557. //
  1558. hNode = W_TreeView_GetRoot(m_hwndTree);
  1559. while ( hNode )
  1560. {
  1561. FreeChildrenAllocations(m_hwndTree, hNode);
  1562. hNode = W_TreeView_GetNextSibling(m_hwndTree, hNode);
  1563. }
  1564. Tvi.hItem = hNode;
  1565. Tvi.mask = TVIF_PARAM;
  1566. if ( W_TreeView_GetItem(m_hwndTree, &Tvi) )
  1567. {
  1568. if ( Tvi.lParam )
  1569. delete ((CTreeNode *)Tvi.lParam);
  1570. }
  1571. //
  1572. // Second, delete the items (visual elements) from the CTreeControl
  1573. //
  1574. W_TreeView_DeleteAllItems(m_hwndTree);
  1575. //
  1576. // Lastly, reload the root.
  1577. //
  1578. LoadFirstLevel(m_pBinTOCRoot, m_hwndTree, &m_tiFirstVisible);
  1579. }
  1580. else
  1581. {
  1582. HWND hwndParent = GetParent(m_hwndTree);
  1583. DestroyWindow(m_hwndTree);
  1584. // Destroying the TreeView control, make sure we no longer point to it as a valid
  1585. // subclassed window.
  1586. if (NULL != lpfnlTreeViewWndProc)
  1587. {
  1588. lpfnlTreeViewWndProc = NULL;
  1589. }
  1590. Create(hwndParent);
  1591. InitTreeView();
  1592. }
  1593. }
  1594. // Helper function for adding the first level to a tree view.
  1595. void LoadFirstLevel( CTreeNode *pRoot, HWND hwndTreeView, HTREEITEM *m_tiFirstVisible )
  1596. {
  1597. CTreeNode *pTempNode = pRoot->GetFirstChild();
  1598. ASSERT(::IsValidWindow(hwndTreeView)) ;
  1599. CHourGlass wait;
  1600. while (pTempNode != NULL )
  1601. {
  1602. *m_tiFirstVisible = AddNode(pTempNode, TVI_ROOT, hwndTreeView);
  1603. pTempNode = pTempNode->GetNextSibling();
  1604. }
  1605. }
  1606. // Helper functions for adding all the children to a parent node in a tree view.
  1607. //
  1608. HTREEITEM AddTitleChildren(CTreeNode *pNode, HTREEITEM hParent, HWND hwndTreeView)
  1609. {
  1610. CTreeNode *pTempNode;
  1611. HTREEITEM hItem = NULL;
  1612. CHourGlass wait;
  1613. pTempNode = pNode->GetFirstChild();
  1614. while (pTempNode != NULL )
  1615. {
  1616. hItem = AddNode(pTempNode, hParent, hwndTreeView);
  1617. pTempNode = pTempNode->GetNextSibling();
  1618. }
  1619. return hItem;
  1620. }
  1621. HTREEITEM AddNode(CTreeNode *pNode, HTREEITEM hParent, HWND hwndTreeView)
  1622. {
  1623. if (pNode->GetObjType() == EXTITLENODE)
  1624. {
  1625. return AddTitleChildren(pNode, hParent, hwndTreeView);
  1626. }
  1627. TV_INSERTSTRUCTW tcAdd;
  1628. unsigned uType;
  1629. tcAdd.hInsertAfter = TVI_LAST;
  1630. tcAdd.hParent = hParent;
  1631. uType = pNode->GetType();
  1632. if ( uType == TOPIC )
  1633. if (pNode->IsNew())
  1634. tcAdd.item.iImage = tcAdd.item.iSelectedImage = 11;
  1635. else
  1636. tcAdd.item.iImage = tcAdd.item.iSelectedImage = 10;
  1637. else if ( uType == CONTAINER )
  1638. if (pNode->IsNew())
  1639. tcAdd.item.iImage = tcAdd.item.iSelectedImage = 2;
  1640. else
  1641. tcAdd.item.iImage = tcAdd.item.iSelectedImage = 0;
  1642. else
  1643. if (pNode->IsNew())
  1644. tcAdd.item.iImage = tcAdd.item.iSelectedImage = 2;
  1645. else
  1646. tcAdd.item.iImage = tcAdd.item.iSelectedImage = 0;
  1647. tcAdd.item.hItem = NULL;
  1648. tcAdd.item.lParam = (LONG_PTR)pNode;
  1649. tcAdd.item.cChildren = (pNode->HasChildren())?1:0;
  1650. tcAdd.item.pszText = LPSTR_TEXTCALLBACKW;
  1651. tcAdd.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM;
  1652. return W_TreeView_InsertItem(hwndTreeView, &tcAdd);
  1653. }
  1654. void AddChildren( TVITEMW* pTvi, HWND hwndTreeView )
  1655. {
  1656. CTreeNode *pNode;
  1657. CTreeNode *pTempNode;
  1658. TV_ITEM tvItem;
  1659. HTREEITEM hItem;
  1660. ASSERT(::IsValidWindow(hwndTreeView)) ;
  1661. if (! (pNode = (CTreeNode*)pTvi->lParam) )
  1662. return;
  1663. tvItem.hItem = pTvi->hItem;
  1664. if (!tvItem.hItem)
  1665. return;
  1666. CHourGlass wait;
  1667. pTempNode = pNode->GetFirstChild();
  1668. // Before we add. Delete the dummy kid.
  1669. //
  1670. if ( (hItem = W_TreeView_GetChild(hwndTreeView, pTvi->hItem)) )
  1671. W_TreeView_DeleteItem(hwndTreeView, hItem);
  1672. while (pTempNode != NULL )
  1673. {
  1674. AddNode(pTempNode, pTvi->hItem, hwndTreeView);
  1675. pTempNode = pTempNode->GetNextSibling();
  1676. }
  1677. }
  1678. void FreeChildrenAllocations(HWND hwndTreeView, HTREEITEM ti)
  1679. {
  1680. HTREEITEM tiChild;
  1681. CTreeNode *pCurNode;
  1682. TV_ITEMW hCur;
  1683. if ( IsValidWindow(hwndTreeView) )
  1684. {
  1685. while ((tiChild = W_TreeView_GetChild(hwndTreeView, ti)) != NULL)
  1686. {
  1687. ZeroMemory(&hCur, sizeof(TV_ITEM));
  1688. hCur.hItem = tiChild;
  1689. hCur.mask = TVIF_PARAM;
  1690. if (W_TreeView_GetItem(hwndTreeView, &hCur) == FALSE)
  1691. continue;
  1692. FreeChildrenAllocations(hwndTreeView, tiChild);
  1693. if ((hCur.mask & TVIF_PARAM) &&hCur.lParam)
  1694. {
  1695. pCurNode = (CTreeNode *)hCur.lParam;
  1696. delete pCurNode;
  1697. }
  1698. W_TreeView_DeleteItem(hwndTreeView, tiChild);
  1699. }
  1700. }
  1701. }
  1702. void DeleteChildren( TVITEMW* pTvi, HWND hwndTreeView )
  1703. {
  1704. TV_INSERTSTRUCTW tcAdd;
  1705. CHourGlass wait;
  1706. ASSERT(::IsValidWindow(hwndTreeView)) ;
  1707. FreeChildrenAllocations(hwndTreeView, pTvi->hItem);
  1708. //
  1709. // After we've deleted, add the dummk kid back.
  1710. //
  1711. ZeroMemory(&tcAdd, sizeof(TV_INSERTSTRUCT));
  1712. tcAdd.hInsertAfter = TVI_LAST;
  1713. tcAdd.hParent = pTvi->hItem;
  1714. W_TreeView_InsertItem(hwndTreeView, &tcAdd);
  1715. }
  1716. // This is the Contents Command Handler for the Binary TOC
  1717. LRESULT CToc::OnBinTOCContentsCommand(UINT id, UINT uNotifyCode, LPARAM lParam )
  1718. {
  1719. ASSERT(::IsValidWindow(m_hwndTree)) ;
  1720. switch (id)
  1721. {
  1722. case ID_EXPAND_ALL:
  1723. {
  1724. m_hitemCurHighlight = W_TreeView_GetSelection(m_hwndTree);
  1725. CTreeNode* pNode;
  1726. TV_ITEMW tvItem;
  1727. HTREEITEM hNext;
  1728. DWORD dwCurLevel = 0;
  1729. HTREEITEM hParents[50];
  1730. tvItem.hItem = W_TreeView_GetRoot(m_hwndTree);
  1731. CHourGlass wait;
  1732. while ( tvItem.hItem)
  1733. {
  1734. tvItem.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ; // Get the pointer into the Binary TOC stored in the Tree View
  1735. W_TreeView_GetItem(m_hwndTree, &tvItem);
  1736. pNode = (CTreeNode *)tvItem.lParam;
  1737. if (pNode->HasChildren() == FALSE)
  1738. goto GetNext;
  1739. if (pNode->m_Expanded == TRUE)
  1740. goto GetNext;
  1741. pNode->m_Expanded = TRUE;
  1742. AddChildren(&tvItem, m_hwndTree); // Add the items below the expanding parent
  1743. W_TreeView_Expand( m_hwndTree, tvItem.hItem, TVE_EXPAND );
  1744. // Set the correct image for the expanding/contracting node
  1745. tvItem.iImage++;
  1746. tvItem.iSelectedImage++;
  1747. tvItem.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1748. W_TreeView_SetItem(m_hwndTree, &tvItem);
  1749. GetNext:
  1750. if (hNext = W_TreeView_GetChild(m_hwndTree, tvItem.hItem))
  1751. {
  1752. hParents[dwCurLevel] = tvItem.hItem;
  1753. tvItem.hItem = hNext;
  1754. dwCurLevel++;
  1755. }
  1756. else if (hNext = W_TreeView_GetNextSibling(m_hwndTree, tvItem.hItem))
  1757. tvItem.hItem = hNext;
  1758. else
  1759. {
  1760. // go up the parent tree
  1761. while (TRUE)
  1762. {
  1763. dwCurLevel--;
  1764. if (dwCurLevel == -1)
  1765. {
  1766. tvItem.hItem = NULL;
  1767. break;
  1768. }
  1769. else
  1770. {
  1771. if (hNext = W_TreeView_GetNextSibling(m_hwndTree, hParents[dwCurLevel]))
  1772. {
  1773. tvItem.hItem = hNext;
  1774. break;
  1775. }
  1776. }
  1777. }
  1778. }
  1779. }
  1780. if (m_hitemCurHighlight)
  1781. {
  1782. m_fSuppressJump = TRUE;
  1783. W_TreeView_Select(m_hwndTree, m_hitemCurHighlight,
  1784. TVGN_FIRSTVISIBLE);
  1785. W_TreeView_SelectItem(m_hwndTree, m_hitemCurHighlight);
  1786. m_fSuppressJump = FALSE;
  1787. }
  1788. }
  1789. return 0;
  1790. case ID_CONTRACT_ALL:
  1791. {
  1792. CHourGlass wait;
  1793. SendMessage(m_hwndTree, WM_SETREDRAW, FALSE, 0);
  1794. CTreeNode* pNode;
  1795. TV_ITEMW tvItem;
  1796. HTREEITEM hNext;
  1797. tvItem.hItem = m_hitemCurHighlight = W_TreeView_GetRoot(m_hwndTree);
  1798. while ( tvItem.hItem)
  1799. {
  1800. tvItem.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN ; // Get the pointer into the Binary TOC stored in the Tree View
  1801. W_TreeView_GetItem(m_hwndTree, &tvItem);
  1802. pNode = (CTreeNode *)tvItem.lParam;
  1803. if (pNode->HasChildren() == FALSE)
  1804. goto GetNextSibling;
  1805. if (pNode->m_Expanded == FALSE)
  1806. goto GetNextSibling;
  1807. pNode->m_Expanded = FALSE;
  1808. DeleteChildren(&tvItem, m_hwndTree);
  1809. W_TreeView_Expand( m_hwndTree, tvItem.hItem, TVE_COLLAPSE );
  1810. // Set the correct image for the expanding/contracting node
  1811. tvItem.iImage--;
  1812. tvItem.iSelectedImage--;
  1813. tvItem.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1814. W_TreeView_SetItem(m_hwndTree, &tvItem);
  1815. GetNextSibling:
  1816. if (hNext = W_TreeView_GetNextSibling(m_hwndTree, tvItem.hItem))
  1817. tvItem.hItem = hNext;
  1818. else
  1819. tvItem.hItem = NULL;
  1820. }
  1821. if (m_hitemCurHighlight)
  1822. {
  1823. m_fSuppressJump = TRUE;
  1824. W_TreeView_Select(m_hwndTree, m_hitemCurHighlight,
  1825. TVGN_FIRSTVISIBLE);
  1826. W_TreeView_SelectItem(m_hwndTree, m_hitemCurHighlight);
  1827. m_fSuppressJump = FALSE;
  1828. }
  1829. m_fHack = FALSE; // process expansion/contraction normally
  1830. }
  1831. SendMessage(m_hwndTree, WM_SETREDRAW, TRUE, 0);
  1832. return 0;
  1833. #if 1
  1834. case ID_CUSTOMIZE_INFO_TYPES:
  1835. {
  1836. if (m_phh->m_phmData->m_pTitleCollection->m_pSubSets->GetTocSubset())
  1837. m_phh->m_phmData->m_pTitleCollection->m_pSubSets->m_cur_Set = m_phh->m_phmData->m_pTitleCollection->m_pSubSets->GetTocSubset(); // set this so the wizard knows which subset to load the combo box with.
  1838. #if 0
  1839. if (ChooseInformationTypes(m_pInfoType, &(this->m_sitemap), m_hwndTree, m_phhctrl, m_phh)) {
  1840. #else
  1841. if (ChooseInformationTypes(m_pInfoType, &(this->m_sitemap), m_hwndTree, m_phhctrl)) {
  1842. #endif
  1843. if (m_phh)
  1844. m_phh->UpdateInformationTypes();
  1845. else {
  1846. HWND hwndParent = GetParent(m_hwndTree);
  1847. DestroyWindow(m_hwndTree);
  1848. // Destroying the TreeView control, make sure we no longer point to it as a valid
  1849. // subclassed window.
  1850. if (NULL != lpfnlTreeViewWndProc)
  1851. {
  1852. lpfnlTreeViewWndProc = NULL;
  1853. }
  1854. Create(hwndParent);
  1855. InitTreeView();
  1856. }
  1857. }
  1858. }
  1859. break;
  1860. #endif
  1861. #ifndef CHIINDEX
  1862. case ID_PRINT:
  1863. {
  1864. TV_ITEM tvi;
  1865. tvi.hItem = W_TreeView_GetSelection(m_hwndTree);
  1866. if (!tvi.hItem)
  1867. return 0; // no current selection
  1868. if (m_phh) {
  1869. if (m_phh->OnTrackNotifyCaller(HHACT_PRINT))
  1870. break;
  1871. m_phh->OnPrint();
  1872. break;
  1873. }
  1874. CPrint prt(GetParent(m_hwndTree));
  1875. prt.SetAction(PRINT_CUR_HEADING);
  1876. if (!prt.DoModal())
  1877. break;
  1878. int action = prt.GetAction();
  1879. ASSERT(m_phhctrl);
  1880. PrintTopics(action, this,
  1881. m_phhctrl->m_pWebBrowserApp, m_phhctrl->m_hwndHelp);
  1882. }
  1883. return 0;
  1884. #endif
  1885. #if 0
  1886. case ID_VIEW_ENTRY:
  1887. {
  1888. TV_ITEM tvi;
  1889. tvi.hItem = W_TreeView_GetSelection(m_hwndTree);
  1890. if (!tvi.hItem)
  1891. return 0; // no current selection
  1892. tvi.mask = TVIF_PARAM;
  1893. W_TreeView_GetItem(m_hwndTree, &tvi);
  1894. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(tvi.lParam);
  1895. DisplayAuthorInfo(&(this->m_sitemap), pSiteMapEntry, FindMessageParent(m_hwndTree), m_phhctrl);
  1896. }
  1897. return 0;
  1898. #endif
  1899. case ID_JUMP_URL:
  1900. {
  1901. char szDstUrl[INTERNET_MAX_URL_LENGTH];
  1902. CStr cszCurUrl;
  1903. if (m_phhctrl)
  1904. m_phhctrl->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  1905. else
  1906. m_phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszCurUrl);
  1907. if (doJumpUrl(GetParent(m_hwndTree), cszCurUrl, szDstUrl)) {
  1908. if (m_phhctrl) {
  1909. CWStr cwJump(szDstUrl);
  1910. HlinkSimpleNavigateToString(cwJump, NULL,
  1911. NULL, m_phhctrl->GetIUnknown(), NULL, NULL, 0, NULL);
  1912. }
  1913. else {
  1914. ChangeHtmlTopic(szDstUrl, GetParent(m_hwndTree));
  1915. }
  1916. }
  1917. }
  1918. break;
  1919. #ifdef _DEBUG
  1920. case ID_VIEW_MEMORY:
  1921. OnReportMemoryUsage();
  1922. return 0;
  1923. #endif
  1924. #if 0
  1925. case ID_TV_SINGLE_CLICK:
  1926. {
  1927. TV_ITEM tvi;
  1928. tvi.mask = TVIF_PARAM;
  1929. tvi.hItem = m_hitemCurHighlight;
  1930. W_TreeView_GetItem(m_hwndTree, &tvi);
  1931. SITEMAP_ENTRY* pSiteMapEntry = m_sitemap.GetSiteMapEntry(tvi.lParam);
  1932. // if (pSiteMapEntry->fShortCut) {
  1933. if (pSiteMapEntry->pUrls) {
  1934. m_fIgnoreNextSelChange = TRUE;
  1935. m_fSuspendSync = TRUE;
  1936. if (pSiteMapEntry->fSendEvent && m_phhctrl)
  1937. m_phhctrl->SendEvent(m_sitemap.GetUrlString(pSiteMapEntry->pUrls->urlPrimary));
  1938. else {
  1939. SaveCurUrl(); // so we can restore our state
  1940. JumpToUrl(m_pOuter, m_hwndTree, pSiteMapEntry, &(this->m_sitemap), NULL);
  1941. }
  1942. if (m_phh)
  1943. {
  1944. m_phh->m_hwndControl = m_hwndTree;
  1945. }
  1946. }
  1947. }
  1948. break;
  1949. #endif
  1950. }
  1951. return 0;
  1952. }
  1953. ///////////////////////////////////////////////////////////
  1954. //
  1955. // INavUI Interface Implementation
  1956. //
  1957. ///////////////////////////////////////////////////////////
  1958. //
  1959. // OnNotify
  1960. //
  1961. LRESULT
  1962. CToc::OnNotify(HWND /*hwnd*/, WPARAM /*wParam*/, LPARAM lParam)
  1963. {
  1964. if (::IsValidWindow(m_hwndTree))
  1965. {
  1966. #ifdef _DEBUG
  1967. BOOL f = TreeView_GetUnicodeFormat(m_hwndTree);
  1968. #endif
  1969. TreeViewMsg((NM_TREEVIEW*) lParam);
  1970. }
  1971. return 1;
  1972. }
  1973. ///////////////////////////////////////////////////////////
  1974. //
  1975. // SetDefaultFocus
  1976. //
  1977. void
  1978. CToc::SetDefaultFocus()
  1979. {
  1980. if (::IsValidWindow(m_hwndTree))
  1981. {
  1982. if (m_fSyncOnActivation) // Move this to the new activation function.
  1983. {
  1984. //PostMessage(GetParent(GetParent(m_hwndTree)), WM_COMMAND, IDTB_SYNC, 0); // Verify: This was a post message.
  1985. // HH Bug 2160: Sending the IDTB_SYNC message causes the TOC tab to get selected.
  1986. // We don't want to select the TOC tab, but mark this thing as needing to be sync'ed.
  1987. if (m_phh && m_phh->m_pCIExpContainer && m_phh->m_pCIExpContainer->m_pWebBrowserApp)
  1988. {
  1989. CStr cszUrl;
  1990. m_phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
  1991. if (!cszUrl.IsEmpty())
  1992. {
  1993. m_fSyncOnActivation = FALSE;
  1994. Synchronize(cszUrl);
  1995. }
  1996. }
  1997. }
  1998. SetFocus(m_hwndTree );
  1999. }
  2000. }
  2001. ///////////////////////////////////////////////////////////
  2002. //
  2003. // Other Classes
  2004. //
  2005. ///////////////////////////////////////////////////////////
  2006. //
  2007. // CJumpUrl
  2008. //
  2009. class CJumpUrl : public CDlg
  2010. {
  2011. public:
  2012. CJumpUrl(HWND hwndParent, PCSTR pszCurUrl) : CDlg(hwndParent, IDDLG_JUMP_URL) {
  2013. m_pszCurUrl = pszCurUrl;
  2014. }
  2015. BOOL OnBeginOrEnd();
  2016. void OnEditChange(UINT id);
  2017. PCSTR m_pszCurUrl;
  2018. CStr m_cszJumpUrl;
  2019. };
  2020. BOOL doJumpUrl(HWND hwndParent, PCSTR pszCurUrl, PSTR pszDstUrl)
  2021. {
  2022. CJumpUrl jump(hwndParent, pszCurUrl);
  2023. if (jump.DoModal()) {
  2024. strcpy(pszDstUrl, jump.m_cszJumpUrl);
  2025. return TRUE;
  2026. }
  2027. else
  2028. return FALSE;
  2029. }
  2030. void CJumpUrl::OnEditChange(UINT id)
  2031. {
  2032. if (id == IDEDIT_JUMP_URL)
  2033. {
  2034. m_cszJumpUrl.GetText(*this, IDEDIT_JUMP_URL);
  2035. if (m_cszJumpUrl.psz[0])
  2036. {
  2037. EnableWindow(IDOK, TRUE);
  2038. }
  2039. else
  2040. {
  2041. EnableWindow(IDOK, FALSE);
  2042. }
  2043. }
  2044. }
  2045. BOOL CJumpUrl::OnBeginOrEnd()
  2046. {
  2047. if (m_fInitializing) {
  2048. SetWindowText(IDEDIT_CUR_URL, m_pszCurUrl);
  2049. SendMessage(IDEDIT_JUMP_URL, WM_SETFONT, (WPARAM)_Resource.GetUIFont(), 0);
  2050. EnableWindow(IDOK, FALSE);
  2051. }
  2052. else {
  2053. m_cszJumpUrl.GetText(*this, IDEDIT_JUMP_URL);
  2054. if (!StrChr(m_cszJumpUrl, CH_COLON) && m_pszCurUrl && strstr(m_pszCurUrl, "::")) {
  2055. CStr csz(m_pszCurUrl);
  2056. PSTR psz = strstr(csz, "::");
  2057. ASSERT(psz);
  2058. psz += 2;
  2059. *psz = '\0';
  2060. if (m_cszJumpUrl.psz[0] != CH_FORWARDSLASH && m_cszJumpUrl.psz[0] != CH_BACKSLASH)
  2061. csz += "/";
  2062. csz += m_cszJumpUrl.psz;
  2063. m_cszJumpUrl = csz.psz;
  2064. }
  2065. }
  2066. return TRUE;
  2067. }