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.

1010 lines
31 KiB

  1. // Copyright (C) 1996 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "autocont.h"
  4. #include <exdispid.h>
  5. #include <exdisp.h>
  6. #include "resource.h"
  7. #include "system.h"
  8. #include "highlite.h"
  9. // make Don's stuff work
  10. #ifdef HHCTRL
  11. #include "parserhh.h"
  12. #else
  13. #include "parser.h"
  14. #endif
  15. #include "collect.h"
  16. #include "hhtypes.h"
  17. //#include "toc.h"
  18. #define NDEF_AUTOMATIONOBJECTINFO
  19. #include "secwin.h"
  20. #include "hhfinder.h"
  21. // from IE4 version of exdispid.h
  22. //
  23. #define DISPID_DOCUMENTCOMPLETE 259 // new document goes ReadyState_Complete
  24. #define DISPID_BEFORENAVIGATE2 250 // hyperlink clicked on
  25. #define DISPID_NAVIGATECOMPLETE2 252 // UIActivate new document
  26. #include "wwheel.h"
  27. #ifndef DISPID_DOCUMENTCOMPLETE
  28. #define DISPID_DOCUMENTCOMPLETE 259 // new document goes ReadyState_Complete
  29. #endif
  30. CAutomateContent::CAutomateContent(CContainer * pOuter) : CUnknownObject(pOuter)
  31. {
  32. m_pOuter = pOuter;
  33. m_cRef = 0;
  34. m_fLoadedTypeInfo = FALSE;
  35. m_bFirstTime = TRUE;
  36. // m_pPrintHook = NULL;
  37. }
  38. CAutomateContent::~CAutomateContent()
  39. {
  40. // if (m_pPrintHook != NULL)
  41. // delete m_pPrintHook;
  42. }
  43. // aggregating IUnknown methods
  44. STDMETHODIMP CAutomateContent::QueryInterface(REFIID riid, LPVOID * ppv)
  45. {
  46. *ppv = 0;
  47. if (m_pOuter)
  48. return m_pOuter->QueryInterface(riid,ppv);
  49. if (riid == IID_IUnknown || riid == IID_IDispatch)
  50. {
  51. *ppv = (LPVOID)(IDispatch*)this;
  52. AddRef();
  53. return S_OK;
  54. }
  55. return E_NOINTERFACE;
  56. }
  57. STDMETHODIMP_(ULONG) CAutomateContent::AddRef(void)
  58. {
  59. m_cRef++;
  60. if (m_pOuter)
  61. m_pOuter->AddRef();
  62. return m_cRef;
  63. }
  64. STDMETHODIMP_(ULONG) CAutomateContent::Release(void)
  65. {
  66. ULONG c = --m_cRef;
  67. if (m_pOuter)
  68. m_pOuter->Release();
  69. if (c <= 0)
  70. delete this;
  71. return c;
  72. }
  73. // wrapping IDispatch methods
  74. STDMETHODIMP CAutomateContent::GetTypeInfoCount(UINT* pui)
  75. {
  76. // arg checking
  77. if (!pui)
  78. return E_INVALIDARG;
  79. // we support GetTypeInfo, so we need to return the count here.
  80. *pui = 1;
  81. return S_OK;
  82. }
  83. STDMETHODIMP CAutomateContent::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **ppTypeInfoOut)
  84. {
  85. // arg checking
  86. if (itinfo != 0)
  87. return DISP_E_BADINDEX;
  88. if (!ppTypeInfoOut)
  89. return E_POINTER;
  90. *ppTypeInfoOut = NULL;
  91. return E_NOTIMPL;
  92. #if 0
  93. // ppTypeInfo will point to our global holder for this particular
  94. // type info. if it's null, then we have to load it up. if it's not
  95. // NULL, then it's already loaded, and we're happy.
  96. // crit sect this entire nightmare so we're okay with multiple
  97. // threads trying to use this object.
  98. ITypeInfo** ppTypeInfo = PPTYPEINFOOFOBJECT(m_ObjectType);
  99. HRESULT hr = E_INVALIDARG;;
  100. if (*ppTypeInfo == NULL) {
  101. ITypeInfo *pTypeInfoTmp;
  102. HREFTYPE hrefType;
  103. // we don't have the type info around, so go load the sucker.
  104. ITypeLib *pTypeLib;
  105. hr = LoadRegTypeLib(*g_pLibid, (USHORT) VERSIONOFOBJECT(m_ObjectType), 0,
  106. LANG_NEUTRAL, &pTypeLib);
  107. // if, for some reason, we failed to load the type library this
  108. // way, we're going to try and load the type library directly out of
  109. // our resources. this has the advantage of going and re-setting all
  110. // the registry information again for us.
  111. if (FAILED(hr)) {
  112. char szDllPath[MAX_PATH];
  113. DWORD dwPathLen = GetModuleFileName(_Module.GetModuleInstance(), szDllPath, MAX_PATH);
  114. if (!dwPathLen) {
  115. hr = E_FAIL;
  116. goto CleanUp;
  117. }
  118. CWStr cwz(szDllPath);
  119. hr = LoadTypeLib(cwz, &pTypeLib);
  120. if (FAILED(hr))
  121. return hr;
  122. }
  123. // we've got the Type Library now, so get the type info for the interface
  124. // we're interested in.
  125. hr = pTypeLib->GetTypeInfoOfGuid((REFIID)INTERFACEOFOBJECT(m_ObjectType), &pTypeInfoTmp);
  126. pTypeLib->Release();
  127. if (FAILED(hr))
  128. return hr;
  129. // the following couple of lines of code are to dereference the dual
  130. // interface stuff and take us right to the dispatch portion of the
  131. // interfaces.
  132. //
  133. hr = pTypeInfoTmp->GetRefTypeOfImplType(0xffffffff, &hrefType);
  134. if (FAILED(hr)) {
  135. pTypeInfoTmp->Release();
  136. goto CleanUp;
  137. }
  138. hr = pTypeInfoTmp->GetRefTypeInfo(hrefType, ppTypeInfo);
  139. pTypeInfoTmp->Release();
  140. if (FAILED(hr))
  141. return hr;
  142. // add an extra reference to this object. if it ever becomes zero, then
  143. // we need to release it ourselves. crit sect this since more than
  144. // one thread can party on this object.
  145. //
  146. CTYPEINFOOFOBJECT(m_ObjectType)++;
  147. m_fLoadedTypeInfo = TRUE;
  148. }
  149. // we still have to go and addref the Type info object, however, so that
  150. // the people using it can release it.
  151. //
  152. (*ppTypeInfo)->AddRef();
  153. *ppTypeInfoOut = *ppTypeInfo;
  154. hr = S_OK;
  155. CleanUp:
  156. return hr;
  157. #endif
  158. }
  159. STDMETHODIMP CAutomateContent::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
  160. {
  161. HRESULT hr;
  162. ITypeInfo *pTypeInfo;
  163. if (!DO_GUIDS_MATCH(riid, IID_NULL))
  164. return E_INVALIDARG;
  165. // get the type info for this dude!
  166. hr = GetTypeInfo(0, lcid, &pTypeInfo);
  167. if (FAILED(hr))
  168. return hr;
  169. // use the standard provided routines to do all the work for us.
  170. hr = pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
  171. pTypeInfo->Release();
  172. return hr;
  173. }
  174. // I don't know if this implementation of IDispatch::Invoke() is correct or not,
  175. // but I haven't found anyone or anything that can tell me otherwise.
  176. STDMETHODIMP CAutomateContent::Invoke(DISPID dispid, REFIID riid, LCID lcid,
  177. WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult,
  178. EXCEPINFO *pexcepinfo, UINT *puArgErr)
  179. {
  180. char szURL[MAX_URL];
  181. char szTFN[MAX_URL];
  182. char szHeaders[MAX_URL];
  183. UINT uArgErr;
  184. if( !puArgErr )
  185. puArgErr = &uArgErr;
  186. // riid should always be IID_NULL.
  187. if (!DO_GUIDS_MATCH(riid, IID_NULL))
  188. return DISP_E_UNKNOWNINTERFACE;
  189. // We only have to handle methods (no properties).
  190. if (!(wFlags & DISPATCH_METHOD))
  191. return E_INVALIDARG;
  192. HRESULT hr;
  193. VARIANTARG varg;
  194. // Initialize the variants.
  195. VariantInit(&varg);
  196. #ifdef EXCEPTIONS
  197. 21-Sep-1997 [ralphw] Nothing in our code throws an exception, and removing
  198. exception handling cuts down on C runtime usage.
  199. try
  200. {
  201. #endif
  202. // The dispid determines which event has been fired.
  203. switch (dispid)
  204. {
  205. // case DISPID_FRAMEBEFORENAVIGATE:
  206. // case DISPID_FRAMENAVIGATECOMPLETE:
  207. // case DISPID_FRAMENEWWINDOW:
  208. // case DISPID_NEWWINDOW:
  209. case DISPID_COMMANDSTATECHANGE: {
  210. OnCommandStateChange(
  211. (long) pdispparams->rgvarg[1].lVal, // VT_I4 == long
  212. (BOOL) pdispparams->rgvarg[0].boolVal ); // VT_BOOL == BOOL
  213. break;
  214. }
  215. #if 0
  216. // 31-May-1997 [ralphw] We don't use these
  217. case DISPID_PROGRESSCHANGE: {
  218. OnProgressChange(
  219. (long) pdispparams->rgvarg[1].lVal, // VT_I4 == long
  220. (long) pdispparams->rgvarg[0].lVal ); // VT_I4 == long
  221. break;
  222. }
  223. case DISPID_PROPERTYCHANGE: {
  224. CStr strProperty(pdispparams->rgvarg[0].bstrVal);
  225. OnPropertyChange(
  226. (LPCTSTR) strProperty ); // VT_BSTR == LPCTSTR
  227. break;
  228. }
  229. case DISPID_QUIT: { // also disabled in web.cpp
  230. OnQuit(
  231. (BOOL*) pdispparams->rgvarg[0].pboolVal ); // VT_BYREF|VT_BOOL == BOOL*
  232. break;
  233. }
  234. case DISPID_STATUSTEXTCHANGE: {
  235. CStr strText(pdispparams->rgvarg[0].bstrVal);
  236. OnStatusTextChange(
  237. (LPCTSTR) strText ); // VT_BSTR == LPCTSTR
  238. break;
  239. }
  240. case DISPID_DOWNLOADCOMPLETE: // DownloadComplete
  241. OnDownloadComplete();
  242. break;
  243. case DISPID_DOWNLOADBEGIN: // DownloadBegin
  244. OnDownloadBegin();
  245. break;
  246. #endif
  247. case DISPID_BEFORENAVIGATE2: // ie4 version.
  248. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[5].pvarVal->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
  249. // 27-Sep-1997 [ralphw] IE 4 will send us a script command, followed
  250. // by a 1 then the current URL. We don't care about the current URL
  251. // in this case, so we nuke it.
  252. {
  253. PSTR pszCurUrl = StrChr(szURL, 1);
  254. if (pszCurUrl)
  255. *pszCurUrl = '\0';
  256. }
  257. szTFN[0] = 0;
  258. if( pdispparams->rgvarg[3].pvarVal->bstrVal )
  259. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[3].pvarVal->bstrVal, -1, szTFN, sizeof(szTFN), NULL, NULL);
  260. szHeaders[0] = 0;
  261. if( pdispparams->rgvarg[1].pvarVal->bstrVal )
  262. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[1].pvarVal->bstrVal, -1, szHeaders, sizeof(szHeaders), NULL, NULL);
  263. OnBeforeNavigate(szURL, (long)pdispparams->rgvarg[4].pvarVal->lVal, szTFN,
  264. pdispparams->rgvarg[2].pvarVal, szHeaders, (BOOL*)pdispparams->rgvarg[0].pboolVal );
  265. break;
  266. case DISPID_BEFORENAVIGATE: // ie3 version.
  267. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[5].bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
  268. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[3].bstrVal, -1, szTFN, sizeof(szTFN), NULL, NULL);
  269. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[1].bstrVal, -1, szHeaders, sizeof(szHeaders), NULL, NULL);
  270. OnBeforeNavigate(szURL, pdispparams->rgvarg[4].lVal, szTFN, pdispparams->rgvarg[2].pvarVal,
  271. szHeaders, (BOOL*)pdispparams->rgvarg[0].pboolVal);
  272. break;
  273. case DISPID_NAVIGATECOMPLETE2: // ie4 version.
  274. if(g_hsemNavigate)
  275. ReleaseSemaphore(g_hsemNavigate, 1, NULL); // signal our navigation semaphore
  276. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[0].pvarVal->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
  277. OnNavigateComplete(szURL);
  278. break;
  279. case DISPID_NAVIGATECOMPLETE: // ie3 version.
  280. if(g_hsemNavigate)
  281. ReleaseSemaphore(g_hsemNavigate, 1, NULL); // signal our navigation semaphore
  282. WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[0].bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
  283. OnNavigateComplete(szURL);
  284. break;
  285. case DISPID_DOCUMENTCOMPLETE: // DocumentComplete
  286. OnDocumentComplete();
  287. break;
  288. case DISPID_TITLECHANGE:
  289. {
  290. hr = DispGetParam(pdispparams, 0, VT_BSTR, &varg, puArgErr);
  291. if (FAILED(hr))
  292. return hr;
  293. CStr strURL(V_BSTR(&varg));
  294. OnTitleChange((PCSTR)strURL);
  295. VariantClear(&varg);
  296. }
  297. break;
  298. }
  299. #ifdef EXCEPTIONS
  300. }
  301. catch (...)
  302. {
  303. if (pexcepinfo != NULL)
  304. {
  305. // Fill in the exception struct.
  306. // The struct should be filled in with more useful information than
  307. // is found here.
  308. pexcepinfo->wCode = 1001;
  309. pexcepinfo->wReserved = 0;
  310. pexcepinfo->bstrSource = L"";
  311. pexcepinfo->bstrDescription = NULL;
  312. pexcepinfo->bstrHelpFile = NULL;
  313. pexcepinfo->dwHelpContext = 0;
  314. pexcepinfo->pvReserved = NULL;
  315. pexcepinfo->pfnDeferredFillIn = NULL;
  316. pexcepinfo->scode = 0;
  317. }
  318. return DISP_E_EXCEPTION;
  319. }
  320. #endif
  321. return S_OK;
  322. #if 0
  323. HRESULT hr;
  324. ITypeInfo *pTypeInfo;
  325. if (!DO_GUIDS_MATCH(riid, IID_NULL))
  326. return E_INVALIDARG;
  327. // get our typeinfo first!
  328. hr = GetTypeInfo(0, lcid, &pTypeInfo);
  329. if (FAILED(hr))
  330. return hr;
  331. // Clear exceptions
  332. SetErrorInfo(0, NULL);
  333. // This is exactly what DispInvoke does--so skip the overhead.
  334. hr = pTypeInfo->Invoke(m_pvInterface, dispid, wFlags,
  335. pdispparams, pvarResult,
  336. pexcepinfo, puArgErr);
  337. pTypeInfo->Release();
  338. return hr;
  339. #endif
  340. }
  341. // actual useful code, as it were...
  342. void CAutomateContent::LookupKeyword(LPCSTR pszKeyword)
  343. {
  344. // gpCOurPackage->LookupKeyword(pszKeyword);
  345. }
  346. ////////////////////////////////////////////////////////////////////////////////////////////////
  347. //
  348. // WebBrowser Event Notification interface.
  349. //
  350. // More actual usefull code, thank god we have Craig!
  351. //
  352. // These are the WebBrowserEvents (I call them notifications ?)
  353. void CAutomateContent::OnCommandStateChange(long Command, BOOL Enable)
  354. {
  355. DBWIN("OnCommandStateChange Event Called.");
  356. HMENU hMenu;
  357. WPARAM btn_index;
  358. TBBUTTON tbbtn;
  359. CHHWinType* phh = FindHHWindowIndex(m_pOuter);
  360. if (!phh || !phh->hwndToolBar || !phh->hwndHelp)
  361. return;
  362. hMenu = GetMenu(phh->hwndHelp);
  363. btn_index = SendMessage(phh->hwndToolBar, TB_COMMANDTOINDEX, IDTB_OPTIONS, 0L);
  364. if( btn_index == (WPARAM) -1 )
  365. return;
  366. SendMessage(phh->hwndToolBar, TB_GETBUTTON, btn_index, (LPARAM) (LPTBBUTTON) &tbbtn);
  367. switch (Command)
  368. {
  369. case 1:
  370. if ( phh->fsToolBarFlags & HHWIN_BUTTON_FORWARD )
  371. SendMessage(phh->hwndToolBar, TB_ENABLEBUTTON, IDTB_FORWARD, Enable);
  372. if ( hMenu )
  373. EnableMenuItem(hMenu, IDTB_FORWARD, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
  374. if ( tbbtn.dwData )
  375. EnableMenuItem((HMENU)tbbtn.dwData, IDTB_FORWARD, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
  376. break;
  377. case 2:
  378. if ( phh->fsToolBarFlags & HHWIN_BUTTON_BACK )
  379. SendMessage(phh->hwndToolBar, TB_ENABLEBUTTON, IDTB_BACK, Enable);
  380. if ( hMenu )
  381. EnableMenuItem(hMenu, IDTB_BACK, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
  382. if ( tbbtn.dwData )
  383. EnableMenuItem((HMENU)tbbtn.dwData, IDTB_BACK, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
  384. break;
  385. default:
  386. break;
  387. }
  388. }
  389. void CAutomateContent::OnDownloadBegin()
  390. {
  391. DBWIN("OnDownloadBegin Event Called.");
  392. // if (m_pPrintHook != NULL)
  393. // m_pPrintHook->OnDownloadBegin();
  394. // gpCOurPackage->m_bAllowStop = TRUE; // Stopping allowed during download.
  395. // gpCOurPackage->m_EnableRefresh = FALSE; // Refresh not allowed during download.
  396. }
  397. void CAutomateContent::OnDownloadComplete()
  398. {
  399. DBWIN("OnDownloadComplete Event Called.");
  400. // if (m_pPrintHook != NULL)
  401. // m_pPrintHook->OnDownloadComplete();
  402. // gpCOurPackage->m_bAllowStop = FALSE; // Disable stop after download complete.
  403. // gpCOurPackage->m_EnableRefresh = TRUE; // Enable refresh.
  404. }
  405. void CAutomateContent::OnBeforeNavigate(LPCTSTR pszURL, long Flags,
  406. LPCTSTR TargetFrameName, VARIANT* pPostData, LPCTSTR Headers, BOOL* pfCancel)
  407. {
  408. #ifdef _DEBUG
  409. char sz[MAX_URL];
  410. wsprintf(sz, "OnBeforeNavigate Event Called: %s", pszURL);
  411. DBWIN(sz);
  412. #endif
  413. CStr PathName;
  414. BOOL bInitNewTitle = FALSE;
  415. BOOL bNewNavigate = FALSE;
  416. WPARAM wParam = 0;
  417. LPARAM lParam = 0;
  418. UINT uiURLType = GetURLType( pszURL );
  419. // new jump pointer
  420. LPTSTR pszJumpURL = (LPTSTR) pszURL;
  421. // default cancel to false
  422. *pfCancel = FALSE;
  423. // if we get a javascript then get the current URL so we
  424. // can do some CD prompting to ensure the current topic is available
  425. // to avoid multiple prompts for the topic via the finder
  426. BOOL bJump = TRUE;
  427. CStr szCurrentURL;
  428. if( uiURLType == HH_URL_JAVASCRIPT ) {
  429. bJump = FALSE;
  430. //Don't use --> GetCurrentURL( &szCurrentURL ); this calls GetActiveWindow which is extrememly inaccurate and unnneeded.
  431. m_pOuter->m_pWebBrowserApp->GetLocationURL( &szCurrentURL );
  432. pszJumpURL = szCurrentURL.psz;
  433. if( !pszJumpURL || !*pszJumpURL )
  434. return;
  435. uiURLType = GetURLType( pszJumpURL ); // reset the type
  436. }
  437. CExCollection* pCollection = NULL;
  438. CExTitle* pTitle = NULL;
  439. BOOL bEnable = FALSE;
  440. HRESULT hr = S_OK;
  441. // check if this is a compiled file (one of ours) first
  442. BOOL bCompiled = (uiURLType != HH_URL_UNKNOWN);
  443. // is this a super automagic URL?
  444. //
  445. // if not a compiled name check if it is a super automagic URL
  446. // that is it is of the form: mytitle.chm::/mytopic.htm
  447. // if so, then prefix it with our moniker, and continue on
  448. //
  449. // Note, the automagic URL support below will take care
  450. // of fully qualifying the path and retry the navigate
  451. CHHWinType* phh = FindHHWindowIndex(m_pOuter);
  452. if(phh)
  453. phh->m_bCancel = TRUE;
  454. char szURL[MAX_URL];
  455. BOOL bWasPrefixLess = FALSE;
  456. if( uiURLType == HH_URL_PREFIX_LESS ) {
  457. bWasPrefixLess = TRUE;
  458. strcpy( szURL, (g_bMsItsMonikerSupport ? txtMsItsMoniker : txtMkStore) );
  459. strcat( szURL, pszJumpURL );
  460. pszJumpURL = szURL;
  461. uiURLType = HH_URL_UNQUALIFIED;
  462. }
  463. // The moniker gets first crack at finding the title and thus if the specified
  464. // title is found in the current directory than the moniker will fully qualify
  465. // the URL and we only find out about it here first (the finder is never called).
  466. //
  467. // Thus, given a qualified URL we still have to check if it is external and if
  468. // so we need to call the same "init and re-navigate" as we do for the automagic
  469. // form of an external title.
  470. //
  471. if( phh && (uiURLType == HH_URL_QUALIFIED) ) {
  472. if( pCollection = GetCurrentCollection(NULL, pszJumpURL) ) {
  473. hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
  474. if( !pTitle ) {
  475. // we now know that we have an external URL
  476. // so do our "init and re-navigate" thing
  477. GetCompiledName( pszJumpURL, &PathName );
  478. bInitNewTitle = TRUE;
  479. bNewNavigate = TRUE;
  480. }
  481. }
  482. }
  483. // is this an automagic URL?
  484. //
  485. // if so, convert the URL to the fully qualified URL (if necessary) and then\
  486. // re-navigate so that IE uses and knows about the the fully qualified URL
  487. //
  488. // we now have to support a new URL format for compiled files. The format is:
  489. //
  490. // mk:@MSITStore:mytitle.chm::/dir/mytopic.htm
  491. //
  492. // where "mk:@MSITStore:" can take any one of the many forms of our URL
  493. // prefix and it may be optional. The "mytitle.chm" substring may or
  494. // may not be a full pathname to the title. The remaining part is simply
  495. // the pathname inside of the compiled title.
  496. //
  497. // When the URL is in this format, we need to change it to the fully
  498. // qualified URL format which is:
  499. //
  500. // mk:@MSITStore:c:\titles\mytitle.chm::/dir/mytopic.htm
  501. //
  502. // where "mytitle.chm" is now changed to the full path name
  503. // of the installed title "c:\titles\mytitle.chm".
  504. //
  505. char szJumpURL[MAX_URL];
  506. if( phh && (uiURLType == HH_URL_UNQUALIFIED) ) {
  507. if( pCollection = GetCurrentCollection(NULL, pszJumpURL) ) {
  508. hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
  509. // If there is no title associated with this URL in the
  510. // collection and this URL was previously a prefix-less
  511. // URL then this means we probably have an external
  512. // title reference and thus we need to resend the new
  513. // unqualified URL through again and have it eventually
  514. // call the finder where it will try to locate the file
  515. // and jump to the topic.
  516. //
  517. // Note, since such a jump eventually is resolved via the finder
  518. // this means that IE will not know about the fully qualified
  519. // path and thus the usual secondary window jump problems
  520. // and and the like will surface if the user navigates via this
  521. // new topic.
  522. //
  523. // To solve the problem we should port over the same code found
  524. // in the finder that handles the external URL condition and simply
  525. // do in here inline and repost this newly qualified URL instead.
  526. //
  527. if( pTitle )
  528. pTitle->ConvertURL( pszJumpURL, szJumpURL );
  529. // IE3 appears to automatically translate %20 into a space.
  530. // Thus, in order to determine if the URL has changed or not
  531. // we are going to have to put both URLs into a canonical form
  532. // and do the string compare.
  533. //
  534. // Note, technically szJumpURL is already in canonical form
  535. // since ConvertURL does this for us but it is better to be safe
  536. // and convert it again. Yes, I am being paranoid but this code
  537. // make me so!
  538. //
  539. CStr TestURL1;
  540. CStr TestURL2;
  541. if( pTitle ) {
  542. ConvertSpacesToEscapes( szJumpURL, &TestURL1 );
  543. ConvertSpacesToEscapes( pszJumpURL, &TestURL2 );
  544. }
  545. if( !pTitle || StrCmpIA( TestURL1.psz, TestURL2.psz ) != 0 ) {
  546. if( pTitle ) {
  547. pszJumpURL = szJumpURL;
  548. }
  549. else {
  550. // we need to add this new title to the list
  551. GetCompiledName( pszJumpURL, &PathName );
  552. // check if it is in the same dir as the master
  553. char szPathName[_MAX_PATH];
  554. char szFileName[_MAX_FNAME]; // add back the extension to this post-SplitPath
  555. char szExtension[_MAX_EXT];
  556. SplitPath((LPSTR)PathName.psz, NULL, NULL, szFileName, szExtension);
  557. strcat( szFileName, szExtension );
  558. char szMasterPath[_MAX_PATH];
  559. char szMasterDrive[_MAX_DRIVE];
  560. SplitPath((LPSTR)pCollection->m_csFile, szMasterDrive, szMasterPath, NULL, NULL);
  561. strcpy( szPathName, szMasterDrive );
  562. CatPath( szPathName, szMasterPath );
  563. CatPath( szPathName, szFileName );
  564. if( (GetFileAttributes(szPathName) != HFILE_ERROR) ) {
  565. PathName = szPathName;
  566. }
  567. else { // try the dreaded ::FindThisFile
  568. if( !::FindThisFile( NULL, szFileName, &PathName, FALSE ) ) {
  569. *pfCancel = TRUE;
  570. return;
  571. }
  572. }
  573. bInitNewTitle = TRUE;
  574. }
  575. bNewNavigate = TRUE;
  576. }
  577. }
  578. }
  579. // do we need to init this as a new title?
  580. if( bInitNewTitle ) {
  581. lParam = (LPARAM) (PSTR) LocalAlloc( LMEM_FIXED, strlen(PathName.psz)+1 );
  582. strcpy( (PSTR) lParam, PathName.psz );
  583. }
  584. // do we need to re-navigate to a new URL?
  585. if( bNewNavigate ) {
  586. #if 1
  587. wParam = (WPARAM) (PSTR) LocalAlloc( LMEM_FIXED, strlen(pszJumpURL)+1 );
  588. strcpy( (PSTR) wParam, pszJumpURL );
  589. PostMessage( phh->GetHwnd(), WMP_JUMP_TO_URL, wParam, lParam );
  590. #else
  591. phh->m_pCIExpContainer->m_pWebBrowserApp->Navigate( pszJumpURL, NULL, NULL, NULL, NULL );
  592. #endif
  593. *pfCancel = TRUE;
  594. return;
  595. }
  596. // get a pointer to the title
  597. if( bCompiled ) {
  598. pCollection = GetCurrentCollection(NULL, pszJumpURL);
  599. if( pCollection ) {
  600. if( !pTitle )
  601. hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
  602. }
  603. }
  604. // Removable media support.
  605. //
  606. // if this is a topic in a chm file then ensure the storage is available
  607. // make sure it is one of our files and not a random URL
  608. //
  609. // Note, this must be one of the first things we do since the URL can change
  610. // if the user changes the title location
  611. //
  612. // Note, we cannot fully move this code into HHFinder since HHFinder has
  613. // no ability to cancel the jump if the user dismisses the swap dialog. All
  614. // we can do is duplicate the code in HHFinder as a fallback for such cases
  615. // as the user pressing Refresh (which does not call BeforeNavigate)!
  616. //
  617. // Now that we have to support automagic URLs inline we are going to have
  618. // to detect if the pathname changed between CD swapping. If so, then we
  619. // are going to have to reissue the jump so that IE gets/knows about the fully
  620. // qualified URL.
  621. //
  622. // Note, this only works for .col collections so skip the check for single title
  623. // and merge sets
  624. //
  625. char szJumpURL2[MAX_URL];
  626. if( bCompiled && phh && pCollection && !(pCollection->IsSingleTitle()) ) {
  627. if( !pTitle )
  628. hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
  629. if( FAILED(hr = EnsureStorageAvailability( pTitle )) ) {
  630. if( hr == HHRMS_E_SKIP_ALWAYS )
  631. MsgBox(IDS_TOPIC_UNAVAILABLE);
  632. if( hr != E_FAIL )
  633. *pfCancel = TRUE;
  634. phh->m_fHighlight = FALSE;
  635. return;
  636. }
  637. else {
  638. if( hr == HHRMS_S_LOCATION_UPDATE ) {
  639. // fetch the new URL and try again
  640. pTitle->ConvertURL( pszJumpURL, szJumpURL2 );
  641. pszJumpURL = szJumpURL2;
  642. *pfCancel = TRUE;
  643. #if 1
  644. PSTR psz = (PSTR) LocalAlloc( LMEM_FIXED, strlen(pszJumpURL)+1 );
  645. strcpy( psz, pszJumpURL );
  646. PostMessage( phh->GetHwnd(), WMP_JUMP_TO_URL, (WPARAM) psz, 0 );
  647. #else
  648. phh->m_pCIExpContainer->m_pWebBrowserApp->Navigate( pszJumpURL, NULL, NULL, NULL, NULL );
  649. #endif
  650. return;
  651. }
  652. }
  653. }
  654. // if this is not a jump then bail out
  655. if( !bJump )
  656. return;
  657. // make sure the chm/chi pairs match
  658. //
  659. if( bCompiled && pTitle ) {
  660. if( !pTitle->EnsureChmChiMatch() ) {
  661. *pfCancel = TRUE;
  662. phh->m_fHighlight = FALSE;
  663. return;
  664. }
  665. }
  666. // This bit of code tells the collection where we think we are in the TOC. This is used for next and prev in the
  667. // TOC as well as any direct jump from the TOC. We can use this data (topic number and toc location information)
  668. // and compare it aginst the the information we get directly from the TOC to try and determine if we are navigating
  669. // to a topic that is referenced in multiple locations in the TOC. This make sync work much more reliably. As a
  670. // side affect, this code will also end up making autosync a little faster as well for binary TOC. Note also it
  671. // relies upon some setup work done in the removable media support code above. <mc>
  672. //
  673. // Update TOC "slot" and topic information here since we have decided to allow the navigation to proceed.
  674. //
  675. if ( phh && pCollection && pCollection->IsBinaryTOC(phh->pszToc) )
  676. {
  677. if ( SUCCEEDED(pCollection->URL2ExTitle( pszJumpURL, &pTitle )) || (pTitle = pCollection->GetCurSyncExTitle()) )
  678. {
  679. DWORD dwSlot, dwTN;
  680. if (! SUCCEEDED(pTitle->GetUrlTocSlot(pszJumpURL, &dwSlot, &dwTN)) )
  681. {
  682. dwSlot = 0;
  683. dwTN = 0;
  684. }
  685. pCollection->UpdateTopicSlot(dwSlot, dwTN, pTitle);
  686. if ( dwSlot )
  687. bEnable = TRUE;
  688. }
  689. }
  690. if ( phh && IsValidWindow(phh->hwndToolBar) && (phh->fsToolBarFlags & HHWIN_BUTTON_SYNC) )
  691. {
  692. if (pCollection && (! pCollection->IsBinaryTOC(phh->pszToc)) )
  693. bEnable = TRUE; // Always enable sync or "locate" button for sitemap.
  694. SendMessage(phh->hwndToolBar, TB_ENABLEBUTTON, IDTB_SYNC, bEnable);
  695. HMENU hMenu = NULL;
  696. if ( phh->hwndHelp )
  697. hMenu = GetMenu(phh->hwndHelp);
  698. if ( hMenu )
  699. EnableMenuItem(hMenu, HHM_SYNC, (MF_BYCOMMAND | (bEnable?MF_ENABLED:MF_GRAYED)));
  700. }
  701. if(!*pfCancel)
  702. phh->m_bCancel = FALSE;
  703. return;
  704. }
  705. void CAutomateContent::OnNavigateComplete(LPCTSTR pszURL)
  706. {
  707. #ifdef _DEBUG
  708. char sz[MAX_URL];
  709. wsprintf(sz, "OnNavigateComplete Event Called: %s", pszURL);
  710. DBWIN(sz);
  711. #endif
  712. // if (m_pPrintHook != NULL)
  713. // m_pPrintHook->OnNavigateComplete();
  714. CHHWinType* phh = FindHHWindowIndex(m_pOuter);
  715. if (phh)
  716. phh->OnNavigateComplete(pszURL);
  717. if ( g_fIE3 )
  718. OnDocumentComplete();
  719. }
  720. void CAutomateContent::OnDocumentComplete()
  721. {
  722. CHHWinType* phh = FindHHWindowIndex(m_pOuter);
  723. CToc* ptoc = NULL;
  724. // Bug 4710. This bit of code allows us to get focus right when we come need to init the focus to
  725. // our ie host.
  726. //
  727. if ( m_bFirstTime )
  728. {
  729. m_bFirstTime = FALSE;
  730. if ( (phh->fNotExpanded == TRUE) && phh->m_pCIExpContainer )
  731. phh->m_pCIExpContainer->SetFocus(TRUE);
  732. }
  733. // Get a pointer to the toc if it exists.
  734. if (phh && phh->m_aNavPane[HH_TAB_CONTENTS])
  735. ptoc = reinterpret_cast<CToc*>(phh->m_aNavPane[HH_TAB_CONTENTS]) ; // HACKHACK: Should use dynamic cast, but no RTTI.
  736. //
  737. // Do autosync if necessary.
  738. //
  739. // <mc>
  740. // I've moved the autosync and UI update code from DownloadComplete() because we ALWAYS get this call. We do
  741. // not get DownloadComplete() calls when we navigate from one anchor point to another within the same .HTM file.
  742. // 12-15-97
  743. // </mc>
  744. //
  745. if (phh && phh->IsProperty(HHWIN_PROP_AUTO_SYNC) && ptoc)
  746. {
  747. CStr cszUrl;
  748. phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
  749. if (cszUrl.IsNonEmpty())
  750. {
  751. ptoc->Synchronize(cszUrl.psz);
  752. }
  753. }
  754. if ( phh )
  755. phh->UpdateCmdUI();
  756. // highlight search terms
  757. //
  758. if(phh && phh->m_fHighlight && !phh->m_bCancel)
  759. {
  760. phh->m_fHighlight = FALSE;
  761. LPDISPATCH lpDispatch = m_pOuter->m_pWebBrowserApp->GetDocument();
  762. if(lpDispatch)
  763. {
  764. HWND hWnd = GetFocus();
  765. // UI active shdocvw to work around Trident bug
  766. //
  767. if (! phh->m_pCIExpContainer->m_pInPlaceActive )
  768. phh->m_pCIExpContainer->m_pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, phh->m_pCIExpContainer->m_pIOleClientSite, -1,phh->m_pCIExpContainer->m_hWnd, NULL);
  769. // Highlight the document
  770. //
  771. phh->m_phmData->m_pTitleCollection->m_pSearchHighlight->HighlightDocument(lpDispatch);
  772. lpDispatch->Release();
  773. // deactivate shdocvw UI after highlighting
  774. //
  775. phh->m_pCIExpContainer->UIDeactivateIE();
  776. SetFocus(hWnd);
  777. }
  778. }
  779. // set focus back to previous control after navigate
  780. if (phh && phh->m_hwndControl)
  781. {
  782. SetFocus(phh->m_hwndControl);
  783. phh->m_hwndControl = NULL;
  784. }
  785. }
  786. void CAutomateContent::OnTitleChange(LPCTSTR pszTitle)
  787. {
  788. DBWIN("OnTitleChange Event Called.");
  789. #ifdef _DEBUG
  790. CHHWinType* phh = FindHHWindowIndex(m_pOuter);
  791. if (phh) {
  792. CStr cszUrl;
  793. phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
  794. if (cszUrl.IsNonEmpty() && strcmp(cszUrl, pszTitle) != 0)
  795. phh->AddToHistory(pszTitle, cszUrl);
  796. }
  797. #endif
  798. }
  799. CHHWinType* FindHHWindowIndex(CContainer* m_pOuter)
  800. {
  801. static iLastWindow = 0;
  802. if (pahwnd[iLastWindow] && (pahwnd[iLastWindow]->m_pCIExpContainer == m_pOuter))
  803. return pahwnd[iLastWindow];
  804. for (iLastWindow = 0; iLastWindow < g_cWindowSlots; iLastWindow++) {
  805. if (pahwnd[iLastWindow] && pahwnd[iLastWindow]->m_pCIExpContainer == m_pOuter)
  806. return pahwnd[iLastWindow];
  807. }
  808. iLastWindow = 0;
  809. return NULL;
  810. }
  811. #if 0
  812. void CAutomateContent::OnProgressChange(long Progress, long ProgressMax)
  813. {
  814. DBWIN("OnProgressChange Event Called.");
  815. if (Progress < 0)
  816. {
  817. }
  818. }
  819. #endif
  820. void CAutomateContent::OnPropertyChange(LPCTSTR pszProperty)
  821. {
  822. #ifdef _DEBUG
  823. char sz[256];
  824. wsprintf(sz, "OnPropertyChange Event Called: %s", pszProperty);
  825. DBWIN(sz);
  826. #endif
  827. }
  828. void CAutomateContent::OnQuit(BOOL* pfCancel)
  829. {
  830. DBWIN("OnQuit Event Called.");
  831. }
  832. void CAutomateContent::OnStatusTextChange(LPCTSTR pszText)
  833. {
  834. #ifdef _DEBUG
  835. char sz[256];
  836. wsprintf(sz, "OnStatusTextChange Event Called: %s", pszText);
  837. DBWIN(sz);
  838. #endif
  839. }
  840. void CAutomateContent::OnWindowActivated()
  841. {
  842. DBWIN("OnWindowActivated Event Called.");
  843. }