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