]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkclist.c
Merges from gtk-1-2
[~andy/gtk] / gtk / gtkclist.c
index ca65edfd311eeaddbf420711b154f5828adea8d4..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 "gtkmain.h"
 #include "gtkclist.h"
 #include "gtkbindings.h"
-#include "gtkprivate.h"
+#include "gtkdnd.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
@@ -111,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 */
@@ -122,8 +139,7 @@ LIST_WIDTH (GtkCList * clist)
 
 
 /* Signals */
-enum
-{
+enum {
   SELECT_ROW,
   UNSELECT_ROW,
   ROW_MOVE,
@@ -143,8 +159,7 @@ enum
   LAST_SIGNAL
 };
 
-enum
-{
+enum {
   SYNC_REMOVE,
   SYNC_INSERT
 };
@@ -154,7 +169,11 @@ enum {
   ARG_N_COLUMNS,
   ARG_SHADOW_TYPE,
   ARG_SELECTION_MODE,
-  ARG_ROW_HEIGHT
+  ARG_ROW_HEIGHT,
+  ARG_TITLES_ACTIVE,
+  ARG_REORDERABLE,
+  ARG_USE_DRAG_ICONS,
+  ARG_SORT_TYPE
 };
 
 /* GtkCList Methods */
@@ -204,6 +223,35 @@ static gint gtk_clist_focus           (GtkContainer     *container,
                                       GtkDirectionType  direction);
 static void gtk_clist_style_set       (GtkWidget        *widget,
                                       GtkStyle         *previous_style);
+static void gtk_clist_drag_begin      (GtkWidget        *widget,
+                                      GdkDragContext   *context);
+static gint gtk_clist_drag_motion     (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      gint              x,
+                                      gint              y,
+                                      guint             time);
+static void gtk_clist_drag_leave      (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      guint             time);
+static void gtk_clist_drag_end        (GtkWidget        *widget,
+                                      GdkDragContext   *context);
+static gboolean gtk_clist_drag_drop   (GtkWidget      *widget,
+                                      GdkDragContext *context,
+                                      gint            x,
+                                      gint            y,
+                                      guint           time);
+static void gtk_clist_drag_data_get   (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      GtkSelectionData *selection_data,
+                                      guint             info,
+                                      guint             time);
+static void gtk_clist_drag_data_received (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint             time);
 
 /* GtkContainer Methods */
 static void gtk_clist_set_focus_child (GtkContainer  *container,
@@ -256,15 +304,6 @@ static void start_selection           (GtkCList      *clist);
 static void end_selection             (GtkCList      *clist);
 static void toggle_add_mode           (GtkCList      *clist);
 static void toggle_focus_row          (GtkCList      *clist);
-static void move_focus_row            (GtkCList      *clist,
-                                      GtkScrollType  scroll_type,
-                                      gfloat         position);
-static void scroll_horizontal         (GtkCList      *clist,
-                                      GtkScrollType  scroll_type,
-                                      gfloat         position);
-static void scroll_vertical           (GtkCList      *clist,
-                                      GtkScrollType  scroll_type,
-                                      gfloat         position);
 static void extend_selection          (GtkCList      *clist,
                                       GtkScrollType  scroll_type,
                                       gfloat         position,
@@ -275,6 +314,26 @@ static gint get_selection_info        (GtkCList       *clist,
                                       gint           *row,
                                       gint           *column);
 
+/* Scrolling */
+static void move_focus_row     (GtkCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void scroll_horizontal  (GtkCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void scroll_vertical    (GtkCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void move_horizontal    (GtkCList      *clist,
+                               gint           diff);
+static void move_vertical      (GtkCList      *clist,
+                               gint           row,
+                               gfloat         align);
+static gint horizontal_timeout (GtkCList      *clist);
+static gint vertical_timeout   (GtkCList      *clist);
+static void remove_grab        (GtkCList      *clist);
+
+
 /* Resize Columns */
 static void draw_xor_line             (GtkCList       *clist);
 static gint new_column_width          (GtkCList       *clist,
@@ -336,6 +395,10 @@ static void draw_row         (GtkCList      *clist,
 static void draw_rows        (GtkCList      *clist,
                              GdkRectangle  *area);
 static void clist_refresh    (GtkCList      *clist);
+static void draw_drag_highlight (GtkCList        *clist,
+                                GtkCListRow     *dest_row,
+                                gint             dest_row_number,
+                                GtkCListDragPos  drag_pos);
      
 /* Size Allocation / Requisition */
 static void size_allocate_title_buttons (GtkCList *clist);
@@ -379,16 +442,25 @@ 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);
+
 
 
 static GtkContainerClass *parent_class = NULL;
 static guint clist_signals[LAST_SIGNAL] = {0};
 
+static GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
 
 GtkType
 gtk_clist_get_type (void)
@@ -421,6 +493,7 @@ gtk_clist_class_init (GtkCListClass *klass)
   GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
+  GtkBindingSet *binding_set;
 
   object_class = (GtkObjectClass *) klass;
   widget_class = (GtkWidgetClass *) klass;
@@ -444,7 +517,22 @@ gtk_clist_class_init (GtkCListClass *klass)
                           GTK_TYPE_UINT,
                           GTK_ARG_READWRITE,
                           ARG_ROW_HEIGHT);
-  
+  gtk_object_add_arg_type ("GtkCList::reorderable",
+                          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;
@@ -595,6 +683,13 @@ gtk_clist_class_init (GtkCListClass *klass)
   widget_class->focus_out_event = gtk_clist_focus_out;
   widget_class->draw_focus = gtk_clist_draw_focus;
   widget_class->style_set = gtk_clist_style_set;
+  widget_class->drag_begin = gtk_clist_drag_begin;
+  widget_class->drag_end = gtk_clist_drag_end;
+  widget_class->drag_motion = gtk_clist_drag_motion;
+  widget_class->drag_leave = gtk_clist_drag_leave;
+  widget_class->drag_drop = gtk_clist_drag_drop;
+  widget_class->drag_data_get = gtk_clist_drag_data_get;
+  widget_class->drag_data_received = gtk_clist_drag_data_received;
 
   /* container_class->add = NULL; use the default GtkContainerClass warning */
   /* container_class->remove=NULL; use the default GtkContainerClass warning */
@@ -614,6 +709,7 @@ gtk_clist_class_init (GtkCListClass *klass)
   klass->click_column = NULL;
   klass->resize_column = real_resize_column;
   klass->draw_row = draw_row;
+  klass->draw_drag_highlight = draw_drag_highlight;
   klass->insert_row = real_insert_row;
   klass->remove_row = real_remove_row;
   klass->clear = real_clear;
@@ -632,203 +728,102 @@ gtk_clist_class_init (GtkCListClass *klass)
   klass->set_cell_contents = set_cell_contents;
   klass->cell_size_request = cell_size_request;
 
-  {
-    GtkBindingSet *binding_set;
-
-    binding_set = gtk_binding_set_by_class (klass);
-    gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 1.0);
-
-    gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_Home,
-                                 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_End,
-                                 GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
-
-    gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 1.0);
-
-    gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
-                                 "undo_selection", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
-                                 "abort_column_resize", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
-                                 "toggle_focus_row", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
-                                 "toggle_add_mode", 0);
-    gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
-                                 "select_all", 0);
-    gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
-                                 "unselect_all", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
-                                 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
-                                 "end_selection", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
-                                 GDK_RELEASE_MASK | GDK_SHIFT_MASK,
-                                 "end_selection", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
-                                 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
-                                 GDK_CONTROL_MASK,
-                                 "end_selection", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
-                                 GDK_RELEASE_MASK | GDK_SHIFT_MASK |
-                                 GDK_CONTROL_MASK,
-                                 "end_selection", 0);
-  }
-
-  /*
-  {
-    GtkBindingSet *binding_set;
-
-    binding_set = gtk_binding_set_by_class (klass);
-    gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
-                                 "scroll_vertical", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0);
-
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
-                                 "extend_selection", 3,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
-
-    gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
-                                 "scroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 0.0);
-    gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
-                                 "sroll_horizontal", 2,
-                                 GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
-                                  GTK_TYPE_FLOAT, 1.0);
-
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, 0,
-                                 "undo_selection", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
-                                 "abort_column_resize", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
-                                 "toggle_focus_row", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Multiply, 0,
-                                 "toggle_add_mode", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0,
-                                 "select_all", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0,
-                                 "unselect_all", 0);
-    gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0,
-                                 "end_selection", 0);
-  }
-  */
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
+                               "scroll_vertical", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
+                               "scroll_vertical", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
+                               "scroll_vertical", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
+                               "scroll_vertical", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
+                               "scroll_vertical", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
+                               "scroll_vertical", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               GTK_TYPE_FLOAT, 1.0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+                               GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+                               GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Home,
+                               GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "extend_selection", 3,
+                               GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_End,
+                               GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "extend_selection", 3,
+                               GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
+                               "scroll_horizontal", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
+                               "scroll_horizontal", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
+                               "scroll_horizontal", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               GTK_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
+                               "scroll_horizontal", 2,
+                               GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               GTK_TYPE_FLOAT, 1.0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+                               "undo_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+                               "abort_column_resize", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
+                               "toggle_focus_row", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
+                               "toggle_add_mode", 0);
+  gtk_binding_entry_add_signal (binding_set, '/', GDK_CONTROL_MASK,
+                               "select_all", 0);
+  gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
+                               "unselect_all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK,
+                               "end_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK,
+                               "end_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK |
+                               GDK_CONTROL_MASK,
+                               "end_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK |
+                               GDK_CONTROL_MASK,
+                               "end_selection", 0);
 }
 
 static void
