+
+// ----------------------------------------------------------------------------
+// freeze/thaw
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::DoFreeze()
+{
+ wxCHECK_RET(m_text != NULL, wxT("invalid text ctrl"));
+
+ GTKFreezeWidget(m_text);
+
+ if ( HasFlag(wxTE_MULTILINE) )
+ {
+ // removing buffer dramatically speeds up insertion:
+ g_object_ref(m_buffer);
+ GtkTextBuffer* buf_new = gtk_text_buffer_new(NULL);
+ gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), buf_new);
+ // gtk_text_view_set_buffer adds its own reference
+ g_object_unref(buf_new);
+ // These marks should be deleted when the buffer is changed,
+ // but they are not (in GTK+ up to at least 3.0.1).
+ // Otherwise these anonymous marks start to build up in the buffer,
+ // and Freeze takes longer and longer each time it is called.
+ if (m_anonymousMarkList)
+ {
+ for (GSList* item = m_anonymousMarkList; item; item = item->next)
+ {
+ GtkTextMark* mark = static_cast<GtkTextMark*>(item->data);
+ if (GTK_IS_TEXT_MARK(mark) && !gtk_text_mark_get_deleted(mark))
+ gtk_text_buffer_delete_mark(m_buffer, mark);
+ }
+ g_slist_free(m_anonymousMarkList);
+ m_anonymousMarkList = NULL;
+ }
+ }
+}
+
+void wxTextCtrl::DoThaw()
+{
+ if ( HasFlag(wxTE_MULTILINE) )
+ {
+ // reattach buffer:
+ gulong sig_id = g_signal_connect(m_buffer, "mark_set", G_CALLBACK(mark_set), &m_anonymousMarkList);
+ gtk_text_view_set_buffer(GTK_TEXT_VIEW(m_text), m_buffer);
+ g_object_unref(m_buffer);
+ g_signal_handler_disconnect(m_buffer, sig_id);
+
+ if (m_showPositionOnThaw != NULL)
+ {
+ gtk_text_view_scroll_mark_onscreen(
+ GTK_TEXT_VIEW(m_text), m_showPositionOnThaw);
+ m_showPositionOnThaw = NULL;
+ }
+ }
+
+ GTKThawWidget(m_text);
+}
+
+// ----------------------------------------------------------------------------
+// wxTextUrlEvent passing if style & wxTE_AUTO_URL
+// ----------------------------------------------------------------------------
+
+// FIXME: when dragging on a link the sample gets an "Unknown event".
+// This might be an excessive event from us or a buggy wxMouseEvent::Moving() or
+// a buggy sample, or something else
+void wxTextCtrl::OnUrlMouseEvent(wxMouseEvent& event)
+{
+ event.Skip();
+ if( !HasFlag(wxTE_AUTO_URL) )
+ return;
+
+ gint x, y;
+ GtkTextIter start, end;
+ GtkTextTag *tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(m_buffer),
+ "wxUrl");
+
+ gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(m_text), GTK_TEXT_WINDOW_WIDGET,
+ event.GetX(), event.GetY(), &x, &y);
+
+ gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(m_text), &end, x, y);
+ if (!gtk_text_iter_has_tag(&end, tag))
+ {
+ SetCursor(wxCursor(wxCURSOR_IBEAM));
+ return;
+ }
+
+ SetCursor(wxCursor(wxCURSOR_HAND));
+
+ start = end;
+ if(!gtk_text_iter_begins_tag(&start, tag))
+ gtk_text_iter_backward_to_tag_toggle(&start, tag);
+ if(!gtk_text_iter_ends_tag(&end, tag))
+ gtk_text_iter_forward_to_tag_toggle(&end, tag);
+
+ // Native context menu is probably not desired on an URL.
+ // Consider making this dependent on ProcessEvent(wxTextUrlEvent) return value
+ if(event.GetEventType() == wxEVT_RIGHT_DOWN)
+ event.Skip(false);
+
+ wxTextUrlEvent url_event(m_windowId, event,
+ gtk_text_iter_get_offset(&start),
+ gtk_text_iter_get_offset(&end));
+
+ InitCommandEvent(url_event);
+ // Is that a good idea? Seems not (pleasure with gtk_text_view_start_selection_drag)
+ //event.Skip(!HandleWindowEvent(url_event));
+ HandleWindowEvent(url_event);
+}
+
+bool wxTextCtrl::GTKProcessEvent(wxEvent& event) const