]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtklist.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~andy/gtk] / gtk / gtklist.c
index ce004f3e8e7c565a8a292c5842ac6a4be5d28d23..9b9f4f08a3d66809969b0991cfda5f388234dfcf 100644 (file)
@@ -2,26 +2,43 @@
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  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 "config.h"
+#include <string.h> /* memset */
+
+#undef GTK_DISABLE_DEPRECATED
+#define __GTK_LIST_C__
+
 #include "gtklist.h"
 #include "gtklistitem.h"
 #include "gtkmain.h"
-#include "gtkprivate.h"
 #include "gtksignal.h"
 #include "gtklabel.h"
+#include "gtkmarshalers.h"
+#include "gtkintl.h"
+
+#include "gtkalias.h"
 
 enum {
   SELECTION_CHANGED,
@@ -30,29 +47,34 @@ enum {
   LAST_SIGNAL
 };
 
+enum {
+  ARG_0,
+  ARG_SELECTION_MODE
+};
+
 #define SCROLL_TIME  100
 
-/** GtkList Methods **/
+/*** GtkList Methods ***/
 static void gtk_list_class_init             (GtkListClass   *klass);
 static void gtk_list_init           (GtkList        *list);
-
-/** GtkObject Methods **/
-static void gtk_list_shutdown       (GtkObject      *object);
-
-/** GtkWidget Methods **/
+static void gtk_list_set_arg         (GtkObject      *object,
+                                     GtkArg         *arg,
+                                     guint           arg_id);
+static void gtk_list_get_arg         (GtkObject      *object,
+                                     GtkArg         *arg,
+                                     guint           arg_id);
+/*** GtkObject Methods ***/
+static void gtk_list_dispose        (GObject        *object);
+
+/*** GtkWidget Methods ***/
 static void gtk_list_size_request    (GtkWidget             *widget,
                                      GtkRequisition *requisition);
 static void gtk_list_size_allocate   (GtkWidget             *widget,
                                      GtkAllocation  *allocation);
 static void gtk_list_realize        (GtkWidget      *widget);
-static void gtk_list_map            (GtkWidget      *widget);
 static void gtk_list_unmap          (GtkWidget      *widget);
 static void gtk_list_style_set      (GtkWidget      *widget,
                                      GtkStyle       *previous_style);
-static void gtk_list_draw           (GtkWidget      *widget,
-                                     GdkRectangle   *area);
-static gint gtk_list_expose         (GtkWidget      *widget,
-                                     GdkEventExpose *event);
 static gint gtk_list_motion_notify   (GtkWidget      *widget,
                                      GdkEventMotion *event);
 static gint gtk_list_button_press    (GtkWidget      *widget,
@@ -60,7 +82,10 @@ static gint gtk_list_button_press    (GtkWidget      *widget,
 static gint gtk_list_button_release  (GtkWidget             *widget,
                                      GdkEventButton *event);
 
-/** GtkContainer Methods **/
+static gboolean gtk_list_focus       (GtkWidget        *widget,
+                                      GtkDirectionType  direction);
+
+/*** GtkContainer Methods ***/
 static void gtk_list_add            (GtkContainer     *container,
                                      GtkWidget        *widget);
 static void gtk_list_remove         (GtkContainer     *container,
@@ -72,10 +97,8 @@ static void gtk_list_forall       (GtkContainer     *container,
 static GtkType gtk_list_child_type   (GtkContainer     *container);
 static void gtk_list_set_focus_child (GtkContainer     *container,
                                      GtkWidget        *widget);
-static gint gtk_list_focus           (GtkContainer     *container,
-                                     GtkDirectionType  direction);
 
-/** GtkList Private Functions **/
+/*** GtkList Private Functions ***/
 static void gtk_list_move_focus_child      (GtkList       *list,
                                            GtkScrollType  scroll_type,
                                            gfloat         position);
@@ -85,13 +108,13 @@ static void gtk_list_remove_items_internal (GtkList       *list,
                                            GList         *items,
                                            gboolean       no_unref);
 
-/** GtkList Selection Methods **/
+/*** GtkList Selection Methods ***/
 static void gtk_real_list_select_child         (GtkList   *list,
                                                 GtkWidget *child);
 static void gtk_real_list_unselect_child        (GtkList   *list,
                                                 GtkWidget *child);
 
-/** GtkList Selection Functions **/
+/*** GtkList Selection Functions ***/
 static void gtk_list_set_anchor                 (GtkList   *list,
                                                 gboolean   add_mode,
                                                 gint       anchor,
@@ -102,11 +125,12 @@ static void gtk_list_fake_toggle_row            (GtkList   *list,
                                                 GtkWidget *item);
 static void gtk_list_update_extended_selection  (GtkList   *list,
                                                 gint       row);
+static void gtk_list_reset_extended_selection   (GtkList   *list);
 
-/** GtkListItem Signal Functions **/
-static void gtk_list_signal_focus_lost         (GtkWidget     *item,
-                                               GdkEventKey   *event,
-                                               GtkList       *list);
+/*** GtkListItem Signal Functions ***/
+static void gtk_list_signal_drag_begin         (GtkWidget      *widget,
+                                               GdkDragContext *context,
+                                               GtkList        *list);
 static void gtk_list_signal_toggle_focus_row   (GtkListItem   *list_item,
                                                GtkList       *list);
 static void gtk_list_signal_select_all         (GtkListItem   *list_item,
@@ -142,12 +166,16 @@ static void gtk_list_signal_item_toggle        (GtkListItem   *list_item,
                                                GtkList       *list);
 
 
+static void gtk_list_drag_begin (GtkWidget      *widget,
+                                GdkDragContext *context);
+
+
 static GtkContainerClass *parent_class = NULL;
 static guint list_signals[LAST_SIGNAL] = { 0 };
 
-static const gchar *vadjustment_key = "gtk-vadjustment";
+static const gchar vadjustment_key[] = "gtk-vadjustment";
 static guint        vadjustment_key_id = 0;
-static const gchar *hadjustment_key = "gtk-hadjustment";
+static const gchar hadjustment_key[] = "gtk-hadjustment";
 static guint        hadjustment_key_id = 0;
 
 GtkType
@@ -169,6 +197,7 @@ gtk_list_get_type (void)
         (GtkClassInitFunc) NULL,
       };
 
+      I_("GtkList");
       list_type = gtk_type_unique (GTK_TYPE_CONTAINER, &list_info);
     }
 
@@ -178,6 +207,7 @@ gtk_list_get_type (void)
 static void
 gtk_list_class_init (GtkListClass *class)
 {
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
   GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
@@ -191,56 +221,61 @@ gtk_list_class_init (GtkListClass *class)
   vadjustment_key_id = g_quark_from_static_string (vadjustment_key);
   hadjustment_key_id = g_quark_from_static_string (hadjustment_key);
 
-  list_signals[SELECTION_CHANGED] =
-    gtk_signal_new ("selection_changed",
-                   GTK_RUN_FIRST,
-                   object_class->type,
-                   GTK_SIGNAL_OFFSET (GtkListClass, selection_changed),
-                   gtk_marshal_NONE__NONE,
-                   GTK_TYPE_NONE, 0);
-  list_signals[SELECT_CHILD] =
-    gtk_signal_new ("select_child",
-                   GTK_RUN_FIRST,
-                   object_class->type,
-                   GTK_SIGNAL_OFFSET (GtkListClass, select_child),
-                   gtk_marshal_NONE__POINTER,
-                   GTK_TYPE_NONE, 1,
-                   GTK_TYPE_WIDGET);
-  list_signals[UNSELECT_CHILD] =
-    gtk_signal_new ("unselect_child",
-                   GTK_RUN_FIRST,
-                   object_class->type,
-                   GTK_SIGNAL_OFFSET (GtkListClass, unselect_child),
-                   gtk_marshal_NONE__POINTER,
-                   GTK_TYPE_NONE, 1,
-                   GTK_TYPE_WIDGET);
+  gobject_class->dispose = gtk_list_dispose;
 
-  gtk_object_class_add_signals (object_class, list_signals, LAST_SIGNAL);
 
-  object_class->shutdown = gtk_list_shutdown;
+  object_class->set_arg = gtk_list_set_arg;
+  object_class->get_arg = gtk_list_get_arg;
 
-  widget_class->map = gtk_list_map;
   widget_class->unmap = gtk_list_unmap;
   widget_class->style_set = gtk_list_style_set;
   widget_class->realize = gtk_list_realize;
-  widget_class->draw = gtk_list_draw;
-  widget_class->expose_event = gtk_list_expose;
   widget_class->button_press_event = gtk_list_button_press;
   widget_class->button_release_event = gtk_list_button_release;
   widget_class->motion_notify_event = gtk_list_motion_notify;
   widget_class->size_request = gtk_list_size_request;
   widget_class->size_allocate = gtk_list_size_allocate;
-
+  widget_class->drag_begin = gtk_list_drag_begin;
+  widget_class->focus = gtk_list_focus;
+  
   container_class->add = gtk_list_add;
   container_class->remove = gtk_list_remove;
   container_class->forall = gtk_list_forall;
   container_class->child_type = gtk_list_child_type;
   container_class->set_focus_child = gtk_list_set_focus_child;
-  container_class->focus = gtk_list_focus;
 
   class->selection_changed = NULL;
   class->select_child = gtk_real_list_select_child;
   class->unselect_child = gtk_real_list_unselect_child;
+
+  list_signals[SELECTION_CHANGED] =
+    gtk_signal_new (I_("selection-changed"),
+                   GTK_RUN_FIRST,
+                   GTK_CLASS_TYPE (object_class),
+                   GTK_SIGNAL_OFFSET (GtkListClass, selection_changed),
+                   _gtk_marshal_VOID__VOID,
+                   GTK_TYPE_NONE, 0);
+  list_signals[SELECT_CHILD] =
+    gtk_signal_new (I_("select-child"),
+                   GTK_RUN_FIRST,
+                   GTK_CLASS_TYPE (object_class),
+                   GTK_SIGNAL_OFFSET (GtkListClass, select_child),
+                   _gtk_marshal_VOID__OBJECT,
+                   GTK_TYPE_NONE, 1,
+                   GTK_TYPE_WIDGET);
+  list_signals[UNSELECT_CHILD] =
+    gtk_signal_new (I_("unselect-child"),
+                   GTK_RUN_FIRST,
+                   GTK_CLASS_TYPE (object_class),
+                   GTK_SIGNAL_OFFSET (GtkListClass, unselect_child),
+                   _gtk_marshal_VOID__OBJECT,
+                   GTK_TYPE_NONE, 1,
+                   GTK_TYPE_WIDGET);
+  
+  gtk_object_add_arg_type ("GtkList::selection-mode",
+                          GTK_TYPE_SELECTION_MODE, 
+                          GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
+                          ARG_SELECTION_MODE);
 }
 
 static void
@@ -267,6 +302,39 @@ gtk_list_init (GtkList *list)
   list->add_mode = FALSE;
 }
 
+static void
+gtk_list_set_arg (GtkObject      *object,
+                 GtkArg         *arg,
+                 guint           arg_id)
+{
+  GtkList *list = GTK_LIST (object);
+  
+  switch (arg_id)
+    {
+    case ARG_SELECTION_MODE:
+      gtk_list_set_selection_mode (list, GTK_VALUE_ENUM (*arg));
+      break;
+    }
+}
+
+static void
+gtk_list_get_arg (GtkObject      *object,
+                 GtkArg         *arg,
+                 guint           arg_id)
+{
+  GtkList *list = GTK_LIST (object);
+  
+  switch (arg_id)
+    {
+    case ARG_SELECTION_MODE: 
+      GTK_VALUE_ENUM (*arg) = list->selection_mode; 
+      break;
+    default:
+      arg->type = GTK_TYPE_INVALID;
+      break;
+    }
+}
+
 GtkWidget*
 gtk_list_new (void)
 {
@@ -276,13 +344,14 @@ gtk_list_new (void)
 
 /* Private GtkObject Methods :
  * 
- * gtk_list_shutdown
+ * gtk_list_dispose
  */
 static void
-gtk_list_shutdown (GtkObject *object)
+gtk_list_dispose (GObject *object)
 {
   gtk_list_clear_items (GTK_LIST (object), 0, -1);
-  GTK_OBJECT_CLASS (parent_class)->shutdown (object);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 
@@ -291,7 +360,6 @@ gtk_list_shutdown (GtkObject *object)
  * gtk_list_size_request
  * gtk_list_size_allocate
  * gtk_list_realize
- * gtk_list_map
  * gtk_list_unmap
  * gtk_list_motion_notify
  * gtk_list_button_press
@@ -301,15 +369,10 @@ static void
 gtk_list_size_request (GtkWidget      *widget,
                       GtkRequisition *requisition)
 {
-  GtkList *list;
+  GtkList *list = GTK_LIST (widget);
   GtkWidget *child;
   GList *children;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_LIST (widget));
-  g_return_if_fail (requisition != NULL);
-
-  list = GTK_LIST (widget);
   requisition->width = 0;
   requisition->height = 0;
 
@@ -319,13 +382,15 @@ gtk_list_size_request (GtkWidget      *widget,
       child = children->data;
       children = children->next;
 
-      if (GTK_WIDGET_VISIBLE (child))
+      if (gtk_widget_get_visible (child))
        {
-         gtk_widget_size_request (child, &child->requisition);
+         GtkRequisition child_requisition;
+         
+         gtk_widget_size_request (child, &child_requisition);
 
          requisition->width = MAX (requisition->width,
-                                   child->requisition.width);
-         requisition->height += child->requisition.height;
+                                   child_requisition.width);
+         requisition->height += child_requisition.height;
        }
     }
 
@@ -340,17 +405,11 @@ static void
 gtk_list_size_allocate (GtkWidget     *widget,
                        GtkAllocation *allocation)
 {
-  GtkList *list;
+  GtkList *list = GTK_LIST (widget);
   GtkWidget *child;
   GtkAllocation child_allocation;
   GList *children;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_LIST (widget));
-  g_return_if_fail (allocation != NULL);
-
-  list = GTK_LIST (widget);
-
   widget->allocation = *allocation;
   if (GTK_WIDGET_REALIZED (widget))
     gdk_window_move_resize (widget->window,
@@ -361,7 +420,7 @@ gtk_list_size_allocate (GtkWidget     *widget,
     {
       child_allocation.x = GTK_CONTAINER (list)->border_width;
       child_allocation.y = GTK_CONTAINER (list)->border_width;
-      child_allocation.width = MAX (1, allocation->width -
+      child_allocation.width = MAX (1, (gint)allocation->width -
                                    child_allocation.x * 2);
 
       children = list->children;
@@ -371,9 +430,12 @@ gtk_list_size_allocate (GtkWidget     *widget,
          child = children->data;
          children = children->next;
 
-         if (GTK_WIDGET_VISIBLE (child))
+         if (gtk_widget_get_visible (child))
            {
-             child_allocation.height = child->requisition.height;
+             GtkRequisition child_requisition;
+             gtk_widget_get_child_requisition (child, &child_requisition);
+             
+             child_allocation.height = child_requisition.height;
 
              gtk_widget_size_allocate (child, &child_allocation);
 
@@ -389,9 +451,6 @@ gtk_list_realize (GtkWidget *widget)
   GdkWindowAttr attributes;
   gint attributes_mask;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_LIST (widget));
-
   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
   attributes.window_type = GDK_WINDOW_CHILD;
@@ -415,40 +474,32 @@ gtk_list_realize (GtkWidget *widget)
                             &widget->style->base[GTK_STATE_NORMAL]);
 }
 
-static void
-gtk_list_map (GtkWidget *widget)
+static gboolean
+list_has_grab (GtkList *list)
 {
-  GtkList *list;
-  GtkWidget *child;
-  GList *children;
+  return (GTK_WIDGET_HAS_GRAB (list) &&
+         gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (list))));
+         
+}
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_LIST (widget));
+static void
+gtk_list_unmap (GtkWidget *widget)
+{
+  GtkList *list = GTK_LIST (widget);
 
-  GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
-  list = GTK_LIST (widget);
+  if (!GTK_WIDGET_MAPPED (widget))
+    return;
 
-  gdk_window_show (widget->window);
+  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
-  children = list->children;
-  while (children)
+  if (list_has_grab (list))
     {
-      child = children->data;
-      children = children->next;
+      gtk_list_end_drag_selection (list);
 
-      if (GTK_WIDGET_VISIBLE (child) &&
-         !GTK_WIDGET_MAPPED (child))
-       gtk_widget_map (child);
+      if (list->anchor != -1 && list->selection_mode == GTK_SELECTION_MULTIPLE)
+       gtk_list_end_selection (list);
     }
-}
-
-static void
-gtk_list_unmap (GtkWidget *widget)
-{
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_LIST (widget));
 
-  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
   gdk_window_hide (widget->window);
 }
 
@@ -456,7 +507,7 @@ static gint
 gtk_list_motion_notify (GtkWidget      *widget,
                        GdkEventMotion *event)
 {
-  GtkList *list;
+  GtkList *list = GTK_LIST (widget);
   GtkWidget *item = NULL;
   GtkAdjustment *adj;
   GtkContainer *container;
@@ -467,12 +518,6 @@ gtk_list_motion_notify (GtkWidget      *widget,
   gint focus_row = 0;
   gint length = 0;
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  list = GTK_LIST (widget);
-
   if (!list->drag_selection || !list->children)
     return FALSE;
 
@@ -480,6 +525,11 @@ gtk_list_motion_notify (GtkWidget      *widget,
 
   if (event->is_hint || event->window != widget->window)
     gdk_window_get_pointer (widget->window, &x, &y, NULL);
+  else
+    {
+      x = event->x;
+      y = event->y;
+    }
 
   adj = gtk_object_get_data_by_id (GTK_OBJECT (list), hadjustment_key_id);
 
@@ -489,14 +539,14 @@ gtk_list_motion_notify (GtkWidget      *widget,
     {
       if (list->htimer == 0)
        {
-         list->htimer = gtk_timeout_add
-           (SCROLL_TIME, (GtkFunction) gtk_list_horizontal_timeout, widget);
+         list->htimer = gdk_threads_add_timeout
+           (SCROLL_TIME, (GSourceFunc) gtk_list_horizontal_timeout, widget);
          
          if (!((x < adj->value && adj->value <= 0) ||
                (x > adj->value + adj->page_size &&
                 adj->value >= adj->upper - adj->page_size)))
            {
-             gfloat value;
+             gdouble value;
 
              if (x < adj->value)
                value = adj->value + (x - adj->value) / 2 - 1;
@@ -537,23 +587,21 @@ gtk_list_motion_notify (GtkWidget      *widget,
 
   if (!((y < 0 && focus_row == 0) ||
        (y > widget->allocation.height && focus_row >= length - 1)))
-    list->vtimer = gtk_timeout_add (SCROLL_TIME,
-                                   (GtkFunction) gtk_list_vertical_timeout,
-                                   list);
+    list->vtimer = gdk_threads_add_timeout (SCROLL_TIME,
+                                 (GSourceFunc) gtk_list_vertical_timeout,
+                                 list);
 
   if (row != focus_row)
     gtk_widget_grab_focus (item);
-         
+
   switch (list->selection_mode)
     {
     case GTK_SELECTION_BROWSE:
       gtk_list_select_child (list, item);
       break;
-      
-    case GTK_SELECTION_EXTENDED:
+    case GTK_SELECTION_MULTIPLE:
       gtk_list_update_extended_selection (list, row);
       break;
-
     default:
       break;
     }
@@ -565,17 +613,12 @@ static gint
 gtk_list_button_press (GtkWidget      *widget,
                       GdkEventButton *event)
 {
-  GtkList *list;
+  GtkList *list = GTK_LIST (widget);
   GtkWidget *item;
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
   if (event->button != 1)
     return FALSE;
 
-  list = GTK_LIST (widget);
   item = gtk_get_event_widget ((GdkEvent*) event);
 
   while (item && !GTK_IS_LIST_ITEM (item))
@@ -588,18 +631,13 @@ gtk_list_button_press (GtkWidget      *widget,
 
       if (event->type == GDK_BUTTON_PRESS)
        {
-         list->drag_selection = TRUE;
-         gdk_pointer_grab (widget->window, TRUE,
-                           GDK_POINTER_MOTION_HINT_MASK |
-                           GDK_BUTTON1_MOTION_MASK |
-                           GDK_BUTTON_RELEASE_MASK,
-                           NULL, NULL, event->time);
          gtk_grab_add (widget);
+         list->drag_selection = TRUE;
        }
-      else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
+      else if (list_has_grab (list))
        gtk_list_end_drag_selection (list);
          
-      if (!GTK_WIDGET_HAS_FOCUS(item))
+      if (!gtk_widget_has_focus(item))
        gtk_widget_grab_focus (item);
 
       if (list->add_mode)
@@ -611,7 +649,6 @@ gtk_list_button_press (GtkWidget      *widget,
       switch (list->selection_mode)
        {
        case GTK_SELECTION_SINGLE:
-       case GTK_SELECTION_MULTIPLE:
          if (event->type != GDK_BUTTON_PRESS)
            gtk_list_select_child (list, item);
          else
@@ -621,7 +658,7 @@ gtk_list_button_press (GtkWidget      *widget,
        case GTK_SELECTION_BROWSE:
          break;
 
-       case GTK_SELECTION_EXTENDED:
+       case GTK_SELECTION_MULTIPLE:
          focus_row = g_list_index (list->children, item);
 
          if (list->last_focus_child)
@@ -690,6 +727,8 @@ gtk_list_button_press (GtkWidget      *widget,
        default:
          break;
        }
+
+      return TRUE;
     }
 
   return FALSE;
@@ -699,15 +738,9 @@ static gint
 gtk_list_button_release (GtkWidget     *widget,
                         GdkEventButton *event)
 {
-  GtkList *list;
+  GtkList *list = GTK_LIST (widget);
   GtkWidget *item;
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  list = GTK_LIST (widget);
-
   /* we don't handle button 2 and 3 */
   if (event->button != 1)
     return FALSE;
@@ -718,13 +751,12 @@ gtk_list_button_release (GtkWidget        *widget,
 
       switch (list->selection_mode)
        {
-       case GTK_SELECTION_EXTENDED:
+       case GTK_SELECTION_MULTIPLE:
          if (!(event->state & GDK_SHIFT_MASK))
            gtk_list_end_selection (list);
          break;
 
        case GTK_SELECTION_SINGLE:
-       case GTK_SELECTION_MULTIPLE:
 
          item = gtk_get_event_widget ((GdkEvent*) event);
   
@@ -742,71 +774,10 @@ gtk_list_button_release (GtkWidget        *widget,
        default:
          break;
        }
-    }
-  
-  return FALSE;
-}
 
-static void
-gtk_list_draw (GtkWidget    *widget,
-              GdkRectangle *area)
-{
-  GtkList *list;
-  GtkWidget *child;
-  GdkRectangle child_area;
-  GList *children;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_LIST (widget));
-  g_return_if_fail (area != NULL);
-
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      list = GTK_LIST (widget);
-
-      children = list->children;
-      while (children)
-       {
-         child = children->data;
-         children = children->next;
-
-         if (gtk_widget_intersect (child, area, &child_area))
-           gtk_widget_draw (child, &child_area);
-       }
+      return TRUE;
     }
-}
-
-static gint
-gtk_list_expose (GtkWidget     *widget,
-                GdkEventExpose *event)
-{
-  GtkList *list;
-  GtkWidget *child;
-  GdkEventExpose child_event;
-  GList *children;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_LIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      list = GTK_LIST (widget);
-
-      child_event = *event;
-
-      children = list->children;
-      while (children)
-       {
-         child = children->data;
-         children = children->next;
-
-         if (GTK_WIDGET_NO_WINDOW (child) &&
-             gtk_widget_intersect (child, &event->area, &child_event.area))
-           gtk_widget_event (child, (GdkEvent*) &child_event);
-       }
-    }
-
+  
   return FALSE;
 }
 
@@ -814,8 +785,6 @@ static void
 gtk_list_style_set     (GtkWidget      *widget,
                         GtkStyle       *previous_style)
 {
-  g_return_if_fail (widget != NULL);
-
   if (previous_style && GTK_WIDGET_REALIZED (widget))
     gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
 }
@@ -834,9 +803,6 @@ gtk_list_add (GtkContainer *container,
 {
   GList *item_list;
 
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_LIST (container));
-  g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_LIST_ITEM (widget));
 
   item_list = g_list_alloc ();
@@ -850,10 +816,7 @@ gtk_list_remove (GtkContainer *container,
                 GtkWidget    *widget)
 {
   GList *item_list;
-  
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_LIST (container));
-  g_return_if_fail (widget != NULL);
+
   g_return_if_fail (container == GTK_CONTAINER (widget->parent));
   
   item_list = g_list_alloc ();
@@ -870,15 +833,10 @@ gtk_list_forall (GtkContainer  *container,
                 GtkCallback    callback,
                 gpointer       callback_data)
 {
-  GtkList *list;
+  GtkList *list = GTK_LIST (container);
   GtkWidget *child;
   GList *children;
 
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_LIST (container));
-  g_return_if_fail (callback != NULL);
-
-  list = GTK_LIST (container);
   children = list->children;
 
   while (children)
@@ -902,22 +860,23 @@ gtk_list_set_focus_child (GtkContainer *container,
 {
   GtkList *list;
 
-  g_return_if_fail (container != NULL);
   g_return_if_fail (GTK_IS_LIST (container));
-
   if (child)
     g_return_if_fail (GTK_IS_WIDGET (child));
 
   list = GTK_LIST (container);
-  list->last_focus_child = container->focus_child;
 
   if (child != container->focus_child)
     {
       if (container->focus_child)
-        gtk_widget_unref (container->focus_child);
+       {
+         list->last_focus_child = container->focus_child;
+         g_object_unref (container->focus_child);
+       }
       container->focus_child = child;
       if (container->focus_child)
-        gtk_widget_ref (container->focus_child);
+        g_object_ref (container->focus_child);
     }
 
   /* check for v adjustment */
@@ -932,45 +891,56 @@ gtk_list_set_focus_child (GtkContainer *container,
                                    container->focus_child->allocation.y,
                                    (container->focus_child->allocation.y +
                                     container->focus_child->allocation.height));
-    }
-
-  switch (list->selection_mode)
-    {
-    case GTK_SELECTION_BROWSE:
-      if (child)
-       gtk_list_select_child (list, child);
-      break;
-    default:
-      break;
+      switch (list->selection_mode)
+       {
+       case GTK_SELECTION_BROWSE:
+         gtk_list_select_child (list, child);
+         break;
+       case GTK_SELECTION_MULTIPLE:
+         if (!list->last_focus_child && !list->add_mode)
+           {
+             list->undo_focus_child = list->last_focus_child;
+             gtk_list_unselect_all (list);
+             gtk_list_select_child (list, child);
+           }
+         break;
+       default:
+         break;
+       }
     }
 }
 
-static gint
-gtk_list_focus (GtkContainer     *container,
+static gboolean
+gtk_list_focus (GtkWidget        *widget,
                GtkDirectionType  direction)
 {
   gint return_val = FALSE;
+  GtkContainer *container;
 
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_LIST (container), FALSE);
-
-  if (!GTK_WIDGET_SENSITIVE (container))
-    return_val = FALSE;
-  else if (container->focus_child == NULL ||
-      !GTK_WIDGET_HAS_FOCUS (container->focus_child))
+  container = GTK_CONTAINER (widget);
+  
+  if (container->focus_child == NULL ||
+      !gtk_widget_has_focus (container->focus_child))
     {
-      if (GTK_CONTAINER_CLASS (parent_class)->focus)
-       return_val = GTK_CONTAINER_CLASS (parent_class)->focus
-         (container, direction);
+      if (GTK_LIST (container)->last_focus_child)
+       gtk_container_set_focus_child
+         (container, GTK_LIST (container)->last_focus_child);
+
+      if (GTK_WIDGET_CLASS (parent_class)->focus)
+       return_val = GTK_WIDGET_CLASS (parent_class)->focus (widget,
+                                                             direction);
     }
-  
+
   if (!return_val)
     {
       GtkList *list;
 
       list =  GTK_LIST (container);
-      if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
+      if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
        gtk_list_end_selection (list);
+
+      if (container->focus_child)
+       list->last_focus_child = container->focus_child;
     }
 
   return return_val;
@@ -998,14 +968,13 @@ gtk_list_insert_items (GtkList *list,
   GList *last;
   gint nchildren;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (!items)
     return;
 
   gtk_list_end_drag_selection (list);
-  if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
+  if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
     gtk_list_end_selection (list);
 
   tmp_list = items;
@@ -1015,61 +984,51 @@ gtk_list_insert_items (GtkList *list,
       tmp_list = tmp_list->next;
 
       gtk_widget_set_parent (widget, GTK_WIDGET (list));
-      gtk_signal_connect (GTK_OBJECT (widget), "focus_out_event",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_focus_lost),
+      gtk_signal_connect (GTK_OBJECT (widget), "drag-begin",
+                         G_CALLBACK (gtk_list_signal_drag_begin),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "toggle_focus_row",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_toggle_focus_row),
+      gtk_signal_connect (GTK_OBJECT (widget), "toggle-focus-row",
+                         G_CALLBACK (gtk_list_signal_toggle_focus_row),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "select_all",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_select_all),
+      gtk_signal_connect (GTK_OBJECT (widget), "select-all",
+                         G_CALLBACK (gtk_list_signal_select_all),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "unselect_all",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_unselect_all),
+      gtk_signal_connect (GTK_OBJECT (widget), "unselect-all",
+                         G_CALLBACK (gtk_list_signal_unselect_all),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "undo_selection",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_undo_selection),
+      gtk_signal_connect (GTK_OBJECT (widget), "undo-selection",
+                         G_CALLBACK (gtk_list_signal_undo_selection),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "start_selection",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_start_selection),
+      gtk_signal_connect (GTK_OBJECT (widget), "start-selection",
+                         G_CALLBACK (gtk_list_signal_start_selection),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "end_selection",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_end_selection),
+      gtk_signal_connect (GTK_OBJECT (widget), "end-selection",
+                         G_CALLBACK (gtk_list_signal_end_selection),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "extend_selection",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_extend_selection),
+      gtk_signal_connect (GTK_OBJECT (widget), "extend-selection",
+                         G_CALLBACK (gtk_list_signal_extend_selection),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "scroll_horizontal",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_scroll_horizontal),
+      gtk_signal_connect (GTK_OBJECT (widget), "scroll-horizontal",
+                         G_CALLBACK (gtk_list_signal_scroll_horizontal),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "scroll_vertical",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_scroll_vertical),
+      gtk_signal_connect (GTK_OBJECT (widget), "scroll-vertical",
+                         G_CALLBACK (gtk_list_signal_scroll_vertical),
                          list);
-      gtk_signal_connect (GTK_OBJECT (widget), "toggle_add_mode",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_toggle_add_mode),
+      gtk_signal_connect (GTK_OBJECT (widget), "toggle-add-mode",
+                         G_CALLBACK (gtk_list_signal_toggle_add_mode),
                          list);
       gtk_signal_connect (GTK_OBJECT (widget), "select",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_item_select),
+                         G_CALLBACK (gtk_list_signal_item_select),
                          list);
       gtk_signal_connect (GTK_OBJECT (widget), "deselect",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_item_deselect),
+                         G_CALLBACK (gtk_list_signal_item_deselect),
                          list);
       gtk_signal_connect (GTK_OBJECT (widget), "toggle",
-                         GTK_SIGNAL_FUNC (gtk_list_signal_item_toggle),
+                         G_CALLBACK (gtk_list_signal_item_toggle),
                          list);
-
-      if (GTK_WIDGET_VISIBLE (widget->parent))
-       {
-         if (GTK_WIDGET_REALIZED (widget->parent) &&
-             !GTK_WIDGET_REALIZED (widget))
-           gtk_widget_realize (widget);
-
-         if (GTK_WIDGET_MAPPED (widget->parent) &&
-             !GTK_WIDGET_MAPPED (widget))
-           gtk_widget_map (widget);
-       }
     }
 
+
   nchildren = g_list_length (list->children);
   if ((position < 0) || (position > nchildren))
     position = nchildren;
@@ -1101,23 +1060,19 @@ gtk_list_insert_items (GtkList *list,
       if (tmp_list == list->children)
        list->children = items;
     }
-
+  
   if (list->children && !list->selection &&
       (list->selection_mode == GTK_SELECTION_BROWSE))
     {
       widget = list->children->data;
       gtk_list_select_child (list, widget);
     }
-
-  if (GTK_WIDGET_VISIBLE (list))
-    gtk_widget_queue_resize (GTK_WIDGET (list));
 }
 
 void
 gtk_list_append_items (GtkList *list,
                       GList   *items)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_insert_items (list, items, -1);
@@ -1127,7 +1082,6 @@ void
 gtk_list_prepend_items (GtkList *list,
                        GList   *items)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_insert_items (list, items, 0);
@@ -1152,74 +1106,106 @@ gtk_list_clear_items (GtkList *list,
                      gint     start,
                      gint     end)
 {
+  GtkContainer *container;
   GtkWidget *widget;
+  GtkWidget *new_focus_child = NULL;
   GList *start_list;
   GList *end_list;
   GList *tmp_list;
   guint nchildren;
+  gboolean grab_focus = FALSE;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   nchildren = g_list_length (list->children);
 
-  if (nchildren > 0)
-    {
-      gboolean selection_changed;
+  if (nchildren == 0)
+    return;
 
-      if ((end < 0) || (end > nchildren))
-       end = nchildren;
+  if ((end < 0) || (end > nchildren))
+    end = nchildren;
 
-      if (start >= end)
-       return;
+  if (start >= end)
+    return;
 
-      start_list = g_list_nth (list->children, start);
-      end_list = g_list_nth (list->children, end);
+  container = GTK_CONTAINER (list);
 
-      gtk_list_end_drag_selection (list);
-      if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
+  gtk_list_end_drag_selection (list);
+  if (list->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      if (list->anchor >= 0)
        gtk_list_end_selection (list);
 
-      if (start_list->prev)
-       start_list->prev->next = end_list;
-      if (end_list && end_list->prev)
-       end_list->prev->next = NULL;
-      if (end_list)
-       end_list->prev = start_list->prev;
-      if (start_list == list->children)
-       list->children = end_list;
+      gtk_list_reset_extended_selection (list);
+    }
 
-      selection_changed = FALSE;
-      widget = NULL;
-      tmp_list = start_list;
+  start_list = g_list_nth (list->children, start);
+  end_list = g_list_nth (list->children, end);
 
-      while (tmp_list)
-       {
-         widget = tmp_list->data;
-         tmp_list = tmp_list->next;
+  if (start_list->prev)
+    start_list->prev->next = end_list;
+  if (end_list && end_list->prev)
+    end_list->prev->next = NULL;
+  if (end_list)
+    end_list->prev = start_list->prev;
+  if (start_list == list->children)
+    list->children = end_list;
 
-         if (widget->state == GTK_STATE_SELECTED)
-           {
-             gtk_list_unselect_child (list, widget);
-             selection_changed = TRUE;
-           }
+  if (container->focus_child)
+    {
+      if (g_list_find (start_list, container->focus_child))
+       {
+         if (start_list->prev)
+           new_focus_child = start_list->prev->data;
+         else if (list->children)
+           new_focus_child = list->children->data;
 
-         gtk_widget_unparent (widget);
+         if (gtk_widget_has_focus (container->focus_child))
+           grab_focus = TRUE;
        }
+    }
 
-      g_list_free (start_list);
+  tmp_list = start_list;
+  while (tmp_list)
+    {
+      widget = tmp_list->data;
+      tmp_list = tmp_list->next;
+
+      g_object_ref (widget);
+
+      if (widget->state == GTK_STATE_SELECTED)
+       gtk_list_unselect_child (list, widget);
+
+      gtk_signal_disconnect_by_data (GTK_OBJECT (widget), (gpointer) list);
+      gtk_widget_unparent (widget);
+      
+      if (widget == list->undo_focus_child)
+       list->undo_focus_child = NULL;
+      if (widget == list->last_focus_child)
+       list->last_focus_child = NULL;
+
+      g_object_unref (widget);
+    }
 
-      if (list->children && !list->selection &&
-         (list->selection_mode == GTK_SELECTION_BROWSE))
+  g_list_free (start_list);
+
+  if (new_focus_child)
+    {
+      if (grab_focus)
+       gtk_widget_grab_focus (new_focus_child);
+      else if (container->focus_child)
+       gtk_container_set_focus_child (container, new_focus_child);
+
+      if ((list->selection_mode == GTK_SELECTION_BROWSE ||
+          list->selection_mode == GTK_SELECTION_MULTIPLE) && !list->selection)
        {
-         widget = list->children->data;
-         gtk_list_select_child (list, widget);
+         list->last_focus_child = new_focus_child; 
+         gtk_list_select_child (list, new_focus_child);
        }
-      else if (selection_changed)
-       gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
-
-      gtk_widget_queue_resize (GTK_WIDGET (list));
     }
+
+  if (gtk_widget_get_visible (GTK_WIDGET (list)))
+    gtk_widget_queue_resize (GTK_WIDGET (list));
 }
 
 gint
@@ -1229,7 +1215,6 @@ gtk_list_child_position (GtkList   *list,
   GList *children;
   gint pos;
 
-  g_return_val_if_fail (list != NULL, -1);
   g_return_val_if_fail (GTK_IS_LIST (list), -1);
   g_return_val_if_fail (child != NULL, -1);
 
@@ -1266,7 +1251,6 @@ gtk_list_remove_items_internal (GtkList    *list,
   GList *work;
   gboolean grab_focus = FALSE;
   
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (!items)
@@ -1275,22 +1259,12 @@ gtk_list_remove_items_internal (GtkList  *list,
   container = GTK_CONTAINER (list);
 
   gtk_list_end_drag_selection (list);
-  if (list->selection_mode == GTK_SELECTION_EXTENDED)
+  if (list->selection_mode == GTK_SELECTION_MULTIPLE)
     {
       if (list->anchor >= 0)
        gtk_list_end_selection (list);
 
-      if (list->undo_selection || list->undo_unselection)
-       {
-         g_list_free (list->undo_selection);
-         g_list_free (list->undo_unselection);
-         list->undo_selection = NULL;
-         list->undo_unselection = NULL;
-
-         list->anchor = -1;
-         list->drag_pos = -1;
-         list->undo_focus_child = container->focus_child;
-       }
+      gtk_list_reset_extended_selection (list);
     }
 
   tmp_list = items;
@@ -1301,20 +1275,26 @@ gtk_list_remove_items_internal (GtkList  *list,
       
       if (widget->state == GTK_STATE_SELECTED)
        gtk_list_unselect_child (list, widget);
+    }
 
+  if (container->focus_child)
+    {
+      old_focus_child = new_focus_child = container->focus_child;
+      if (gtk_widget_has_focus (container->focus_child))
+       grab_focus = TRUE;
     }
+  else
+    old_focus_child = new_focus_child = list->last_focus_child;
 
   tmp_list = items;
-  old_focus_child = new_focus_child = container->focus_child;
-
   while (tmp_list)
     {
       widget = tmp_list->data;
       tmp_list = tmp_list->next;
-      
+
+      g_object_ref (widget);
       if (no_unref)
-       gtk_widget_ref (widget);
-      
+       g_object_ref (widget);
 
       if (widget == new_focus_child) 
        {
@@ -1328,26 +1308,36 @@ gtk_list_remove_items_internal (GtkList  *list,
                new_focus_child = work->prev->data;
              else
                new_focus_child = NULL;
-             
-             if (GTK_WIDGET_HAS_FOCUS (widget))
-               grab_focus = TRUE;
            }
        }
 
       gtk_signal_disconnect_by_data (GTK_OBJECT (widget), (gpointer) list);
       list->children = g_list_remove (list->children, widget);
       gtk_widget_unparent (widget);
+
+      if (widget == list->undo_focus_child)
+       list->undo_focus_child = NULL;
+      if (widget == list->last_focus_child)
+       list->last_focus_child = NULL;
+
+      g_object_unref (widget);
     }
   
   if (new_focus_child && new_focus_child != old_focus_child)
     {
       if (grab_focus)
        gtk_widget_grab_focus (new_focus_child);
-      else
+      else if (container->focus_child)
        gtk_container_set_focus_child (container, new_focus_child);
+
+      if (list->selection_mode == GTK_SELECTION_BROWSE && !list->selection)
+       {
+         list->last_focus_child = new_focus_child; 
+         gtk_list_select_child (list, new_focus_child);
+       }
     }
-  
-  if (GTK_WIDGET_VISIBLE (list))
+
+  if (gtk_widget_get_visible (GTK_WIDGET (list)))
     gtk_widget_queue_resize (GTK_WIDGET (list));
 }
 
@@ -1374,7 +1364,6 @@ void
 gtk_list_set_selection_mode (GtkList         *list,
                             GtkSelectionMode  mode)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (list->selection_mode == mode)
@@ -1388,7 +1377,6 @@ gtk_list_set_selection_mode (GtkList            *list,
     case GTK_SELECTION_BROWSE:
       gtk_list_unselect_all (list);
       break;
-
     default:
       break;
     }
@@ -1400,7 +1388,6 @@ gtk_list_select_item (GtkList *list,
 {
   GList *tmp_list;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   tmp_list = g_list_nth (list->children, item);
@@ -1414,7 +1401,6 @@ gtk_list_unselect_item (GtkList *list,
 {
   GList *tmp_list;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   tmp_list = g_list_nth (list->children, item);
@@ -1440,18 +1426,16 @@ void
 gtk_list_select_all (GtkList *list)
 {
   GtkContainer *container;
-  GList *work;
  
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (!list->children)
     return;
   
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
+  if (list_has_grab (list))
     gtk_list_end_drag_selection (list);
 
-  if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
+  if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
     gtk_list_end_selection (list);
 
   container = GTK_CONTAINER (list);
@@ -1465,8 +1449,7 @@ gtk_list_select_all (GtkList *list)
          return;
        }
       break;
-
-    case GTK_SELECTION_EXTENDED:
+    case GTK_SELECTION_MULTIPLE:
       g_list_free (list->undo_selection);
       g_list_free (list->undo_unselection);
       list->undo_selection = NULL;
@@ -1483,15 +1466,6 @@ gtk_list_select_all (GtkList *list)
       gtk_list_update_extended_selection (list, g_list_length(list->children));
       gtk_list_end_selection (list);
       return;
-
-    case GTK_SELECTION_MULTIPLE:
-      for (work = list->children; work; work = work->next)
-       {
-         if (GTK_WIDGET_STATE (work->data) == GTK_STATE_NORMAL)
-           gtk_list_select_child (list, GTK_WIDGET (work->data));
-       }
-      return;
-
     default:
       break;
     }
@@ -1504,16 +1478,15 @@ gtk_list_unselect_all (GtkList *list)
   GtkWidget *item;
   GList *work;
  
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (!list->children)
     return;
-  
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
+
+  if (list_has_grab (list))
     gtk_list_end_drag_selection (list);
 
-  if (list->selection_mode == GTK_SELECTION_EXTENDED && list->anchor >= 0)
+  if (list->selection_mode == GTK_SELECTION_MULTIPLE && list->anchor >= 0)
     gtk_list_end_selection (list);
 
   container = GTK_CONTAINER (list);
@@ -1527,18 +1500,9 @@ gtk_list_unselect_all (GtkList *list)
          return;
        }
       break;
-
-    case GTK_SELECTION_EXTENDED:
-      g_list_free (list->undo_selection);
-      g_list_free (list->undo_unselection);
-      list->undo_selection = NULL;
-      list->undo_unselection = NULL;
-
-      list->anchor = -1;
-      list->drag_pos = -1;
-      list->undo_focus_child = container->focus_child;
+    case GTK_SELECTION_MULTIPLE:
+      gtk_list_reset_extended_selection (list);
       break;
-
     default:
       break;
     }
@@ -1561,11 +1525,10 @@ gtk_list_extend_selection (GtkList       *list,
 {
   GtkContainer *container;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
-      list->selection_mode != GTK_SELECTION_EXTENDED)
+  if (list_has_grab (list) ||
+      list->selection_mode != GTK_SELECTION_MULTIPLE)
     return;
 
   container = GTK_CONTAINER (list);
@@ -1589,23 +1552,20 @@ gtk_list_extend_selection (GtkList       *list,
 void
 gtk_list_end_drag_selection (GtkList *list)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   list->drag_selection = FALSE;
   if (GTK_WIDGET_HAS_GRAB (list))
-    {
-      gtk_grab_remove (GTK_WIDGET (list));
-      gdk_pointer_ungrab (GDK_CURRENT_TIME);
-    }
+    gtk_grab_remove (GTK_WIDGET (list));
+
   if (list->htimer)
     {
-      gtk_timeout_remove (list->htimer);
+      g_source_remove (list->htimer);
       list->htimer = 0;
     }
   if (list->vtimer)
     {
-      gtk_timeout_remove (list->vtimer);
+      g_source_remove (list->vtimer);
       list->vtimer = 0;
     }
 }
@@ -1616,10 +1576,9 @@ gtk_list_start_selection (GtkList *list)
   GtkContainer *container;
   gint focus_row;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
+  if (list_has_grab (list))
     return;
 
   container = GTK_CONTAINER (list);
@@ -1635,23 +1594,24 @@ gtk_list_end_selection (GtkList *list)
 {
   gint i;
   gint e;
+  gboolean top_down;
   GList *work;
   GtkWidget *item;
   gint item_index;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
-      list->anchor < 0)
+  if (list_has_grab (list) || list->anchor < 0)
     return;
 
   i = MIN (list->anchor, list->drag_pos);
   e = MAX (list->anchor, list->drag_pos);
-  
+
+  top_down = (list->anchor < list->drag_pos);
+
   list->anchor = -1;
   list->drag_pos = -1;
-
+  
   if (list->undo_selection)
     {
       work = list->selection;
@@ -1673,53 +1633,77 @@ gtk_list_end_selection (GtkList *list)
        }
     }    
 
-  for (work = g_list_nth (list->children, i); i <= e; i++, work = work->next)
+  if (top_down)
     {
-      item = work->data;
-      if (g_list_find (list->selection, item))
-         {
-           if (item->state == GTK_STATE_NORMAL)
-             {
-               gtk_widget_set_state (item, GTK_STATE_SELECTED);
-               gtk_list_unselect_child (list, item);
-               list->undo_selection = g_list_prepend (list->undo_selection,
+      for (work = g_list_nth (list->children, i); i <= e;
+          i++, work = work->next)
+       {
+         item = work->data;
+         if (g_list_find (list->selection, item))
+           {
+             if (item->state == GTK_STATE_NORMAL)
+               {
+                 gtk_widget_set_state (item, GTK_STATE_SELECTED);
+                 gtk_list_unselect_child (list, item);
+                 list->undo_selection = g_list_prepend (list->undo_selection,
+                                                        item);
+               }
+           }
+         else if (item->state == GTK_STATE_SELECTED)
+           {
+             gtk_widget_set_state (item, GTK_STATE_NORMAL);
+             list->undo_unselection = g_list_prepend (list->undo_unselection,
                                                       item);
-             }
-         }
-      else if (item->state == GTK_STATE_SELECTED)
+           }
+       }
+    }
+  else
+    {
+      for (work = g_list_nth (list->children, e); i <= e;
+          e--, work = work->prev)
        {
-         gtk_widget_set_state (item, GTK_STATE_NORMAL);
-         list->undo_unselection = g_list_prepend (list->undo_unselection,
-                                                  item);
+         item = work->data;
+         if (g_list_find (list->selection, item))
+           {
+             if (item->state == GTK_STATE_NORMAL)
+               {
+                 gtk_widget_set_state (item, GTK_STATE_SELECTED);
+                 gtk_list_unselect_child (list, item);
+                 list->undo_selection = g_list_prepend (list->undo_selection,
+                                                        item);
+               }
+           }
+         else if (item->state == GTK_STATE_SELECTED)
+           {
+             gtk_widget_set_state (item, GTK_STATE_NORMAL);
+             list->undo_unselection = g_list_prepend (list->undo_unselection,
+                                                      item);
+           }
        }
     }
 
-  for (work = list->undo_unselection; work; work = work->next)
+  for (work = g_list_reverse (list->undo_unselection); work; work = work->next)
     gtk_list_select_child (list, GTK_WIDGET (work->data));
 
+
 }
 
 void
 gtk_list_toggle_row (GtkList   *list,
                     GtkWidget *item)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
-  g_return_if_fail (item != NULL);
   g_return_if_fail (GTK_IS_LIST_ITEM (item));
 
   switch (list->selection_mode)
     {
-    case GTK_SELECTION_EXTENDED:
     case GTK_SELECTION_MULTIPLE:
     case GTK_SELECTION_SINGLE:
-
       if (item->state == GTK_STATE_SELECTED)
        {
          gtk_list_unselect_child (list, item);
          return;
        }
-
     case GTK_SELECTION_BROWSE:
       gtk_list_select_child (list, item);
       break;
@@ -1737,20 +1721,15 @@ gtk_list_toggle_focus_row (GtkList *list)
 
   container = GTK_CONTAINER (list);
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
-      !container->focus_child)
+  if (list_has_grab (list) || !container->focus_child)
     return;
 
   switch (list->selection_mode)
     {
     case  GTK_SELECTION_SINGLE:
-    case  GTK_SELECTION_MULTIPLE:
-      
       gtk_list_toggle_row (list, container->focus_child);
       break;
-      
-    case GTK_SELECTION_EXTENDED:
-
+    case GTK_SELECTION_MULTIPLE:
       if ((focus_row = g_list_index (list->children, container->focus_child))
          < 0)
        return;
@@ -1771,7 +1750,6 @@ gtk_list_toggle_focus_row (GtkList *list)
       
       gtk_list_end_selection (list);
       break;
-      
     default:
       break;
     }
@@ -1785,8 +1763,8 @@ gtk_list_toggle_add_mode (GtkList *list)
   g_return_if_fail (list != 0);
   g_return_if_fail (GTK_IS_LIST (list));
   
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)) ||
-      list->selection_mode != GTK_SELECTION_EXTENDED)
+  if (list_has_grab (list) ||
+      list->selection_mode != GTK_SELECTION_MULTIPLE)
     return;
   
   container = GTK_CONTAINER (list);
@@ -1808,11 +1786,10 @@ gtk_list_undo_selection (GtkList *list)
 {
   GList *work;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
-  if (list->selection_mode != GTK_SELECTION_EXTENDED ||
-      (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list)))
+  if (list->selection_mode != GTK_SELECTION_MULTIPLE ||
+      list_has_grab (list))
     return;
   
   if (list->anchor >= 0)
@@ -1837,7 +1814,7 @@ gtk_list_undo_selection (GtkList *list)
       container = GTK_CONTAINER (list);
 
       if (container->focus_child &&
-         GTK_WIDGET_HAS_FOCUS (container->focus_child))
+         gtk_widget_has_focus (container->focus_child))
        gtk_widget_grab_focus (list->undo_focus_child);
       else
        gtk_container_set_focus_child (container, list->undo_focus_child);
@@ -1861,9 +1838,7 @@ static void
 gtk_real_list_select_child (GtkList   *list,
                            GtkWidget *child)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
-  g_return_if_fail (child != NULL);
   g_return_if_fail (GTK_IS_LIST_ITEM (child));
 
   switch (child->state)
@@ -1881,9 +1856,7 @@ static void
 gtk_real_list_unselect_child (GtkList  *list,
                              GtkWidget *child)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
-  g_return_if_fail (child != NULL);
   g_return_if_fail (GTK_IS_LIST_ITEM (child));
 
   if (child->state == GTK_STATE_SELECTED)
@@ -1897,6 +1870,7 @@ gtk_real_list_unselect_child (GtkList     *list,
  * gtk_list_fake_unselect_all
  * gtk_list_fake_toggle_row
  * gtk_list_update_extended_selection
+ * gtk_list_reset_extended_selection
  */
 static void
 gtk_list_set_anchor (GtkList   *list,
@@ -1906,10 +1880,9 @@ gtk_list_set_anchor (GtkList   *list,
 {
   GList *work;
 
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
   
-  if (list->selection_mode != GTK_SELECTION_EXTENDED || list->anchor >= 0)
+  if (list->selection_mode != GTK_SELECTION_MULTIPLE || list->anchor >= 0)
     return;
 
   g_list_free (list->undo_selection);
@@ -1988,7 +1961,7 @@ gtk_list_update_extended_selection (GtkList *list,
   if (row >= length)
     row = length - 1;
 
-  if (list->selection_mode != GTK_SELECTION_EXTENDED || !list->anchor < 0)
+  if (list->selection_mode != GTK_SELECTION_MULTIPLE || !list->anchor < 0)
     return;
 
   /* extending downwards */
@@ -2061,6 +2034,21 @@ gtk_list_update_extended_selection (GtkList *list,
     }
 }
 
+static void
+gtk_list_reset_extended_selection (GtkList *list)
+{ 
+  g_return_if_fail (list != 0);
+  g_return_if_fail (GTK_IS_LIST (list));
+
+  g_list_free (list->undo_selection);
+  g_list_free (list->undo_unselection);
+  list->undo_selection = NULL;
+  list->undo_unselection = NULL;
+
+  list->anchor = -1;
+  list->drag_pos = -1;
+  list->undo_focus_child = GTK_CONTAINER (list)->focus_child;
+}
 
 /* Public GtkList Scroll Methods :
  *
@@ -2077,7 +2065,7 @@ gtk_list_scroll_horizontal (GtkList       *list,
   g_return_if_fail (list != 0);
   g_return_if_fail (GTK_IS_LIST (list));
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
+  if (list_has_grab (list))
     return;
 
   if (!(adj =
@@ -2086,18 +2074,22 @@ gtk_list_scroll_horizontal (GtkList       *list,
 
   switch (scroll_type)
     {
+    case GTK_SCROLL_STEP_UP:
     case GTK_SCROLL_STEP_BACKWARD:
       adj->value = CLAMP (adj->value - adj->step_increment, adj->lower,
                          adj->upper - adj->page_size);
       break;
+    case GTK_SCROLL_STEP_DOWN:
     case GTK_SCROLL_STEP_FORWARD:
       adj->value = CLAMP (adj->value + adj->step_increment, adj->lower,
                          adj->upper - adj->page_size);
       break;
+    case GTK_SCROLL_PAGE_UP:
     case GTK_SCROLL_PAGE_BACKWARD:
       adj->value = CLAMP (adj->value - adj->page_increment, adj->lower,
                          adj->upper - adj->page_size);
       break;
+    case GTK_SCROLL_PAGE_DOWN:
     case GTK_SCROLL_PAGE_FORWARD:
       adj->value = CLAMP (adj->value + adj->page_increment, adj->lower,
                          adj->upper - adj->page_size);
@@ -2117,13 +2109,12 @@ gtk_list_scroll_vertical (GtkList       *list,
                          GtkScrollType  scroll_type,
                          gfloat         position)
 {
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (list))
+  if (list_has_grab (list))
     return;
 
-  if (list->selection_mode == GTK_SELECTION_EXTENDED)
+  if (list->selection_mode == GTK_SELECTION_MULTIPLE)
     {
       GtkContainer *container;
 
@@ -2181,13 +2172,11 @@ gtk_list_move_focus_child (GtkList       *list,
       if (work)
        gtk_widget_grab_focus (GTK_WIDGET (work->data));
       break;
-
     case GTK_SCROLL_STEP_FORWARD:
       work = work->next;
       if (work)
        gtk_widget_grab_focus (GTK_WIDGET (work->data));
       break;
-
     case GTK_SCROLL_PAGE_BACKWARD:
       if (!work->prev)
        return;
@@ -2233,7 +2222,6 @@ gtk_list_move_focus_child (GtkList       *list,
          
       gtk_widget_grab_focus (item);
       break;
-         
     case GTK_SCROLL_PAGE_FORWARD:
       if (!work->next)
        return;
@@ -2282,7 +2270,6 @@ gtk_list_move_focus_child (GtkList       *list,
          
       gtk_widget_grab_focus (item);
       break;
-
     case GTK_SCROLL_JUMP:
       new_value = GTK_WIDGET(list)->allocation.height * CLAMP (position, 0, 1);
 
@@ -2296,57 +2283,36 @@ gtk_list_move_focus_child (GtkList       *list,
 
       gtk_widget_grab_focus (item);
       break;
-
     default:
       break;
     }
 }
 
-static gint
-gtk_list_horizontal_timeout (GtkWidget *list)
+static void
+do_fake_motion (GtkWidget *list)
 {
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  GTK_THREADS_ENTER;
+  GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
 
-  GTK_LIST (list)->htimer = 0;
-  gdk_window_get_pointer (list->window, &x, &y, &mask);
+  event->motion.send_event = TRUE;
 
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
-
-  gtk_list_motion_notify (list, &event);
-
-  GTK_THREADS_LEAVE;
+  gtk_list_motion_notify (list, (GdkEventMotion *)event);
+  gdk_event_free (event);
+}
 
+static gint
+gtk_list_horizontal_timeout (GtkWidget *list)
+{
+  GTK_LIST (list)->htimer = 0;
+  do_fake_motion (list);
+  
   return FALSE;
 }
 
 static gint
 gtk_list_vertical_timeout (GtkWidget *list)
 {
-  gint x;
-  gint y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  GTK_THREADS_ENTER;
-
   GTK_LIST (list)->vtimer = 0;
-  gdk_window_get_pointer (list->window, &x, &y, &mask);
-
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
-
-  gtk_list_motion_notify (list, &event);
-
-  GTK_THREADS_LEAVE;
+  do_fake_motion (list);
 
   return FALSE;
 }
@@ -2354,7 +2320,6 @@ gtk_list_vertical_timeout (GtkWidget *list)
 
 /* Private GtkListItem Signal Functions :
  *
- * gtk_list_signal_focus_lost
  * gtk_list_signal_toggle_focus_row
  * gtk_list_signal_select_all
  * gtk_list_signal_unselect_all
@@ -2369,29 +2334,11 @@ gtk_list_vertical_timeout (GtkWidget *list)
  * gtk_list_signal_item_deselect
  * gtk_list_signal_item_toggle
  */
-static void
-gtk_list_signal_focus_lost (GtkWidget   *item,
-                           GdkEventKey *event,
-                           GtkList     *list)
-{
-  g_return_if_fail (list != NULL);
-  g_return_if_fail (GTK_IS_LIST (list));
-  g_return_if_fail (item != NULL);
-  g_return_if_fail (GTK_IS_LIST_ITEM (item));
-
-  if (list->selection_mode == GTK_SELECTION_EXTENDED &&
-      list->anchor >= 0 &&
-      item == GTK_CONTAINER (list)->focus_child)
-    gtk_list_end_selection (list);
-}
-
 static void
 gtk_list_signal_toggle_focus_row (GtkListItem *list_item,
                                  GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_toggle_focus_row (list);
@@ -2401,9 +2348,7 @@ static void
 gtk_list_signal_select_all (GtkListItem *list_item,
                            GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_select_all (list);
@@ -2413,9 +2358,7 @@ static void
 gtk_list_signal_unselect_all (GtkListItem *list_item,
                              GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_unselect_all (list);
@@ -2425,9 +2368,7 @@ static void
 gtk_list_signal_undo_selection (GtkListItem *list_item,
                                GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_undo_selection (list);
@@ -2437,9 +2378,7 @@ static void
 gtk_list_signal_start_selection (GtkListItem *list_item,
                                 GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_start_selection (list);
@@ -2449,9 +2388,7 @@ static void
 gtk_list_signal_end_selection (GtkListItem *list_item,
                               GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_end_selection (list);
@@ -2464,9 +2401,7 @@ gtk_list_signal_extend_selection (GtkListItem   *list_item,
                                  gboolean       auto_start_selection,
                                  GtkList       *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_extend_selection (list, scroll_type, position,
@@ -2479,9 +2414,7 @@ gtk_list_signal_scroll_horizontal (GtkListItem   *list_item,
                                   gfloat         position,
                                   GtkList       *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_scroll_horizontal (list, scroll_type, position);
@@ -2493,9 +2426,7 @@ gtk_list_signal_scroll_vertical (GtkListItem   *list_item,
                                 gfloat         position,
                                 GtkList       *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_scroll_vertical (list, scroll_type, position);
@@ -2505,9 +2436,7 @@ static void
 gtk_list_signal_toggle_add_mode (GtkListItem *list_item,
                                 GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   gtk_list_toggle_add_mode (list);
@@ -2521,9 +2450,7 @@ gtk_list_signal_item_select (GtkListItem *list_item,
   GList *tmp_list;
   GList *sel_list;
 
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (GTK_WIDGET (list_item)->state != GTK_STATE_SELECTED)
@@ -2550,21 +2477,13 @@ gtk_list_signal_item_select (GtkListItem *list_item,
       if (!sel_list)
        {
          list->selection = g_list_prepend (list->selection, list_item);
-         gtk_widget_ref (GTK_WIDGET (list_item));
+         g_object_ref (list_item);
        }
       gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
       break;
-    case GTK_SELECTION_EXTENDED:
+    case GTK_SELECTION_MULTIPLE:
       if (list->anchor >= 0)
        return;
-    case GTK_SELECTION_MULTIPLE:
-      if (!g_list_find (list->selection, list_item))
-       {
-         list->selection = g_list_prepend (list->selection, list_item);
-         gtk_widget_ref (GTK_WIDGET (list_item));
-         gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
-       }
-      break;
     }
 }
 
@@ -2574,9 +2493,7 @@ gtk_list_signal_item_deselect (GtkListItem *list_item,
 {
   GList *node;
 
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
   if (GTK_WIDGET (list_item)->state != GTK_STATE_NORMAL)
@@ -2588,7 +2505,7 @@ gtk_list_signal_item_deselect (GtkListItem *list_item,
     {
       list->selection = g_list_remove_link (list->selection, node);
       g_list_free_1 (node);
-      gtk_widget_unref (GTK_WIDGET (list_item));
+      g_object_unref (list_item);
       gtk_signal_emit (GTK_OBJECT (list), list_signals[SELECTION_CHANGED]);
     }
 }
@@ -2597,11 +2514,17 @@ static void
 gtk_list_signal_item_toggle (GtkListItem *list_item,
                             GtkList     *list)
 {
-  g_return_if_fail (list_item != 0);
   g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
-  g_return_if_fail (list != NULL);
   g_return_if_fail (GTK_IS_LIST (list));
 
+  if ((list->selection_mode == GTK_SELECTION_BROWSE ||
+       list->selection_mode == GTK_SELECTION_MULTIPLE) &&
+      GTK_WIDGET (list_item)->state == GTK_STATE_NORMAL)
+    {
+      gtk_widget_set_state (GTK_WIDGET (list_item), GTK_STATE_SELECTED);
+      return;
+    }
+  
   switch (GTK_WIDGET (list_item)->state)
     {
     case GTK_STATE_SELECTED:
@@ -2614,3 +2537,45 @@ gtk_list_signal_item_toggle (GtkListItem *list_item,
       break;
     }
 }
+
+static void
+gtk_list_signal_drag_begin (GtkWidget      *widget,
+                           GdkDragContext *context,
+                           GtkList         *list)
+{
+  g_return_if_fail (GTK_IS_LIST_ITEM (widget));
+  g_return_if_fail (GTK_IS_LIST (list));
+
+  gtk_list_drag_begin (GTK_WIDGET (list), context);
+}
+
+static void
+gtk_list_drag_begin (GtkWidget      *widget,
+                    GdkDragContext *context)
+{
+  GtkList *list;
+
+  g_return_if_fail (GTK_IS_LIST (widget));
+  g_return_if_fail (context != NULL);
+
+  list = GTK_LIST (widget);
+
+  if (list->drag_selection)
+    {
+      gtk_list_end_drag_selection (list);
+
+      switch (list->selection_mode)
+       {
+       case GTK_SELECTION_MULTIPLE:
+         gtk_list_end_selection (list);
+         break;
+       case GTK_SELECTION_SINGLE:
+         list->undo_focus_child = NULL;
+         break;
+       default:
+         break;
+       }
+    }
+}
+
+#include "gtkaliasdef.c"