+#if wxUSE_CLIPBOARD
+void wxHtmlWindow::StopAutoScrolling()
+{
+ if ( m_timerAutoScroll )
+ {
+ wxDELETE(m_timerAutoScroll);
+ }
+}
+
+void wxHtmlWindow::OnMouseEnter(wxMouseEvent& event)
+{
+ StopAutoScrolling();
+ event.Skip();
+}
+
+void wxHtmlWindow::OnMouseLeave(wxMouseEvent& event)
+{
+ // don't prevent the usual processing of the event from taking place
+ event.Skip();
+
+ // when a captured mouse leave a scrolled window we start generate
+ // scrolling events to allow, for example, extending selection beyond the
+ // visible area in some controls
+ if ( wxWindow::GetCapture() == this )
+ {
+ // where is the mouse leaving?
+ int pos, orient;
+ wxPoint pt = event.GetPosition();
+ if ( pt.x < 0 )
+ {
+ orient = wxHORIZONTAL;
+ pos = 0;
+ }
+ else if ( pt.y < 0 )
+ {
+ orient = wxVERTICAL;
+ pos = 0;
+ }
+ else // we're lower or to the right of the window
+ {
+ wxSize size = GetClientSize();
+ if ( pt.x > size.x )
+ {
+ orient = wxHORIZONTAL;
+ pos = GetVirtualSize().x / wxHTML_SCROLL_STEP;
+ }
+ else if ( pt.y > size.y )
+ {
+ orient = wxVERTICAL;
+ pos = GetVirtualSize().y / wxHTML_SCROLL_STEP;
+ }
+ else // this should be impossible
+ {
+ // but seems to happen sometimes under wxMSW - maybe it's a bug
+ // there but for now just ignore it
+
+ //wxFAIL_MSG( _T("can't understand where has mouse gone") );
+
+ return;
+ }
+ }
+
+ // only start the auto scroll timer if the window can be scrolled in
+ // this direction
+ if ( !HasScrollbar(orient) )
+ return;
+
+ delete m_timerAutoScroll;
+ m_timerAutoScroll = new wxHtmlWinAutoScrollTimer
+ (
+ this,
+ pos == 0 ? wxEVT_SCROLLWIN_LINEUP
+ : wxEVT_SCROLLWIN_LINEDOWN,
+ pos,
+ orient
+ );
+ m_timerAutoScroll->Start(50); // FIXME: make configurable
+ }
+}
+
+void wxHtmlWindow::OnKeyUp(wxKeyEvent& event)
+{
+ if ( IsSelectionEnabled() &&
+ event.GetKeyCode() == 'C' && event.ControlDown() )
+ {
+ (void) CopySelection();
+ }
+}
+
+void wxHtmlWindow::OnCopy(wxCommandEvent& WXUNUSED(event))
+{
+ (void) CopySelection();
+}
+
+void wxHtmlWindow::OnDoubleClick(wxMouseEvent& event)
+{
+ // select word under cursor:
+ if ( IsSelectionEnabled() )
+ {
+ SelectWord(CalcUnscrolledPosition(event.GetPosition()));
+
+ (void) CopySelection(Primary);
+
+ m_lastDoubleClick = wxGetLocalTimeMillis();
+ }
+ else
+ event.Skip();
+}
+
+void wxHtmlWindow::SelectWord(const wxPoint& pos)
+{
+ wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
+ if ( cell )
+ {
+ delete m_selection;
+ m_selection = new wxHtmlSelection();
+ m_selection->Set(cell, cell);
+ RefreshRect(wxRect(CalcScrolledPosition(cell->GetAbsPos()),
+ wxSize(cell->GetWidth(), cell->GetHeight())));
+ }
+}
+
+void wxHtmlWindow::SelectLine(const wxPoint& pos)
+{
+ wxHtmlCell *cell = m_Cell->FindCellByPos(pos.x, pos.y);
+ if ( cell )
+ {
+ // We use following heuristic to find a "line": let the line be all
+ // cells in same container as the cell under mouse cursor that are
+ // neither completely above nor completely bellow the clicked cell
+ // (i.e. are likely to be words positioned on same line of text).
+
+ int y1 = cell->GetAbsPos().y;
+ int y2 = y1 + cell->GetHeight();
+ int y;
+ const wxHtmlCell *c;
+ const wxHtmlCell *before = NULL;
+ const wxHtmlCell *after = NULL;
+
+ // find last cell of line:
+ for ( c = cell->GetNext(); c; c = c->GetNext())
+ {
+ y = c->GetAbsPos().y;
+ if ( y + c->GetHeight() > y1 && y < y2 )
+ after = c;
+ else
+ break;
+ }
+ if ( !after )
+ after = cell;
+
+ // find first cell of line:
+ for ( c = cell->GetParent()->GetFirstChild();
+ c && c != cell; c = c->GetNext())
+ {
+ y = c->GetAbsPos().y;
+ if ( y + c->GetHeight() > y1 && y < y2 )
+ {
+ if ( ! before )
+ before = c;
+ }
+ else
+ before = NULL;
+ }
+ if ( !before )
+ before = cell;
+
+ delete m_selection;
+ m_selection = new wxHtmlSelection();
+ m_selection->Set(before, after);
+
+ Refresh();
+ }
+}
+#endif // wxUSE_CLIPBOARD
+
+