]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkclist.c
Merges from gtk-1-2
[~andy/gtk] / gtk / gtkclist.c
index 401614ab8c21a856842d05c0642aec243a6d84ec..34396b6295c06faefbe95dd69f4f175df58eec63 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
 #include <stdlib.h>
 #include <string.h>
 #include "config.h"
 #include "gtkclist.h"
 #include "gtkbindings.h"
 #include "gtkdnd.h"
-#include <gdk/gdkx.h>
 #include <gdk/gdkkeysyms.h>
 
 /* length of button_actions array */
 #define MAX_BUTTON 5
 
 /* the number rows memchunk expands at a time */
-#define CLIST_OPTIMUM_SIZE 512
+#define CLIST_OPTIMUM_SIZE 64
 
 /* the width of the column resize windows */
 #define DRAG_WIDTH  6
@@ -115,6 +122,12 @@ LIST_WIDTH (GtkCList * clist)
   return 0;
 }
 
+/* returns the GList item for the nth row */
+#define        ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
+                                (clist)->row_list_end : \
+                                g_list_nth ((clist)->row_list, (row)))
+
+
 #define GTK_CLIST_CLASS_FW(_widget_) GTK_CLIST_CLASS (((GtkObject*) (_widget_))->klass)
 
 /* redraw the list if it's not frozen */
@@ -126,8 +139,7 @@ LIST_WIDTH (GtkCList * clist)
 
 
 /* Signals */
-enum
-{
+enum {
   SELECT_ROW,
   UNSELECT_ROW,
   ROW_MOVE,
@@ -147,8 +159,7 @@ enum
   LAST_SIGNAL
 };
 
-enum
-{
+enum {
   SYNC_REMOVE,
   SYNC_INSERT
 };
@@ -159,8 +170,10 @@ enum {
   ARG_SHADOW_TYPE,
   ARG_SELECTION_MODE,
   ARG_ROW_HEIGHT,
+  ARG_TITLES_ACTIVE,
   ARG_REORDERABLE,
-  ARG_USE_DRAG_ICONS
+  ARG_USE_DRAG_ICONS,
+  ARG_SORT_TYPE
 };
 
 /* GtkCList Methods */
@@ -238,7 +251,7 @@ static void gtk_clist_drag_data_received (GtkWidget        *widget,
                                          gint              y,
                                          GtkSelectionData *selection_data,
                                          guint             info,
-                                         guint32           time);
+                                         guint             time);
 
 /* GtkContainer Methods */
 static void gtk_clist_set_focus_child (GtkContainer  *container,
@@ -429,11 +442,18 @@ static GList *gtk_clist_mergesort  (GtkCList      *clist,
                                    GList         *list,
                                    gint           num);
 /* Misc */
-static gboolean title_focus (GtkCList *clist,
-                            gint      dir);
-static void real_row_move   (GtkCList *clist,
-                            gint      source_row,
-                            gint      dest_row);
+static gboolean title_focus           (GtkCList  *clist,
+                                      gint       dir);
+static void real_row_move             (GtkCList  *clist,
+                                      gint       source_row,
+                                      gint       dest_row);
+static gint column_title_passive_func (GtkWidget *widget, 
+                                      GdkEvent  *event,
+                                      gpointer   data);
+static void drag_dest_cell            (GtkCList         *clist,
+                                      gint              x,
+                                      gint              y,
+                                      GtkCListDestInfo *dest_info);
 
 
 
@@ -501,11 +521,18 @@ gtk_clist_class_init (GtkCListClass *klass)
                           GTK_TYPE_BOOL,
                           GTK_ARG_READWRITE,
                           ARG_REORDERABLE);
+  gtk_object_add_arg_type ("GtkCList::titles_active",
+                          GTK_TYPE_BOOL,
+                          GTK_ARG_READWRITE,
+                          ARG_TITLES_ACTIVE);
   gtk_object_add_arg_type ("GtkCList::use_drag_icons",
                           GTK_TYPE_BOOL,
                           GTK_ARG_READWRITE,
                           ARG_USE_DRAG_ICONS);
-  
+  gtk_object_add_arg_type ("GtkCList::sort_type",
+                          GTK_TYPE_SORT_TYPE,
+                          GTK_ARG_READWRITE,
+                          ARG_SORT_TYPE);  
   object_class->set_arg = gtk_clist_set_arg;
   object_class->get_arg = gtk_clist_get_arg;
   object_class->destroy = gtk_clist_destroy;
@@ -825,10 +852,17 @@ gtk_clist_set_arg (GtkObject      *object,
     case ARG_REORDERABLE:
       gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
       break;
+    case ARG_TITLES_ACTIVE:
+      if (GTK_VALUE_BOOL (*arg))
+       gtk_clist_column_titles_active (clist);
+      else
+       gtk_clist_column_titles_passive (clist);
+      break;
     case ARG_USE_DRAG_ICONS:
       gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
       break;
-    default:
+    case ARG_SORT_TYPE:
+      gtk_clist_set_sort_type (clist, GTK_VALUE_ENUM (*arg));
       break;
     }
 }
