From a1c3cdc4a2c4cc2b15d7fdf60c1be228f9fbc520 Mon Sep 17 00:00:00 2001
From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= <vslavik@fastmail.fm>
Date: Sun, 29 Oct 2006 20:26:03 +0000
Subject: [PATCH] add events API to wxHtmlWindow (patch #1504493 by Francesco
 Montorsi)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42658 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt           |   3 +-
 docs/latex/wx/htmllbox.tex |  29 ++++++-
 docs/latex/wx/htwindow.tex | 153 ++++++++++++++++++++++++++++++++++++-
 include/wx/html/helpwnd.h  |  31 --------
 include/wx/html/htmlwin.h  |  97 +++++++++++++++++++++++
 include/wx/htmllbox.h      |   3 +-
 samples/htlbox/htlbox.cpp  |  52 +++++++++----
 samples/html/test/test.cpp |  43 +++++++++++
 src/html/helpwnd.cpp       |  17 ++---
 src/html/htmlwin.cpp       |  52 ++++++++++---
 10 files changed, 408 insertions(+), 72 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index b26dd514af..5efe738d87 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -93,7 +93,8 @@ All (GUI):
 - Many enhancements to wxRichTextCtrl including URL support,
   formatting and symbol dialogs, print/preview, and better list
   formatting.
-- Support for loading TGA files added (Seth Jackson)
+- Support for loading TGA files added (Seth Jackson).
+- Added events API to wxHtmlWindow (Francesco Montorsi).
 
 Unix Ports:
 
diff --git a/docs/latex/wx/htmllbox.tex b/docs/latex/wx/htmllbox.tex
index d7cc8f62cd..fabd6a4f46 100644
--- a/docs/latex/wx/htmllbox.tex
+++ b/docs/latex/wx/htmllbox.tex
@@ -35,6 +35,19 @@ example) but you will only need to override a single
 \helpref{wxSimpleHtmlListBox}{wxsimplehtmllistbox}
 
 
+\wxheading{Event handling}
+
+To process input from a wxHtmlListBox, use these event handler macros to direct input to member
+functions that take a \helpref{wxHtmlCellEvent}{wxhtmlcellevent} argument or a \helpref{wxHtmlLinkEvent}{wxhtmllinkevent}.
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_CLICKED(id, func)}}{A \helpref{wxHtmlCell}{wxhtmlcell} was clicked.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_HOVER(id, func)}}{The mouse passed over a {\helpref{wxHtmlCell}{wxhtmlcell}.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_LINK\_CLICKED(id, func)}}{A \helpref{wxHtmlCell}{wxhtmlcell} which contains an hyperlink was clicked.}
+\end{twocollist}
+
+
 \latexignore{\rtfignore{\wxheading{Members}}}
 
 
@@ -147,6 +160,7 @@ This function may be overridden to decorate HTML returned by
 \func{virtual void}{OnLinkClicked}{\param{size\_t }{n}, \param{const wxHtmlLinkInfo\& }{link}}
 
 Called when the user clicks on hypertext link. Does nothing by default.
+Overloading this method is deprecated; intercept the event instead.
 
 \wxheading{Parameters}
 
@@ -226,7 +240,10 @@ See also \helpref{window styles overview}{windowstyles}.
 
 \wxheading{Event handling}
 
-A wxSimpleHtmlListBox emits the same events used by \helpref{wxListBox}{wxlistbox}:
+A wxSimpleHtmlListBox emits the same events used by \helpref{wxListBox}{wxlistbox} and by
+\helpref{wxHtmlListBox}{wxhtmllistbox}.
+
+The event handlers for the following events take a \helpref{wxCommandEvent}{wxcommandevent}:
 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
@@ -236,6 +253,16 @@ when an item on the list is selected.}
 when the listbox is double-clicked.}
 \end{twocollist}
 
