Add support for searching and highlighting a wxWebView.

Currently supports WebView on GTK and IE. Closes #14045.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72390 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Steve Lamerton 2012-08-28 17:13:13 +00:00
parent de3d7096fe
commit 66ac040060
9 changed files with 609 additions and 1 deletions

View File

@ -535,6 +535,7 @@ All:
All (GUI):
- Add support for searching in wxWebView for MSW and GTK (Allonii).
- Respect window max size in wxBoxSizer (Nathan Ridge).
- Add possibility to hide and show again wxRibbonBar pages (wxBen).
- Add wxRibbonBar pages highlighting (wxBen).

View File

@ -96,6 +96,9 @@ public:
virtual void Undo();
virtual void Redo();
//Find function
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT);
//Editing functions
virtual void SetEditable(bool enable = true);
virtual bool IsEditable() const;
@ -142,6 +145,9 @@ private:
void SetWebkitZoom(float level);
float GetWebkitZoom() const;
//Find helper function
void FindClear();
// focus event handler: calls GTKUpdateBitmap()
void GTKOnFocus(wxFocusEvent& event);
@ -150,6 +156,12 @@ private:
wxVector<wxSharedPtr<wxWebViewHandler> > m_handlerList;
//variables used for Find()
int m_findFlags;
wxString m_findText;
int m_findPosition;
int m_findCount;
wxDECLARE_DYNAMIC_CLASS(wxWebViewWebKit);
};

View File

@ -244,10 +244,13 @@ public:
/* END OF MSHTMHST.H implementation */
struct IHTMLDocument2;
struct IHTMLElement;
struct IMarkupPointer;
class wxFSFile;
class ClassFactory;
class wxIEContainer;
class DocHostUIHandler;
class wxFindPointers;
class WXDLLIMPEXP_WEBVIEW wxWebViewIE : public wxWebView
{
@ -320,6 +323,9 @@ public:
virtual void Undo();
virtual void Redo();
//Find function
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT);
//Editing functions
virtual void SetEditable(bool enable = true);
virtual bool IsEditable() const;
@ -384,10 +390,21 @@ private:
bool m_historyLoadingFromList;
bool m_historyEnabled;
//Generic helper functions for IHtmlDocument commands
//We store find flag, results and position.
wxVector<wxFindPointers> m_findPointers;
int m_findFlags;
wxString m_findText;
int m_findPosition;
//Generic helper functions
bool CanExecCommand(wxString command) const;
void ExecCommand(wxString command);
wxCOMPtr<IHTMLDocument2> GetDocument() const;
bool IsElementVisible(IHTMLElement* elm);
//Find helper functions.
void FindInternal(const wxString& text, int flags, int internal_flag);
long FindNext(int direction = 1);
void FindClear();
//Toggles control features see INTERNETFEATURELIST for values.
bool EnableControlFeature(long flag, bool enable = true);
@ -517,6 +534,18 @@ public:
DECLARE_IUNKNOWN_METHODS;
};
class wxFindPointers
{
public:
wxFindPointers(IMarkupPointer *ptrBegin, IMarkupPointer *ptrEnd)
{
begin = ptrBegin;
end = ptrEnd;
}
//The two markup pointers.
IMarkupPointer *begin, *end;
};
#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE && defined(__WXMSW__)
#endif // wxWebViewIE_H

View File

@ -86,6 +86,9 @@ public:
virtual void Undo();
virtual void Redo();
//Find function
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT) { return wxNOT_FOUND; };
//Clipboard functions
virtual bool CanCut() const { return true; }
virtual bool CanCopy() const { return true; }

View File

