+extern bool g_blockEventsOnDrag;
+extern bool g_blockEventsOnScroll;
+
+
+
+//-----------------------------------------------------------------------------
+// Macro to tell which row the strings are in (1 if native checklist, 0 if not)
+//-----------------------------------------------------------------------------
+
+#if wxUSE_CHECKLISTBOX
+# define WXLISTBOX_DATACOLUMN_ARG(x) (x->m_hasCheckBoxes ? 1 : 0)
+#else
+# define WXLISTBOX_DATACOLUMN_ARG(x) (0)
+#endif // wxUSE_CHECKLISTBOX
+
+#define WXLISTBOX_DATACOLUMN WXLISTBOX_DATACOLUMN_ARG(this)
+
+// ----------------------------------------------------------------------------
+// helper functions
+// ----------------------------------------------------------------------------
+
+namespace
+{
+
+// Return the entry for the given listbox item.
+//
+// Return value must be released by caller if non-NULL.
+GtkTreeEntry *
+GetEntry(GtkListStore *store, GtkTreeIter *iter, const wxListBox *listbox)
+{
+ GtkTreeEntry* entry;
+ gtk_tree_model_get(GTK_TREE_MODEL(store),
+ iter,
+ WXLISTBOX_DATACOLUMN_ARG(listbox),
+ &entry,
+ -1);
+
+ return entry;
+}
+
+} // anonymous namespace
+
+//-----------------------------------------------------------------------------
+// "row-activated"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_listbox_row_activated_callback(GtkTreeView * WXUNUSED(treeview),
+ GtkTreePath *path,
+ GtkTreeViewColumn * WXUNUSED(col),
+ wxListBox *listbox)
+{
+ if (g_blockEventsOnDrag) return;
+ if (g_blockEventsOnScroll) return;
+
+ // This is triggered by either a double-click or a space press
+
+ int sel = gtk_tree_path_get_indices(path)[0];
+
+ listbox->GTKOnActivated(sel);
+}
+}
+
+//-----------------------------------------------------------------------------
+// "changed"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+gtk_listitem_changed_callback(GtkTreeSelection * WXUNUSED(selection),
+ wxListBox *listbox )
+{
+ if (g_blockEventsOnDrag) return;
+
+ listbox->GTKOnSelectionChanged();
+}
+
+}
+
+//-----------------------------------------------------------------------------
+// "key_press_event"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gboolean
+gtk_listbox_key_press_callback( GtkWidget *WXUNUSED(widget),
+ GdkEventKey *gdk_event,
+ wxListBox *listbox )
+{
+ if ((gdk_event->keyval == GDK_Return) ||
+ (gdk_event->keyval == GDK_ISO_Enter) ||
+ (gdk_event->keyval == GDK_KP_Enter))
+ {
+ int index = -1;
+ if (!listbox->HasMultipleSelection())
+ index = listbox->GetSelection();
+ else
+ {
+ wxArrayInt sels;
+ if (listbox->GetSelections( sels ) < 1)
+ return FALSE;
+ index = sels[0];
+ }
+
+ if (index != wxNOT_FOUND)
+ {
+ listbox->GTKOnActivated(index);
+
+// wxMac and wxMSW always invoke default action
+// if (!ret)
+ {
+ // DClick not handled -> invoke default action
+ wxWindow *tlw = wxGetTopLevelParent( listbox );
+ if (tlw)
+ {
+ GtkWindow *gtk_window = GTK_WINDOW( tlw->GetHandle() );
+ if (gtk_window)
+ gtk_window_activate_default( gtk_window );
+ }
+ }
+
+ // Always intercept, otherwise we'd get another dclick
+ // event from row_activated
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+}
+
+//-----------------------------------------------------------------------------
+// GtkTreeEntry destruction (to destroy client data)
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void gtk_tree_entry_destroy_cb(GtkTreeEntry* entry,
+ wxListBox* listbox)
+{
+ if (listbox->HasClientObjectData())
+ {
+ gpointer userdata = gtk_tree_entry_get_userdata(entry);
+ if (userdata)
+ delete (wxClientData *)userdata;
+ }
+}
+}
+
+//-----------------------------------------------------------------------------
+// Sorting callback (standard CmpNoCase return value)
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gint gtk_listbox_sort_callback(GtkTreeModel * WXUNUSED(model),
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ wxListBox *listbox)
+{
+ wxGtkObject<GtkTreeEntry> entry1(GetEntry(listbox->m_liststore, a, listbox));
+ wxCHECK_MSG(entry1, 0, wxT("Could not get first entry"));
+
+ wxGtkObject<GtkTreeEntry> entry2(GetEntry(listbox->m_liststore, b, listbox));
+ wxCHECK_MSG(entry2, 0, wxT("Could not get second entry"));
+
+ //We compare collate keys here instead of calling g_utf8_collate
+ //as it is rather slow (and even the docs reccommend this)
+ return strcmp(gtk_tree_entry_get_collate_key(entry1),
+ gtk_tree_entry_get_collate_key(entry2)) >= 0;
+}
+}
+
+//-----------------------------------------------------------------------------
+// Searching callback (TRUE == not equal, FALSE == equal)
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static gboolean gtk_listbox_searchequal_callback(GtkTreeModel * WXUNUSED(model),
+ gint WXUNUSED(column),
+ const gchar* key,
+ GtkTreeIter* iter,
+ wxListBox* listbox)
+{
+ wxGtkObject<GtkTreeEntry>
+ entry(GetEntry(listbox->m_liststore, iter, listbox));
+ wxCHECK_MSG(entry, 0, wxT("Could not get entry"));
+
+ wxGtkString keycollatekey(g_utf8_collate_key(key, -1));
+
+ return strcmp(keycollatekey, gtk_tree_entry_get_collate_key(entry)) != 0;
+}
+}