+The event handlers for the following events take a \helpref{wxHtmlCellEvent}{wxhtmlcellevent}
+or a \helpref{wxHtmlLinkEvent}{wxhtmllinkevent}:
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_CLICKED(id, func)}}{A \helpref{wxHtmlCell}{wxhtmlcell} was clicked.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_HOVER(id, func)}}{The mouse passed over a {\helpref{wxHtmlCell}{wxhtmlcell}.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_LINK\_CLICKED(id, func)}}{A \helpref{wxHtmlCell}{wxhtmlcell} which contains an hyperlink was clicked.}
+\end{twocollist}
+
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 
diff --git a/docs/latex/wx/htwindow.tex b/docs/latex/wx/htwindow.tex
index eddfc34f44..ef351d0917 100644
--- a/docs/latex/wx/htwindow.tex
+++ b/docs/latex/wx/htwindow.tex
@@ -45,6 +45,26 @@ page's size exceeds window's size.}
 text.}
 \end{twocollist}
 
+
+\wxheading{Event handling}
+
+To process input from a wxHtmlWindow, use these event handler macros to direct input to member
+functions that take a \helpref{wxHtmlCellEvent}{wxhtmlcellevent} argument or a \helpref{wxHtmlLinkEvent}{wxhtmllinkevent}.
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_CLICKED(id, func)}}{A \helpref{wxHtmlCell}{wxhtmlcell} was clicked.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_HOVER(id, func)}}{The mouse passed over a {\helpref{wxHtmlCell}{wxhtmlcell}.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_LINK\_CLICKED(id, func)}}{A \helpref{wxHtmlCell}{wxhtmlcell} which contains an hyperlink was clicked.}
+\end{twocollist}
+
+
+\wxheading{See also}
+
+\helpref{wxHtmlLinkEvent}{wxhtmllinkevent}, \helpref{wxHtmlCellEvent}{wxhtmlcellevent}
+
+
+
 \membersection{wxHtmlWindow::wxHtmlWindow}\label{wxhtmlwindowwxhtmlwindow}
 
 \func{}{wxHtmlWindow}{\void}
@@ -200,10 +220,15 @@ false if an error occurred, true otherwise
 \func{virtual bool}{OnCellClicked}{\param{wxHtmlCell }{*cell}, \param{wxCoord }{x}, \param{wxCoord }{y}, \param{const wxMouseEvent\& }{event}}
 
 This method is called when a mouse button is clicked inside wxHtmlWindow.
-The default behaviour is to call 
-\helpref{OnLinkClicked}{wxhtmlwindowonlinkclicked} if the cell contains a
+
+The default behaviour is to emit a \helpref{wxHtmlCellEvent}{wxhtmlcellevent}
+and, if the event was not processed or skipped, call
+\helpref{OnLinkClicked}{wxhtmlwindowonlinkclicked} if the cell contains an
 hypertext link.
 