@@ -854,7 +849,20 @@ gtk_clist_set_arg (GtkObject      *object,
     case ARG_ROW_HEIGHT:
       gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
       break;
-    default:
+    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;
+    case ARG_SORT_TYPE:
+      gtk_clist_set_sort_type (clist, GTK_VALUE_ENUM (*arg));
       break;
     }
 }
@@ -870,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;
@@ -880,7 +890,26 @@ gtk_clist_get_arg (GtkObject      *object,
       GTK_VALUE_ENUM (*arg) = clist->selection_mode;
       break;
     case ARG_ROW_HEIGHT:
-      GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET (clist) ? clist->row_height : 0;
+      GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
+      break;
+    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;
@@ -894,6 +923,10 @@ gtk_clist_init (GtkCList *clist)
   clist->flags = 0;
 
   GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
+  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
+  GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
+  GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
+  GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
 
   clist->row_mem_chunk = NULL;
   clist->cell_mem_chunk = NULL;
@@ -925,6 +958,12 @@ gtk_clist_init (GtkCList *clist)
   clist->vadjustment = NULL;
   clist->hadjustment = NULL;
 
+  clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
+  clist->button_actions[1] = GTK_BUTTON_IGNORED;
+  clist->button_actions[2] = GTK_BUTTON_IGNORED;
+  clist->button_actions[3] = GTK_BUTTON_IGNORED;
+  clist->button_actions[4] = GTK_BUTTON_IGNORED;
+
   clist->cursor_drag = NULL;
   clist->xor_gc = NULL;
   clist->fg_gc = NULL;
@@ -937,8 +976,6 @@ gtk_clist_init (GtkCList *clist)
   clist->undo_selection = NULL;
   clist->undo_unselection = NULL;
 
-  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
-  GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
   clist->focus_row = -1;
   clist->undo_anchor = -1;
 
@@ -948,6 +985,9 @@ gtk_clist_init (GtkCList *clist)
   clist->htimer = 0;
   clist->vtimer = 0;
 
+  clist->click_cell.row = -1;
+  clist->click_cell.column = -1;
+
   clist->compare = default_compare;
   clist->sort_type = GTK_SORT_ASCENDING;
   clist->sort_column = 0;
@@ -1015,7 +1055,6 @@ gtk_clist_construct (GtkCList *clist,
  *   gtk_clist_get_hadjustment
  *   gtk_clist_get_vadjustment
  *   gtk_clist_set_shadow_type
- *   gtk_clist_set_border *** deprecated function ***
  *   gtk_clist_set_selection_mode
  *   gtk_clist_freeze
  *   gtk_clist_thaw
@@ -1162,16 +1201,6 @@ gtk_clist_set_shadow_type (GtkCList      *clist,
     gtk_widget_queue_resize (GTK_WIDGET (clist));
 }
 
-/* deprecated function, use gtk_clist_set_shadow_type instead. */
-void
-gtk_clist_set_border (GtkCList      *clist,
-                     GtkShadowType  border)
-{
-  g_message ("gtk_clist_set_border() is deprecated");
-
-  gtk_clist_set_shadow_type (clist, border);
-}
-
 void
 gtk_clist_set_selection_mode (GtkCList         *clist,
                              GtkSelectionMode  mode)
@@ -1252,7 +1281,7 @@ gtk_clist_column_titles_show (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_CLIST_SHOW_TITLES (clist))
+  if (!GTK_CLIST_SHOW_TITLES(clist))
     {
       GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
       if (clist->title_window)
@@ -1267,7 +1296,7 @@ gtk_clist_column_titles_hide (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (GTK_CLIST_SHOW_TITLES (clist))
+  if (GTK_CLIST_SHOW_TITLES(clist))
     {
       GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
       if (clist->title_window)
@@ -1285,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
@@ -1328,6 +1367,9 @@ gtk_clist_column_titles_active (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
+  if (!GTK_CLIST_SHOW_TITLES(clist))
+    return;
+
   for (i = 0; i < clist->columns; i++)
     gtk_clist_column_title_active (clist, i);
 }
@@ -1340,7 +1382,7 @@ gtk_clist_column_titles_passive (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_CLIST_SHOW_TITLES (clist))
+  if (!GTK_CLIST_SHOW_TITLES(clist))
     return;
 
   for (i = 0; i < clist->columns; i++)
@@ -1568,12 +1610,14 @@ gtk_clist_set_column_visibility (GtkCList *clist,
       else
        gtk_widget_hide (clist->column[column].button);
     }
+  
+  gtk_widget_queue_resize (GTK_WIDGET(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));
@@ -1608,7 +1652,7 @@ gtk_clist_set_column_auto_resize (GtkCList *clist,
   if (auto_resize)
     {
       clist->column[column].resizeable = FALSE;
-      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
        {
          gint width;
 
@@ -1658,9 +1702,12 @@ gtk_clist_optimal_column_width (GtkCList *clist,
   if (column < 0 || column > clist->columns)
     return 0;
 
-  if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
-    width = (clist->column[column].button->requisition.width -
-            (CELL_SPACING + (2 * COLUMN_INSET)));
+  if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
+    width = (clist->column[column].button->requisition.width)
+#if 0
+            (CELL_SPACING + (2 * COLUMN_INSET)))
+#endif
+               ;
   else
     width = 0;
 
@@ -1745,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,
@@ -1756,7 +1804,7 @@ column_auto_resize (GtkCList    *clist,
   GtkRequisition requisition;
 
   if (!clist->column[column].auto_resize ||
-      GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     return;
 
   if (clist_row)
@@ -1775,7 +1823,7 @@ column_auto_resize (GtkCList    *clist,
 
       /* run a "gtk_clist_optimal_column_width" but break, if
        * the column doesn't shrink */
-      if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
+      if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
        new_width = (clist->column[column].button->requisition.width -
                     (CELL_SPACING + (2 * COLUMN_INSET)));
       else
@@ -1831,7 +1879,7 @@ abort_column_resize (GtkCList *clist)
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_CLIST_IN_DRAG (clist))
+  if (!GTK_CLIST_IN_DRAG(clist))
     return;
 
   GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
@@ -1842,7 +1890,7 @@ abort_column_resize (GtkCList *clist)
   if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
     draw_xor_line (clist);
 
-  if (GTK_CLIST_ADD_MODE (clist))
+  if (GTK_CLIST_ADD_MODE(clist))
     {
       gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
       gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
@@ -1947,7 +1995,7 @@ size_allocate_columns (GtkCList *clist,
       clist->column[i].area.x = xoffset;
       if (clist->column[i].width_set)
        {
-         if (!block_resize && GTK_CLIST_SHOW_TITLES (clist) &&
+         if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
              clist->column[i].auto_resize && clist->column[i].button)
            {
              gint width;
@@ -1962,7 +2010,7 @@ size_allocate_columns (GtkCList *clist,
          clist->column[i].area.width = clist->column[i].width;
          xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
        }
-      else if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button)
+      else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
        {
          clist->column[i].area.width =
            clist->column[i].button->requisition.width -
@@ -1981,17 +2029,14 @@ list_requisition_width (GtkCList *clist)
   gint width = CELL_SPACING;
   gint i;
 
-  for (i = clist->columns - 1; i >= 0 && !clist->column[i].visible; i--)
-    ;
-
-  for (; i >= 0; i--)
+  for (i = clist->columns - 1; i >= 0; i--)
     {
       if (!clist->column[i].visible)
        continue;
 
       if (clist->column[i].width_set)
        width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
-      else if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button)
+      else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
        width += clist->column[i].button->requisition.width;
     }
 
@@ -2010,15 +2055,19 @@ new_column_width (GtkCList *clist,
   gint width;
   gint cx;
   gint dx;
+  gint last_column;
 
   /* first translate the x position from widget->window
    * to clist->clist_window */
   cx = *x - xthickness;
 
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
   /* calculate new column width making sure it doesn't end up
    * less than the minimum width */
   dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
-       (column < clist->columns - 1) * CELL_SPACING);
+       (column < last_column) * CELL_SPACING);
   width = cx - dx;
 
   if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
@@ -2059,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);
 }
 
@@ -2083,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
@@ -2187,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;
 }
@@ -2208,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
@@ -2238,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;
@@ -2266,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);
   
@@ -2300,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;
@@ -2334,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);
@@ -2368,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;
@@ -2393,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);
@@ -2404,10 +2397,10 @@ 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))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
 
@@ -2441,7 +2434,7 @@ set_cell_contents (GtkCList    *clist,
   g_return_if_fail (clist_row != NULL);
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
 
@@ -2505,7 +2498,7 @@ set_cell_contents (GtkCList    *clist,
     }
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     column_auto_resize (clist, clist_row, column, requisition.width);
 }
 
@@ -2659,7 +2652,7 @@ real_insert_row (GtkCList *clist,
     }
   else
     {
-      if (GTK_CLIST_AUTO_SORT (clist))   /* override insertion pos */
+      if (GTK_CLIST_AUTO_SORT(clist))   /* override insertion pos */
        {
          GList *work;
          
@@ -2694,8 +2687,8 @@ real_insert_row (GtkCList *clist,
                                              clist_row))->next;
       else
        clist->row_list = g_list_insert (clist->row_list, clist_row, row);
+
     }
-  
   clist->rows++;
 
   if (row < ROW_FROM_YPIXEL (clist, 0))
@@ -2704,6 +2697,13 @@ real_insert_row (GtkCList *clist,
   /* syncronize the selection list */
   sync_selection (clist, row, SYNC_INSERT);
 
+  if (clist->rows == 1)
+    {
+      clist->focus_row = 0;
+      if (clist->selection_mode == GTK_SELECTION_BROWSE)
+       gtk_clist_select_row (clist, 0, -1);
+    }
+
   /* redraw the list if it isn't frozen */
   if (CLIST_UNFROZEN (clist))
     {
@@ -2735,7 +2735,8 @@ 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;
 
   /* if we're removing a selected row, we have to make sure
@@ -2746,13 +2747,14 @@ 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--;
-  clist->row_list = g_list_remove (clist->row_list, clist_row);
+  if (clist->row_list == list)
+    clist->row_list = g_list_next (list);
+  if (clist->row_list_end == list)
+    clist->row_list_end = g_list_previous (list);
+  g_list_remove (list, clist_row);
 
-  if (row == clist->rows)
-    clist->row_list_end = list->prev;
   /*if (clist->focus_row >=0 &&
       (row <= clist->focus_row || clist->focus_row >= clist->rows))
       clist->focus_row--;*/
@@ -2762,8 +2764,8 @@ real_remove_row (GtkCList *clist,
 
   sync_selection (clist, row, SYNC_REMOVE);
 
-  if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
-       clist->selection_mode == GTK_SELECTION_EXTENDED) && !clist->selection)
+  if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
+      clist->focus_row >= 0)
     gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
                     clist->focus_row, -1, NULL);
 
@@ -2819,7 +2821,7 @@ real_clear (GtkCList *clist)
   for (i = 0; i < clist->columns; i++)
     if (clist->column[i].auto_resize)
       {
-       if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[i].button)
+       if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
          gtk_clist_set_column_width
            (clist, i, (clist->column[i].button->requisition.width -
                        (CELL_SPACING + (2 * COLUMN_INSET))));
@@ -2849,7 +2851,7 @@ real_row_move (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CLIST_AUTO_SORT(clist))
     return;
 
   if (source_row < 0 || source_row >= clist->rows ||
@@ -2860,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);
@@ -2904,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
@@ -2914,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,
@@ -2936,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;
 }
@@ -2953,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;
 }
 
@@ -2985,7 +3072,7 @@ gtk_clist_swap_rows (GtkCList *clist,
   g_return_if_fail (GTK_IS_CLIST (clist));
   g_return_if_fail (row1 != row2);
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CLIST_AUTO_SORT(clist))
     return;
 
   gtk_clist_freeze (clist);
@@ -3007,7 +3094,7 @@ gtk_clist_row_move (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CLIST_AUTO_SORT(clist))
     return;
 
   if (source_row < 0 || source_row >= clist->rows ||
@@ -3062,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)
     {
@@ -3092,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)
     {
@@ -3122,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);
@@ -3133,13 +3220,13 @@ 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;
 
   if (clist->column[column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
 
@@ -3185,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;
 }
@@ -3206,14 +3293,14 @@ 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;
 
   old_width = g_new (gint, clist->columns);
 
-  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     {
       for (i = 0; i < clist->columns; i++)
        if (clist->column[i].auto_resize)
@@ -3242,7 +3329,7 @@ gtk_clist_set_row_style (GtkCList *clist,
                                             clist->clist_window);
     }
 
-  if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+  if (GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     for (i = 0; i < clist->columns; i++)
       column_auto_resize (clist, clist_row, i, old_width[i]);
 
@@ -3268,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;
 }
@@ -3295,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;
@@ -3307,22 +3394,8 @@ gtk_clist_set_selectable (GtkCList *clist,
       if (clist->anchor >= 0 &&
          clist->selection_mode == GTK_SELECTION_EXTENDED)
        {
-         if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
-           {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gtk_grab_remove (GTK_WIDGET (clist));
-             gdk_pointer_ungrab (GDK_CURRENT_TIME);
-             if (clist->htimer)
-               {
-                 gtk_timeout_remove (clist->htimer);
-                 clist->htimer = 0;
-               }
-             if (clist->vtimer)
-               {
-                 gtk_timeout_remove (clist->vtimer);
-                 clist->vtimer = 0;
-               }
-           }
+         clist->drag_button = 0;
+         remove_grab (clist);
          GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
        }
       gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
@@ -3340,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
@@ -3447,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;
@@ -3471,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;
@@ -3513,7 +3586,7 @@ toggle_focus_row (GtkCList *clist)
       clist->drag_pos = clist->focus_row;
       clist->undo_anchor = clist->focus_row;
       
-      if (GTK_CLIST_ADD_MODE (clist))
+      if (GTK_CLIST_ADD_MODE(clist))
        fake_toggle_row (clist, clist->focus_row);
       else
        GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
@@ -3536,7 +3609,7 @@ toggle_add_mode (GtkCList *clist)
     return;
 
   gtk_clist_draw_focus (GTK_WIDGET (clist));
-  if (!GTK_CLIST_ADD_MODE (clist))
+  if (!GTK_CLIST_ADD_MODE(clist))
     {
       GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
       gdk_gc_set_line_attributes (clist->xor_gc, 1,
@@ -3596,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;
@@ -3631,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)
     {
@@ -3753,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)
@@ -3770,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 ||
@@ -3797,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))
     {
@@ -3811,10 +3883,13 @@ 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)
+  if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
     {
       gtk_clist_draw_focus (GTK_WIDGET (clist));
       clist->focus_row = clist->undo_anchor;
@@ -3877,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);
@@ -3912,28 +3990,64 @@ resync_selection (GtkCList *clist,
        }
     }    
 
-  for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
-    if (GTK_CLIST_ROW (list)->selectable)
-      {
-       if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
+  if (clist->anchor < clist->drag_pos)
+    {
+      for (list = g_list_nth (clist->row_list, i); i <= e;
+          i++, list = list->next)
+       if (GTK_CLIST_ROW (list)->selectable)
          {
-           if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
+           if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
              {
-               GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
-               gtk_signal_emit (GTK_OBJECT (clist),
-                                clist_signals[UNSELECT_ROW], i, -1, event);
-               clist->undo_selection = g_list_prepend (clist->undo_selection,
-                                                       GINT_TO_POINTER (i));
+               if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
+                 {
+                   GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+                   gtk_signal_emit (GTK_OBJECT (clist),
+                                    clist_signals[UNSELECT_ROW],
+                                    i, -1, event);
+                   clist->undo_selection =
+                     g_list_prepend (clist->undo_selection,
+                                     GINT_TO_POINTER (i));
+                 }
+             }
+           else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+             {
+               GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+               clist->undo_unselection =
+                 g_list_prepend (clist->undo_unselection,
+                                 GINT_TO_POINTER (i));
              }
          }
-       else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+    }
+  else
+    {
+      for (list = g_list_nth (clist->row_list, e); i <= e;
+          e--, list = list->prev)
+       if (GTK_CLIST_ROW (list)->selectable)
          {
-           GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
-           clist->undo_unselection = g_list_prepend (clist->undo_unselection,
-                                                     GINT_TO_POINTER (i));
+           if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
+             {
+               if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
+                 {
+                   GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+                   gtk_signal_emit (GTK_OBJECT (clist),
+                                    clist_signals[UNSELECT_ROW],
+                                    e, -1, event);
+                   clist->undo_selection =
+                     g_list_prepend (clist->undo_selection,
+                                     GINT_TO_POINTER (e));
+                 }
+             }
+           else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+             {
+               GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+               clist->undo_unselection =
+                 g_list_prepend (clist->undo_unselection,
+                                 GINT_TO_POINTER (e));
+             }
          }
-      }
-
+    }
+  
+  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);
@@ -4109,7 +4223,7 @@ start_selection (GtkCList *clist)
   if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
     return;
 
