Index: gobject/gsignal.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gsignal.c,v
retrieving revision 1.56
diff -u -p -r1.56 gsignal.c
--- gobject/gsignal.c	16 Sep 2004 18:52:40 -0000	1.56
+++ gobject/gsignal.c	25 Sep 2004 17:33:36 -0000
@@ -209,7 +209,9 @@ struct _HandlerList
 {
   guint    signal_id;
   Handler *handlers;
+  Handler *tail_before;
 };
+
 struct _Handler
 {
   gulong        sequential_number;
@@ -356,6 +358,7 @@ handler_list_ensure (guint    signal_id,
   
   key.signal_id = signal_id;
   key.handlers = NULL;
+  key.tail_before = NULL;
   if (!hlbsa)
     {
       hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
@@ -577,16 +580,31 @@ handler_unref_R (guint    signal_id,
   handler->ref_count -= 1;
   if (!handler->ref_count)
     {
+      HandlerList *hlist = NULL;
+
       if (handler->next)
         handler->next->prev = handler->prev;
-      if (handler->prev)	/* watch out for g_signal_handlers_destroy()! */
+      if (handler->prev)    /* watch out for g_signal_handlers_destroy()! */
         handler->prev->next = handler->next;
       else
         {
-          HandlerList *hlist = handler_list_lookup (signal_id, instance);
-          
+          hlist = handler_list_lookup (signal_id, instance);
           hlist->handlers = handler->next;
         }
+
+      /*  check if we are removing the handler pointed to by tail_before  */
+      if (instance &&
+          !handler->after && (!handler->next || handler->next->after))
+        {
+          if (!hlist)
+            hlist = handler_list_lookup (signal_id, instance);
+          if (hlist)
+            {
+              g_assert (hlist->tail_before == handler); /* paranoid */
+              hlist->tail_before = handler->prev;
+            }
+        }
+
       SIGNAL_UNLOCK ();
       g_closure_unref (handler->closure);
       SIGNAL_LOCK ();
@@ -605,28 +623,39 @@ handler_insert (guint    signal_id,
   
   hlist = handler_list_ensure (signal_id, instance);
   if (!hlist->handlers)
-    hlist->handlers = handler;
-  else if (hlist->handlers->after && !handler->after)
     {
-      handler->next = hlist->handlers;
-      hlist->handlers->prev = handler;
       hlist->handlers = handler;
+      if (!handler->after)
+        hlist->tail_before = handler;
     }
-  else
+  else if (handler->after)
     {
-      Handler *tmp = hlist->handlers;
-      
-      if (handler->after)
-        while (tmp->next)
-          tmp = tmp->next;
-      else
-        while (tmp->next && !tmp->next->after)
-          tmp = tmp->next;
-      if (tmp->next)
-        tmp->next->prev = handler;
-      handler->next = tmp->next;
+      Handler *tmp = hlist->tail_before ? hlist->tail_before : hlist->handlers;
+
+      while (tmp->next)
+        tmp = tmp->next;
+
       handler->prev = tmp;
       tmp->next = handler;
+    }
+  else
+    {
+      if (hlist->tail_before)
+        {
+          handler->next = hlist->tail_before->next;
+          if (handler->next)
+            handler->next->prev = handler;
+          handler->prev = hlist->tail_before;
+          hlist->tail_before->next = handler;
+        }
+      else
+        {
+          handler->next = hlist->handlers;
+          if (handler->next)
+            handler->next->prev = handler;
+          hlist->handlers = handler;
+        }
+      hlist->tail_before = handler;
     }
 }
 
