+
+#ifndef WX_PRECOMP
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/utils.h"
+    #include "wx/panel.h"
+    #include "wx/settings.h"
+    #include "wx/math.h"
+#endif
+
+#include "wx/strconv.h"
+#include "wx/fontutil.h"        // for wxNativeFontInfo (GetNativeFontInfo())
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#include "wx/gtk1/private.h"
+#include <gdk/gdkkeysyms.h>
+
+//-----------------------------------------------------------------------------
+// idle system
+//-----------------------------------------------------------------------------
+
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+
+//-----------------------------------------------------------------------------
+// data
+//-----------------------------------------------------------------------------
+
+extern wxCursor   g_globalCursor;
+extern wxWindowGTK *g_delayedFocus;
+
+// ----------------------------------------------------------------------------
+// helpers
+// ----------------------------------------------------------------------------
+
+extern "C" {
+static void wxGtkTextInsert(GtkWidget *text,
+                            const wxTextAttr& attr,
+                            const char *txt,
+                            size_t len)
+{
+    GdkFont *font = attr.HasFont() ? attr.GetFont().GetInternalFont()
+                                   : NULL;
+
+    GdkColor *colFg = attr.HasTextColour() ? attr.GetTextColour().GetColor()
+                                           : NULL;
+
+    GdkColor *colBg = attr.HasBackgroundColour()
+                        ? attr.GetBackgroundColour().GetColor()
+                        : NULL;
+
+    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 *new_text,
+                         gint new_text_length,
+                         gint *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, _T("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_COMMAND_TEXT_UPDATED event
+        win->IgnoreNextTextUpdate();
+
+        // and generate the correct one ourselves
+        wxCommandEvent event(wxEVT_COMMAND_TEXT_MAXLEN, win->GetId());
+        event.SetEventObject(win);
+        event.SetString(win->GetValue());
+        win->GetEventHandler()->ProcessEvent( event );
+    }
+}
+}
+
+//-----------------------------------------------------------------------------
+//  "changed"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_text_changed_callback( GtkWidget *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_COMMAND_TEXT_UPDATED, win->GetId() );
+    event.SetEventObject( win );
+    win->GetEventHandler()->ProcessEvent( 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 bool wxIsInsideYield;
+
+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)
+{
+    if ( !wxIsInsideYield )
+    {
+        wxCHECK_RET( gs_gtk_text_draw != wxgtk_text_draw,
+                     _T("infinite recursion in wxgtk_text_draw aborted") );
+
+        gs_gtk_text_draw(widget, rect);
+    }
+}
+}