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