-  set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
+  set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
              clist->focus_row);
 }
 
@@ -4119,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);
 }
 
@@ -4140,7 +4253,7 @@ extend_selection (GtkCList      *clist,
     return;
 
   if (auto_start_selection)
-    set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
+    set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
                clist->focus_row);
   else if (clist->anchor == -1)
     return;
@@ -4179,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);
@@ -4243,16 +4355,7 @@ gtk_clist_destroy (GtkObject *object)
       clist->vadjustment = NULL;
     }
 
-  if (clist->htimer)
-    {
-      gtk_timeout_remove (clist->htimer);
-      clist->htimer = 0;
-    }
-  if (clist->vtimer)
-    {
-      gtk_timeout_remove (clist->vtimer);
-      clist->vtimer = 0;
-    }
+  remove_grab (clist);
 
   /* destroy the column buttons */
   for (i = 0; i < clist->columns; i++)
@@ -4422,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,
@@ -4474,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;
@@ -4502,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);
@@ -4541,22 +4653,26 @@ gtk_clist_map (GtkWidget *widget)
     {
       GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
 
-      gdk_window_show (widget->window);
-      gdk_window_show (clist->title_window);
-      gdk_window_show (clist->clist_window);
-
       /* 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);
+       }
       
-      /* map resize windows AFTER column buttons (above) */
       for (i = 0; i < clist->columns; i++)
        if (clist->column[i].window && clist->column[i].button)
-         gdk_window_show (clist->column[i].window);
-       
+         {
+           gdk_window_raise (clist->column[i].window);
+           gdk_window_show (clist->column[i].window);
+         }
+
+      gdk_window_show (clist->title_window);
+      gdk_window_show (clist->clist_window);
+      gdk_window_show (widget->window);
+
       /* unfreeze the list */
       clist->freeze_count = 0;
     }
