+ gtk_text_insert( GTK_TEXT(text), font, colFg, colBg, txt, len );
+}
+}
+
+// ----------------------------------------------------------------------------
+// "insert_text" for GtkEntry
+// ----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_insert_text_callback(GtkEditable *editable,
+ const gchar *WXUNUSED(new_text),
+ gint WXUNUSED(new_text_length),
+ gint *WXUNUSED(position),
+ wxTextCtrl *win)
+{
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ // we should only be called if we have a max len limit at all
+ GtkEntry *entry = GTK_ENTRY (editable);
+
+ wxCHECK_RET( entry->text_max_length, wxT("shouldn't be called") );
+
+ // check that we don't overflow the max length limit
+ //
+ // FIXME: this doesn't work when we paste a string which is going to be
+ // truncated
+ if ( entry->text_length == entry->text_max_length )
+ {
+ // we don't need to run the base class version at all
+ gtk_signal_emit_stop_by_name(GTK_OBJECT(editable), "insert_text");
+
+ // remember that the next changed signal is to be ignored to avoid
+ // generating a dummy wxEVT_TEXT event
+ win->IgnoreNextTextUpdate();
+
+ // and generate the correct one ourselves
+ wxCommandEvent event(wxEVT_TEXT_MAXLEN, win->GetId());
+ event.SetEventObject(win);
+ event.SetString(win->GetValue());
+ win->HandleWindowEvent( event );
+ }
+}
+}
+
+//-----------------------------------------------------------------------------
+// "changed"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_text_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
+{
+ if ( win->IgnoreTextUpdate() )
+ return;
+
+ if (!win->m_hasVMT) return;
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ win->SetModified();
+ win->UpdateFontIfNeeded();
+
+ wxCommandEvent event( wxEVT_TEXT, win->GetId() );
+ event.SetEventObject( win );
+ win->HandleWindowEvent( event );
+}
+}
+
+//-----------------------------------------------------------------------------
+// "changed" from vertical scrollbar
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win )
+{
+ if (!win->m_hasVMT) return;
+
+ if (g_isIdle)
+ wxapp_install_idle_handler();
+
+ win->CalculateScrollbar();
+}
+}
+
+// ----------------------------------------------------------------------------
+// redraw callback for multiline text
+// ----------------------------------------------------------------------------
+
+// redrawing a GtkText from inside a wxYield() call results in crashes (the
+// text sample shows it in its "Add lines" command which shows wxProgressDialog
+// which implicitly calls wxYield()) so we override GtkText::draw() and simply
+// don't do anything if we're inside wxYield()
+
+extern "C" {
+ typedef void (*GtkDrawCallback)(GtkWidget *widget, GdkRectangle *rect);
+}
+
+static GtkDrawCallback gs_gtk_text_draw = NULL;
+
+extern "C" {
+static void wxgtk_text_draw( GtkWidget *widget, GdkRectangle *rect)
+{
+ wxEventLoopBase* loop = wxEventLoopBase::GetActive();
+ if ( loop && !loop->IsYielding() )
+ {
+ wxCHECK_RET( gs_gtk_text_draw != wxgtk_text_draw,
+ wxT("infinite recursion in wxgtk_text_draw aborted") );
+
+ gs_gtk_text_draw(widget, rect);
+ }
+}
+}
+
+//-----------------------------------------------------------------------------
+// wxTextCtrl
+//-----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
+ EVT_CHAR(wxTextCtrl::OnChar)
+
+ EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
+ EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
+ EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
+ EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
+ EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
+
+ EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
+ EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
+ EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
+ EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
+ EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)