+Overloading this method is deprecated; intercept the event instead.
+
+
 \wxheading{Parameters}
 
 \docparam{cell}{The cell inside which the mouse was clicked, always a simple
@@ -222,6 +247,8 @@ hypertext link.
 \func{virtual void}{OnCellMouseHover}{\param{wxHtmlCell }{*cell}, \param{wxCoord }{x}, \param{wxCoord }{y}}
 
 This method is called when a mouse moves over an HTML cell.
+Default behaviour is to emit a \helpref{wxHtmlCellEvent}{wxhtmlcellevent}.
+Overloading this method is deprecated; intercept the event instead.
 
 \wxheading{Parameters}
 
@@ -234,8 +261,10 @@ This method is called when a mouse moves over an HTML cell.
 
 \func{virtual void}{OnLinkClicked}{\param{const wxHtmlLinkInfo\& }{link}}
 
-Called when user clicks on hypertext link. Default behaviour is to call 
-\helpref{LoadPage}{wxhtmlwindowloadpage} and do nothing else.
+Called when user clicks on hypertext link. Default behaviour is to emit a
+\helpref{wxHtmlLinkEvent}{wxhtmllinkevent} and, if the event was not processed
+or skipped, call \helpref{LoadPage}{wxhtmlwindowloadpage} and do nothing else.
+Overloading this method is deprecated; intercept the event instead.
 
 Also see \helpref{wxHtmlLinkInfo}{wxhtmllinkinfo}.
 
@@ -447,3 +476,119 @@ Saved values: all things set by SetFonts, SetBorders.
 
 \docparam{path}{Optional path in config tree. If not given, the current path is used.}
 
+
+
+
+
+
+
+\section{\class{wxHtmlLinkEvent}}\label{wxhtmllinkevent}
+
+This event class is used for the events generated by \helpref{wxHtmlWindow}{wxhtmlwindow}.
+
+\wxheading{Derived from}
+
+\helpref{wxCommandEvent}{wxcommandevent}\\
+\helpref{wxEvent}{wxevent}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/html/htmlwin.h>
+
+\wxheading{Event handling}
+
+To process input from a wxHtmlLinkEvent, use one of these event handler macros to
+direct input to member function that take a \helpref{wxHtmlLinkEvent}{wxhtmllinkevent} argument:
+
+\twocolwidtha{7cm}
+\begin{twocollist}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_LINK\_CLICKED(id, func)}}{User clicked on an hyperlink.}
+\end{twocollist}
+
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxHtmlLinkEvent::wxHtmlLinkEvent}\label{wxhtmllinkeventctor}
+
+\func{}{wxHyperlinkEvent}{\param{int}{ id}, \param{const wxHtmlLinkInfo \&}{ linkinfo}}
+
+The constructor is not normally used by the user code.
+
+
+\membersection{wxHtmlLinkEvent::GetLinkInfo}\label{wxhtmllinkeventgetlinkinfo}
+
+\constfunc{const wxHtmlLinkInfo &}{GetLinkInfo}{\void}
+
+Returns the \helpref{wxHtmlLinkInfo}{wxhtmllinkinfo} which contains info about the cell clicked and the hyperlink it contains.
+
+
+
+
+
+
+\section{\class{wxHtmlCellEvent}}\label{wxhtmlcellevent}
+
+This event class is used for the events generated by \helpref{wxHtmlWindow}{wxhtmlwindow}.
+
+\wxheading{Derived from}
+
+\helpref{wxCommandEvent}{wxcommandevent}\\
+\helpref{wxEvent}{wxevent}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/html/htmlwin.h>
+
+\wxheading{Event handling}
+
+To process input from a wxHtmlCellEvent, use one of these event handler macros to
+direct input to member function that take a \helpref{wxHtmlCellEvent}{wxhtmlcellevent} argument:
+
+\twocolwidtha{7cm}
+\begin{twocollist}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_HOVER(id, func)}}{User moved the mouse over a \helpref{wxHtmlCell}{wxhtmlcell}.}
+\twocolitem{{\bf EVT\_HTMLWINDOW\_CELL\_CLICKED(id, func)}}{User clicked on a \helpref{wxHtmlCell}{wxhtmlcell}. When handling this event, remember to use \helpref{wxHtmlCell::SetLinkClicked(true)}{wxhtmlcelleventsetlinkclicked} if the cell contains a link.}
+\end{twocollist}
+
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxHtmlCellEvent::wxHtmlCellEvent}\label{wxhtmlcelleventctor}
+
+\func{}{wxHtmlCellEvent}{\param{wxEventType}{ commandType}, \param{int}{ id}, \param{wxHtmlCell *}{ cell}, \param{const wxPoint \&}{ point}}
+
+The constructor is not normally used by the user code.
+
+
+\membersection{wxHtmlCellEvent::GetCell}\label{wxhtmlcelleventgetcell}
+
+\constfunc{wxHtmlCell *}{GetCell}{\void}
+
+Returns the \helpref{wxHtmlCellEvent}{wxhtmlcellevent} associated with the event.
+
+
+\membersection{wxHtmlCellEvent::GetPoint}\label{wxhtmlcelleventgetpoint}
+
+\constfunc{wxPoint}{GetPoint}{\void}
+
+Returns the \helpref{wxPoint}{wxpoint} associated with the event.
+
+
+\membersection{wxHtmlCellEvent::SetLinkClicked}\label{wxhtmlcelleventsetlinkclicked}
+
+\func{bool}{SetLinkClicked}{\param{bool}{ linkclicked}}
+
+Call this function with {\tt linkclicked} set to \true if the cell which has been clicked contained a link or
+\false otherwise (which is the default). With this function the event handler can return info to the
+wxHtmlWindow which sent the event.
+
+
+\membersection{wxHtmlCellEvent::GetLinkClicked}\label{wxhtmlcelleventgetlinkclicked}
+
+\constfunc{bool}{GetLinkClicked}{\void}
+
+Returns \true if \helpref{SetLinkClicked(true)}{wxhtmlcelleventsetlinkclicked} has previously been called;
+\false otherwise.
+
diff --git a/include/wx/html/helpwnd.h b/include/wx/html/helpwnd.h
index 2e718c3fb5..5e31933df5 100644
--- a/include/wx/html/helpwnd.h
+++ b/include/wx/html/helpwnd.h
@@ -295,37 +295,6 @@ enum
     wxID_HTML_COUNTINFO
 };
 