@@ -4577,6 +4693,29 @@ gtk_clist_unmap (GtkWidget *widget)
     {
       GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
+      if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+       {
+         remove_grab (clist);
+
+         GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, NULL);
+
+         clist->click_cell.row = -1;
+         clist->click_cell.column = -1;
+         clist->drag_button = 0;
+
+         if (GTK_CLIST_IN_DRAG(clist))
+           {
+             gpointer drag_data;
+
+             GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
+             drag_data = gtk_object_get_data (GTK_OBJECT (clist),
+                                              "gtk-site-data");
+             if (drag_data)
+               gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist),
+                                                   drag_data);
+           }
+       }
+
       for (i = 0; i < clist->columns; i++)
        if (clist->column[i].window)
          gdk_window_hide (clist->column[i].window);
@@ -4629,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++)
@@ -4700,7 +4839,7 @@ gtk_clist_style_set (GtkWidget *widget,
   /* Fill in data after widget has correct style */
 
   /* text properties */
-  if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
+  if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
     {
       clist->row_height = (widget->style->font->ascent +
                           widget->style->font->descent + 1);
@@ -4712,7 +4851,7 @@ gtk_clist_style_set (GtkWidget *widget,
                                      widget->style->font->descent - 1) / 2;
 
   /* Column widths */
-  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED(clist))
     {
       gint width;
       gint i;
@@ -4765,6 +4904,7 @@ gtk_clist_button_press (GtkWidget      *widget,
   gint y;
   gint row;
   gint column;
+  gint button_actions;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
@@ -4772,10 +4912,11 @@ gtk_clist_button_press (GtkWidget      *widget,
 
   clist = GTK_CLIST (widget);
 
-  /* we don't handle button 2 and 3 */
-  if (event->button != 1)
+  button_actions = clist->button_actions[event->button - 1];
+
+  if (button_actions == GTK_BUTTON_IGNORED)
     return FALSE;
-  
+
   /* selections on the list */
   if (event->window == clist->clist_window)
     {
@@ -4791,126 +4932,144 @@ gtk_clist_button_press (GtkWidget      *widget,
 
          if (event->type == GDK_BUTTON_PRESS)
            {
-             GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gdk_pointer_grab (clist->clist_window, FALSE,
-                               GDK_POINTER_MOTION_HINT_MASK |
-                               GDK_BUTTON1_MOTION_MASK |
-                               GDK_BUTTON_RELEASE_MASK,
-                               NULL, NULL, event->time);
+             GdkEventMask mask = ((1 << (4 + event->button)) |
+                                  GDK_POINTER_MOTION_HINT_MASK |
+                                  GDK_BUTTON_RELEASE_MASK);
+
+             if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
+                                   NULL, NULL, event->time))
+               return FALSE;
              gtk_grab_add (widget);
+
+             clist->click_cell.row = row;
+             clist->click_cell.column = column;
+             clist->drag_button = event->button;
            }
-         else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget))
+         else
            {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gtk_grab_remove (widget);
-             gdk_pointer_ungrab (event->time);
+             clist->click_cell.row = -1;
+             clist->click_cell.column = -1;
+
+             clist->drag_button = 0;
+             remove_grab (clist);
            }
 
-         if (GTK_CLIST_ADD_MODE (clist))
+         if (button_actions & GTK_BUTTON_SELECTS)
            {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
-             if (GTK_WIDGET_HAS_FOCUS (widget))
-               {
-                 gtk_clist_draw_focus (widget);
-                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                             GDK_LINE_SOLID, 0, 0);
-                 clist->focus_row = row;
-                 gtk_clist_draw_focus (widget);
-               }
-             else
+             if (GTK_CLIST_ADD_MODE(clist))
                {
-                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                             GDK_LINE_SOLID, 0, 0);
-                 clist->focus_row = row;
+                 GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
+                 if (GTK_WIDGET_HAS_FOCUS(widget))
+                   {
+                     gtk_clist_draw_focus (widget);
+                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                                 GDK_LINE_SOLID, 0, 0);
+                     clist->focus_row = row;
+                     gtk_clist_draw_focus (widget);
+                   }
+                 else
+                   {
+                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                                 GDK_LINE_SOLID, 0, 0);
+                     clist->focus_row = row;
+                   }
                }
-           }
-         else if (row != clist->focus_row)
-           {
-             if (GTK_WIDGET_HAS_FOCUS (widget))
+             else if (row != clist->focus_row)
                {
-                 gtk_clist_draw_focus (widget);
-                 clist->focus_row = row;
-                 gtk_clist_draw_focus (widget);
+                 if (GTK_WIDGET_HAS_FOCUS(widget))
+                   {
+                     gtk_clist_draw_focus (widget);
+                     clist->focus_row = row;
+                     gtk_clist_draw_focus (widget);
+                   }
+                 else
+                   clist->focus_row = row;
                }
-             else
-               clist->focus_row = row;
            }
 
-         if (!GTK_WIDGET_HAS_FOCUS (widget))
+         if (!GTK_WIDGET_HAS_FOCUS(widget))
            gtk_widget_grab_focus (widget);
 
-         switch (clist->selection_mode)
+         if (button_actions & GTK_BUTTON_SELECTS)
            {
-           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);
-             else
-               clist->anchor = row;
-             break;
-           case GTK_SELECTION_BROWSE:
-             gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                              row, column, event);
-             break;
-           case GTK_SELECTION_EXTENDED:
-             if (event->type != GDK_BUTTON_PRESS)
+             switch (clist->selection_mode)
                {
-                 if (clist->anchor != -1)
+               case GTK_SELECTION_SINGLE:
+               case GTK_SELECTION_MULTIPLE:
+                 if (event->type != GDK_BUTTON_PRESS)
                    {
-                     update_extended_selection (clist, clist->focus_row);
-                     GTK_CLIST_CLASS_FW (clist)->resync_selection
-                       (clist, (GdkEvent *) event);
+                     gtk_signal_emit (GTK_OBJECT (clist),
+                                      clist_signals[SELECT_ROW],
+                                      row, column, event);
+                     clist->anchor = -1;
                    }
+                 else
+                   clist->anchor = row;
+                 break;
+               case GTK_SELECTION_BROWSE:
                  gtk_signal_emit (GTK_OBJECT (clist),
                                   clist_signals[SELECT_ROW],
                                   row, column, event);
                  break;
-               }
-             
-             if (event->state & GDK_CONTROL_MASK)
-               {
-                 if (event->state & GDK_SHIFT_MASK)
+               case GTK_SELECTION_EXTENDED:
+                 if (event->type != GDK_BUTTON_PRESS)
                    {
-                     if (clist->anchor < 0)
+                     if (clist->anchor != -1)
                        {
-                         g_list_free (clist->undo_selection);
-                         g_list_free (clist->undo_unselection);
-                         clist->undo_selection = NULL;
-                         clist->undo_unselection = NULL;
-                         clist->anchor = old_row;
-                         clist->drag_pos = old_row;
-                         clist->undo_anchor = old_row;
+                         update_extended_selection (clist, clist->focus_row);
+                         GTK_CLIST_CLASS_FW (clist)->resync_selection
+                           (clist, (GdkEvent *) event);
                        }
-                     update_extended_selection (clist, clist->focus_row);
+                     gtk_signal_emit (GTK_OBJECT (clist),
+                                      clist_signals[SELECT_ROW],
+                                      row, column, event);
+                     break;
                    }
-                 else
+             
+                 if (event->state & GDK_CONTROL_MASK)
                    {
-                     if (clist->anchor == -1)
-                       set_anchor (clist, TRUE, row, old_row);
+                     if (event->state & GDK_SHIFT_MASK)
+                       {
+                         if (clist->anchor < 0)
+                           {
+                             g_list_free (clist->undo_selection);
+                             g_list_free (clist->undo_unselection);
+                             clist->undo_selection = NULL;
+                             clist->undo_unselection = NULL;
+                             clist->anchor = old_row;
+                             clist->drag_pos = old_row;
+                             clist->undo_anchor = old_row;
+                           }
+                         update_extended_selection (clist, clist->focus_row);
+                       }
                      else
-                       update_extended_selection (clist, clist->focus_row);
+                       {
+                         if (clist->anchor == -1)
+                           set_anchor (clist, TRUE, row, old_row);
+                         else
+                           update_extended_selection (clist,
+                                                      clist->focus_row);
+                       }
+                     break;
                    }
-                 break;
-               }
 
