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
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtksignal.h"
27 #define GTK_RUN_TYPE(x) ((x) & GTK_RUN_MASK)
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;
36 typedef void (*GtkSignalMarshaller0) (GtkObject *object,
49 guint function_offset;
50 GtkSignalRunType run_type;
51 GtkSignalMarshaller marshaller;
61 guint object_signal : 1;
68 GtkSignalDestroy destroy_func;
73 struct _GtkHandlerInfo
76 GtkSignalMarshaller marshaller;
80 GtkSignalRunType run_type;
92 static void gtk_signal_init (void);
93 static guint gtk_signal_hash (guint *key);
94 static gint gtk_signal_compare (guint *a,
96 static guint gtk_signal_info_hash (GtkSignalInfo *a);
97 static gint gtk_signal_info_compare (GtkSignalInfo *a,
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,
103 static void gtk_signal_handler_insert (GtkObject *object,
104 GtkHandler *handler);
105 static void gtk_signal_real_emit (GtkObject *object,
108 static GtkHandler* gtk_signal_get_handlers (GtkObject *object,
110 static guint gtk_signal_connect_by_type (GtkObject *object,
114 GtkSignalDestroy destroy_func,
118 static GtkEmission* gtk_emission_new (void);
119 static void gtk_emission_destroy (GtkEmission *emission);
120 static void gtk_emission_add (GList **emissions,
123 static void gtk_emission_remove (GList **emissions,
126 static gint gtk_emission_check (GList *emissions,
129 static gint gtk_handlers_run (GtkHandler *handlers,
130 GtkHandlerInfo *info,
132 static void gtk_params_get (GtkArg *params,
134 GtkType *param_types,
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;
145 static const gchar *handler_key = "gtk-signal-handlers";
146 static guint handler_key_id = 0;
148 static GMemChunk *handler_mem_chunk = NULL;
149 static GMemChunk *emission_mem_chunk = NULL;
151 static GList *current_emissions = NULL;
152 static GList *stop_emissions = NULL;
153 static GList *restart_emissions = NULL;
155 static GtkSignalMarshal global_marshaller = NULL;
156 static GtkSignalDestroy global_destroy_notify = NULL;
160 gtk_signal_new (const gchar *name,
161 GtkSignalRunType run_type,
163 guint function_offset,
164 GtkSignalMarshaller marshaller,
174 g_return_val_if_fail (nparams < 16, 0);
178 params = g_new (GtkType, nparams);
180 va_start (args, nparams);
182 for (i = 0; i < nparams; i++)
183 params[i] = va_arg (args, GtkType);
190 return_id = gtk_signal_newv (name,
205 gtk_signal_newv (const gchar *name,
206 GtkSignalRunType run_type,
208 guint function_offset,
209 GtkSignalMarshaller marshaller,
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);
223 g_return_val_if_fail (params != NULL, 0);
228 info.name = (char*)name;
229 info.object_type = object_type;
231 type = g_hash_table_lookup (signal_info_hash_table, &info);
234 g_warning ("gtk_signal_newv(): signal \"%s\" already exists in the `%s' class ancestry\n",
235 name, gtk_type_name (object_type));
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;
251 signal->params = g_new (GtkType, nparams);
253 for (i = 0; i < nparams; i++)
254 signal->params[i] = params[i];
257 signal->params = NULL;
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);
262 return signal->info.signal_type;
266 gtk_signal_query (guint signal_id)
268 GtkSignalQuery *query;
271 g_return_val_if_fail (signal_id >= 1, NULL);
273 signal = g_hash_table_lookup (signal_hash_table, &signal_id);
276 query = g_new (GtkSignalQuery, 1);
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;
294 gtk_signal_lookup (const gchar *name,
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);
305 info.name = (char*)name;
311 info.object_type = object_type;
313 type = g_hash_table_lookup (signal_info_hash_table, &info);
317 object_type = gtk_type_parent (object_type);
324 gtk_signal_name (guint signal_id)
328 g_return_val_if_fail (signal_id >= 1, NULL);
330 signal = g_hash_table_lookup (signal_hash_table, &signal_id);
332 return signal->info.name;
338 gtk_signal_emit (GtkObject *object,
344 g_return_if_fail (object != NULL);
345 g_return_if_fail (signal_id >= 1);
350 va_start (args, signal_id);
352 gtk_signal_real_emit (object, signal_id, args);
358 gtk_signal_emit_by_name (GtkObject *object,
365 g_return_if_fail (object != NULL);
366 g_return_if_fail (name != NULL);
371 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
375 va_start (args, name);
377 gtk_signal_real_emit (object, type, args);
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)));
389 gtk_signal_emit_stop (GtkObject *object,
392 g_return_if_fail (object != NULL);
393 g_return_if_fail (signal_id >= 1);
398 if (gtk_emission_check (current_emissions, object, signal_id))
399 gtk_emission_add (&stop_emissions, object, signal_id);
401 g_warning ("gtk_signal_emit_stop(): no current emission (%u) for object `%s'",
402 signal_id, gtk_type_name (GTK_OBJECT_TYPE (object)));
406 gtk_signal_emit_stop_by_name (GtkObject *object,
411 g_return_if_fail (object != NULL);
412 g_return_if_fail (name != NULL);
417 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
419 gtk_signal_emit_stop (object, type);
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)));
426 gtk_signal_n_emissions (GtkObject *object,
432 g_return_val_if_fail (object != NULL, 0);
433 g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
435 tmp = current_emissions;
439 GtkEmission *emission;
441 emission = tmp->data;
444 if ((emission->object == object) &&
445 (emission->signal_type == signal_id))
453 gtk_signal_n_emissions_by_name (GtkObject *object,
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);
466 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
468 n = gtk_signal_n_emissions (object, type);
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)));
480 gtk_signal_connect (GtkObject *object,
487 g_return_val_if_fail (object != NULL, 0);
488 g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
493 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
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)));
501 return gtk_signal_connect_by_type (object, type,
502 func, func_data, NULL,
503 FALSE, FALSE, FALSE);
507 gtk_signal_connect_after (GtkObject *object,
514 g_return_val_if_fail (object != NULL, 0);
519 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
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)));
527 return gtk_signal_connect_by_type (object, type,
528 func, func_data, NULL,
533 gtk_signal_connect_full (GtkObject *object,
536 GtkCallbackMarshal marshal,
538 GtkDestroyNotify destroy_func,
544 g_return_val_if_fail (object != NULL, 0);
549 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
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)));
558 return gtk_signal_connect_by_type (object, type, (GtkSignalFunc) marshal,
559 func_data, destroy_func,
560 object_signal, after, TRUE);
562 return gtk_signal_connect_by_type (object, type, func,
563 func_data, destroy_func,
564 object_signal, after, FALSE);
568 gtk_signal_connect_interp (GtkObject *object,
570 GtkCallbackMarshal func,
572 GtkDestroyNotify destroy_func,
575 return gtk_signal_connect_full (object, name, NULL, func,
576 func_data, destroy_func, FALSE, after);
580 gtk_signal_connect_object (GtkObject *object,
583 GtkObject *slot_object)
587 g_return_val_if_fail (object != NULL, 0);
588 /* slot_object needs to be treated as ordinary pointer */
593 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
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)));
601 return gtk_signal_connect_by_type (object, type,
602 func, slot_object, NULL,
607 gtk_signal_connect_object_after (GtkObject *object,
610 GtkObject *slot_object)
614 g_return_val_if_fail (object != NULL, 0);
619 type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
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)));
627 return gtk_signal_connect_by_type (object, type,
628 func, slot_object, NULL,
632 typedef struct _GtkDisconnectInfo GtkDisconnectInfo;
633 struct _GtkDisconnectInfo
636 guint disconnect_handler1;
637 guint signal_handler;
639 guint disconnect_handler2;
643 gtk_alive_disconnecter (GtkDisconnectInfo *info)
645 g_return_val_if_fail (info != NULL, 0);
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);
656 gtk_signal_connect_while_alive (GtkObject *object,
660 GtkObject *alive_object)
662 GtkDisconnectInfo *info;
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));
671 info = g_new (GtkDisconnectInfo, 1);
672 info->object1 = object;
673 info->object2 = alive_object;
675 info->signal_handler = gtk_signal_connect (object, signal, func, func_data);
676 info->disconnect_handler1 = gtk_signal_connect_object (info->object1,
678 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
680 info->disconnect_handler2 = gtk_signal_connect_object (info->object2,
682 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
687 gtk_signal_connect_object_while_alive (GtkObject *object,
690 GtkObject *alive_object)
692 GtkDisconnectInfo *info;
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));
701 info = g_new (GtkDisconnectInfo, 1);
702 info->object1 = object;
703 info->object2 = alive_object;
705 info->signal_handler = gtk_signal_connect_object (object, signal, func, alive_object);
706 info->disconnect_handler1 = gtk_signal_connect_object (info->object1,
708 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
710 info->disconnect_handler2 = gtk_signal_connect_object (info->object2,
712 GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
717 gtk_signal_disconnect (GtkObject *object,
722 g_return_if_fail (object != NULL);
723 g_return_if_fail (handler_id > 0);
725 handler = gtk_object_get_data_by_id (object, handler_key_id);
729 if (handler->id == handler_id)
732 handler->blocked += 1;
733 gtk_signal_handler_unref (handler, object);
736 handler = handler->next;
739 g_warning ("gtk_signal_disconnect(): could not find handler (%u)", handler_id);
743 gtk_signal_disconnect_by_func (GtkObject *object,
750 g_return_if_fail (object != NULL);
751 g_return_if_fail (func != NULL);
754 handler = gtk_object_get_data_by_id (object, handler_key_id);
758 GtkHandler *handler_next;
760 handler_next = handler->next;
761 if ((handler->id > 0) &&
762 (handler->func == func) &&
763 (handler->func_data == data))
767 handler->blocked += 1;
768 gtk_signal_handler_unref (handler, object);
770 handler = handler_next;
774 g_warning ("gtk_signal_disconnect_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
778 gtk_signal_disconnect_by_data (GtkObject *object,
784 g_return_if_fail (object != NULL);
787 handler = gtk_object_get_data_by_id (object, handler_key_id);
791 GtkHandler *handler_next;
793 handler_next = handler->next;
794 if ((handler->id > 0) &&
795 (handler->func_data == data))
799 handler->blocked += 1;
800 gtk_signal_handler_unref (handler, object);
802 handler = handler_next;
806 g_warning ("gtk_signal_disconnect_by_data(): could not find handler containing data (0x%0lX)", (long) data);
810 gtk_signal_handler_block (GtkObject *object,
815 g_return_if_fail (object != NULL);
816 g_return_if_fail (handler_id > 0);
818 handler = gtk_object_get_data_by_id (object, handler_key_id);
822 if (handler->id == handler_id)
824 handler->blocked += 1;
827 handler = handler->next;
830 g_warning ("gtk_signal_handler_block(): could not find handler (%u)", handler_id);
834 gtk_signal_handler_block_by_func (GtkObject *object,
841 g_return_if_fail (object != NULL);
842 g_return_if_fail (func != NULL);
845 handler = gtk_object_get_data_by_id (object, handler_key_id);
849 if ((handler->id > 0) &&
850 (handler->func == func) &&
851 (handler->func_data == data))
854 handler->blocked += 1;
856 handler = handler->next;
860 g_warning ("gtk_signal_handler_block_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
864 gtk_signal_handler_block_by_data (GtkObject *object,
870 g_return_if_fail (object != NULL);
873 handler = gtk_object_get_data_by_id (object, handler_key_id);
877 if ((handler->id > 0) &&
878 (handler->func_data == data))
881 handler->blocked += 1;
883 handler = handler->next;
887 g_warning ("gtk_signal_handler_block_by_data(): could not find handler containing data (0x%0lX)", (long) data);
891 gtk_signal_handler_unblock (GtkObject *object,
896 g_return_if_fail (object != NULL);
897 g_return_if_fail (handler_id > 0);
902 handler = gtk_object_get_data_by_id (object, handler_key_id);
906 if (handler->id == handler_id)
908 if (handler->blocked > 0)
909 handler->blocked -= 1;
911 g_warning ("gtk_signal_handler_unblock(): handler (%u) is not blocked", handler_id);
914 handler = handler->next;
917 g_warning ("gtk_signal_handler_unblock(): could not find handler (%u)", handler_id);
921 gtk_signal_handler_unblock_by_func (GtkObject *object,
928 g_return_if_fail (object != NULL);
929 g_return_if_fail (func != NULL);
932 handler = gtk_object_get_data_by_id (object, handler_key_id);
936 if ((handler->id > 0) &&
937 (handler->func == func) &&
938 (handler->func_data == data) &&
939 (handler->blocked > 0))
941 handler->blocked -= 1;
944 handler = handler->next;
948 g_warning ("gtk_signal_handler_unblock_by_func(): could not find blocked handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
952 gtk_signal_handler_unblock_by_data (GtkObject *object,
958 g_return_if_fail (object != NULL);
961 handler = gtk_object_get_data_by_id (object, handler_key_id);
965 if ((handler->id > 0) &&
966 (handler->func_data == data) &&
967 (handler->blocked > 0))
969 handler->blocked -= 1;
972 handler = handler->next;
976 g_warning ("gtk_signal_handler_unblock_by_data(): could not find blocked handler containing data (0x%0lX)", (long) data);
980 gtk_signal_handlers_destroy (GtkObject *object)
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
989 handler = gtk_object_get_data_by_id (object, handler_key_id);
992 handler = handler->next;
997 next = handler->next;
998 gtk_signal_handler_unref (handler, object);
1001 handler = gtk_object_get_data_by_id (object, handler_key_id);
1002 gtk_signal_handler_unref (handler, object);
1007 gtk_signal_default_marshaller (GtkObject *object,
1012 GtkSignalMarshaller0 rfunc;
1014 rfunc = (GtkSignalMarshaller0) func;
1016 (* rfunc) (object, func_data);
1020 gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
1021 GtkSignalDestroy destroy_func)
1023 global_marshaller = marshal_func;
1024 global_destroy_notify = destroy_func;
1029 gtk_signal_init (void)
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);
1042 gtk_signal_hash (guint *key)
1048 gtk_signal_compare (guint *a,
1055 gtk_signal_info_hash (GtkSignalInfo *a)
1057 return (g_str_hash (a->name) + a->object_type);
1061 gtk_signal_info_compare (GtkSignalInfo *a,
1064 return ((a->object_type == b->object_type) &&
1065 g_str_equal (a->name, b->name));
1069 gtk_signal_handler_new (void)
1071 GtkHandler *handler;
1073 if (!handler_mem_chunk)
1074 handler_mem_chunk = g_mem_chunk_new ("handler mem chunk", sizeof (GtkHandler),
1075 1024, G_ALLOC_AND_FREE);
1077 handler = g_chunk_new (GtkHandler, handler_mem_chunk);
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;
1096 gtk_signal_handler_ref (GtkHandler *handler)
1098 handler->ref_count += 1;
1102 gtk_signal_handler_unref (GtkHandler *handler,
1105 handler->ref_count -= 1;
1106 if (handler->ref_count == 0)
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);
1114 handler->prev->next = handler->next;
1116 gtk_object_set_data_by_id (object, handler_key_id, handler->next);
1118 handler->next->prev = handler->prev;
1120 g_mem_chunk_free (handler_mem_chunk, handler);
1125 gtk_signal_handler_insert (GtkObject *object,
1126 GtkHandler *handler)
1130 /* FIXME: remove */ g_assert (handler->next == NULL);
1131 /* FIXME: remove */ g_assert (handler->prev == NULL);
1133 tmp = gtk_object_get_data_by_id (object, handler_key_id);
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);
1143 if (tmp->signal_type < handler->signal_type)
1147 tmp->prev->next = handler;
1148 handler->prev = tmp->prev;
1151 gtk_object_set_data_by_id (object, handler_key_id, handler);
1152 tmp->prev = handler;
1153 handler->next = tmp;
1159 tmp->next = handler;
1160 handler->prev = tmp;
1168 gtk_signal_real_emit (GtkObject *object,
1173 GtkHandler *handlers;
1174 GtkHandlerInfo info;
1175 guchar **signal_func_offset;
1176 GtkArg params[MAX_PARAMS];
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));
1183 if ((signal->run_type & GTK_RUN_NO_RECURSE) &&
1184 gtk_emission_check (current_emissions, object, signal_type))
1186 gtk_emission_add (&restart_emissions, object, signal_type);
1190 gtk_params_get (params, signal->nparams, signal->params,
1191 signal->return_val, args);
1193 gtk_emission_add (¤t_emissions, object, signal_type);
1195 gtk_object_ref (object);
1198 if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_LAST && signal->function_offset != 0)
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,
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;
1216 handlers = gtk_signal_get_handlers (object, signal_type);
1217 switch (gtk_handlers_run (handlers, &info, FALSE))
1225 if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_FIRST && signal->function_offset != 0)
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,
1234 handlers = gtk_signal_get_handlers (object, signal_type);
1235 switch (gtk_handlers_run (handlers, &info, TRUE))
1245 gtk_emission_remove (¤t_emissions, object, signal_type);
1247 if (signal->run_type & GTK_RUN_NO_RECURSE)
1248 gtk_emission_remove (&restart_emissions, object, signal_type);
1250 gtk_object_unref (object);
1254 gtk_signal_get_handlers (GtkObject *object,
1257 GtkHandler *handlers;
1259 g_return_val_if_fail (object != NULL, NULL);
1260 g_return_val_if_fail (signal_type >= 1, NULL);
1262 handlers = gtk_object_get_data_by_id (object, handler_key_id);
1266 if (handlers->signal_type == signal_type)
1268 handlers = handlers->next;
1275 gtk_signal_handler_pending (GtkObject *object,
1277 gboolean may_be_blocked)
1279 GtkHandler *handlers;
1282 g_return_val_if_fail (object != NULL, 0);
1283 g_return_val_if_fail (signal_id >= 1, 0);
1285 handlers = gtk_signal_get_handlers (object, signal_id);
1288 while (handlers && handlers->signal_type == signal_id)
1290 if (handlers->id > 0 &&
1291 (may_be_blocked || handlers->blocked == 0))
1293 handler_id = handlers->id;
1297 handlers = handlers->next;
1304 gtk_signal_connect_by_type (GtkObject *object,
1308 GtkSignalDestroy destroy_func,
1313 GtkObjectClass *class;
1314 GtkHandler *handler;
1317 g_return_val_if_fail (object != NULL, 0);
1318 g_return_val_if_fail (object->klass != NULL, 0);
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.
1326 class = object->klass;
1330 guint *object_signals;
1334 object_signals = class->signals;
1335 nsignals = class->nsignals;
1337 for (i = 0; i < nsignals; i++)
1338 if (object_signals[i] == signal_type)
1344 parent = gtk_type_parent (class->type);
1346 class = gtk_type_class (parent);
1353 g_warning ("gtk_signal_connect_by_type(): could not find signal id (%u) in the `%s' class ancestry",
1355 gtk_type_name (class->type));
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;
1369 gtk_signal_handler_insert (object, handler);
1374 gtk_emission_new (void)
1376 GtkEmission *emission;
1378 if (!emission_mem_chunk)
1379 emission_mem_chunk = g_mem_chunk_new ("emission mem chunk", sizeof (GtkEmission),
1380 1024, G_ALLOC_AND_FREE);
1382 emission = g_chunk_new (GtkEmission, emission_mem_chunk);
1384 emission->object = NULL;
1385 emission->signal_type = 0;
1391 gtk_emission_destroy (GtkEmission *emission)
1393 g_mem_chunk_free (emission_mem_chunk, emission);
1397 gtk_emission_add (GList **emissions,
1401 GtkEmission *emission;
1403 g_return_if_fail (emissions != NULL);
1404 g_return_if_fail (object != NULL);
1406 emission = gtk_emission_new ();
1407 emission->object = object;
1408 emission->signal_type = signal_type;
1410 *emissions = g_list_prepend (*emissions, emission);
1414 gtk_emission_remove (GList **emissions,
1418 GtkEmission *emission;
1421 g_return_if_fail (emissions != NULL);
1426 emission = tmp->data;
1428 if ((emission->object == object) &&
1429 (emission->signal_type == signal_type))
1431 gtk_emission_destroy (emission);
1432 *emissions = g_list_remove_link (*emissions, tmp);
1442 gtk_emission_check (GList *emissions,
1446 GtkEmission *emission;
1452 emission = tmp->data;
1455 if ((emission->object == object) &&
1456 (emission->signal_type == signal_type))
1463 gtk_handlers_run (GtkHandler *handlers,
1464 GtkHandlerInfo *info,
1467 while (handlers && handlers->signal_type == info->signal_type)
1469 GtkHandler *handlers_next;
1471 gtk_signal_handler_ref (handlers);
1473 if (handlers->blocked == 0 && (handlers->after == after))
1477 if (handlers->no_marshal)
1478 (* (GtkCallbackMarshal) handlers->func) (info->object,
1479 handlers->func_data,
1482 else if (handlers->object_signal)
1483 (* info->marshaller) ((GtkObject*) handlers->func_data, /* don't GTK_OBJECT() cast */
1485 handlers->func_data,
1488 (* info->marshaller) (info->object,
1490 handlers->func_data,
1493 else if (global_marshaller)
1494 (* global_marshaller) (info->object,
1495 handlers->func_data,
1501 if (gtk_emission_check (stop_emissions, info->object,
1504 gtk_emission_remove (&stop_emissions, info->object,
1507 if (info->run_type & GTK_RUN_NO_RECURSE)
1508 gtk_emission_remove (&restart_emissions, info->object,
1510 gtk_signal_handler_unref (handlers, info->object);
1513 else if ((info->run_type & GTK_RUN_NO_RECURSE) &&
1514 gtk_emission_check (restart_emissions, info->object,
1517 gtk_emission_remove (&restart_emissions, info->object,
1519 gtk_signal_handler_unref (handlers, info->object);
1524 handlers_next = handlers->next;
1525 gtk_signal_handler_unref (handlers, info->object);
1526 handlers = handlers_next;
1533 gtk_params_get (GtkArg *params,
1535 GtkType *param_types,
1541 for (i = 0; i < nparams; i++)
1543 params[i].type = param_types[i];
1544 params[i].name = NULL;
1546 switch (GTK_FUNDAMENTAL_TYPE (param_types[i]))
1548 case GTK_TYPE_INVALID:
1553 GTK_VALUE_CHAR(params[i]) = va_arg (args, gint);
1556 GTK_VALUE_BOOL(params[i]) = va_arg (args, gint);
1559 GTK_VALUE_INT(params[i]) = va_arg (args, gint);
1562 GTK_VALUE_UINT(params[i]) = va_arg (args, guint);
1565 GTK_VALUE_ENUM(params[i]) = va_arg (args, gint);
1567 case GTK_TYPE_FLAGS:
1568 GTK_VALUE_FLAGS(params[i]) = va_arg (args, gint);
1571 GTK_VALUE_LONG(params[i]) = va_arg (args, glong);
1573 case GTK_TYPE_ULONG:
1574 GTK_VALUE_ULONG(params[i]) = va_arg (args, gulong);
1576 case GTK_TYPE_FLOAT:
1577 GTK_VALUE_FLOAT(params[i]) = va_arg (args, gfloat);
1579 case GTK_TYPE_DOUBLE:
1580 GTK_VALUE_DOUBLE(params[i]) = va_arg (args, gdouble);
1582 case GTK_TYPE_STRING:
1583 GTK_VALUE_STRING(params[i]) = va_arg (args, gchar*);
1585 case GTK_TYPE_POINTER:
1586 GTK_VALUE_POINTER(params[i]) = va_arg (args, gpointer);
1588 case GTK_TYPE_BOXED:
1589 GTK_VALUE_BOXED(params[i]) = va_arg (args, gpointer);
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);
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);
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);
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);
1612 GTK_VALUE_ARGS(params[i]).n_args = va_arg (args, gint);
1613 GTK_VALUE_ARGS(params[i]).args = va_arg (args, GtkArg*);
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));
1624 g_error ("unsupported type `%s' in signal arg",
1625 gtk_type_name (params[i].type));
1630 params[i].type = return_val;
1631 params[i].name = NULL;
1633 switch (GTK_FUNDAMENTAL_TYPE (return_val))
1635 case GTK_TYPE_INVALID:
1640 params[i].d.pointer_data = va_arg (args, gchar*);
1643 params[i].d.pointer_data = va_arg (args, gint*);
1646 params[i].d.pointer_data = va_arg (args, gint*);
1649 params[i].d.pointer_data = va_arg (args, guint*);
1652 params[i].d.pointer_data = va_arg (args, gint*);
1654 case GTK_TYPE_FLAGS:
1655 params[i].d.pointer_data = va_arg (args, gint*);
1658 params[i].d.pointer_data = va_arg (args, glong*);
1660 case GTK_TYPE_ULONG:
1661 params[i].d.pointer_data = va_arg (args, gulong*);
1663 case GTK_TYPE_FLOAT:
1664 params[i].d.pointer_data = va_arg (args, gfloat*);
1666 case GTK_TYPE_DOUBLE:
1667 params[i].d.pointer_data = va_arg (args, gdouble*);
1669 case GTK_TYPE_STRING:
1670 params[i].d.pointer_data = va_arg (args, gchar**);
1672 case GTK_TYPE_POINTER:
1673 params[i].d.pointer_data = va_arg (args, gpointer*);
1675 case GTK_TYPE_BOXED:
1676 params[i].d.pointer_data = va_arg (args, gpointer*);
1678 case GTK_TYPE_OBJECT:
1679 params[i].d.pointer_data = va_arg (args, GtkObject**);
1681 case GTK_TYPE_SIGNAL:
1682 case GTK_TYPE_FOREIGN:
1683 case GTK_TYPE_CALLBACK:
1684 case GTK_TYPE_C_CALLBACK:
1687 g_error ("unsupported type `%s' in signal return",
1688 gtk_type_name (return_val));