1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "gtksignal.h"
26 #define GTK_RUN_TYPE(x) ((x) & GTK_RUN_MASK)
29 typedef struct _GtkSignal GtkSignal;
30 typedef struct _GtkSignalInfo GtkSignalInfo;
31 typedef struct _GtkHandler GtkHandler;
32 typedef struct _GtkHandlerInfo GtkHandlerInfo;
33 typedef struct _GtkEmission GtkEmission;
35 typedef void (*GtkSignalMarshaller0) (GtkObject *object,
49 GtkSignalRunType run_type;
50 GtkSignalMarshaller marshaller;
60 guint object_signal : 1;
67 GtkSignalDestroy destroy_func;
72 struct _GtkHandlerInfo
75 GtkSignalMarshaller marshaller;
79 GtkSignalRunType run_type;
91 static void gtk_signal_init (void);
92 static guint gtk_signal_hash (gint *key);
93 static gint gtk_signal_compare (gint *a,
95 static guint gtk_signal_info_hash (GtkSignalInfo *a);
96 static gint gtk_signal_info_compare (GtkSignalInfo *a,
98 static GtkHandler* gtk_signal_handler_new (void);
99 static void gtk_signal_handler_ref (GtkHandler *handler);
100 static void gtk_signal_handler_unref (GtkHandler *handler,
102 static void gtk_signal_handler_insert (GtkObject *object,
103 GtkHandler *handler);
104 static void gtk_signal_real_emit (GtkObject *object,
107 static GtkHandler* gtk_signal_get_handlers (GtkObject *object,
109 static gint gtk_signal_connect_by_type (GtkObject *object,
113 GtkSignalDestroy destroy_func,
117 static GtkEmission* gtk_emission_new (void);
118 static void gtk_emission_destroy (GtkEmission *emission);
119 static void gtk_emission_add (GList **emissions,
122 static void gtk_emission_remove (GList **emissions,
125 static gint gtk_emission_check (GList *emissions,
128 static gint gtk_handlers_run (GtkHandler *handlers,
129 GtkHandlerInfo *info,
131 static void gtk_params_get (GtkArg *params,
133 GtkType *param_types,
138 static gint initialize = TRUE;
139 static GHashTable *signal_hash_table = NULL;
140 static GHashTable *signal_info_hash_table = NULL;
141 static guint next_signal = 1;
142 static guint next_handler_id = 1;
144 static const gchar *handler_key = "gtk-signal-handlers";
146 static GMemChunk *handler_mem_chunk = NULL;
147 static GMemChunk *emission_mem_chunk = NULL;
149 static GList *current_emissions = NULL;
150 static GList *stop_emissions = NULL;
151 static GList *restart_emissions = NULL;
153 static GtkSignalMarshal marshal = NULL;
154 static GtkSignalDestroy destroy = NULL;
158 gtk_signal_new (const gchar *name,
159 GtkSignalRunType run_type,
161 gint function_offset,
162 GtkSignalMarshaller marshaller,
172 g_return_val_if_fail (nparams < 16, 0);
176 params = g_new (GtkType, nparams);
178 va_start (args, nparams);
180 for (i = 0; i < nparams; i++)
181 params[i] = va_arg (args, GtkType);
188 return_id = gtk_signal_newv (name,
203 gtk_signal_newv (const gchar *name,
204 GtkSignalRunType run_type,
206 gint function_offset,
207 GtkSignalMarshaller marshaller,
217 g_return_val_if_fail (name != NULL, 0);
218 g_return_val_if_fail (marshaller != NULL, 0);
219 g_return_val_if_fail (nparams < 16, 0);
221 g_return_val_if_fail (params != NULL, 0);
226 info.name = (char*)name;
227 info.object_type = object_type;
229 type = g_hash_table_lookup (signal_info_hash_table, &info);
232 g_warning ("gtk_signal_newv(): signal \"%s\" already exists in the `%s' class ancestry\n",
233 name, gtk_type_name (object_type));
237 signal = g_new (GtkSignal, 1);
238 signal->info.name = g_strdup (name);
239 signal->info.object_type = object_type;
240 signal->info.signal_type = next_signal++;
241 signal->function_offset = function_offset;
242 signal->run_type = run_type;
243 signal->marshaller = marshaller;
244 signal->return_val = return_val;
245 signal->nparams = nparams;
249 signal->params = g_new (GtkType, nparams);
251 for (i = 0; i < nparams; i++)
252 signal->params[i] = params[i];
255 signal->params = NULL;
257 g_hash_table_insert (signal_hash_table, &signal->info.signal_type, signal);
258 g_hash_table_insert (signal_info_hash_table, &signal->info, &signal->info.signal_type);
260 return signal->info.signal_type;
264 gtk_signal_query (gint signal_num)
266 GtkSignalQuery *query;
269 signal = g_hash_table_lookup (signal_hash_table, &signal_num);
272 query = g_new (GtkSignalQuery, 1);
274 query->object_type = signal->info.object_type;
275 query->signal_name = signal->info.name;
276 query->is_user_signal = signal->function_offset == 0;
277 query->run_type = signal->run_type;
278 query->return_val = signal->return_val;
279 query->nparams = signal->nparams;
280 query->params = signal->params;
289 gtk_signal_lookup (const gchar *name,
295 g_return_val_if_fail (name != NULL, 0);
300 info.name = (char*)name;
304 info.object_type = object_type;
306 type = g_hash_table_lookup (signal_info_hash_table, &info);
310 object_type = gtk_type_parent (object_type);
317 gtk_signal_name (gint signal_num)
321 signal = g_hash_table_lookup (signal_hash_table, &signal_num);
323 return signal->info.name;
329 gtk_signal_emit (GtkObject *object,
335 g_return_if_fail (object != NULL);
340 va_start (args, signal_type);
342 gtk_signal_real_emit (object, signal_type, args);
348 gtk_signal_emit_by_name (GtkObject *object,
355 g_return_if_fail (object != NULL);
360 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
364 va_start (args, name);
366 gtk_signal_real_emit (object, type, args);
372 g_warning ("gtk_signal_emit_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
373 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
378 gtk_signal_emit_stop (GtkObject *object,
381 g_return_if_fail (object != NULL);
382 g_return_if_fail (signal_type >= 1);
387 if (gtk_emission_check (current_emissions, object, signal_type))
388 gtk_emission_add (&stop_emissions, object, signal_type);
390 g_warning ("gtk_signal_emit_stop(): no current emission (%d) for object `%s'",
391 signal_type, gtk_type_name (GTK_OBJECT_TYPE (object)));
395 gtk_signal_emit_stop_by_name (GtkObject *object,
400 g_return_if_fail (object != NULL);
401 g_return_if_fail (name != NULL);
406 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
408 gtk_signal_emit_stop (object, type);
410 g_warning ("gtk_signal_emit_stop_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
411 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
415 gtk_signal_connect (GtkObject *object,
422 g_return_val_if_fail (object != NULL, 0);
427 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
430 g_warning ("gtk_signal_connect(): could not find signal \"%s\" in the `%s' class ancestry",
431 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
435 return gtk_signal_connect_by_type (object, type,
436 func, func_data, NULL,
437 FALSE, FALSE, FALSE);
441 gtk_signal_connect_after (GtkObject *object,
448 g_return_val_if_fail (object != NULL, 0);
453 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
456 g_warning ("gtk_signal_connect_after(): could not find signal \"%s\" in the `%s' class ancestry",
457 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
461 return gtk_signal_connect_by_type (object, type,
462 func, func_data, NULL,
467 gtk_signal_connect_full (GtkObject *object,
470 GtkCallbackMarshal marshal,
472 GtkDestroyNotify destroy_func,
478 g_return_val_if_fail (object != NULL, 0);
483 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
486 g_warning ("gtk_signal_connect_full(): could not find signal \"%s\" in the `%s' class ancestry",
487 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
492 return gtk_signal_connect_by_type (object, type, (GtkSignalFunc) marshal,
493 func_data, destroy_func,
494 object_signal, after, TRUE);
496 return gtk_signal_connect_by_type (object, type, func,
497 func_data, destroy_func,
498 object_signal, after, FALSE);
502 gtk_signal_connect_interp (GtkObject *object,
504 GtkCallbackMarshal func,
506 GtkDestroyNotify destroy_func,
509 return gtk_signal_connect_full (object, name, NULL, func,
510 func_data, destroy_func, FALSE, after);
514 gtk_signal_connect_object (GtkObject *object,
517 GtkObject *slot_object)
521 g_return_val_if_fail (object != NULL, 0);
522 /* slot_object needs to be treated as ordinary pointer */
527 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
530 g_warning ("gtk_signal_connect_object(): could not find signal \"%s\" in the `%s' class ancestry",
531 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
535 return gtk_signal_connect_by_type (object, type,
536 func, slot_object, NULL,
541 gtk_signal_connect_object_after (GtkObject *object,
544 GtkObject *slot_object)
548 g_return_val_if_fail (object != NULL, 0);
553 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
556 g_warning ("gtk_signal_connect_object_after(): could not find signal \"%s\" in the `%s' class ancestry",
557 name, gtk_type_name (GTK_OBJECT_TYPE (object)));
561 return gtk_signal_connect_by_type (object, type,
562 func, slot_object, NULL,
566 typedef struct _GtkDisconnectInfo GtkDisconnectInfo;
567 struct _GtkDisconnectInfo
570 gint disconnect_handler1;
573 gint disconnect_handler2;
577 gtk_alive_disconnecter (GtkDisconnectInfo *info)
579 g_return_val_if_fail (info != NULL, 0);
581 gtk_signal_disconnect (info->object1, info->disconnect_handler1);
582 gtk_signal_disconnect (info->object1, info->signal_handler);
583 gtk_signal_disconnect (info->object2, info->disconnect_handler2);
590 gtk_signal_connect_while_alive (GtkObject *object,
594 GtkObject *alive_object)
596 GtkDisconnectInfo *info;
598 g_return_if_fail (object != NULL);
599 g_return_if_fail (GTK_IS_OBJECT (object));
600 g_return_if_fail (signal != NULL);
601 g_return_if_fail (func != NULL);
602 g_return_if_fail (alive_object != NULL);
603 g_return_if_fail (GTK_IS_OBJECT (alive_object));
605 info = g_new (GtkDisconnectInfo, 1);
606 info->object1 = object;
607 info->object2 = alive_object;
609 info->signal_handler = gtk_signal_connect (object, signal, func, func_data);
610 info->disconnect_handler1 = gtk_signal_connect_object (info->object1,
612 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
614 info->disconnect_handler2 = gtk_signal_connect_object (info->object2,
616 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
621 gtk_signal_connect_object_while_alive (GtkObject *object,
624 GtkObject *alive_object)
626 GtkDisconnectInfo *info;
628 g_return_if_fail (object != NULL);
629 g_return_if_fail (GTK_IS_OBJECT (object));
630 g_return_if_fail (signal != NULL);
631 g_return_if_fail (func != NULL);
632 g_return_if_fail (alive_object != NULL);
633 g_return_if_fail (GTK_IS_OBJECT (alive_object));
635 info = g_new (GtkDisconnectInfo, 1);
636 info->object1 = object;
637 info->object2 = alive_object;
639 info->signal_handler = gtk_signal_connect_object (object, signal, func, alive_object);
640 info->disconnect_handler1 = gtk_signal_connect_object (info->object1,
642 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
644 info->disconnect_handler2 = gtk_signal_connect_object (info->object2,
646 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
651 gtk_signal_disconnect (GtkObject *object,
656 g_return_if_fail (object != NULL);
657 g_return_if_fail (an_id > 0);
659 handler = gtk_object_get_data (object, handler_key);
663 if (handler->id == an_id)
666 handler->blocked = TRUE;
667 gtk_signal_handler_unref (handler, object);
670 handler = handler->next;
673 g_warning ("gtk_signal_disconnect(): could not find handler (%d)", an_id);
677 gtk_signal_disconnect_by_data (GtkObject *object,
683 g_return_if_fail (object != NULL);
686 handler = gtk_object_get_data (object, handler_key);
690 GtkHandler *handler_next;
692 handler_next = handler->next;
693 if (handler->func_data == data &&
698 handler->blocked = TRUE;
699 gtk_signal_handler_unref (handler, object);
701 handler = handler_next;
705 g_warning ("gtk_signal_disconnect_by_data(): could not find handler containing data (0x%0lX)", (long) data);
709 gtk_signal_handler_block (GtkObject *object,
714 g_return_if_fail (object != NULL);
715 g_return_if_fail (an_id > 0);
717 tmp = gtk_object_get_data (object, handler_key);
721 if (tmp->id == an_id)
730 g_warning ("gtk_signal_handler_block(): could not find handler (%d)", an_id);
734 gtk_signal_handler_block_by_data (GtkObject *object,
740 g_return_if_fail (object != NULL);
746 handler = gtk_object_get_data (object, handler_key);
750 if (handler->func_data == data &&
754 handler->blocked = TRUE;
757 handler = handler->next;
761 g_warning ("gtk_signal_handler_block_by_data(): could not find handler containing data (0x%0lX)", (long) data);
765 gtk_signal_handler_unblock (GtkObject *object,
770 g_return_if_fail (object != NULL);
771 g_return_if_fail (an_id > 0);
776 handler = gtk_object_get_data (object, handler_key);
780 if (handler->id == an_id)
782 handler->blocked = FALSE;
786 handler = handler->next;
789 g_warning ("gtk_signal_handler_unblock(): could not find handler (%d)", an_id);
793 gtk_signal_handler_unblock_by_data (GtkObject *object,
799 g_return_if_fail (object != NULL);
805 handler = gtk_object_get_data (object, handler_key);
809 if (handler->func_data == data &&
813 handler->blocked = FALSE;
816 handler = handler->next;
820 g_warning ("gtk_signal_handler_unblock_by_data(): could not find handler containing data (0x%0lX)", (long) data);
824 gtk_signal_handlers_destroy (GtkObject *object)
828 /* we make the "optimization" of destroying the first handler in the last
829 * place, since we don't want gtk_signal_handler_unref() to reset the objects
830 * handler_key data on each removal
833 handler = gtk_object_get_data (object, handler_key);
836 handler = handler->next;
841 next = handler->next;
842 gtk_signal_handler_unref (handler, object);
845 handler = gtk_object_get_data (object, handler_key);
846 gtk_signal_handler_unref (handler, object);
851 gtk_signal_default_marshaller (GtkObject *object,
856 GtkSignalMarshaller0 rfunc;
858 rfunc = (GtkSignalMarshaller0) func;
860 (* rfunc) (object, func_data);
864 gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
865 GtkSignalDestroy destroy_func)
867 marshal = marshal_func;
868 destroy = destroy_func;
878 signal_hash_table = g_hash_table_new ((GHashFunc) gtk_signal_hash,
879 (GCompareFunc) gtk_signal_compare);
880 signal_info_hash_table = g_hash_table_new ((GHashFunc) gtk_signal_info_hash,
881 (GCompareFunc) gtk_signal_info_compare);
886 gtk_signal_hash (gint *key)
892 gtk_signal_compare (gint *a,
899 gtk_signal_info_hash (GtkSignalInfo *a)
901 return (g_str_hash (a->name) + a->object_type);
905 gtk_signal_info_compare (GtkSignalInfo *a,
908 return ((a->object_type == b->object_type) &&
909 g_str_equal (a->name, b->name));
913 gtk_signal_handler_new ()
917 if (!handler_mem_chunk)
918 handler_mem_chunk = g_mem_chunk_new ("handler mem chunk", sizeof (GtkHandler),
919 1024, G_ALLOC_AND_FREE);
921 handler = g_chunk_new (GtkHandler, handler_mem_chunk);
924 handler->ref_count = 1;
925 handler->signal_type = 0;
926 handler->blocked = FALSE;
927 handler->object_signal = FALSE;
928 handler->after = FALSE;
929 handler->no_marshal = FALSE;
930 handler->func = NULL;
931 handler->func_data = NULL;
932 handler->destroy_func = NULL;
933 handler->prev = NULL;
934 handler->next = NULL;
940 gtk_signal_handler_ref (GtkHandler *handler)
942 handler->ref_count += 1;
946 gtk_signal_handler_unref (GtkHandler *handler,
949 if (!handler->ref_count)
951 /* FIXME: i wanna get removed some when (maybe at gtk+-1.0?) */
952 g_warning ("gtk_signal_handler_unref(): handler with ref_count==0!");
956 handler->ref_count -= 1;
957 if (handler->ref_count == 0)
959 if (!handler->func && destroy)
960 (* destroy) (handler->func_data);
961 else if (handler->destroy_func)
962 (* handler->destroy_func) (handler->func_data);
966 handler->prev->next = handler->next;
968 gtk_object_set_data (object, handler_key, handler->next);
970 handler->next->prev = handler->prev;
972 g_mem_chunk_free (handler_mem_chunk, handler);
977 gtk_signal_handler_insert (GtkObject *object,
982 /* FIXME: remove */ g_assert (handler->next == NULL);
983 /* FIXME: remove */ g_assert (handler->prev == NULL);
985 tmp = gtk_object_get_data (object, handler_key);
987 gtk_object_set_data (object, handler_key, handler);
991 if (tmp->signal_type < handler->signal_type)
995 tmp->prev->next = handler;
996 handler->prev = tmp->prev;
999 gtk_object_set_data (object, handler_key, handler);
1000 tmp->prev = handler;
1001 handler->next = tmp;
1007 tmp->next = handler;
1008 handler->prev = tmp;
1016 gtk_signal_real_emit (GtkObject *object,
1021 GtkHandler *handlers;
1022 GtkHandlerInfo info;
1023 guchar **signal_func_offset;
1024 GtkArg params[MAX_PARAMS];
1026 g_return_if_fail (object != NULL);
1027 g_return_if_fail (signal_type >= 1);
1029 signal = g_hash_table_lookup (signal_hash_table, &signal_type);
1030 g_return_if_fail (signal != NULL);
1031 g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object),
1032 signal->info.object_type));
1034 if ((signal->run_type & GTK_RUN_NO_RECURSE) &&
1035 gtk_emission_check (current_emissions, object, signal_type))
1037 gtk_emission_add (&restart_emissions, object, signal_type);
1041 gtk_params_get (params, signal->nparams, signal->params,
1042 signal->return_val, args);
1044 gtk_emission_add (¤t_emissions, object, signal_type);
1046 gtk_object_ref (object);
1049 if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_LAST && signal->function_offset != 0)
1051 signal_func_offset = (guchar**) ((guchar*) object->klass +
1052 signal->function_offset);
1053 if (*signal_func_offset)
1054 (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset,
1058 info.object = object;
1059 info.marshaller = signal->marshaller;
1060 info.params = params;
1061 info.param_types = signal->params;
1062 info.return_val = signal->return_val;
1063 info.nparams = signal->nparams;
1064 info.run_type = signal->run_type;
1065 info.signal_type = signal_type;
1067 handlers = gtk_signal_get_handlers (object, signal_type);
1068 switch (gtk_handlers_run (handlers, &info, FALSE))
1076 if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_FIRST && signal->function_offset != 0)
1078 signal_func_offset = (guchar**) ((guchar*) object->klass +
1079 signal->function_offset);
1080 if (*signal_func_offset)
1081 (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset,
1085 handlers = gtk_signal_get_handlers (object, signal_type);
1086 switch (gtk_handlers_run (handlers, &info, TRUE))
1096 gtk_emission_remove (¤t_emissions, object, signal_type);
1098 if (signal->run_type & GTK_RUN_NO_RECURSE)
1099 gtk_emission_remove (&restart_emissions, object, signal_type);
1101 gtk_object_unref (object);
1105 gtk_signal_get_handlers (GtkObject *object,
1108 GtkHandler *handlers;
1110 g_return_val_if_fail (object != NULL, NULL);
1111 g_return_val_if_fail (signal_type >= 1, NULL);
1113 handlers = gtk_object_get_data (object, handler_key);
1117 if (handlers->signal_type == signal_type)
1119 handlers = handlers->next;
1126 gtk_signal_handler_pending (GtkObject *object,
1128 gboolean may_be_blocked)
1130 GtkHandler *handlers;
1133 g_return_val_if_fail (object != NULL, 0);
1134 g_return_val_if_fail (signal_type >= 1, 0);
1136 handlers = gtk_signal_get_handlers (object, signal_type);
1139 while (handlers && handlers->signal_type == signal_type)
1141 if (handlers->id > 0 &&
1143 !handlers->blocked))
1145 handler_id = handlers->id;
1149 handlers = handlers->next;
1156 gtk_signal_connect_by_type (GtkObject *object,
1160 GtkSignalDestroy destroy_func,
1165 GtkObjectClass *class;
1166 GtkHandler *handler;
1169 g_return_val_if_fail (object != NULL, 0);
1170 g_return_val_if_fail (object->klass != NULL, 0);
1172 /* Search through the signals for this object and make
1173 * sure the one we are adding is valid. We need to perform
1174 * the lookup on the objects parents as well. If it isn't
1175 * valid then issue a warning and return.
1178 class = object->klass;
1182 gint *object_signals;
1186 object_signals = class->signals;
1187 nsignals = class->nsignals;
1189 for (i = 0; i < nsignals; i++)
1190 if (object_signals[i] == signal_type)
1196 parent = gtk_type_parent (class->type);
1198 class = gtk_type_class (parent);
1205 g_warning ("gtk_signal_connect_by_type(): could not find signal type (%d) in signal list of `%s'",
1207 gtk_type_name (class->type));
1211 handler = gtk_signal_handler_new ();
1212 handler->id = next_handler_id++;
1213 handler->signal_type = signal_type;
1214 handler->object_signal = object_signal;
1215 handler->func = func;
1216 handler->func_data = func_data;
1217 handler->destroy_func = destroy_func;
1218 handler->after = after != FALSE;
1219 handler->no_marshal = no_marshal;
1221 gtk_signal_handler_insert (object, handler);
1228 GtkEmission *emission;
1230 if (!emission_mem_chunk)
1231 emission_mem_chunk = g_mem_chunk_new ("emission mem chunk", sizeof (GtkEmission),
1232 1024, G_ALLOC_AND_FREE);
1234 emission = g_chunk_new (GtkEmission, emission_mem_chunk);
1236 emission->object = NULL;
1237 emission->signal_type = 0;
1243 gtk_emission_destroy (GtkEmission *emission)
1245 g_mem_chunk_free (emission_mem_chunk, emission);
1249 gtk_emission_add (GList **emissions,
1253 GtkEmission *emission;
1255 g_return_if_fail (emissions != NULL);
1256 g_return_if_fail (object != NULL);
1258 emission = gtk_emission_new ();
1259 emission->object = object;
1260 emission->signal_type = signal_type;
1262 *emissions = g_list_prepend (*emissions, emission);
1266 gtk_emission_remove (GList **emissions,
1270 GtkEmission *emission;
1273 g_return_if_fail (emissions != NULL);
1274 g_return_if_fail (object != NULL);
1279 emission = tmp->data;
1281 if ((emission->object == object) &&
1282 (emission->signal_type == signal_type))
1284 gtk_emission_destroy (emission);
1285 *emissions = g_list_remove_link (*emissions, tmp);
1295 gtk_emission_check (GList *emissions,
1299 GtkEmission *emission;
1302 g_return_val_if_fail (object != NULL, FALSE);
1307 emission = tmp->data;
1310 if ((emission->object == object) &&
1311 (emission->signal_type == signal_type))
1318 gtk_handlers_run (GtkHandler *handlers,
1319 GtkHandlerInfo *info,
1324 GtkHandler *handlers_next;
1326 gtk_signal_handler_ref (handlers);
1328 if (handlers->signal_type != info->signal_type)
1330 gtk_signal_handler_unref (handlers, info->object);
1334 if (!handlers->blocked && (handlers->after == after))
1338 if (handlers->no_marshal)
1339 (* (GtkCallbackMarshal)handlers->func) (info->object,
1340 handlers->func_data,
1343 else if (handlers->object_signal)
1344 (* info->marshaller) ((GtkObject*) handlers->func_data, /* don't GTK_OBJECT() cast */
1346 handlers->func_data,
1349 (* info->marshaller) (info->object,
1351 handlers->func_data,
1355 (* marshal) (info->object,
1356 handlers->func_data,
1362 if (gtk_emission_check (stop_emissions, info->object,
1365 gtk_emission_remove (&stop_emissions, info->object,
1368 if (info->run_type & GTK_RUN_NO_RECURSE)
1369 gtk_emission_remove (&restart_emissions, info->object,
1371 gtk_signal_handler_unref (handlers, info->object);
1374 else if ((info->run_type & GTK_RUN_NO_RECURSE) &&
1375 gtk_emission_check (restart_emissions, info->object,
1378 gtk_emission_remove (&restart_emissions, info->object,
1380 gtk_signal_handler_unref (handlers, info->object);
1385 handlers_next = handlers->next;
1386 gtk_signal_handler_unref (handlers, info->object);
1387 handlers = handlers_next;
1394 gtk_params_get (GtkArg *params,
1396 GtkType *param_types,
1402 for (i = 0; i < nparams; i++)
1404 params[i].type = param_types[i];
1405 params[i].name = NULL;
1407 switch (GTK_FUNDAMENTAL_TYPE (param_types[i]))
1409 case GTK_TYPE_INVALID:
1414 GTK_VALUE_CHAR(params[i]) = va_arg (args, gint);
1417 GTK_VALUE_BOOL(params[i]) = va_arg (args, gint);
1420 GTK_VALUE_INT(params[i]) = va_arg (args, gint);
1423 GTK_VALUE_UINT(params[i]) = va_arg (args, guint);
1426 GTK_VALUE_ENUM(params[i]) = va_arg (args, gint);
1428 case GTK_TYPE_FLAGS:
1429 GTK_VALUE_FLAGS(params[i]) = va_arg (args, gint);
1432 GTK_VALUE_LONG(params[i]) = va_arg (args, glong);
1434 case GTK_TYPE_ULONG:
1435 GTK_VALUE_ULONG(params[i]) = va_arg (args, gulong);
1437 case GTK_TYPE_FLOAT:
1438 GTK_VALUE_FLOAT(params[i]) = va_arg (args, gfloat);
1440 case GTK_TYPE_DOUBLE:
1441 GTK_VALUE_DOUBLE(params[i]) = va_arg (args, gdouble);
1443 case GTK_TYPE_STRING:
1444 GTK_VALUE_STRING(params[i]) = va_arg (args, gchar*);
1446 case GTK_TYPE_POINTER:
1447 GTK_VALUE_POINTER(params[i]) = va_arg (args, gpointer);
1449 case GTK_TYPE_BOXED:
1450 GTK_VALUE_BOXED(params[i]) = va_arg (args, gpointer);
1452 case GTK_TYPE_SIGNAL:
1453 GTK_VALUE_SIGNAL(params[i]).f = va_arg (args, GtkFunction);
1454 GTK_VALUE_SIGNAL(params[i]).d = va_arg (args, gpointer);
1456 case GTK_TYPE_FOREIGN:
1457 GTK_VALUE_FOREIGN(params[i]).data = va_arg (args, gpointer);
1458 GTK_VALUE_FOREIGN(params[i]).notify =
1459 va_arg (args, GtkDestroyNotify);
1461 case GTK_TYPE_CALLBACK:
1462 GTK_VALUE_CALLBACK(params[i]).marshal =
1463 va_arg (args, GtkCallbackMarshal);
1464 GTK_VALUE_CALLBACK(params[i]).data = va_arg (args, gpointer);
1465 GTK_VALUE_CALLBACK(params[i]).notify =
1466 va_arg (args, GtkDestroyNotify);
1468 case GTK_TYPE_C_CALLBACK:
1469 GTK_VALUE_C_CALLBACK(params[i]).func = va_arg (args, GtkFunction);
1470 GTK_VALUE_C_CALLBACK(params[i]).func_data = va_arg (args, gpointer);
1473 GTK_VALUE_ARGS(params[i]).n_args = va_arg (args, int);
1474 GTK_VALUE_ARGS(params[i]).args = va_arg (args, GtkArg*);
1476 case GTK_TYPE_OBJECT:
1477 GTK_VALUE_OBJECT(params[i]) = va_arg (args, GtkObject*);
1478 g_assert (GTK_VALUE_OBJECT(params[i]) == NULL ||
1479 GTK_CHECK_TYPE (GTK_VALUE_OBJECT(params[i]),
1483 g_error ("unsupported type %s in signal arg",
1484 gtk_type_name (params[i].type));
1489 params[i].type = return_val;
1490 params[i].name = NULL;
1492 switch (GTK_FUNDAMENTAL_TYPE (return_val))
1494 case GTK_TYPE_INVALID:
1499 params[i].d.pointer_data = va_arg (args, gchar*);
1502 params[i].d.pointer_data = va_arg (args, gint*);
1505 params[i].d.pointer_data = va_arg (args, gint*);
1508 params[i].d.pointer_data = va_arg (args, guint*);
1511 params[i].d.pointer_data = va_arg (args, gint*);
1513 case GTK_TYPE_FLAGS:
1514 params[i].d.pointer_data = va_arg (args, gint*);
1517 params[i].d.pointer_data = va_arg (args, glong*);
1519 case GTK_TYPE_ULONG:
1520 params[i].d.pointer_data = va_arg (args, gulong*);
1522 case GTK_TYPE_FLOAT:
1523 params[i].d.pointer_data = va_arg (args, gfloat*);
1525 case GTK_TYPE_DOUBLE:
1526 params[i].d.pointer_data = va_arg (args, gdouble*);
1528 case GTK_TYPE_STRING:
1529 params[i].d.pointer_data = va_arg (args, gchar**);
1531 case GTK_TYPE_POINTER:
1532 params[i].d.pointer_data = va_arg (args, gpointer*);
1534 case GTK_TYPE_BOXED:
1535 params[i].d.pointer_data = va_arg (args, gpointer*);
1537 case GTK_TYPE_OBJECT:
1538 params[i].d.pointer_data = va_arg (args, GtkObject**);
1540 case GTK_TYPE_SIGNAL:
1541 case GTK_TYPE_FOREIGN:
1542 case GTK_TYPE_CALLBACK:
1543 case GTK_TYPE_C_CALLBACK:
1546 g_error ("unsupported type %s in signal return",
1547 gtk_type_name (return_val));