-             if (event->state & GDK_SHIFT_MASK)
-               {
-                 set_anchor (clist, FALSE, old_row, old_row);
-                 update_extended_selection (clist, clist->focus_row);
+                 if (event->state & GDK_SHIFT_MASK)
+                   {
+                     set_anchor (clist, FALSE, old_row, old_row);
+                     update_extended_selection (clist, clist->focus_row);
+                     break;
+                   }
+
+                 if (clist->anchor == -1)
+                   set_anchor (clist, FALSE, row, old_row);
+                 else
+                   update_extended_selection (clist, clist->focus_row);
+                 break;
+               default:
                  break;
                }
-
-             if (clist->anchor == -1)
-               set_anchor (clist, FALSE, row, old_row);
-             else
-               update_extended_selection (clist, clist->focus_row);
-             break;
-           default:
-             break;
            }
        }
-
       return FALSE;
     }
 
@@ -4919,26 +5078,33 @@ gtk_clist_button_press (GtkWidget      *widget,
     if (clist->column[i].resizeable && clist->column[i].window &&
        event->window == clist->column[i].window)
       {
-       gdk_pointer_grab (clist->column[i].window, FALSE,
-                         GDK_POINTER_MOTION_HINT_MASK |
-                         GDK_BUTTON1_MOTION_MASK |
-                         GDK_BUTTON_RELEASE_MASK,
-                         NULL, NULL, event->time);
+       gpointer drag_data;
+
+       if (gdk_pointer_grab (clist->column[i].window, FALSE,
+                             GDK_POINTER_MOTION_HINT_MASK |
+                             GDK_BUTTON1_MOTION_MASK |
+                             GDK_BUTTON_RELEASE_MASK,
+                             NULL, NULL, event->time))
+         return FALSE;
+
        gtk_grab_add (widget);
        GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
 
-       if (!GTK_WIDGET_HAS_FOCUS (widget))
+       /* block attached dnd signal handler */
+       drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
+       if (drag_data)
+         gtk_signal_handler_block_by_data (GTK_OBJECT (clist), drag_data);
+
+       if (!GTK_WIDGET_HAS_FOCUS(widget))
          gtk_widget_grab_focus (widget);
 
        clist->drag_pos = i;
        clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
                         clist->column[i].area.width + CELL_SPACING);
 
-       if (GTK_CLIST_ADD_MODE (clist))
+       if (GTK_CLIST_ADD_MODE(clist))
          gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
        draw_xor_line (clist);
-
-       return FALSE;
       }
   return FALSE;
 }