-/*!
- * Help window event
- */
-
-class WXDLLIMPEXP_HTML wxHtmlWindowEvent: public wxNotifyEvent
-{
-public:
-    wxHtmlWindowEvent(wxEventType commandType = wxEVT_NULL, int id = 0):
-                 wxNotifyEvent(commandType, id)
-    {
-
-    }
-
-    void SetURL(const wxString& url) { m_url = url; }
-    const wxString& GetURL() const { return m_url; }
-
-private:
-    wxString    m_url;
-
-    DECLARE_DYNAMIC_CLASS(wxHtmlWindowEvent)
-};
-
-typedef void (wxEvtHandler::*wxHtmlWindowEventFunction)(wxHtmlWindowEvent&);
-
-BEGIN_DECLARE_EVENT_TYPES()
-    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_HTML,
-                                wxEVT_COMMAND_HTMLWINDOW_URL_CLICKED, 1000)
-END_DECLARE_EVENT_TYPES()
-
-#define EVT_HTMLWINDOW_URL_CLICKED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_HTMLWINDOW_URL_CLICKED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxHtmlWindowEventFunction) & fn, (wxObject *) NULL ),
-
 #endif // wxUSE_WXHTML_HELP
 
 #endif
diff --git a/include/wx/html/htmlwin.h b/include/wx/html/htmlwin.h
index f8338ab280..d4629c9ad5 100644
--- a/include/wx/html/htmlwin.h
+++ b/include/wx/html/htmlwin.h
@@ -29,6 +29,8 @@ class wxHtmlWinModule;
 class wxHtmlHistoryArray;
 class wxHtmlProcessorList;
 class WXDLLIMPEXP_HTML wxHtmlWinAutoScrollTimer;
+class WXDLLIMPEXP_HTML wxHtmlCellEvent;
+class WXDLLIMPEXP_HTML wxHtmlLinkEvent;
 
 
 // wxHtmlWindow flags:
@@ -547,6 +549,101 @@ private:
 };
 
 