@ -68,6 +68,16 @@ enum wxWebViewReloadFlags
wxWEB_VIEW_RELOAD_NO_CACHE
};
enum wxWebViewFindFlags
{
wxWEB_VIEW_FIND_WRAP = 0x0001,
wxWEB_VIEW_FIND_ENTIRE_WORD = 0x0002,
wxWEB_VIEW_FIND_MATCH_CASE = 0x0004,
wxWEB_VIEW_FIND_HIGHLIGHT_RESULT = 0x0008,
wxWEB_VIEW_FIND_BACKWARDS = 0x0010,
wxWEB_VIEW_FIND_DEFAULT = 0
};
enum wxWebViewBackend
{
wxWEB_VIEW_BACKEND_DEFAULT,
@ -181,6 +191,8 @@ public:
//Get the pointer to the underlying native engine.
virtual void* GetNativeBackend() const = 0;
//Find function
virtual long Find(const wxString& text, int flags = wxWEB_VIEW_FIND_DEFAULT) = 0;
protected:
virtual void DoSetPage(const wxString& html, const wxString& baseUrl) = 0;

View File

@ -69,6 +69,30 @@ enum wxWebViewReloadFlags
wxWEB_VIEW_RELOAD_NO_CACHE
};
/**
Find flags used when searching for text on page.
*/
enum wxWebViewFindFlags
{
/** Causes the search to restart when end or beginning reached */
wxWEB_VIEW_FIND_WRAP = 0x0001,
/** Matches an entire word when searching */
wxWEB_VIEW_FIND_ENTIRE_WORD = 0x0002,
/** Match case, i.e. case sensitive searching */
wxWEB_VIEW_FIND_MATCH_CASE = 0x0004,
/** Highlights the search results */
wxWEB_VIEW_FIND_HIGHLIGHT_RESULT = 0x0008,
/** Searches for phrase in backward direction */
wxWEB_VIEW_FIND_BACKWARDS = 0x0010,
/** The default flag, which is simple searching */
wxWEB_VIEW_FIND_DEFAULT = 0
};
/**
* List of available backends for wxWebView
*/
@ -572,6 +596,30 @@ public:
*/
virtual void Undo() = 0;
/**
@name Finding
*/
/**
Finds a phrase on the current page and if found, the control will
scroll the phrase into view and select it.
@param text The phrase to search for.
@param flags The flags for the search.
@return If search phrase was not found in combination with the flags
then @c wxNOT_FOUND is returned. If called for the first time
with search phrase then the total number of results will be
returned. Then for every time its called with the same search
phrase it will return the number of the current match.
@note This function will restart the search if the flags
@c wxWEB_VIEW_FIND_ENTIRE_WORD or @c wxWEB_VIEW_FIND_MATCH_CASE
are changed, since this will require a new search. To reset the
search, for example reseting the highlights call the function
with an empty search phrase. This always returns @c wxNOT_FOUND
on the OSX WebKit backend.
@since 2.9.5
*/
virtual long Find(const wxString& text, wxWebViewFindFlags flags = wxWEB_VIEW_FIND_DEFAULT) = 0;
/**
@name Zoom
*/

View File