@@ -4948,6 +5114,7 @@ gtk_clist_button_release (GtkWidget      *widget,
                          GdkEventButton *event)
 {
   GtkCList *clist;
+  gint button_actions;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
@@ -4955,13 +5122,14 @@ gtk_clist_button_release (GtkWidget      *widget,
 
   clist = GTK_CLIST (widget);
 
-  /* we don't handle button 2 and 3 */
-  if (event->button != 1)
+  button_actions = clist->button_actions[event->button - 1];
+  if (button_actions == GTK_BUTTON_IGNORED)
     return FALSE;
 
   /* release on resize windows */
-  if (GTK_CLIST_IN_DRAG (clist))
+  if (GTK_CLIST_IN_DRAG(clist))
     {
+      gpointer drag_data;
       gint width;
       gint x;
       gint i;
@@ -4969,6 +5137,11 @@ gtk_clist_button_release (GtkWidget      *widget,
       i = clist->drag_pos;
       clist->drag_pos = -1;
 
+      /* unblock attached dnd signal handler */
+      drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
+      if (drag_data)
+       gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), drag_data);
+
       GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
       gtk_widget_get_pointer (widget, &x, NULL);
       gtk_grab_remove (widget);
@@ -4977,7 +5150,7 @@ gtk_clist_button_release (GtkWidget      *widget,
       if (clist->x_drag >= 0)
        draw_xor_line (clist);
 
-      if (GTK_CLIST_ADD_MODE (clist))
+      if (GTK_CLIST_ADD_MODE(clist))
        {
          gdk_gc_set_line_attributes (clist->xor_gc, 1,
                                      GDK_LINE_ON_OFF_DASH, 0, 0);
@@ -4989,134 +5162,47 @@ gtk_clist_button_release (GtkWidget      *widget,
       return FALSE;
     }
 
-  if (GTK_CLIST_DRAG_SELECTION (clist))
+  if (clist->drag_button == event->button)
     {
       gint row;
       gint column;
 
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-      gtk_grab_remove (widget);
-      gdk_pointer_ungrab (event->time);
-      if (clist->htimer)
-       {
-         gtk_timeout_remove (clist->htimer);
-         clist->htimer = 0;
-       }
-      if (clist->vtimer)
-       {
-         gtk_timeout_remove (clist->vtimer);
-         clist->vtimer = 0;
-       }
-      switch (clist->selection_mode)
-       {
-       case GTK_SELECTION_EXTENDED:
-         if (!(event->state & GDK_SHIFT_MASK) ||
-             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
-             (clist, (GdkEvent *) event);
-         break;
+      clist->drag_button = 0;
+      clist->click_cell.row = -1;
+      clist->click_cell.column = -1;
+
+      remove_grab (clist);
 
-       case GTK_SELECTION_SINGLE:
-       case GTK_SELECTION_MULTIPLE:
-         if (get_selection_info (clist, event->x, event->y, &row, &column))
+      if (button_actions & GTK_BUTTON_SELECTS)
+       {
+         switch (clist->selection_mode)
            {
-             if (row >= 0 && row < clist->rows && clist->anchor == row)
-               toggle_row (clist, row, column, (GdkEvent *) event);
+           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
+                 (clist, (GdkEvent *) event);
+             break;
+           case GTK_SELECTION_SINGLE:
+           case GTK_SELECTION_MULTIPLE:
+             if (get_selection_info (clist, event->x, event->y,
+                                     &row, &column))
+               {
+                 if (row >= 0 && row < clist->rows && clist->anchor == row)
+                   toggle_row (clist, row, column, (GdkEvent *) event);
+               }
+             clist->anchor = -1;
+             break;
+           default:
+             break;
            }
-         clist->anchor = -1;
-         break;
-
-       default:
-         break;
        }
     }
-
-  return FALSE;
-}
-
-static gint
-horizontal_timeout (GtkCList *clist)
-{
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  GTK_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;
-
-  gtk_clist_motion (GTK_WIDGET (clist), &event);
-
-  GTK_THREADS_LEAVE;
-  
-  return FALSE;
-}
-
-static gint
-vertical_timeout (GtkCList *clist)
-{
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  GTK_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;
-
-  gtk_clist_motion (GTK_WIDGET (clist), &event);
-
-  GTK_THREADS_LEAVE;
-
   return FALSE;
 }
 
-static void
-move_vertical (GtkCList *clist,
-              gint      row,
-              gfloat    align)
-{
-  gfloat value;
-
-  if (!clist->vadjustment)
-    return;
-
-  value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
-          align * (clist->clist_window_height - clist->row_height) +
-          (2 * align - 1) * CELL_SPACING);
-
-  if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
-    value = clist->vadjustment->upper - clist->vadjustment->page_size;
-
-  gtk_adjustment_set_value(clist->vadjustment, value);
-}
-
-static void
-move_horizontal (GtkCList *clist,
-                gint      diff)
-{
-  gfloat value;
-
-  if (!clist->hadjustment)
-    return;
-
-  value = CLAMP (clist->hadjustment->value + diff, 0.0,
-                clist->hadjustment->upper - clist->hadjustment->page_size);
-  gtk_adjustment_set_value(clist->hadjustment, value);
-}
-
 static gint
 gtk_clist_motion (GtkWidget      *widget,
                  GdkEventMotion *event)
@@ -5126,6 +5212,7 @@ gtk_clist_motion (GtkWidget      *widget,
   gint y;
   gint row;
   gint new_width;
+  gint button_actions = 0;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
@@ -5134,7 +5221,10 @@ gtk_clist_motion (GtkWidget      *widget,
   if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
     return FALSE;
 
-  if (GTK_CLIST_IN_DRAG (clist))
+  if (clist->drag_button > 0)
+    button_actions = clist->button_actions[clist->drag_button - 1];
+
+  if (GTK_CLIST_IN_DRAG(clist))
     {
       if (event->is_hint || event->window != widget->window)
        gtk_widget_get_pointer (widget, &x, NULL);
@@ -5177,6 +5267,30 @@ gtk_clist_motion (GtkWidget      *widget,
   if (event->is_hint || event->window != clist->clist_window)
     gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
 
+  if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS)
+    {
+      /* delayed drag start */
+      if (event->window == clist->clist_window &&
+         clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
+         (y < 0 || y >= clist->clist_window_height ||
+          x < 0 || x >= clist->clist_window_width  ||
+          y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
+          y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
+                clist->row_height) ||
+          x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
+          x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) + 
+                clist->column[clist->click_cell.column].area.width)))
+       {
+         GtkTargetList  *target_list;
+
+         target_list = gtk_target_list_new (&clist_target_table, 1);
+         gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
+                         clist->drag_button, (GdkEvent *)event);
+
+       }
+      return TRUE;
+    }
+
   /* horizontal autoscrolling */
   if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
       (x < 0 || x >= clist->clist_window_width))
@@ -5199,7 +5313,7 @@ gtk_clist_motion (GtkWidget      *widget,
        }
     }
 
-  if (GTK_CLIST_IN_DRAG (clist))
+  if (GTK_CLIST_IN_DRAG(clist))
     return FALSE;
 
   /* vertical autoscrolling */
@@ -5219,18 +5333,17 @@ gtk_clist_motion (GtkWidget      *widget,
       clist->vtimer = gtk_timeout_add (SCROLL_TIME,
                                       (GtkFunction) vertical_timeout, clist);
 
-      if (GTK_CLIST_DRAG_SELECTION (clist))
-       {
-         if ((y < 0 && clist->focus_row == 0) ||
-             (y >= clist->clist_window_height &&
-              clist->focus_row == clist->rows-1))
-           return FALSE;
-       }
+      if (clist->drag_button &&
+         ((y < 0 && clist->focus_row == 0) ||
+          (y >= clist->clist_window_height &&
+           clist->focus_row == clist->rows - 1)))
+       return FALSE;
     }
 
   row = CLAMP (row, 0, clist->rows - 1);
 
-  if (GTK_CLIST_DRAG_SELECTION (clist))
+  if (button_actions & GTK_BUTTON_SELECTS &
+      !gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"))
     {
       if (row == clist->focus_row)
        return FALSE;
@@ -5280,15 +5393,17 @@ gtk_clist_size_request (GtkWidget      *widget,
 
   /* compute the size of the column title (title) area */
   clist->column_title_area.height = 0;
-  if (GTK_CLIST_SHOW_TITLES (clist))
+  if (GTK_CLIST_SHOW_TITLES(clist))
     for (i = 0; i < clist->columns; i++)
       if (clist->column[i].button)
        {
+         GtkRequisition child_requisition;
+         
          gtk_widget_size_request (clist->column[i].button,
-                                  &clist->column[i].button->requisition);
+                                  &child_requisition);
          clist->column_title_area.height =
            MAX (clist->column_title_area.height,
-                clist->column[i].button->requisition.height);
+                child_requisition.height);
        }
 
   requisition->width += (widget->style->klass->xthickness +
@@ -5333,9 +5448,9 @@ gtk_clist_size_allocate (GtkWidget     *widget,
    * border width */
   clist->internal_allocation.x = 0;
   clist->internal_allocation.y = 0;
-  clist->internal_allocation.width = MAX (1, allocation->width -
+  clist->internal_allocation.width = MAX (1, (gint)allocation->width -
                                          border_width * 2);
-  clist->internal_allocation.height = MAX (1, allocation->height -
+  clist->internal_allocation.height = MAX (1, (gint)allocation->height -
                                           border_width * 2);
        
   /* allocate clist window assuming no scrollbars */
@@ -5344,11 +5459,11 @@ gtk_clist_size_allocate (GtkWidget     *widget,
   clist_allocation.y = (clist->internal_allocation.y +
                        widget->style->klass->ythickness +
                        clist->column_title_area.height);
-  clist_allocation.width = MAX (1, clist->internal_allocation.width - 
-                               (2 * widget->style->klass->xthickness));
-  clist_allocation.height = MAX (1, clist->internal_allocation.height -
-                                (2 * widget->style->klass->ythickness) -
-                                clist->column_title_area.height);
+  clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width - 
+                               (2 * (gint)widget->style->klass->xthickness));
+  clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
+                                (2 * (gint)widget->style->klass->ythickness) -
+                                (gint)clist->column_title_area.height);
   
   clist->clist_window_width = clist_allocation.width;
   clist->clist_window_height = clist_allocation.height;
@@ -5524,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);
 }
@@ -5540,6 +5657,7 @@ draw_row (GtkCList     *clist,
   GdkRectangle cell_rectangle;
   GdkRectangle clip_rectangle;
   GdkRectangle intersect_rectangle;
+  gint last_column;
   gint state;
   gint i;
 
@@ -5554,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;
@@ -5568,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 */
@@ -5599,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;
@@ -5630,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;
@@ -5645,6 +5763,10 @@ draw_row (GtkCList     *clist,
        }         
     }
   
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--)
+    ;
+
   /* iterate and draw all the columns (row cells) and draw their contents */
   for (i = 0; i < clist->columns; i++)
     {
@@ -5669,7 +5791,7 @@ draw_row (GtkCList     *clist,
       /* calculate clipping region clipping region */
       clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
       clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
-                              (i + 1 == clist->columns) * CELL_SPACING);
+                              (i == last_column) * CELL_SPACING);
       
       if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
                                            &intersect_rectangle))
@@ -5680,7 +5802,7 @@ draw_row (GtkCList     *clist,
 
       clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
       clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
-                              (i + 1 == clist->columns) * CELL_SPACING);
+                              (i == last_column) * CELL_SPACING);
 
       /* calculate real width for column justification */
       pixmap_width = 0;
@@ -5772,7 +5894,8 @@ draw_row (GtkCList     *clist,
     }
 
   /* draw focus rectangle */