+
+
+BEGIN_DECLARE_EVENT_TYPES()
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_HTML,
+                                wxEVT_COMMAND_HTML_CELL_CLICKED, 1000)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_HTML,
+                                wxEVT_COMMAND_HTML_CELL_HOVER, 1001)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_HTML,
+                                wxEVT_COMMAND_HTML_LINK_CLICKED, 1002)
+END_DECLARE_EVENT_TYPES()
+
+
+/*!
+ * Html cell window event
+ */
+
+class WXDLLIMPEXP_HTML wxHtmlCellEvent : public wxCommandEvent
+{
+public:
+    wxHtmlCellEvent() {}
+    wxHtmlCellEvent(wxEventType commandType, int id,
+                    wxHtmlCell *cell, const wxPoint &pt,
+                    const wxMouseEvent &ev)
+        : wxCommandEvent(commandType, id)
+    {
+        m_cell = cell;
+        m_pt = pt;
+        m_mouseEvent = ev;
+        m_bLinkWasClicked = false;
+    }
+
+    wxHtmlCell* GetCell() const { return m_cell; }
+    wxPoint GetPoint() const { return m_pt; }
+    wxMouseEvent GetMouseEvent() const { return m_mouseEvent; }
+
+    void SetLinkClicked(bool linkclicked) { m_bLinkWasClicked=linkclicked; }
+    bool GetLinkClicked() const { return m_bLinkWasClicked; }
+
+    // default copy ctor, assignment operator and dtor are ok
+    virtual wxEvent *Clone() const { return new wxHtmlCellEvent(*this); }
+
+private:
+    wxHtmlCell *m_cell;
+    wxMouseEvent m_mouseEvent;
+    wxPoint m_pt;
+
+    bool m_bLinkWasClicked;
+
+    DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHtmlCellEvent)
+};
+
+
+
+/*!
+ * Html link event
+ */
+
+class WXDLLIMPEXP_HTML wxHtmlLinkEvent : public wxCommandEvent
+{
+public:
+    wxHtmlLinkEvent() {}
+    wxHtmlLinkEvent(int id, const wxHtmlLinkInfo &linkinfo)
+        : wxCommandEvent(wxEVT_COMMAND_HTML_LINK_CLICKED, id)
+    {
+        m_linkInfo = linkinfo;
+    }
+
+    const wxHtmlLinkInfo &GetLinkInfo() const { return m_linkInfo; }
+
+    // default copy ctor, assignment operator and dtor are ok
+    virtual wxEvent *Clone() const { return new wxHtmlLinkEvent(*this); }
+
+private:
+    wxHtmlLinkInfo m_linkInfo;
+
+    DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHtmlLinkEvent)
+};
+
+
+typedef void (wxEvtHandler::*wxHtmlCellEventFunction)(wxHtmlCellEvent&);
+typedef void (wxEvtHandler::*wxHtmlLinkEventFunction)(wxHtmlLinkEvent&);
+
+#define wxHtmlCellEventHandler(func) \
+    (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxHtmlCellEventFunction, &func)
+#define wxHtmlLinkEventHandler(func) \
+    (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxHtmlLinkEventFunction, &func)
+
+#define EVT_HTML_CELL_CLICKED(id, fn) \
+    wx__DECLARE_EVT1(wxEVT_COMMAND_HTML_CELL_CLICKED, id, wxHtmlCellEventHandler(fn))
+#define EVT_HTML_CELL_HOVER(id, fn) \
+    wx__DECLARE_EVT1(wxEVT_COMMAND_HTML_CELL_HOVER, id, wxHtmlCellEventHandler(fn))
+#define EVT_HTML_LINK_CLICKED(id, fn) \
+    wx__DECLARE_EVT1(wxEVT_COMMAND_HTML_LINK_CLICKED, id, wxHtmlLinkEventHandler(fn))
+
+
 #endif // wxUSE_HTML
 
 #endif // _WX_HTMLWIN_H_
diff --git a/include/wx/htmllbox.h b/include/wx/htmllbox.h
index 6f225f8ec0..16dab9008f 100644
--- a/include/wx/htmllbox.h
+++ b/include/wx/htmllbox.h
@@ -114,8 +114,7 @@ protected:
 
     // This method may be overriden to handle clicking on a link in
     // the listbox. By default, clicking links is ignored.
-    virtual void OnLinkClicked(size_t WXUNUSED(n),
-                               const wxHtmlLinkInfo& WXUNUSED(link)) { }
+    virtual void OnLinkClicked(size_t n, const wxHtmlLinkInfo& link);
 
     // event handlers
     void OnSize(wxSizeEvent& event);
diff --git a/samples/htlbox/htlbox.cpp b/samples/htlbox/htlbox.cpp
index a53accf347..4e445bdeb1 100644
--- a/samples/htlbox/htlbox.cpp
+++ b/samples/htlbox/htlbox.cpp
@@ -78,9 +78,6 @@ protected:
     virtual void OnDrawSeparator(wxDC& dc, wxRect& rect, size_t n) const;
     virtual wxColour GetSelectedTextColour(const wxColour& colFg) const;
 
-    // override this method to handle mouse clicks
-    virtual void OnLinkClicked(size_t n, const wxHtmlLinkInfo& link);
-
     // flag telling us whether we should use fg colour even for the selected
     // item
     bool m_change;
@@ -88,11 +85,12 @@ protected:
     // flag which we toggle to update the first items text in OnGetItem()
     bool m_firstItemUpdated;
 
+public:
+
     // flag which we toggle when the user clicks on the link in 2nd item
     // to change 2nd item's text
     bool m_linkClicked;
 
-
 #ifdef USE_HTML_FILE
     wxTextFile m_file;
 #endif
@@ -132,6 +130,10 @@ public:
         wxLogMessage(_T("Listbox item %d double clicked."), event.GetInt());
     }
     
