+ if (m_windowStyle & wxTE_MULTILINE)
+ {
+#ifdef __WXGTK20__
+ GtkTextIter fromi, toi;
+ gtk_text_buffer_get_iter_at_offset( m_buffer, &fromi, from );
+ gtk_text_buffer_get_iter_at_offset( m_buffer, &toi, to );
+
+ gtk_text_buffer_place_cursor( m_buffer, &toi );
+ gtk_text_buffer_move_mark_by_name( m_buffer, "selection_bound", &fromi );
+#else
+ gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
+#endif
+ }
+ else
+ {
+ gtk_editable_select_region( GTK_EDITABLE(m_text), (gint)from, (gint)to );
+ }
+}
+
+void wxTextCtrl::ShowPosition( long pos )
+{
+ if (m_windowStyle & wxTE_MULTILINE)
+ {
+#ifdef __WXGTK20__
+ GtkTextIter iter;
+ gtk_text_buffer_get_start_iter( m_buffer, &iter );
+ gtk_text_iter_set_offset( &iter, pos );
+ GtkTextMark *mark = gtk_text_buffer_create_mark( m_buffer, NULL, &iter, TRUE );
+ gtk_text_view_scroll_to_mark( GTK_TEXT_VIEW(m_text), mark, 0.0, FALSE, 0.0, 0.0 );
+#else // GTK 1.x
+ GtkAdjustment *vp = GTK_TEXT(m_text)->vadj;
+ float totalLines = (float) GetNumberOfLines();
+ long posX;
+ long posY;
+ PositionToXY(pos, &posX, &posY);
+ float posLine = (float) posY;
+ float p = (posLine/totalLines)*(vp->upper - vp->lower) + vp->lower;
+ gtk_adjustment_set_value(GTK_TEXT(m_text)->vadj, p);
+#endif // GTK 1.x/2.x
+ }
+}
+
+#ifdef __WXGTK20__
+
+wxTextCtrlHitTestResult
+wxTextCtrl::HitTest(const wxPoint& pt, long *pos) const
+{
+ if ( !IsMultiLine() )
+ {
+ // not supported
+ return wxTE_HT_UNKNOWN;
+ }
+
+ int x, y;
+ gtk_text_view_window_to_buffer_coords
+ (
+ GTK_TEXT_VIEW(m_text),
+ GTK_TEXT_WINDOW_TEXT,
+ pt.x, pt.y,
+ &x, &y
+ );
+
+ GtkTextIter iter;
+ gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(m_text), &iter, x, y);
+ if ( pos )
+ *pos = gtk_text_iter_get_offset(&iter);
+
+ return wxTE_HT_ON_TEXT;
+}
+
+#endif // __WXGTK20__
+
+long wxTextCtrl::GetInsertionPoint() const
+{
+ wxCHECK_MSG( m_text != NULL, 0, wxT("invalid text ctrl") );
+
+#ifdef __WXGTK20__
+ if (m_windowStyle & wxTE_MULTILINE)
+ {
+ // There is no direct accessor for the cursor, but
+ // internally, the cursor is the "mark" called
+ // "insert" in the text view's btree structure.
+
+ GtkTextMark *mark = gtk_text_buffer_get_insert( m_buffer );
+ GtkTextIter cursor;
+ gtk_text_buffer_get_iter_at_mark( m_buffer, &cursor, mark );
+
+ return gtk_text_iter_get_offset( &cursor );
+ }
+ else
+#endif
+ {
+ return (long) GET_EDITABLE_POS(m_text);
+ }
+}
+
+long wxTextCtrl::GetLastPosition() const
+{
+ wxCHECK_MSG( m_text != NULL, 0, wxT("invalid text ctrl") );
+
+ int pos = 0;
+
+ if (m_windowStyle & wxTE_MULTILINE)
+ {
+#ifdef __WXGTK20__
+ GtkTextIter end;
+ gtk_text_buffer_get_end_iter( m_buffer, &end );
+
+ pos = gtk_text_iter_get_offset( &end );
+#else
+ pos = gtk_text_get_length( GTK_TEXT(m_text) );
+#endif
+ }
+ else
+ {
+ pos = GTK_ENTRY(m_text)->text_length;
+ }
+
+ return (long)pos;
+}
+
+void wxTextCtrl::Remove( long from, long to )
+{
+ wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
+
+#ifdef __WXGTK20__
+ if (m_windowStyle & wxTE_MULTILINE)
+ {
+ GtkTextIter fromi, toi;
+ gtk_text_buffer_get_iter_at_offset( m_buffer, &fromi, from );
+ gtk_text_buffer_get_iter_at_offset( m_buffer, &toi, to );
+
+ gtk_text_buffer_delete( m_buffer, &fromi, &toi );
+ }
+ else // single line
+#endif
+ gtk_editable_delete_text( GTK_EDITABLE(m_text), (gint)from, (gint)to );
+}
+
+void wxTextCtrl::Replace( long from, long to, const wxString &value )
+{
+ wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
+
+ Remove( from, to );
+
+ if (!value.IsEmpty())
+ {
+#ifdef __WXGTK20__
+ SetInsertionPoint( from );
+ WriteText( value );
+#else // GTK 1.x
+ gint pos = (gint)from;
+#if wxUSE_UNICODE
+ wxWX2MBbuf buf = value.mbc_str();
+ gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &pos );
+#else
+ gtk_editable_insert_text( GTK_EDITABLE(m_text), value, value.Length(), &pos );
+#endif // wxUSE_UNICODE
+#endif // GTK 1.x/2.x
+ }
+}
+
+void wxTextCtrl::Cut()
+{
+ wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
+
+#ifdef __WXGTK20__
+ if (m_windowStyle & wxTE_MULTILINE)
+ g_signal_emit_by_name(m_text, "cut-clipboard");
+ else
+#endif
+ gtk_editable_cut_clipboard(GTK_EDITABLE(m_text) DUMMY_CLIPBOARD_ARG);
+}
+
+void wxTextCtrl::Copy()
+{
+ wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
+
+#ifdef __WXGTK20__
+ if (m_windowStyle & wxTE_MULTILINE)
+ g_signal_emit_by_name(m_text, "copy-clipboard");
+ else
+#endif
+ gtk_editable_copy_clipboard(GTK_EDITABLE(m_text) DUMMY_CLIPBOARD_ARG);
+}
+
+void wxTextCtrl::Paste()