-  if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
+  if (clist->focus_row == row &&
+      GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
     {
       if (!area)
        gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
@@ -5826,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)
     {
@@ -5841,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                          
@@ -5922,10 +6045,7 @@ gtk_clist_get_selection_info (GtkCList *clist,
   return get_selection_info (clist, x, y, row, column);
 }
 
-/* 
- * SCROLLBARS
- *
- * functions:
+/* PRIVATE ADJUSTMENT FUNCTIONS
  *   adjust_adjustments
  *   vadjustment_changed
  *   hadjustment_changed
@@ -5945,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));
@@ -5963,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));
@@ -5976,14 +6098,15 @@ adjust_adjustments (GtkCList *clist,
   if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
     {
       GtkWidget *widget;
+      GtkRequisition requisition;
 
       widget = GTK_WIDGET (clist);
-      gtk_widget_size_request (widget, &widget->requisition);
+      gtk_widget_size_request (widget, &requisition);
 
       if ((!clist->hadjustment &&
-          widget->requisition.width != widget->allocation.width) ||
+          requisition.width != widget->allocation.width) ||
          (!clist->vadjustment &&
-          widget->requisition.height != widget->allocation.height))
+          requisition.height != widget->allocation.height))
        gtk_widget_queue_resize (widget);
     }
 }
@@ -6145,8 +6268,8 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
          return;
        }
 
-      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_CLIST_ADD_MODE (clist))
+      if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+         !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_ADD_MODE(clist))
        {
          y = ROW_TOP_YPIXEL (clist, clist->focus_row);
              
@@ -6180,8 +6303,8 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
          return;
        }
       
-      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_CLIST_ADD_MODE (clist))
+      if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+         !GTK_CLIST_CHILD_HAS_FOCUS(clist) && GTK_CLIST_ADD_MODE(clist))
        {
          y = ROW_TOP_YPIXEL (clist, clist->focus_row);
          
@@ -6208,9 +6331,10 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
 
   check_exposures (clist);
 
-  if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+  if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+      !GTK_CLIST_CHILD_HAS_FOCUS(clist))
     {
-      if (GTK_CLIST_ADD_MODE (clist))
+      if (GTK_CLIST_ADD_MODE(clist))
        {
          gint focus_row;
          
@@ -6273,7 +6397,7 @@ check_exposures (GtkCList *clist)
     }
 }
 
-/* 
+/* PRIVATE 
  * Memory Allocation/Distruction Routines for GtkCList stuctures
  *
  * functions:
@@ -6307,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;
     }
 
@@ -6415,7 +6540,7 @@ gtk_clist_focus (GtkContainer     *container,
   g_return_val_if_fail (container != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
 
-  if (!GTK_WIDGET_SENSITIVE (container))
+  if (!GTK_WIDGET_IS_SENSITIVE (container))
     return FALSE;
   
   clist = GTK_CLIST (container);
@@ -6426,7 +6551,7 @@ gtk_clist_focus (GtkContainer     *container,
     {
     case GTK_DIR_LEFT:
     case GTK_DIR_RIGHT:
-      if (GTK_CLIST_CHILD_HAS_FOCUS (clist))
+      if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
        {
          if (title_focus (clist, direction))
            return TRUE;
@@ -6437,7 +6562,7 @@ gtk_clist_focus (GtkContainer     *container,
       return TRUE;
     case GTK_DIR_DOWN:
     case GTK_DIR_TAB_FORWARD:
-      if (GTK_CLIST_CHILD_HAS_FOCUS (clist))
+      if (GTK_CLIST_CHILD_HAS_FOCUS(clist))
        {
          gboolean tf = FALSE;
 
@@ -6469,7 +6594,7 @@ gtk_clist_focus (GtkContainer     *container,
     case GTK_DIR_UP:
     case GTK_DIR_TAB_BACKWARD:
       if (!focus_child &&
-         GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
+         GTK_CLIST_CHILD_HAS_FOCUS(clist) && clist->rows)
        {
          if (clist->focus_row < 0)
            {
@@ -6507,7 +6632,7 @@ gtk_clist_draw_focus (GtkWidget *widget)
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_CLIST (widget));
 
-  if (!GTK_WIDGET_DRAWABLE (widget))
+  if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
     return;
 
   clist = GTK_CLIST (widget);
@@ -6568,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;
 }
@@ -6596,25 +6720,30 @@ title_focus (GtkCList *clist,
 {
   GtkWidget *focus_child;
   gboolean return_val = FALSE;
+  gint last_column;
   gint d = 1;
   gint i = 0;
   gint j;
 
-  if (!GTK_CLIST_SHOW_TITLES (clist))
+  if (!GTK_CLIST_SHOW_TITLES(clist))
     return FALSE;
 
   focus_child = GTK_CONTAINER (clist)->focus_child;
+
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--)
+    ;
   
   switch (dir)
     {
     case GTK_DIR_TAB_BACKWARD:
     case GTK_DIR_UP:
-      if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+      if (!focus_child || !GTK_CLIST_CHILD_HAS_FOCUS(clist))
        {
          if (dir == GTK_DIR_UP)
            i = COLUMN_FROM_XPIXEL (clist, 0);
          else
-           i = clist->columns - 1;
+           i = last_column;
          focus_child = clist->column[i].button;
          dir = GTK_DIR_TAB_FORWARD;
        }
@@ -6625,7 +6754,7 @@ title_focus (GtkCList *clist,
       d = -1;
       if (!focus_child)
        {
-         i = clist->columns - 1;
+         i = last_column;
          focus_child = clist->column[i].button;
        }
       break;
@@ -6646,7 +6775,7 @@ title_focus (GtkCList *clist,
            if (clist->column[i].button && 
                GTK_WIDGET_VISIBLE (clist->column[i].button) &&
                GTK_IS_CONTAINER (clist->column[i].button) &&
-               !GTK_WIDGET_HAS_FOCUS (clist->column[i].button))
+               !GTK_WIDGET_HAS_FOCUS(clist->column[i].button))
              if (gtk_container_focus 
                  (GTK_CONTAINER (clist->column[i].button), dir))
                {
@@ -6693,7 +6822,7 @@ title_focus (GtkCList *clist,
       else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
               clist->clist_window_width)
        {
-         if (j == clist->columns-1)
+         if (j == last_column)
            gtk_clist_moveto (clist, -1, j, 0, 0);
          else
            gtk_clist_moveto (clist, -1, j, 0, 1);
@@ -6702,10 +6831,15 @@ title_focus (GtkCList *clist,
   return return_val;
 }
 
-/* SCROLLING FUNCTIONS
+/* PRIVATE SCROLLING FUNCTIONS
  *   move_focus_row
  *   scroll_horizontal
  *   scroll_vertical
+ *   move_horizontal
+ *   move_vertical
+ *   horizontal_timeout
+ *   vertical_timeout
+ *   remove_grab
  */
 static void
 move_focus_row (GtkCList      *clist,
@@ -6774,6 +6908,7 @@ scroll_horizontal (GtkCList      *clist,
                   gfloat         position)
 {
   gint column = 0;
+  gint last_column;
 
   g_return_if_fail (clist != 0);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -6781,6 +6916,10 @@ scroll_horizontal (GtkCList      *clist,
   if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
     return;
 
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--)
+    ;
+
   switch (scroll_type)
     {
     case GTK_SCROLL_STEP_BACKWARD:
@@ -6790,13 +6929,13 @@ scroll_horizontal (GtkCList      *clist,
        column--;
       break;
     case GTK_SCROLL_STEP_FORWARD:
-      column =  COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
+      column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
       if (column < 0)
        return;
       if (COLUMN_LEFT_XPIXEL (clist, column) +
          clist->column[column].area.width +
          CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
-         column < clist->columns - 1)
+         column < last_column)
        column++;
       break;
     case GTK_SCROLL_PAGE_BACKWARD:
@@ -6804,7 +6943,22 @@ scroll_horizontal (GtkCList      *clist,
       return;
     case GTK_SCROLL_JUMP:
       if (position >= 0 && position <= 1)
-       column = position * (clist->columns - 1);
+       {
+         gint vis_columns = 0;
+         gint i;
+
+         for (i = 0; i <= last_column; i++)
+           if (clist->column[i].visible)
+             vis_columns++;
+
+         column = position * vis_columns;
+
+         for (i = 0; i <= last_column && column > 0; i++)
+           if (clist->column[i].visible)
+             column--;
+
+         column = i;
+       }
       else
        return;
       break;
@@ -6817,7 +6971,7 @@ scroll_horizontal (GtkCList      *clist,
   else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
           + clist->column[column].area.width > clist->clist_window_width)
     {
-      if (column == clist->columns - 1)
+      if (column == last_column)
        gtk_clist_moveto (clist, -1, column, 0, 0);
       else
        gtk_clist_moveto (clist, -1, column, 0, 1);
@@ -6852,7 +7006,7 @@ scroll_vertical (GtkCList      *clist,
          if (clist->selection_mode == GTK_SELECTION_BROWSE)
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
                             old_focus_row, -1, NULL);
-         else if (!GTK_CLIST_ADD_MODE (clist))
+         else if (!GTK_CLIST_ADD_MODE(clist))
            {
              gtk_clist_unselect_all (clist);
              clist->undo_anchor = old_focus_row;
@@ -6864,7 +7018,7 @@ scroll_vertical (GtkCList      *clist,
        case GTK_VISIBILITY_NONE:
          if (old_focus_row != clist->focus_row &&
              !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
-               GTK_CLIST_ADD_MODE (clist)))
+               GTK_CLIST_ADD_MODE(clist)))
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
                             clist->focus_row, -1, NULL);
          switch (scroll_type)
@@ -6904,7 +7058,7 @@ scroll_vertical (GtkCList      *clist,
        default:
          if (old_focus_row != clist->focus_row &&
              !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
-               GTK_CLIST_ADD_MODE (clist)))
+               GTK_CLIST_ADD_MODE(clist)))
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
                             clist->focus_row, -1, NULL);
          break;
@@ -6922,6 +7076,101 @@ scroll_vertical (GtkCList      *clist,
     }
 }
 
+static void
+move_horizontal (GtkCList *clist,
+                gint      diff)
+{
+  gfloat value;
+
+  if (!clist->hadjustment)
+    return;
+
+  value = CLAMP (clist->hadjustment->value + diff, 0.0,
+                clist->hadjustment->upper - clist->hadjustment->page_size);
+  gtk_adjustment_set_value(clist->hadjustment, value);
+}
+
+static void
+move_vertical (GtkCList *clist,
+              gint      row,
+              gfloat    align)
+{
+  gfloat value;
+
+  if (!clist->vadjustment)
+    return;
+
+  value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
+          align * (clist->clist_window_height - clist->row_height) +
+          (2 * align - 1) * CELL_SPACING);
+
+  if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
+    value = clist->vadjustment->upper - clist->vadjustment->page_size;
+
+  gtk_adjustment_set_value(clist->vadjustment, value);
+}
+
+static gint
+horizontal_timeout (GtkCList *clist)
+{
+  GdkEventMotion event = { 0 };
+
+  GDK_THREADS_ENTER ();
+
+  clist->htimer = 0;
+
+  event.type = GDK_MOTION_NOTIFY;
+  event.send_event = TRUE;
+
+  gtk_clist_motion (GTK_WIDGET (clist), &event);
+
+  GDK_THREADS_LEAVE ();
+  
+  return FALSE;
+}
+
+static gint
+vertical_timeout (GtkCList *clist)
+{
+  GdkEventMotion event = { 0 };
+
+  GDK_THREADS_ENTER ();
+
+  clist->vtimer = 0;
+
+  event.type = GDK_MOTION_NOTIFY;
+  event.send_event = TRUE;
+
+  gtk_clist_motion (GTK_WIDGET (clist), &event);
+
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+static void
+remove_grab (GtkCList *clist)
+{
+  if (GTK_WIDGET_HAS_GRAB (clist))
+    {
+      gtk_grab_remove (GTK_WIDGET (clist));
+      if (gdk_pointer_is_grabbed ())
+       gdk_pointer_ungrab (GDK_CURRENT_TIME);
+    }
+
+  if (clist->htimer)
+    {
+      gtk_timeout_remove (clist->htimer);
+      clist->htimer = 0;
+    }
+
+  if (clist->vtimer)
+    {
+      gtk_timeout_remove (clist->vtimer);
+      clist->vtimer = 0;
+    }
+}
+
 /* PUBLIC SORTING FUNCTIONS
  * gtk_clist_sort
  * gtk_clist_set_compare_func
@@ -6955,9 +7204,9 @@ gtk_clist_set_auto_sort (GtkCList *clist,
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
   
-  if (GTK_CLIST_AUTO_SORT (clist) && !auto_sort)
+  if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
     GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
-  else if (!GTK_CLIST_AUTO_SORT (clist) && auto_sort)
+  else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
     {
       GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
       gtk_clist_sort (clist);
@@ -7166,3 +7415,480 @@ gtk_clist_mergesort (GtkCList *clist,
                       gtk_clist_mergesort (clist, half, num - num / 2));
     }
 }
+
+/************************/
+
+static void
+drag_source_info_destroy (gpointer data)
+{
+  GtkCListCellInfo *info = data;
+
+  g_free (info);
+}
+
+static void
+drag_dest_info_destroy (gpointer data)
+{
+  GtkCListDestInfo *info = 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)
+{
+  GtkCList *clist;
+  GtkCListCellInfo *info;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  clist->drag_button = 0;
+  remove_grab (clist);
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_EXTENDED:
+      update_extended_selection (clist, clist->focus_row);
+      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+      break;
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_MULTIPLE:
+      clist->anchor = -1;
+    case GTK_SELECTION_BROWSE:
+      break;
+    }
+
+  info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+  if (!info)
+    {
+      info = g_new (GtkCListCellInfo, 1);
+
+      if (clist->click_cell.row < 0)
+       clist->click_cell.row = 0;
+      else if (clist->click_cell.row >= clist->rows)
+       clist->click_cell.row = clist->rows - 1;
+      info->row = clist->click_cell.row;
+      info->column = clist->click_cell.column;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
+                              drag_source_info_destroy);
+    }
+
+  if (GTK_CLIST_USE_DRAG_ICONS (clist))
+    gtk_drag_set_icon_default (context);
+}
+
+static void
+gtk_clist_drag_end (GtkWidget     *widget,
+                   GdkDragContext *context)
+{
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  clist->click_cell.row = -1;
+  clist->click_cell.column = -1;
+}
+
+static void
+gtk_clist_drag_leave (GtkWidget      *widget,
+                     GdkDragContext *context,
+                     guint           time)
+{
+  GtkCList *clist;
+  GtkCListDestInfo *dest_info;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+  
+  if (dest_info)
+    {
+      if (dest_info->cell.row >= 0 &&
+         GTK_CLIST_REORDERABLE(clist) &&
+         gtk_drag_get_source_widget (context) == widget)
+       {
+         GList *list;
+         GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+         list = context->targets;
+         while (list)
+           {
+             if (atom == GPOINTER_TO_INT (list->data))
+               {
+                 GTK_CLIST_CLASS_FW (clist)->draw_drag_highlight
+                   (clist,
+                    g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                    dest_info->cell.row, dest_info->insert_pos);
+                 break;
+               }
+             list = list->next;
+           }
+       }
+      g_dataset_remove_data (context, "gtk-clist-drag-dest");
+    }
+}
+
+static gint
+gtk_clist_drag_motion (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      gint            x,
+                      gint            y,
+                      guint           time)
+{
+  GtkCList *clist;
+  GtkCListDestInfo new_info;
+  GtkCListDestInfo *dest_info;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+
+  clist = GTK_CLIST (widget);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+  if (!dest_info)
+    {
+      dest_info = g_new (GtkCListDestInfo, 1);
+
+      dest_info->insert_pos  = GTK_CLIST_DRAG_NONE;
+      dest_info->cell.row    = -1;
+      dest_info->cell.column = -1;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
+                              drag_dest_info_destroy);
+    }
+
+  drag_dest_cell (clist, x, y, &new_info);
+
+  if (GTK_CLIST_REORDERABLE (clist))
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GPOINTER_TO_INT (list->data))
+           break;
+         list = list->next;
+       }
+
+      if (list)
+       {
+         if (gtk_drag_get_source_widget (context) != widget ||
+             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)
+               {
+                 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
+                 return FALSE;
+               }
+             return TRUE;
+           }
+               
+         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
+                 (clist, g_list_nth (clist->row_list,
+                                     dest_info->cell.row)->data,
+                  dest_info->cell.row, dest_info->insert_pos);
+
+             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,
+                                   dest_info->cell.row)->data,
+                dest_info->cell.row, dest_info->insert_pos);
+
+             gdk_drag_status (context, context->suggested_action, time);
+           }
+         return TRUE;
+       }
+    }
+
+  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;
+}
+
+static gboolean
+gtk_clist_drag_drop (GtkWidget      *widget,
+                    GdkDragContext *context,
+                    gint            x,
+                    gint            y,
+                    guint           time)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (GTK_CLIST_REORDERABLE (widget) &&
+      gtk_drag_get_source_widget (context) == widget)
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern ("gtk-clist-drag-reorder", FALSE);
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GPOINTER_TO_INT (list->data))
+           return TRUE;
+         list = list->next;
+       }
+    }
+  return FALSE;
+}
+
+static void
+gtk_clist_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x,
+                             gint              y,
+                             GtkSelectionData *selection_data,
+                             guint             info,
+                             guint             time)
+{
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  clist = GTK_CLIST (widget);
+
+  if (GTK_CLIST_REORDERABLE (clist) &&
+      gtk_drag_get_source_widget (context) == widget &&
+      selection_data->target ==
+      gdk_atom_intern ("gtk-clist-drag-reorder", FALSE) &&
+      selection_data->format == GTK_TYPE_POINTER &&
+      selection_data->length == sizeof (GtkCListCellInfo))
+    {
+      GtkCListCellInfo *source_info;
+
+      source_info = (GtkCListCellInfo *)(selection_data->data);
+      if (source_info)
+       {
+         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");
+       }
+    }
+}
+
+static void  
+gtk_clist_drag_data_get (GtkWidget        *widget,
+                        GdkDragContext   *context,
+                        GtkSelectionData *selection_data,
+                        guint             info,
+                        guint             time)
+{
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  if (selection_data->target ==
+      gdk_atom_intern ("gtk-clist-drag-reorder", FALSE))
+    {
+      GtkCListCellInfo *info;
+
+      info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+      if (info)
+       {
+         GtkCListCellInfo ret_info;
+
+         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,
+                                 sizeof (GtkCListCellInfo));
+       }
+      else
+       gtk_selection_data_set (selection_data, selection_data->target,
+                               GTK_TYPE_POINTER, NULL, 0);
+    }
+}
+
+static void
+draw_drag_highlight (GtkCList        *clist,
+                    GtkCListRow     *dest_row,
+                    gint             dest_row_number,
+                    GtkCListDragPos  drag_pos)
+{
+  gint y;
+
+  y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+  switch (drag_pos)
+    {
+    case GTK_CLIST_DRAG_NONE:
+      break;
+    case GTK_CLIST_DRAG_AFTER:
+      y += clist->row_height + 1;
+    case GTK_CLIST_DRAG_BEFORE:
+      gdk_draw_line (clist->clist_window, clist->xor_gc,
+                    0, y, clist->clist_window_width, y);
+      break;
+    case GTK_CLIST_DRAG_INTO:
+      gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+                         clist->clist_window_width - 1, clist->row_height);
+      break;
+    }
+}
+
+void
+gtk_clist_set_reorderable (GtkCList *clist, 
+                          gboolean  reorderable)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
+    return;
+
+  widget = GTK_WIDGET (clist);
+
+  if (reorderable)
+    {
+      GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
+      gtk_drag_dest_set (widget,
+                        GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+                        &clist_target_table, 1, GDK_ACTION_MOVE);
+    }
+  else
+    {
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
+      gtk_drag_dest_unset (GTK_WIDGET (clist));
+    }
+}
+
+void
+gtk_clist_set_use_drag_icons (GtkCList *clist,
+                             gboolean  use_icons)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (use_icons != 0)
+    GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
+  else
+    GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
+}
+
+void
+gtk_clist_set_button_actions (GtkCList *clist,
+                             guint     button,
+                             guint8    button_actions)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  
+  if (button < MAX_BUTTON)
+    {
+      if (gdk_pointer_is_grabbed () || GTK_WIDGET_HAS_GRAB (clist))
+       {
+         remove_grab (clist);
+         clist->drag_button = 0;
+       }
+
+      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+
+      clist->button_actions[button] = button_actions;
+    }
+}