+    void OnHtmlLinkClicked(wxHtmlLinkEvent& event);
+    void OnHtmlCellHover(wxHtmlCellEvent &event);
+    void OnHtmlCellClicked(wxHtmlCellEvent &event);
+
     wxSimpleHtmlListBox *GetSimpleBox() 
         { return wxDynamicCast(m_hlbox, wxSimpleHtmlListBox); }
     MyHtmlListBox *GetMyBox()
@@ -206,6 +208,13 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 
     EVT_LISTBOX(wxID_ANY, MyFrame::OnLboxSelect)
     EVT_LISTBOX_DCLICK(wxID_ANY, MyFrame::OnLboxDClick)
+
+
+    // the HTML listbox's events
+    EVT_HTML_LINK_CLICKED(wxID_ANY, MyFrame::OnHtmlLinkClicked)
+    EVT_HTML_CELL_HOVER(wxID_ANY, MyFrame::OnHtmlCellHover)
+    EVT_HTML_CELL_CLICKED(wxID_ANY, MyFrame::OnHtmlCellClicked)
+
 END_EVENT_TABLE()
 
 IMPLEMENT_APP(MyApp)
@@ -454,6 +463,32 @@ void MyFrame::OnSetSelFgCol(wxCommandEvent& event)
     }
 }
 
+void MyFrame::OnHtmlLinkClicked(wxHtmlLinkEvent &event)
+{
+    wxLogMessage(wxT("The url '%s' has been clicked!"), event.GetLinkInfo().GetHref().c_str());
+
+    if (GetMyBox())
+    {
+        GetMyBox()->m_linkClicked = true;
+        GetMyBox()->RefreshLine(1);
+    }
+}
+
+void MyFrame::OnHtmlCellHover(wxHtmlCellEvent &event)
+{
+    wxLogMessage(wxT("Mouse moved over cell %p at %d;%d"),
+                 event.GetCell(), event.GetPoint().x, event.GetPoint().y);
+}
+
+void MyFrame::OnHtmlCellClicked(wxHtmlCellEvent &event)
+{
+    wxLogMessage(wxT("Click over cell %p at %d;%d"),
+                 event.GetCell(), event.GetPoint().x, event.GetPoint().y);
+
+    // if we don't skip the event, OnHtmlLinkClicked won't be called!
+    event.Skip();
+}
+
 // ----------------------------------------------------------------------------
 // listbox event handlers
 // ----------------------------------------------------------------------------
@@ -585,12 +620,3 @@ void MyHtmlListBox::UpdateFirstItem()
 
     RefreshLine(0);
 }
-
-void MyHtmlListBox::OnLinkClicked(size_t WXUNUSED(n),
-                                  const wxHtmlLinkInfo& WXUNUSED(link))
-{
-    m_linkClicked = true;
-
-    RefreshLine(1);
-}
-
diff --git a/samples/html/test/test.cpp b/samples/html/test/test.cpp
index c726b60907..eeab3617a7 100644
--- a/samples/html/test/test.cpp
+++ b/samples/html/test/test.cpp
@@ -71,6 +71,10 @@ public:
     void OnForward(wxCommandEvent& event);
     void OnProcessor(wxCommandEvent& event);
 
+    void OnHtmlLinkClicked(wxHtmlLinkEvent& event);
+    void OnHtmlCellHover(wxHtmlCellEvent &event);
+    void OnHtmlCellClicked(wxHtmlCellEvent &event);
+
 private:
     MyHtmlWindow *m_Html;
     wxHtmlProcessor *m_Processor;
@@ -121,6 +125,10 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(ID_Back, MyFrame::OnBack)
     EVT_MENU(ID_Forward, MyFrame::OnForward)
     EVT_MENU(ID_Processor, MyFrame::OnProcessor)
+
+    EVT_HTML_LINK_CLICKED(wxID_ANY, MyFrame::OnHtmlLinkClicked)
+    EVT_HTML_CELL_HOVER(wxID_ANY, MyFrame::OnHtmlCellHover)
+    EVT_HTML_CELL_CLICKED(wxID_ANY, MyFrame::OnHtmlCellClicked)
 END_EVENT_TABLE()
 
 IMPLEMENT_APP(MyApp)
