]> Pileus Git - ~andy/gtk/blob - gtk/gtksignal.c
pass only the signal_id to this function. it needs to relookup the signal
[~andy/gtk] / gtk / gtksignal.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <stdarg.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include "gtksignal.h"
23 #include "gtkargcollector.c"
24
25
26 #define SIGNAL_BLOCK_SIZE               (100)
27 #define HANDLER_BLOCK_SIZE              (200)
28 #define EMISSION_BLOCK_SIZE             (100)
29 #define DISCONNECT_INFO_BLOCK_SIZE      (64)
30 #define MAX_SIGNAL_PARAMS               (31)
31
32 enum
33 {
34   EMISSION_CONTINUE,
35   EMISSION_RESTART,
36   EMISSION_DONE
37 };
38
39 #define GTK_RUN_TYPE(x)  ((x) & GTK_RUN_MASK)
40
41
42 typedef struct _GtkSignal               GtkSignal;
43 typedef struct _GtkSignalHash           GtkSignalHash;
44 typedef struct _GtkHandler              GtkHandler;
45 typedef struct _GtkHandlerInfo          GtkHandlerInfo;
46 typedef struct _GtkEmission             GtkEmission;
47 typedef union  _GtkEmissionAllocator    GtkEmissionAllocator;
48 typedef struct _GtkDisconnectInfo       GtkDisconnectInfo;
49
50 typedef void (*GtkSignalMarshaller0) (GtkObject *object,
51                                       gpointer   data);
52
53 struct _GtkSignal
54 {
55   guint               signal_id;
56   GtkType             object_type;
57   gchar              *name;
58   guint               function_offset;
59   GtkSignalRunType    signal_flags;
60   GtkSignalMarshaller marshaller;
61   GtkType             return_val;
62   GtkType            *params;
63   guint               nparams;
64 };
65
66 struct _GtkSignalHash
67 {
68   GtkType object_type;
69   GQuark  quark;
70   guint   signal_id;
71 };
72
73 struct _GtkHandler
74 {
75   guint            id;
76   guint            blocked : 20;
77   guint            object_signal : 1;
78   guint            after : 1;
79   guint            no_marshal : 1;
80   guint16          ref_count;
81   guint16          signal_id;
82   GtkSignalFunc    func;
83   gpointer         func_data;
84   GtkSignalDestroy destroy_func;
85   GtkHandler      *prev;
86   GtkHandler      *next;
87 };
88
89 struct _GtkHandlerInfo
90 {
91   GtkObject          *object;
92   GtkSignalMarshaller marshaller;
93   GtkArg             *params;
94   GtkType            *param_types;
95   GtkType             return_val;
96   GtkSignalRunType    signal_flags;
97   guint               nparams;
98   guint               signal_id;
99 };
100
101 struct _GtkEmission
102 {
103   GtkObject *object;
104   guint      signal_id;
105 };
106
107 union _GtkEmissionAllocator
108 {
109   GtkEmissionAllocator *next;
110   GtkEmission           emission;
111 };
112
113 struct _GtkDisconnectInfo
114 {
115   GtkObject     *object1;
116   guint          disconnect_handler1;
117   guint          signal_handler;
118   GtkObject     *object2;
119   guint          disconnect_handler2;
120 };
121
122
123 static guint        gtk_signal_hash            (gconstpointer h);
124 static gint         gtk_signal_compare         (gconstpointer h1,
125                                                 gconstpointer h2);
126 static GtkHandler*  gtk_signal_handler_new     (void);
127 static void         gtk_signal_handler_ref     (GtkHandler    *handler);
128 static void         gtk_signal_handler_unref   (GtkHandler    *handler,
129                                                 GtkObject     *object);
130 static void         gtk_signal_handler_insert  (GtkObject     *object,
131                                                 GtkHandler    *handler);
132 static void         gtk_signal_real_emit       (GtkObject     *object,
133                                                 guint          signal_id,
134                                                 GtkArg        *params);
135 static GtkHandler*  gtk_signal_get_handlers    (GtkObject     *object,
136                                                 guint          signal_type);
137 static guint        gtk_signal_connect_by_type (GtkObject     *object,
138                                                 guint          signal_id,
139                                                 GtkSignalFunc  func,
140                                                 gpointer       func_data,
141                                                 GtkSignalDestroy destroy_func,
142                                                 gint           object_signal,
143                                                 gint           after,
144                                                 gint           no_marshal);
145 static guint        gtk_alive_disconnecter     (GtkDisconnectInfo *info);
146 static GtkEmission* gtk_emission_new           (void);
147 static void         gtk_emission_add           (GList         **emissions,
148                                                 GtkObject      *object,
149                                                 guint           signal_type);
150 static void         gtk_emission_remove        (GList         **emissions,
151                                                 GtkObject      *object,
152                                                 guint           signal_type);
153 static gint         gtk_emission_check         (GList          *emissions,
154                                                 GtkObject      *object,
155                                                 guint           signal_type);
156 static gint         gtk_handlers_run           (GtkHandler     *handlers,
157                                                 GtkHandlerInfo *info,
158                                                 gint            after);
159 static gboolean     gtk_signal_collect_params  (GtkArg         *params,
160                                                 guint           nparams,
161                                                 GtkType        *param_types,
162                                                 GtkType         return_type,
163                                                 va_list         var_args);
164
165 #define LOOKUP_SIGNAL_ID(signal_id)     ( \
166   signal_id > 0 && signal_id < gtk_n_signals ? \
167     (GtkSignal*) gtk_signals + signal_id : \
168     (GtkSignal*) 0 \
169 )
170
171
172 static GtkSignalMarshal global_marshaller = NULL;
173 static GtkSignalDestroy global_destroy_notify = NULL;
174
175 static guint                     gtk_handler_id = 1;
176 static guint                     handler_quark = 0;
177 static GHashTable               *gtk_signal_hash_table = NULL;
178 static GtkSignal                *gtk_signals = NULL;
179 static guint                     gtk_n_signals = 0;
180 static GMemChunk                *gtk_signal_hash_mem_chunk = NULL;
181 static GMemChunk                *gtk_disconnect_info_mem_chunk = NULL;
182 static GtkHandler               *gtk_handler_free_list = NULL;
183 static GtkEmissionAllocator     *gtk_emission_free_list = NULL;
184
185
186
187 static GList *current_emissions = NULL;
188 static GList *stop_emissions = NULL;
189 static GList *restart_emissions = NULL;
190
191 static GtkSignal*
192 gtk_signal_next_and_invalidate (void)
193 {
194   static guint gtk_n_free_signals = 0;
195   register GtkSignal *signal;
196   register guint new_signal_id;
197   
198   /* don't keep *any* GtkSignal pointers across invokation of this function!!!
199    */
200   
201   if (gtk_n_free_signals == 0)
202     {
203       register guint i;
204       register guint size;
205       
206       /* nearest pow
207        */
208       size = gtk_n_signals + SIGNAL_BLOCK_SIZE;
209       size *= sizeof (GtkSignal);
210       i = 1;
211       while (i < size)
212         i <<= 1;
213       size = i;
214       
215       gtk_signals = g_realloc (gtk_signals, size);
216       
217       gtk_n_free_signals = size / sizeof (GtkSignal) - gtk_n_signals;
218       
219       memset (gtk_signals + gtk_n_signals, 0, gtk_n_free_signals * sizeof (GtkSignal));
220     }
221   
222   new_signal_id = gtk_n_signals++;
223   gtk_n_free_signals--;
224   
225   signal = LOOKUP_SIGNAL_ID (new_signal_id);
226   if (signal)
227     signal->signal_id = new_signal_id;
228   
229   return signal;
230 }
231
232 void
233 gtk_signal_init (void)
234 {
235   if (!handler_quark)
236     {
237       GtkSignal *zero;
238       
239       zero = gtk_signal_next_and_invalidate ();
240       g_assert (zero == NULL);
241       
242       handler_quark = g_quark_from_static_string ("gtk-signal-handlers");
243       
244       gtk_signal_hash_mem_chunk =
245         g_mem_chunk_new ("GtkSignalHash mem chunk",
246                          sizeof (GtkSignalHash),
247                          sizeof (GtkSignalHash) * SIGNAL_BLOCK_SIZE,
248                          G_ALLOC_ONLY);
249       gtk_disconnect_info_mem_chunk =
250         g_mem_chunk_new ("GtkDisconnectInfo mem chunk",
251                          sizeof (GtkDisconnectInfo),
252                          sizeof (GtkDisconnectInfo) * DISCONNECT_INFO_BLOCK_SIZE,
253                          G_ALLOC_AND_FREE);
254       gtk_handler_free_list = NULL;
255       gtk_emission_free_list = NULL;
256       
257       gtk_signal_hash_table = g_hash_table_new (gtk_signal_hash,
258                                                 gtk_signal_compare);
259     }
260 }
261
262 guint
263 gtk_signal_newv (const gchar         *r_name,
264                  GtkSignalRunType     signal_flags,
265                  GtkType              object_type,
266                  guint                function_offset,
267                  GtkSignalMarshaller  marshaller,
268                  GtkType              return_val,
269                  guint                nparams,
270                  GtkType             *params)
271 {
272   GtkSignal *signal;
273   GtkSignalHash *hash;
274   GQuark quark;
275   guint i;
276   gchar *name;
277   
278   g_return_val_if_fail (r_name != NULL, 0);
279   g_return_val_if_fail (marshaller != NULL, 0);
280   g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0);
281   if (nparams)
282     g_return_val_if_fail (params != NULL, 0);
283   
284   if (!handler_quark)
285     gtk_signal_init ();
286
287
288   name = g_strdup (r_name);
289   g_strdelimit (name, NULL, '_');
290
291   quark = gtk_signal_lookup (name, object_type);
292   if (quark)
293     {
294       g_warning ("gtk_signal_newv(): signal \"%s\" already exists in the `%s' class ancestry\n",
295                  r_name,
296                  gtk_type_name (object_type));
297       g_free (name);
298       return 0;
299     }
300   
301   if (return_val != GTK_TYPE_NONE &&
302       (signal_flags & GTK_RUN_BOTH) == GTK_RUN_FIRST)
303     {
304       g_warning ("gtk_signal_newv(): signal \"%s\" with return value `%s' excludes GTK_RUN_LAST",
305                  name, gtk_type_name (return_val));
306       g_free (name);
307       return 0;
308     }
309   
310   signal = gtk_signal_next_and_invalidate ();
311   
312   /* signal->signal_id already set */
313   
314   signal->object_type = object_type;
315   signal->name = name;
316   signal->function_offset = function_offset;
317   signal->signal_flags = signal_flags;
318   signal->marshaller = marshaller;
319   signal->return_val = return_val;
320   signal->nparams = nparams;
321   
322   if (nparams > 0)
323     {
324       signal->params = g_new (GtkType, nparams);
325       
326       for (i = 0; i < nparams; i++)
327         signal->params[i] = params[i];
328     }
329   else
330     signal->params = NULL;
331
332   /* insert "signal_name" into hash table
333    */
334   hash = g_chunk_new (GtkSignalHash, gtk_signal_hash_mem_chunk);
335   hash->object_type = object_type;
336   hash->quark = g_quark_from_string (signal->name);
337   hash->signal_id = signal->signal_id;
338   g_hash_table_insert (gtk_signal_hash_table, hash, GUINT_TO_POINTER (hash->signal_id));
339
340   /* insert "signal-name" into hash table
341    */
342   g_strdelimit (signal->name, NULL, '-');
343   quark = g_quark_from_static_string (signal->name);
344   if (quark != hash->quark)
345     {
346       hash = g_chunk_new (GtkSignalHash, gtk_signal_hash_mem_chunk);
347       hash->object_type = object_type;
348       hash->quark = quark;
349       hash->signal_id = signal->signal_id;
350       g_hash_table_insert (gtk_signal_hash_table, hash, GUINT_TO_POINTER (hash->signal_id));
351     }
352   
353   return signal->signal_id;
354 }
355
356 guint
357 gtk_signal_new (const gchar         *name,
358                 GtkSignalRunType     signal_flags,
359                 GtkType              object_type,
360                 guint                function_offset,
361                 GtkSignalMarshaller  marshaller,
362                 GtkType              return_val,
363                 guint                nparams,
364                 ...)
365 {
366   GtkType *params;
367   guint i;
368   va_list args;
369   guint signal_id;
370   
371   g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0);
372   
373   if (nparams > 0)
374     {
375       params = g_new (GtkType, nparams);
376       
377       va_start (args, nparams);
378       
379       for (i = 0; i < nparams; i++)
380         params[i] = va_arg (args, GtkType);
381       
382       va_end (args);
383     }
384   else
385     params = NULL;
386   
387   signal_id = gtk_signal_newv (name,
388                                signal_flags,
389                                object_type,
390                                function_offset,
391                                marshaller,
392                                return_val,
393                                nparams,
394                                params);
395   
396   g_free (params);
397   
398   return signal_id;
399 }
400
401 guint
402 gtk_signal_lookup (const gchar *name,
403                    GtkType      object_type)
404 {
405   GtkSignalHash hash;
406   
407   g_return_val_if_fail (name != NULL, 0);
408   g_return_val_if_fail (gtk_type_is_a (object_type, GTK_TYPE_OBJECT), 0);
409   
410   hash.quark = g_quark_try_string (name);
411   if (hash.quark)
412     {
413       while (object_type)
414         {
415           guint signal_id;
416           
417           hash.object_type = object_type;
418           
419           signal_id = GPOINTER_TO_UINT (g_hash_table_lookup (gtk_signal_hash_table, &hash));
420           if (signal_id)
421             return signal_id;
422           
423           object_type = gtk_type_parent (object_type);
424         }
425     }
426   
427   return 0;
428 }
429
430 GtkSignalQuery*
431 gtk_signal_query (guint signal_id)
432 {
433   GtkSignalQuery *query;
434   GtkSignal *signal;
435   
436   g_return_val_if_fail (signal_id >= 1, NULL);
437   
438   signal = LOOKUP_SIGNAL_ID (signal_id);
439   if (signal)
440     {
441       query = g_new (GtkSignalQuery, 1);
442       
443       query->object_type = signal->object_type;
444       query->signal_id = signal_id;
445       query->signal_name = signal->name;
446       query->is_user_signal = signal->function_offset == 0;
447       query->signal_flags = signal->signal_flags;
448       query->return_val = signal->return_val;
449       query->nparams = signal->nparams;
450       query->params = signal->params;
451     }
452   else
453     query = NULL;
454   
455   return query;
456 }
457
458 gchar*
459 gtk_signal_name (guint signal_id)
460 {
461   GtkSignal *signal;
462   
463   g_return_val_if_fail (signal_id >= 1, NULL);
464   
465   signal = LOOKUP_SIGNAL_ID (signal_id);
466   if (signal)
467     return signal->name;
468   
469   return NULL;
470 }
471
472 void
473 gtk_signal_emitv (GtkObject           *object,
474                   guint                signal_id,
475                   GtkArg              *params)
476 {
477   GtkSignal *signal;
478
479   g_return_if_fail (object != NULL);
480   g_return_if_fail (signal_id >= 1);
481   
482   signal = LOOKUP_SIGNAL_ID (signal_id);
483   g_return_if_fail (signal != NULL);
484   g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type));
485
486   if (signal->nparams > 0)
487     g_return_if_fail (params != NULL);
488
489   gtk_signal_real_emit (object, signal_id, params);
490 }
491
492 void
493 gtk_signal_emit (GtkObject *object,
494                  guint      signal_id,
495                  ...)
496 {
497   GtkSignal *signal;
498   va_list    args;
499   GtkArg     params[MAX_SIGNAL_PARAMS + 1];
500   gboolean   abort;
501
502   g_return_if_fail (object != NULL);
503   g_return_if_fail (signal_id >= 1);
504   
505   signal = LOOKUP_SIGNAL_ID (signal_id);
506   g_return_if_fail (signal != NULL);
507   g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type));
508
509   va_start (args, signal_id);
510   abort = gtk_signal_collect_params (params,
511                                      signal->nparams,
512                                      signal->params,
513                                      signal->return_val,
514                                      args);
515   va_end (args);
516
517   if (!abort)
518     gtk_signal_real_emit (object, signal_id, params);
519 }
520
521 void
522 gtk_signal_emitv_by_name (GtkObject           *object,
523                           const gchar         *name,
524                           GtkArg              *params)
525 {
526   guint signal_id;
527   
528   g_return_if_fail (object != NULL);
529   g_return_if_fail (name != NULL);
530   g_return_if_fail (params != NULL);
531   
532   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
533   
534   if (signal_id >= 1)
535     {
536       GtkSignal *signal;
537       
538       signal = LOOKUP_SIGNAL_ID (signal_id);
539       g_return_if_fail (signal != NULL);
540       g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type));
541
542       gtk_signal_real_emit (object, signal_id, params);
543     }
544   else
545     {
546       g_warning ("gtk_signal_emitv_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
547                  name,
548                  gtk_type_name (GTK_OBJECT_TYPE (object)));
549     }
550 }
551
552 void
553 gtk_signal_emit_by_name (GtkObject       *object,
554                          const gchar     *name,
555                          ...)
556 {
557   guint signal_id;
558   
559   g_return_if_fail (object != NULL);
560   g_return_if_fail (name != NULL);
561   
562   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
563   
564   if (signal_id >= 1)
565     {
566       GtkSignal *signal;
567       GtkArg     params[MAX_SIGNAL_PARAMS + 1];
568       va_list    args;
569       gboolean   abort;
570       
571       signal = LOOKUP_SIGNAL_ID (signal_id);
572       g_return_if_fail (signal != NULL);
573       g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type));
574
575       va_start (args, name);
576       abort = gtk_signal_collect_params (params,
577                                          signal->nparams,
578                                          signal->params,
579                                          signal->return_val,
580                                          args);
581       va_end (args);
582
583       if (!abort)
584         gtk_signal_real_emit (object, signal_id, params);
585     }
586   else
587     {
588       g_warning ("gtk_signal_emit_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
589                  name,
590                  gtk_type_name (GTK_OBJECT_TYPE (object)));
591     }
592 }
593
594 void
595 gtk_signal_emit_stop (GtkObject *object,
596                       guint       signal_id)
597 {
598   g_return_if_fail (object != NULL);
599   g_return_if_fail (signal_id >= 1);
600   
601   if (gtk_emission_check (current_emissions, object, signal_id))
602     gtk_emission_add (&stop_emissions, object, signal_id);
603   else
604     g_warning ("gtk_signal_emit_stop(): no current emission (%u) for object `%s'",
605                signal_id,
606                gtk_type_name (GTK_OBJECT_TYPE (object)));
607 }
608
609 void
610 gtk_signal_emit_stop_by_name (GtkObject       *object,
611                               const gchar     *name)
612 {
613   guint signal_id;
614   
615   g_return_if_fail (object != NULL);
616   g_return_if_fail (name != NULL);
617   
618   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
619   if (signal_id)
620     gtk_signal_emit_stop (object, signal_id);
621   else
622     g_warning ("gtk_signal_emit_stop_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
623                name,
624                gtk_type_name (GTK_OBJECT_TYPE (object)));
625 }
626
627 guint
628 gtk_signal_n_emissions (GtkObject  *object,
629                         guint       signal_id)
630 {
631   GList *list;
632   guint n;
633   
634   g_return_val_if_fail (object != NULL, 0);
635   g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
636   
637   n = 0;
638   for (list = current_emissions; list; list = list->next)
639     {
640       GtkEmission *emission;
641       
642       emission = list->data;
643       
644       if ((emission->object == object) &&
645           (emission->signal_id == signal_id))
646         n++;
647     }
648   
649   return n;
650 }
651
652 guint
653 gtk_signal_n_emissions_by_name (GtkObject       *object,
654                                 const gchar     *name)
655 {
656   guint signal_id;
657   guint n;
658   
659   g_return_val_if_fail (object != NULL, 0);
660   g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
661   g_return_val_if_fail (name != NULL, 0);
662   
663   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
664   if (signal_id)
665     n = gtk_signal_n_emissions (object, signal_id);
666   else
667     {
668       g_warning ("gtk_signal_n_emissions_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
669                  name,
670                  gtk_type_name (GTK_OBJECT_TYPE (object)));
671       n = 0;
672     }
673   
674   return n;
675 }
676
677 guint
678 gtk_signal_connect (GtkObject     *object,
679                     const gchar   *name,
680                     GtkSignalFunc  func,
681                     gpointer       func_data)
682 {
683   guint signal_id;
684   
685   g_return_val_if_fail (object != NULL, 0);
686   g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
687   
688   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
689   if (!signal_id)
690     {
691       g_warning ("gtk_signal_connect(): could not find signal \"%s\" in the `%s' class ancestry",
692                  name,
693                  gtk_type_name (GTK_OBJECT_TYPE (object)));
694       return 0;
695     }
696   
697   return gtk_signal_connect_by_type (object, signal_id, 
698                                      func, func_data, NULL,
699                                      FALSE, FALSE, FALSE);
700 }
701
702 guint
703 gtk_signal_connect_after (GtkObject     *object,
704                           const gchar   *name,
705                           GtkSignalFunc  func,
706                           gpointer       func_data)
707 {
708   guint signal_id;
709   
710   g_return_val_if_fail (object != NULL, 0);
711   
712   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
713   if (!signal_id)
714     {
715       g_warning ("gtk_signal_connect_after(): could not find signal \"%s\" in the `%s' class ancestry",
716                  name,
717                  gtk_type_name (GTK_OBJECT_TYPE (object)));
718       return 0;
719     }
720   
721   return gtk_signal_connect_by_type (object, signal_id, 
722                                      func, func_data, NULL,
723                                      FALSE, TRUE, FALSE);
724 }
725
726 guint   
727 gtk_signal_connect_full (GtkObject           *object,
728                          const gchar         *name,
729                          GtkSignalFunc        func,
730                          GtkCallbackMarshal   marshal,
731                          gpointer             func_data,
732                          GtkDestroyNotify     destroy_func,
733                          gint                 object_signal,
734                          gint                 after)
735 {
736   guint signal_id;
737   
738   g_return_val_if_fail (object != NULL, 0);
739   
740   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
741   if (!signal_id)
742     {
743       g_warning ("gtk_signal_connect_full(): could not find signal \"%s\" in the `%s' class ancestry",
744                  name,
745                  gtk_type_name (GTK_OBJECT_TYPE (object)));
746       return 0;
747     }
748   
749   if (marshal)
750     return gtk_signal_connect_by_type (object, signal_id, (GtkSignalFunc) marshal, 
751                                        func_data, destroy_func, 
752                                        object_signal, after, TRUE);
753   else
754     return gtk_signal_connect_by_type (object, signal_id, func, 
755                                        func_data, destroy_func, 
756                                        object_signal, after, FALSE);
757 }
758
759 guint
760 gtk_signal_connect_interp (GtkObject         *object,
761                            const gchar       *name,
762                            GtkCallbackMarshal func,
763                            gpointer           func_data,
764                            GtkDestroyNotify   destroy_func,
765                            gint               after)
766 {
767   return gtk_signal_connect_full (object, name, NULL, func,
768                                   func_data, destroy_func, FALSE, after);
769 }
770
771 guint
772 gtk_signal_connect_object (GtkObject     *object,
773                            const gchar   *name,
774                            GtkSignalFunc  func,
775                            GtkObject     *slot_object)
776 {
777   guint signal_id;
778   
779   g_return_val_if_fail (object != NULL, 0);
780   /* slot_object needs to be treated as ordinary pointer
781    */
782   
783   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
784   if (!signal_id)
785     {
786       g_warning ("gtk_signal_connect_object(): could not find signal \"%s\" in the `%s' class ancestry",
787                  name,
788                  gtk_type_name (GTK_OBJECT_TYPE (object)));
789       return 0;
790     }
791   
792   return gtk_signal_connect_by_type (object, signal_id, 
793                                      func, slot_object, NULL,
794                                      TRUE, FALSE, FALSE);
795 }
796
797 guint
798 gtk_signal_connect_object_after (GtkObject     *object,
799                                  const gchar   *name,
800                                  GtkSignalFunc  func,
801                                  GtkObject     *slot_object)
802 {
803   guint signal_id;
804   
805   g_return_val_if_fail (object != NULL, 0);
806   
807   signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
808   if (!signal_id)
809     {
810       g_warning ("gtk_signal_connect_object_after(): could not find signal \"%s\" in the `%s' class ancestry",
811                  name,
812                  gtk_type_name (GTK_OBJECT_TYPE (object)));
813       return 0;
814     }
815   
816   return gtk_signal_connect_by_type (object, signal_id, 
817                                      func, slot_object, NULL,
818                                      TRUE, TRUE, FALSE);
819 }
820
821 void
822 gtk_signal_connect_while_alive (GtkObject        *object,
823                                 const gchar      *signal,
824                                 GtkSignalFunc     func,
825                                 gpointer          func_data,
826                                 GtkObject        *alive_object)
827 {
828   GtkDisconnectInfo *info;
829   
830   g_return_if_fail (object != NULL);
831   g_return_if_fail (GTK_IS_OBJECT (object));
832   g_return_if_fail (signal != NULL);
833   g_return_if_fail (func != NULL);
834   g_return_if_fail (alive_object != NULL);
835   g_return_if_fail (GTK_IS_OBJECT (alive_object));
836   
837   info = g_chunk_new (GtkDisconnectInfo, gtk_disconnect_info_mem_chunk);
838   info->object1 = object;
839   info->object2 = alive_object;
840   
841   info->signal_handler = gtk_signal_connect (object, signal, func, func_data);
842   info->disconnect_handler1 =
843     gtk_signal_connect_object (info->object1,
844                                "destroy",
845                                GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
846                                (GtkObject*) info);
847   info->disconnect_handler2 =
848     gtk_signal_connect_object (info->object2,
849                                "destroy",
850                                GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
851                                (GtkObject*) info);
852 }
853
854 void
855 gtk_signal_connect_object_while_alive (GtkObject        *object,
856                                        const gchar      *signal,
857                                        GtkSignalFunc     func,
858                                        GtkObject        *alive_object)
859 {
860   GtkDisconnectInfo *info;
861   
862   g_return_if_fail (object != NULL);
863   g_return_if_fail (GTK_IS_OBJECT (object));
864   g_return_if_fail (signal != NULL);
865   g_return_if_fail (func != NULL);
866   g_return_if_fail (alive_object != NULL);
867   g_return_if_fail (GTK_IS_OBJECT (alive_object));
868   
869   info = g_chunk_new (GtkDisconnectInfo, gtk_disconnect_info_mem_chunk);
870   info->object1 = object;
871   info->object2 = alive_object;
872   
873   info->signal_handler = gtk_signal_connect_object (object, signal, func, alive_object);
874   info->disconnect_handler1 =
875     gtk_signal_connect_object (info->object1,
876                                "destroy",
877                                GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
878                                (GtkObject*) info);
879   info->disconnect_handler2 =
880     gtk_signal_connect_object (info->object2,
881                                "destroy",
882                                GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
883                                (GtkObject*) info);
884 }
885
886 void
887 gtk_signal_disconnect (GtkObject *object,
888                        guint      handler_id)
889 {
890   GtkHandler *handler;
891   
892   g_return_if_fail (object != NULL);
893   g_return_if_fail (handler_id > 0);
894   
895   handler = gtk_object_get_data_by_id (object, handler_quark);
896   
897   while (handler)
898     {
899       if (handler->id == handler_id)
900         {
901           handler->id = 0;
902           handler->blocked += 1;
903           gtk_signal_handler_unref (handler, object);
904           return;
905         }
906       handler = handler->next;
907     }
908   
909   g_warning ("gtk_signal_disconnect(): could not find handler (%u)", handler_id);
910 }
911
912 void
913 gtk_signal_disconnect_by_func (GtkObject     *object,
914                                GtkSignalFunc  func,
915                                gpointer       data)
916 {
917   GtkHandler *handler;
918   gint found_one;
919   
920   g_return_if_fail (object != NULL);
921   g_return_if_fail (func != NULL);
922   
923   found_one = FALSE;
924   handler = gtk_object_get_data_by_id (object, handler_quark);
925   
926   while (handler)
927     {
928       GtkHandler *handler_next;
929       
930       handler_next = handler->next;
931       if ((handler->id > 0) &&
932           (handler->func == func) &&
933           (handler->func_data == data))
934         {
935           found_one = TRUE;
936           handler->id = 0;
937           handler->blocked += 1;
938           gtk_signal_handler_unref (handler, object);
939         }
940       handler = handler_next;
941     }
942   
943   if (!found_one)
944     g_warning ("gtk_signal_disconnect_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
945 }
946
947 void
948 gtk_signal_disconnect_by_data (GtkObject *object,
949                                gpointer   data)
950 {
951   GtkHandler *handler;
952   gint found_one;
953   
954   g_return_if_fail (object != NULL);
955   
956   found_one = FALSE;
957   handler = gtk_object_get_data_by_id (object, handler_quark);
958   
959   while (handler)
960     {
961       GtkHandler *handler_next;
962       
963       handler_next = handler->next;
964       if ((handler->id > 0) &&
965           (handler->func_data == data))
966         {
967           found_one = TRUE;
968           handler->id = 0;
969           handler->blocked += 1;
970           gtk_signal_handler_unref (handler, object);
971         }
972       handler = handler_next;
973     }
974   
975   if (!found_one)
976     g_warning ("gtk_signal_disconnect_by_data(): could not find handler containing data (0x%0lX)", (long) data);
977 }
978
979 void
980 gtk_signal_handler_block (GtkObject *object,
981                           guint      handler_id)
982 {
983   GtkHandler *handler;
984   
985   g_return_if_fail (object != NULL);
986   g_return_if_fail (handler_id > 0);
987   
988   handler = gtk_object_get_data_by_id (object, handler_quark);
989   
990   while (handler)
991     {
992       if (handler->id == handler_id)
993         {
994           handler->blocked += 1;
995           return;
996         }
997       handler = handler->next;
998     }
999   
1000   g_warning ("gtk_signal_handler_block(): could not find handler (%u)", handler_id);
1001 }
1002
1003 void
1004 gtk_signal_handler_block_by_func (GtkObject     *object,
1005                                   GtkSignalFunc  func,
1006                                   gpointer       data)
1007 {
1008   GtkHandler *handler;
1009   gint found_one;
1010   
1011   g_return_if_fail (object != NULL);
1012   g_return_if_fail (func != NULL);
1013   
1014   found_one = FALSE;
1015   handler = gtk_object_get_data_by_id (object, handler_quark);
1016   
1017   while (handler)
1018     {
1019       if ((handler->id > 0) &&
1020           (handler->func == func) &&
1021           (handler->func_data == data))
1022         {
1023           found_one = TRUE;
1024           handler->blocked += 1;
1025         }
1026       handler = handler->next;
1027     }
1028   
1029   if (!found_one)
1030     g_warning ("gtk_signal_handler_block_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
1031 }
1032
1033 void
1034 gtk_signal_handler_block_by_data (GtkObject *object,
1035                                   gpointer   data)
1036 {
1037   GtkHandler *handler;
1038   gint found_one;
1039   
1040   g_return_if_fail (object != NULL);
1041   
1042   found_one = FALSE;
1043   handler = gtk_object_get_data_by_id (object, handler_quark);
1044   
1045   while (handler)
1046     {
1047       if ((handler->id > 0) &&
1048           (handler->func_data == data))
1049         {
1050           found_one = TRUE;
1051           handler->blocked += 1;
1052         }
1053       handler = handler->next;
1054     }
1055   
1056   if (!found_one)
1057     g_warning ("gtk_signal_handler_block_by_data(): could not find handler containing data (0x%0lX)", (long) data);
1058 }
1059
1060 void
1061 gtk_signal_handler_unblock (GtkObject *object,
1062                             guint      handler_id)
1063 {
1064   GtkHandler *handler;
1065   
1066   g_return_if_fail (object != NULL);
1067   g_return_if_fail (handler_id > 0);
1068   
1069   handler = gtk_object_get_data_by_id (object, handler_quark);
1070   
1071   while (handler)
1072     {
1073       if (handler->id == handler_id)
1074         {
1075           if (handler->blocked > 0)
1076             handler->blocked -= 1;
1077           else
1078             g_warning ("gtk_signal_handler_unblock(): handler (%u) is not blocked", handler_id);
1079           return;
1080         }
1081       handler = handler->next;
1082     }
1083   
1084   g_warning ("gtk_signal_handler_unblock(): could not find handler (%u)", handler_id);
1085 }
1086
1087 void
1088 gtk_signal_handler_unblock_by_func (GtkObject     *object,
1089                                     GtkSignalFunc  func,
1090                                     gpointer       data)
1091 {
1092   GtkHandler *handler;
1093   gint found_one;
1094   
1095   g_return_if_fail (object != NULL);
1096   g_return_if_fail (func != NULL);
1097   
1098   found_one = FALSE;
1099   handler = gtk_object_get_data_by_id (object, handler_quark);
1100   
1101   while (handler)
1102     {
1103       if ((handler->id > 0) &&
1104           (handler->func == func) &&
1105           (handler->func_data == data) &&
1106           (handler->blocked > 0))
1107         {
1108           handler->blocked -= 1;
1109           found_one = TRUE;
1110         }
1111       handler = handler->next;
1112     }
1113   
1114   if (!found_one)
1115     g_warning ("gtk_signal_handler_unblock_by_func(): could not find blocked handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
1116 }
1117
1118 void
1119 gtk_signal_handler_unblock_by_data (GtkObject *object,
1120                                     gpointer   data)
1121 {
1122   GtkHandler *handler;
1123   gint found_one;
1124   
1125   g_return_if_fail (object != NULL);
1126   
1127   found_one = FALSE;
1128   handler = gtk_object_get_data_by_id (object, handler_quark);
1129   
1130   while (handler)
1131     {
1132       if ((handler->id > 0) &&
1133           (handler->func_data == data) &&
1134           (handler->blocked > 0))
1135         {
1136           handler->blocked -= 1;
1137           found_one = TRUE;
1138         }
1139       handler = handler->next;
1140     }
1141   
1142   if (!found_one)
1143     g_warning ("gtk_signal_handler_unblock_by_data(): could not find blocked handler containing data (0x%0lX)", (long) data);
1144 }
1145
1146 void
1147 gtk_signal_handlers_destroy (GtkObject *object)
1148 {
1149   GtkHandler *handler;
1150   
1151   /* we make the "optimization" of destroying the first handler in the last
1152    * place, since we don't want gtk_signal_handler_unref() to reset the objects
1153    * handler_key data on each removal
1154    */
1155   
1156   handler = gtk_object_get_data_by_id (object, handler_quark);
1157   if (handler)
1158     {
1159       handler = handler->next;
1160       while (handler)
1161         {
1162           GtkHandler *next;
1163           
1164           next = handler->next;
1165           gtk_signal_handler_unref (handler, object);
1166           handler = next;
1167         }
1168       handler = gtk_object_get_data_by_id (object, handler_quark);
1169       gtk_signal_handler_unref (handler, object);
1170     }
1171 }
1172
1173 void
1174 gtk_signal_default_marshaller (GtkObject      *object,
1175                                GtkSignalFunc   func,
1176                                gpointer        func_data,
1177                                GtkArg         *params)
1178 {
1179   GtkSignalMarshaller0 rfunc;
1180   
1181   rfunc = (GtkSignalMarshaller0) func;
1182   
1183   (* rfunc) (object, func_data);
1184 }
1185
1186 void
1187 gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
1188                       GtkSignalDestroy destroy_func)
1189 {
1190   global_marshaller = marshal_func;
1191   global_destroy_notify = destroy_func;
1192 }
1193
1194 static guint
1195 gtk_signal_hash (gconstpointer h)
1196 {
1197   register const GtkSignalHash *hash = h;
1198   
1199   return hash->object_type ^ hash->quark;
1200 }
1201
1202 static gint
1203 gtk_signal_compare (gconstpointer h1,
1204                     gconstpointer h2)
1205 {
1206   register const GtkSignalHash *hash1 = h1;
1207   register const GtkSignalHash *hash2 = h2;
1208   
1209   return (hash1->quark == hash2->quark &&
1210           hash1->object_type == hash2->object_type);
1211 }
1212
1213 static guint
1214 gtk_alive_disconnecter (GtkDisconnectInfo *info)
1215 {
1216   g_return_val_if_fail (info != NULL, 0);
1217   
1218   gtk_signal_disconnect (info->object1, info->disconnect_handler1);
1219   gtk_signal_disconnect (info->object1, info->signal_handler);
1220   gtk_signal_disconnect (info->object2, info->disconnect_handler2);
1221   
1222   g_mem_chunk_free (gtk_disconnect_info_mem_chunk, info);
1223   
1224   return 0;
1225 }
1226
1227 static GtkHandler*
1228 gtk_signal_handler_new (void)
1229 {
1230   GtkHandler *handler;
1231
1232   if (!gtk_handler_free_list)
1233     {
1234       GtkHandler *handler_block;
1235       guint i;
1236
1237       handler_block = g_new0 (GtkHandler, HANDLER_BLOCK_SIZE);
1238       for (i = 1; i < HANDLER_BLOCK_SIZE; i++)
1239         {
1240           (handler_block + i)->next = gtk_handler_free_list;
1241           gtk_handler_free_list = (handler_block + i);
1242         }
1243       
1244       handler = handler_block;
1245     }
1246   else
1247     {
1248       handler = gtk_handler_free_list;
1249       gtk_handler_free_list = handler->next;
1250     }
1251   
1252   handler->id = 0;
1253   handler->blocked = 0;
1254   handler->signal_id = 0;
1255   handler->object_signal = FALSE;
1256   handler->after = FALSE;
1257   handler->no_marshal = FALSE;
1258   handler->ref_count = 1;
1259   handler->func = NULL;
1260   handler->func_data = NULL;
1261   handler->destroy_func = NULL;
1262   handler->prev = NULL;
1263   handler->next = NULL;
1264   
1265   return handler;
1266 }
1267
1268 static void
1269 gtk_signal_handler_ref (GtkHandler *handler)
1270 {
1271   handler->ref_count += 1;
1272 }
1273
1274 static void
1275 gtk_signal_handler_unref (GtkHandler *handler,
1276                           GtkObject  *object)
1277 {
1278   if (!handler->ref_count)
1279     {
1280       /* FIXME: i wanna get removed somewhen */
1281       g_warning ("gtk_signal_handler_unref(): handler with ref_count==0!");
1282       return;
1283     }
1284   
1285   handler->ref_count -= 1;
1286   
1287   if (handler->ref_count == 0)
1288     {
1289       if (handler->destroy_func)
1290         (* handler->destroy_func) (handler->func_data);
1291       else if (!handler->func && global_destroy_notify)
1292         (* global_destroy_notify) (handler->func_data);
1293       
1294       if (handler->prev)
1295         handler->prev->next = handler->next;
1296       else if (handler->next)
1297         gtk_object_set_data_by_id (object, handler_quark, handler->next);
1298       else
1299         {
1300           GTK_OBJECT_UNSET_FLAGS (object, GTK_CONNECTED);
1301           gtk_object_set_data_by_id (object, handler_quark, NULL);
1302         }
1303       if (handler->next)
1304         handler->next->prev = handler->prev;
1305       
1306       handler->next = gtk_handler_free_list;
1307       gtk_handler_free_list = handler;
1308     }
1309 }
1310
1311 static void
1312 gtk_signal_handler_insert (GtkObject  *object,
1313                            GtkHandler *handler)
1314 {
1315   GtkHandler *tmp;
1316   
1317   /* FIXME: remove */ g_assert (handler->next == NULL);
1318   /* FIXME: remove */ g_assert (handler->prev == NULL);
1319   
1320   tmp = gtk_object_get_data_by_id (object, handler_quark);
1321   if (!tmp)
1322     {
1323       GTK_OBJECT_SET_FLAGS (object, GTK_CONNECTED);
1324       gtk_object_set_data_by_id (object, handler_quark, handler);
1325     }
1326   else
1327     while (tmp)
1328       {
1329         if (tmp->signal_id < handler->signal_id)
1330           {
1331             if (tmp->prev)
1332               {
1333                 tmp->prev->next = handler;
1334                 handler->prev = tmp->prev;
1335               }
1336             else
1337               gtk_object_set_data_by_id (object, handler_quark, handler);
1338             tmp->prev = handler;
1339             handler->next = tmp;
1340             break;
1341           }
1342         
1343         if (!tmp->next)
1344           {
1345             tmp->next = handler;
1346             handler->prev = tmp;
1347             break;
1348           }
1349         tmp = tmp->next;
1350       }
1351 }
1352
1353 static GtkObject *gtk_trace_signal_object = NULL;
1354
1355 static void
1356 gtk_signal_real_emit (GtkObject *object,
1357                       guint      signal_id,
1358                       GtkArg    *params)
1359 {
1360   GtkSignal *signal;
1361   GtkHandler    *handlers;
1362   GtkHandlerInfo info;
1363   guchar       **signal_func_offset;
1364
1365   signal = LOOKUP_SIGNAL_ID (signal_id);
1366
1367 #ifdef  G_ENABLE_DEBUG
1368   if (gtk_debug_flags & GTK_DEBUG_SIGNALS ||
1369       object == gtk_trace_signal_object)
1370     fprintf (stdout, "trace: signal_emit(\"%s\") for %s:%p\n",
1371              signal->name,
1372              gtk_type_name (GTK_OBJECT_TYPE (object)),
1373              object);
1374 #endif  /* G_ENABLE_DEBUG */
1375   
1376   if ((signal->signal_flags & GTK_RUN_NO_RECURSE) &&
1377       gtk_emission_check (current_emissions, object, signal_id))
1378     {
1379       gtk_emission_add (&restart_emissions, object, signal_id);
1380       return;
1381     }
1382   
1383   gtk_object_ref (object);
1384
1385   gtk_emission_add (&current_emissions, object, signal_id);
1386   
1387  emission_restart:
1388   if (GTK_RUN_TYPE (signal->signal_flags) != GTK_RUN_LAST && signal->function_offset != 0)
1389     {
1390       signal_func_offset = (guchar**) ((guchar*) object->klass +
1391                                        signal->function_offset);
1392       if (*signal_func_offset)
1393         {
1394           (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset,
1395                                   NULL, params);
1396           signal = LOOKUP_SIGNAL_ID (signal_id);
1397         }
1398     }
1399   
1400   if (GTK_OBJECT_CONNECTED (object))
1401     {
1402       handlers = gtk_signal_get_handlers (object, signal_id);
1403       if (handlers)
1404         {
1405           gint return_val;
1406
1407           info.object = object;
1408           info.marshaller = signal->marshaller;
1409           info.params = params;
1410           info.param_types = signal->params;
1411           info.return_val = signal->return_val;
1412           info.nparams = signal->nparams;
1413           info.signal_flags = signal->signal_flags;
1414           info.signal_id = signal_id;
1415
1416           return_val = gtk_handlers_run (handlers, &info, FALSE);
1417           signal = LOOKUP_SIGNAL_ID (signal_id);
1418           switch (return_val)
1419             {
1420             case  EMISSION_CONTINUE:
1421               break;
1422             case  EMISSION_RESTART:
1423               goto emission_restart;
1424             case  EMISSION_DONE:
1425               goto emission_done;
1426             }
1427         }
1428       else
1429         info.object = NULL;
1430     }
1431   else
1432     info.object = NULL;
1433   
1434   if (GTK_RUN_TYPE (signal->signal_flags) != GTK_RUN_FIRST      && signal->function_offset != 0)
1435     {
1436       signal_func_offset = (guchar**) ((guchar*) object->klass +
1437                                        signal->function_offset);
1438       if (*signal_func_offset)
1439         {
1440           (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset,
1441                                   NULL, params);
1442           signal = LOOKUP_SIGNAL_ID (signal_id);
1443         }
1444     }
1445   
1446   if (GTK_OBJECT_CONNECTED (object))
1447     {
1448       handlers = gtk_signal_get_handlers (object, signal_id);
1449       if (handlers)
1450         {
1451           gint return_val;
1452
1453           if (!info.object)
1454             {
1455               info.object = object;
1456               info.marshaller = signal->marshaller;
1457               info.params = params;
1458               info.param_types = signal->params;
1459               info.return_val = signal->return_val;
1460               info.nparams = signal->nparams;
1461               info.signal_flags = signal->signal_flags;
1462               info.signal_id = signal_id;
1463             }
1464           return_val = gtk_handlers_run (handlers, &info, TRUE);
1465           signal = LOOKUP_SIGNAL_ID (signal_id);
1466           switch (return_val)
1467             {
1468             case  EMISSION_CONTINUE:
1469               break;
1470             case  EMISSION_RESTART:
1471               goto emission_restart;
1472             case  EMISSION_DONE:
1473               goto emission_done;
1474             }
1475         }
1476     }
1477   
1478  emission_done:
1479   
1480   gtk_emission_remove (&current_emissions, object, signal_id);
1481   
1482   if (signal->signal_flags & GTK_RUN_NO_RECURSE)
1483     gtk_emission_remove (&restart_emissions, object, signal_id);
1484   
1485   gtk_object_unref (object);
1486 }
1487
1488 static GtkHandler*
1489 gtk_signal_get_handlers (GtkObject *object,
1490                          guint      signal_id)
1491 {
1492   GtkHandler *handlers;
1493   
1494   handlers = gtk_object_get_data_by_id (object, handler_quark);
1495   
1496   while (handlers)
1497     {
1498       if (handlers->signal_id == signal_id)
1499         return handlers;
1500       handlers = handlers->next;
1501     }
1502   
1503   return NULL;
1504 }
1505
1506 guint
1507 gtk_signal_handler_pending (GtkObject           *object,
1508                             guint                signal_id,
1509                             gboolean             may_be_blocked)
1510 {
1511   GtkHandler *handlers;
1512   guint handler_id;
1513   
1514   g_return_val_if_fail (object != NULL, 0);
1515   g_return_val_if_fail (signal_id >= 1, 0);
1516
1517   if (GTK_OBJECT_CONNECTED (object))
1518     handlers = gtk_signal_get_handlers (object, signal_id);
1519   else
1520     return 0;
1521   
1522   handler_id = 0;
1523   while (handlers && handlers->signal_id == signal_id)
1524     {
1525       if (handlers->id > 0 &&
1526           (may_be_blocked || handlers->blocked == FALSE))
1527         {
1528           handler_id = handlers->id;
1529           break;
1530         }
1531       
1532       handlers = handlers->next;
1533     }
1534   
1535   return handler_id;
1536 }
1537
1538 guint
1539 gtk_signal_handler_pending_by_func (GtkObject           *object,
1540                                     guint                signal_id,
1541                                     gboolean             may_be_blocked,
1542                                     GtkSignalFunc        func,
1543                                     gpointer             data)
1544 {
1545   GtkHandler *handlers;
1546   guint handler_id;
1547   
1548   g_return_val_if_fail (object != NULL, 0);
1549   g_return_val_if_fail (func != NULL, 0);
1550   g_return_val_if_fail (signal_id >= 1, 0);
1551
1552   if (GTK_OBJECT_CONNECTED (object))
1553     handlers = gtk_signal_get_handlers (object, signal_id);
1554   else
1555     return 0;
1556   
1557   handler_id = 0;
1558   while (handlers && handlers->signal_id == signal_id)
1559     {
1560       if (handlers->id > 0 &&
1561           handlers->func == func &&
1562           handlers->func_data == data &&
1563           (may_be_blocked || handlers->blocked == FALSE))
1564         {
1565           handler_id = handlers->id;
1566           break;
1567         }
1568       
1569       handlers = handlers->next;
1570     }
1571   
1572   return handler_id;
1573 }
1574
1575 static guint
1576 gtk_signal_connect_by_type (GtkObject       *object,
1577                             guint            signal_id,
1578                             GtkSignalFunc    func,
1579                             gpointer         func_data,
1580                             GtkSignalDestroy destroy_func,
1581                             gint             object_signal,
1582                             gint             after,
1583                             gint             no_marshal)
1584 {
1585   GtkObjectClass *class;
1586   GtkHandler *handler;
1587   gint found_it;
1588   
1589   g_return_val_if_fail (object != NULL, 0);
1590   g_return_val_if_fail (object->klass != NULL, 0);
1591   
1592   /* Search through the signals for this object and make
1593    *  sure the one we are adding is valid. We need to perform
1594    *  the lookup on the objects parents as well. If it isn't
1595    *  valid then issue a warning and return.
1596    * As of now (1998-05-27) this lookup shouldn't be neccessarry
1597    *  anymore since gtk_signal_lookup() has been reworked to only
1598    *  return correct signal ids per class-branch.
1599    */
1600   found_it = FALSE;
1601   class = object->klass;
1602   while (class)
1603     {
1604       GtkType parent;
1605       guint *object_signals;
1606       guint nsignals;
1607       guint i;
1608       
1609       object_signals = class->signals;
1610       nsignals = class->nsignals;
1611       
1612       for (i = 0; i < nsignals; i++)
1613         if (object_signals[i] == signal_id)
1614           {
1615             found_it = TRUE;
1616             break;
1617           }
1618       
1619       parent = gtk_type_parent (class->type);
1620       if (parent)
1621         class = gtk_type_class (parent);
1622       else
1623         class = NULL;
1624     }
1625   
1626   if (!found_it)
1627     {
1628       g_warning ("gtk_signal_connect_by_type(): could not find signal id (%u) in the `%s' class ancestry",
1629                  signal_id,
1630                  gtk_type_name (object->klass->type));
1631       return 0;
1632     }
1633   
1634   handler = gtk_signal_handler_new ();
1635   handler->id = gtk_handler_id++;
1636   handler->signal_id = signal_id;
1637   handler->object_signal = object_signal;
1638   handler->func = func;
1639   handler->func_data = func_data;
1640   handler->destroy_func = destroy_func;
1641   handler->after = after != FALSE;
1642   handler->no_marshal = no_marshal;
1643   
1644   gtk_signal_handler_insert (object, handler);
1645   return handler->id;
1646 }
1647
1648 static GtkEmission*
1649 gtk_emission_new (void)
1650 {
1651   GtkEmission *emission;
1652   
1653   if (!gtk_emission_free_list)
1654     {
1655       GtkEmissionAllocator *emission_block;
1656       guint i;
1657
1658       emission_block = g_new0 (GtkEmissionAllocator, EMISSION_BLOCK_SIZE);
1659       for (i = 1; i < EMISSION_BLOCK_SIZE; i++)
1660         {
1661           (emission_block + i)->next = gtk_emission_free_list;
1662           gtk_emission_free_list = (emission_block + i);
1663         }
1664
1665       emission = &emission_block->emission;
1666     }
1667   else
1668     {
1669       emission = &gtk_emission_free_list->emission;
1670       gtk_emission_free_list = gtk_emission_free_list->next;
1671     }
1672
1673   emission->object = NULL;
1674   emission->signal_id = 0;
1675   
1676   return emission;
1677 }
1678
1679 static void
1680 gtk_emission_add (GList     **emissions,
1681                   GtkObject  *object,
1682                   guint       signal_id)
1683 {
1684   GtkEmission *emission;
1685   
1686   g_return_if_fail (emissions != NULL);
1687   g_return_if_fail (object != NULL);
1688   
1689   emission = gtk_emission_new ();
1690   emission->object = object;
1691   emission->signal_id = signal_id;
1692   
1693   *emissions = g_list_prepend (*emissions, emission);
1694 }
1695
1696 static void
1697 gtk_emission_remove (GList     **emissions,
1698                      GtkObject  *object,
1699                      guint       signal_id)
1700 {
1701   GList *tmp;
1702   
1703   g_return_if_fail (emissions != NULL);
1704   
1705   tmp = *emissions;
1706   while (tmp)
1707     {
1708       GtkEmissionAllocator *ea;
1709       
1710       ea = tmp->data;
1711       
1712       if ((ea->emission.object == object) &&
1713           (ea->emission.signal_id == signal_id))
1714         {
1715           *emissions = g_list_remove_link (*emissions, tmp);
1716           g_list_free (tmp);
1717
1718           ea->next = gtk_emission_free_list;
1719           gtk_emission_free_list = ea;
1720           break;
1721         }
1722       
1723       tmp = tmp->next;
1724     }
1725 }
1726
1727 static gint
1728 gtk_emission_check (GList     *emissions,
1729                     GtkObject *object,
1730                     guint      signal_id)
1731 {
1732   GtkEmission *emission;
1733   GList *tmp;
1734   
1735   tmp = emissions;
1736   while (tmp)
1737     {
1738       emission = tmp->data;
1739       tmp = tmp->next;
1740       
1741       if ((emission->object == object) &&
1742           (emission->signal_id == signal_id))
1743         return TRUE;
1744     }
1745   return FALSE;
1746 }
1747
1748 static gint
1749 gtk_handlers_run (GtkHandler     *handlers,
1750                   GtkHandlerInfo *info,
1751                   gint            after)
1752 {
1753   while (handlers && handlers->signal_id == info->signal_id)
1754     {
1755       GtkHandler *handlers_next;
1756       
1757       gtk_signal_handler_ref (handlers);
1758       
1759       if (handlers->blocked == 0 && (handlers->after == after))
1760         {
1761           if (handlers->func)
1762             {
1763               if (handlers->no_marshal)
1764                 (* (GtkCallbackMarshal) handlers->func) (info->object,
1765                                                          handlers->func_data,
1766                                                          info->nparams,
1767                                                          info->params);
1768               else if (handlers->object_signal)
1769                 (* info->marshaller) ((GtkObject*) handlers->func_data, /* don't GTK_OBJECT() cast */
1770                                       handlers->func,
1771                                       handlers->func_data,
1772                                       info->params);
1773               else
1774                 (* info->marshaller) (info->object,
1775                                       handlers->func,
1776                                       handlers->func_data,
1777                                       info->params);
1778             }
1779           else if (global_marshaller)
1780             (* global_marshaller) (info->object,
1781                                    handlers->func_data,
1782                                    info->nparams,
1783                                    info->params,
1784                                    info->param_types,
1785                                    info->return_val);
1786           
1787           if (gtk_emission_check (stop_emissions, info->object,
1788                                   info->signal_id))
1789             {
1790               gtk_emission_remove (&stop_emissions, info->object,
1791                                    info->signal_id);
1792               
1793               if (info->signal_flags & GTK_RUN_NO_RECURSE)
1794                 gtk_emission_remove (&restart_emissions, info->object,
1795                                      info->signal_id);
1796               gtk_signal_handler_unref (handlers, info->object);
1797               return EMISSION_DONE;
1798             }
1799           else if ((info->signal_flags & GTK_RUN_NO_RECURSE) &&
1800                    gtk_emission_check (restart_emissions, info->object,
1801                                        info->signal_id))
1802             {
1803               gtk_emission_remove (&restart_emissions, info->object,
1804                                    info->signal_id);
1805               gtk_signal_handler_unref (handlers, info->object);
1806               return EMISSION_RESTART;
1807             }
1808         }
1809       
1810       handlers_next = handlers->next;
1811       gtk_signal_handler_unref (handlers, info->object);
1812       handlers = handlers_next;
1813     }
1814   
1815   return EMISSION_CONTINUE;
1816 }
1817
1818 static gboolean
1819 gtk_signal_collect_params (GtkArg              *params,
1820                            guint                n_params,
1821                            GtkType             *param_types,
1822                            GtkType              return_type,
1823                            va_list              var_args)
1824 {
1825   register GtkArg *last_param;
1826   register gboolean failed = FALSE;
1827
1828   for (last_param = params + n_params; params < last_param; params++)
1829     {
1830       register gchar *error;
1831
1832       params->type = *(param_types++);
1833       params->name = NULL;
1834       error = gtk_arg_collect_value (GTK_FUNDAMENTAL_TYPE (params->type),
1835                                      params,
1836                                      &var_args);
1837       if (error)
1838         {
1839           failed = TRUE;
1840           g_warning ("gtk_signal_collect_params(): %s", error);
1841           g_free (error);
1842         }
1843     }
1844
1845   params->type = return_type;
1846   params->name = NULL;
1847
1848   return_type = GTK_FUNDAMENTAL_TYPE (return_type);
1849   if (return_type != GTK_TYPE_NONE)
1850     {
1851       if ((return_type >= GTK_TYPE_FLAT_FIRST &&
1852            return_type <= GTK_TYPE_FLAT_LAST) ||
1853           (return_type == GTK_TYPE_OBJECT))
1854         {
1855           GTK_VALUE_POINTER (*params) = va_arg (var_args, gpointer);
1856           
1857           if (GTK_VALUE_POINTER (*params) == NULL)
1858             {
1859               failed = TRUE;
1860               g_warning ("gtk_signal_collect_params(): invalid NULL pointer for return argument type `%s'",
1861                          gtk_type_name (params->type));
1862             }
1863         }
1864       else
1865         {
1866           failed = TRUE;
1867           g_warning ("gtk_signal_collect_params(): unsupported return argument type `%s'",
1868                      gtk_type_name (params->type));
1869         }
1870     }
1871   else
1872     GTK_VALUE_POINTER (*params) = NULL;
1873
1874   return failed;
1875 }