WindowsXP-SP1/enduser/stuff/hhctrl/autocont.cpp
2020-09-30 16:53:49 +02:00

1011 lines
32 KiB
C++

// Copyright (C) 1996 Microsoft Corporation. All rights reserved.
#include "header.h"
#include "autocont.h"
#include <exdispid.h>
#include <exdisp.h>
#include "resource.h"
#include "system.h"
#include "highlite.h"
// make Don's stuff work
#ifdef HHCTRL
#include "parserhh.h"
#else
#include "parser.h"
#endif
#include "collect.h"
#include "hhtypes.h"
//#include "toc.h"
#define NDEF_AUTOMATIONOBJECTINFO
#include "secwin.h"
#include "hhfinder.h"
// from IE4 version of exdispid.h
//
#define DISPID_DOCUMENTCOMPLETE 259 // new document goes ReadyState_Complete
#define DISPID_BEFORENAVIGATE2 250 // hyperlink clicked on
#define DISPID_NAVIGATECOMPLETE2 252 // UIActivate new document
#include "wwheel.h"
#ifndef DISPID_DOCUMENTCOMPLETE
#define DISPID_DOCUMENTCOMPLETE 259 // new document goes ReadyState_Complete
#endif
CAutomateContent::CAutomateContent(CContainer * pOuter) : CUnknownObject(pOuter)
{
m_pOuter = pOuter;
m_cRef = 0;
m_fLoadedTypeInfo = FALSE;
m_bFirstTime = TRUE;
// m_pPrintHook = NULL;
}
CAutomateContent::~CAutomateContent()
{
// if (m_pPrintHook != NULL)
// delete m_pPrintHook;
}
// aggregating IUnknown methods
STDMETHODIMP CAutomateContent::QueryInterface(REFIID riid, LPVOID * ppv)
{
*ppv = 0;
if (m_pOuter)
return m_pOuter->QueryInterface(riid,ppv);
if (riid == IID_IUnknown || riid == IID_IDispatch)
{
*ppv = (LPVOID)(IDispatch*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CAutomateContent::AddRef(void)
{
m_cRef++;
if (m_pOuter)
m_pOuter->AddRef();
return m_cRef;
}
STDMETHODIMP_(ULONG) CAutomateContent::Release(void)
{
ULONG c = --m_cRef;
if (m_pOuter)
m_pOuter->Release();
if (c <= 0)
delete this;
return c;
}
// wrapping IDispatch methods
STDMETHODIMP CAutomateContent::GetTypeInfoCount(UINT* pui)
{
// arg checking
if (!pui)
return E_INVALIDARG;
// we support GetTypeInfo, so we need to return the count here.
*pui = 1;
return S_OK;
}
STDMETHODIMP CAutomateContent::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **ppTypeInfoOut)
{
// arg checking
if (itinfo != 0)
return DISP_E_BADINDEX;
if (!ppTypeInfoOut)
return E_POINTER;
*ppTypeInfoOut = NULL;
return E_NOTIMPL;
#if 0
// ppTypeInfo will point to our global holder for this particular
// type info. if it's null, then we have to load it up. if it's not
// NULL, then it's already loaded, and we're happy.
// crit sect this entire nightmare so we're okay with multiple
// threads trying to use this object.
ITypeInfo** ppTypeInfo = PPTYPEINFOOFOBJECT(m_ObjectType);
HRESULT hr = E_INVALIDARG;;
if (*ppTypeInfo == NULL) {
ITypeInfo *pTypeInfoTmp;
HREFTYPE hrefType;
// we don't have the type info around, so go load the sucker.
ITypeLib *pTypeLib;
hr = LoadRegTypeLib(*g_pLibid, (USHORT) VERSIONOFOBJECT(m_ObjectType), 0,
LANG_NEUTRAL, &pTypeLib);
// if, for some reason, we failed to load the type library this
// way, we're going to try and load the type library directly out of
// our resources. this has the advantage of going and re-setting all
// the registry information again for us.
if (FAILED(hr)) {
char szDllPath[MAX_PATH];
DWORD dwPathLen = GetModuleFileName(_Module.GetModuleInstance(), szDllPath, MAX_PATH);
if (!dwPathLen) {
hr = E_FAIL;
goto CleanUp;
}
CWStr cwz(szDllPath);
hr = LoadTypeLib(cwz, &pTypeLib);
if (FAILED(hr))
return hr;
}
// we've got the Type Library now, so get the type info for the interface
// we're interested in.
hr = pTypeLib->GetTypeInfoOfGuid((REFIID)INTERFACEOFOBJECT(m_ObjectType), &pTypeInfoTmp);
pTypeLib->Release();
if (FAILED(hr))
return hr;
// the following couple of lines of code are to dereference the dual
// interface stuff and take us right to the dispatch portion of the
// interfaces.
//
hr = pTypeInfoTmp->GetRefTypeOfImplType(0xffffffff, &hrefType);
if (FAILED(hr)) {
pTypeInfoTmp->Release();
goto CleanUp;
}
hr = pTypeInfoTmp->GetRefTypeInfo(hrefType, ppTypeInfo);
pTypeInfoTmp->Release();
if (FAILED(hr))
return hr;
// add an extra reference to this object. if it ever becomes zero, then
// we need to release it ourselves. crit sect this since more than
// one thread can party on this object.
//
CTYPEINFOOFOBJECT(m_ObjectType)++;
m_fLoadedTypeInfo = TRUE;
}
// we still have to go and addref the Type info object, however, so that
// the people using it can release it.
//
(*ppTypeInfo)->AddRef();
*ppTypeInfoOut = *ppTypeInfo;
hr = S_OK;
CleanUp:
return hr;
#endif
}
STDMETHODIMP CAutomateContent::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
{
HRESULT hr;
ITypeInfo *pTypeInfo;
if (!DO_GUIDS_MATCH(riid, IID_NULL))
return E_INVALIDARG;
// get the type info for this dude!
hr = GetTypeInfo(0, lcid, &pTypeInfo);
if (FAILED(hr))
return hr;
// use the standard provided routines to do all the work for us.
hr = pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
pTypeInfo->Release();
return hr;
}
// I don't know if this implementation of IDispatch::Invoke() is correct or not,
// but I haven't found anyone or anything that can tell me otherwise.
STDMETHODIMP CAutomateContent::Invoke(DISPID dispid, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult,
EXCEPINFO *pexcepinfo, UINT *puArgErr)
{
char szURL[MAX_URL];
char szTFN[MAX_URL];
char szHeaders[MAX_URL];
UINT uArgErr;
if( !puArgErr )
puArgErr = &uArgErr;
// riid should always be IID_NULL.
if (!DO_GUIDS_MATCH(riid, IID_NULL))
return DISP_E_UNKNOWNINTERFACE;
// We only have to handle methods (no properties).
if (!(wFlags & DISPATCH_METHOD))
return E_INVALIDARG;
HRESULT hr;
VARIANTARG varg;
// Initialize the variants.
VariantInit(&varg);
#ifdef EXCEPTIONS
21-Sep-1997 [ralphw] Nothing in our code throws an exception, and removing
exception handling cuts down on C runtime usage.
try
{
#endif
// The dispid determines which event has been fired.
switch (dispid)
{
// case DISPID_FRAMEBEFORENAVIGATE:
// case DISPID_FRAMENAVIGATECOMPLETE:
// case DISPID_FRAMENEWWINDOW:
// case DISPID_NEWWINDOW:
case DISPID_COMMANDSTATECHANGE: {
OnCommandStateChange(
(long) pdispparams->rgvarg[1].lVal, // VT_I4 == long
(BOOL) pdispparams->rgvarg[0].boolVal ); // VT_BOOL == BOOL
break;
}
#if 0
// 31-May-1997 [ralphw] We don't use these
case DISPID_PROGRESSCHANGE: {
OnProgressChange(
(long) pdispparams->rgvarg[1].lVal, // VT_I4 == long
(long) pdispparams->rgvarg[0].lVal ); // VT_I4 == long
break;
}
case DISPID_PROPERTYCHANGE: {
CStr strProperty(pdispparams->rgvarg[0].bstrVal);
OnPropertyChange(
(LPCTSTR) strProperty ); // VT_BSTR == LPCTSTR
break;
}
case DISPID_QUIT: { // also disabled in web.cpp
OnQuit(
(BOOL*) pdispparams->rgvarg[0].pboolVal ); // VT_BYREF|VT_BOOL == BOOL*
break;
}
case DISPID_STATUSTEXTCHANGE: {
CStr strText(pdispparams->rgvarg[0].bstrVal);
OnStatusTextChange(
(LPCTSTR) strText ); // VT_BSTR == LPCTSTR
break;
}
case DISPID_DOWNLOADCOMPLETE: // DownloadComplete
OnDownloadComplete();
break;
case DISPID_DOWNLOADBEGIN: // DownloadBegin
OnDownloadBegin();
break;
#endif
case DISPID_BEFORENAVIGATE2: // ie4 version.
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[5].pvarVal->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
// 27-Sep-1997 [ralphw] IE 4 will send us a script command, followed
// by a 1 then the current URL. We don't care about the current URL
// in this case, so we nuke it.
{
PSTR pszCurUrl = StrChr(szURL, 1);
if (pszCurUrl)
*pszCurUrl = '\0';
}
szTFN[0] = 0;
if( pdispparams->rgvarg[3].pvarVal->bstrVal )
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[3].pvarVal->bstrVal, -1, szTFN, sizeof(szTFN), NULL, NULL);
szHeaders[0] = 0;
if( pdispparams->rgvarg[1].pvarVal->bstrVal )
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[1].pvarVal->bstrVal, -1, szHeaders, sizeof(szHeaders), NULL, NULL);
OnBeforeNavigate(szURL, (long)pdispparams->rgvarg[4].pvarVal->lVal, szTFN,
pdispparams->rgvarg[2].pvarVal, szHeaders, (BOOL*)pdispparams->rgvarg[0].pboolVal );
break;
case DISPID_BEFORENAVIGATE: // ie3 version.
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[5].bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[3].bstrVal, -1, szTFN, sizeof(szTFN), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[1].bstrVal, -1, szHeaders, sizeof(szHeaders), NULL, NULL);
OnBeforeNavigate(szURL, pdispparams->rgvarg[4].lVal, szTFN, pdispparams->rgvarg[2].pvarVal,
szHeaders, (BOOL*)pdispparams->rgvarg[0].pboolVal);
break;
case DISPID_NAVIGATECOMPLETE2: // ie4 version.
if(g_hsemNavigate)
ReleaseSemaphore(g_hsemNavigate, 1, NULL); // signal our navigation semaphore
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[0].pvarVal->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
OnNavigateComplete(szURL);
break;
case DISPID_NAVIGATECOMPLETE: // ie3 version.
if(g_hsemNavigate)
ReleaseSemaphore(g_hsemNavigate, 1, NULL); // signal our navigation semaphore
WideCharToMultiByte(CP_ACP, 0, pdispparams->rgvarg[0].bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
OnNavigateComplete(szURL);
break;
case DISPID_DOCUMENTCOMPLETE: // DocumentComplete
OnDocumentComplete();
break;
case DISPID_TITLECHANGE:
{
hr = DispGetParam(pdispparams, 0, VT_BSTR, &varg, puArgErr);
if (FAILED(hr))
return hr;
CStr strURL(V_BSTR(&varg));
OnTitleChange((PCSTR)strURL);
VariantClear(&varg);
}
break;
}
#ifdef EXCEPTIONS
}
catch (...)
{
if (pexcepinfo != NULL)
{
// Fill in the exception struct.
// The struct should be filled in with more useful information than
// is found here.
pexcepinfo->wCode = 1001;
pexcepinfo->wReserved = 0;
pexcepinfo->bstrSource = L"";
pexcepinfo->bstrDescription = NULL;
pexcepinfo->bstrHelpFile = NULL;
pexcepinfo->dwHelpContext = 0;
pexcepinfo->pvReserved = NULL;
pexcepinfo->pfnDeferredFillIn = NULL;
pexcepinfo->scode = 0;
}
return DISP_E_EXCEPTION;
}
#endif
return S_OK;
#if 0
HRESULT hr;
ITypeInfo *pTypeInfo;
if (!DO_GUIDS_MATCH(riid, IID_NULL))
return E_INVALIDARG;
// get our typeinfo first!
hr = GetTypeInfo(0, lcid, &pTypeInfo);
if (FAILED(hr))
return hr;
// Clear exceptions
SetErrorInfo(0, NULL);
// This is exactly what DispInvoke does--so skip the overhead.
hr = pTypeInfo->Invoke(m_pvInterface, dispid, wFlags,
pdispparams, pvarResult,
pexcepinfo, puArgErr);
pTypeInfo->Release();
return hr;
#endif
}
// actual useful code, as it were...
void CAutomateContent::LookupKeyword(LPCSTR pszKeyword)
{
// gpCOurPackage->LookupKeyword(pszKeyword);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//
// WebBrowser Event Notification interface.
//
// More actual usefull code, thank god we have Craig!
//
// These are the WebBrowserEvents (I call them notifications ?)
void CAutomateContent::OnCommandStateChange(long Command, BOOL Enable)
{
DBWIN("OnCommandStateChange Event Called.");
HMENU hMenu;
WPARAM btn_index;
TBBUTTON tbbtn;
CHHWinType* phh = FindHHWindowIndex(m_pOuter);
if (!phh || !phh->hwndToolBar || !phh->hwndHelp)
return;
hMenu = GetMenu(phh->hwndHelp);
btn_index = SendMessage(phh->hwndToolBar, TB_COMMANDTOINDEX, IDTB_OPTIONS, 0L);
if( btn_index == (WPARAM) -1 )
return;
SendMessage(phh->hwndToolBar, TB_GETBUTTON, btn_index, (LPARAM) (LPTBBUTTON) &tbbtn);
switch (Command)
{
case 1:
if ( phh->fsToolBarFlags & HHWIN_BUTTON_FORWARD )
SendMessage(phh->hwndToolBar, TB_ENABLEBUTTON, IDTB_FORWARD, Enable);
if ( hMenu )
EnableMenuItem(hMenu, IDTB_FORWARD, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
if ( tbbtn.dwData )
EnableMenuItem((HMENU)tbbtn.dwData, IDTB_FORWARD, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
break;
case 2:
if ( phh->fsToolBarFlags & HHWIN_BUTTON_BACK )
SendMessage(phh->hwndToolBar, TB_ENABLEBUTTON, IDTB_BACK, Enable);
if ( hMenu )
EnableMenuItem(hMenu, IDTB_BACK, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
if ( tbbtn.dwData )
EnableMenuItem((HMENU)tbbtn.dwData, IDTB_BACK, (MF_BYCOMMAND | (Enable?MF_ENABLED:MF_GRAYED)));
break;
default:
break;
}
}
void CAutomateContent::OnDownloadBegin()
{
DBWIN("OnDownloadBegin Event Called.");
// if (m_pPrintHook != NULL)
// m_pPrintHook->OnDownloadBegin();
// gpCOurPackage->m_bAllowStop = TRUE; // Stopping allowed during download.
// gpCOurPackage->m_EnableRefresh = FALSE; // Refresh not allowed during download.
}
void CAutomateContent::OnDownloadComplete()
{
DBWIN("OnDownloadComplete Event Called.");
// if (m_pPrintHook != NULL)
// m_pPrintHook->OnDownloadComplete();
// gpCOurPackage->m_bAllowStop = FALSE; // Disable stop after download complete.
// gpCOurPackage->m_EnableRefresh = TRUE; // Enable refresh.
}
void CAutomateContent::OnBeforeNavigate(LPCTSTR pszURL, long Flags,
LPCTSTR TargetFrameName, VARIANT* pPostData, LPCTSTR Headers, BOOL* pfCancel)
{
#ifdef _DEBUG
char sz[MAX_URL];
wsprintf(sz, "OnBeforeNavigate Event Called: %s", pszURL);
DBWIN(sz);
#endif
CStr PathName;
BOOL bInitNewTitle = FALSE;
BOOL bNewNavigate = FALSE;
WPARAM wParam = 0;
LPARAM lParam = 0;
UINT uiURLType = GetURLType( pszURL );
// new jump pointer
LPTSTR pszJumpURL = (LPTSTR) pszURL;
// default cancel to false
*pfCancel = FALSE;
// if we get a javascript then get the current URL so we
// can do some CD prompting to ensure the current topic is available
// to avoid multiple prompts for the topic via the finder
BOOL bJump = TRUE;
CStr szCurrentURL;
if( uiURLType == HH_URL_JAVASCRIPT ) {
bJump = FALSE;
//Don't use --> GetCurrentURL( &szCurrentURL ); this calls GetActiveWindow which is extrememly inaccurate and unnneeded.
m_pOuter->m_pWebBrowserApp->GetLocationURL( &szCurrentURL );
pszJumpURL = szCurrentURL.psz;
if( !pszJumpURL || !*pszJumpURL )
return;
uiURLType = GetURLType( pszJumpURL ); // reset the type
}
CExCollection* pCollection = NULL;
CExTitle* pTitle = NULL;
BOOL bEnable = FALSE;
HRESULT hr = S_OK;
// check if this is a compiled file (one of ours) first
BOOL bCompiled = (uiURLType != HH_URL_UNKNOWN);
// is this a super automagic URL?
//
// if not a compiled name check if it is a super automagic URL
// that is it is of the form: mytitle.chm::/mytopic.htm
// if so, then prefix it with our moniker, and continue on
//
// Note, the automagic URL support below will take care
// of fully qualifying the path and retry the navigate
CHHWinType* phh = FindHHWindowIndex(m_pOuter);
if(phh)
phh->m_bCancel = TRUE;
char szURL[MAX_URL];
BOOL bWasPrefixLess = FALSE;
if( uiURLType == HH_URL_PREFIX_LESS ) {
bWasPrefixLess = TRUE;
strcpy( szURL, (g_bMsItsMonikerSupport ? txtMsItsMoniker : txtMkStore) );
strcat( szURL, pszJumpURL );
pszJumpURL = szURL;
uiURLType = HH_URL_UNQUALIFIED;
}
// The moniker gets first crack at finding the title and thus if the specified
// title is found in the current directory than the moniker will fully qualify
// the URL and we only find out about it here first (the finder is never called).
//
// Thus, given a qualified URL we still have to check if it is external and if
// so we need to call the same "init and re-navigate" as we do for the automagic
// form of an external title.
//
if( phh && (uiURLType == HH_URL_QUALIFIED) ) {
if( pCollection = GetCurrentCollection(NULL, pszJumpURL) ) {
hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
if( !pTitle ) {
// we now know that we have an external URL
// so do our "init and re-navigate" thing
GetCompiledName( pszJumpURL, &PathName );
bInitNewTitle = TRUE;
bNewNavigate = TRUE;
}
}
}
// is this an automagic URL?
//
// if so, convert the URL to the fully qualified URL (if necessary) and then\
// re-navigate so that IE uses and knows about the the fully qualified URL
//
// we now have to support a new URL format for compiled files. The format is:
//
// mk:@MSITStore:mytitle.chm::/dir/mytopic.htm
//
// where "mk:@MSITStore:" can take any one of the many forms of our URL
// prefix and it may be optional. The "mytitle.chm" substring may or
// may not be a full pathname to the title. The remaining part is simply
// the pathname inside of the compiled title.
//
// When the URL is in this format, we need to change it to the fully
// qualified URL format which is:
//
// mk:@MSITStore:c:\titles\mytitle.chm::/dir/mytopic.htm
//
// where "mytitle.chm" is now changed to the full path name
// of the installed title "c:\titles\mytitle.chm".
//
char szJumpURL[MAX_URL];
if( phh && (uiURLType == HH_URL_UNQUALIFIED) ) {
if( pCollection = GetCurrentCollection(NULL, pszJumpURL) ) {
hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
// If there is no title associated with this URL in the
// collection and this URL was previously a prefix-less
// URL then this means we probably have an external
// title reference and thus we need to resend the new
// unqualified URL through again and have it eventually
// call the finder where it will try to locate the file
// and jump to the topic.
//
// Note, since such a jump eventually is resolved via the finder
// this means that IE will not know about the fully qualified
// path and thus the usual secondary window jump problems
// and and the like will surface if the user navigates via this
// new topic.
//
// To solve the problem we should port over the same code found
// in the finder that handles the external URL condition and simply
// do in here inline and repost this newly qualified URL instead.
//
if( pTitle )
pTitle->ConvertURL( pszJumpURL, szJumpURL );
// IE3 appears to automatically translate %20 into a space.
// Thus, in order to determine if the URL has changed or not
// we are going to have to put both URLs into a canonical form
// and do the string compare.
//
// Note, technically szJumpURL is already in canonical form
// since ConvertURL does this for us but it is better to be safe
// and convert it again. Yes, I am being paranoid but this code
// make me so!
//
CStr TestURL1;
CStr TestURL2;
if( pTitle ) {
ConvertSpacesToEscapes( szJumpURL, &TestURL1 );
ConvertSpacesToEscapes( pszJumpURL, &TestURL2 );
}
if( !pTitle || StrCmpIA( TestURL1.psz, TestURL2.psz ) != 0 ) {
if( pTitle ) {
pszJumpURL = szJumpURL;
}
else {
// we need to add this new title to the list
GetCompiledName( pszJumpURL, &PathName );
// check if it is in the same dir as the master
char szPathName[_MAX_PATH];
char szFileName[_MAX_FNAME]; // add back the extension to this post-SplitPath
char szExtension[_MAX_EXT];
SplitPath((LPSTR)PathName.psz, NULL, NULL, szFileName, szExtension);
strcat( szFileName, szExtension );
char szMasterPath[_MAX_PATH];
char szMasterDrive[_MAX_DRIVE];
SplitPath((LPSTR)pCollection->m_csFile, szMasterDrive, szMasterPath, NULL, NULL);
strcpy( szPathName, szMasterDrive );
CatPath( szPathName, szMasterPath );
CatPath( szPathName, szFileName );
if( (GetFileAttributes(szPathName) != HFILE_ERROR) ) {
PathName = szPathName;
}
else { // try the dreaded ::FindThisFile
if( !::FindThisFile( NULL, szFileName, &PathName, FALSE ) ) {
*pfCancel = TRUE;
return;
}
}
bInitNewTitle = TRUE;
}
bNewNavigate = TRUE;
}
}
}
// do we need to init this as a new title?
if( bInitNewTitle ) {
lParam = (LPARAM) (PSTR) LocalAlloc( LMEM_FIXED, strlen(PathName.psz)+1 );
strcpy( (PSTR) lParam, PathName.psz );
}
// do we need to re-navigate to a new URL?
if( bNewNavigate ) {
#if 1
wParam = (WPARAM) (PSTR) LocalAlloc( LMEM_FIXED, strlen(pszJumpURL)+1 );
strcpy( (PSTR) wParam, pszJumpURL );
PostMessage( phh->GetHwnd(), WMP_JUMP_TO_URL, wParam, lParam );
#else
phh->m_pCIExpContainer->m_pWebBrowserApp->Navigate( pszJumpURL, NULL, NULL, NULL, NULL );
#endif
*pfCancel = TRUE;
return;
}
// get a pointer to the title
if( bCompiled ) {
pCollection = GetCurrentCollection(NULL, pszJumpURL);
if( pCollection ) {
if( !pTitle )
hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
}
}
// Removable media support.
//
// if this is a topic in a chm file then ensure the storage is available
// make sure it is one of our files and not a random URL
//
// Note, this must be one of the first things we do since the URL can change
// if the user changes the title location
//
// Note, we cannot fully move this code into HHFinder since HHFinder has
// no ability to cancel the jump if the user dismisses the swap dialog. All
// we can do is duplicate the code in HHFinder as a fallback for such cases
// as the user pressing Refresh (which does not call BeforeNavigate)!
//
// Now that we have to support automagic URLs inline we are going to have
// to detect if the pathname changed between CD swapping. If so, then we
// are going to have to reissue the jump so that IE gets/knows about the fully
// qualified URL.
//
// Note, this only works for .col collections so skip the check for single title
// and merge sets
//
char szJumpURL2[MAX_URL];
if( bCompiled && phh && pCollection && !(pCollection->IsSingleTitle()) ) {
if( !pTitle )
hr = pCollection->URL2ExTitle( pszJumpURL, &pTitle );
if( FAILED(hr = EnsureStorageAvailability( pTitle )) ) {
if( hr == HHRMS_E_SKIP_ALWAYS )
MsgBox(IDS_TOPIC_UNAVAILABLE);
if( hr != E_FAIL )
*pfCancel = TRUE;
phh->m_fHighlight = FALSE;
return;
}
else {
if( hr == HHRMS_S_LOCATION_UPDATE ) {
// fetch the new URL and try again
pTitle->ConvertURL( pszJumpURL, szJumpURL2 );
pszJumpURL = szJumpURL2;
*pfCancel = TRUE;
#if 1
PSTR psz = (PSTR) LocalAlloc( LMEM_FIXED, strlen(pszJumpURL)+1 );
strcpy( psz, pszJumpURL );
PostMessage( phh->GetHwnd(), WMP_JUMP_TO_URL, (WPARAM) psz, 0 );
#else
phh->m_pCIExpContainer->m_pWebBrowserApp->Navigate( pszJumpURL, NULL, NULL, NULL, NULL );
#endif
return;
}
}
}
// if this is not a jump then bail out
if( !bJump )
return;
// make sure the chm/chi pairs match
//
if( bCompiled && pTitle ) {
if( !pTitle->EnsureChmChiMatch() ) {
*pfCancel = TRUE;
phh->m_fHighlight = FALSE;
return;
}
}
// This bit of code tells the collection where we think we are in the TOC. This is used for next and prev in the
// TOC as well as any direct jump from the TOC. We can use this data (topic number and toc location information)
// and compare it aginst the the information we get directly from the TOC to try and determine if we are navigating
// to a topic that is referenced in multiple locations in the TOC. This make sync work much more reliably. As a
// side affect, this code will also end up making autosync a little faster as well for binary TOC. Note also it
// relies upon some setup work done in the removable media support code above. <mc>
//
// Update TOC "slot" and topic information here since we have decided to allow the navigation to proceed.
//
if ( phh && pCollection && pCollection->IsBinaryTOC(phh->pszToc) )
{
if ( SUCCEEDED(pCollection->URL2ExTitle( pszJumpURL, &pTitle )) || (pTitle = pCollection->GetCurSyncExTitle()) )
{
DWORD dwSlot, dwTN;
if (! SUCCEEDED(pTitle->GetUrlTocSlot(pszJumpURL, &dwSlot, &dwTN)) )
{
dwSlot = 0;
dwTN = 0;
}
pCollection->UpdateTopicSlot(dwSlot, dwTN, pTitle);
if ( dwSlot )
bEnable = TRUE;
}
}
if ( phh && IsValidWindow(phh->hwndToolBar) && (phh->fsToolBarFlags & HHWIN_BUTTON_SYNC) )
{
if (pCollection && (! pCollection->IsBinaryTOC(phh->pszToc)) )
bEnable = TRUE; // Always enable sync or "locate" button for sitemap.
SendMessage(phh->hwndToolBar, TB_ENABLEBUTTON, IDTB_SYNC, bEnable);
HMENU hMenu = NULL;
if ( phh->hwndHelp )
hMenu = GetMenu(phh->hwndHelp);
if ( hMenu )
EnableMenuItem(hMenu, HHM_SYNC, (MF_BYCOMMAND | (bEnable?MF_ENABLED:MF_GRAYED)));
}
if(!*pfCancel)
phh->m_bCancel = FALSE;
return;
}
void CAutomateContent::OnNavigateComplete(LPCTSTR pszURL)
{
#ifdef _DEBUG
char sz[MAX_URL];
wsprintf(sz, "OnNavigateComplete Event Called: %s", pszURL);
DBWIN(sz);
#endif
// if (m_pPrintHook != NULL)
// m_pPrintHook->OnNavigateComplete();
CHHWinType* phh = FindHHWindowIndex(m_pOuter);
if (phh)
phh->OnNavigateComplete(pszURL);
if ( g_fIE3 )
OnDocumentComplete();
}
void CAutomateContent::OnDocumentComplete()
{
CHHWinType* phh = FindHHWindowIndex(m_pOuter);
CToc* ptoc = NULL;
// Bug 4710. This bit of code allows us to get focus right when we come need to init the focus to
// our ie host.
//
if ( m_bFirstTime )
{
m_bFirstTime = FALSE;
if ( (phh->fNotExpanded == TRUE) && phh->m_pCIExpContainer )
phh->m_pCIExpContainer->SetFocus(TRUE);
}
// Get a pointer to the toc if it exists.
if (phh && phh->m_aNavPane[HH_TAB_CONTENTS])
ptoc = reinterpret_cast<CToc*>(phh->m_aNavPane[HH_TAB_CONTENTS]) ; // HACKHACK: Should use dynamic cast, but no RTTI.
//
// Do autosync if necessary.
//
// <mc>
// I've moved the autosync and UI update code from DownloadComplete() because we ALWAYS get this call. We do
// not get DownloadComplete() calls when we navigate from one anchor point to another within the same .HTM file.
// 12-15-97
// </mc>
//
if (phh && phh->IsProperty(HHWIN_PROP_AUTO_SYNC) && ptoc)
{
CStr cszUrl;
phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
if (cszUrl.IsNonEmpty())
{
ptoc->Synchronize(cszUrl.psz);
}
}
if ( phh )
phh->UpdateCmdUI();
// highlight search terms
//
if(phh && phh->m_fHighlight && !phh->m_bCancel)
{
phh->m_fHighlight = FALSE;
LPDISPATCH lpDispatch = m_pOuter->m_pWebBrowserApp->GetDocument();
if(lpDispatch)
{
HWND hWnd = GetFocus();
// UI active shdocvw to work around Trident bug
//
if (! phh->m_pCIExpContainer->m_pInPlaceActive )
phh->m_pCIExpContainer->m_pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, phh->m_pCIExpContainer->m_pIOleClientSite, -1,phh->m_pCIExpContainer->m_hWnd, NULL);
// Highlight the document
//
phh->m_phmData->m_pTitleCollection->m_pSearchHighlight->HighlightDocument(lpDispatch);
lpDispatch->Release();
// deactivate shdocvw UI after highlighting
//
phh->m_pCIExpContainer->UIDeactivateIE();
SetFocus(hWnd);
}
}
// set focus back to previous control after navigate
if (phh && phh->m_hwndControl)
{
SetFocus(phh->m_hwndControl);
phh->m_hwndControl = NULL;
}
}
void CAutomateContent::OnTitleChange(LPCTSTR pszTitle)
{
DBWIN("OnTitleChange Event Called.");
#ifdef _DEBUG
CHHWinType* phh = FindHHWindowIndex(m_pOuter);
if (phh) {
CStr cszUrl;
phh->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&cszUrl);
if (cszUrl.IsNonEmpty() && strcmp(cszUrl, pszTitle) != 0)
phh->AddToHistory(pszTitle, cszUrl);
}
#endif
}
CHHWinType* FindHHWindowIndex(CContainer* m_pOuter)
{
static iLastWindow = 0;
if (pahwnd[iLastWindow] && (pahwnd[iLastWindow]->m_pCIExpContainer == m_pOuter))
return pahwnd[iLastWindow];
for (iLastWindow = 0; iLastWindow < g_cWindowSlots; iLastWindow++) {
if (pahwnd[iLastWindow] && pahwnd[iLastWindow]->m_pCIExpContainer == m_pOuter)
return pahwnd[iLastWindow];
}
iLastWindow = 0;
return NULL;
}
#if 0
void CAutomateContent::OnProgressChange(long Progress, long ProgressMax)
{
DBWIN("OnProgressChange Event Called.");
if (Progress < 0)
{
}
}
#endif
void CAutomateContent::OnPropertyChange(LPCTSTR pszProperty)
{
#ifdef _DEBUG
char sz[256];
wsprintf(sz, "OnPropertyChange Event Called: %s", pszProperty);
DBWIN(sz);
#endif
}
void CAutomateContent::OnQuit(BOOL* pfCancel)
{
DBWIN("OnQuit Event Called.");
}
void CAutomateContent::OnStatusTextChange(LPCTSTR pszText)
{
#ifdef _DEBUG
char sz[256];
wsprintf(sz, "OnStatusTextChange Event Called: %s", pszText);
DBWIN(sz);
#endif
}
void CAutomateContent::OnWindowActivated()
{
DBWIN("OnWindowActivated Event Called.");
}