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.

3002 lines
89 KiB

  1. // Copyright (C) Microsoft Corporation 1996-1997, All Rights reserved.
  2. // Precompiled header
  3. #include "header.h"
  4. #include "state.h"
  5. #include "cctlww.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static const char THIS_FILE[] = __FILE__;
  9. #endif
  10. ///////////////////////////////////////////////////////////
  11. //
  12. // Includes
  13. //
  14. #include "secwin.h" // Header for this file.
  15. #include "hha_strtable.h"
  16. #include "contain.h"
  17. #include "highlite.h"
  18. #include "resource.h" // needed for subset picker combo control ID.
  19. #include "subset.h" // Needed to dealing with CStructucturalSubset object.
  20. // Advanced Search UI header.
  21. #include "adsearch.h"
  22. #include "search.h"
  23. // Bookmarks Nav Pane
  24. #include "bookmark.h"
  25. // Custom NavPane
  26. #include "custmtab.h"
  27. // Sizebar class
  28. #include "sizebar.h"
  29. #define ACCESS_KEY '&'
  30. static const char txtAccessKey[] = "&";
  31. BOOL HxInsertMenuItem(HMENU, UINT, BOOL, MENUITEMINFOA *);
  32. ///////////////////////////////////////////////////////////
  33. //
  34. // Globals
  35. //
  36. // Pointer to global array of window types.
  37. CHHWinType** pahwnd = NULL;
  38. AUTO_CLASS_COUNT_CHECK( CHHWinType );
  39. ///////////////////////////////////////////////////////////
  40. //
  41. // Function Implementation
  42. //
  43. /***************************************************************************
  44. FUNCTION: GetCurrentCollection
  45. PURPOSE: Returns the currect collection
  46. PARAMETERS:
  47. None.
  48. RETURNS: Pointer to the currect collection (CExCollection)
  49. COMMENTS:
  50. This function returns the current collection based on the
  51. current active window and window type. Use this function
  52. anytime you need a pointer to the currect active collection
  53. when you can assume that the collection is already loaded.
  54. MODIFICATION DATES:
  55. 15-Sept-1997 [paulti]
  56. 29-April-1998 [mikecole]
  57. As per agreement of all hhctrl devs I am adding a .CHM filespec argument
  58. to this function. Since it is possible for a single task to utilize hhctrl
  59. services on multiple CExCollections we will distinguish CExCollections
  60. from one another by using a .CHM filespec.
  61. ***************************************************************************/
  62. CExCollection* GetCurrentCollection( HWND hwnd, LPCSTR lpszChmFilespec )
  63. {
  64. CExCollection* pCExCol;
  65. PSTR psz;
  66. TCHAR szFN[MAX_PATH];
  67. TCHAR szFN2[MAX_PATH];
  68. int i = 0;
  69. szFN[0] = '\0';
  70. if ( lpszChmFilespec )
  71. {
  72. //
  73. // First, we need to normalize the filespec. This thing can come to us in any number of
  74. // forms, it could be a URL, it could be an unqualified filename, a fully qualified path...
  75. //
  76. if ( psz = stristr(lpszChmFilespec, txtDefExtension) )
  77. {
  78. while ( *psz != ' ' && *psz != '/' && *psz != '\\' && *psz != '@' && *psz != '\0' && *psz != ':' && (psz != lpszChmFilespec) )
  79. {
  80. psz = CharPrev(lpszChmFilespec, psz);
  81. i++;
  82. if(IsDBCSLeadByte(*CharNext(psz)))
  83. i++;
  84. }
  85. if ( psz != lpszChmFilespec )
  86. psz++;
  87. else
  88. i++;
  89. lstrcpyn(szFN, psz, i);
  90. }
  91. //
  92. // Next, see if the filespec matches a single title .CHM or and merged .CHMs of a single title .CHM.
  93. //
  94. if ( szFN[0] )
  95. {
  96. for (int i = 0; i < g_cHmSlots; i++)
  97. {
  98. if ( g_phmData[i] && g_phmData[i]->m_pTitleCollection && g_phmData[i]->m_pTitleCollection->IsSingleTitle() )
  99. {
  100. //
  101. // Search title list for a match.
  102. //
  103. CExTitle* pTitle;
  104. pCExCol = g_phmData[i]->m_pTitleCollection;
  105. pTitle = pCExCol->GetFirstTitle();
  106. while ( pTitle )
  107. {
  108. _splitpath((LPCSTR)pTitle->GetContentFileName(), NULL, NULL, szFN2, NULL);
  109. if (! lstrcmpi(szFN, szFN2) )
  110. return g_phmData[i]->m_pTitleCollection;
  111. pTitle = pTitle->GetNext();
  112. }
  113. }
  114. }
  115. }
  116. }
  117. //
  118. // Last resort...
  119. //
  120. if ( g_pCurrentCollection )
  121. return g_pCurrentCollection;
  122. else if ( g_phmData && g_phmData[0] )
  123. return g_phmData[0]->m_pTitleCollection;
  124. else return NULL; // Ohhh, very bad!
  125. }
  126. /***************************************************************************
  127. FUNCTION: GetCurrentURL
  128. PURPOSE: Returns the currect URL
  129. PARAMETERS:
  130. None.
  131. RETURNS: TRUE if found with pcszCurrentURL filed in, otherwise FALSE.
  132. COMMENTS:
  133. This function returns the current URL based on the
  134. current active window and window type.
  135. MODIFICATION DATES:
  136. 10-Dec-1997 [paulti]
  137. ***************************************************************************/
  138. BOOL GetCurrentURL( CStr* pcszCurrentURL, HWND hwnd )
  139. {
  140. ASSERT(pahwnd);
  141. CHHWinType* phh = NULL;
  142. BOOL bFound = FALSE;
  143. // if anyone can find a guarenteed way to get the current
  144. // URL please modify the code below [paulti]
  145. if( !hwnd )
  146. hwnd = GetActiveWindow();
  147. phh = FindHHWindowIndex(hwnd);
  148. if( phh && phh->m_pCIExpContainer &&
  149. phh->m_pCIExpContainer->m_pWebBrowserApp ) {
  150. phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL( pcszCurrentURL );
  151. bFound = TRUE;
  152. }
  153. return bFound;
  154. }
  155. HFONT CHHWinType::GetContentFont()
  156. {
  157. if ( m_phmData )
  158. {
  159. CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
  160. return (pTitle->GetInfo()->GetContentFont());
  161. }
  162. else
  163. return _Resource.GetUIFont(); // This would be highly unusual!
  164. }
  165. HFONT CHHWinType::GetAccessableContentFont()
  166. {
  167. if ( m_phmData )
  168. {
  169. CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
  170. return (pTitle->GetInfo()->GetAccessableContentFont());
  171. }
  172. else
  173. return _Resource.GetUIFont(); // This would be highly unusual!
  174. }
  175. INT CHHWinType::GetContentCharset()
  176. {
  177. if ( m_phmData )
  178. {
  179. CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
  180. return (pTitle->GetInfo()->GetTitleCharset());
  181. }
  182. else
  183. return ANSI_CHARSET; // This would be highly unusual!
  184. }
  185. UINT CHHWinType::GetCodePage(void)
  186. {
  187. if ( m_phmData )
  188. {
  189. CExTitle* pTitle = m_phmData->m_pTitleCollection->GetMasterTitle();
  190. return (pTitle->GetInfo()->GetCodePage());
  191. }
  192. else
  193. return 0; // This would be highly unusual!
  194. }
  195. /***************************************************************************
  196. FUNCTION: CHHWinType::SetString
  197. PURPOSE: Set a window type string
  198. PARAMETERS:
  199. pszSrcString
  200. ppszDst
  201. RETURNS:
  202. COMMENTS:
  203. If string is non-NULL and non-empty, frees any previous string memory
  204. and allocates and copies the string.
  205. MODIFICATION DATES:
  206. 09-Sep-1997 [ralphw]
  207. ***************************************************************************/
  208. void CHHWinType::SetString(PCSTR pszSrcString, PSTR* ppszDst)
  209. {
  210. if (!pszSrcString)
  211. return;
  212. CStr csz ;
  213. if (IsUniCodeStrings())
  214. csz = (WCHAR*) pszSrcString;
  215. else
  216. csz = pszSrcString;
  217. if (csz.IsNonEmpty())
  218. {
  219. if (*ppszDst)
  220. lcFree(*ppszDst);
  221. csz.TransferPointer(ppszDst);
  222. }
  223. }
  224. /***************************************************************************
  225. FUNCTION: CHHWinType::SetUrl
  226. PURPOSE: Set a window type URL
  227. PARAMETERS:
  228. pszSrcString
  229. ppszDst
  230. RETURNS:
  231. COMMENTS:
  232. If string is non-NULL and non-empty, frees any previous string memory
  233. and allocates and copies the string.
  234. If the string contains a compiled HTML filename, then the URL
  235. is converted into a full path.
  236. MODIFICATION DATES:
  237. 09-Sep-1997 [ralphw]
  238. ***************************************************************************/
  239. void CHHWinType::SetUrl(PCSTR pszSrcString, PSTR* ppszDst)
  240. {
  241. if (!pszSrcString)
  242. return;
  243. CStr csz;
  244. if (IsUniCodeStrings())
  245. csz = (WCHAR*) pszSrcString;
  246. else
  247. csz = pszSrcString;
  248. if (csz.IsNonEmpty())
  249. {
  250. if (*ppszDst)
  251. lcFree(*ppszDst);
  252. CStr cszFull;
  253. if (IsCompiledHtmlFile(csz, &cszFull))
  254. cszFull.TransferPointer(ppszDst);
  255. else
  256. csz.TransferPointer(ppszDst);
  257. }
  258. }
  259. void CHHWinType::SetTypeName(HH_WINTYPE* phhWinType)
  260. {
  261. SetString(phhWinType->pszType, (PSTR*) &pszType);
  262. if (pszType && *pszType == '>')
  263. strcpy((PSTR) pszType, pszType + 1);
  264. }
  265. /**********************************************************
  266. FUNCTION SetJump1
  267. NOTES
  268. The button caption pszJump1 can be empty.
  269. The URL cannot.
  270. ***********************************************************/
  271. void CHHWinType::SetJump1(HH_WINTYPE* phhWinType)
  272. {
  273. if (!(fsToolBarFlags & HHWIN_BUTTON_JUMP1) || (phhWinType->pszUrlJump1 == NULL))
  274. return;
  275. SetString(phhWinType->pszJump1, (PSTR*) &pszJump1);
  276. SetUrl(phhWinType->pszUrlJump1, (PSTR*) &pszUrlJump1);
  277. }
  278. /**********************************************************
  279. FUNCTION SetJump2
  280. NOTES
  281. The button caption pszJump1 can be empty.
  282. The URL cannot.
  283. ***********************************************************/
  284. void CHHWinType::SetJump2(HH_WINTYPE* phhWinType)
  285. {
  286. if (!(fsToolBarFlags & HHWIN_BUTTON_JUMP2) || (phhWinType->pszUrlJump2 == NULL))
  287. return;
  288. SetString(phhWinType->pszJump2, (PSTR*) &pszJump2);
  289. SetUrl(phhWinType->pszUrlJump2, (PSTR*) &pszUrlJump2);
  290. }
  291. /**********************************************************
  292. FUNCTION SetTabOrder
  293. NOTES
  294. ***********************************************************/
  295. void CHHWinType::SetTabOrder(HH_WINTYPE* phhWinType)
  296. {
  297. // REVIEW: We need to be able to loop true this array and find tabs.
  298. // This means that we need some way to determine the upper most array entry.
  299. // This is harder in the user defined case...[14 Jan 98]
  300. if (IsValidMember(HHWIN_PARAM_TABORDER))
  301. memcpy(tabOrder, phhWinType->tabOrder, sizeof(tabOrder));
  302. else {
  303. for (int j = HH_TAB_FAVORITES + 1; j < HH_TAB_CUSTOM_FIRST; j++)
  304. tabOrder[j] = -1; // clear empty slots
  305. tabOrder[HH_TAB_CONTENTS] = HH_TAB_CONTENTS;
  306. tabOrder[HH_TAB_INDEX] = HH_TAB_INDEX;
  307. tabOrder[HH_TAB_SEARCH] = HH_TAB_SEARCH;
  308. tabOrder[HH_TAB_HISTORY] = HH_TAB_HISTORY;
  309. tabOrder[HH_TAB_FAVORITES] = HH_TAB_FAVORITES;
  310. #ifdef __TEST_CUSTOMTAB__
  311. tabOrder[HH_TAB_AUTHOR] = HH_TAB_AUTHOR; // hha.dll supplied tab
  312. #endif
  313. // Setup the default tab order for the custom tabs.
  314. for (int i = HH_TAB_CUSTOM_FIRST; i <= HH_TAB_CUSTOM_LAST; i++)
  315. tabOrder[i] = (BYTE)i;
  316. // This member is now valid. Mark it as such.
  317. fsValidMembers |= HHWIN_PARAM_TABORDER ;
  318. }
  319. }
  320. //////////////////////////////////////////////////////////////////////////
  321. //
  322. //
  323. //
  324. DWORD
  325. CHHWinType::GetStyles() const
  326. {
  327. DWORD style = NULL ;
  328. if (IsValidMember(HHWIN_PARAM_STYLES))
  329. {
  330. style = dwStyles ;
  331. }
  332. if (!IsProperty(HHWIN_PROP_NODEF_STYLES))
  333. {
  334. style |= DEFAULT_STYLE ;
  335. }
  336. if (!IsProperty(HHWIN_PROP_NOTITLEBAR))
  337. {
  338. style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ;
  339. }
  340. return style ;
  341. }
  342. void CHHWinType::GetClientRect(RECT* prc)
  343. {
  344. ::GetClientRect(hwndHelp, prc);
  345. if (IsValidWindow(hwndToolBar)) {
  346. RECT rc;
  347. ::GetWindowRect(hwndToolBar, &rc);
  348. prc->top += RECT_HEIGHT(rc);
  349. }
  350. }
  351. void CHHWinType::CalcHtmlPaneRect(void)
  352. {
  353. ::GetClientRect(hwndHelp, &rcHTML); // the total size of the help window
  354. if (IsValidWindow(hwndToolBar))
  355. {
  356. ::GetWindowRect(hwndToolBar, &rcToolBar);
  357. rcHTML.top += RECT_HEIGHT(rcToolBar);
  358. if (m_fNotesWindow)
  359. {
  360. int height = RECT_HEIGHT(rcNotes);
  361. CopyRect(&rcNotes, &rcHTML);
  362. if (!height)
  363. height = DEFAULT_NOTES_HEIGHT;
  364. rcNotes.bottom = rcNotes.top + height;
  365. rcHTML.top = rcNotes.bottom;
  366. if (IsExpandedNavPane())
  367. rcNotes.left += RECT_WIDTH(rcNav);
  368. }
  369. }
  370. if (IsExpandedNavPane() && !IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
  371. {
  372. if( hwndNavigation )
  373. ::GetClientRect(hwndNavigation, &rcNav);
  374. if (m_pSizeBar)
  375. {
  376. rcHTML.left += m_pSizeBar->Width() + RECT_WIDTH(rcNav);
  377. }
  378. else
  379. {
  380. rcHTML.left += RECT_WIDTH(rcNav);
  381. }
  382. }
  383. rcNav.top = m_fNotesWindow ? rcNotes.top : rcHTML.top;
  384. if ( m_hWndSSCB )
  385. rcNav.top += m_iSSCBHeight;
  386. rcNav.bottom = rcHTML.bottom;
  387. }
  388. // Wrap the toolbar
  389. void CHHWinType::WrapTB()
  390. {
  391. extern SHORT g_tbRightMargin;
  392. extern SHORT g_tbLeftMargin;
  393. int cRows, cButtons;
  394. RECT btnRc;
  395. int btnWidth=0;
  396. int btnspace;
  397. int btnsperrow;
  398. cButtons = (int)SendMessage(hwndToolBar, TB_BUTTONCOUNT, 0, 0);
  399. if (cButtons == 0)
  400. {
  401. ASSERT(cButtons != 0) ; // Should never happen.
  402. return ;
  403. }
  404. if (fsToolBarFlags & HHWIN_BUTTON_EXPAND)
  405. cButtons--;
  406. ::GetWindowRect(hwndHelp, &rcWindowPos);
  407. for ( int i=0; (btnWidth==0)&&(i<cButtons); i++)
  408. {
  409. if ( SendMessage(hwndToolBar, TB_GETITEMRECT, (WPARAM)i, (LPARAM)&btnRc) )
  410. btnWidth = RECT_WIDTH(btnRc);
  411. }
  412. if ( btnWidth == 0 )
  413. btnWidth = TB_BTN_CX;
  414. // How many buttons per row??
  415. btnspace = RECT_WIDTH(rcWindowPos) -(g_tbLeftMargin+g_tbRightMargin);
  416. btnsperrow = btnspace / btnWidth;
  417. if( btnsperrow == 0 )
  418. btnsperrow = 1;
  419. cRows = cButtons / btnsperrow;
  420. if ( cButtons % btnsperrow )
  421. cRows++;
  422. if (RECT_HEIGHT(btnRc) == 0)
  423. {
  424. ASSERT(RECT_HEIGHT(btnRc) != 0) ;
  425. return ; // Avoid divide by zero.
  426. }
  427. if ( cRows < RECT_HEIGHT(rcToolBar)/RECT_HEIGHT(btnRc))
  428. {
  429. WPARAM wParam = MAKEWPARAM( cRows, FALSE);
  430. SendMessage(hwndToolBar, TB_SETROWS, wParam, (LPARAM)&rcToolBar);
  431. }
  432. else if ( cRows > RECT_HEIGHT(rcToolBar)/RECT_HEIGHT(btnRc) )
  433. {
  434. WPARAM wParam = MAKEWPARAM( cRows, TRUE);
  435. SendMessage(hwndToolBar, TB_SETROWS, wParam, (LPARAM)&rcToolBar);
  436. }
  437. ::GetClientRect(hwndToolBar, &rcToolBar);
  438. rcToolBar.bottom = rcToolBar.top + cRows*RECT_HEIGHT(btnRc);
  439. rcToolBar.right = RECT_WIDTH(rcWindowPos);
  440. MoveWindow(hwndToolBar, rcToolBar.top+g_tbLeftMargin, rcToolBar.left, RECT_WIDTH(rcToolBar)-(g_tbLeftMargin+g_tbRightMargin), RECT_HEIGHT(rcToolBar), TRUE);
  441. }
  442. void CHHWinType::ToggleExpansion(bool bNotify /*=true*/)
  443. {
  444. if (!IsValidWindow(GetHwnd()))
  445. {
  446. return ;
  447. }
  448. if (bNotify)
  449. {
  450. // Review: Should we check the return value? [dalero: 21 Sep 98]
  451. OnTrackNotifyCaller(IsExpandedNavPane() ? HHACT_CONTRACT : HHACT_EXPAND) ;
  452. }
  453. RECT rc;
  454. if (RECT_WIDTH(rcNav) <= 0)
  455. {
  456. rcNav.right = (iNavWidth ? iNavWidth : DEFAULT_NAV_WIDTH);
  457. }
  458. if (fNotExpanded)
  459. {
  460. fNotExpanded = FALSE; // now expanding
  461. if (IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
  462. {
  463. if (IsValidWindow(hwndHTML) )
  464. {
  465. ShowWindow(hwndHTML, SW_HIDE);
  466. }
  467. }
  468. else
  469. { // normal tri-pane window
  470. // Expand the window to the left to make room
  471. ::GetWindowRect(GetHwnd(), &rc);
  472. rc.left -= RECT_WIDTH(rcNav) + m_pSizeBar->Width() ;
  473. GetWorkArea(); // Multiple Monitor support.
  474. if (rc.left < g_rcWorkArea.left)
  475. {
  476. rc.left = g_rcWorkArea.left;
  477. }
  478. /*
  479. BUG 3463 --- the MoveWindow call below was not sending a WM_SIZE message, when
  480. RECT_WIDTH(rc) > the width of the screen. Adjusting the width fixes this issue.nn
  481. */
  482. // Don't make the window wider than the screen width.
  483. if (rc.right > g_rcWorkArea.right)
  484. {
  485. rc.right = g_rcWorkArea.right;
  486. }
  487. // create a size bar window between the Nav pane and the HTML pane
  488. CreateSizeBar(); // Moved because the function below resizes...
  489. if (!m_fLockSize)
  490. {
  491. MoveWindow(GetHwnd(), rc.left, rc.top, RECT_WIDTH(rc), RECT_HEIGHT(rc), TRUE);
  492. }
  493. }
  494. CreateOrShowNavPane();
  495. if (GetToolBarHwnd())
  496. {
  497. SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_EXPAND, TRUE);
  498. SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_CONTRACT, FALSE);
  499. SendMessage(GetToolBarHwnd(), TB_ENABLEBUTTON, IDTB_CONTRACT, TRUE);
  500. }
  501. }
  502. else
  503. {
  504. fNotExpanded = TRUE;
  505. DestroySizeBar();
  506. if ( m_hWndST )
  507. ShowWindow(m_hWndST, SW_HIDE);
  508. if ( m_hWndSSCB )
  509. ShowWindow(m_hWndSSCB, SW_HIDE);
  510. if (IsValidWindow(hwndNavigation))
  511. {
  512. ShowWindow(hwndNavigation, SW_HIDE);
  513. }
  514. if (IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
  515. {
  516. ShowWindow(hwndHTML, SW_SHOW);
  517. }
  518. else
  519. {
  520. ::GetWindowRect(GetHwnd(), &rc);
  521. if (!m_fLockSize)
  522. rc.left += RECT_WIDTH(rcNav) + m_pSizeBar->Width() ;
  523. // make sure we are not going off the screen Bug 6611
  524. GetWorkArea(); // Multiple Monitor support.
  525. if (rc.left > g_rcWorkArea.right)
  526. {
  527. int min = GetSystemMetrics(SM_CXHTHUMB);
  528. rc.left = g_rcWorkArea.right - min*2;
  529. }
  530. MoveWindow(GetHwnd(), rc.left, rc.top, RECT_WIDTH(rc), RECT_HEIGHT(rc), TRUE);
  531. }
  532. if (GetToolBarHwnd())
  533. {
  534. SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_CONTRACT, TRUE);
  535. SendMessage(GetToolBarHwnd(), TB_HIDEBUTTON, IDTB_EXPAND, FALSE);
  536. SendMessage(GetToolBarHwnd(), TB_ENABLEBUTTON, IDTB_EXPAND, TRUE);
  537. }
  538. }
  539. }
  540. void CHHWinType::CreateSizeBar( void )
  541. {
  542. if (!m_pSizeBar && IsValidWindow(GetHTMLHwnd()))
  543. {
  544. m_pSizeBar = new CSizeBar ;
  545. ASSERT(m_pSizeBar) ;
  546. m_pSizeBar->Create(this) ;
  547. }
  548. }
  549. void CHHWinType::DestroySizeBar( void )
  550. {
  551. if (m_pSizeBar)
  552. {
  553. delete m_pSizeBar ;
  554. m_pSizeBar = NULL ;
  555. }
  556. }
  557. void CHHWinType::CreateOrShowNavPane(void)
  558. {
  559. if (IsProperty(HHWIN_PROP_NAV_ONLY_WIN))
  560. rcNav.right = rcHTML.right;
  561. if (!IsValidWindow(hwndNavigation)/* && !IsProperty(HHWIN_PROP_NO_TOOLBAR)*/) {
  562. rcNav.left = 0;
  563. if (RECT_WIDTH(rcNav) <= 0)
  564. {
  565. rcNav.right = (iNavWidth ? iNavWidth : DEFAULT_NAV_WIDTH);
  566. }
  567. CalcHtmlPaneRect();
  568. //
  569. // Create the structural subset picker combo if necessary.
  570. //
  571. if (m_phmData && // BUG 5214
  572. m_phmData->m_sysflags.fDoSS && !
  573. m_phmData->m_pTitleCollection->IsSingleTitle() )
  574. {
  575. HFONT hFont, hFontOld;
  576. TEXTMETRIC tm;
  577. HDC hDC;
  578. RECT rc;
  579. hFont = _Resource.GetAccessableUIFont(); // GetUIFont();
  580. hDC = GetDC(NULL);
  581. hFontOld = (HFONT)SelectObject(hDC, hFont);
  582. GetTextMetrics(hDC, &tm);
  583. SelectObject(hDC, hFontOld);
  584. ReleaseDC(NULL, hDC);
  585. rcNav.top += 5;
  586. m_iSSCBHeight = 5;
  587. if ( (m_hWndST = CreateWindow("STATIC", GetStringResource(IDS_SUBSET_UI), WS_CHILD , rcNav.left + 6, rcNav.top,
  588. RECT_WIDTH(rcNav) - 8, tm.tmHeight, GetHwnd(), NULL, _Module.GetModuleInstance(), NULL)) )
  589. {
  590. SendMessage(m_hWndST, WM_SETFONT, (WPARAM)hFont, 0L);
  591. rcNav.top += tm.tmHeight + 2;
  592. m_iSSCBHeight += tm.tmHeight + 2;
  593. rc.left = rcNav.left + 6;
  594. rc.top = rcNav.top;
  595. rc.right = rcNav.right - 10;
  596. rc.bottom = rcNav.top + tm.tmHeight + 10;
  597. if(g_bWinNT5)
  598. {
  599. SetWindowTextW(m_hWndST,GetStringResourceW(IDS_SUBSET_UI));
  600. }
  601. m_hWndSSCB = CreateWindow("COMBOBOX", NULL, (WS_CHILD | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL), rc.left, rc.top,
  602. RECT_WIDTH(rc), RECT_HEIGHT(rc) + 80, GetHwnd(), (HMENU)IDC_SS_PICKER,
  603. _Module.GetModuleInstance(), NULL);
  604. SendMessage(m_hWndSSCB, WM_SETFONT, (WPARAM)GetAccessableContentFont(), 0L);
  605. rcNav.top += tm.tmHeight + 11;
  606. m_iSSCBHeight += tm.tmHeight + 11;
  607. ShowWindow(m_hWndST, SW_SHOW);
  608. ShowWindow(m_hWndSSCB, SW_SHOW);
  609. //
  610. // Populate the combo.
  611. //
  612. if ( m_phmData->m_pTitleCollection->m_pSSList )
  613. {
  614. CStructuralSubset* pSSSel = NULL, *pSS = NULL;
  615. while ( pSS = m_phmData->m_pTitleCollection->m_pSSList->GetNextSubset(pSS) )
  616. {
  617. if (! pSS->IsEmpty() ) // Don't put "new" here.
  618. {
  619. if(g_bWinNT5)
  620. {
  621. CExTitle *pTitle = m_phmData->m_pTitleCollection->GetFirstTitle();
  622. DWORD cp;
  623. if(pSS->IsEntire() == TRUE)
  624. cp = CodePageFromLCID(MAKELCID(_Module.m_Language.GetUiLanguage(),SORT_DEFAULT));
  625. else
  626. cp = CodePageFromLCID((pTitle->GetInfo())->GetLanguage());
  627. DWORD dwSize = (DWORD)(sizeof(WCHAR) * strlen(pSS->GetName())) + 4;
  628. WCHAR *pwcString = (WCHAR *) lcMalloc(dwSize);
  629. if(pwcString)
  630. {
  631. MultiByteToWideChar(cp, MB_PRECOMPOSED, pSS->GetName(), -1, pwcString, dwSize);
  632. SendMessageW(m_hWndSSCB, CB_ADDSTRING, 0, (LPARAM)pwcString);
  633. lcFree(pwcString);
  634. }
  635. }
  636. else
  637. {
  638. SendMessage(m_hWndSSCB, CB_ADDSTRING, 0, (LPARAM)pSS->GetName());
  639. }
  640. }
  641. if ( pSS->IsTOC() )
  642. pSSSel = pSS;
  643. }
  644. // Select as appropiate...
  645. //
  646. if (! pSSSel )
  647. pSSSel = m_phmData->m_pTitleCollection->m_pSSList->GetEC();
  648. if(g_bWinNT5 && pSSSel->IsEntire())
  649. {
  650. // This code special cases the selection of the "Entire Collection" subset in the combobox.
  651. //
  652. WCHAR pszUnicodeSubsetName[MAX_SS_NAME_LEN];
  653. pszUnicodeSubsetName[0] = 0;
  654. // Get the UI language codepage
  655. //
  656. DWORD cp = CodePageFromLCID(MAKELCID(_Module.m_Language.GetUiLanguage(),SORT_DEFAULT));
  657. // convert subset name to Unicode using UI codepage
  658. //
  659. MultiByteToWideChar(cp, MB_PRECOMPOSED, pSSSel->GetName(), -1, pszUnicodeSubsetName, sizeof(pszUnicodeSubsetName));
  660. // select the subset in the combobox
  661. //
  662. SendMessageW(m_hWndSSCB, CB_SELECTSTRING, -1, (LPARAM)pszUnicodeSubsetName);
  663. }
  664. else
  665. SendMessage(m_hWndSSCB, CB_SELECTSTRING, -1, (LPARAM)pSSSel->GetName());
  666. m_phmData->m_pTitleCollection->m_pSSList->SetFTS(pSSSel);
  667. m_phmData->m_pTitleCollection->m_pSSList->SetF1(pSSSel);
  668. m_phmData->m_pTitleCollection->m_pSSList->SetTOC(pSSSel);
  669. pSSSel->SelectAsTOCSubset(m_phmData->m_pTitleCollection);
  670. }
  671. }
  672. }
  673. //
  674. // Create the HH CHILD window on which the SysTabCtrl32 window will sit.
  675. //txtHtmlHelpChildWindowClass
  676. hwndNavigation = W_CreateWindow(L"HH Child", NULL, WS_CHILD, rcNav.left, rcNav.top, RECT_WIDTH(rcNav),
  677. RECT_HEIGHT(rcNav), GetHwnd(), NULL, _Module.GetModuleInstance(), NULL);
  678. // How many tabs do we have?
  679. int cTabs = GetValidNavPaneCount();
  680. if (cTabs > 1)
  681. {
  682. // Remove the non-existant tabs from the tab order.
  683. int max = HH_MAX_TABS ;
  684. for (int i = 0; i < max; i++) // Don't have to move last if invalid So don't add 1 to HH_MAX_TABS
  685. {
  686. if (!IsValidNavPane(tabOrder[i]))
  687. {
  688. // Collapse the array.
  689. MemMove(&tabOrder[i], &tabOrder[i + 1], max - i);
  690. // Decrement the count so we do this index again.
  691. i-- ;
  692. max-- ;
  693. }
  694. }
  695. // Now create the tab.
  696. m_pTabCtrl = new CTabControl(hwndNavigation, tabpos, this);
  697. }
  698. ResizeWindow(this);
  699. }
  700. if (!IsProperty(HHWIN_PROP_NO_TOOLBAR))
  701. ShowWindow(hwndNavigation, SW_SHOW);
  702. if (m_pTabCtrl)
  703. ShowWindow(m_pTabCtrl->hWnd(), SW_SHOW);
  704. if ( m_hWndST )
  705. ShowWindow(m_hWndST, SW_SHOW);
  706. if ( m_hWndSSCB )
  707. ShowWindow(m_hWndSSCB, SW_SHOW);
  708. //Validate the current nav pane.
  709. if (!IsValidNavPane(curNavType))
  710. {
  711. // The current nav pane doesn't exist. Pick another.
  712. curNavType = GetValidNavPane() ;
  713. if (curNavType < 0)
  714. {
  715. ASSERT(0) ; // Should never happen.
  716. return; // hopeless...
  717. }
  718. }
  719. // Create the nav pane if needed.
  720. CreateNavPane(curNavType) ;
  721. // Show the pane.
  722. if (m_aNavPane[curNavType])
  723. {
  724. if (curNavType != 0 && m_pTabCtrl)
  725. TabCtrl_SetCurSel(m_pTabCtrl->hWnd(), GetTabIndexFromNavPaneIndex(curNavType));
  726. m_aNavPane[curNavType]->ShowWindow() ;
  727. // BUG HH 16685 - The current tab is now persisted. So we come along and
  728. // create this new tab. However, resize is never called. So, we will call
  729. // resize here to make sure that we resize the window.
  730. m_aNavPane[curNavType]->ResizeWindow() ;
  731. }
  732. if ( m_pSizeBar )
  733. m_pSizeBar->ResizeWindow();
  734. }
  735. void CHHWinType::CreateOrShowHTMLPane(void)
  736. {
  737. if (!IsValidWindow(hwndNavigation))
  738. hwndHTML = CreateWindow(txtHtmlHelpChildWindowClass, NULL,
  739. WS_CHILD | WS_CLIPCHILDREN, rcHTML.left, rcHTML.top,
  740. RECT_WIDTH(rcHTML), RECT_HEIGHT(rcHTML), GetHwnd(), NULL,
  741. _Module.GetModuleInstance(), NULL);
  742. ShowWindow(hwndHTML, SW_SHOW);
  743. }
  744. void CHHWinType::CreateToc(void)
  745. {
  746. if (IsEmptyString(pszToc))
  747. return;
  748. TCHAR szPath[MAX_URL];
  749. if (!ConvertToCacheFile(pszToc, szPath)) {
  750. AuthorMsg(IDS_CANT_OPEN, pszToc);
  751. strcpy(szPath, pszToc);
  752. }
  753. CToc* ptoc = new CToc(NULL, NULL, this);
  754. m_aNavPane[HH_TAB_CONTENTS] = ptoc ;
  755. ptoc->SetTabPos(tabpos);
  756. ptoc->SetPadding(TAB_PADDING);
  757. ptoc->ReadFile(szPath);
  758. // populate the InfoType member object of the CToc
  759. if ( !ptoc->m_pInfoType )
  760. {
  761. if (ptoc->m_phh && ptoc->m_phh->m_phmData && ptoc->m_phh->m_phmData->m_pdInfoTypes )
  762. { // load from the global IT store
  763. ptoc->m_pInfoType = new CInfoType;
  764. ptoc->m_pInfoType->CopyTo( ptoc->m_phh->m_phmData );
  765. #if 0 // for subset testing purposes
  766. #include "csubset.h"
  767. CSubSets *pSubSets = new CSubSets( ptoc->m_pInfoType->InfoTypeSize(), ptoc->m_pInfoType, TRUE );
  768. pSubSets->CopyTo( ptoc->m_phh->m_phmData );
  769. #endif
  770. }
  771. else {
  772. // no global IT's; load from the .hhc IT store
  773. ptoc->m_pInfoType = new CInfoType;
  774. *ptoc->m_pInfoType = ptoc->m_sitemap;
  775. }
  776. }
  777. ptoc->SetStyles(WS_EX_CLIENTEDGE,
  778. ptoc->m_sitemap.m_tvStyles == (DWORD) -1 ?
  779. DEFAULT_TOC_STYLES : ptoc->m_sitemap.m_tvStyles);
  780. ptoc->Create((m_pTabCtrl ? m_pTabCtrl->hWnd() :
  781. (IsValidWindow(hwndNavigation) ? hwndNavigation : hwndHelp)));
  782. ptoc->m_fHack = FALSE;
  783. ptoc->InitTreeView();
  784. }
  785. void CHHWinType::UpdateInformationTypes(void)
  786. {
  787. if ( m_aNavPane[HH_TAB_CONTENTS] )
  788. {
  789. m_aNavPane[HH_TAB_CONTENTS]->Refresh();
  790. if (IsProperty(HHWIN_PROP_AUTO_SYNC) && IsExpandedNavPane())
  791. {
  792. CStr cszUrl;
  793. m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
  794. m_aNavPane[HH_TAB_CONTENTS]->Synchronize(cszUrl);
  795. }
  796. // Next/Prev command UI updates...
  797. //
  798. UpdateCmdUI();
  799. }
  800. if ( m_aNavPane[HH_TAB_INDEX] && curNavType == HHWIN_NAVTYPE_INDEX )
  801. m_aNavPane[HH_TAB_INDEX]->Refresh();
  802. }
  803. void CHHWinType::UpdateCmdUI(void)
  804. {
  805. HMENU hMenu;
  806. BOOL bEnable, ptoc;
  807. ptoc = (m_aNavPane[HH_TAB_CONTENTS] != NULL);
  808. if ( IsValidWindow(hwndToolBar) )
  809. {
  810. if ( hwndHelp )
  811. hMenu = GetMenu(hwndHelp);
  812. //
  813. // Does TOCNext or TOCPrev need to be enabled/disabled ?
  814. //
  815. if ( (fsToolBarFlags & HHWIN_BUTTON_TOC_PREV) || (fsToolBarFlags & HHWIN_BUTTON_TOC_NEXT) || hMenu )
  816. {
  817. bEnable = ptoc ? OnTocPrev(FALSE) : FALSE ; // If no TOC, disable.
  818. if ( fsToolBarFlags & HHWIN_BUTTON_TOC_PREV )
  819. SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_TOC_PREV, bEnable);
  820. if ( hMenu )
  821. EnableMenuItem(hMenu, IDTB_TOC_PREV, (MF_BYCOMMAND | (bEnable?MF_ENABLED:MF_GRAYED)));
  822. bEnable = ptoc ? OnTocNext(FALSE) : FALSE; // If no TOC, disable.
  823. if ( fsToolBarFlags & HHWIN_BUTTON_TOC_NEXT )
  824. SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_TOC_NEXT, bEnable);
  825. if ( hMenu )
  826. EnableMenuItem(hMenu, IDTB_TOC_NEXT, (MF_BYCOMMAND | (bEnable?MF_ENABLED:MF_GRAYED)));
  827. }
  828. if (NoRun() == TRUE)
  829. {
  830. if (hMenu)
  831. EnableMenuItem(hMenu, HHM_JUMP_URL, MF_BYCOMMAND|MF_GRAYED);
  832. }
  833. }
  834. }
  835. ///////////////////////////////////////////////////////////
  836. //
  837. // CreateIndex
  838. //
  839. void CHHWinType::CreateIndex(void)
  840. {
  841. if (IsEmptyString(pszIndex))
  842. return;
  843. TCHAR szPath[MAX_URL];
  844. if (!ConvertToCacheFile(pszIndex, szPath)) {
  845. AuthorMsg(IDS_CANT_OPEN, pszIndex);
  846. strcpy(szPath, pszIndex);
  847. }
  848. if (!m_aNavPane[HH_TAB_INDEX])
  849. {
  850. CIndex* pIndex = new CIndex(NULL, NULL, this);
  851. m_aNavPane[HH_TAB_INDEX] = pIndex ;
  852. pIndex->SetPadding(TAB_PADDING);
  853. pIndex->SetTabPos(tabpos);
  854. pIndex->ReadIndexFile(szPath); // A CIndex function, but not a INavUI function.
  855. }
  856. m_aNavPane[HH_TAB_INDEX]->Create(GetTabCtrlHwnd());
  857. }
  858. ///////////////////////////////////////////////////////////
  859. //
  860. // CreateSearchTab
  861. //
  862. void CHHWinType::CreateSearchTab(void)
  863. {
  864. if (!
  865. m_phmData || !m_phmData->m_pTitleCollection->m_pFullTextSearch)
  866. return; // no compiled information
  867. if (!m_aNavPane[HH_TAB_SEARCH])
  868. {
  869. if (IsProperty(HHWIN_PROP_TAB_ADVSEARCH))
  870. {
  871. //---Create the Advanced Search Navigation Pane.
  872. m_aNavPane[HH_TAB_SEARCH] = new CAdvancedSearchNavPane(this);
  873. }
  874. else
  875. {
  876. //---Create the simple Search Navigation Pane.
  877. m_aNavPane[HH_TAB_SEARCH] = new CSearch(this);
  878. }
  879. m_aNavPane[HH_TAB_SEARCH]->SetPadding(TAB_PADDING);
  880. m_aNavPane[HH_TAB_SEARCH]->SetTabPos(tabpos);
  881. }
  882. m_aNavPane[HH_TAB_SEARCH]->Create(GetTabCtrlHwnd());
  883. }
  884. ///////////////////////////////////////////////////////////
  885. //
  886. // CreateBookmarksTab
  887. //
  888. void
  889. CHHWinType::CreateBookmarksTab()
  890. {
  891. if (!m_aNavPane[HH_TAB_FAVORITES])
  892. {
  893. CBookmarksNavPane* p= new CBookmarksNavPane(this);
  894. m_aNavPane[HH_TAB_FAVORITES] = p;
  895. p->SetPadding(TAB_PADDING);
  896. p->SetTabPos(tabpos);
  897. }
  898. m_aNavPane[HH_TAB_FAVORITES]->Create(GetTabCtrlHwnd());
  899. }
  900. ///////////////////////////////////////////////////////////
  901. //
  902. // CreatesCustomTab - Creates a tab defined by the client.
  903. //
  904. void
  905. CHHWinType::CreateCustomTab(int iPane, LPCOLESTR pszProgId)
  906. {
  907. // REVIEW: The lines marked with [chm] assume that the information can be found in the chm file.
  908. if (!m_aNavPane[iPane])
  909. {
  910. CCustomNavPane* p= new CCustomNavPane(this);
  911. m_aNavPane[iPane] = p;
  912. p->SetPadding(TAB_PADDING);
  913. p->SetTabPos(tabpos);
  914. p->SetControlProgId(pszProgId); //[chm] We could also use the GUID instead/in addition.
  915. }
  916. m_aNavPane[iPane]->Create(GetTabCtrlHwnd());
  917. }
  918. ///////////////////////////////////////////////////////////
  919. //
  920. // Destructor
  921. //
  922. CHHWinType::~CHHWinType()
  923. {
  924. CloseWindow();
  925. }
  926. extern BOOL g_fThreadCall;
  927. extern HWND g_hwndApi;
  928. //
  929. // This member can be called from DllMain at process detach time. Note that this is only a partial cleanup but
  930. // it's the best we can do at process detach time.
  931. //
  932. //
  933. void CHHWinType::ProcessDetachSafeCleanup()
  934. {
  935. if (m_pTabCtrl) {
  936. delete m_pTabCtrl;
  937. m_pTabCtrl = NULL;
  938. }
  939. // Get rid of the sizebar.
  940. DestroySizeBar() ;
  941. if (m_ptblBtnStrings) {
  942. delete m_ptblBtnStrings;
  943. m_ptblBtnStrings = NULL;
  944. }
  945. }
  946. void CHHWinType::CloseWindow()
  947. {
  948. // Save the state..
  949. SaveState() ;
  950. // Things we can cleanup a process shutdown.
  951. ProcessDetachSafeCleanup() ;
  952. // Things we cleanup when we are reloading the nav panes.
  953. ReloadCleanup() ;
  954. // Free here and not in ReloadCleanup.
  955. CHECK_AND_FREE( pszHome );
  956. CHECK_AND_FREE( pszCustomTabs );
  957. CHECK_AND_FREE( pszType );
  958. CHECK_AND_FREE( pszCaption );
  959. if (m_pCIExpContainer)
  960. {
  961. m_pCIExpContainer->ShutDown(); // This call WILL end up doing the delete m_pCIExpContainer;
  962. m_pCIExpContainer = NULL;
  963. }
  964. if ( m_phmData && !m_phmData->Release() ) // Cleanup ChmData
  965. {
  966. //
  967. // Find this instance of the ChmData in the global array, null out it's entry and clean this one up.
  968. //
  969. for (int n = 0; n < g_cHmSlots; n++)
  970. {
  971. if ( g_phmData && (g_phmData[n] == m_phmData) )
  972. {
  973. g_phmData[n] = NULL;
  974. }
  975. }
  976. }
  977. m_phmData = NULL;
  978. if (IsProperty(HHWIN_PROP_POST_QUIT))
  979. {
  980. PostQuitMessage(0);
  981. }
  982. // Null out our window from the window list.
  983. for (int i = 0; i < g_cWindowSlots; i++)
  984. {
  985. if (pahwnd[i] != NULL && pahwnd[i]->hwndHelp == hwndHelp)
  986. {
  987. pahwnd[i] = NULL ;
  988. }
  989. }
  990. curNavType = 0;
  991. hwndHelp = NULL;
  992. // Do other windows exist?
  993. for (i = 0; i < g_cWindowSlots; i++)
  994. {
  995. if (pahwnd[i] != NULL && pahwnd[i]->hwndHelp != NULL)
  996. {
  997. // If other windows exist exit.
  998. return ;
  999. }
  1000. }
  1001. for(int j=0; i< c_NUMNAVPANES; i++)
  1002. {
  1003. if ( m_aNavPane[j] )
  1004. {
  1005. delete m_aNavPane[j];
  1006. m_aNavPane[j] = NULL;
  1007. }
  1008. }
  1009. if ( m_pTabCtrl )
  1010. {
  1011. delete m_pTabCtrl;
  1012. m_pTabCtrl = NULL;
  1013. }
  1014. if ( m_pSizeBar )
  1015. {
  1016. delete m_pSizeBar;
  1017. m_pSizeBar = NULL;
  1018. }
  1019. if (m_hAccel)
  1020. {
  1021. DestroyAcceleratorTable(m_hAccel) ;
  1022. m_hAccel = NULL ;
  1023. }
  1024. if( m_hMenuOptions ) {
  1025. DestroyMenu( m_hMenuOptions );
  1026. m_hMenuOptions = NULL;
  1027. }
  1028. if( m_hImageListGray ) {
  1029. ImageList_Destroy( m_hImageListGray );
  1030. m_hImageListGray = NULL;
  1031. }
  1032. if( m_hImageList ) {
  1033. ImageList_Destroy( m_hImageList );
  1034. m_hImageList = NULL;
  1035. }
  1036. if( hwndToolBar ) {
  1037. DestroyWindow( hwndToolBar );
  1038. hwndToolBar = NULL;
  1039. }
  1040. // If we got here, all windows have been closed
  1041. DeleteAllHmData();
  1042. #ifdef _CHECKMEM_ON_CLOSEWINDOW_
  1043. _CrtMemDumpAllObjectsSince(&m_MemState) ;
  1044. #endif
  1045. if (g_fThreadCall && g_hwndApi)
  1046. PostQuitMessage(0);
  1047. }
  1048. ////////////////////////////////////////////////////////////////
  1049. //
  1050. // ReloadCleanUp --- This is the things we have to clean up before we reload the nav pane.
  1051. //
  1052. void
  1053. CHHWinType::ReloadCleanup()
  1054. {
  1055. // Delete all of the navigation panes.
  1056. for(int j = 0 ; j < c_NUMNAVPANES ; j++)
  1057. {
  1058. if (m_aNavPane[j])
  1059. {
  1060. delete m_aNavPane[j] ;
  1061. m_aNavPane[j] = NULL ;
  1062. }
  1063. }
  1064. CHECK_AND_FREE( pszToc );
  1065. CHECK_AND_FREE( pszIndex );
  1066. CHECK_AND_FREE( pszFile );
  1067. CHECK_AND_FREE( pszJump1 );
  1068. CHECK_AND_FREE( pszJump2 );
  1069. CHECK_AND_FREE( pszUrlJump1 );
  1070. CHECK_AND_FREE( pszUrlJump2 );
  1071. // Don't free this here. Because we need to keep this around.
  1072. // CHECK_AND_FREE( pszHome );
  1073. //CHECK_AND_FREE( pszCustomTabs );
  1074. //CHECK_AND_FREE( pszType );
  1075. //CHECK_AND_FREE( pszCaption );
  1076. }
  1077. void
  1078. CHHWinType::SaveState()
  1079. {
  1080. WINDOW_STATE wstate;
  1081. WINDOWPLACEMENT winPlace;
  1082. wstate.cbStruct = sizeof(wstate);
  1083. winPlace.length = sizeof(WINDOWPLACEMENT);
  1084. GetWindowPlacement(GetHwnd(), &winPlace);
  1085. if (winPlace.showCmd == SW_SHOWMINIMIZED)
  1086. {
  1087. wstate.rcPos = winPlace.rcNormalPosition;
  1088. }
  1089. else
  1090. {
  1091. ::GetWindowRect(GetHwnd(), &wstate.rcPos);
  1092. }
  1093. wstate.iNavWidth = rcNav.right;
  1094. wstate.fHighlight = (m_phmData&&m_phmData->m_pTitleCollection->m_pSearchHighlight)?m_phmData->m_pTitleCollection->m_pSearchHighlight->m_bHighlightEnabled:TRUE;
  1095. wstate.fLockSize = m_fLockSize;
  1096. wstate.fNoToolBarText = m_fNoToolBarText;
  1097. wstate.curNavType = curNavType;
  1098. wstate.fNotExpanded = fNotExpanded;
  1099. if( m_phmData ) {
  1100. CState* pstate = m_phmData->m_pTitleCollection->GetState();
  1101. if (SUCCEEDED(pstate->Open(GetTypeName(), STGM_WRITE))) {
  1102. pstate->Write(&wstate, sizeof(wstate));
  1103. pstate->Close();
  1104. }
  1105. }
  1106. }
  1107. int CHHWinType::CreateToolBar(TBBUTTON* pabtn)
  1108. {
  1109. // create a dropdown menu for the options button to display
  1110. int cMenuItems=0;
  1111. const int MENUITEMSTRINGLEN = 80;
  1112. CStr cszMenuItem;
  1113. m_hMenuOptions = CreatePopupMenu();
  1114. cszMenuItem.ReSize(MENUITEMSTRINGLEN);
  1115. ASSERT(!IsProperty(HHWIN_PROP_NO_TOOLBAR));
  1116. if (m_ptblBtnStrings)
  1117. delete m_ptblBtnStrings;
  1118. m_ptblBtnStrings = new CTable(256); // room for 256 bytes
  1119. int cButtons = 0;
  1120. MENUITEMINFO mii;
  1121. ZERO_STRUCTURE ( mii );
  1122. mii.cbSize = sizeof(MENUITEMINFO);
  1123. mii.fMask = MIIM_TYPE|MIIM_STATE|MIIM_ID|MIIM_SUBMENU|MIIM_CHECKMARKS;
  1124. mii.fType = MFT_STRING;
  1125. if (fsToolBarFlags & HHWIN_BUTTON_EXPAND) {
  1126. pabtn[cButtons].iBitmap = 12;
  1127. pabtn[cButtons].idCommand = IDTB_EXPAND;
  1128. pabtn[cButtons].fsState = (IsExpandedNavPane() ? TBSTATE_HIDDEN : TBSTATE_ENABLED);
  1129. pabtn[cButtons].iString = cButtons;
  1130. m_ptblBtnStrings->AddString(GetStringResource(IDTB_EXPAND));
  1131. cButtons++;
  1132. }
  1133. if (fsToolBarFlags & HHWIN_BUTTON_EXPAND) {
  1134. pabtn[cButtons].iBitmap = 13;
  1135. pabtn[cButtons].idCommand = IDTB_CONTRACT;
  1136. pabtn[cButtons].fsState = (IsExpandedNavPane() ? TBSTATE_ENABLED : TBSTATE_HIDDEN);
  1137. pabtn[cButtons].iString = cButtons;
  1138. m_ptblBtnStrings->AddString(GetStringResource(IDTB_CONTRACT));
  1139. cButtons++;
  1140. }
  1141. if (fsToolBarFlags & HHWIN_BUTTON_SYNC) {
  1142. if (!IsEmptyString(pszToc)) {
  1143. pabtn[cButtons].iBitmap = 9;
  1144. pabtn[cButtons].idCommand = IDTB_SYNC;
  1145. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1146. pabtn[cButtons].iString = cButtons;
  1147. m_ptblBtnStrings->AddString(GetStringResource(IDTB_SYNC));
  1148. cButtons++;
  1149. }
  1150. }
  1151. if (fsToolBarFlags & HHWIN_BUTTON_TOC_PREV) {
  1152. pabtn[cButtons].iBitmap = 14;
  1153. pabtn[cButtons].idCommand = IDTB_TOC_PREV;
  1154. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1155. pabtn[cButtons].iString = cButtons;
  1156. m_ptblBtnStrings->AddString(GetStringResource(IDTB_TOC_PREV));
  1157. cButtons++;
  1158. }
  1159. if (fsToolBarFlags & HHWIN_BUTTON_TOC_NEXT) {
  1160. pabtn[cButtons].iBitmap = 8;
  1161. pabtn[cButtons].idCommand = IDTB_TOC_NEXT;
  1162. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1163. pabtn[cButtons].iString = cButtons;
  1164. m_ptblBtnStrings->AddString(GetStringResource(IDTB_TOC_NEXT));
  1165. cButtons++;
  1166. }
  1167. if (g_fBiDi)
  1168. {
  1169. if (fsToolBarFlags & HHWIN_BUTTON_FORWARD) {
  1170. pabtn[cButtons].iBitmap = 0;
  1171. pabtn[cButtons].idCommand = IDTB_FORWARD;
  1172. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1173. pabtn[cButtons].iString = cButtons;
  1174. m_ptblBtnStrings->AddString(GetStringResource(IDTB_FORWARD));
  1175. cButtons++;
  1176. }
  1177. if (fsToolBarFlags & HHWIN_BUTTON_BACK) {
  1178. pabtn[cButtons].iBitmap = 1;
  1179. pabtn[cButtons].idCommand = IDTB_BACK;
  1180. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1181. pabtn[cButtons].iString = cButtons;
  1182. m_ptblBtnStrings->AddString(GetStringResource(IDTB_BACK));
  1183. cButtons++;
  1184. }
  1185. }
  1186. else
  1187. {
  1188. if (fsToolBarFlags & HHWIN_BUTTON_BACK) {
  1189. pabtn[cButtons].iBitmap = 0;
  1190. pabtn[cButtons].idCommand = IDTB_BACK;
  1191. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1192. pabtn[cButtons].iString = cButtons;
  1193. m_ptblBtnStrings->AddString(GetStringResource(IDTB_BACK));
  1194. cButtons++;
  1195. }
  1196. if (fsToolBarFlags & HHWIN_BUTTON_FORWARD) {
  1197. pabtn[cButtons].iBitmap = 1;
  1198. pabtn[cButtons].idCommand = IDTB_FORWARD;
  1199. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1200. pabtn[cButtons].iString = cButtons;
  1201. m_ptblBtnStrings->AddString(GetStringResource(IDTB_FORWARD));
  1202. cButtons++;
  1203. }
  1204. }
  1205. if (fsToolBarFlags & HHWIN_BUTTON_STOP) {
  1206. pabtn[cButtons].iBitmap = 2;
  1207. pabtn[cButtons].idCommand = IDTB_STOP;
  1208. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1209. pabtn[cButtons].iString = cButtons;
  1210. m_ptblBtnStrings->AddString(GetStringResource(IDTB_STOP));
  1211. cButtons++;
  1212. }
  1213. if ( fsToolBarFlags & HHWIN_BUTTON_REFRESH) {
  1214. pabtn[cButtons].iBitmap = 3;
  1215. pabtn[cButtons].idCommand = IDTB_REFRESH;
  1216. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1217. pabtn[cButtons].iString = cButtons;
  1218. m_ptblBtnStrings->AddString(GetStringResource(IDTB_REFRESH));
  1219. cButtons++;
  1220. }
  1221. if (fsToolBarFlags & HHWIN_BUTTON_HOME) {
  1222. if (pszHome) {
  1223. pabtn[cButtons].iBitmap = 4;
  1224. pabtn[cButtons].idCommand = IDTB_HOME;
  1225. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1226. pabtn[cButtons].iString = cButtons;
  1227. m_ptblBtnStrings->AddString(GetStringResource(IDTB_HOME));
  1228. cButtons++;
  1229. }
  1230. }
  1231. if (fsToolBarFlags & HHWIN_BUTTON_BROWSE_FWD) {
  1232. if (pszHome) {
  1233. pabtn[cButtons].iBitmap = 14;
  1234. pabtn[cButtons].idCommand = IDTB_BROWSE_FWD;
  1235. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1236. pabtn[cButtons].iString = cButtons;
  1237. m_ptblBtnStrings->AddString(GetStringResource(IDTB_BROWSE_FWD));
  1238. cButtons++;
  1239. }
  1240. }
  1241. if (fsToolBarFlags & HHWIN_BUTTON_BROWSE_BCK) {
  1242. if (pszHome) {
  1243. pabtn[cButtons].iBitmap = 8;
  1244. pabtn[cButtons].idCommand = IDTB_BROWSE_BACK;
  1245. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1246. pabtn[cButtons].iString = cButtons;
  1247. m_ptblBtnStrings->AddString(GetStringResource(IDTB_BROWSE_BACK));
  1248. cButtons++;
  1249. }
  1250. }
  1251. if (fsToolBarFlags & HHWIN_BUTTON_ZOOM) {
  1252. pabtn[cButtons].iBitmap = 16; // BUGBUG: We need a zoom glyph in toolb16g.bmp
  1253. pabtn[cButtons].idCommand = IDTB_ZOOM;
  1254. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1255. pabtn[cButtons].iString = cButtons;
  1256. m_ptblBtnStrings->AddString(GetStringResource(IDTB_ZOOM));
  1257. cButtons++;
  1258. }
  1259. if ( fsToolBarFlags & HHWIN_BUTTON_PRINT) {
  1260. pabtn[cButtons].iBitmap = 7;
  1261. pabtn[cButtons].idCommand = IDTB_PRINT;
  1262. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1263. pabtn[cButtons].iString = cButtons;
  1264. m_ptblBtnStrings->AddString(GetStringResource(IDTB_PRINT));
  1265. cButtons++;
  1266. }
  1267. //--- hard-coded menu
  1268. CTable tblMenus(8 * 1024);
  1269. mii.cbSize = sizeof(MENUITEMINFO);
  1270. mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  1271. mii.fType = MFT_STRING;
  1272. mii.fState = MFS_ENABLED;
  1273. mii.hSubMenu = NULL;
  1274. mii.hbmpChecked = NULL; // bitmap tp display when checked
  1275. mii.hbmpUnchecked = NULL; // bitmap to display when not checked
  1276. mii.dwItemData = NULL; // data associated with the menu item
  1277. mii.wID = IDTB_CONTRACT; // Menu Item ID
  1278. cszMenuItem = GetStringResource(IDS_OPTION_HIDE); // the string to display for the menu item
  1279. tblMenus.AddString(cszMenuItem.psz);
  1280. mii.dwTypeData = cszMenuItem.psz;
  1281. mii.cch = (DWORD)strlen(mii.dwTypeData); // length of the string.
  1282. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1283. if (fsToolBarFlags & HHWIN_BUTTON_SYNC)
  1284. {
  1285. if (!IsEmptyString(pszToc))
  1286. {
  1287. mii.wID = IDTB_SYNC; // Menu Item ID
  1288. cszMenuItem = GetStringResource(IDS_OPTION_SYNC); // the string to display for the menu item
  1289. tblMenus.AddString(cszMenuItem.psz);
  1290. mii.dwTypeData = cszMenuItem.psz;
  1291. mii.cch = (DWORD)strlen(mii.dwTypeData); // length of the string.
  1292. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1293. }
  1294. }
  1295. mii.wID = IDTB_BACK; // Menu Item ID
  1296. cszMenuItem = GetStringResource(IDS_OPTION_BACK); // the string to display for the menu item
  1297. tblMenus.AddString(cszMenuItem.psz);
  1298. mii.dwTypeData = cszMenuItem.psz;
  1299. mii.cch = (DWORD)strlen(mii.dwTypeData); // length of the string.
  1300. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1301. mii.wID = IDTB_FORWARD; // Menu Item ID
  1302. cszMenuItem = GetStringResource(IDS_OPTION_FORWARD); // the string to display for the menu item
  1303. tblMenus.AddString(cszMenuItem.psz);
  1304. mii.dwTypeData = cszMenuItem.psz;
  1305. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1306. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1307. if (pszHome) {
  1308. mii.wID = IDTB_HOME; // Menu Item ID
  1309. cszMenuItem = GetStringResource(IDS_OPTION_HOME); // the string to display for the menu item
  1310. tblMenus.AddString(cszMenuItem.psz);
  1311. mii.dwTypeData = cszMenuItem.psz;
  1312. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1313. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1314. }
  1315. mii.wID = IDTB_STOP; // Menu Item ID
  1316. cszMenuItem = GetStringResource(IDS_OPTION_STOP); // the string to display for the menu item
  1317. tblMenus.AddString(cszMenuItem.psz);
  1318. mii.dwTypeData = cszMenuItem.psz;
  1319. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1320. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1321. mii.wID = IDTB_REFRESH; // Menu Item ID
  1322. cszMenuItem = GetStringResource(IDS_OPTION_REFRESH); // the string to display for the menu item
  1323. tblMenus.AddString(cszMenuItem.psz);
  1324. mii.dwTypeData = cszMenuItem.psz;
  1325. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1326. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1327. mii.wID = HHM_OPTIONS; // Menu Item ID
  1328. cszMenuItem = GetStringResource(IDS_OPTION_IE_OPTIONS); // the string to display for the menu item
  1329. tblMenus.AddString(cszMenuItem.psz);
  1330. mii.dwTypeData = cszMenuItem.psz;
  1331. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1332. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1333. mii.fMask = MIIM_TYPE;
  1334. mii.fType = MFT_SEPARATOR;
  1335. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1336. // Now restore the mast and type
  1337. mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  1338. mii.fType = MFT_STRING;
  1339. BOOL fSeperatorNeeded = FALSE;
  1340. /*
  1341. * At this point, we need to add any custom Jump buttons, and to do
  1342. * that we need to know all of the hard-coded menu items so that we can
  1343. * adjust the accelerators as needed.
  1344. */
  1345. if ((fsToolBarFlags & HHWIN_BUTTON_JUMP1 && pszJump1) ||
  1346. (fsToolBarFlags & HHWIN_BUTTON_JUMP2 && pszJump2)) {
  1347. tblMenus.AddString(GetStringResource(IDS_OPTION_CUSTOMIZE));
  1348. tblMenus.AddString(GetStringResource(IDS_OPTION_PRINT));
  1349. if (!g_fIE3 && m_phmData && m_phmData->m_pTitleCollection && m_phmData->m_pTitleCollection->m_pSearchHighlight)
  1350. tblMenus.AddString(GetStringResource(IDS_OPTION_HILITING_OFF));
  1351. }
  1352. if (fsToolBarFlags & HHWIN_BUTTON_JUMP1 && pszJump1) {
  1353. mii.wID = IDTB_JUMP1; // Menu Item ID
  1354. cszMenuItem = "&1 ";
  1355. cszMenuItem += pszJump1;
  1356. tblMenus.AddString(cszMenuItem.psz);
  1357. mii.dwTypeData = cszMenuItem.psz;
  1358. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1359. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1360. fSeperatorNeeded = TRUE;
  1361. }
  1362. if (fsToolBarFlags & HHWIN_BUTTON_JUMP2 && pszJump2) {
  1363. mii.wID = IDTB_JUMP2; // Menu Item ID
  1364. cszMenuItem = "&2 ";
  1365. cszMenuItem += pszJump2;
  1366. tblMenus.AddString(cszMenuItem.psz);
  1367. mii.dwTypeData = cszMenuItem.psz;
  1368. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1369. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1370. fSeperatorNeeded = TRUE;
  1371. }
  1372. if (fSeperatorNeeded) {
  1373. mii.fMask = MIIM_TYPE;
  1374. mii.fType = MFT_SEPARATOR;
  1375. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1376. // Now restore the mast and type
  1377. mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  1378. mii.fType = MFT_STRING;
  1379. }
  1380. if (m_phmData && m_phmData->m_pInfoType && m_phmData->m_pInfoType->HowManyInfoTypes() > 0)
  1381. {
  1382. mii.wID = IDTB_CUSTOMIZE; // Menu Item ID
  1383. cszMenuItem = GetStringResource(IDS_OPTION_CUSTOMIZE); // the string to display for the menu item
  1384. mii.dwTypeData = cszMenuItem.psz;
  1385. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1386. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1387. }
  1388. mii.wID = IDTB_PRINT; // Menu Item ID
  1389. cszMenuItem = GetStringResource(IDS_OPTION_PRINT); // the string to display for the menu item
  1390. mii.dwTypeData = cszMenuItem.psz;
  1391. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1392. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1393. // --- end fixed menu
  1394. if (!g_fIE3 && m_phmData && m_phmData->m_pTitleCollection && m_phmData->m_pTitleCollection->m_pSearchHighlight) {
  1395. // Add search term hiliting to the options menu.
  1396. mii.wID = IDTB_HILITE; // Menu Item ID
  1397. cszMenuItem = GetStringResource(IDS_OPTION_HILITING_OFF); // the string to display for the menu item
  1398. mii.dwTypeData = cszMenuItem.psz;
  1399. mii.cch = (DWORD)strlen( mii.dwTypeData ); // length of the string.
  1400. HxInsertMenuItem(m_hMenuOptions, cMenuItems++, TRUE, &mii);
  1401. }
  1402. if ( fsToolBarFlags & HHWIN_BUTTON_OPTIONS && cMenuItems) {
  1403. pabtn[cButtons].iBitmap = 10;
  1404. pabtn[cButtons].idCommand = IDTB_OPTIONS;
  1405. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1406. pabtn[cButtons].fsStyle = TBSTYLE_DROPDOWN;
  1407. pabtn[cButtons].iString = cButtons;
  1408. m_ptblBtnStrings->AddString(GetStringResource(IDTB_OPTIONS));
  1409. if ( cMenuItems )
  1410. pabtn[cButtons].dwData = (DWORD_PTR)m_hMenuOptions;
  1411. cButtons++;
  1412. }
  1413. if (fsToolBarFlags & HHWIN_BUTTON_NOTES) {
  1414. pabtn[cButtons].iBitmap = 11;
  1415. pabtn[cButtons].idCommand = IDTB_NOTES;
  1416. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1417. pabtn[cButtons].iString = cButtons;
  1418. m_ptblBtnStrings->AddString(GetStringResource(IDTB_NOTES));
  1419. cButtons++;
  1420. }
  1421. if (fsToolBarFlags & HHWIN_BUTTON_CONTENTS) {
  1422. pabtn[cButtons].iBitmap = 15;
  1423. pabtn[cButtons].idCommand = IDTB_CONTENTS;
  1424. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1425. pabtn[cButtons].iString = cButtons;
  1426. m_ptblBtnStrings->AddString(GetStringResource(IDTB_CONTENTS));
  1427. cButtons++;
  1428. }
  1429. if (fsToolBarFlags & HHWIN_BUTTON_INDEX) {
  1430. pabtn[cButtons].iBitmap = 16;
  1431. pabtn[cButtons].idCommand = IDTB_INDEX;
  1432. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1433. pabtn[cButtons].iString = cButtons;
  1434. m_ptblBtnStrings->AddString(GetStringResource(IDTB_INDEX));
  1435. cButtons++;
  1436. }
  1437. if (fsToolBarFlags & HHWIN_BUTTON_SEARCH) {
  1438. pabtn[cButtons].iBitmap = 5;
  1439. pabtn[cButtons].idCommand = IDTB_SEARCH;
  1440. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1441. pabtn[cButtons].iString = cButtons;
  1442. m_ptblBtnStrings->AddString(GetStringResource(IDTB_SEARCH));
  1443. cButtons++;
  1444. }
  1445. if (fsToolBarFlags & HHWIN_BUTTON_HISTORY) {
  1446. pabtn[cButtons].iBitmap = 19;
  1447. pabtn[cButtons].idCommand = IDTB_HISTORY;
  1448. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1449. pabtn[cButtons].iString = cButtons;
  1450. m_ptblBtnStrings->AddString(GetStringResource(IDTB_HISTORY));
  1451. cButtons++;
  1452. }
  1453. if (fsToolBarFlags & HHWIN_BUTTON_FAVORITES) {
  1454. pabtn[cButtons].iBitmap = 6;
  1455. pabtn[cButtons].idCommand = IDTB_FAVORITES;
  1456. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1457. pabtn[cButtons].iString = cButtons;
  1458. m_ptblBtnStrings->AddString(GetStringResource(IDTB_FAVORITES));
  1459. cButtons++;
  1460. }
  1461. if ((fsToolBarFlags & HHWIN_BUTTON_JUMP1) && !(IsProperty(HHWIN_PROP_MENU))) {
  1462. pabtn[cButtons].iBitmap = 17;
  1463. pabtn[cButtons].idCommand = IDTB_JUMP1;
  1464. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1465. pabtn[cButtons].iString = cButtons;
  1466. m_ptblBtnStrings->AddString(pszJump1 ? pszJump1 : "");
  1467. cButtons++;
  1468. }
  1469. if ((fsToolBarFlags & HHWIN_BUTTON_JUMP2) && !(IsProperty(HHWIN_PROP_MENU))) {
  1470. pabtn[cButtons].iBitmap = 18;
  1471. pabtn[cButtons].idCommand = IDTB_JUMP2;
  1472. pabtn[cButtons].fsState = TBSTATE_ENABLED;
  1473. pabtn[cButtons].iString = cButtons;
  1474. m_ptblBtnStrings->AddString(pszJump2 ? pszJump2 : "");
  1475. cButtons++;
  1476. }
  1477. return cButtons;
  1478. }
  1479. // No longer used, but we'll keep in around awhile just in case
  1480. /*
  1481. static void FixDupMenuAccelerator(const CTable* ptbl, PSTR pszMenu)
  1482. {
  1483. int i;
  1484. PSTR pszOrg;
  1485. PSTR pszTmp = StrChr(pszMenu, ACCESS_KEY);
  1486. if (!pszTmp) {
  1487. MoveMemory(pszMenu + 1, pszMenu, strlen(pszMenu) + 1);
  1488. *pszMenu = ACCESS_KEY;
  1489. pszTmp = pszMenu;
  1490. }
  1491. pszOrg = pszTmp;
  1492. SHORT ch = VkKeyScan((BYTE) CharLower((LPSTR) pszTmp[1]));
  1493. for (i = 1; i <= ptbl->CountStrings(); i++) {
  1494. // check for a duplicate accelerator key
  1495. PCSTR psz = StrChr(ptbl->GetPointer(i), ACCESS_KEY);
  1496. if (VkKeyScan((BYTE) CharLower((LPSTR) psz[1])) == ch) {
  1497. strcpy(pszTmp, pszTmp + 1); // remove the accelerator
  1498. pszTmp++;
  1499. if (!*pszTmp) {
  1500. // End of string, nothing we can do
  1501. MoveMemory(pszOrg + 1, pszOrg, strlen(pszOrg) + 1);
  1502. *pszOrg = ACCESS_KEY;
  1503. return;
  1504. }
  1505. else {
  1506. MoveMemory(pszTmp + 1, pszTmp, strlen(pszTmp) + 1);
  1507. *pszTmp = ACCESS_KEY;
  1508. ch = VkKeyScan((BYTE) CharLower((LPSTR) pszTmp[1]));
  1509. i = 0; // start over
  1510. }
  1511. }
  1512. }
  1513. }
  1514. */
  1515. #ifndef TCS_FLATBUTTONS
  1516. #define TCS_FLATBUTTONS 0x0008
  1517. #endif
  1518. //////////////////////////////////////////////////////////////////////////////////
  1519. //
  1520. // IsValidTab(int iTab) --- Index returned from tabOrder.
  1521. //
  1522. BOOL
  1523. CHHWinType::IsValidNavPane(int iTab)
  1524. {
  1525. //REVIEW:: Assumes that the tabs have not been re-ordered!
  1526. BOOL bResult = FALSE ;
  1527. // We only have valid tabs if we are a TRI_PANE.
  1528. if (IsProperty(HHWIN_PROP_TRI_PANE))
  1529. {
  1530. switch(iTab)
  1531. {
  1532. case HH_TAB_CONTENTS:
  1533. if (!IsEmptyString(pszToc) && tabOrder[HH_TAB_CONTENTS] != 255)
  1534. bResult = TRUE ;
  1535. break;
  1536. case HH_TAB_INDEX:
  1537. if (!IsEmptyString(pszIndex) && tabOrder[HH_TAB_INDEX] != 255)
  1538. bResult = TRUE ;
  1539. break;
  1540. case HH_TAB_SEARCH:
  1541. if ((fsWinProperties & HHWIN_PROP_TAB_SEARCH) /*&& m_phmData && m_phmData->m_sysflags.fFTI*/)
  1542. {
  1543. //BUGBUG: m_phmdata isn't always valid when we are getting called. See HH_SET_WIN_TYPE
  1544. bResult = TRUE ;
  1545. }
  1546. break;
  1547. case HH_TAB_HISTORY:
  1548. if (fsWinProperties & HHWIN_PROP_TAB_HISTORY)
  1549. bResult = TRUE ;
  1550. break;
  1551. case HH_TAB_FAVORITES:
  1552. if (fsWinProperties & HHWIN_PROP_TAB_FAVORITES)
  1553. bResult = TRUE ;
  1554. break;
  1555. #ifdef __TEST_CUSTOMTAB__
  1556. case HH_TAB_AUTHOR:
  1557. return IsHelpAuthor(GetHwnd());
  1558. #endif
  1559. default:
  1560. if (iTab >= HH_TAB_CUSTOM_FIRST && iTab <= HH_TAB_CUSTOM_LAST)
  1561. {
  1562. if (fsWinProperties & (HHWIN_PROP_TAB_CUSTOM1 << (iTab - HH_TAB_CUSTOM_FIRST)))
  1563. {
  1564. bResult = TRUE;
  1565. }
  1566. }
  1567. }
  1568. }
  1569. return bResult;
  1570. }
  1571. //////////////////////////////////////////////////////////////////////////////////
  1572. //
  1573. // GetValidNavPane --- Returns the index of the first valid tab it finds. -1 if no valid tabs.
  1574. //
  1575. int
  1576. CHHWinType::GetValidNavPane()
  1577. {
  1578. for (int i = 0 ; i < HH_MAX_TABS+1 ; i++)
  1579. {
  1580. if (IsValidNavPane(i))
  1581. {
  1582. return i;
  1583. }
  1584. }
  1585. return -1 ;
  1586. }
  1587. //////////////////////////////////////////////////////////////////////////////////
  1588. //
  1589. // GetNavPaneCount --- Counts the number of valid navigation panes
  1590. //
  1591. int CHHWinType::GetValidNavPaneCount()
  1592. {
  1593. int count = 0 ;
  1594. for (int i = 0 ; i < HH_MAX_TABS+1 ; i++)
  1595. {
  1596. if (IsValidNavPane(i))
  1597. {
  1598. count++;
  1599. }
  1600. }
  1601. return count;
  1602. }
  1603. void CHHWinType::OnNavigateComplete(LPCTSTR pszUrl)
  1604. {
  1605. // Update the Bookmark pane if it exists.
  1606. if (curNavType == HH_TAB_FAVORITES && m_aNavPane[HH_TAB_FAVORITES])
  1607. {
  1608. // Here we are synchronizing the current topic edit control in the bookmarks pane
  1609. // witht he current topic.
  1610. m_aNavPane[HH_TAB_FAVORITES]->Synchronize(NULL) ;
  1611. }
  1612. // Get a pointer to the toc if it exists.
  1613. CToc* ptoc = NULL ;
  1614. if (m_aNavPane[HH_TAB_CONTENTS])
  1615. {
  1616. ptoc = reinterpret_cast<CToc*>(m_aNavPane[HH_TAB_CONTENTS]) ; // HACKHACK: Should use dynamic cast, but no RTTI.
  1617. }
  1618. //
  1619. // Check if zooming is supported on this page.
  1620. //
  1621. if ( IsValidWindow(hwndToolBar) )
  1622. {
  1623. if ( IsProperty(HHWIN_PROP_MENU) || fsToolBarFlags & HHWIN_BUTTON_ZOOM )
  1624. {
  1625. HRESULT hr = GetZoomMinMax();
  1626. if( fsToolBarFlags & HHWIN_BUTTON_ZOOM ) {
  1627. if ( hr == S_OK )
  1628. SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_ZOOM, TRUE);
  1629. else
  1630. SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDTB_ZOOM, FALSE);
  1631. }
  1632. }
  1633. }
  1634. if (idNotify) {
  1635. HHN_NOTIFY hhcomp;
  1636. hhcomp.hdr.hwndFrom = hwndHelp;
  1637. hhcomp.hdr.idFrom = idNotify;
  1638. hhcomp.hdr.code = HHN_NAVCOMPLETE;
  1639. hhcomp.pszUrl = pszUrl;
  1640. if (IsWindow(hwndCaller))
  1641. {
  1642. SendMessage(hwndCaller, WM_NOTIFY, idNotify, (LPARAM) &hhcomp);
  1643. }
  1644. }
  1645. }
  1646. // NOTE - call the following in your OnNavigateComplete event handler to update the minmax. Do not do
  1647. // it when you navigate, do it when the control fires the OnNavigate event - by then you
  1648. // should be able to get the minmax stuff.
  1649. //***************************************************************************
  1650. //
  1651. // Member: CHHWinType:::GetZoomMinMax
  1652. //
  1653. // Synopsis: sets m_iZoomMin, and Most - gets called whenever we
  1654. // navigate to a document. Note that many document types
  1655. // do not support Zoom, and so this fails. This is OK,
  1656. // and expected.
  1657. //
  1658. // Returns: HRESULT
  1659. //
  1660. //***************************************************************************
  1661. HRESULT CHHWinType::GetZoomMinMax(void)
  1662. {
  1663. VARIANT vararg;
  1664. HRESULT hr;
  1665. ::VariantInit(&vararg);
  1666. V_VT(&vararg) = VT_I4;
  1667. V_I4(&vararg) = 0;
  1668. m_iZoom = m_iZoomMin = m_iZoomMax = 0;
  1669. hr = m_pCIExpContainer->m_pIE3CmdTarget->Exec(0, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
  1670. 0, &vararg);
  1671. #if 0
  1672. if (hr)
  1673. {
  1674. OLECMDTEXT oct;
  1675. OLECMD olecmd;
  1676. olecmd.cmdID = OLECMDID_ZOOM;
  1677. olecmd.cmdf = 0;
  1678. hr = m_pCIExpContainer->m_pIE3CmdTarget->QueryStatus(NULL, 1, &olecmd, &oct);
  1679. }
  1680. #endif
  1681. if (hr)
  1682. return hr;
  1683. if (VT_I4 == V_VT(&vararg))
  1684. m_iZoom = V_I4(&vararg);
  1685. ::VariantClear(&vararg);
  1686. V_VT(&vararg) = VT_I4;
  1687. V_I4(&vararg) = 0;
  1688. hr = m_pCIExpContainer->m_pIE3CmdTarget->Exec(0, OLECMDID_GETZOOMRANGE, OLECMDEXECOPT_DONTPROMPTUSER,
  1689. 0, &vararg);
  1690. if (hr)
  1691. return hr;
  1692. if (VT_I4 == V_VT(&vararg))
  1693. {
  1694. // I looked at the IE code for this - this cast is necessary.
  1695. m_iZoomMin = (INT)(SHORT)LOWORD(V_I4(&vararg));
  1696. m_iZoomMax = (INT)(SHORT)HIWORD(V_I4(&vararg));
  1697. }
  1698. return hr;
  1699. }
  1700. //***************************************************************************
  1701. //
  1702. // Member: CHHWinType::ZoomIn
  1703. //
  1704. // Synopsis: Zooms in one - whenever we navigate to a new document,
  1705. // we get the zoom range for that document. ZoomIn will
  1706. // cycle thru that zoom range, from small to large, wrapping
  1707. // back to smallest again.
  1708. //
  1709. // Returns: nothing, fails quietly (by design).
  1710. //
  1711. //***************************************************************************
  1712. void CHHWinType::ZoomIn(void)
  1713. {
  1714. INT iZoomNew = m_iZoom + 1;
  1715. if (iZoomNew > m_iZoomMax)
  1716. iZoomNew = m_iZoomMin;
  1717. Zoom(iZoomNew);
  1718. }
  1719. //***************************************************************************
  1720. //
  1721. // Member: CHHWinType::ZoomOut
  1722. //
  1723. // Synopsis: Zooms out one - whenever we navigate to a new document,
  1724. // we get the zoom range for that document. ZoomOut will
  1725. // cycle thru that zoom range, from large to small, wrapping
  1726. // back to largest again.
  1727. //
  1728. // Returns: nothing, fails quietly (by design).
  1729. //
  1730. //***************************************************************************
  1731. void CHHWinType::ZoomOut(void)
  1732. {
  1733. INT iZoomNew = m_iZoom - 1;
  1734. if (iZoomNew < m_iZoomMin)
  1735. iZoomNew = m_iZoomMax;
  1736. Zoom(iZoomNew);
  1737. }
  1738. //***************************************************************************
  1739. //
  1740. // Member: CHHWinType::_Zoom
  1741. //
  1742. // Synopsis: helper function that manages zoomin and zoomout.
  1743. //
  1744. // Arguments: [iZoom] -- value for new zoom.
  1745. //
  1746. // Requires: iZoom needs to be in a valid range for the current docobj.
  1747. // current docobj must support IOleCommandTarget
  1748. // it will fail if current docobj doesn't respond to
  1749. // OLECMDID_ZOOM.
  1750. //
  1751. // Returns: HRESULT
  1752. //
  1753. //***************************************************************************
  1754. HRESULT CHHWinType::Zoom(int iZoom)
  1755. {
  1756. HRESULT hr;
  1757. VARIANTARG varIn;
  1758. VARIANTARG varOut;
  1759. // initialize the argument to Exec.
  1760. ::VariantInit(&varIn);
  1761. V_VT(&varIn) = VT_I4;
  1762. V_I4(&varIn) = iZoom;
  1763. // init the out variant. This probably isn't necessary, but
  1764. // doesn't hurt - it's defensive as opposed to passing 0.
  1765. //
  1766. ::VariantInit(&varOut);
  1767. hr = m_pCIExpContainer->m_pIE3CmdTarget->Exec(0, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER,
  1768. &varIn, &varOut);
  1769. if (SUCCEEDED(hr))
  1770. m_iZoom = iZoom;
  1771. return hr;
  1772. }
  1773. //***************************************************************************
  1774. //
  1775. // Member: CHHWinType::OnNext
  1776. //
  1777. // Synopsis: Executes a next in TOC navigation.
  1778. //
  1779. // Arguments: bDoJump - BOOL value indicates weather to execute a jump or not.
  1780. //
  1781. // Returns: BOOL - TRUE on success, FALSE on failure.
  1782. //
  1783. //***************************************************************************
  1784. BOOL CHHWinType::OnTocNext(BOOL bDoJump)
  1785. {
  1786. CExTitle *pTitle= NULL;
  1787. CStr cszUrl;
  1788. char szURL[MAX_URL];
  1789. CTreeNode* pTreeNode = NULL, *pTocNext = NULL, *pTocKid = NULL;
  1790. CToc* pToc = NULL;
  1791. DWORD dwSlot;
  1792. BOOL bReturn = FALSE;
  1793. if ( !m_phmData || !m_phmData->m_pTitleCollection )
  1794. return FALSE;
  1795. if (! SUCCEEDED(m_phmData->m_pTitleCollection->GetCurrentTocNode(&pTreeNode)) )
  1796. {
  1797. m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
  1798. if (cszUrl.psz != NULL)
  1799. {
  1800. strcpy(szURL, cszUrl);
  1801. if ( SUCCEEDED(m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle)) )
  1802. pTitle->GetURLTreeNode(szURL, &pTreeNode);
  1803. }
  1804. }
  1805. if ( pTreeNode )
  1806. {
  1807. if ( pTocNext = m_phmData->m_pTitleCollection->GetNextTopicNode(pTreeNode, &dwSlot) )
  1808. {
  1809. // Ok now we can execute the jump and sync!
  1810. //
  1811. if ( bDoJump )
  1812. {
  1813. pTocNext->GetURL(szURL, sizeof(szURL));
  1814. m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle);
  1815. m_phmData->m_pTitleCollection->SetTopicSlot(dwSlot, ((CExNode*)pTocNext)->m_Node.dwOffsTopic, pTitle);
  1816. ChangeHtmlTopic(szURL, *this);
  1817. if (! IsProperty(HHWIN_PROP_AUTO_SYNC) && (pToc = (CToc*)m_aNavPane[HH_TAB_CONTENTS]) )
  1818. pToc->Synchronize(szURL);
  1819. }
  1820. delete pTocNext;
  1821. bReturn = TRUE;
  1822. }
  1823. delete pTreeNode;
  1824. }
  1825. return bReturn;
  1826. }
  1827. //***************************************************************************
  1828. //
  1829. // Member: CHHWinType::OnPrev
  1830. //
  1831. // Synopsis: Executes a previous in TOC navigation.
  1832. //
  1833. // Arguments: bDoJump - BOOL value indicates weather to execute a jump or not.
  1834. //
  1835. // Returns: BOOL - TRUE on success, FALSE on failure.
  1836. //
  1837. //***************************************************************************
  1838. BOOL CHHWinType::OnTocPrev(BOOL bDoJump)
  1839. {
  1840. CExTitle *pTitle = NULL;
  1841. CStr cszUrl;
  1842. char szURL[MAX_URL];
  1843. CTreeNode* pTreeNode = NULL, *pTocPrev = NULL;
  1844. CToc* pToc = NULL;
  1845. DWORD dwSlot;
  1846. BOOL bReturn = FALSE;
  1847. if ( !m_phmData || !m_phmData->m_pTitleCollection )
  1848. return FALSE;
  1849. if (! SUCCEEDED(m_phmData->m_pTitleCollection->GetCurrentTocNode(&pTreeNode)) )
  1850. {
  1851. m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
  1852. if (cszUrl.psz != NULL)
  1853. {
  1854. strcpy(szURL, cszUrl);
  1855. if ( SUCCEEDED(m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle)) )
  1856. pTitle->GetURLTreeNode(szURL, &pTreeNode);
  1857. }
  1858. }
  1859. if ( pTreeNode )
  1860. {
  1861. // We have the TOC node, now get it's next.
  1862. //
  1863. if ( pTocPrev = m_phmData->m_pTitleCollection->GetPrev(pTreeNode, &dwSlot) )
  1864. {
  1865. //
  1866. // Ok now, we can execute the jump and sync!
  1867. //
  1868. if ( bDoJump )
  1869. {
  1870. pTocPrev->GetURL(szURL, sizeof(szURL));
  1871. m_phmData->m_pTitleCollection->URL2ExTitle(szURL, &pTitle);
  1872. m_phmData->m_pTitleCollection->SetTopicSlot(dwSlot, ((CExNode*)pTocPrev)->m_Node.dwOffsTopic, pTitle);
  1873. ChangeHtmlTopic(szURL, *this);
  1874. if (! IsProperty(HHWIN_PROP_AUTO_SYNC) && (pToc = (CToc*)m_aNavPane[HH_TAB_CONTENTS]) )
  1875. pToc->Synchronize(szURL);
  1876. }
  1877. bReturn = TRUE;
  1878. delete pTocPrev;
  1879. }
  1880. delete pTreeNode;
  1881. }
  1882. return bReturn;
  1883. }
  1884. /***************************************************************************
  1885. FUNCTION: FindWindowType
  1886. PURPOSE: Find whether the window type exists and has already created
  1887. a window
  1888. PARAMETERS:
  1889. pszType -- window type to look for.
  1890. hwndCaller -- who the caller is
  1891. pszOwnerFile -- CHM file which defines this window type.
  1892. RETURNS:
  1893. -1 if window type not found, or found but no window created
  1894. position in pahwnd if window found
  1895. COMMENTS:
  1896. MODIFICATION DATES:
  1897. 27-Feb-1996 [ralphw]
  1898. 27-Apr-1998 [dalero] Added pszOwnerFile parameter
  1899. ***************************************************************************/
  1900. CHHWinType* FindWindowType(PCSTR pszType, HWND hwndCaller, LPCTSTR pszOwnerFile)
  1901. {
  1902. if (IsEmptyString(pszType))
  1903. {
  1904. return NULL;
  1905. }
  1906. // Skip window separator if present.
  1907. if (*pszType == WINDOW_SEPARATOR)
  1908. {
  1909. pszType++;
  1910. if (IsEmptyString(pszType))
  1911. {
  1912. return NULL;
  1913. }
  1914. }
  1915. // We ignore the owner file if the file is URL or the window type is global.
  1916. bool bIgnoreOwnerFile = IsGlobalWinType(pszType) || IsHttp(pszOwnerFile) ;
  1917. if (!bIgnoreOwnerFile )
  1918. {
  1919. // If its not global, we need a filename.
  1920. if (IsEmptyString(pszOwnerFile))
  1921. {
  1922. return NULL ;
  1923. }
  1924. }
  1925. for (int i = 0; i < g_cWindowSlots; i++)
  1926. {
  1927. if (pahwnd[i] && pahwnd[i]->pszType != NULL
  1928. && lstrcmpi(pszType, pahwnd[i]->pszType) == 0)
  1929. {
  1930. // Found the window type.
  1931. // If its a global window type, we are done.
  1932. if (bIgnoreOwnerFile)
  1933. {
  1934. break ;
  1935. }
  1936. else
  1937. {
  1938. // Call IsCompiledHtmlFile to get the filename into a consistant format.
  1939. CStr cszCompiled(pszOwnerFile);
  1940. if (NormalizeFileName(cszCompiled))
  1941. {
  1942. // Is this window type in the correct CHM file.
  1943. ASSERT(pahwnd[i]->GetOwnerFile());
  1944. if (pahwnd[i]->GetOwnerFile()
  1945. && lstrcmpi(cszCompiled, pahwnd[i]->GetOwnerFile()) == 0)
  1946. {
  1947. break;
  1948. }
  1949. }
  1950. }
  1951. }
  1952. }
  1953. if (i >= g_cWindowSlots)
  1954. {
  1955. return NULL;
  1956. }
  1957. //REVIEW: 28-Apr-98 [dalero] This seems dangerous...
  1958. if (hwndCaller)
  1959. {
  1960. pahwnd[i]->hwndCaller = hwndCaller; // In case it changed
  1961. }
  1962. return pahwnd[i];
  1963. }
  1964. /***************************************************************************
  1965. FUNCTION: FindOrCreateWindowSlot
  1966. PURPOSE: Find whether the window type exists and create it if not.
  1967. PARAMETERS:
  1968. pszType -- window type to look for.
  1969. hwndCaller -- who the caller is
  1970. pszOwnerFile -- the file which defines this window type.
  1971. if pszType has the GLOBAL_WINDOWTYPE_PREFIX, the pszOwnerFile is not used.
  1972. RETURNS:
  1973. Return a pointer to the window type. May be an empty one just created.
  1974. COMMENTS:
  1975. MODIFICATION DATES:
  1976. 27 Apr 98 [DaleRo] Added pszOwnerFile parameter
  1977. ***************************************************************************/
  1978. CHHWinType* FindOrCreateWindowSlot(LPCTSTR pszType, LPCTSTR pszOwnerFile)
  1979. {
  1980. ASSERT(pahwnd != NULL) ;
  1981. // pszType cannot be NULL or emptry.
  1982. if (IsEmptyString(pszType))
  1983. {
  1984. return NULL;
  1985. }
  1986. // Skip window type pointer if present.
  1987. if (*pszType == WINDOW_SEPARATOR)
  1988. {
  1989. pszType++;
  1990. if (IsEmptyString(pszType))
  1991. {
  1992. return NULL ;
  1993. }
  1994. }
  1995. // We ignore the owning file if...
  1996. bool bIgnoreOwnerFile = IsGlobalWinType(pszType) // Its a global window type
  1997. || IsHttp(pszOwnerFile); // or an Http address. Ideally, the window type has been registered to a particular chm...
  1998. const char* pOwner = ""; // Empty string is stored in the cases where we ignore wintypes... CHHWinType will copy...
  1999. CStr cszOwner(pszOwnerFile);
  2000. if (!bIgnoreOwnerFile)
  2001. {
  2002. // If its not a global window type, it must have a valid file.
  2003. if (!NormalizeFileName(cszOwner))
  2004. {
  2005. return NULL ;
  2006. }
  2007. // pOwner is NULL if its a global wintype. Its non-null otherwise.
  2008. pOwner = cszOwner;
  2009. }
  2010. // Check to see if this window type already exists.
  2011. CHHWinType* phh = FindWindowType(pszType, NULL, cszOwner);
  2012. if (phh)
  2013. {
  2014. return phh;
  2015. }
  2016. // The window type did not exist. So, find an empty slot to put it in.
  2017. for (int i = 0; i < g_cWindowSlots; i++)
  2018. {
  2019. if (pahwnd[i] == NULL)
  2020. {
  2021. break;
  2022. }
  2023. }
  2024. // Allocate more space for the array if we are out of room.
  2025. if (i >= g_cWindowSlots)
  2026. {
  2027. g_cWindowSlots += 5;
  2028. CHHWinType** paNew = (CHHWinType**) lcReAlloc(pahwnd,
  2029. g_cWindowSlots * sizeof(CHHWinType*));
  2030. memset( paNew + (g_cWindowSlots-5), 0, 5 * sizeof(CHHWinType*) );
  2031. if (paNew == NULL)
  2032. {
  2033. OOM();
  2034. return FALSE;
  2035. }
  2036. pahwnd = paNew;
  2037. }
  2038. // Create the new window type object. Note that it is not initialized.
  2039. pahwnd[i] = new CHHWinType(pOwner);
  2040. return pahwnd[i];
  2041. }
  2042. /***************************************************************************
  2043. FUNCTION: FindCurWindow
  2044. PURPOSE: Find a current window displayed
  2045. PARAMETERS:
  2046. RETURNS:
  2047. COMMENTS:
  2048. This function is random. It picks the first window displayed.
  2049. Depending on how HHCTRL has been called any window could be first.
  2050. MODIFICATION DATES:
  2051. 09-Nov-1997 [ralphw]
  2052. 03-Mar-1998 [dalero]
  2053. ***************************************************************************/
  2054. CHHWinType* FindCurWindow()
  2055. {
  2056. ASSERT(pahwnd != NULL) ;
  2057. for (int i = 0; i < g_cWindowSlots; i++)
  2058. {
  2059. if (pahwnd[i] != NULL)
  2060. {
  2061. return pahwnd[i];
  2062. }
  2063. }
  2064. return NULL;
  2065. }
  2066. ///////////////////////////////////////////////////////////
  2067. //
  2068. // Delete all of the CHHWinType structures for this process.
  2069. //
  2070. void DeleteWindows()
  2071. {
  2072. ASSERT(pahwnd != NULL) ;
  2073. for (int i = 0; i < g_cWindowSlots; i++)
  2074. {
  2075. if (pahwnd[i] != NULL)
  2076. {
  2077. CHHWinType* phh = pahwnd[i] ;
  2078. //pahwnd[i] = NULL ; --- Set to null in the destructor...
  2079. if (IsWindow(phh->hwndHelp))
  2080. {
  2081. DestroyWindow(phh->hwndHelp) ;
  2082. }
  2083. else
  2084. {
  2085. delete phh ;
  2086. }
  2087. }
  2088. }
  2089. }
  2090. ///////////////////////////////////////////////////////////
  2091. //
  2092. // Functions which operate on the m_aNavPane array.
  2093. //
  2094. ///////////////////////////////////////////////////////////
  2095. //
  2096. // CreateNavPane
  2097. //
  2098. static const WCHAR txtAuthorTab[] = L"HHAuthorTab.CustPane";
  2099. void
  2100. CHHWinType::CreateNavPane(int iPane)
  2101. {
  2102. // Is this a valid pane number?
  2103. if (iPane > c_NUMNAVPANES || iPane < 0)
  2104. {
  2105. ASSERT(0) ;
  2106. return ;
  2107. }
  2108. // Has pane already been created?
  2109. if (m_aNavPane[iPane])
  2110. {
  2111. return ; // Already created.
  2112. }
  2113. // Create the pane.
  2114. switch(iPane)
  2115. {
  2116. case HHWIN_NAVTYPE_TOC:
  2117. CreateToc();
  2118. break ;
  2119. case HHWIN_NAVTYPE_INDEX:
  2120. CreateIndex();
  2121. break ;
  2122. case HHWIN_NAVTYPE_SEARCH:
  2123. CreateSearchTab();
  2124. break;
  2125. case HHWIN_NAVTYPE_FAVORITES:
  2126. CreateBookmarksTab() ;
  2127. break ;
  2128. #if 0
  2129. case HHWIN_NAVTYPE_HISTORY:
  2130. //CreateHistoryTab();
  2131. ItDoesntWork() ;
  2132. break ;
  2133. #endif
  2134. #ifdef __TEST_CUSTOMTAB__
  2135. case HHWIN_NAVTYPE_AUTHOR:
  2136. CreateCustomTab(iPane, txtAuthorTab);
  2137. break;
  2138. #endif
  2139. default:
  2140. if (iPane < HH_MAX_TABS+1 && iPane >= HHWIN_NAVTYPE_CUSTOM_FIRST)
  2141. {
  2142. // We have a custom tab.
  2143. EXTENSIBLE_TAB* pExtTab = GetExtTab(iPane - HH_TAB_CUSTOM_FIRST);
  2144. if (pExtTab)
  2145. {
  2146. CWStr cwsz(pExtTab->pszProgId);
  2147. CreateCustomTab(iPane, cwsz);
  2148. }
  2149. }
  2150. else
  2151. {
  2152. ASSERT_COMMENT(0, "illegal tab index");
  2153. }
  2154. }
  2155. }
  2156. /***************************************************************************
  2157. FUNCTION: doSelectTab
  2158. PURPOSE: changes the current navigation tab
  2159. PARAMETERS:
  2160. RETURNS:
  2161. TODO
  2162. COMMENTS:
  2163. MODIFICATION DATES:
  2164. 27-Feb-1996 [ralphw]
  2165. 09-Nov-1997 [ralphw] Moved to CHHWinType
  2166. ***************************************************************************/
  2167. void
  2168. CHHWinType::doSelectTab(int newTabIndex)
  2169. {
  2170. if ( newTabIndex < 0 )
  2171. return ;
  2172. // Make sure we have tabs before we switch or toggle.
  2173. if (!IsValidNavPane(curNavType))
  2174. return ;
  2175. // make sure the nav pane is shown
  2176. if (IsExpandedNavPane() == FALSE)
  2177. ToggleExpansion();
  2178. //
  2179. // <mc> 4/10/98 Bug 4701 - I've moved the m_pTabCtrl == NULL check to after the ToggleExpansion() call
  2180. // done above because it's legitimate to have a NULL m_pTabCtrl pointer if we get to this code and the
  2181. // nav pane has never been shown. The ToggleExpansion() call will instantiate m_pTabCtrl if the nav
  2182. // pane is hidden and has never been shown.
  2183. //
  2184. if ( m_pTabCtrl == NULL )
  2185. return; // REVIEW: This is null when there isn't an FTS. See BUG 462 in RAID database.
  2186. // Get the index of the currently selected tab.
  2187. int oldTabIndex = GetCurrentNavPaneIndex() ;
  2188. // Only change the tab if its not the current one.
  2189. if (oldTabIndex != newTabIndex)
  2190. {
  2191. // This code was copied from WM_NOTIFY in wndproc.cpp. This should become common.
  2192. ASSERT(curNavType >= 0 && curNavType < c_NUMNAVPANES) ;
  2193. // Hide the current tab.
  2194. if (m_aNavPane[curNavType])
  2195. {
  2196. m_aNavPane[curNavType]->HideWindow();
  2197. }
  2198. // Code throughout HHCtrl assumes that HH_NAVTYPE_* == HH_TAB_*.
  2199. // but doesn't assert it anywhere. So I'm going to assert it here.
  2200. ASSERT(HHWIN_NAVTYPE_SEARCH == HH_TAB_SEARCH) ;
  2201. ASSERT(HHWIN_NAVTYPE_TOC == HH_TAB_CONTENTS) ;
  2202. ASSERT(HHWIN_NAVTYPE_INDEX == HH_TAB_INDEX);
  2203. ASSERT(HHWIN_NAVTYPE_FAVORITES == HH_TAB_FAVORITES);
  2204. #ifdef _INTERNAL
  2205. ASSERT(HHWIN_NAVTYPE_HISTORY == HH_TAB_HISTORY);
  2206. #endif
  2207. // Select the new navigation method.
  2208. curNavType = newTabIndex;
  2209. // Select the new current tab.
  2210. int iNewTabCtrlIndex = GetTabIndexFromNavPaneIndex(newTabIndex) ;
  2211. ASSERT(iNewTabCtrlIndex >= 0) ;
  2212. int iRet = TabCtrl_SetCurSel(m_pTabCtrl->hWnd(), iNewTabCtrlIndex) ;
  2213. ASSERT(iRet >= 0) ;
  2214. ASSERT(tabOrder[iRet] == oldTabIndex) ;
  2215. //REVIEW: If I've ever seen a use for virtual functions...
  2216. // Create the new pane for the new current tab if necessary.
  2217. CreateNavPane(newTabIndex) ;
  2218. if (m_aNavPane[newTabIndex])
  2219. {
  2220. m_aNavPane[newTabIndex]->ResizeWindow();
  2221. m_aNavPane[newTabIndex]->ShowWindow();
  2222. }
  2223. // Update the tab window
  2224. ::UpdateWindow(m_pTabCtrl->hWnd()) ;
  2225. } //if
  2226. if (m_aNavPane[newTabIndex]) m_aNavPane[newTabIndex]->SetDefaultFocus();
  2227. if ( m_pCIExpContainer )
  2228. m_pCIExpContainer->UIDeactivateIE(); // shdocvw is loosing focus need to uideactivate here.
  2229. }
  2230. ///////////////////////////////////////////////////////////////////////////////
  2231. //
  2232. // Restore if minimzied window, and set focus to the window
  2233. //
  2234. void CHHWinType::SetActiveHelpWindow(void)
  2235. {
  2236. if (IsIconic(*this))
  2237. ShowWindow(*this, SW_RESTORE);
  2238. SetForegroundWindow(*this);
  2239. // SetFocus(*this);
  2240. }
  2241. ///////////////////////////////////////////////////////////////////////////////
  2242. //
  2243. // Finds the currently selected tab in the tab control. It then looks in the
  2244. // tabOrder array to find out the index into the array of nav panes for this control.
  2245. //
  2246. int
  2247. CHHWinType::GetCurrentNavPaneIndex()
  2248. {
  2249. if( !m_pTabCtrl )
  2250. return -1;
  2251. // REVIEW: All of this mapping between tabctrl index and nav pane index should be
  2252. // hidden inside of the tabctrl...
  2253. int index = -1 ;
  2254. if (m_pTabCtrl && IsWindow(m_pTabCtrl->hWnd()))
  2255. {
  2256. index = (int)::SendMessage(m_pTabCtrl->hWnd(), TCM_GETCURSEL, 0, 0);
  2257. index = tabOrder[index] ;
  2258. }
  2259. return index ;
  2260. }
  2261. ///////////////////////////////////////////////////////////////////////////////
  2262. //
  2263. // Finds the index of the tab on the tabctrl which co-responds to a particular
  2264. // nav pane.
  2265. //
  2266. int
  2267. CHHWinType::GetTabIndexFromNavPaneIndex(int iNavPaneIndex)
  2268. {
  2269. for(int i = 0 ; i < HH_MAX_TABS+1 ; i++)
  2270. {
  2271. //REVIEW: Not all of these entries are valid. Possible to get a bogus hit. See reorder tab.
  2272. if( tabOrder[i] == iNavPaneIndex)
  2273. {
  2274. return i ;
  2275. }
  2276. }
  2277. return -1 ;
  2278. }
  2279. ///////////////////////////////////////////////////////////////////////////////
  2280. //
  2281. // Translate the accelerators for the tabs. These are not in the global accelerator table.
  2282. //
  2283. bool
  2284. CHHWinType::ManualTranslateAccelerator(char iChar)
  2285. {
  2286. CHAR ch = ToLower(iChar) ;
  2287. // The Options menu button.
  2288. if (ch == _Resource.TabCtrlKeys(ACCEL_KEY_OPTIONS)
  2289. && GetToolBarHwnd())
  2290. {
  2291. PostMessage( GetHwnd(), WM_COMMAND, IDTB_OPTIONS, 0);
  2292. return true;
  2293. }
  2294. /*
  2295. else if()
  2296. // When adding in new cases, make sure not to eat a key. If you UI doesn't exist.
  2297. // Let someone else have the key.
  2298. */
  2299. else
  2300. {
  2301. // Handle the tab accelerator keys
  2302. for (int i= 0 ; i < HH_MAX_TABS+1 ; i++)
  2303. {
  2304. if (ch == _Resource.TabCtrlKeys(i) && IsValidNavPane(i))
  2305. {
  2306. doSelectTab(i) ;
  2307. return true ;
  2308. }
  2309. }
  2310. // Handle the nav panes accelerator keys
  2311. if (m_aNavPane[curNavType])
  2312. {
  2313. if (m_aNavPane[curNavType]->ProcessMenuChar(GetHwnd(),ch) )
  2314. {
  2315. if ( m_pCIExpContainer )
  2316. m_pCIExpContainer->UIDeactivateIE(); // shdocvw is loosing focus need to uideactivate here.
  2317. return true ;
  2318. }
  2319. }
  2320. }
  2321. return false ;
  2322. }
  2323. ///////////////////////////////////////////////////////////////////////////////
  2324. //
  2325. // Dynamically build an accelerator table for this window...
  2326. //
  2327. bool
  2328. CHHWinType::DynamicTranslateAccelerator(MSG* pMsg)
  2329. {
  2330. bool bReturn = false ;
  2331. if (IsWindow(GetHwnd()))
  2332. {
  2333. if (!m_hAccel)
  2334. {
  2335. // Get the static accelerators table;
  2336. HACCEL hAccelStatic = _Resource.AcceleratorTable() ;
  2337. // Get number of accelerator table entries.
  2338. int cStaticAccelEntries = CopyAcceleratorTable(hAccelStatic, NULL, 0);
  2339. // Add on the options menu and the tabs...
  2340. int cAccelEntries = cStaticAccelEntries + HH_MAX_TABS + 2 ;
  2341. // Allocate structure to hold accelerator table.
  2342. ACCEL* accel = new ACCEL[cAccelEntries] ;
  2343. if (!accel)
  2344. return false ;
  2345. // Copy the table into the structure:
  2346. CopyAcceleratorTable(hAccelStatic, accel, cStaticAccelEntries ) ;
  2347. // Add on dynamic accelerators.
  2348. int index = cStaticAccelEntries;
  2349. // Add on options menu.
  2350. if (fsToolBarFlags & HHWIN_BUTTON_OPTIONS)
  2351. {
  2352. accel[index].fVirt = FALT | FNOINVERT | FVIRTKEY ;
  2353. accel[index].key = (WORD)ToUpper(_Resource.TabCtrlKeys(ACCEL_KEY_OPTIONS)) ;
  2354. accel[index].cmd = IDTB_OPTIONS ;
  2355. index++ ;
  2356. }
  2357. // Add on accelerators for each tab.
  2358. for (int i= 0 ; i < HH_MAX_TABS+1 ; i++)
  2359. {
  2360. if (IsValidNavPane(i))
  2361. {
  2362. accel[index].fVirt = FALT | FNOINVERT | FVIRTKEY;
  2363. accel[index].key = (WORD)ToUpper(_Resource.TabCtrlKeys(i)) ;
  2364. accel[index].cmd = IDC_SELECT_TAB_FIRST + i ;
  2365. index++ ;
  2366. }
  2367. }
  2368. // Create the accelerator table.
  2369. m_hAccel = CreateAcceleratorTable(accel, index) ;
  2370. // Cleanup
  2371. delete [] accel ;
  2372. }
  2373. bReturn = (TranslateAccelerator(GetHwnd(), m_hAccel, pMsg) != 0 ) ;
  2374. }
  2375. if (bReturn)
  2376. {
  2377. DBWIN("--- Translated Accelerator ---") ;
  2378. }
  2379. return bReturn ;
  2380. }
  2381. ///////////////////////////////////////////////////////////////////////////////
  2382. //
  2383. // Stolen from System.cpp...readsystemfiles. Should be shared.
  2384. //
  2385. LPSTR _MakeItFullPath(LPCTSTR name, CHmData* phmData)
  2386. {
  2387. LPSTR pszReturn = NULL ;
  2388. CStr csz(name) ;
  2389. if (csz.IsNonEmpty())
  2390. {
  2391. if (!stristr(csz, txtDoubleColonSep) &&
  2392. !stristr(csz, txtFileHeader) && !stristr(csz, txtHttpHeader))
  2393. {
  2394. CStr cszCompiledFile ;
  2395. cszCompiledFile = phmData->GetCompiledFile();
  2396. cszCompiledFile += txtSepBack;
  2397. cszCompiledFile += csz.psz;
  2398. //Transfer pointer.
  2399. pszReturn = cszCompiledFile.psz ;
  2400. cszCompiledFile.psz = NULL ;
  2401. }
  2402. else
  2403. {
  2404. // Transfer pointer.
  2405. pszReturn = csz.psz ;
  2406. csz.psz = NULL ;
  2407. }
  2408. }
  2409. return pszReturn ;
  2410. }
  2411. ///////////////////////////////////////////////////////////////////////////////
  2412. //
  2413. // Kills all of the nav panes and then re-fills them with the new CHM data.
  2414. //
  2415. bool
  2416. CHHWinType::ReloadNavData(CHmData* phmdata)
  2417. {
  2418. if (!phmdata)
  2419. return false;
  2420. //--- Do we have valid data?
  2421. char* pszTocNew = NULL ;
  2422. char* pszIndexNew = NULL ;
  2423. // Only if we currently have a TOC, will we get the new toc.
  2424. if (IsNonEmptyString(pszToc))
  2425. {
  2426. pszTocNew = _MakeItFullPath(phmdata->GetDefaultToc(), phmdata) ;
  2427. }
  2428. // Only if we currently have an INDEX, will we get the new index.
  2429. if (IsNonEmptyString(pszIndex))
  2430. {
  2431. pszIndexNew = _MakeItFullPath(phmdata->GetDefaultIndex(), phmdata) ;
  2432. }
  2433. // CHM doesn't have a default TOC or CHM which we need. So look up one in the default window type.
  2434. if ((IsNonEmptyString(pszToc) && IsEmptyString(pszTocNew)) ||
  2435. (IsNonEmptyString(pszIndex) && IsEmptyString(pszIndexNew)))
  2436. {
  2437. CHECK_AND_FREE(pszTocNew) ;
  2438. CHECK_AND_FREE(pszIndexNew) ;
  2439. // Office Beta work around: Less attempt looking in the default window type.
  2440. if (IsNonEmptyString(phmdata->GetDefaultWindow()))
  2441. {
  2442. CHHWinType* pDefWinTypeNew = FindWindowType(phmdata->GetDefaultWindow(), NULL, phmdata->GetCompiledFile()) ;
  2443. if (pDefWinTypeNew)
  2444. {
  2445. if (IsNonEmptyString(pszToc))
  2446. {
  2447. pszTocNew = _MakeItFullPath(pDefWinTypeNew->pszToc, phmdata) ;
  2448. }
  2449. if (IsNonEmptyString(pszIndex))
  2450. {
  2451. pszIndexNew = _MakeItFullPath(pDefWinTypeNew->pszIndex, phmdata) ;
  2452. }
  2453. }
  2454. }
  2455. // If we still aren't in sync, fail.
  2456. if ((IsNonEmptyString(pszToc) && IsEmptyString(pszTocNew)) ||
  2457. (IsNonEmptyString(pszIndex) && IsEmptyString(pszIndexNew)))
  2458. {
  2459. CHECK_AND_FREE(pszTocNew) ;
  2460. CHECK_AND_FREE(pszIndexNew) ;
  2461. return false ;
  2462. }
  2463. }
  2464. //--- Kill all nav panes and cleanup other infomation
  2465. ReloadCleanup() ;
  2466. //--- Clean up some more stuff...
  2467. //--- Start re-initializing...
  2468. m_phmData = phmdata;
  2469. pszToc = pszTocNew ;
  2470. pszIndex = pszIndexNew ;
  2471. pszFile = lcStrDup(phmdata->GetDefaultHtml()); //_MakeItFullPath(phmdata->m_pszDefHtml, phmdata);
  2472. //TODO: I think we need to get a window name to read from....ick
  2473. pszJump1 = NULL;
  2474. pszJump2 = NULL;
  2475. pszUrlJump1 = NULL;
  2476. pszUrlJump2 = NULL;
  2477. //--- Okay, lets start up the first current tab...
  2478. if (IsExpandedNavPane())
  2479. {
  2480. // We have a naviation pane which we need to re-create.
  2481. fNotExpanded = TRUE ; // Force a re-creation.
  2482. ToggleExpansion(false) ;
  2483. }
  2484. return true ;
  2485. }
  2486. //////////////////////////////////////////////////////////////////////////
  2487. //
  2488. // Restores the focus to the ctrl which had it focus during the last WM_ACTIVATE.
  2489. //
  2490. bool
  2491. CHHWinType::RestoreCtrlWithFocus()
  2492. {
  2493. if (m_hwndLastFocus)
  2494. {
  2495. SetFocus(m_hwndLastFocus) ;
  2496. m_hwndLastFocus = NULL ;
  2497. return true ;
  2498. }
  2499. else
  2500. {
  2501. return false ;
  2502. }
  2503. }
  2504. //////////////////////////////////////////////////////////////////////////
  2505. //
  2506. // Saves hwnd of ctrl with focus during WM_ACTVIATE (INACTIVATE).
  2507. //
  2508. void
  2509. CHHWinType::SaveCtrlWithFocus()
  2510. {
  2511. m_hwndLastFocus = GetFocus() ;
  2512. }
  2513. //////////////////////////////////////////////////////////////////////////
  2514. //
  2515. // GetExtTabCount
  2516. //
  2517. int
  2518. CHHWinType::GetExtTabCount()
  2519. {
  2520. // If we have an original, pre-reload navdata ChmData. Use that to get the custom tab information.
  2521. if (m_phmDataOrg)
  2522. return m_phmDataOrg->GetExtTabCount();
  2523. else if (m_phmData)
  2524. return m_phmData->GetExtTabCount(); // Review: Will this ever happen?
  2525. else
  2526. return 0;
  2527. }
  2528. //////////////////////////////////////////////////////////////////////////
  2529. //
  2530. // GetExtTab
  2531. //
  2532. EXTENSIBLE_TAB*
  2533. CHHWinType::GetExtTab(int pos)
  2534. {
  2535. if (m_phmDataOrg)
  2536. return m_phmDataOrg->GetExtTab(pos);
  2537. else if (m_phmData)
  2538. return m_phmData->GetExtTab(pos); // Review:: will this ever happen?
  2539. else
  2540. return NULL;
  2541. }
  2542. ///////////////////////////////////////////////////////////////////////////////
  2543. // MUI support
  2544. //
  2545. // This InsertMenuItem wrapper will translate the MENUITEMINFOA structure
  2546. // to a MENUITEMINFOW and call InsertMenuItemW when running under Windows 2000.
  2547. //
  2548. BOOL HxInsertMenuItem(HMENU hMenu, UINT uItem, BOOL fByPosition, MENUITEMINFOA *lpmii)
  2549. {
  2550. if(g_bWinNT5 && (lpmii->fMask | MIIM_TYPE) && lpmii->fType == MFT_STRING)
  2551. {
  2552. DWORD cp = CodePageFromLCID(MAKELCID(_Module.m_Language.GetUiLanguage(),SORT_DEFAULT));
  2553. DWORD dwSize = (sizeof(WCHAR) * lpmii->cch) + 4;
  2554. WCHAR *pwcString = (WCHAR *) lcMalloc(dwSize);
  2555. if(!pwcString || !(lpmii->cch))
  2556. return FALSE;
  2557. MultiByteToWideChar(cp, MB_PRECOMPOSED, lpmii->dwTypeData, -1, pwcString, dwSize);
  2558. lpmii->dwTypeData = (CHAR *) pwcString;
  2559. lpmii->cch = wcslen((WCHAR *)lpmii->dwTypeData);
  2560. BOOL ret = InsertMenuItemW(hMenu, uItem, fByPosition, (LPMENUITEMINFOW) lpmii);
  2561. lcFree(pwcString);
  2562. return ret;
  2563. }
  2564. else
  2565. {
  2566. return InsertMenuItem(hMenu, uItem, fByPosition, lpmii);
  2567. }
  2568. }