+    wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
+
+    if ( pos == GetLastPosition() )
+        pos = -1;
+
+    GtkWidget *entry = GTK_COMBO(m_widget)->entry;
+    gtk_entry_set_position( GTK_ENTRY(entry), (int)pos );
+}
+
+long wxComboBox::GetInsertionPoint() const
+{
+    return (long) GET_EDITABLE_POS( GTK_COMBO(m_widget)->entry );
+}
+
+wxTextPos wxComboBox::GetLastPosition() const
+{
+    GtkWidget *entry = GTK_COMBO(m_widget)->entry;
+    int pos = GTK_ENTRY(entry)->text_length;
+    return (long) pos-1;
+}
+
+void wxComboBox::Replace( long from, long to, const wxString& value )
+{
+    wxCHECK_RET( m_widget != NULL, wxT("invalid combobox") );
+
+    GtkWidget *entry = GTK_COMBO(m_widget)->entry;
+    gtk_editable_delete_text( GTK_EDITABLE(entry), (gint)from, (gint)to );
+    if (value.IsNull()) return;
+    gint pos = (gint)to;
+
+#if wxUSE_UNICODE
+    wxCharBuffer buffer = wxConvUTF8.cWX2MB( value );
+    gtk_editable_insert_text( GTK_EDITABLE(entry), (const char*) buffer, strlen( (const char*) buffer ), &pos );
+#else
+    gtk_editable_insert_text( GTK_EDITABLE(entry), value.c_str(), value.Length(), &pos );
+#endif
+}
+
+void wxComboBox::SetSelection( long from, long to )
+{
+    GtkWidget *entry = GTK_COMBO(m_widget)->entry;
+    gtk_editable_select_region( GTK_EDITABLE(entry), (gint)from, (gint)to );
+}
+
+void wxComboBox::GetSelection( long* from, long* to ) const
+{
+    if (IsEditable())
+    {
+        GtkEditable *editable = GTK_EDITABLE(GTK_COMBO(m_widget)->entry);
+#ifdef __WXGTK20__
+        gint start, end;
+        gtk_editable_get_selection_bounds(editable, & start, & end);
+        *from = start;
+        *to = end;
+#else
+        *from = (long) editable->selection_start_pos;
+        *to = (long) editable->selection_end_pos;
+#endif
+    }
+}
+
+void wxComboBox::SetEditable( bool editable )
+{
+    GtkWidget *entry = GTK_COMBO(m_widget)->entry;
+    gtk_entry_set_editable( GTK_ENTRY(entry), editable );
+}
+
+void wxComboBox::OnChar( wxKeyEvent &event )
+{
+    if ( event.GetKeyCode() == WXK_RETURN )
+    {
+        // GTK automatically selects an item if its in the list
+        wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, GetId());
+        event.SetString( GetValue() );
+        event.SetInt( GetSelection() );
+        event.SetEventObject( this );
+
+        if (!GetEventHandler()->ProcessEvent( event ))
+        {
+            // This will invoke the dialog default action, such
+            // as the clicking the default button.
+
+            wxWindow *top_frame = m_parent;
+            while (top_frame->GetParent() && !(top_frame->IsTopLevel()))
+                top_frame = top_frame->GetParent();
+
+            if (top_frame && GTK_IS_WINDOW(top_frame->m_widget))
+            {
+                GtkWindow *window = GTK_WINDOW(top_frame->m_widget);
+
+                if (window->default_widget)
+                        gtk_widget_activate (window->default_widget);
+            }
+        }
+
+        // Catch GTK event so that GTK doesn't open the drop
+        // down list upon RETURN.
+        return;
+    }
+
+    event.Skip();
+}
+
+void wxComboBox::DisableEvents()
+{
+    gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(m_widget)->list),
+      GTK_SIGNAL_FUNC(gtk_combo_select_child_callback), (gpointer)this );
+    gtk_signal_disconnect_by_func( GTK_OBJECT(GTK_COMBO(m_widget)->entry),
+      GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this );
+}
+
+void wxComboBox::EnableEvents()
+{
+    gtk_signal_connect_after( GTK_OBJECT(GTK_COMBO(m_widget)->list), "select-child",
+      GTK_SIGNAL_FUNC(gtk_combo_select_child_callback), (gpointer)this );
+    gtk_signal_connect_after( GTK_OBJECT(GTK_COMBO(m_widget)->entry), "changed",
+      GTK_SIGNAL_FUNC(gtk_text_changed_callback), (gpointer)this );
+}
+
+void wxComboBox::OnSize( wxSizeEvent &event )
+{
+    // NB: In some situations (e.g. on non-first page of a wizard, if the
+    //     size used is default size), GtkCombo widget is resized correctly,
+    //     but it's look is not updated, it's rendered as if it was much wider.
+    //     No other widgets are affected, so it looks like a bug in GTK+.
+    //     Manually requesting resize calculation (as gtk_pizza_set_size does)
+    //     fixes it.
+    if (GTK_WIDGET_VISIBLE(m_widget))
+        gtk_widget_queue_resize(m_widget);
+
+    event.Skip();
+}
+
+void wxComboBox::DoApplyWidgetStyle(GtkRcStyle *style)
+{
+//    gtk_widget_modify_style( GTK_COMBO(m_widget)->button, syle );
+
+    gtk_widget_modify_style( GTK_COMBO(m_widget)->entry, style );
+    gtk_widget_modify_style( GTK_COMBO(m_widget)->list, style );
+
+    GtkList *list = GTK_LIST( GTK_COMBO(m_widget)->list );
+    GList *child = list->children;
+    while (child)
+    {
+        gtk_widget_modify_style( GTK_WIDGET(child->data), style );
+
+        GtkBin *bin = GTK_BIN(child->data);
+        gtk_widget_modify_style( bin->child, style );
+
+        child = child->next;
+    }
+}
+
+GtkWidget* wxComboBox::GetConnectWidget()
+{
+    return GTK_COMBO(m_widget)->entry;
+}
+
+bool wxComboBox::IsOwnGtkWindow( GdkWindow *window )
+{
+    return ( (window == GTK_ENTRY( GTK_COMBO(m_widget)->entry )->text_area) ||
+             (window == GTK_COMBO(m_widget)->button->window ) );
+}
+
+wxSize wxComboBox::DoGetBestSize() const
+{
+    wxSize ret( wxControl::DoGetBestSize() );
+
+    // we know better our horizontal extent: it depends on the longest string
+    // in the combobox
+    if ( m_widget )
+    {
+        int width;
+        size_t count = GetCount();
+        for ( size_t n = 0; n < count; n++ )
+        {
+            GetTextExtent( GetString(n), &width, NULL, NULL, NULL );
+            if ( width > ret.x )
+                ret.x = width;
+        }
+    }
+
+    // empty combobox should have some reasonable default size too
+    if ( ret.x < 100 )
+        ret.x = 100;
+
+    CacheBestSize(ret);
+    return ret;
+}
+
+// static
+wxVisualAttributes
+wxComboBox::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
+{
+    return GetDefaultAttributesFromGTKWidget(gtk_combo_new, true);
+}
+
+// ----------------------------------------------------------------------------
+// standard event handling
+// ----------------------------------------------------------------------------
+
+void wxComboBox::OnCut(wxCommandEvent& WXUNUSED(event))
+{
+    Cut();
+}
+
+void wxComboBox::OnCopy(wxCommandEvent& WXUNUSED(event))
+{
+    Copy();
+}
+
+void wxComboBox::OnPaste(wxCommandEvent& WXUNUSED(event))
+{
+    Paste();
+}
+
+void wxComboBox::OnUndo(wxCommandEvent& WXUNUSED(event))
+{
+    Undo();
+}
+
+void wxComboBox::OnRedo(wxCommandEvent& WXUNUSED(event))
+{
+    Redo();
+}
+
+void wxComboBox::OnDelete(wxCommandEvent& WXUNUSED(event))
+{
+    long from, to;
+    GetSelection(& from, & to);
+    if (from != -1 && to != -1)
+        Remove(from, to);
+}
+
+void wxComboBox::OnSelectAll(wxCommandEvent& WXUNUSED(event))
+{
+    SetSelection(-1, -1);
+}
+
+void wxComboBox::OnUpdateCut(wxUpdateUIEvent& event)
+{
+    event.Enable( CanCut() );
+}
+
+void wxComboBox::OnUpdateCopy(wxUpdateUIEvent& event)
+{
+    event.Enable( CanCopy() );
+}
+
+void wxComboBox::OnUpdatePaste(wxUpdateUIEvent& event)
+{
+    event.Enable( CanPaste() );
+}
+
+void wxComboBox::OnUpdateUndo(wxUpdateUIEvent& event)
+{
+    event.Enable( CanUndo() );
+}
+
+void wxComboBox::OnUpdateRedo(wxUpdateUIEvent& event)
+{
+    event.Enable( CanRedo() );
+}
+
+void wxComboBox::OnUpdateDelete(wxUpdateUIEvent& event)
+{
+    event.Enable(HasSelection() && IsEditable()) ;
+}
+
+void wxComboBox::OnUpdateSelectAll(wxUpdateUIEvent& event)
+{
+    event.Enable(GetLastPosition() > 0);
+}
+
+#endif