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.
22 #include "gtkobject.h"
23 #include "gtksignal.h"
26 #define OBJECT_DATA_ID_CHUNK 1024
41 typedef struct _GtkObjectData GtkObjectData;
42 typedef struct _GtkArgInfo GtkArgInfo;
48 GtkDestroyNotify destroy;
63 static void gtk_object_class_init (GtkObjectClass *klass);
64 static void gtk_object_init (GtkObject *object);
65 static void gtk_object_set_arg (GtkObject *object,
68 static void gtk_object_get_arg (GtkObject *object,
71 static void gtk_object_real_destroy (GtkObject *object);
72 static void gtk_object_finalize (GtkObject *object);
73 static void gtk_object_notify_weaks (gpointer data);
74 static void gtk_object_data_init (void);
75 static GtkObjectData* gtk_object_data_new (void);
76 static void gtk_object_data_destroy (GtkObjectData *odata);
77 static guint* gtk_object_data_id_alloc (void);
79 GtkArg* gtk_object_collect_args (guint *nargs,
83 static gint object_signals[LAST_SIGNAL] = { 0 };
85 static gint object_data_init = TRUE;
86 static GHashTable *object_data_ht = NULL;
87 static GMemChunk *object_data_mem_chunk = NULL;
88 static GSList *object_data_id_list = NULL;
89 static gint object_data_id_index = 0;
91 static GHashTable *arg_info_ht = NULL;
93 static const char *user_data_key = "user_data";
96 static gint obj_count = 0;
97 static GSList *living_objs = NULL;
101 gtk_object_debug (void)
107 printf ("living objects (%d):\n", g_slist_length (living_objs));
108 for (node = living_objs; node; node = node->next)
112 obj = (GtkObject*) node->data;
113 printf ("%p: %s ref_count=%d%s%s\n",
114 obj, gtk_type_name (GTK_OBJECT_TYPE (obj)),
116 GTK_OBJECT_FLOATING (obj) ? " (floating)" : "",
117 GTK_OBJECT_DESTROYED (obj) ? " (destroyed)" : "");
120 printf ("living objects count = %d\n", obj_count);
123 /*****************************************
124 * gtk_object_init_type:
129 *****************************************/
132 gtk_object_init_type ()
134 GtkType object_type = 0;
135 GtkTypeInfo object_info =
139 sizeof (GtkObjectClass),
140 (GtkClassInitFunc) gtk_object_class_init,
141 (GtkObjectInitFunc) gtk_object_init,
146 object_type = gtk_type_unique (0, &object_info);
147 g_assert (object_type == GTK_TYPE_OBJECT);
149 #ifdef G_ENABLE_DEBUG
150 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
151 ATEXIT (gtk_object_debug);
152 #endif /* G_ENABLE_DEBUG */
156 gtk_object_get_type ()
158 return GTK_TYPE_OBJECT;
161 /*****************************************
162 * gtk_object_class_init:
167 *****************************************/
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->destroy = gtk_object_real_destroy;
200 class->finalize = gtk_object_finalize;
203 /*****************************************
204 * gtk_object_real_destroy:
209 *****************************************/
212 gtk_object_real_destroy (GtkObject *object)
214 g_return_if_fail (object != NULL);
215 g_return_if_fail (GTK_IS_OBJECT (object));
217 gtk_signal_handlers_destroy (object);
220 /*****************************************
226 *****************************************/
229 gtk_object_init (GtkObject *object)
231 GTK_OBJECT_FLAGS (object) = GTK_FLOATING;
233 object->ref_count = 1;
234 object->object_data = NULL;
236 #ifdef G_ENABLE_DEBUG
237 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
240 living_objs = g_slist_prepend (living_objs, object);
242 #endif /* G_ENABLE_DEBUG */
245 /*****************************************
246 * gtk_object_set_arg:
251 *****************************************/
254 gtk_object_set_arg (GtkObject *object,
261 gtk_object_set_user_data (object, GTK_VALUE_POINTER (*arg));
264 if ((arg->name[9 + 2 + 6] != ':') || (arg->name[9 + 2 + 7] != ':'))
266 g_warning ("invalid signal argument: \"%s\"\n", arg->name);
267 arg->type = GTK_TYPE_INVALID;
270 gtk_signal_connect (object, arg->name + 9 + 2 + 6 + 2,
271 (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
272 GTK_VALUE_SIGNAL (*arg).d);
274 case ARG_OBJECT_SIGNAL:
275 if ((arg->name[9 + 2 + 13] != ':') || (arg->name[9 + 2 + 14] != ':'))
277 g_warning ("invalid signal argument: \"%s\"\n", arg->name);
278 arg->type = GTK_TYPE_INVALID;
281 gtk_signal_connect_object (object, arg->name + 9 + 2 + 13 + 2,
282 (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
283 (GtkObject*) GTK_VALUE_SIGNAL (*arg).d);
286 arg->type = GTK_TYPE_INVALID;
291 /*****************************************
292 * gtk_object_get_arg:
297 *****************************************/
300 gtk_object_get_arg (GtkObject *object,
307 GTK_VALUE_POINTER (*arg) = gtk_object_get_user_data (object);
310 case ARG_OBJECT_SIGNAL:
312 arg->type = GTK_TYPE_INVALID;
317 /*****************************************
318 * gtk_object_class_add_signals:
323 *****************************************/
326 gtk_object_class_add_signals (GtkObjectClass *class,
333 g_return_if_fail (class != NULL);
335 new_signals = g_new (gint, class->nsignals + nsignals);
336 for (i = 0; i < class->nsignals; i++)
337 new_signals[i] = class->signals[i];
338 for (i = 0; i < nsignals; i++)
339 new_signals[class->nsignals + i] = signals[i];
341 g_free (class->signals);
342 class->signals = new_signals;
343 class->nsignals += nsignals;
346 /*****************************************
347 * gtk_object_class_add_user_signal:
352 *****************************************/
355 gtk_object_class_add_user_signal (GtkObjectClass *class,
357 GtkSignalMarshaller marshaller,
367 g_return_val_if_fail (class != NULL, 0);
371 params = g_new (GtkType, nparams);
373 va_start (args, nparams);
375 for (i = 0; i < nparams; i++)
376 params[i] = va_arg (args, GtkType);
383 signal_id = gtk_signal_newv (name,
395 gtk_object_class_add_signals (class, &signal_id, 1);
400 /*****************************************
401 * gtk_object_finalize:
406 *****************************************/
409 gtk_object_finalize (GtkObject *object)
411 GtkObjectData *odata, *next;
413 odata = object->object_data;
417 gtk_object_data_destroy (odata);
424 /*****************************************
430 *****************************************/
433 gtk_object_sink (GtkObject *object)
435 g_return_if_fail (object != NULL);
436 g_return_if_fail (GTK_IS_OBJECT (object));
438 if (GTK_OBJECT_FLOATING (object))
440 GTK_OBJECT_UNSET_FLAGS (object, GTK_FLOATING);
441 gtk_object_unref (object);
445 /*****************************************
446 * gtk_object_destroy:
451 *****************************************/
454 gtk_object_destroy (GtkObject *object)
456 g_return_if_fail (object != NULL);
457 g_return_if_fail (GTK_IS_OBJECT (object));
459 if (!GTK_OBJECT_DESTROYED (object))
461 GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
462 gtk_signal_emit (object, object_signals[DESTROY]);
466 /*****************************************
469 * Weak refs are very similar to the old "destroy" signal. They allow
470 * one to register a callback that is called when the weakly
471 * referenced object is finalized.
473 * They are not implemented as a signal because they really are
474 * special and need to be used with great care. Unlike signals, who
475 * should be able to execute any code whatsoever.
477 * A weakref callback is not allowed to retain a reference to the
478 * object. In fact, the object is no longer there at all when it is
481 * A weakref callback is called atmost once.
483 *****************************************/
485 typedef struct _GtkWeakRef GtkWeakRef;
490 GtkDestroyNotify notify;
494 static const gchar *weakrefs_key = "gtk-weakrefs";
497 gtk_object_weakref (GtkObject *object,
498 GtkDestroyNotify notify,
503 g_return_if_fail (object != NULL);
504 g_return_if_fail (notify != NULL);
505 g_return_if_fail (GTK_IS_OBJECT (object));
507 weak = g_new (GtkWeakRef, 1);
508 weak->next = gtk_object_get_data (object, weakrefs_key);
509 weak->notify = notify;
511 gtk_object_set_data_full (object, weakrefs_key, weak,
512 gtk_object_notify_weaks);
516 gtk_object_weakunref (GtkObject *object,
517 GtkDestroyNotify notify,
520 GtkWeakRef *weaks, *w, **wp;
522 g_return_if_fail (object != NULL);
523 g_return_if_fail (GTK_IS_OBJECT (object));
525 weaks = gtk_object_get_data (object, weakrefs_key);
526 for (wp = &weaks; *wp; wp = &(*wp)->next)
529 if (w->notify == notify && w->data == data)
532 gtk_object_set_data_full (object, weakrefs_key, w->next,
533 gtk_object_notify_weaks);
543 gtk_object_notify_weaks (gpointer data)
547 w1 = (GtkWeakRef *)data;
551 w1->notify (w1->data);
558 /*****************************************
564 *****************************************/
567 gtk_object_new (guint type,
576 obj = gtk_type_new (type);
578 va_start (args1, type);
579 va_start (args2, type);
581 args = gtk_object_collect_args (&nargs, args1, args2);
582 gtk_object_setv (obj, nargs, args);
591 /*****************************************
597 *****************************************/
600 gtk_object_newv (guint type,
606 obj = gtk_type_new (type);
607 gtk_object_setv (obj, nargs, args);
612 /*****************************************
618 *****************************************/
621 gtk_object_getv (GtkObject *object,
627 g_return_if_fail (object != NULL);
632 for (i = 0; i < nargs; i++)
639 /* hm, the name cutting shouldn't be needed on gets, but what the heck...
641 lookup_name = g_strdup (args[i].name);
642 d = strchr (lookup_name, ':');
643 if (d && d[1] == ':')
645 d = strchr (d + 2, ':');
649 info = g_hash_table_lookup (arg_info_ht, lookup_name);
656 g_warning ("invalid arg name: \"%s\"\n", lookup_name);
657 args[i].type = GTK_TYPE_INVALID;
658 g_free (lookup_name);
661 else if (!gtk_type_is_a (object->klass->type, info->class_type))
663 g_warning ("invalid arg for %s: \"%s\"\n", gtk_type_name (object->klass->type), lookup_name);
664 args[i].type = GTK_TYPE_INVALID;
665 g_free (lookup_name);
668 else if (!info->arg_flags & GTK_ARG_READABLE)
670 g_warning ("arg is not supplied for read-access: \"%s\"\n", lookup_name);
671 args[i].type = GTK_TYPE_INVALID;
672 g_free (lookup_name);
676 g_free (lookup_name);
678 args[i].type = info->type;
679 gtk_type_get_arg (object, info->class_type, &args[i], info->arg_id);
683 /*****************************************
684 * gtk_object_query_args:
689 *****************************************/
691 struct _GtkQueryArgData
696 typedef struct _GtkQueryArgData GtkQueryArgData;
699 gtk_query_arg_foreach (gpointer key,
703 register GtkArgInfo *info;
704 register GtkQueryArgData *data;
709 if (info->class_type == data->class_type)
710 data->arg_list = g_list_prepend (data->arg_list, info);
714 gtk_object_query_args (GtkType class_type,
719 GtkQueryArgData query_data;
723 g_return_val_if_fail (nargs != NULL, NULL);
725 g_return_val_if_fail (gtk_type_is_a (class_type, gtk_object_get_type ()), NULL);
730 /* make sure the types class has been initialized, because
731 * the argument setup happens in the gtk_*_class_init() functions.
733 gtk_type_class (class_type);
735 query_data.arg_list = NULL;
736 query_data.class_type = class_type;
737 g_hash_table_foreach (arg_info_ht, gtk_query_arg_foreach, &query_data);
739 if (query_data.arg_list)
741 register GList *list;
744 list = query_data.arg_list;
751 g_assert (len == ((GtkObjectClass*) gtk_type_class (class_type))->n_args); /* paranoid */
753 args = g_new0 (GtkArg, len);
756 *arg_flags = g_new (guint32, len);
765 g_assert (info->seq_id > 0 && info->seq_id <= len); /* paranoid */
767 args[info->seq_id - 1].type = info->type;
768 args[info->seq_id - 1].name = info->name;
770 (*arg_flags)[info->seq_id - 1] = info->arg_flags;
774 g_list_free (query_data.arg_list);
782 /*****************************************
788 *****************************************/
791 gtk_object_set (GtkObject *object,
799 g_return_if_fail (object != NULL);
801 va_start (args1, object);
802 va_start (args2, object);
804 args = gtk_object_collect_args (&nargs, args1, args2);
805 gtk_object_setv (object, nargs, args);
812 /*****************************************
818 *****************************************/
821 gtk_object_setv (GtkObject *object,
827 g_return_if_fail (object != NULL);
832 for (i = 0; i < nargs; i++)
839 lookup_name = g_strdup (args[i].name);
840 d = strchr (lookup_name, ':');
841 if (d && d[1] == ':')
843 d = strchr (d + 2, ':');
847 info = g_hash_table_lookup (arg_info_ht, lookup_name);
856 g_warning ("invalid arg name: \"%s\"\n", lookup_name);
859 else if (info->type != args[i].type)
861 g_warning ("invalid arg type for: \"%s\"\n", lookup_name);
864 else if (!gtk_type_is_a (object->klass->type, info->class_type))
866 g_warning ("invalid arg for %s: \"%s\"\n", gtk_type_name (object->klass->type), lookup_name);
869 else if (!info->arg_flags & GTK_ARG_WRITABLE)
871 g_warning ("arg is not supplied for write-access: \"%s\"\n", lookup_name);
875 g_free (lookup_name);
880 gtk_type_set_arg (object, info->class_type, &args[i], info->arg_id);
884 /*****************************************
885 * gtk_object_add_arg_type:
890 *****************************************/
893 gtk_object_add_arg_type (const char *arg_name,
899 gchar class_part[1024];
903 g_return_if_fail (arg_name != NULL);
904 g_return_if_fail (arg_type > GTK_TYPE_NONE);
905 g_return_if_fail (arg_id > 0);
906 g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) != 0);
908 arg_part = strchr (arg_name, ':');
909 if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':'))
911 g_warning ("invalid arg name: \"%s\"\n", arg_name);
915 strncpy (class_part, arg_name, (glong) (arg_part - arg_name));
916 class_part[(glong) (arg_part - arg_name)] = '\0';
918 class_type = gtk_type_from_name (class_part);
921 g_warning ("invalid class name in arg: \"%s\"\n", arg_name);
925 info = g_new (GtkArgInfo, 1);
926 info->name = g_strdup (arg_name);
927 info->type = arg_type;
928 info->class_type = class_type;
929 info->arg_flags = arg_flags & (GTK_ARG_READABLE | GTK_ARG_WRITABLE);
930 info->arg_id = arg_id;
931 info->seq_id = ++((GtkObjectClass*) gtk_type_class (class_type))->n_args;
934 arg_info_ht = g_hash_table_new (g_str_hash, g_str_equal);
936 g_hash_table_insert (arg_info_ht, info->name, info);
939 /*****************************************
940 * gtk_object_get_arg_type:
945 *****************************************/
948 gtk_object_get_arg_type (const char *arg_name)
955 return GTK_TYPE_INVALID;
957 t = strchr (arg_name, ':');
958 if (!t || (t[0] != ':') || (t[1] != ':'))
960 g_warning ("invalid arg name: \"%s\"\n", arg_name);
961 return GTK_TYPE_INVALID;
964 t = strchr (t + 2, ':');
967 strncpy (buffer, arg_name, (long) (t - arg_name));
968 buffer[(long) (t - arg_name)] = '\0';
972 info = g_hash_table_lookup (arg_info_ht, (gpointer) arg_name);
976 return GTK_TYPE_INVALID;
979 /*****************************************
980 * gtk_object_set_data:
985 *****************************************/
988 gtk_object_set_data (GtkObject *object,
992 gtk_object_set_data_full (object, key, data, NULL);
995 /*****************************************
996 * gtk_object_set_data_full:
1001 *****************************************/
1004 gtk_object_set_data_full (GtkObject *object,
1007 GtkDestroyNotify destroy)
1009 GtkObjectData *odata;
1010 GtkObjectData *prev;
1013 g_return_if_fail (object != NULL);
1014 g_return_if_fail (GTK_IS_OBJECT (object));
1015 g_return_if_fail (key != NULL);
1017 if (object_data_init)
1018 gtk_object_data_init ();
1020 id = g_hash_table_lookup (object_data_ht, (gpointer) key);
1027 odata = object->object_data;
1031 if (odata->id == *id)
1034 prev->next = odata->next;
1035 if (odata == object->object_data)
1036 object->object_data = odata->next;
1038 gtk_object_data_destroy (odata);
1043 odata = odata->next;
1051 id = gtk_object_data_id_alloc ();
1052 g_hash_table_insert (object_data_ht, (gpointer) key, id);
1055 odata = object->object_data;
1058 if (odata->id == *id)
1061 odata->destroy = destroy;
1065 odata = odata->next;
1068 odata = gtk_object_data_new ();
1071 odata->destroy = destroy;
1073 odata->next = object->object_data;
1074 object->object_data = odata;
1078 /*****************************************
1079 * gtk_object_get_data:
1084 *****************************************/
1087 gtk_object_get_data (GtkObject *object,
1090 GtkObjectData *odata;
1093 g_return_val_if_fail (object != NULL, NULL);
1094 g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
1095 g_return_val_if_fail (key != NULL, NULL);
1097 if (object_data_init)
1098 gtk_object_data_init ();
1100 id = g_hash_table_lookup (object_data_ht, (gpointer) key);
1103 odata = object->object_data;
1106 if (odata->id == *id)
1108 odata = odata->next;
1115 /*****************************************
1116 * gtk_object_remove_data:
1121 *****************************************/
1124 gtk_object_remove_data (GtkObject *object,
1127 g_return_if_fail (object != NULL);
1128 g_return_if_fail (GTK_IS_OBJECT (object));
1129 g_return_if_fail (key != NULL);
1131 gtk_object_set_data_full (object, key, NULL, NULL);
1134 /*****************************************
1135 * gtk_object_set_user_data:
1140 *****************************************/
1143 gtk_object_set_user_data (GtkObject *object,
1146 g_return_if_fail (object != NULL);
1147 g_return_if_fail (GTK_IS_OBJECT (object));
1149 gtk_object_set_data_full (object, user_data_key, data, NULL);
1152 /*****************************************
1153 * gtk_object_get_user_data:
1158 *****************************************/
1161 gtk_object_get_user_data (GtkObject *object)
1163 g_return_val_if_fail (object != NULL, NULL);
1164 g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
1166 return gtk_object_get_data (object, user_data_key);
1169 /*****************************************
1170 * gtk_object_check_cast:
1175 *****************************************/
1178 gtk_object_descriptive_type_name (GtkType type)
1182 name = gtk_type_name (type);
1190 gtk_object_check_cast (GtkObject *obj,
1195 g_warning ("invalid cast from (NULL) pointer to `%s'",
1196 gtk_object_descriptive_type_name (cast_type));
1201 g_warning ("invalid unclassed pointer in cast to `%s'",
1202 gtk_object_descriptive_type_name (cast_type));
1205 if (obj->klass->type < GTK_TYPE_OBJECT)
1207 g_warning ("invalid class type `%s' in cast to `%s'",
1208 gtk_object_descriptive_type_name (obj->klass->type),
1209 gtk_object_descriptive_type_name (cast_type));
1212 if (!gtk_type_is_a (obj->klass->type, cast_type))
1214 g_warning ("invalid cast from `%s' to `%s'",
1215 gtk_object_descriptive_type_name (obj->klass->type),
1216 gtk_object_descriptive_type_name (cast_type));
1223 /*****************************************
1224 * gtk_object_check_class_cast:
1229 *****************************************/
1232 gtk_object_check_class_cast (GtkObjectClass *klass,
1237 g_warning ("invalid class cast from (NULL) pointer to `%s'",
1238 gtk_object_descriptive_type_name (cast_type));
1241 if (klass->type < GTK_TYPE_OBJECT)
1243 g_warning ("invalid class type `%s' in class cast to `%s'",
1244 gtk_object_descriptive_type_name (klass->type),
1245 gtk_object_descriptive_type_name (cast_type));
1248 if (!gtk_type_is_a (klass->type, cast_type))
1250 g_warning ("invalid class cast from `%s' to `%s'",
1251 gtk_object_descriptive_type_name (klass->type),
1252 gtk_object_descriptive_type_name (cast_type));
1259 /*****************************************
1260 * gtk_object_data_init:
1265 *****************************************/
1268 gtk_object_data_init ()
1270 if (object_data_init)
1272 object_data_init = FALSE;
1274 object_data_ht = g_hash_table_new (g_str_hash, g_str_equal);
1278 /*****************************************
1279 * gtk_object_data_new:
1284 *****************************************/
1286 static GtkObjectData*
1287 gtk_object_data_new ()
1289 GtkObjectData *odata;
1291 if (!object_data_mem_chunk)
1292 object_data_mem_chunk = g_mem_chunk_new ("object data mem chunk",
1293 sizeof (GtkObjectData),
1294 1024, G_ALLOC_AND_FREE);
1296 odata = g_chunk_new (GtkObjectData, object_data_mem_chunk);
1300 odata->destroy = NULL;
1306 /*****************************************
1307 * gtk_object_data_destroy:
1312 *****************************************/
1315 gtk_object_data_destroy (GtkObjectData *odata)
1317 g_return_if_fail (odata != NULL);
1320 odata->destroy (odata->data);
1322 g_mem_chunk_free (object_data_mem_chunk, odata);
1325 /*****************************************
1326 * gtk_object_data_id_alloc:
1331 *****************************************/
1334 gtk_object_data_id_alloc ()
1336 static guint next_id = 1;
1339 if (!object_data_id_list ||
1340 (object_data_id_index == OBJECT_DATA_ID_CHUNK))
1342 ids = g_new (guint, OBJECT_DATA_ID_CHUNK);
1343 object_data_id_index = 0;
1344 object_data_id_list = g_slist_prepend (object_data_id_list, ids);
1348 ids = object_data_id_list->data;
1351 ids[object_data_id_index] = next_id++;
1352 return &ids[object_data_id_index++];
1355 /*****************************************
1356 * gtk_object_collect_args:
1361 *****************************************/
1364 gtk_object_collect_args (guint *nargs,
1379 name = va_arg (args1, char *);
1386 type = gtk_object_get_arg_type (name);
1388 switch (GTK_FUNDAMENTAL_TYPE (type))
1390 case GTK_TYPE_INVALID:
1391 g_warning ("invalid arg name: \"%s\" %x\n", name, type);
1392 (void) va_arg (args1, long);
1401 case GTK_TYPE_FLAGS:
1402 (void) va_arg (args1, gint);
1405 case GTK_TYPE_ULONG:
1406 (void) va_arg (args1, glong);
1408 case GTK_TYPE_FLOAT:
1409 (void) va_arg (args1, gfloat);
1411 case GTK_TYPE_DOUBLE:
1412 (void) va_arg (args1, gdouble);
1414 case GTK_TYPE_STRING:
1415 (void) va_arg (args1, gchar*);
1417 case GTK_TYPE_POINTER:
1418 case GTK_TYPE_BOXED:
1419 (void) va_arg (args1, gpointer);
1421 case GTK_TYPE_SIGNAL:
1422 (void) va_arg (args1, GtkFunction);
1423 (void) va_arg (args1, gpointer);
1425 case GTK_TYPE_FOREIGN:
1426 (void) va_arg (args1, gpointer);
1427 (void) va_arg (args1, GtkDestroyNotify);
1429 case GTK_TYPE_CALLBACK:
1430 (void) va_arg (args1, GtkCallbackMarshal);
1431 (void) va_arg (args1, gpointer);
1432 (void) va_arg (args1, GtkDestroyNotify);
1434 case GTK_TYPE_C_CALLBACK:
1435 (void) va_arg (args1, GtkFunction);
1436 (void) va_arg (args1, gpointer);
1439 (void) va_arg (args1, gint);
1440 (void) va_arg (args1, GtkArg*);
1442 case GTK_TYPE_OBJECT:
1443 (void) va_arg (args1, GtkObject*);
1446 g_error ("unsupported type %s in args", gtk_type_name (type));
1458 args = g_new0 (GtkArg, n);
1460 for (i = 0; i < n; i++)
1462 args[i].name = va_arg (args2, char *);
1463 args[i].type = gtk_object_get_arg_type (args[i].name);
1465 switch (GTK_FUNDAMENTAL_TYPE (args[i].type))
1467 case GTK_TYPE_INVALID:
1468 (void) va_arg (args2, long);
1474 GTK_VALUE_CHAR(args[i]) = va_arg (args2, gint);
1477 GTK_VALUE_BOOL(args[i]) = va_arg (args2, gint);
1480 GTK_VALUE_INT(args[i]) = va_arg (args2, gint);
1483 GTK_VALUE_UINT(args[i]) = va_arg (args2, guint);
1486 GTK_VALUE_ENUM(args[i]) = va_arg (args2, gint);
1488 case GTK_TYPE_FLAGS:
1489 GTK_VALUE_FLAGS(args[i]) = va_arg (args2, gint);
1492 GTK_VALUE_LONG(args[i]) = va_arg (args2, glong);
1494 case GTK_TYPE_ULONG:
1495 GTK_VALUE_ULONG(args[i]) = va_arg (args2, gulong);
1497 case GTK_TYPE_FLOAT:
1498 GTK_VALUE_FLOAT(args[i]) = va_arg (args2, gfloat);
1500 case GTK_TYPE_DOUBLE:
1501 GTK_VALUE_DOUBLE(args[i]) = va_arg (args2, gdouble);
1503 case GTK_TYPE_STRING:
1504 GTK_VALUE_STRING(args[i]) = va_arg (args2, gchar*);
1506 case GTK_TYPE_POINTER:
1507 GTK_VALUE_POINTER(args[i]) = va_arg (args2, gpointer);
1509 case GTK_TYPE_BOXED:
1510 GTK_VALUE_BOXED(args[i]) = va_arg (args2, gpointer);
1512 case GTK_TYPE_SIGNAL:
1513 GTK_VALUE_SIGNAL(args[i]).f = va_arg (args2, GtkFunction);
1514 GTK_VALUE_SIGNAL(args[i]).d = va_arg (args2, gpointer);
1516 case GTK_TYPE_FOREIGN:
1517 GTK_VALUE_FOREIGN(args[i]).data = va_arg (args2, gpointer);
1518 GTK_VALUE_FOREIGN(args[i]).notify =
1519 va_arg (args2, GtkDestroyNotify);
1521 case GTK_TYPE_CALLBACK:
1522 GTK_VALUE_CALLBACK(args[i]).marshal =
1523 va_arg (args2, GtkCallbackMarshal);
1524 GTK_VALUE_CALLBACK(args[i]).data = va_arg (args2, gpointer);
1525 GTK_VALUE_CALLBACK(args[i]).notify =
1526 va_arg (args2, GtkDestroyNotify);
1528 case GTK_TYPE_C_CALLBACK:
1529 GTK_VALUE_C_CALLBACK(args[i]).func = va_arg (args2, GtkFunction);
1530 GTK_VALUE_C_CALLBACK(args[i]).func_data =
1531 va_arg (args2, gpointer);
1534 GTK_VALUE_ARGS(args[i]).n_args = va_arg (args2, gint);
1535 GTK_VALUE_ARGS(args[i]).args = va_arg (args2, GtkArg*);
1537 case GTK_TYPE_OBJECT:
1538 GTK_VALUE_OBJECT(args[i]) = va_arg (args2, GtkObject*);
1539 g_assert (GTK_VALUE_OBJECT(args[i]) == NULL ||
1540 GTK_CHECK_TYPE (GTK_VALUE_OBJECT(args[i]),
1544 g_error ("unsupported type %s in args",
1545 gtk_type_name (args[i].type));
1556 #undef gtk_object_ref
1557 #undef gtk_object_unref
1560 gtk_object_ref (GtkObject *object)
1562 g_return_if_fail (object != NULL);
1563 g_return_if_fail (GTK_IS_OBJECT (object));
1565 object->ref_count += 1;
1569 gtk_object_unref (GtkObject *object)
1571 g_return_if_fail (object != NULL);
1572 g_return_if_fail (GTK_IS_OBJECT (object));
1574 if (object->ref_count == 1)
1575 gtk_object_destroy (object);
1577 if (object->ref_count > 0)
1578 object->ref_count -= 1;
1580 if (object->ref_count == 0)
1582 #ifdef G_ENABLE_DEBUG
1583 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
1585 g_assert (g_slist_find (living_objs, object));
1586 living_objs = g_slist_remove (living_objs, object);
1589 #endif /* G_ENABLE_DEBUG */
1590 object->klass->finalize (object);
1594 #ifdef G_ENABLE_DEBUG
1596 static GtkObject *gtk_trace_object = NULL;
1599 gtk_trace_referencing (gpointer *o,
1606 GtkObject *object = (GtkObject*) o;
1608 if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
1610 g_return_if_fail (object != NULL);
1611 g_return_if_fail (GTK_IS_OBJECT (object));
1613 exists = (g_slist_find (living_objs, object) != NULL);
1616 (object == gtk_trace_object ||
1617 gtk_trace_object == (void*)42))
1618 printf ("trace: object_%s: (%s:%p)->ref_count=%d%s (%s_f%02d:%d)\n",
1619 do_ref ? "ref" : "unref",
1620 gtk_type_name (GTK_OBJECT_TYPE (object)),
1623 do_ref ? " + 1" : " - 1 ",
1629 printf ("trace: object_%s(%p): no such object! (%s_f%02d:%d)\n",
1630 do_ref ? "ref" : "unref",
1638 gtk_object_ref (object);
1640 gtk_object_unref (object);
1643 #endif /* G_ENABLE_DEBUG */