@@ -216,6 +224,17 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
     m_Html->ReadCustomization(wxConfig::Get());
     m_Html->LoadFile(wxFileName(wxT("test.htm")));
     m_Html->AddProcessor(m_Processor);
+
+    wxTextCtrl *text = new wxTextCtrl(this, wxID_ANY, _T(""),
+                                      wxDefaultPosition, wxDefaultSize,
+                                      wxTE_MULTILINE);
+
+    delete wxLog::SetActiveTarget(new wxLogTextCtrl(text));
+
+    wxSizer *sz = new wxBoxSizer(wxVERTICAL);
+    sz->Add(m_Html, 3, wxGROW);
+    sz->Add(text, 1, wxGROW);
+    SetSizer(sz);
 }
 
 
@@ -272,6 +291,30 @@ void MyFrame::OnProcessor(wxCommandEvent& WXUNUSED(event))
     m_Html->LoadPage(m_Html->GetOpenedPage());
 }
 
+void MyFrame::OnHtmlLinkClicked(wxHtmlLinkEvent &event)
+{
+    wxLogMessage(wxT("The url '%s' has been clicked!"), event.GetLinkInfo().GetHref().c_str());
+
+    // skipping this event the default behaviour (load the clicked URL)
+    // will happen...
+    event.Skip();
+}
+
+void MyFrame::OnHtmlCellHover(wxHtmlCellEvent &event)
+{
+    wxLogMessage(wxT("Mouse moved over cell %d at %d;%d"),
+                 event.GetCell(), event.GetPoint().x, event.GetPoint().y);
+}
+
+void MyFrame::OnHtmlCellClicked(wxHtmlCellEvent &event)
+{
+    wxLogMessage(wxT("Click over cell %d at %d;%d"),
+                 event.GetCell(), event.GetPoint().x, event.GetPoint().y);
+
+    // if we don't skip the event, OnHtmlLinkClicked won't be called!
+    event.Skip();
+}
+
 wxHtmlOpeningStatus MyHtmlWindow::OnOpeningURL(wxHtmlURLType WXUNUSED(type),
                                                const wxString& url,
                                                wxString *WXUNUSED(redirect)) const
diff --git a/src/html/helpwnd.cpp b/src/html/helpwnd.cpp
index 1b55a9c21a..0d71ff3a0a 100644
--- a/src/html/helpwnd.cpp
+++ b/src/html/helpwnd.cpp
@@ -104,8 +104,6 @@ class wxHtmlHelpHashData : public wxObject
 // wxHtmlHelpHtmlWindow (private)
 //--------------------------------------------------------------------------
 
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_HTMLWINDOW_URL_CLICKED)
-IMPLEMENT_DYNAMIC_CLASS(wxHtmlWindowEvent, wxNotifyEvent)
 
 class wxHtmlHelpHtmlWindow : public wxHtmlWindow
 {
@@ -116,15 +114,9 @@ class wxHtmlHelpHtmlWindow : public wxHtmlWindow
             SetStandardFonts();
         }
 
-        virtual void OnLinkClicked(const wxHtmlLinkInfo& link)
+        void OnLinkClicked(wxHtmlLinkEvent& ev)
         {
-            wxHtmlWindowEvent event(wxEVT_COMMAND_HTMLWINDOW_URL_CLICKED, GetId());
-            event.SetURL(link.GetHref());
-            if (!ProcessEvent(event))
-            {
-                wxHtmlWindow::OnLinkClicked(link);
-            }
-            const wxMouseEvent *e = link.GetEvent();
+            const wxMouseEvent *e = ev.GetLinkInfo().GetEvent();
             if (e == NULL || e->LeftUp())
                 m_Window->NotifyPageChanged();
         }
@@ -149,8 +141,13 @@ class wxHtmlHelpHtmlWindow : public wxHtmlWindow
         wxHtmlHelpWindow *m_Window;
 
     DECLARE_NO_COPY_CLASS(wxHtmlHelpHtmlWindow)
+    DECLARE_EVENT_TABLE()
 };
 
+BEGIN_EVENT_TABLE(wxHtmlHelpHtmlWindow, wxHtmlWindow)
+    EVT_HTML_LINK_CLICKED(wxID_ANY, wxHtmlHelpHtmlWindow::OnLinkClicked)
+END_EVENT_TABLE()
+
 
 //---------------------------------------------------------------------------
 // wxHtmlHelpWindow::m_mergedIndex
diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp
index 431b30b32c..3311725dfc 100644
--- a/src/html/htmlwin.cpp
+++ b/src/html/htmlwin.cpp
@@ -34,6 +34,14 @@
 #include "wx/arrimpl.cpp"
 #include "wx/listimpl.cpp"
 
+// HTML events:
+IMPLEMENT_DYNAMIC_CLASS(wxHtmlLinkEvent, wxCommandEvent)
+IMPLEMENT_DYNAMIC_CLASS(wxHtmlCellEvent, wxCommandEvent)
+
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_HTML_CELL_CLICKED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_HTML_CELL_HOVER)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_HTML_LINK_CLICKED)
+
 
 #if wxUSE_CLIPBOARD
 // ----------------------------------------------------------------------------
@@ -227,18 +235,36 @@ bool wxHtmlWindowMouseHelper::OnCellClicked(wxHtmlCell *cell,
                                             wxCoord x, wxCoord y,
                                             const wxMouseEvent& event)
 {
-    wxCHECK_MSG( cell, false, _T("can't be called with NULL cell") );
+    wxHtmlCellEvent ev(wxEVT_COMMAND_HTML_CELL_CLICKED,
+                       m_interface->GetHTMLWindow()->GetId(),
+                       cell, wxPoint(x,y), event);
+
+    if (!m_interface->GetHTMLWindow()->GetEventHandler()->ProcessEvent(ev))
+    {
+        // if the event wasn't handled, do the default processing here:
+
+        wxASSERT_MSG( cell, _T("can't be called with NULL cell") );
+
+        cell->ProcessMouseClick(m_interface, ev.GetPoint(), ev.GetMouseEvent());
+    }
 
-    return cell->ProcessMouseClick(m_interface, wxPoint(x, y), event);
+    // true if a link was clicked, false otherwise
+    return ev.GetLinkClicked();
 }
 
-void wxHtmlWindowMouseHelper::OnCellMouseHover(wxHtmlCell * WXUNUSED(cell),
-                                               wxCoord WXUNUSED(x),
-                                               wxCoord WXUNUSED(y))
+void wxHtmlWindowMouseHelper::OnCellMouseHover(wxHtmlCell * cell,
+                                               wxCoord x,
+                                               wxCoord y)
 {
-    // do nothing here
+    wxHtmlCellEvent ev(wxEVT_COMMAND_HTML_CELL_HOVER,
+                       m_interface->GetHTMLWindow()->GetId(),
+                       cell, wxPoint(x,y), wxMouseEvent());
+    m_interface->GetHTMLWindow()->GetEventHandler()->ProcessEvent(ev);
 }
 
+
+
+
 //-----------------------------------------------------------------------------
 // wxHtmlWindow
 //-----------------------------------------------------------------------------
@@ -926,9 +952,14 @@ bool wxHtmlWindow::CopySelection(ClipboardType t)
 
 void wxHtmlWindow::OnLinkClicked(const wxHtmlLinkInfo& link)
 {
-    const wxMouseEvent *e = link.GetEvent();
-    if (e == NULL || e->LeftUp())
-        LoadPage(link.GetHref());
+    wxHtmlLinkEvent event(GetId(), link);
+    if (!GetEventHandler()->ProcessEvent(event))
+    {
+        // the default behaviour is to load the URL in this window
+        const wxMouseEvent *e = event.GetLinkInfo().GetEvent();
+        if (e == NULL || e->LeftUp())
+            LoadPage(event.GetLinkInfo().GetHref());
+    }
 }
 
 void wxHtmlWindow::OnEraseBackground(wxEraseEvent& event)
@@ -1256,7 +1287,8 @@ void wxHtmlWindow::OnInternalIdle()
                     if ( m_tmpSelFromCell->IsBefore(selcell) )
                     {
                         m_selection->Set(m_tmpSelFromPos, m_tmpSelFromCell,
-                                         wxPoint(x,y), selcell);                                    }
+                                         wxPoint(x,y), selcell);
+                    }
                     else
                     {
                         m_selection->Set(wxPoint(x,y), selcell,
-- 
2.50.0

