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