+ 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.
+
+ GtkTextMark *mark = gtk_text_buffer_get_insert( text_buffer );
+ GtkTextIter cursor;
+ gtk_text_buffer_get_iter_at_mark( text_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") );
+