@ -136,6 +136,10 @@ public:
void OnDeleteSelection(wxCommandEvent& evt);
void OnSelectAll(wxCommandEvent& evt);
void OnLoadScheme(wxCommandEvent& evt);
void OnFind(wxCommandEvent& evt);
void OnFindDone(wxCommandEvent& evt);
void OnFindText(wxCommandEvent& evt);
void OnFindOptions(wxCommandEvent& evt);
private:
wxTextCtrl* m_url;
@ -148,6 +152,15 @@ private:
wxToolBarToolBase* m_toolbar_reload;
wxToolBarToolBase* m_toolbar_tools;
wxToolBarToolBase* m_find_toolbar_done;
wxToolBarToolBase* m_find_toolbar_next;
wxToolBarToolBase* m_find_toolbar_previous;
wxToolBarToolBase* m_find_toolbar_options;
wxMenuItem* m_find_toolbar_wrap;
wxMenuItem* m_find_toolbar_highlight;
wxMenuItem* m_find_toolbar_matchcase;
wxMenuItem* m_find_toolbar_wholeword;
wxMenu* m_tools_menu;
wxMenu* m_tools_history_menu;
wxMenuItem* m_tools_layout;
@ -171,11 +184,16 @@ private:
wxMenuItem* m_scroll_page_down;
wxMenuItem* m_selection_clear;
wxMenuItem* m_selection_delete;
wxMenuItem* m_find;
wxInfoBar *m_info;
wxStaticText* m_info_text;
wxTextCtrl* m_find_ctrl;
wxToolBar* m_find_toolbar;
wxMenuHistoryMap m_histMenuItems;
wxString m_findText;
int m_findFlags, m_findCount;
};
class SourceViewDialog : public wxDialog
@ -240,6 +258,47 @@ WebFrame::WebFrame(const wxString& url) :
m_toolbar->Realize();
// Set find values.
m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
m_findText = wxEmptyString;
m_findCount = 0;
// Create panel for find toolbar.
wxPanel* panel = new wxPanel(this);
topsizer->Add(panel, wxSizerFlags().Expand());
// Create sizer for panel.
wxBoxSizer* panel_sizer = new wxBoxSizer(wxVERTICAL);
panel->SetSizer(panel_sizer);
// Create the find toolbar.
m_find_toolbar = new wxToolBar(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL|wxTB_TEXT|wxTB_HORZ_LAYOUT);
m_find_toolbar->Hide();
panel_sizer->Add(m_find_toolbar, wxSizerFlags().Expand());
// Create find control.
m_find_ctrl = new wxTextCtrl(m_find_toolbar, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(140,-1), wxTE_PROCESS_ENTER);
//Find options menu
wxMenu* findmenu = new wxMenu;
m_find_toolbar_wrap = findmenu->AppendCheckItem(wxID_ANY,"Wrap");
m_find_toolbar_matchcase = findmenu->AppendCheckItem(wxID_ANY,"Match Case");
m_find_toolbar_wholeword = findmenu->AppendCheckItem(wxID_ANY,"Entire Word");
m_find_toolbar_highlight = findmenu->AppendCheckItem(wxID_ANY,"Highlight");
// Add find toolbar tools.
m_find_toolbar->SetToolSeparation(7);
m_find_toolbar_done = m_find_toolbar->AddTool(wxID_ANY, "Close", wxArtProvider::GetBitmap(wxART_CROSS_MARK));
m_find_toolbar->AddSeparator();
m_find_toolbar->AddControl(m_find_ctrl, "Find");
m_find_toolbar->AddSeparator();
m_find_toolbar_next = m_find_toolbar->AddTool(wxID_ANY, "Next", wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_TOOLBAR, wxSize(16,16)));
m_find_toolbar_previous = m_find_toolbar->AddTool(wxID_ANY, "Previous", wxArtProvider::GetBitmap(wxART_GO_UP, wxART_TOOLBAR, wxSize(16,16)));
m_find_toolbar->AddSeparator();
m_find_toolbar_options = m_find_toolbar->AddTool(wxID_ANY, "Options", wxArtProvider::GetBitmap(wxART_PLUS, wxART_TOOLBAR, wxSize(16,16)), "", wxITEM_DROPDOWN);
m_find_toolbar_options->SetDropdownMenu(findmenu);
m_find_toolbar->Realize();
// Create the info panel
m_info = new wxInfoBar(this);
topsizer->Add(m_info, wxSizerFlags().Expand());
@ -275,6 +334,10 @@ WebFrame::WebFrame(const wxString& url) :
m_tools_handle_new_window = m_tools_menu->AppendCheckItem(wxID_ANY, _("Handle New Windows"));
m_tools_menu->AppendSeparator();
//Find
m_find = m_tools_menu->Append(wxID_ANY, _("Find"));
m_tools_menu->AppendSeparator();
//History menu
m_tools_history_menu = new wxMenu();
wxMenuItem* clearhist = m_tools_history_menu->Append(wxID_ANY, _("Clear History"));
@ -339,6 +402,20 @@ WebFrame::WebFrame(const wxString& url) :
Connect(m_url->GetId(), wxEVT_COMMAND_TEXT_ENTER,
wxCommandEventHandler(WebFrame::OnUrl), NULL, this );
// Connect find toolbar events.
Connect(m_find_toolbar_done->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
wxCommandEventHandler(WebFrame::OnFindDone), NULL, this );
Connect(m_find_toolbar_next->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
Connect(m_find_toolbar_previous->GetId(), wxEVT_COMMAND_TOOL_CLICKED,
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
// Connect find control events.
Connect(m_find_ctrl->GetId(), wxEVT_COMMAND_TEXT_UPDATED,
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
Connect(m_find_ctrl->GetId(), wxEVT_COMMAND_TEXT_ENTER,
wxCommandEventHandler(WebFrame::OnFindText), NULL, this );
// Connect the webview events
Connect(m_browser->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
wxWebViewEventHandler(WebFrame::OnNavigationRequest), NULL, this);
@ -404,6 +481,8 @@ WebFrame::WebFrame(const wxString& url) :
wxCommandEventHandler(WebFrame::OnSelectAll), NULL, this );
Connect(loadscheme->GetId(), wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(WebFrame::OnLoadScheme), NULL, this );
Connect(m_find->GetId(), wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(WebFrame::OnFind), NULL, this );
//Connect the idle events
Connect(wxID_ANY, wxEVT_IDLE, wxIdleEventHandler(WebFrame::OnIdle), NULL, this);
@ -549,6 +628,72 @@ void WebFrame::OnLoadScheme(wxCommandEvent& WXUNUSED(evt))
m_browser->LoadURL(path);
}
void WebFrame::OnFind(wxCommandEvent& WXUNUSED(evt))
{
wxString value = m_browser->GetSelectedText();
if(value.Len() > 150)
{
value.Truncate(150);
}
m_find_ctrl->SetValue(value);
if(!m_find_toolbar->IsShown()){
m_find_toolbar->Show(true);
SendSizeEvent();
}
m_find_ctrl->SelectAll();
}
void WebFrame::OnFindDone(wxCommandEvent& WXUNUSED(evt))
{
m_browser->Find("");
m_find_toolbar->Show(false);
SendSizeEvent();
}
void WebFrame::OnFindText(wxCommandEvent& evt)
{
int flags = 0;
if(m_find_toolbar_wrap->IsChecked())
flags |= wxWEB_VIEW_FIND_WRAP;
if(m_find_toolbar_wholeword->IsChecked())
flags |= wxWEB_VIEW_FIND_ENTIRE_WORD;
if(m_find_toolbar_matchcase->IsChecked())
flags |= wxWEB_VIEW_FIND_MATCH_CASE;
if(m_find_toolbar_highlight->IsChecked())
flags |= wxWEB_VIEW_FIND_HIGHLIGHT_RESULT;
if(m_find_toolbar_previous->GetId() == evt.GetId())
flags |= wxWEB_VIEW_FIND_BACKWARDS;
wxString find_text = m_find_ctrl->GetValue();
long count = m_browser->Find(find_text, flags);
if(m_findText != find_text)
{
m_findCount = count;
m_findText = find_text;
}
if(count != wxNOT_FOUND || find_text.IsEmpty())
{
m_find_ctrl->SetBackgroundColour(*wxWHITE);
}
else
{
m_find_ctrl->SetBackgroundColour(wxColour(255, 101, 101));
}
m_find_ctrl->Refresh();
//Log the result, note that count is zero indexed.
if(count != m_findCount)
{
count++;
}
wxLogMessage("Searching for:%s current match:%i/%i", m_findText.c_str(), count, m_findCount);
}
/**
* Callback invoked when there is a request to load a new page (for instance
* when the user clicks a link)

View File

@ -400,6 +400,7 @@ bool wxWebViewWebKit::Create(wxWindow *parent,
{
m_busy = false;
m_guard = false;
FindClear();
// We currently unconditionally impose scrolling in both directions as it's
// necessary to show arbitrary pages.
@ -927,6 +928,80 @@ void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
m_handlerList.push_back(handler);
}
long wxWebViewWebKit::Find(const wxString& text, int flags)
{
bool newSearch = false;
if(text != m_findText ||
(flags & wxWEB_VIEW_FIND_MATCH_CASE) != (m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE))
{
newSearch = true;
//If it is a new search we need to clear existing highlights
webkit_web_view_unmark_text_matches(m_web_view);
webkit_web_view_set_highlight_text_matches(m_web_view, false);
}
m_findFlags = flags;
m_findText = text;
//If the search string is empty then we clear any selection and highlight
if(text == "")
{
webkit_web_view_unmark_text_matches(m_web_view);
webkit_web_view_set_highlight_text_matches(m_web_view, false);
ClearSelection();
return wxNOT_FOUND;
}
bool wrap = false, matchCase = false, forward = true;
if(flags & wxWEB_VIEW_FIND_WRAP)
wrap = true;
if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
matchCase = true;
if(flags & wxWEB_VIEW_FIND_BACKWARDS)
forward = false;
if(newSearch)
{
//Initially we mark the matches to know how many we have
m_findCount = webkit_web_view_mark_text_matches(m_web_view, wxGTK_CONV(text), matchCase, 0);
//In this case we return early to match IE behaviour
m_findPosition = -1;
return m_findCount;
}
else
{
if(forward)
m_findPosition++;
else
m_findPosition--;
if(m_findPosition < 0)
m_findPosition += m_findCount;
if(m_findPosition > m_findCount)
m_findPosition -= m_findCount;
}
//Highlight them if needed
bool highlight = flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT ? true : false;
webkit_web_view_set_highlight_text_matches(m_web_view, highlight);
if(!webkit_web_view_search_text(m_web_view, wxGTK_CONV(text), matchCase, forward, wrap))
{
m_findPosition = -1;
ClearSelection();
return wxNOT_FOUND;
}
wxLogMessage(wxString::Format("Returning %d", m_findPosition));
return newSearch ? m_findCount : m_findPosition;
}
void wxWebViewWebKit::FindClear()
{
m_findCount = 0;
m_findFlags = 0;
m_findText = "";
m_findPosition = -1;
}
// static
wxVisualAttributes
wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))

View File

@ -39,6 +39,12 @@ DEFINE_GUID(wxIID_IInternetProtocolRoot,0x79eac9e3,0xbaf9,0x11ce,0x8c,0x82,0,0xa
DEFINE_GUID(wxIID_IInternetProtocol,0x79eac9e4,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
DEFINE_GUID(wxIID_IDocHostUIHandler, 0xbd3f23c0, 0xd43e, 0x11cf, 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a);
enum //Internal find flags
{
wxWEB_VIEW_FIND_ADD_POINTERS = 0x0001,
wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT = 0x0002
};
}
wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView);
@ -68,6 +74,7 @@ bool wxWebViewIE::Create(wxWindow* parent,
m_historyEnabled = true;
m_historyPosition = -1;
m_zoomType = wxWEB_VIEW_ZOOM_TYPE_TEXT;
FindClear();
if (::CoCreateInstance(CLSID_WebBrowser, NULL,
CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
@ -98,6 +105,7 @@ wxWebViewIE::~wxWebViewIE()
{
m_factories[i]->Release();
}
FindClear();
}
void wxWebViewIE::LoadURL(const wxString& url)
@ -591,6 +599,53 @@ void wxWebViewIE::Redo()
ExecCommand("Redo");
}
long wxWebViewIE::Find(const wxString& text, int flags)
{
//If the text is empty then we clear.
if(text.IsEmpty())
{
ClearSelection();
if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
{
FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
}
FindClear();
return wxNOT_FOUND;
}
//Have we done this search before?
if(m_findText == text)
{
//Just do a highlight?
if((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) != (m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT))
{
m_findFlags = flags;
if(!m_findPointers.empty())
{
FindInternal(m_findText, m_findFlags, ((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) == 0 ? wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT : 0));
}
return m_findPosition;
}
else if(((m_findFlags & wxWEB_VIEW_FIND_ENTIRE_WORD) == (flags & wxWEB_VIEW_FIND_ENTIRE_WORD)) && ((m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE) == (flags&wxWEB_VIEW_FIND_MATCH_CASE)))
{
m_findFlags = flags;
return FindNext(((flags & wxWEB_VIEW_FIND_BACKWARDS) ? -1 : 1));
}
}
//Remove old highlight if any.
if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
{
FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
}
//Reset find variables.
FindClear();
ClearSelection();
m_findText = text;
m_findFlags = flags;
//find the text and return count.
FindInternal(text, flags, wxWEB_VIEW_FIND_ADD_POINTERS);
return m_findPointers.empty() ? wxNOT_FOUND : m_findPointers.size();
}
void wxWebViewIE::SetEditable(bool enable)
{
wxCOMPtr<IHTMLDocument2> document(GetDocument());
@ -856,6 +911,232 @@ wxCOMPtr<IHTMLDocument2> wxWebViewIE::GetDocument() const
return document;
}
bool wxWebViewIE::IsElementVisible(IHTMLElement* elm)
{
IHTMLCurrentStyle* style;
IHTMLElement *elm1 = elm;
IHTMLElement2 *elm2;
BSTR tmp_bstr;
bool is_visible = true;
//This method is not perfect but it does discover most of the hidden elements.
//so if a better solution is found, then please do improve.
while(elm1)
{
if(SUCCEEDED(elm1->QueryInterface(IID_IHTMLElement2, (void**) &elm2)))
{
if(SUCCEEDED(elm2->get_currentStyle(&style)))
{
//Check if the object has the style display:none.
if((style->get_display(&tmp_bstr) != S_OK) ||
(tmp_bstr != NULL && (_wcsicmp(tmp_bstr, L"none") == 0)))
{
is_visible = false;
}
//Check if the object has the style visibility:hidden.
if(is_visible && (style->get_visibility(&tmp_bstr) != S_OK) ||
(tmp_bstr != NULL && _wcsicmp(tmp_bstr, L"hidden") == 0))
{
is_visible = false;
}
style->Release();
}
elm2->Release();
}
//Lets check the object's parent element.
IHTMLElement* parent;
if(is_visible && SUCCEEDED(elm1->get_parentElement(&parent)))
{
elm1->Release();
elm1 = parent;
}
else
{
elm1->Release();
break;
}
}
return is_visible;
}
void wxWebViewIE::FindInternal(const wxString& text, int flags, int internal_flag)
{
IMarkupServices *pIMS;
IMarkupContainer *pIMC;
IMarkupPointer *ptrBegin, *ptrEnd;
IHTMLElement* elm;
long find_flag = 0;
IHTMLDocument2 *document = GetDocument();
//This function does the acutal work.
if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices, (void **)&pIMS)))
{
if(SUCCEEDED(document->QueryInterface(IID_IMarkupContainer, (void **)&pIMC)))
{
BSTR attr_bstr = SysAllocString(L"style=\"background-color:#ffff00\"");
BSTR text_bstr = SysAllocString(text.wc_str());
pIMS->CreateMarkupPointer(&ptrBegin);
pIMS->CreateMarkupPointer(&ptrEnd);
ptrBegin->SetGravity(POINTER_GRAVITY_Right);
ptrBegin->MoveToContainer(pIMC, TRUE);
//Create the find flag from the wx one.
if(flags & wxWEB_VIEW_FIND_ENTIRE_WORD)
{
find_flag |= FINDTEXT_WHOLEWORD;
}
if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
{
find_flag |= FINDTEXT_MATCHCASE;
}
//A little speed-up to avoid to re-alloc in the positions vector.
if(text.Len() < 3 && m_findPointers.capacity() < 500)
{
m_findPointers.reserve(text.Len() == 1 ? 1000 : 500);
}
while(ptrBegin->FindText(text_bstr, find_flag, ptrEnd, NULL) == S_OK)
{
if(ptrBegin->CurrentScope(&elm) == S_OK)
{
if(IsElementVisible(elm))
{
//Highlight the word if the flag was set.
if(flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
{
IHTMLElement* pFontEl;
pIMS->CreateElement(TAGID_FONT, attr_bstr, &pFontEl);
pIMS->InsertElement(pFontEl, ptrBegin, ptrEnd);
}
if(internal_flag & wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT)
{
IHTMLElement* pFontEl;
ptrBegin->CurrentScope(&pFontEl);
pIMS->RemoveElement(pFontEl);
pFontEl->Release();
}
if(internal_flag & wxWEB_VIEW_FIND_ADD_POINTERS)
{
IMarkupPointer *cptrBegin, *cptrEnd;
pIMS->CreateMarkupPointer(&cptrBegin);
pIMS->CreateMarkupPointer(&cptrEnd);
cptrBegin->MoveToPointer(ptrBegin);
cptrEnd->MoveToPointer(ptrEnd);
m_findPointers.push_back(wxFindPointers(cptrBegin,cptrEnd));
}
}
elm->Release();
}
ptrBegin->MoveToPointer(ptrEnd);
}
//Clean up.
SysFreeString(text_bstr);
SysFreeString(attr_bstr);
pIMC->Release();
ptrBegin->Release();
ptrEnd->Release();
}
pIMS->Release();
}
document->Release();
}
long wxWebViewIE::FindNext(int direction)
{
//Don't bother if we have no pointers set.
if(m_findPointers.empty())
{
return wxNOT_FOUND;
}
//Manage the find position and do some checks.
if(direction > 0)
{
m_findPosition++;
}
else
{
m_findPosition--;
}
if(m_findPosition >= (signed)m_findPointers.size())
{
if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
{
m_findPosition = 0;
}
else
{
m_findPosition--;
return wxNOT_FOUND;
}
}
else if(m_findPosition < 0)
{
if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
{
m_findPosition = m_findPointers.size()-1;
}
else
{
m_findPosition++;
return wxNOT_FOUND;
}
}
//some variables to use later on.
IHTMLElement *body_element;
IHTMLBodyElement *body;
IHTMLTxtRange *range = NULL;
IMarkupServices *pIMS;
IHTMLDocument2 *document = GetDocument();
long ret = -1;
//Now try to create a range from the body.
if(SUCCEEDED(document->get_body(&body_element)))
{
if(SUCCEEDED(body_element->QueryInterface(IID_IHTMLBodyElement,(void**)&body)))
{
if(SUCCEEDED(body->createTextRange(&range)))
{
//So far so good, now we try to position our find pointers.
if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices,(void **)&pIMS)))
{
IMarkupPointer *begin = m_findPointers[m_findPosition].begin, *end = m_findPointers[m_findPosition].end;
if(pIMS->MoveRangeToPointers(begin,end,range) == S_OK && range->select() == S_OK)
{
ret = m_findPosition;
}
pIMS->Release();
}
range->Release();
}
body->Release();
}
body_element->Release();
}
document->Release();
return ret;
}
void wxWebViewIE::FindClear()
{
//Reset find variables.
m_findText.Empty();
m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
m_findPosition = -1;
//The m_findPointers contains pointers for the found text.
//Since it uses ref counting we call release on the pointers first
//before we remove them from the vector. In other words do not just
//remove elements from m_findPointers without calling release first
//or you will get a memory leak.
size_t count = m_findPointers.size();
for(size_t i = 0; i < count; i++)
{
m_findPointers[i].begin->Release();
m_findPointers[i].end->Release();
}
m_findPointers.clear();
}
bool wxWebViewIE::EnableControlFeature(long flag, bool enable)
{
#if wxUSE_DYNLIB_CLASS
@ -989,6 +1270,8 @@ void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
}
//Reset as we are done now
m_historyLoadingFromList = false;
//Reset the find values.
FindClear();
// TODO: set target parameter if possible
wxString target = wxEmptyString;
wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),