@@ -844,6 +878,8 @@ gtk_clist_get_arg (GtkObject      *object,
 
   switch (arg_id)
     {
+      guint i;
+
     case ARG_N_COLUMNS:
       GTK_VALUE_UINT (*arg) = clist->columns;
       break;
@@ -859,9 +895,22 @@ gtk_clist_get_arg (GtkObject      *object,
     case ARG_REORDERABLE:
       GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
       break;
+    case ARG_TITLES_ACTIVE:
+      GTK_VALUE_BOOL (*arg) = TRUE;
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].button &&
+           !GTK_WIDGET_SENSITIVE (clist->column[i].button))
+         {
+           GTK_VALUE_BOOL (*arg) = FALSE;
+           break;
+         }
+      break;
     case ARG_USE_DRAG_ICONS:
       GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
       break;
+    case ARG_SORT_TYPE:
+      GTK_VALUE_ENUM (*arg) = clist->sort_type;
+      break;
     default:
       arg->type = GTK_TYPE_INVALID;
       break;
@@ -1265,39 +1314,49 @@ gtk_clist_column_title_active (GtkCList *clist,
 
   if (column < 0 || column >= clist->columns)
     return;
-  if (!clist->column[column].button)
+  if (!clist->column[column].button || !clist->column[column].button_passive)
     return;
 
-  if (!GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
-      !GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
-    {
-      GTK_WIDGET_SET_FLAGS (clist->column[column].button,
-                           GTK_SENSITIVE | GTK_CAN_FOCUS);
-      if (GTK_WIDGET_VISIBLE (clist))
-       gtk_widget_queue_draw (clist->column[column].button);
-    }
+  clist->column[column].button_passive = FALSE;
+
+  gtk_signal_disconnect_by_func (GTK_OBJECT (clist->column[column].button),
+                                (GtkSignalFunc) column_title_passive_func,
+                                NULL);
+
+  GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
+  if (GTK_WIDGET_VISIBLE (clist))
+    gtk_widget_queue_draw (clist->column[column].button);
 }
 
 void
 gtk_clist_column_title_passive (GtkCList *clist,
                                gint      column)
 {
+  GtkButton *button;
+
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
   if (column < 0 || column >= clist->columns)
     return;
-  if (!clist->column[column].button)
+  if (!clist->column[column].button || clist->column[column].button_passive)
     return;
 
-  if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
-      GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
-    {
-      GTK_WIDGET_UNSET_FLAGS (clist->column[column].button,
-                             GTK_SENSITIVE | GTK_CAN_FOCUS);
-      if (GTK_WIDGET_VISIBLE (clist))
-       gtk_widget_queue_draw (clist->column[column].button);
-    }
+  button = GTK_BUTTON (clist->column[column].button);
+
+  clist->column[column].button_passive = TRUE;
+
+  if (button->button_down)
+    gtk_button_released (button);
+  if (button->in_button)
+    gtk_button_leave (button);
+
+  gtk_signal_connect (GTK_OBJECT (clist->column[column].button), "event",
+                     (GtkSignalFunc) column_title_passive_func, NULL);
+
+  GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
+  if (GTK_WIDGET_VISIBLE (clist))
+    gtk_widget_queue_draw (clist->column[column].button);
 }
 
 void
@@ -1558,7 +1617,7 @@ gtk_clist_set_column_visibility (GtkCList *clist,
 void
 gtk_clist_set_column_resizeable (GtkCList *clist,
                                 gint      column,
-                                gint      resizeable)
+                                gboolean  resizeable)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1733,6 +1792,7 @@ gtk_clist_set_column_max_width (GtkCList *clist,
  *   new_column_width
  *   column_button_create
  *   column_button_clicked
+ *   column_title_passive_func
  */
 static void
 column_auto_resize (GtkCList    *clist,
@@ -2048,7 +2108,6 @@ column_button_create (GtkCList *clist,
   gtk_signal_connect (GTK_OBJECT (button), "clicked",
                      (GtkSignalFunc) column_button_clicked,
                      (gpointer) clist);
-
   gtk_widget_show (button);
 }
 
@@ -2072,84 +2131,29 @@ column_button_clicked (GtkWidget *widget,
   gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
 }
 
-void
-gtk_clist_set_row_height (GtkCList *clist,
-                         guint     height)
+static gint
+column_title_passive_func (GtkWidget *widget, 
+                          GdkEvent  *event,
+                          gpointer   data)
 {
-  GtkWidget *widget;
-
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  widget = GTK_WIDGET (clist);
-
-  if (height > 0)
-    {
-      clist->row_height = height;
-      GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
-    }
-  else
-    {
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
-      clist->row_height = 0;
-    }
-
-  if (GTK_WIDGET_REALIZED (clist))
-    {
-      if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
-       {
-         clist->row_height = (widget->style->font->ascent +
-                              widget->style->font->descent + 1);
-         clist->row_center_offset = widget->style->font->ascent + 1.5;
-       }
-      else
-       clist->row_center_offset = 1.5 + (clist->row_height +
-                                         widget->style->font->ascent -
-                                         widget->style->font->descent - 1) / 2;
+  g_return_val_if_fail (event != NULL, FALSE);
+  
+  switch (event->type)
+    {
+    case GDK_MOTION_NOTIFY:
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      return TRUE;
+    default:
+      break;
     }
-      
-  CLIST_REFRESH (clist);
+  return FALSE;
 }
 
-void
-gtk_clist_moveto (GtkCList *clist,
-                 gint      row,
-                 gint      column,
-                 gfloat    row_align,
-                 gfloat    col_align)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (row < -1 || row >= clist->rows)
-    return;
-  if (column < -1 || column >= clist->columns)
-    return;
-
-  row_align = CLAMP (row_align, 0, 1);
-  col_align = CLAMP (col_align, 0, 1);
-
-  /* adjust horizontal scrollbar */
-  if (clist->hadjustment && column >= 0)
-    {
-      gint x;
-
-      x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
-          (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
-                        CELL_SPACING - clist->column[column].area.width)));
-      if (x < 0)
-       gtk_adjustment_set_value (clist->hadjustment, 0.0);
-      else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
-       gtk_adjustment_set_value 
-         (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
-      else
-       gtk_adjustment_set_value (clist->hadjustment, x);
-    }
-
-  /* adjust vertical scrollbar */
-  if (clist->vadjustment && row >= 0)
-    move_vertical (clist, row, row_align);
-}
 
 /* PUBLIC CELL FUNCTIONS
  *   gtk_clist_get_cell_type
@@ -2176,7 +2180,7 @@ gtk_clist_get_cell_type (GtkCList *clist,
   if (column < 0 || column >= clist->columns)
     return -1;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   return clist_row->cell[column].type;
 }
@@ -2197,7 +2201,7 @@ gtk_clist_set_text (GtkCList    *clist,
   if (column < 0 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   /* if text is null, then the cell is empty */
   GTK_CLIST_CLASS_FW (clist)->set_cell_contents
@@ -2227,7 +2231,7 @@ gtk_clist_get_text (GtkCList  *clist,
   if (column < 0 || column >= clist->columns)
     return 0;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->cell[column].type != GTK_CELL_TEXT)
     return 0;
@@ -2255,7 +2259,7 @@ gtk_clist_set_pixmap (GtkCList  *clist,
   if (column < 0 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
   
   gdk_pixmap_ref (pixmap);
   
@@ -2289,7 +2293,7 @@ gtk_clist_get_pixmap (GtkCList   *clist,
   if (column < 0 || column >= clist->columns)
     return 0;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
     return 0;
@@ -2323,7 +2327,7 @@ gtk_clist_set_pixtext (GtkCList    *clist,
   if (column < 0 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
   
   gdk_pixmap_ref (pixmap);
   if (mask) gdk_pixmap_ref (mask);
@@ -2357,7 +2361,7 @@ gtk_clist_get_pixtext (GtkCList   *clist,
   if (column < 0 || column >= clist->columns)
     return 0;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
     return 0;
@@ -2382,7 +2386,7 @@ gtk_clist_set_shift (GtkCList *clist,
                     gint      vertical,
                     gint      horizontal)
 {
-  GtkRequisition requisition;
+  GtkRequisition requisition = { 0 };
   GtkCListRow *clist_row;
 
   g_return_if_fail (clist != NULL);
@@ -2393,7 +2397,7 @@ gtk_clist_set_shift (GtkCList *clist,
   if (column < 0 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist->column[column].auto_resize &&
       !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
@@ -2731,7 +2735,7 @@ real_remove_row (GtkCList *clist,
   was_selected = 0;
 
   /* get the row we're going to delete */
-  list = g_list_nth (clist->row_list, row);
+  list = ROW_ELEMENT (clist, row);
   g_assert (list != NULL);
   clist_row = list->data;
 
@@ -2743,8 +2747,7 @@ real_remove_row (GtkCList *clist,
     gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
                     row, -1, NULL);
 
-  /* reset the row end pointer if we're removing at the
-   * end of the list */
+  /* reset the row end pointer if we're removing at the end of the list */
   clist->rows--;
   if (clist->row_list == list)
     clist->row_list = g_list_next (list);
@@ -2859,7 +2862,7 @@ real_row_move (GtkCList *clist,
   gtk_clist_freeze (clist);
 
   /* unlink source row */
-  clist_row = g_list_nth_data (clist->row_list, source_row);
+  clist_row = ROW_ELEMENT (clist, source_row)->data;
   if (source_row == clist->rows - 1)
     clist->row_list_end = clist->row_list_end->prev;
   clist->row_list = g_list_remove (clist->row_list, clist_row);
@@ -2903,6 +2906,8 @@ real_row_move (GtkCList *clist,
 }
 
 /* PUBLIC ROW FUNCTIONS
+ *   gtk_clist_moveto
+ *   gtk_clist_set_row_height
  *   gtk_clist_set_row_data
  *   gtk_clist_set_row_data_full
  *   gtk_clist_get_row_data
@@ -2913,6 +2918,85 @@ real_row_move (GtkCList *clist,
  *   gtk_clist_set_foreground
  *   gtk_clist_set_background
  */
+void
+gtk_clist_moveto (GtkCList *clist,
+                 gint      row,
+                 gint      column,
+                 gfloat    row_align,
+                 gfloat    col_align)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (row < -1 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
+
+  row_align = CLAMP (row_align, 0, 1);
+  col_align = CLAMP (col_align, 0, 1);
+
+  /* adjust horizontal scrollbar */
+  if (clist->hadjustment && column >= 0)
+    {
+      gint x;
+
+      x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
+          (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
+                        CELL_SPACING - clist->column[column].area.width)));
+      if (x < 0)
+       gtk_adjustment_set_value (clist->hadjustment, 0.0);
+      else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
+       gtk_adjustment_set_value 
+         (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
+      else
+       gtk_adjustment_set_value (clist->hadjustment, x);
+    }
+
+  /* adjust vertical scrollbar */
+  if (clist->vadjustment && row >= 0)
+    move_vertical (clist, row, row_align);
+}
+
+void
+gtk_clist_set_row_height (GtkCList *clist,
+                         guint     height)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  widget = GTK_WIDGET (clist);
+
+  if (height > 0)
+    {
+      clist->row_height = height;
+      GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
+    }
+  else
+    {
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
+      clist->row_height = 0;
+    }
+
+  if (GTK_WIDGET_REALIZED (clist))
+    {
+      if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
+       {
+         clist->row_height = (widget->style->font->ascent +
+                              widget->style->font->descent + 1);
+         clist->row_center_offset = widget->style->font->ascent + 1.5;
+       }
+      else
+       clist->row_center_offset = 1.5 + (clist->row_height +
+                                         widget->style->font->ascent -
+                                         widget->style->font->descent - 1) / 2;
+    }
+      
+  CLIST_REFRESH (clist);
+}
+
 void
 gtk_clist_set_row_data (GtkCList *clist,
                        gint      row,
@@ -2935,7 +3019,11 @@ gtk_clist_set_row_data_full (GtkCList         *clist,
   if (row < 0 || row > (clist->rows - 1))
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->destroy)
+    clist_row->destroy (clist_row->data);
+  
   clist_row->data = data;
   clist_row->destroy = destroy;
 }
@@ -2952,7 +3040,7 @@ gtk_clist_get_row_data (GtkCList *clist,
   if (row < 0 || row > (clist->rows - 1))
     return NULL;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
   return clist_row->data;
 }
 
@@ -3061,7 +3149,7 @@ gtk_clist_set_foreground (GtkCList *clist,
   if (row < 0 || row >= clist->rows)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (color)
     {
@@ -3091,7 +3179,7 @@ gtk_clist_set_background (GtkCList *clist,
   if (row < 0 || row >= clist->rows)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (color)
     {
@@ -3121,7 +3209,7 @@ gtk_clist_set_cell_style (GtkCList *clist,
                          gint      column,
                          GtkStyle *style)
 {
-  GtkRequisition requisition;
+  GtkRequisition requisition = { 0 };
   GtkCListRow *clist_row;
 
   g_return_if_fail (clist != NULL);
@@ -3132,7 +3220,7 @@ gtk_clist_set_cell_style (GtkCList *clist,
   if (column < 0 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->cell[column].style == style)
     return;
@@ -3184,7 +3272,7 @@ gtk_clist_get_cell_style (GtkCList *clist,
   if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
     return NULL;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   return clist_row->cell[column].style;
 }
@@ -3205,7 +3293,7 @@ gtk_clist_set_row_style (GtkCList *clist,
   if (row < 0 || row >= clist->rows)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->style == style)
     return;
@@ -3267,7 +3355,7 @@ gtk_clist_get_row_style (GtkCList *clist,
   if (row < 0 || row >= clist->rows)
     return NULL;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   return clist_row->style;
 }
@@ -3294,7 +3382,7 @@ gtk_clist_set_selectable (GtkCList *clist,
   if (row < 0 || row >= clist->rows)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (selectable == clist_row->selectable)
     return;
@@ -3325,7 +3413,7 @@ gtk_clist_get_selectable (GtkCList *clist,
   if (row < 0 || row >= clist->rows)
     return FALSE;
 
-  return GTK_CLIST_ROW (g_list_nth (clist->row_list, row))->selectable;
+  return GTK_CLIST_ROW (ROW_ELEMENT (clist, row))->selectable;
 }
 
 void
@@ -3432,7 +3520,7 @@ toggle_row (GtkCList *clist,
     case GTK_SELECTION_EXTENDED:
     case GTK_SELECTION_MULTIPLE:
     case GTK_SELECTION_SINGLE:
-      clist_row = g_list_nth (clist->row_list, row)->data;
+      clist_row = ROW_ELEMENT (clist, row)->data;
 
       if (!clist_row)
        return;
@@ -3456,7 +3544,7 @@ fake_toggle_row (GtkCList *clist,
 {
   GList *work;
 
-  work = g_list_nth (clist->row_list, row);
+  work = ROW_ELEMENT (clist, row);
 
   if (!work || !GTK_CLIST_ROW (work)->selectable)
     return;
@@ -3581,7 +3669,7 @@ real_select_row (GtkCList *clist,
       break;
     }
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
     return;
@@ -3616,7 +3704,7 @@ real_unselect_row (GtkCList *clist,
   if (row < 0 || row > (clist->rows - 1))
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  clist_row = ROW_ELEMENT (clist, row)->data;
 
   if (clist_row->state == GTK_STATE_SELECTED)
     {
@@ -3738,7 +3826,7 @@ fake_unselect_all (GtkCList *clist,
   GList *work;
   gint i;
 
-  if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
+  if (row >= 0 && (work = ROW_ELEMENT (clist, row)))
     {
       if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
          GTK_CLIST_ROW (work)->selectable)
@@ -3755,7 +3843,7 @@ fake_unselect_all (GtkCList *clist,
   clist->undo_selection = clist->selection;
   clist->selection = NULL;
   clist->selection_end = NULL;
-  
+
   for (list = clist->undo_selection; list; list = list->next)
     {
       if ((i = GPOINTER_TO_INT (list->data)) == row ||
@@ -3782,8 +3870,7 @@ real_undo_selection (GtkCList *clist)
       clist->selection_mode != GTK_SELECTION_EXTENDED)
     return;
 
-  if (clist->anchor >= 0)
-    GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+  GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 
   if (!(clist->undo_selection || clist->undo_unselection))
     {
@@ -3796,8 +3883,11 @@ real_undo_selection (GtkCList *clist)
                     GPOINTER_TO_INT (work->data), -1, NULL);
 
   for (work = clist->undo_unselection; work; work = work->next)
-    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
-                    GPOINTER_TO_INT (work->data), -1, NULL);
+    {
+      /* g_print ("unselect %d\n",GPOINTER_TO_INT (work->data)); */
+      gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
+                      GPOINTER_TO_INT (work->data), -1, NULL);
+    }
 
   if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
     {
@@ -3862,7 +3952,10 @@ resync_selection (GtkCList *clist,
   GList *list;
   GtkCListRow *clist_row;
 
-  if (clist->anchor < 0)
+  if (clist->selection_mode != GTK_SELECTION_EXTENDED)
+    return;
+
+  if (clist->anchor < 0 || clist->drag_pos < 0)
     return;
 
   gtk_clist_freeze (clist);
@@ -3953,9 +4046,9 @@ resync_selection (GtkCList *clist,
              }
          }
     }
-
-  for (list = g_list_reverse (clist->undo_unselection); list;
-       list = list->next)
+  
+  clist->undo_unselection = g_list_reverse (clist->undo_unselection);
+  for (list = clist->undo_unselection; list; list = list->next)
     gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
                     GPOINTER_TO_INT (list->data), -1, event);
 
@@ -4140,10 +4233,9 @@ end_selection (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist)) ||
-      clist->anchor == -1)
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS(clist))
     return;
-  
+
   GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 }
 
@@ -4200,8 +4292,7 @@ sync_selection (GtkCList *clist,
        clist->focus_row = clist->rows - 1;
     }
 
-  if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
-    GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+  GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 
   g_list_free (clist->undo_selection);
   g_list_free (clist->undo_unselection);
@@ -4434,7 +4525,8 @@ gtk_clist_realize (GtkWidget *widget)
   /* We'll use this gc to do scrolling as well */
   gdk_gc_set_exposures (clist->fg_gc, TRUE);
 
-  values.foreground = widget->style->white;
+  values.foreground = (widget->style->white.pixel==0 ?
+                      widget->style->black:widget->style->white);
   values.function = GDK_XOR;
   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
   clist->xor_gc = gdk_gc_new_with_values (widget->window,
@@ -4486,8 +4578,12 @@ gtk_clist_unrealize (GtkWidget *widget)
   /* freeze the list */
   clist->freeze_count++;
 
-  /* detach optional row/cell styles */
+  if (GTK_WIDGET_MAPPED (widget))
+    gtk_clist_unmap (widget);
 
+  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+  /* detach optional row/cell styles */
   if (GTK_WIDGET_REALIZED (widget))
     {
       GtkCListRow *clist_row;
@@ -4514,12 +4610,16 @@ gtk_clist_unrealize (GtkWidget *widget)
   gdk_gc_destroy (clist->bg_gc);
 
   for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].window)
-      {
-       gdk_window_set_user_data (clist->column[i].window, NULL);
-       gdk_window_destroy (clist->column[i].window);
-       clist->column[i].window = NULL;
-      }
+    {
+      if (clist->column[i].button)
+       gtk_widget_unrealize (clist->column[i].button);
+      if (clist->column[i].window)
+       {
+         gdk_window_set_user_data (clist->column[i].window, NULL);
+         gdk_window_destroy (clist->column[i].window);
+         clist->column[i].window = NULL;
+       }
+    }
 
   gdk_window_set_user_data (clist->clist_window, NULL);
   gdk_window_destroy (clist->clist_window);
@@ -4555,10 +4655,12 @@ gtk_clist_map (GtkWidget *widget)
 
       /* map column buttons */
       for (i = 0; i < clist->columns; i++)
-       if (clist->column[i].button &&
-           GTK_WIDGET_VISIBLE (clist->column[i].button) &&
-           !GTK_WIDGET_MAPPED (clist->column[i].button))
-         gtk_widget_map (clist->column[i].button);
+       {
+         if (clist->column[i].button &&
+             GTK_WIDGET_VISIBLE (clist->column[i].button) &&
+             !GTK_WIDGET_MAPPED (clist->column[i].button))
+           gtk_widget_map (clist->column[i].button);
+       }
       
       for (i = 0; i < clist->columns; i++)
        if (clist->column[i].window && clist->column[i].button)
@@ -4595,9 +4697,7 @@ gtk_clist_unmap (GtkWidget *widget)
        {
          remove_grab (clist);
 
-         if (clist->anchor != -1 &&
-             clist->selection_mode == GTK_SELECTION_EXTENDED)
-           GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, NULL);
+         GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, NULL);
 
          clist->click_cell.row = -1;
          clist->click_cell.column = -1;
@@ -4668,7 +4768,7 @@ gtk_clist_draw (GtkWidget    *widget,
                       (2 * widget->style->klass->ythickness) +
                       clist->column_title_area.height);
 
-      gdk_window_clear_area (clist->clist_window, 0, 0, -1, -1);
+      gdk_window_clear_area (clist->clist_window, 0, 0, 0, 0);
       draw_rows (clist, NULL);
 
       for (i = 0; i < clist->columns; i++)
@@ -4897,9 +4997,12 @@ gtk_clist_button_press (GtkWidget      *widget,
                case GTK_SELECTION_SINGLE:
                case GTK_SELECTION_MULTIPLE:
                  if (event->type != GDK_BUTTON_PRESS)
-                   gtk_signal_emit (GTK_OBJECT (clist),
-                                    clist_signals[SELECT_ROW],
-                                    row, column, event);
+                   {
+                     gtk_signal_emit (GTK_OBJECT (clist),
+                                      clist_signals[SELECT_ROW],
+                                      row, column, event);
+                     clist->anchor = -1;
+                   }
                  else
                    clist->anchor = row;
                  break;
@@ -5076,6 +5179,7 @@ gtk_clist_button_release (GtkWidget      *widget,
            {
            case GTK_SELECTION_EXTENDED:
              if (!(event->state & GDK_SHIFT_MASK) ||
+                 !GTK_WIDGET_CAN_FOCUS (widget) ||
                  event->x < 0 || event->x >= clist->clist_window_width ||
                  event->y < 0 || event->y >= clist->clist_window_height)
                GTK_CLIST_CLASS_FW (clist)->resync_selection
@@ -5535,6 +5639,8 @@ draw_cell_pixmap (GdkWindow    *window,
 
   gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
   gdk_gc_set_clip_origin (fg_gc, 0, 0);
+  if (mask)
+    gdk_gc_set_clip_mask (fg_gc, NULL);
 
   return x + MAX (width, 0);
 }
@@ -5566,7 +5672,7 @@ draw_row (GtkCList     *clist,
   /* if the function is passed the pointer to the row instead of null,
    * it avoids this expensive lookup */
   if (!clist_row)
-    clist_row = (g_list_nth (clist->row_list, row))->data;
+    clist_row = ROW_ELEMENT (clist, row)->data;
 
   /* rectangle of the entire row */
   row_rectangle.x = 0;
@@ -5580,7 +5686,7 @@ draw_row (GtkCList     *clist,
   cell_rectangle.width = row_rectangle.width;
   cell_rectangle.height = CELL_SPACING;
 
-  /* rectangle used to clip drawing operations, it's y and height
+  /* rectangle used to clip drawing operations, its y and height
    * positions only need to be set once, so we set them once here. 
    * the x and width are set withing the drawing loop below once per
    * column */
@@ -5611,7 +5717,7 @@ draw_row (GtkCList     *clist,
                            intersect_rectangle.width,
                            intersect_rectangle.height);
 
-      /* the last row has to clear it's bottom cell spacing too */
+      /* the last row has to clear its bottom cell spacing too */
       if (clist_row == clist->row_list_end->data)
        {
          cell_rectangle.y += clist->row_height + CELL_SPACING;
@@ -5642,7 +5748,7 @@ draw_row (GtkCList     *clist,
                          cell_rectangle.width,
                          cell_rectangle.height);
 
-      /* the last row has to clear it's bottom cell spacing too */
+      /* the last row has to clear its bottom cell spacing too */
       if (clist_row == clist->row_list_end->data)
        {
          cell_rectangle.y += clist->row_height + CELL_SPACING;
@@ -5843,7 +5949,7 @@ draw_rows (GtkCList     *clist,
   if (clist->rows == first_row)
     first_row--;
 
-  list = g_list_nth (clist->row_list, first_row);
+  list = ROW_ELEMENT (clist, first_row);
   i = first_row;
   while (list)
     {
@@ -5858,8 +5964,8 @@ draw_rows (GtkCList     *clist,
     }
 
   if (!area)
-    gdk_window_clear_area (clist->clist_window,
-                          0, ROW_TOP_YPIXEL (clist, i), -1, -1);
+    gdk_window_clear_area (clist->clist_window, 0,
+                          ROW_TOP_YPIXEL (clist, i), 0, 0);
 }
 
 static void                          
@@ -5959,7 +6065,8 @@ adjust_adjustments (GtkCList *clist,
       clist->vadjustment->lower = 0;
       clist->vadjustment->upper = LIST_HEIGHT (clist);
 
-      if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
+      if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist) ||
+         (clist->voffset + (gint)clist->vadjustment->value) != 0)
        {
          clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
                                               clist->clist_window_height));
@@ -5977,7 +6084,8 @@ adjust_adjustments (GtkCList *clist,
       clist->hadjustment->lower = 0;
       clist->hadjustment->upper = LIST_WIDTH (clist);
 
-      if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
+      if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist) ||
+         (clist->hoffset + (gint)clist->hadjustment->value) != 0)
        {
          clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
                                               clist->clist_window_width));
@@ -6323,6 +6431,7 @@ columns_new (GtkCList *clist)
       column[i].width_set = FALSE;
       column[i].resizeable = TRUE;
       column[i].auto_resize = FALSE;
+      column[i].button_passive = FALSE;
       column[i].justification = GTK_JUSTIFY_LEFT;
     }
 
@@ -6584,8 +6693,7 @@ gtk_clist_focus_out (GtkWidget     *widget,
   
   clist = GTK_CLIST (widget);
 
-  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
-    GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
+  GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
 
   return FALSE;
 }
@@ -7005,19 +7113,14 @@ move_vertical (GtkCList *clist,
 static gint
 horizontal_timeout (GtkCList *clist)
 {
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
+  GdkEventMotion event = { 0 };
 
   GDK_THREADS_ENTER ();
 
   clist->htimer = 0;
-  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
 
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
+  event.type = GDK_MOTION_NOTIFY;
+  event.send_event = TRUE;
 
   gtk_clist_motion (GTK_WIDGET (clist), &event);
 
@@ -7029,19 +7132,14 @@ horizontal_timeout (GtkCList *clist)
 static gint
 vertical_timeout (GtkCList *clist)
 {
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
+  GdkEventMotion event = { 0 };
 
   GDK_THREADS_ENTER ();
 
   clist->vtimer = 0;
-  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
 
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
+  event.type = GDK_MOTION_NOTIFY;
+  event.send_event = TRUE;
 
   gtk_clist_motion (GTK_WIDGET (clist), &event);
 
@@ -7336,6 +7434,62 @@ drag_dest_info_destroy (gpointer data)
   g_free (info);
 }
 
+static void
+drag_dest_cell (GtkCList         *clist,
+               gint              x,
+               gint              y,
+               GtkCListDestInfo *dest_info)
+{
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (clist);
+
+  dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
+
+  y -= (GTK_CONTAINER (clist)->border_width +
+       widget->style->klass->ythickness +
+       clist->column_title_area.height);
+
+  dest_info->cell.row = ROW_FROM_YPIXEL (clist, y);
+  if (dest_info->cell.row >= clist->rows)
+    {
+      dest_info->cell.row = clist->rows - 1;
+      y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height;
+    }
+  if (dest_info->cell.row < -1)
+    dest_info->cell.row = -1;
+
+  x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
+  dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
+
+  if (dest_info->cell.row >= 0)
+    {
+      gint y_delta;
+      gint h = 0;
+
+      y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
+      
+      if (GTK_CLIST_DRAW_DRAG_RECT(clist))
+       {
+         dest_info->insert_pos = GTK_CLIST_DRAG_INTO;
+         h = clist->row_height / 4;
+       }
+      else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+       {
+         dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
+         h = clist->row_height / 2;
+       }
+
+      if (GTK_CLIST_DRAW_DRAG_LINE(clist))
+       {
+         if (y_delta < h)
+           dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
+         else if (clist->row_height - y_delta < h)
+           dest_info->insert_pos = GTK_CLIST_DRAG_AFTER;
+       }
+    }
+}
+
 static void
 gtk_clist_drag_begin (GtkWidget             *widget,
                      GdkDragContext *context)
@@ -7453,56 +7607,14 @@ gtk_clist_drag_motion (GtkWidget      *widget,
                       guint           time)
 {
   GtkCList *clist;
-  gint row, column;
+  GtkCListDestInfo new_info;
   GtkCListDestInfo *dest_info;
-  gint h = 0;
-  gint insert_pos = GTK_CLIST_DRAG_NONE;
-  gint y_delta;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
   clist = GTK_CLIST (widget);
 
-  y -= (GTK_CONTAINER (widget)->border_width +
-       widget->style->klass->ythickness + clist->column_title_area.height);
-  row = ROW_FROM_YPIXEL (clist, y);
-
-  if (row >= clist->rows)
-    {
-      row = clist->rows - 1;
-      y = ROW_TOP_YPIXEL (clist, row) + clist->row_height;
-    }
-  if (row < -1)
-    row = -1;
-
-  x -= GTK_CONTAINER (widget)->border_width + widget->style->klass->xthickness;
-  column = COLUMN_FROM_XPIXEL (clist, x);
-
-  if (row >= 0)
-    {
-      y_delta = y - ROW_TOP_YPIXEL (clist, row);
-      
-      if (GTK_CLIST_DRAW_DRAG_RECT(clist))
-       {
-         insert_pos = GTK_CLIST_DRAG_INTO;
-         h = clist->row_height / 4;
-       }
-      else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
-       {
-         insert_pos = GTK_CLIST_DRAG_BEFORE;
-         h = clist->row_height / 2;
-       }
-
-      if (GTK_CLIST_DRAW_DRAG_LINE(clist))
-       {
-         if (y_delta < h)
-           insert_pos = GTK_CLIST_DRAG_BEFORE;
-         else if (clist->row_height - y_delta < h)
-           insert_pos = GTK_CLIST_DRAG_AFTER;
-       }
-    }
-
   dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
 
   if (!dest_info)
@@ -7517,6 +7629,8 @@ gtk_clist_drag_motion (GtkWidget      *widget,
                               drag_dest_info_destroy);
     }
 
+  drag_dest_cell (clist, x, y, &new_info);
+
   if (GTK_CLIST_REORDERABLE (clist))
     {
       GList *list;
@@ -7533,12 +7647,12 @@ gtk_clist_drag_motion (GtkWidget      *widget,
       if (list)
        {
          if (gtk_drag_get_source_widget (context) != widget ||
-             insert_pos == GTK_CLIST_DRAG_NONE ||
-             row == clist->click_cell.row ||
-             (row == clist->click_cell.row - 1 &&
-              insert_pos == GTK_CLIST_DRAG_AFTER) ||
-             (row == clist->click_cell.row + 1 &&
-              insert_pos == GTK_CLIST_DRAG_BEFORE))
+             new_info.insert_pos == GTK_CLIST_DRAG_NONE ||
+             new_info.cell.row == clist->click_cell.row ||
+             (new_info.cell.row == clist->click_cell.row - 1 &&
+              new_info.insert_pos == GTK_CLIST_DRAG_AFTER) ||
+             (new_info.cell.row == clist->click_cell.row + 1 &&
+              new_info.insert_pos == GTK_CLIST_DRAG_BEFORE))
            {
              if (dest_info->cell.row < 0)
                {
@@ -7548,9 +7662,9 @@ gtk_clist_drag_motion (GtkWidget      *widget,
              return TRUE;
            }
                
-         if (row != dest_info->cell.row ||
-             (row == dest_info->cell.row &&
-              dest_info->insert_pos != insert_pos))
+         if (new_info.cell.row != dest_info->cell.row ||
+             (new_info.cell.row == dest_info->cell.row &&
+              dest_info->insert_pos != new_info.insert_pos))
            {
              if (dest_info->cell.row >= 0)
                GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
@@ -7558,9 +7672,9 @@ gtk_clist_drag_motion (GtkWidget      *widget,
                                      dest_info->cell.row)->data,
                   dest_info->cell.row, dest_info->insert_pos);
 
-             dest_info->insert_pos  = insert_pos;
-             dest_info->cell.row    = row;
-             dest_info->cell.column = column;
+             dest_info->insert_pos  = new_info.insert_pos;
+             dest_info->cell.row    = new_info.cell.row;
+             dest_info->cell.column = new_info.cell.column;
              
              GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
                (clist, g_list_nth (clist->row_list,
@@ -7573,9 +7687,9 @@ gtk_clist_drag_motion (GtkWidget      *widget,
        }
     }
 
-  dest_info->insert_pos  = insert_pos;
-  dest_info->cell.row    = row;
-  dest_info->cell.column = column;
+  dest_info->insert_pos  = new_info.insert_pos;
+  dest_info->cell.row    = new_info.cell.row;
+  dest_info->cell.column = new_info.cell.column;
   return TRUE;
 }
 
@@ -7614,7 +7728,7 @@ gtk_clist_drag_data_received (GtkWidget        *widget,
                              gint              y,
                              GtkSelectionData *selection_data,
                              guint             info,
-                             guint32           time)
+                             guint             time)
 {
   GtkCList *clist;
 
@@ -7633,22 +7747,21 @@ gtk_clist_drag_data_received (GtkWidget        *widget,
       selection_data->length == sizeof (GtkCListCellInfo))
     {
       GtkCListCellInfo *source_info;
-      GtkCListDestInfo *dest_info;
 
       source_info = (GtkCListCellInfo *)(selection_data->data);
-      dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
-
-      if (dest_info && source_info)
+      if (source_info)
        {
-         if (dest_info->insert_pos == GTK_CLIST_DRAG_AFTER)
-           dest_info->cell.row++;
-         if (source_info->row < dest_info->cell.row)
-           dest_info->cell.row--;
-
-         if (dest_info->cell.row != source_info->row)
-           gtk_clist_row_move (GTK_CLIST (widget),
-                               source_info->row,
-                               dest_info->cell.row);
+         GtkCListDestInfo dest_info;
+
+         drag_dest_cell (clist, x, y, &dest_info);
+
+         if (dest_info.insert_pos == GTK_CLIST_DRAG_AFTER)
+           dest_info.cell.row++;
+         if (source_info->row < dest_info.cell.row)
+           dest_info.cell.row--;
+         if (dest_info.cell.row != source_info->row)
+           gtk_clist_row_move (clist, source_info->row, dest_info.cell.row);
+
          g_dataset_remove_data (context, "gtk-clist-drag-dest");
        }
     }
@@ -7675,21 +7788,18 @@ gtk_clist_drag_data_get (GtkWidget        *widget,
 
       if (info)
        {
-         GtkCListCellInfo *ret_info;
+         GtkCListCellInfo ret_info;
 
-         ret_info = g_new (GtkCListCellInfo, 1);
-         ret_info->row = info->row;
-         ret_info->column = info->column;
+         ret_info.row = info->row;
+         ret_info.column = info->column;
 
-         gtk_selection_data_set (selection_data,
-                                 selection_data->target,
-                                 GTK_TYPE_POINTER,
-                                 (guchar *) ret_info,
+         gtk_selection_data_set (selection_data, selection_data->target,
+                                 GTK_TYPE_POINTER, (guchar *) &ret_info,
                                  sizeof (GtkCListCellInfo));
        }
       else
        gtk_selection_data_set (selection_data, selection_data->target,
-                               GTK_TYPE_POINTER, NULL, 0);
+                               GTK_TYPE_POINTER, NULL, 0);
     }
 }
 
@@ -7769,7 +7879,7 @@ gtk_clist_set_button_actions (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
   
-  if (button <= MAX_BUTTON)
+  if (button < MAX_BUTTON)
     {
       if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist))
        {
@@ -7777,9 +7887,7 @@ gtk_clist_set_button_actions (GtkCList *clist,
          clist->drag_button = 0;
        }
 
-      if (clist->anchor >= 0 &&
-         clist->selection_mode == GTK_SELECTION_EXTENDED)
-       GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 
       clist->button_actions[button] = button_actions;
     }