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.
23 #include "gtkobject.h"
24 #include "gtksignal.h"
27 #define GTK_OBJECT_DATA_ID_BLOCK_SIZE (1024)
28 #define GTK_OBJECT_DATA_BLOCK_SIZE (1024)
42 typedef struct _GtkObjectData GtkObjectData;
43 typedef struct _GtkArgInfo GtkArgInfo;
49 GtkDestroyNotify destroy;
64 static void gtk_object_class_init (GtkObjectClass *klass);
65 static void gtk_object_init (GtkObject *object);
66 static void gtk_object_set_arg (GtkObject *object,
69 static void gtk_object_get_arg (GtkObject *object,
72 static void gtk_object_shutdown (GtkObject *object);
73 static void gtk_object_real_destroy (GtkObject *object);
74 static void gtk_object_finalize (GtkObject *object);
75 static void gtk_object_notify_weaks (GtkObject *object);
77 GtkArg* gtk_object_collect_args (guint *nargs,
81 static guint object_signals[LAST_SIGNAL] = { 0 };
83 static GHashTable *arg_info_ht = NULL;
85 static const gchar *user_data_key = "user_data";
86 static guint user_data_key_id = 0;
87 static const gchar *weakrefs_key = "gtk-weakrefs";
88 static guint weakrefs_key_id = 0;
90 static GtkObjectData *gtk_object_data_free_list = NULL;
92 #define GTK_OBJECT_DATA_DESTROY( odata ) { \
94 odata->destroy (odata->data); \
95 odata->next = gtk_object_data_free_list; \
96 gtk_object_data_free_list = odata; \
100 #ifdef G_ENABLE_DEBUG
101 static guint obj_count = 0;
102 static GHashTable *living_objs_ht = NULL;
104 gtk_object_debug_foreach (gpointer key, gpointer value, gpointer user_data)
108 object = (GtkObject*) value;
109 g_print ("GTK-DEBUG: %p: %s ref_count=%d%s%s\n",
111 gtk_type_name (GTK_OBJECT_TYPE (object)),
113 GTK_OBJECT_FLOATING (object) ? " (floating)" : "",
114 GTK_OBJECT_DESTROYED (object) ? " (destroyed)" : "");
117 gtk_object_debug (void)
119 g_hash_table_foreach (living_objs_ht, gtk_object_debug_foreach, NULL);
121 g_print ("GTK-DEBUG: living objects count = %d\n", obj_count);
124 gtk_object_pointer_hash (const gpointer v)
132 #endif /* G_ENABLE_DEBUG */
134 /****************************************************
135 * GtkObject type, class and instance initialization
137 ****************************************************/
140 gtk_object_init_type (void)
142 GtkType object_type = 0;
143 GtkTypeInfo object_info =
147 sizeof (GtkObjectClass),
148 (GtkClassInitFunc) gtk_object_class_init,
149 (GtkObjectInitFunc) gtk_object_init,
154 object_type = gtk_type_unique (0, &object_info);
155 g_assert (object_type == GTK_TYPE_OBJECT);
157 #ifdef G_ENABLE_DEBUG
158 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
159 ATEXIT (gtk_object_debug);
160 #endif /* G_ENABLE_DEBUG */
164 gtk_object_get_type (void)
166 return GTK_TYPE_OBJECT;
170 gtk_object_class_init (GtkObjectClass *class)
172 class->signals = NULL;
176 gtk_object_add_arg_type ("GtkObject::user_data",
180 gtk_object_add_arg_type ("GtkObject::signal",
184 gtk_object_add_arg_type ("GtkObject::object_signal",
189 object_signals[DESTROY] =
190 gtk_signal_new ("destroy",
193 GTK_SIGNAL_OFFSET (GtkObjectClass, destroy),
194 gtk_signal_default_marshaller,
197 gtk_object_class_add_signals (class, object_signals, LAST_SIGNAL);
199 class->shutdown = gtk_object_shutdown;
200 class->destroy = gtk_object_real_destroy;
201 class->finalize = gtk_object_finalize;
205 gtk_object_init (GtkObject *object)
207 GTK_OBJECT_FLAGS (object) = GTK_FLOATING;
209 object->ref_count = 1;
210 object->object_data = NULL;
212 #ifdef G_ENABLE_DEBUG
213 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
218 living_objs_ht = g_hash_table_new (gtk_object_pointer_hash, NULL);
220 g_hash_table_insert (living_objs_ht, object, object);
222 #endif /* G_ENABLE_DEBUG */
225 /********************************************
226 * Functions to end a GtkObject's life time
228 ********************************************/
230 gtk_object_destroy (GtkObject *object)
232 g_return_if_fail (object != NULL);
233 g_return_if_fail (GTK_IS_OBJECT (object));
235 if (!GTK_OBJECT_DESTROYED (object))
237 /* we will hold a reference on the object in this place, so
238 * to ease all classes shutdown and destroy implementations.
239 * i.e. they don't have to bother about referencing at all.
241 gtk_object_ref (object);
242 object->klass->shutdown (object);
243 gtk_object_unref (object);
248 gtk_object_shutdown (GtkObject *object)
250 GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
251 gtk_signal_emit (object, object_signals[DESTROY]);
255 gtk_object_real_destroy (GtkObject *object)
257 if (GTK_OBJECT_CONNECTED (object))
258 gtk_signal_handlers_destroy (object);
262 gtk_object_finalize (GtkObject *object)
264 gtk_object_notify_weaks (object);
266 while (object->object_data)
268 GtkObjectData *odata;
270 odata = object->object_data;
271 object->object_data = odata->next;
272 GTK_OBJECT_DATA_DESTROY (odata);
278 /*****************************************
279 * GtkObject argument handlers
281 *****************************************/
284 gtk_object_set_arg (GtkObject *object,
291 gtk_object_set_user_data (object, GTK_VALUE_POINTER (*arg));
294 if ((arg->name[9 + 2 + 6] != ':') || (arg->name[9 + 2 + 7] != ':'))
296 g_warning ("invalid signal argument: \"%s\"\n", arg->name);
297 arg->type = GTK_TYPE_INVALID;
300 gtk_signal_connect (object, arg->name + 9 + 2 + 6 + 2,
301 (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
302 GTK_VALUE_SIGNAL (*arg).d);
304 case ARG_OBJECT_SIGNAL:
305 if ((arg->name[9 + 2 + 13] != ':') || (arg->name[9 + 2 + 14] != ':'))
307 g_warning ("invalid signal argument: \"%s\"\n", arg->name);
308 arg->type = GTK_TYPE_INVALID;
311 gtk_signal_connect_object (object, arg->name + 9 + 2 + 13 + 2,
312 (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
313 (GtkObject*) GTK_VALUE_SIGNAL (*arg).d);
316 arg->type = GTK_TYPE_INVALID;
322 gtk_object_get_arg (GtkObject *object,
329 GTK_VALUE_POINTER (*arg) = gtk_object_get_user_data (object);
332 case ARG_OBJECT_SIGNAL:
334 arg->type = GTK_TYPE_INVALID;
339 /*****************************************
340 * gtk_object_class_add_signals:
345 *****************************************/
348 gtk_object_class_add_signals (GtkObjectClass *class,
355 g_return_if_fail (class != NULL);
357 new_signals = g_new (guint, class->nsignals + nsignals);
358 for (i = 0; i < class->nsignals; i++)
359 new_signals[i] = class->signals[i];
360 for (i = 0; i < nsignals; i++)
361 new_signals[class->nsignals + i] = signals[i];
363 g_free (class->signals);
364 class->signals = new_signals;
365 class->nsignals += nsignals;
368 /*****************************************
369 * gtk_object_class_add_user_signal:
374 *****************************************/
377 gtk_object_class_add_user_signal (GtkObjectClass *class,
379 GtkSignalMarshaller marshaller,
389 g_return_val_if_fail (class != NULL, 0);
393 params = g_new (GtkType, nparams);
395 va_start (args, nparams);
397 for (i = 0; i < nparams; i++)
398 params[i] = va_arg (args, GtkType);
405 signal_id = gtk_signal_newv (name,
417 gtk_object_class_add_signals (class, &signal_id, 1);
422 /*****************************************
428 *****************************************/
431 gtk_object_sink (GtkObject *object)
433 g_return_if_fail (object != NULL);
434 g_return_if_fail (GTK_IS_OBJECT (object));
436 if (GTK_OBJECT_FLOATING (object))
438 GTK_OBJECT_UNSET_FLAGS (object, GTK_FLOATING);
439 gtk_object_unref (object);
443 /*****************************************
446 * Weak refs are very similar to the old "destroy" signal. They allow
447 * one to register a callback that is called when the weakly
448 * referenced object is finalized.
450 * They are not implemented as a signal because they really are
451 * special and need to be used with great care. Unlike signals, which
452 * should be able to execute any code whatsoever.
454 * A weakref callback is not allowed to retain a reference to the
455 * object. Object data keys may be retrieved in a weak reference
458 * A weakref callback is called at most once.
460 *****************************************/
462 typedef struct _GtkWeakRef GtkWeakRef;
467 GtkDestroyNotify notify;
472 gtk_object_weakref (GtkObject *object,
473 GtkDestroyNotify notify,
478 g_return_if_fail (object != NULL);
479 g_return_if_fail (notify != NULL);
480 g_return_if_fail (GTK_IS_OBJECT (object));
482 if (!weakrefs_key_id)
483 weakrefs_key_id = gtk_object_data_force_id (weakrefs_key);
485 weak = g_new (GtkWeakRef, 1);
486 weak->next = gtk_object_get_data_by_id (object, weakrefs_key_id);
487 weak->notify = notify;
489 gtk_object_set_data_by_id (object, weakrefs_key_id, weak);
493 gtk_object_weakunref (GtkObject *object,
494 GtkDestroyNotify notify,
497 GtkWeakRef *weaks, *w, **wp;
499 g_return_if_fail (object != NULL);
500 g_return_if_fail (GTK_IS_OBJECT (object));
502 if (!weakrefs_key_id)
505 weaks = gtk_object_get_data_by_id (object, weakrefs_key_id);
506 for (wp = &weaks; *wp; wp = &(*wp)->next)
509 if (w->notify == notify && w->data == data)
512 gtk_object_set_data_by_id (object, weakrefs_key_id, w->next);
522 gtk_object_notify_weaks (GtkObject *object)
528 w1 = gtk_object_get_data_by_id (object, weakrefs_key_id);
532 w1->notify (w1->data);
540 /*****************************************
546 *****************************************/
549 gtk_object_new (GtkType type,
558 obj = gtk_type_new (type);
560 va_start (args1, type);
561 va_start (args2, type);
563 args = gtk_object_collect_args (&nargs, args1, args2);
564 gtk_object_setv (obj, nargs, args);
573 /*****************************************
579 *****************************************/
582 gtk_object_newv (GtkType type,
588 obj = gtk_type_new (type);
589 gtk_object_setv (obj, nargs, args);
594 /*****************************************
600 *****************************************/
603 gtk_object_getv (GtkObject *object,
609 g_return_if_fail (object != NULL);
610 g_return_if_fail (GTK_IS_OBJECT (object));
615 for (i = 0; i < nargs; i++)
622 /* hm, the name cutting shouldn't be needed on gets, but what the heck...
624 lookup_name = g_strdup (args[i].name);
625 d = strchr (lookup_name, ':');
626 if (d && d[1] == ':')
628 d = strchr (d + 2, ':');
632 info = g_hash_table_lookup (arg_info_ht, lookup_name);
639 g_warning ("invalid arg name: \"%s\"\n", lookup_name);
640 args[i].type = GTK_TYPE_INVALID;
641 g_free (lookup_name);
644 else if (!gtk_type_is_a (object->klass->type, info->class_type))
646 g_warning ("invalid arg for %s: \"%s\"\n", gtk_type_name (object->klass->type), lookup_name);
647 args[i].type = GTK_TYPE_INVALID;
648 g_free (lookup_name);
651 else if (! (info->arg_flags & GTK_ARG_READABLE))
653 g_warning ("arg is not supplied for read-access: \"%s\"\n", lookup_name);
654 args[i].type = GTK_TYPE_INVALID;
655 g_free (lookup_name);
659 g_free (lookup_name);
661 args[i].type = info->type;
662 gtk_type_get_arg (object, info->class_type, &args[i], info->arg_id);
666 /*****************************************
667 * gtk_object_query_args:
672 *****************************************/
674 struct _GtkQueryArgData
679 typedef struct _GtkQueryArgData GtkQueryArgData;
682 gtk_query_arg_foreach (gpointer key,
686 register GtkArgInfo *info;
687 register GtkQueryArgData *data;
692 if (info->class_type == data->class_type)
693 data->arg_list = g_list_prepend (data->arg_list, info);
697 gtk_object_query_args (GtkType class_type,
702 GtkQueryArgData query_data;
706 g_return_val_if_fail (nargs != NULL, NULL);
708 g_return_val_if_fail (gtk_type_is_a (class_type, gtk_object_get_type ()), NULL);
713 /* make sure the types class has been initialized, because
714 * the argument setup happens in the gtk_*_class_init() functions.
716 gtk_type_class (class_type);
718 query_data.arg_list = NULL;
719 query_data.class_type = class_type;
720 g_hash_table_foreach (arg_info_ht, gtk_query_arg_foreach, &query_data);
722 if (query_data.arg_list)
724 register GList *list;
727 list = query_data.arg_list;
734 g_assert (len == ((GtkObjectClass*) gtk_type_class (class_type))->n_args); /* paranoid */
736 args = g_new0 (GtkArg, len);
739 *arg_flags = g_new (guint32, len);
748 g_assert (info->seq_id > 0 && info->seq_id <= len); /* paranoid */
750 args[info->seq_id - 1].type = info->type;
751 args[info->seq_id - 1].name = info->name;
753 (*arg_flags)[info->seq_id - 1] = info->arg_flags;
757 g_list_free (query_data.arg_list);
765 /*****************************************
771 *****************************************/
774 gtk_object_set (GtkObject *object,
782 g_return_if_fail (object != NULL);
784 va_start (args1, object);
785 va_start (args2, object);
787 args = gtk_object_collect_args (&nargs, args1, args2);
788 gtk_object_setv (object, nargs, args);
795 /*****************************************
801 *****************************************/
804 gtk_object_setv (GtkObject *object,
810 g_return_if_fail (object != NULL);
811 g_return_if_fail (GTK_OBJECT (object));
816 for (i = 0; i < nargs; i++)
823 lookup_name = g_strdup (args[i].name);
824 d = strchr (lookup_name, ':');
825 if (d && d[1] == ':')
827 d = strchr (d + 2, ':');
831 info = g_hash_table_lookup (arg_info_ht, lookup_name);
840 g_warning ("invalid arg name: \"%s\"\n", lookup_name);
843 else if (info->type != args[i].type)
845 g_warning ("invalid arg type for: \"%s\"\n", lookup_name);
848 else if (!gtk_type_is_a (object->klass->type, info->class_type))
850 g_warning ("invalid arg for %s: \"%s\"\n", gtk_type_name (object->klass->type), lookup_name);
853 else if (! (info->arg_flags & GTK_ARG_WRITABLE))
855 g_warning ("arg is not supplied for write-access: \"%s\"\n", lookup_name);
859 g_free (lookup_name);
864 gtk_type_set_arg (object, info->class_type, &args[i], info->arg_id);
868 /*****************************************
869 * gtk_object_add_arg_type:
874 *****************************************/
877 gtk_object_add_arg_type (const char *arg_name,
883 gchar class_part[1024];
887 g_return_if_fail (arg_name != NULL);
888 g_return_if_fail (arg_type > GTK_TYPE_NONE);
889 g_return_if_fail (arg_id > 0);
890 g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) != 0);
892 arg_part = strchr (arg_name, ':');
893 if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':'))
895 g_warning ("invalid arg name: \"%s\"\n", arg_name);
899 strncpy (class_part, arg_name, (glong) (arg_part - arg_name));
900 class_part[(glong) (arg_part - arg_name)] = '\0';
902 class_type = gtk_type_from_name (class_part);
905 g_warning ("invalid class name in arg: \"%s\"\n", arg_name);
909 info = g_new (GtkArgInfo, 1);
910 info->name = g_strdup (arg_name);
911 info->type = arg_type;
912 info->class_type = class_type;
913 info->arg_flags = arg_flags & (GTK_ARG_READABLE | GTK_ARG_WRITABLE);
914 info->arg_id = arg_id;
915 info->seq_id = ++((GtkObjectClass*) gtk_type_class (class_type))->n_args;
918 arg_info_ht = g_hash_table_new (g_str_hash, g_str_equal);
920 g_hash_table_insert (arg_info_ht, info->name, info);
923 /*****************************************
924 * gtk_object_get_arg_type:
929 *****************************************/
932 gtk_object_get_arg_type (const gchar *arg_name)
938 g_return_val_if_fail (arg_name != NULL, 0);
941 return GTK_TYPE_INVALID;
943 if (!arg_name || strlen (arg_name) > 1000)
947 g_warning ("gtk_object_get_arg_type(): argument `arg_name' exceeds maximum size.");
951 t = strchr (arg_name, ':');
952 if (!t || (t[0] != ':') || (t[1] != ':'))
954 g_warning ("invalid arg name: \"%s\"\n", arg_name);
955 return GTK_TYPE_INVALID;
958 t = strchr (t + 2, ':');
961 strncpy (buffer, arg_name, (long) (t - arg_name));
962 buffer[(long) (t - arg_name)] = '\0';
966 info = g_hash_table_lookup (arg_info_ht, (gpointer) arg_name);
970 return GTK_TYPE_INVALID;
973 /*****************************************
974 * GtkObject object_data mechanism
976 *****************************************/
979 gtk_object_set_data_by_id (GtkObject *object,
983 g_return_if_fail (data_id > 0);
985 gtk_object_set_data_by_id_full (object, data_id, data, NULL);
989 gtk_object_set_data (GtkObject *object,
993 g_return_if_fail (key != NULL);
995 gtk_object_set_data_by_id_full (object, gtk_object_data_force_id (key), data, NULL);
999 gtk_object_set_data_by_id_full (GtkObject *object,
1002 GtkDestroyNotify destroy)
1004 GtkObjectData *odata;
1006 g_return_if_fail (object != NULL);
1007 g_return_if_fail (GTK_IS_OBJECT (object));
1008 g_return_if_fail (data_id > 0);
1010 odata = object->object_data;
1013 GtkObjectData *prev;
1019 if (odata->id == data_id)
1022 prev->next = odata->next;
1024 object->object_data = odata->next;
1026 GTK_OBJECT_DATA_DESTROY (odata);
1031 odata = odata->next;
1036 GtkObjectData *prev;
1042 if (odata->id == data_id)
1044 /* we need to be unlinked while invoking the destroy function
1049 prev->next = odata->next;
1051 object->object_data = odata->next;
1053 odata->destroy (odata->data);
1055 odata->next = object->object_data;
1056 object->object_data = odata;
1060 odata->destroy = destroy;
1068 if (gtk_object_data_free_list)
1070 odata = gtk_object_data_free_list;
1071 gtk_object_data_free_list = odata->next;
1075 GtkObjectData *odata_block;
1078 odata_block = g_new0 (GtkObjectData, GTK_OBJECT_DATA_BLOCK_SIZE);
1079 for (i = 1; i < GTK_OBJECT_DATA_BLOCK_SIZE; i++)
1081 (odata_block + i)->next = gtk_object_data_free_list;
1082 gtk_object_data_free_list = (odata_block + i);
1085 odata = odata_block;
1088 odata->id = data_id;
1090 odata->destroy = destroy;
1091 odata->next = object->object_data;
1093 object->object_data = odata;
1098 gtk_object_set_data_full (GtkObject *object,
1101 GtkDestroyNotify destroy)
1103 g_return_if_fail (key != NULL);
1105 gtk_object_set_data_by_id_full (object, gtk_object_data_force_id (key), data, destroy);
1109 gtk_object_get_data_by_id (GtkObject *object,
1112 GtkObjectData *odata;
1114 g_return_val_if_fail (object != NULL, NULL);
1115 g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
1119 odata = object->object_data;
1122 if (odata->id == data_id)
1124 odata = odata->next;
1132 gtk_object_get_data (GtkObject *object,
1137 g_return_val_if_fail (key != NULL, NULL);
1139 id = gtk_object_data_try_key (key);
1141 return gtk_object_get_data_by_id (object, id);
1147 gtk_object_remove_data_by_id (GtkObject *object,
1151 gtk_object_set_data_by_id_full (object, data_id, NULL, NULL);
1155 gtk_object_remove_data (GtkObject *object,
1160 g_return_if_fail (key != NULL);
1162 id = gtk_object_data_try_key (key);
1164 gtk_object_set_data_by_id_full (object, id, NULL, NULL);
1167 /*****************************************
1168 * gtk_object_set_user_data:
1173 *****************************************/
1176 gtk_object_set_user_data (GtkObject *object,
1179 if (!user_data_key_id)
1180 user_data_key_id = gtk_object_data_force_id (user_data_key);
1182 gtk_object_set_data_by_id_full (object, user_data_key_id, data, NULL);
1185 /*****************************************
1186 * gtk_object_get_user_data:
1191 *****************************************/
1194 gtk_object_get_user_data (GtkObject *object)
1196 if (user_data_key_id)
1197 return gtk_object_get_data_by_id (object, user_data_key_id);
1202 /*****************************************
1203 * gtk_object_check_cast:
1208 *****************************************/
1211 gtk_object_descriptive_type_name (GtkType type)
1215 name = gtk_type_name (type);
1223 gtk_object_check_cast (GtkObject *obj,
1228 g_warning ("invalid cast from (NULL) pointer to `%s'",
1229 gtk_object_descriptive_type_name (cast_type));
1234 g_warning ("invalid unclassed pointer in cast to `%s'",
1235 gtk_object_descriptive_type_name (cast_type));
1238 if (obj->klass->type < GTK_TYPE_OBJECT)
1240 g_warning ("invalid class type `%s' in cast to `%s'",
1241 gtk_object_descriptive_type_name (obj->klass->type),
1242 gtk_object_descriptive_type_name (cast_type));
1245 if (!gtk_type_is_a (obj->klass->type, cast_type))
1247 g_warning ("invalid cast from `%s' to `%s'",
1248 gtk_object_descriptive_type_name (obj->klass->type),
1249 gtk_object_descriptive_type_name (cast_type));
1256 /*****************************************
1257 * gtk_object_check_class_cast:
1262 *****************************************/
1265 gtk_object_check_class_cast (GtkObjectClass *klass,
1270 g_warning ("invalid class cast from (NULL) pointer to `%s'",
1271 gtk_object_descriptive_type_name (cast_type));
1274 if (klass->type < GTK_TYPE_OBJECT)
1276 g_warning ("invalid class type `%s' in class cast to `%s'",
1277 gtk_object_descriptive_type_name (klass->type),
1278 gtk_object_descriptive_type_name (cast_type));
1281 if (!gtk_type_is_a (klass->type, cast_type))
1283 g_warning ("invalid class cast from `%s' to `%s'",
1284 gtk_object_descriptive_type_name (klass->type),
1285 gtk_object_descriptive_type_name (cast_type));
1292 /*****************************************
1293 * gtk_object_collect_args:
1298 *****************************************/
1301 gtk_object_collect_args (guint *nargs,
1316 name = va_arg (args1, char *);
1323 type = gtk_object_get_arg_type (name);
1325 switch (GTK_FUNDAMENTAL_TYPE (type))
1327 case GTK_TYPE_INVALID:
1328 g_warning ("invalid arg name: \"%s\" %x\n", name, type);
1329 (void) va_arg (args1, long);
1338 case GTK_TYPE_FLAGS:
1339 (void) va_arg (args1, gint);
1342 case GTK_TYPE_ULONG:
1343 (void) va_arg (args1, glong);
1345 case GTK_TYPE_FLOAT:
1346 (void) va_arg (args1, gfloat);
1348 case GTK_TYPE_DOUBLE:
1349 (void) va_arg (args1, gdouble);
1351 case GTK_TYPE_STRING:
1352 (void) va_arg (args1, gchar*);
1354 case GTK_TYPE_POINTER:
1355 case GTK_TYPE_BOXED:
1356 (void) va_arg (args1, gpointer);
1358 case GTK_TYPE_SIGNAL:
1359 (void) va_arg (args1, GtkFunction);
1360 (void) va_arg (args1, gpointer);
1362 case GTK_TYPE_FOREIGN:
1363 (void) va_arg (args1, gpointer);
1364 (void) va_arg (args1, GtkDestroyNotify);
1366 case GTK_TYPE_CALLBACK:
1367 (void) va_arg (args1, GtkCallbackMarshal);
1368 (void) va_arg (args1, gpointer);
1369 (void) va_arg (args1, GtkDestroyNotify);
1371 case GTK_TYPE_C_CALLBACK:
1372 (void) va_arg (args1, GtkFunction);
1373 (void) va_arg (args1, gpointer);
1376 (void) va_arg (args1, gint);
1377 (void) va_arg (args1, GtkArg*);
1379 case GTK_TYPE_OBJECT:
1380 (void) va_arg (args1, GtkObject*);
1383 g_error ("unsupported type %s in args", gtk_type_name (type));
1395 args = g_new0 (GtkArg, n);
1397 for (i = 0; i < n; i++)
1399 args[i].name = va_arg (args2, char *);
1400 args[i].type = gtk_object_get_arg_type (args[i].name);
1402 switch (GTK_FUNDAMENTAL_TYPE (args[i].type))
1404 case GTK_TYPE_INVALID:
1405 (void) va_arg (args2, long);
1411 GTK_VALUE_CHAR(args[i]) = va_arg (args2, gint);
1414 GTK_VALUE_BOOL(args[i]) = va_arg (args2, gint);
1417 GTK_VALUE_INT(args[i]) = va_arg (args2, gint);
1420 GTK_VALUE_UINT(args[i]) = va_arg (args2, guint);
1423 GTK_VALUE_ENUM(args[i]) = va_arg (args2, gint);
1425 case GTK_TYPE_FLAGS:
1426 GTK_VALUE_FLAGS(args[i]) = va_arg (args2, gint);
1429 GTK_VALUE_LONG(args[i]) = va_arg (args2, glong);
1431 case GTK_TYPE_ULONG:
1432 GTK_VALUE_ULONG(args[i]) = va_arg (args2, gulong);
1434 case GTK_TYPE_FLOAT:
1435 GTK_VALUE_FLOAT(args[i]) = va_arg (args2, gfloat);
1437 case GTK_TYPE_DOUBLE:
1438 GTK_VALUE_DOUBLE(args[i]) = va_arg (args2, gdouble);
1440 case GTK_TYPE_STRING:
1441 GTK_VALUE_STRING(args[i]) = va_arg (args2, gchar*);
1443 case GTK_TYPE_POINTER:
1444 GTK_VALUE_POINTER(args[i]) = va_arg (args2, gpointer);
1446 case GTK_TYPE_BOXED:
1447 GTK_VALUE_BOXED(args[i]) = va_arg (args2, gpointer);
1449 case GTK_TYPE_SIGNAL:
1450 GTK_VALUE_SIGNAL(args[i]).f = va_arg (args2, GtkFunction);
1451 GTK_VALUE_SIGNAL(args[i]).d = va_arg (args2, gpointer);
1453 case GTK_TYPE_FOREIGN:
1454 GTK_VALUE_FOREIGN(args[i]).data = va_arg (args2, gpointer);
1455 GTK_VALUE_FOREIGN(args[i]).notify =
1456 va_arg (args2, GtkDestroyNotify);
1458 case GTK_TYPE_CALLBACK:
1459 GTK_VALUE_CALLBACK(args[i]).marshal =
1460 va_arg (args2, GtkCallbackMarshal);
1461 GTK_VALUE_CALLBACK(args[i]).data = va_arg (args2, gpointer);
1462 GTK_VALUE_CALLBACK(args[i]).notify =
1463 va_arg (args2, GtkDestroyNotify);
1465 case GTK_TYPE_C_CALLBACK:
1466 GTK_VALUE_C_CALLBACK(args[i]).func = va_arg (args2, GtkFunction);
1467 GTK_VALUE_C_CALLBACK(args[i]).func_data =
1468 va_arg (args2, gpointer);
1471 GTK_VALUE_ARGS(args[i]).n_args = va_arg (args2, gint);
1472 GTK_VALUE_ARGS(args[i]).args = va_arg (args2, GtkArg*);
1474 case GTK_TYPE_OBJECT:
1475 GTK_VALUE_OBJECT(args[i]) = va_arg (args2, GtkObject*);
1476 g_assert (GTK_VALUE_OBJECT(args[i]) == NULL ||
1477 GTK_CHECK_TYPE (GTK_VALUE_OBJECT(args[i]),
1481 g_error ("unsupported type %s in args",
1482 gtk_type_name (args[i].type));
1493 #undef gtk_object_ref
1494 #undef gtk_object_unref
1497 gtk_object_ref (GtkObject *object)
1499 g_return_if_fail (object != NULL);
1500 g_return_if_fail (GTK_IS_OBJECT (object));
1502 object->ref_count += 1;
1506 gtk_object_unref (GtkObject *object)
1508 g_return_if_fail (object != NULL);
1509 g_return_if_fail (GTK_IS_OBJECT (object));
1511 if (object->ref_count == 1)
1512 gtk_object_destroy (object);
1514 if (object->ref_count > 0)
1515 object->ref_count -= 1;
1517 if (object->ref_count == 0)
1519 #ifdef G_ENABLE_DEBUG
1520 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
1522 g_assert (g_hash_table_lookup (living_objs_ht, object) == object);
1523 g_hash_table_remove (living_objs_ht, object);
1526 #endif /* G_ENABLE_DEBUG */
1527 object->klass->finalize (object);
1531 static GtkObject *gtk_trace_object = NULL;
1533 gtk_trace_referencing (GtkObject *object,
1539 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
1541 gboolean exists = TRUE;
1543 g_return_if_fail (object != NULL);
1544 g_return_if_fail (GTK_IS_OBJECT (object));
1546 #ifdef G_ENABLE_DEBUG
1547 exists = g_hash_table_lookup (living_objs_ht, object) != NULL;
1548 #endif /* G_ENABLE_DEBUG */
1551 (object == gtk_trace_object ||
1552 gtk_trace_object == (void*)42))
1553 fprintf (stdout, "trace: object_%s: (%s:%p)->ref_count=%d %s (%s:%d)\n",
1554 do_ref ? "ref" : "unref",
1555 gtk_type_name (GTK_OBJECT_TYPE (object)),
1558 do_ref ? "+ 1" : "- 1",
1562 fprintf (stdout, "trace: object_%s(%p): no such object! (%s:%d)\n",
1563 do_ref ? "ref" : "unref",
1570 gtk_object_ref (object);
1572 gtk_object_unref (object);