From: Jacob Czekalla jczekalla@codeweavers.com
Currently the treeview items do not change selection when back or forward buttons are clicked. --- dlls/hhctrl.ocx/help.c | 164 ++++++++++++++++++++++++++++++++--- dlls/hhctrl.ocx/hhctrl.h | 13 +++ dlls/hhctrl.ocx/webbrowser.c | 2 + 3 files changed, 168 insertions(+), 11 deletions(-)
diff --git a/dlls/hhctrl.ocx/help.c b/dlls/hhctrl.ocx/help.c index 413659c7097..4eacb07d53c 100644 --- a/dlls/hhctrl.ocx/help.c +++ b/dlls/hhctrl.ocx/help.c @@ -25,6 +25,7 @@ #include "wingdi.h" #include "commctrl.h" #include "wininet.h" +#include "exdispid.h"
#include "wine/debug.h"
@@ -258,12 +259,21 @@ BOOL NavigateToChm(HHInfo *info, LPCWSTR file, LPCWSTR index) return SUCCEEDED(navigate_url(info, buf)); }
-static void DoSync(HHInfo *info) +static BOOL is_chm(WCHAR *url) { - WCHAR buf[INTERNET_MAX_URL_LENGTH]; + const WCHAR *prefix = L"mk:@MSITStore:"; + return !wcsncmp(url, prefix, wcslen(prefix)); +} + +static void DoSyncContent(HHInfo *info) +{ + const WCHAR *index; HRESULT hres; BSTR url;
+ if (info->current_tab != TAB_CONTENTS) + return; + hres = IWebBrowser2_get_LocationURL(info->web_browser->web_browser, &url);
if (FAILED(hres)) @@ -272,24 +282,123 @@ static void DoSync(HHInfo *info) return; }
- /* If we're not currently viewing a page in the active .chm file, abort */ - if ((!AppendFullPathURL(info->WinType.pszFile, buf, NULL)) || (lstrlenW(buf) > lstrlenW(url))) + /* If we're not currently viewing a page in a .chm file, abort */ + if (!is_chm(url)) { SysFreeString(url); return; }
- if (lstrcmpiW(buf, url) > 0) + index = wcsstr(url, L"::/"); + + if (index) + ActivateContentTopic(info->tabs[TAB_CONTENTS].hwnd, index + 3, info->content); /* skip over ::/ */ + + SysFreeString(url); +} + +static HRESULT WINAPI WebBrowserEvents2_QueryInterface(IDispatch *iface, REFIID riid, void **v) +{ + *v = NULL; + + if (IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IUnknown, riid)) + { + *v = iface; + IDispatch_AddRef(iface); + return S_OK; + } + + return E_NOINTERFACE; +} + +static inline WebBrowserEvents2Impl *impl_from_IDispatch(IDispatch *iface) +{ + return CONTAINING_RECORD(iface, WebBrowserEvents2Impl, WebBrowserEvents2Impl_iface); +} + +static ULONG WINAPI WebBrowserEvents2_AddRef(IDispatch *iface) +{ + WebBrowserEvents2Impl *impl = impl_from_IDispatch(iface); + return InterlockedIncrement(&impl->ref); +} + +static ULONG WINAPI WebBrowserEvents2_Release(IDispatch *iface) +{ + WebBrowserEvents2Impl *impl = impl_from_IDispatch(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + if (!ref) + free(impl); + return ref; +} + +static HRESULT WINAPI WebBrowserEvents2_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowserEvents2_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowserEvents2_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowserEvents2_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + if (dispIdMember == DISPID_NAVIGATECOMPLETE2) { - const WCHAR *index; + WebBrowserEvents2Impl *impl = impl_from_IDispatch(iface); + DoSyncContent((HHInfo *)impl->info); + } + return S_OK; +} + +static const IDispatchVtbl WebBrowserEvents2Vtbl = +{ + WebBrowserEvents2_QueryInterface, + WebBrowserEvents2_AddRef, + WebBrowserEvents2_Release, + WebBrowserEvents2_GetTypeInfoCount, + WebBrowserEvents2_GetTypeInfo, + WebBrowserEvents2_GetIDsOfNames, + WebBrowserEvents2_Invoke +}; + +static void hook_WebBrowserEvents2(HHInfo *info, BOOL init) +{ + IConnectionPointContainer *container; + IConnectionPoint *point; + HRESULT hres;
- index = wcsstr(url, L"::/"); + hres = IWebBrowser2_QueryInterface(info->web_browser->web_browser, &IID_IConnectionPointContainer, (void **)&container); + if (FAILED(hres)) + return;
- if (index) - ActivateContentTopic(info->tabs[TAB_CONTENTS].hwnd, index + 3, info->content); /* skip over ::/ */ + hres = IConnectionPointContainer_FindConnectionPoint(container, &DIID_DWebBrowserEvents2, &point); + IConnectionPointContainer_Release(container); + if (FAILED(hres)) + return; + + if (init) + { + info->web_browser->WebBrowser_events_sink = malloc(sizeof(*(info->web_browser->WebBrowser_events_sink))); + info->web_browser->WebBrowser_events_sink->WebBrowserEvents2Impl_iface.lpVtbl = &WebBrowserEvents2Vtbl; + info->web_browser->WebBrowser_events_sink->info = (struct HHInfo *)info; + info->web_browser->WebBrowser_events_sink->ref = 1; + IConnectionPoint_Advise(point, (IUnknown *)info->web_browser->WebBrowser_events_sink, &info->web_browser->WebBrowser_events_sink->cookie); } + else + IConnectionPoint_Unadvise(point, info->web_browser->WebBrowser_events_sink->cookie);
- SysFreeString(url); + IConnectionPoint_Release(point); }
/* Size Bar */ @@ -577,9 +686,36 @@ static LRESULT OnTabChange(HWND hwnd) if(info->tabs[info->current_tab].hwnd) ShowWindow(info->tabs[info->current_tab].hwnd, SW_SHOW);
+ if (info->current_tab == TAB_CONTENTS) + DoSyncContent(info); + return 0; }
+static BOOL is_current_page(HHInfo *info, const WCHAR *local) +{ + WCHAR *url; + WCHAR *current_page; + HRESULT res; + + res = IWebBrowser2_get_LocationURL(info->web_browser->web_browser, &url); + if (FAILED(res)) + return FALSE; + + if (is_chm(url)) + { + current_page = wcsstr(url, L"::/"); + if (current_page && !lstrcmpW(local, current_page + 3)) + return TRUE; + }else + { + if (!lstrcmpW(local, url)) + return TRUE; + } + + return FALSE; +} + static LRESULT OnTopicChange(HHInfo *info, void *user_data) { LPCWSTR chmfile = NULL, name = NULL, local = NULL; @@ -596,6 +732,9 @@ static LRESULT OnTopicChange(HHInfo *info, void *user_data) citer = (ContentItem *) user_data; name = citer->name; local = citer->local; + if (is_current_page(info, local)) + return 0; + while(citer) { if(citer->merge.chm_file) { chmfile = citer->merge.chm_file; @@ -880,7 +1019,7 @@ static void TB_OnClick(HWND hWnd, DWORD dwID) ExpandContract(info); break; case IDTB_SYNC: - DoSync(info); + DoSyncContent(info); break; case IDTB_OPTIONS: DisplayPopupMenu(info); @@ -1158,6 +1297,8 @@ static BOOL HH_AddHTMLPane(HHInfo *pHHInfo) if (!InitWebBrowser(pHHInfo, hWnd)) return FALSE;
+ hook_WebBrowserEvents2(pHHInfo, TRUE); + /* store the pointer to the HH info struct */ SetWindowLongPtrW(hWnd, 0, (LONG_PTR)pHHInfo);
@@ -1785,6 +1926,7 @@ void ReleaseHelpViewer(HHInfo *info) if (info->pCHMInfo) CloseCHM(info->pCHMInfo);
+ hook_WebBrowserEvents2(info, FALSE); ReleaseWebBrowser(info); ReleaseContent(info); ReleaseIndex(info); diff --git a/dlls/hhctrl.ocx/hhctrl.h b/dlls/hhctrl.ocx/hhctrl.h index ebec0eebf30..f346fc735d5 100644 --- a/dlls/hhctrl.ocx/hhctrl.h +++ b/dlls/hhctrl.ocx/hhctrl.h @@ -168,6 +168,17 @@ struct wintype_stringsA { char *pszCustomTabs; };
+struct HHInfo; + +typedef struct WebBrowserEvents2Impl +{ + IDispatch WebBrowserEvents2Impl_iface; + + struct HHInfo *info; + LONG ref; + DWORD cookie; +} WebBrowserEvents2Impl; + typedef struct { IOleClientSite IOleClientSite_iface; IOleInPlaceSite IOleInPlaceSite_iface; @@ -179,6 +190,8 @@ typedef struct { IOleObject *ole_obj; IWebBrowser2 *web_browser; HWND hwndWindow; + + WebBrowserEvents2Impl *WebBrowser_events_sink; } WebBrowserContainer;
typedef struct { diff --git a/dlls/hhctrl.ocx/webbrowser.c b/dlls/hhctrl.ocx/webbrowser.c index 4e97a727a72..4fc7d9fc901 100644 --- a/dlls/hhctrl.ocx/webbrowser.c +++ b/dlls/hhctrl.ocx/webbrowser.c @@ -81,6 +81,8 @@ static ULONG STDMETHODCALLTYPE Site_Release(IOleClientSite *iface) IOleObject_Release(This->ole_obj); if(This->web_browser) IWebBrowser2_Release(This->web_browser); + if(This->WebBrowser_events_sink) + IDispatch_Release(&This->WebBrowser_events_sink->WebBrowserEvents2Impl_iface); free(This); }