+    // If we have a custom background colour, we use this colour in both
+    // disabled and enabled mode, or we end up with a different colour under the
+    // text.
+    wxColour oldColour = GetBackgroundColour();
+    if (oldColour.Ok())
+    {
+        // Need to set twice or it'll optimize the useful stuff out
+        if (oldColour == * wxWHITE)
+            SetBackgroundColour(*wxBLACK);
+        else
+            SetBackgroundColour(*wxWHITE);
+        SetBackgroundColour(oldColour);
+    }
+}
+
+void wxTextCtrl::MarkDirty()
+{
+    m_modified = TRUE;
+}
+
+void wxTextCtrl::DiscardEdits()
+{
+    m_modified = FALSE;
+}
+
+// ----------------------------------------------------------------------------
+// max text length support
+// ----------------------------------------------------------------------------
+
+void wxTextCtrl::IgnoreNextTextUpdate()
+{
+    m_ignoreNextUpdate = TRUE;
+}
+
+bool wxTextCtrl::IgnoreTextUpdate()
+{
+    if ( m_ignoreNextUpdate )
+    {
+        m_ignoreNextUpdate = FALSE;
+
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+void wxTextCtrl::SetMaxLength(unsigned long len)
+{
+    if ( !HasFlag(wxTE_MULTILINE) )
+    {
+        gtk_entry_set_max_length(GTK_ENTRY(m_text), len);
+
+        // there is a bug in GTK+ 1.2.x: "changed" signal is emitted even if
+        // we had tried to enter more text than allowed by max text length and
+        // the text wasn't really changed
+        //
+        // to detect this and generate TEXT_MAXLEN event instead of
+        // TEXT_CHANGED one in this case we also catch "insert_text" signal
+        //
+        // when max len is set to 0 we disconnect our handler as it means that
+        // we shouldn't check anything any more
+        if ( len )
+        {
+            gtk_signal_connect( GTK_OBJECT(m_text),
+                                "insert_text",
+                                GTK_SIGNAL_FUNC(gtk_insert_text_callback),
+                                (gpointer)this);
+        }
+        else // no checking
+        {
+            gtk_signal_disconnect_by_func
+            (
+                GTK_OBJECT(m_text),
+                GTK_SIGNAL_FUNC(gtk_insert_text_callback),
+                (gpointer)this
+            );
+        }
+    }
+}
+
+void wxTextCtrl::SetSelection( long from, long to )
+{
+    wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") );
+
+    if (from == -1 && to == -1)
+    {
+        from = 0;
+        to = GetValue().Length();
+    }
+
+#ifndef __WXGTK20__
+    if ( (m_windowStyle & wxTE_MULTILINE) &&
+         !GTK_TEXT(m_text)->line_start_cache )
+    {
+        // tell the programmer that it didn't work
+        wxLogDebug(_T("Can't call SetSelection() before realizing the control"));
+        return;
+    }
+#endif
+
+    if (m_windowStyle & wxTE_MULTILINE)
+    {
+#ifdef __WXGTK20__
+        GtkTextBuffer *buf = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_text) );
+
+        GtkTextIter fromi, toi;
+        gtk_text_buffer_get_iter_at_offset( buf, &fromi, from );
+        gtk_text_buffer_get_iter_at_offset( buf, &toi, to );
+
+        gtk_text_buffer_place_cursor( buf, &toi );
+        gtk_text_buffer_move_mark_by_name( buf, "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__
+        GtkTextBuffer *buf = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_text) );
+        GtkTextIter iter;
+        gtk_text_buffer_get_start_iter( buf, &iter );
+        gtk_text_iter_set_offset( &iter, pos );
+        GtkTextMark *mark = gtk_text_buffer_create_mark( buf, 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
+    }
+}
+
+long wxTextCtrl::GetInsertionPoint() const
+{
+    wxCHECK_MSG( m_text != NULL, 0, wxT("invalid text ctrl") );
+
+#ifdef __WXGTK20__
+    if (m_windowStyle & wxTE_MULTILINE)
+    {
+        GtkTextBuffer *text_buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_text) );
+
+        // There is no direct accessor for the cursor, but
+        // internally, the cursor is the "mark" called
+        // "insert" in the text view's btree structure.