* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
#include <stdarg.h>
#include <string.h>
#include "gtksignal.h"
-#define OBJECT_DATA_ID_CHUNK 1024
-
+#define GTK_OBJECT_DATA_ID_BLOCK_SIZE (1024)
+#define GTK_OBJECT_DATA_BLOCK_SIZE (1024)
enum {
DESTROY,
ARG_0,
ARG_USER_DATA,
ARG_SIGNAL,
- ARG_OBJECT_SIGNAL
+ ARG_SIGNAL_AFTER,
+ ARG_OBJECT_SIGNAL,
+ ARG_OBJECT_SIGNAL_AFTER
};
typedef struct _GtkObjectData GtkObjectData;
-typedef struct _GtkArgInfo GtkArgInfo;
struct _GtkObjectData
{
GtkObjectData *next;
};
-struct _GtkArgInfo
-{
- char *name;
- GtkType type;
- GtkType class_type;
- guint arg_flags;
- guint arg_id;
- guint seq_id;
-};
-
-static void gtk_object_class_init (GtkObjectClass *klass);
-static void gtk_object_init (GtkObject *object);
-static void gtk_object_set_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id);
-static void gtk_object_get_arg (GtkObject *object,
- GtkArg *arg,
- guint arg_id);
-static void gtk_object_real_destroy (GtkObject *object);
-static void gtk_object_finalize (GtkObject *object);
-static void gtk_object_notify_weaks (gpointer data);
-static void gtk_object_data_init (void);
-static GtkObjectData* gtk_object_data_new (void);
-static void gtk_object_data_destroy (GtkObjectData *odata);
-static guint* gtk_object_data_id_alloc (void);
+void gtk_object_init_type (void);
+static void gtk_object_base_class_init (GtkObjectClass *klass);
+static void gtk_object_class_init (GtkObjectClass *klass);
+static void gtk_object_init (GtkObject *object);
+static void gtk_object_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_object_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_object_shutdown (GtkObject *object);
+static void gtk_object_real_destroy (GtkObject *object);
+static void gtk_object_finalize (GtkObject *object);
+static void gtk_object_notify_weaks (GtkObject *object);
-GtkArg* gtk_object_collect_args (guint *nargs,
- va_list args1,
- va_list args2);
+static guint object_signals[LAST_SIGNAL] = { 0 };
-static gint object_signals[LAST_SIGNAL] = { 0 };
+static GHashTable *object_arg_info_ht = NULL;
-static gint object_data_init = TRUE;
-static GHashTable *object_data_ht = NULL;
-static GMemChunk *object_data_mem_chunk = NULL;
-static GSList *object_data_id_list = NULL;
-static gint object_data_id_index = 0;
-
-static GHashTable *arg_info_ht = NULL;
-
-static const char *user_data_key = "user_data";
+static const gchar *user_data_key = "user_data";
+static guint user_data_key_id = 0;
+static const gchar *weakrefs_key = "gtk-weakrefs";
+static guint weakrefs_key_id = 0;
+static GtkObjectData *gtk_object_data_free_list = NULL;
-static gint obj_count = 0;
-static GSList *living_objs = NULL;
+#define GTK_OBJECT_DATA_DESTROY( odata ) { \
+ if (odata->destroy) \
+ odata->destroy (odata->data); \
+ odata->next = gtk_object_data_free_list; \
+ gtk_object_data_free_list = odata; \
+}
+#ifdef G_ENABLE_DEBUG
+static guint obj_count = 0;
+static GHashTable *living_objs_ht = NULL;
+static void
+gtk_object_debug_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+ GtkObject *object;
+
+ object = (GtkObject*) value;
+ g_message ("[%p] %s\tref_count=%d%s%s\n",
+ object,
+ gtk_type_name (GTK_OBJECT_TYPE (object)),
+ object->ref_count,
+ GTK_OBJECT_FLOATING (object) ? " (floating)" : "",
+ GTK_OBJECT_DESTROYED (object) ? " (destroyed)" : "");
+}
static void
gtk_object_debug (void)
{
- if (1)
- {
- GSList *node;
-
- printf ("living objects (%d):\n", g_slist_length (living_objs));
- for (node = living_objs; node; node = node->next)
- {
- GtkObject *obj;
-
- obj = (GtkObject*) node->data;
- printf ("%p: %s ref_count=%d%s%s\n",
- obj, gtk_type_name (GTK_OBJECT_TYPE (obj)),
- obj->ref_count,
- GTK_OBJECT_FLOATING (obj) ? " (floating)" : "",
- GTK_OBJECT_DESTROYED (obj) ? " (destroyed)" : "");
- }
- }
- printf ("living objects count = %d\n", obj_count);
+ g_hash_table_foreach (living_objs_ht, gtk_object_debug_foreach, NULL);
+
+ g_message ("living objects count = %d\n", obj_count);
}
+#endif /* G_ENABLE_DEBUG */
-/*****************************************
- * gtk_object_init_type:
- *
- * arguments:
+/****************************************************
+ * GtkObject type, class and instance initialization
*
- * results:
- *****************************************/
+ ****************************************************/
void
-gtk_object_init_type ()
+gtk_object_init_type (void)
{
GtkType object_type = 0;
GtkTypeInfo object_info =
sizeof (GtkObjectClass),
(GtkClassInitFunc) gtk_object_class_init,
(GtkObjectInitFunc) gtk_object_init,
- gtk_object_set_arg,
- gtk_object_get_arg,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) gtk_object_base_class_init,
};
object_type = gtk_type_unique (0, &object_info);
}
GtkType
-gtk_object_get_type ()
+gtk_object_get_type (void)
{
return GTK_TYPE_OBJECT;
}
-/*****************************************
- * gtk_object_class_init:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
static void
-gtk_object_class_init (GtkObjectClass *class)
+gtk_object_base_class_init (GtkObjectClass *class)
{
+ /* reset instance specific fields that don't get inhrited */
class->signals = NULL;
class->nsignals = 0;
class->n_args = 0;
+ /* reset instance specifc methods that don't get inherited */
+ class->get_arg = NULL;
+ class->set_arg = NULL;
+}
+
+static void
+gtk_object_class_init (GtkObjectClass *class)
+{
gtk_object_add_arg_type ("GtkObject::user_data",
GTK_TYPE_POINTER,
GTK_ARG_READWRITE,
GTK_TYPE_SIGNAL,
GTK_ARG_WRITABLE,
ARG_SIGNAL);
+ gtk_object_add_arg_type ("GtkObject::signal_after",
+ GTK_TYPE_SIGNAL,
+ GTK_ARG_WRITABLE,
+ ARG_SIGNAL_AFTER);
gtk_object_add_arg_type ("GtkObject::object_signal",
GTK_TYPE_SIGNAL,
GTK_ARG_WRITABLE,
ARG_OBJECT_SIGNAL);
+ gtk_object_add_arg_type ("GtkObject::object_signal_after",
+ GTK_TYPE_SIGNAL,
+ GTK_ARG_WRITABLE,
+ ARG_OBJECT_SIGNAL_AFTER);
object_signals[DESTROY] =
gtk_signal_new ("destroy",
GTK_RUN_LAST,
class->type,
GTK_SIGNAL_OFFSET (GtkObjectClass, destroy),
- gtk_signal_default_marshaller,
+ gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (class, object_signals, LAST_SIGNAL);
+ class->get_arg = gtk_object_get_arg;
+ class->set_arg = gtk_object_set_arg;
+ class->shutdown = gtk_object_shutdown;
class->destroy = gtk_object_real_destroy;
class->finalize = gtk_object_finalize;
}
-/*****************************************
- * gtk_object_real_destroy:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-static void
-gtk_object_real_destroy (GtkObject *object)
-{
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_OBJECT (object));
-
- gtk_signal_handlers_destroy (object);
-}
-
-/*****************************************
- * gtk_object_init:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
static void
gtk_object_init (GtkObject *object)
{
if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
{
obj_count++;
- living_objs = g_slist_prepend (living_objs, object);
+
+ if (!living_objs_ht)
+ living_objs_ht = g_hash_table_new (g_direct_hash, NULL);
+
+ g_hash_table_insert (living_objs_ht, object, object);
}
#endif /* G_ENABLE_DEBUG */
}
-/*****************************************
- * gtk_object_set_arg:
+/********************************************
+ * Functions to end a GtkObject's life time
*
- * arguments:
+ ********************************************/
+void
+gtk_object_destroy (GtkObject *object)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ if (!GTK_OBJECT_DESTROYED (object))
+ {
+ /* we will hold a reference on the object in this place, so
+ * to ease all classes shutdown and destroy implementations.
+ * i.e. they don't have to bother about referencing at all.
+ */
+ gtk_object_ref (object);
+ object->klass->shutdown (object);
+ gtk_object_unref (object);
+ }
+}
+
+static void
+gtk_object_shutdown (GtkObject *object)
+{
+ GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
+ gtk_signal_emit (object, object_signals[DESTROY]);
+}
+
+static void
+gtk_object_real_destroy (GtkObject *object)
+{
+ if (GTK_OBJECT_CONNECTED (object))
+ gtk_signal_handlers_destroy (object);
+}
+
+static void
+gtk_object_finalize (GtkObject *object)
+{
+ gtk_object_notify_weaks (object);
+
+ while (object->object_data)
+ {
+ GtkObjectData *odata;
+
+ odata = object->object_data;
+ object->object_data = odata->next;
+ GTK_OBJECT_DATA_DESTROY (odata);
+ }
+
+ gtk_type_free (GTK_OBJECT_TYPE (object), object);
+}
+
+/*****************************************
+ * GtkObject argument handlers
*
- * results:
*****************************************/
static void
GtkArg *arg,
guint arg_id)
{
+ guint n = 0;
+
switch (arg_id)
{
+ gchar *arg_name;
+
case ARG_USER_DATA:
gtk_object_set_user_data (object, GTK_VALUE_POINTER (*arg));
break;
- case ARG_SIGNAL:
- if ((arg->name[9 + 2 + 6] != ':') || (arg->name[9 + 2 + 7] != ':'))
- {
- g_warning ("invalid signal argument: \"%s\"\n", arg->name);
- arg->type = GTK_TYPE_INVALID;
- return;
- }
- gtk_signal_connect (object, arg->name + 9 + 2 + 6 + 2,
- (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
- GTK_VALUE_SIGNAL (*arg).d);
- break;
+ case ARG_OBJECT_SIGNAL_AFTER:
+ n += 6;
case ARG_OBJECT_SIGNAL:
- if ((arg->name[9 + 2 + 13] != ':') || (arg->name[9 + 2 + 14] != ':'))
+ n += 1;
+ case ARG_SIGNAL_AFTER:
+ n += 6;
+ case ARG_SIGNAL:
+ n += 6;
+ arg_name = gtk_arg_name_strip_type (arg->name);
+ if (arg_name &&
+ arg_name[n] == ':' &&
+ arg_name[n + 1] == ':' &&
+ arg_name[n + 2] != 0)
{
- g_warning ("invalid signal argument: \"%s\"\n", arg->name);
- arg->type = GTK_TYPE_INVALID;
- return;
+ gtk_signal_connect_full (object,
+ arg_name + n + 2,
+ GTK_VALUE_SIGNAL (*arg).f, NULL,
+ GTK_VALUE_SIGNAL (*arg).d,
+ NULL,
+ (arg_id == ARG_OBJECT_SIGNAL ||
+ arg_id == ARG_OBJECT_SIGNAL_AFTER),
+ (arg_id == ARG_OBJECT_SIGNAL_AFTER ||
+ arg_id == ARG_SIGNAL_AFTER));
}
- gtk_signal_connect_object (object, arg->name + 9 + 2 + 13 + 2,
- (GtkSignalFunc) GTK_VALUE_SIGNAL (*arg).f,
- (GtkObject*) GTK_VALUE_SIGNAL (*arg).d);
+ else
+ g_warning ("gtk_object_set_arg(): invalid signal argument: \"%s\"\n", arg->name);
break;
default:
- arg->type = GTK_TYPE_INVALID;
break;
}
}
-/*****************************************
- * gtk_object_get_arg:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
static void
gtk_object_get_arg (GtkObject *object,
GtkArg *arg,
void
gtk_object_class_add_signals (GtkObjectClass *class,
- gint *signals,
- gint nsignals)
+ guint *signals,
+ guint nsignals)
{
- gint *new_signals;
- gint i;
+ guint *new_signals;
+ guint i;
g_return_if_fail (class != NULL);
- new_signals = g_new (gint, class->nsignals + nsignals);
+ new_signals = g_new (guint, class->nsignals + nsignals);
for (i = 0; i < class->nsignals; i++)
new_signals[i] = class->signals[i];
for (i = 0; i < nsignals; i++)
class->nsignals += nsignals;
}
-/*****************************************
- * gtk_object_class_add_user_signal:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-gint
+guint
gtk_object_class_add_user_signal (GtkObjectClass *class,
const gchar *name,
GtkSignalMarshaller marshaller,
GtkType return_val,
- gint nparams,
+ guint nparams,
...)
{
GtkType *params;
guint i;
va_list args;
- gint signal_id;
+ guint signal_id;
g_return_val_if_fail (class != NULL, 0);
return signal_id;
}
-/*****************************************
- * gtk_object_finalize:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-static void
-gtk_object_finalize (GtkObject *object)
+guint
+gtk_object_class_user_signal_new (GtkObjectClass *class,
+ const gchar *name,
+ GtkSignalRunType signal_flags,
+ GtkSignalMarshaller marshaller,
+ GtkType return_val,
+ guint nparams,
+ ...)
{
- GtkObjectData *odata, *next;
-
- odata = object->object_data;
- while (odata)
+ GtkType *params;
+ guint i;
+ va_list args;
+ guint signal_id;
+
+ g_return_val_if_fail (class != NULL, 0);
+
+ if (nparams > 0)
{
- next = odata->next;
- gtk_object_data_destroy (odata);
- odata = next;
+ params = g_new (GtkType, nparams);
+
+ va_start (args, nparams);
+
+ for (i = 0; i < nparams; i++)
+ params[i] = va_arg (args, GtkType);
+
+ va_end (args);
}
-
- g_free (object);
+ else
+ params = NULL;
+
+ signal_id = gtk_signal_newv (name,
+ signal_flags,
+ class->type,
+ 0,
+ marshaller,
+ return_val,
+ nparams,
+ params);
+
+ g_free (params);
+
+ if (signal_id)
+ gtk_object_class_add_signals (class, &signal_id, 1);
+
+ return signal_id;
+}
+
+guint
+gtk_object_class_user_signal_newv (GtkObjectClass *class,
+ const gchar *name,
+ GtkSignalRunType signal_flags,
+ GtkSignalMarshaller marshaller,
+ GtkType return_val,
+ guint nparams,
+ GtkType *params)
+{
+ guint signal_id;
+
+ g_return_val_if_fail (class != NULL, 0);
+
+ if (nparams > 0)
+ g_return_val_if_fail (params != NULL, 0);
+
+ signal_id = gtk_signal_newv (name,
+ signal_flags,
+ class->type,
+ 0,
+ marshaller,
+ return_val,
+ nparams,
+ params);
+
+ if (signal_id)
+ gtk_object_class_add_signals (class, &signal_id, 1);
+
+ return signal_id;
}
/*****************************************
}
}
-/*****************************************
- * gtk_object_destroy:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-void
-gtk_object_destroy (GtkObject *object)
-{
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_OBJECT (object));
-
- if (!GTK_OBJECT_DESTROYED (object))
- {
- GTK_OBJECT_SET_FLAGS (object, GTK_DESTROYED);
- gtk_signal_emit (object, object_signals[DESTROY]);
- }
-}
-
/*****************************************
* Weak references.
*
* referenced object is finalized.
*
* They are not implemented as a signal because they really are
- * special and need to be used with great care. Unlike signals, who
+ * special and need to be used with great care. Unlike signals, which
* should be able to execute any code whatsoever.
*
* A weakref callback is not allowed to retain a reference to the
- * object. In fact, the object is no longer there at all when it is
- * called.
+ * object. Object data keys may be retrieved in a weak reference
+ * callback.
*
- * A weakref callback is called atmost once.
+ * A weakref callback is called at most once.
*
*****************************************/
gpointer data;
};
-static const gchar *weakrefs_key = "gtk-weakrefs";
-
void
gtk_object_weakref (GtkObject *object,
GtkDestroyNotify notify,
g_return_if_fail (notify != NULL);
g_return_if_fail (GTK_IS_OBJECT (object));
+ if (!weakrefs_key_id)
+ weakrefs_key_id = g_quark_from_static_string (weakrefs_key);
+
weak = g_new (GtkWeakRef, 1);
- weak->next = gtk_object_get_data (object, weakrefs_key);
+ weak->next = gtk_object_get_data_by_id (object, weakrefs_key_id);
weak->notify = notify;
weak->data = data;
- gtk_object_set_data_full (object, weakrefs_key, weak,
- gtk_object_notify_weaks);
+ gtk_object_set_data_by_id (object, weakrefs_key_id, weak);
}
void
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_OBJECT (object));
- weaks = gtk_object_get_data (object, weakrefs_key);
+ if (!weakrefs_key_id)
+ return;
+
+ weaks = gtk_object_get_data_by_id (object, weakrefs_key_id);
for (wp = &weaks; *wp; wp = &(*wp)->next)
{
w = *wp;
if (w->notify == notify && w->data == data)
{
if (w == weaks)
- gtk_object_set_data_full (object, weakrefs_key, w->next,
- gtk_object_notify_weaks);
+ gtk_object_set_data_by_id (object, weakrefs_key_id, w->next);
else
*wp = w->next;
g_free (w);
}
static void
-gtk_object_notify_weaks (gpointer data)
+gtk_object_notify_weaks (GtkObject *object)
{
- GtkWeakRef *w1, *w2;
-
- w1 = (GtkWeakRef *)data;
-
- while (w1)
+ if (weakrefs_key_id)
{
- w1->notify (w1->data);
- w2 = w1->next;
- g_free (w1);
- w1 = w2;
+ GtkWeakRef *w1, *w2;
+
+ w1 = gtk_object_get_data_by_id (object, weakrefs_key_id);
+
+ while (w1)
+ {
+ w1->notify (w1->data);
+ w2 = w1->next;
+ g_free (w1);
+ w1 = w2;
+ }
}
}
-/*****************************************
- * gtk_object_new:
- *
- * arguments:
+/****************************************************
+ * GtkObject argument mechanism and object creation
*
- * results:
- *****************************************/
+ ****************************************************/
GtkObject*
-gtk_object_new (guint type,
+gtk_object_new (GtkType object_type,
...)
{
- GtkObject *obj;
- GtkArg *args;
- guint nargs;
- va_list args1;
- va_list args2;
-
- obj = gtk_type_new (type);
-
- va_start (args1, type);
- va_start (args2, type);
-
- args = gtk_object_collect_args (&nargs, args1, args2);
- gtk_object_setv (obj, nargs, args);
- g_free (args);
-
- va_end (args1);
- va_end (args2);
+ GtkObject *object;
+ va_list var_args;
+ GSList *arg_list = NULL;
+ GSList *info_list = NULL;
+ gchar *error;
+
+ g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (object_type) == GTK_TYPE_OBJECT, NULL);
+
+ object = gtk_type_new (object_type);
+
+ va_start (var_args, object_type);
+ error = gtk_object_args_collect (GTK_OBJECT_TYPE (object),
+ &arg_list,
+ &info_list,
+ &var_args);
+ va_end (var_args);
+
+ if (error)
+ {
+ g_warning ("gtk_object_new(): %s", error);
+ g_free (error);
+ }
+ else
+ {
+ GSList *slist_arg;
+ GSList *slist_info;
+
+ slist_arg = arg_list;
+ slist_info = info_list;
+ while (slist_arg)
+ {
+ gtk_object_arg_set (object, slist_arg->data, slist_info->data);
+ slist_arg = slist_arg->next;
+ slist_info = slist_info->next;
+ }
+ gtk_args_collect_cleanup (arg_list, info_list);
+ }
- return obj;
+ return object;
}
-/*****************************************
- * gtk_object_newv:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
GtkObject*
-gtk_object_newv (guint type,
- guint nargs,
- GtkArg *args)
+gtk_object_newv (GtkType object_type,
+ guint n_args,
+ GtkArg *args)
{
- gpointer obj;
+ GtkObject *object;
+ GtkArg *max_args;
+
+ g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (object_type) == GTK_TYPE_OBJECT, NULL);
+ if (n_args)
+ g_return_val_if_fail (args != NULL, NULL);
+
+ object = gtk_type_new (object_type);
+
+ for (max_args = args + n_args; args < max_args; args++)
+ gtk_object_arg_set (object, args, NULL);
+
+ return object;
+}
- obj = gtk_type_new (type);
- gtk_object_setv (obj, nargs, args);
+void
+gtk_object_setv (GtkObject *object,
+ guint n_args,
+ GtkArg *args)
+{
+ GtkArg *max_args;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+ if (n_args)
+ g_return_if_fail (args != NULL);
- return obj;
+ for (max_args = args + n_args; args < max_args; args++)
+ gtk_object_arg_set (object, args, NULL);
}
-/*****************************************
- * gtk_object_getv:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
void
gtk_object_getv (GtkObject *object,
- guint nargs,
+ guint n_args,
GtkArg *args)
{
- int i;
+ GtkArg *max_args;
g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+ if (n_args)
+ g_return_if_fail (args != NULL);
- if (!arg_info_ht)
- return;
-
- for (i = 0; i < nargs; i++)
- {
- GtkArgInfo *info;
- gchar *lookup_name;
- gchar *d;
-
-
- /* hm, the name cutting shouldn't be needed on gets, but what the heck...
- */
- lookup_name = g_strdup (args[i].name);
- d = strchr (lookup_name, ':');
- if (d && d[1] == ':')
- {
- d = strchr (d + 2, ':');
- if (d)
- *d = 0;
-
- info = g_hash_table_lookup (arg_info_ht, lookup_name);
- }
- else
- info = NULL;
-
- if (!info)
- {
- g_warning ("invalid arg name: \"%s\"\n", lookup_name);
- args[i].type = GTK_TYPE_INVALID;
- g_free (lookup_name);
- continue;
- }
- else if (!gtk_type_is_a (object->klass->type, info->class_type))
- {
- g_warning ("invalid arg for %s: \"%s\"\n", gtk_type_name (object->klass->type), lookup_name);
- args[i].type = GTK_TYPE_INVALID;
- g_free (lookup_name);
- continue;
- }
- else if (!info->arg_flags & GTK_ARG_READABLE)
- {
- g_warning ("arg is not supplied for read-access: \"%s\"\n", lookup_name);
- args[i].type = GTK_TYPE_INVALID;
- g_free (lookup_name);
- continue;
- }
- else
- g_free (lookup_name);
-
- args[i].type = info->type;
- gtk_type_get_arg (object, info->class_type, &args[i], info->arg_id);
- }
-}
-
-/*****************************************
- * gtk_object_query_args:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-struct _GtkQueryArgData
-{
- GList *arg_list;
- GtkType class_type;
-};
-typedef struct _GtkQueryArgData GtkQueryArgData;
-
-static void
-gtk_query_arg_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- register GtkArgInfo *info;
- register GtkQueryArgData *data;
-
- info = value;
- data = user_data;
-
- if (info->class_type == data->class_type)
- data->arg_list = g_list_prepend (data->arg_list, info);
-}
-
-GtkArg*
-gtk_object_query_args (GtkType class_type,
- guint32 **arg_flags,
- guint *nargs)
-{
- GtkArg *args;
- GtkQueryArgData query_data;
-
- if (arg_flags)
- *arg_flags = NULL;
- g_return_val_if_fail (nargs != NULL, NULL);
- *nargs = 0;
- g_return_val_if_fail (gtk_type_is_a (class_type, gtk_object_get_type ()), NULL);
-
- if (!arg_info_ht)
- return NULL;
-
- /* make sure the types class has been initialized, because
- * the argument setup happens in the gtk_*_class_init() functions.
- */
- gtk_type_class (class_type);
-
- query_data.arg_list = NULL;
- query_data.class_type = class_type;
- g_hash_table_foreach (arg_info_ht, gtk_query_arg_foreach, &query_data);
-
- if (query_data.arg_list)
- {
- register GList *list;
- register guint len;
-
- list = query_data.arg_list;
- len = 1;
- while (list->next)
- {
- len++;
- list = list->next;
- }
- g_assert (len == ((GtkObjectClass*) gtk_type_class (class_type))->n_args); /* paranoid */
-
- args = g_new0 (GtkArg, len);
- *nargs = len;
- if (arg_flags)
- *arg_flags = g_new (guint32, len);
-
- do
- {
- GtkArgInfo *info;
-
- info = list->data;
- list = list->prev;
-
- g_assert (info->seq_id > 0 && info->seq_id <= len); /* paranoid */
-
- args[info->seq_id - 1].type = info->type;
- args[info->seq_id - 1].name = info->name;
- if (arg_flags)
- (*arg_flags)[info->seq_id - 1] = info->arg_flags;
- }
- while (list);
-
- g_list_free (query_data.arg_list);
- }
- else
- args = NULL;
-
- return args;
+ for (max_args = args + n_args; args < max_args; args++)
+ gtk_object_arg_get (object, args, NULL);
}
-/*****************************************
- * gtk_object_set:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
void
gtk_object_set (GtkObject *object,
...)
{
- GtkArg *args;
- guint nargs;
- va_list args1;
- va_list args2;
-
+ va_list var_args;
+ GSList *arg_list = NULL;
+ GSList *info_list = NULL;
+ gchar *error;
+
g_return_if_fail (object != NULL);
-
- va_start (args1, object);
- va_start (args2, object);
-
- args = gtk_object_collect_args (&nargs, args1, args2);
- gtk_object_setv (object, nargs, args);
- g_free (args);
-
- va_end (args1);
- va_end (args2);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+
+ va_start (var_args, object);
+ error = gtk_object_args_collect (GTK_OBJECT_TYPE (object),
+ &arg_list,
+ &info_list,
+ &var_args);
+ va_end (var_args);
+
+ if (error)
+ {
+ g_warning ("gtk_object_set(): %s", error);
+ g_free (error);
+ }
+ else
+ {
+ GSList *slist_arg;
+ GSList *slist_info;
+
+ slist_arg = arg_list;
+ slist_info = info_list;
+ while (slist_arg)
+ {
+ gtk_object_arg_set (object, slist_arg->data, slist_info->data);
+ slist_arg = slist_arg->next;
+ slist_info = slist_info->next;
+ }
+ gtk_args_collect_cleanup (arg_list, info_list);
+ }
}
-/*****************************************
- * gtk_object_setv:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
void
-gtk_object_setv (GtkObject *object,
- guint nargs,
- GtkArg *args)
+gtk_object_arg_set (GtkObject *object,
+ GtkArg *arg,
+ GtkArgInfo *info)
{
- int i;
+ GtkObjectClass *oclass;
g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+ g_return_if_fail (arg != NULL);
- if (!arg_info_ht)
- return;
-
- for (i = 0; i < nargs; i++)
+ if (!info)
{
- GtkArgInfo *info;
- gchar *lookup_name;
- gchar *d;
- gboolean arg_ok;
-
- lookup_name = g_strdup (args[i].name);
- d = strchr (lookup_name, ':');
- if (d && d[1] == ':')
- {
- d = strchr (d + 2, ':');
- if (d)
- *d = 0;
+ gchar *error;
- info = g_hash_table_lookup (arg_info_ht, lookup_name);
- }
- else
- info = NULL;
-
- arg_ok = TRUE;
-
- if (!info)
- {
- g_warning ("invalid arg name: \"%s\"\n", lookup_name);
- arg_ok = FALSE;
- }
- else if (info->type != args[i].type)
- {
- g_warning ("invalid arg type for: \"%s\"\n", lookup_name);
- arg_ok = FALSE;
- }
- else if (!gtk_type_is_a (object->klass->type, info->class_type))
- {
- g_warning ("invalid arg for %s: \"%s\"\n", gtk_type_name (object->klass->type), lookup_name);
- arg_ok = FALSE;
- }
- else if (!info->arg_flags & GTK_ARG_WRITABLE)
+ error = gtk_arg_get_info (GTK_OBJECT_TYPE (object),
+ object_arg_info_ht,
+ arg->name,
+ &info);
+ if (error)
{
- g_warning ("arg is not supplied for write-access: \"%s\"\n", lookup_name);
- arg_ok = FALSE;
+ g_warning ("gtk_object_arg_set(): %s", error);
+ g_free (error);
+ return;
}
-
- g_free (lookup_name);
-
- if (!arg_ok)
- continue;
-
- gtk_type_set_arg (object, info->class_type, &args[i], info->arg_id);
}
-}
-
-/*****************************************
- * gtk_object_add_arg_type:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-void
-gtk_object_add_arg_type (const char *arg_name,
- GtkType arg_type,
- guint arg_flags,
- guint arg_id)
-{
- GtkArgInfo *info;
- gchar class_part[1024];
- gchar *arg_part;
- GtkType class_type;
-
- g_return_if_fail (arg_name != NULL);
- g_return_if_fail (arg_type > GTK_TYPE_NONE);
- g_return_if_fail (arg_id > 0);
- g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) != 0);
- arg_part = strchr (arg_name, ':');
- if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':'))
+ if (! (info->arg_flags & GTK_ARG_WRITABLE))
{
- g_warning ("invalid arg name: \"%s\"\n", arg_name);
+ g_warning ("gtk_object_arg_set(): argument \"%s\" is not writable",
+ info->full_name);
return;
}
-
- strncpy (class_part, arg_name, (glong) (arg_part - arg_name));
- class_part[(glong) (arg_part - arg_name)] = '\0';
-
- class_type = gtk_type_from_name (class_part);
- if (!class_type)
+ if (info->type != arg->type)
{
- g_warning ("invalid class name in arg: \"%s\"\n", arg_name);
+ g_warning ("gtk_object_arg_set(): argument \"%s\" has invalid type `%s'",
+ info->full_name,
+ gtk_type_name (arg->type));
return;
}
-
- info = g_new (GtkArgInfo, 1);
- info->name = g_strdup (arg_name);
- info->type = arg_type;
- info->class_type = class_type;
- info->arg_flags = arg_flags & (GTK_ARG_READABLE | GTK_ARG_WRITABLE);
- info->arg_id = arg_id;
- info->seq_id = ++((GtkObjectClass*) gtk_type_class (class_type))->n_args;
-
- if (!arg_info_ht)
- arg_info_ht = g_hash_table_new (g_str_hash, g_str_equal);
-
- g_hash_table_insert (arg_info_ht, info->name, info);
-}
-
-/*****************************************
- * gtk_object_get_arg_type:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-GtkType
-gtk_object_get_arg_type (const char *arg_name)
-{
- GtkArgInfo *info;
- char buffer[1024];
- char *t;
-
- if (!arg_info_ht)
- return GTK_TYPE_INVALID;
-
- t = strchr (arg_name, ':');
- if (!t || (t[0] != ':') || (t[1] != ':'))
- {
- g_warning ("invalid arg name: \"%s\"\n", arg_name);
- return GTK_TYPE_INVALID;
- }
-
- t = strchr (t + 2, ':');
- if (t)
- {
- strncpy (buffer, arg_name, (long) (t - arg_name));
- buffer[(long) (t - arg_name)] = '\0';
- arg_name = buffer;
- }
-
- info = g_hash_table_lookup (arg_info_ht, (gpointer) arg_name);
- if (info)
- return info->type;
-
- return GTK_TYPE_INVALID;
-}
-
-/*****************************************
- * gtk_object_set_data:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-void
-gtk_object_set_data (GtkObject *object,
- const gchar *key,
- gpointer data)
-{
- gtk_object_set_data_full (object, key, data, NULL);
+
+ oclass = gtk_type_class (info->class_type);
+ g_assert (oclass->set_arg != NULL);
+ oclass->set_arg (object, arg, info->arg_id);
}
-/*****************************************
- * gtk_object_set_data_full:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
void
-gtk_object_set_data_full (GtkObject *object,
- const gchar *key,
- gpointer data,
- GtkDestroyNotify destroy)
+gtk_object_arg_get (GtkObject *object,
+ GtkArg *arg,
+ GtkArgInfo *info)
{
- GtkObjectData *odata;
- GtkObjectData *prev;
- guint *id;
-
+ GtkObjectClass *oclass;
+
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_OBJECT (object));
- g_return_if_fail (key != NULL);
-
- if (object_data_init)
- gtk_object_data_init ();
+ g_return_if_fail (arg != NULL);
- id = g_hash_table_lookup (object_data_ht, (gpointer) key);
-
- if (!data)
+ if (!info)
{
- if (id)
- {
- prev = NULL;
- odata = object->object_data;
-
- while (odata)
- {
- if (odata->id == *id)
- {
- if (prev)
- prev->next = odata->next;
- if (odata == object->object_data)
- object->object_data = odata->next;
-
- gtk_object_data_destroy (odata);
- break;
- }
-
- prev = odata;
- odata = odata->next;
- }
- }
- }
- else
- {
- if (!id)
- {
- id = gtk_object_data_id_alloc ();
- g_hash_table_insert (object_data_ht, (gpointer) key, id);
- }
+ gchar *error;
- odata = object->object_data;
- while (odata)
+ error = gtk_arg_get_info (GTK_OBJECT_TYPE (object),
+ object_arg_info_ht,
+ arg->name,
+ &info);
+ if (error)
{
- if (odata->id == *id)
- {
- odata->data = data;
- odata->destroy = destroy;
- return;
- }
-
- odata = odata->next;
+ g_warning ("gtk_object_arg_get(): %s", error);
+ g_free (error);
+ arg->type = GTK_TYPE_INVALID;
+ return;
}
-
- odata = gtk_object_data_new ();
- odata->id = *id;
- odata->data = data;
- odata->destroy = destroy;
-
- odata->next = object->object_data;
- object->object_data = odata;
}
-}
-
-/*****************************************
- * gtk_object_get_data:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-gpointer
-gtk_object_get_data (GtkObject *object,
- const gchar *key)
-{
- GtkObjectData *odata;
- guint *id;
-
- g_return_val_if_fail (object != NULL, NULL);
- g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
- g_return_val_if_fail (key != NULL, NULL);
-
- if (object_data_init)
- gtk_object_data_init ();
-
- id = g_hash_table_lookup (object_data_ht, (gpointer) key);
- if (id)
+
+ if (! (info->arg_flags & GTK_ARG_READABLE))
{
- odata = object->object_data;
- while (odata)
- {
- if (odata->id == *id)
- return odata->data;
- odata = odata->next;
- }
+ g_warning ("gtk_object_arg_get(): argument \"%s\" is not readable",
+ info->full_name);
+ arg->type = GTK_TYPE_INVALID;
+ return;
}
-
- return NULL;
+
+ oclass = gtk_type_class (info->class_type);
+ g_assert (oclass->get_arg != NULL);
+ arg->type = info->type;
+ oclass->get_arg (object, arg, info->arg_id);
}
-/*****************************************
- * gtk_object_remove_data:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
void
-gtk_object_remove_data (GtkObject *object,
- const gchar *key)
+gtk_object_add_arg_type (const char *arg_name,
+ GtkType arg_type,
+ guint arg_flags,
+ guint arg_id)
{
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_OBJECT (object));
- g_return_if_fail (key != NULL);
-
- gtk_object_set_data_full (object, key, NULL, NULL);
+ g_return_if_fail (arg_name != NULL);
+ g_return_if_fail (arg_type > GTK_TYPE_NONE);
+ g_return_if_fail (arg_id > 0);
+ g_return_if_fail ((arg_flags & GTK_ARG_CHILD_ARG) == 0);
+ if (arg_flags & GTK_ARG_CONSTRUCT)
+ g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) == GTK_ARG_READWRITE);
+ else
+ g_return_if_fail ((arg_flags & GTK_ARG_READWRITE) != 0);
+
+ if (!object_arg_info_ht)
+ object_arg_info_ht = g_hash_table_new (gtk_arg_info_hash,
+ gtk_arg_info_equal);
+
+ gtk_arg_type_new_static (GTK_TYPE_OBJECT,
+ arg_name,
+ GTK_STRUCT_OFFSET (GtkObjectClass, n_args),
+ object_arg_info_ht,
+ arg_type,
+ arg_flags,
+ arg_id);
}
-/*****************************************
- * gtk_object_set_user_data:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-void
-gtk_object_set_user_data (GtkObject *object,
- gpointer data)
+gchar*
+gtk_object_args_collect (GtkType object_type,
+ GSList **arg_list_p,
+ GSList **info_list_p,
+ gpointer var_args_p)
{
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_OBJECT (object));
-
- gtk_object_set_data_full (object, user_data_key, data, NULL);
+ return gtk_args_collect (object_type,
+ object_arg_info_ht,
+ arg_list_p,
+ info_list_p,
+ var_args_p);
}
-/*****************************************
- * gtk_object_get_user_data:
- *
- * arguments:
- *
- * results:
- *****************************************/
+gchar*
+gtk_object_arg_get_info (GtkType object_type,
+ const gchar *arg_name,
+ GtkArgInfo **info_p)
+{
+ return gtk_arg_get_info (object_type,
+ object_arg_info_ht,
+ arg_name,
+ info_p);
+}
-gpointer
-gtk_object_get_user_data (GtkObject *object)
+GtkArg*
+gtk_object_query_args (GtkType class_type,
+ guint32 **arg_flags,
+ guint *n_args)
{
- g_return_val_if_fail (object != NULL, NULL);
- g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (n_args != NULL, NULL);
+ *n_args = 0;
+ g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (class_type) == GTK_TYPE_OBJECT, NULL);
- return gtk_object_get_data (object, user_data_key);
+ return gtk_args_query (class_type, object_arg_info_ht, arg_flags, n_args);
}
-/*****************************************
- * gtk_object_check_cast:
- *
- * arguments:
+/********************************************************
+ * GtkObject and GtkObjectClass cast checking functions
*
- * results:
- *****************************************/
+ ********************************************************/
static gchar*
gtk_object_descriptive_type_name (GtkType type)
return obj;
}
-/*****************************************
- * gtk_object_check_class_cast:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
GtkObjectClass*
gtk_object_check_class_cast (GtkObjectClass *klass,
GtkType cast_type)
}
/*****************************************
- * gtk_object_data_init:
- *
- * arguments:
+ * GtkObject object_data mechanism
*
- * results:
*****************************************/
-static void
-gtk_object_data_init ()
+void
+gtk_object_set_data_by_id (GtkObject *object,
+ GQuark data_id,
+ gpointer data)
{
- if (object_data_init)
- {
- object_data_init = FALSE;
-
- object_data_ht = g_hash_table_new (g_str_hash, g_str_equal);
- }
+ g_return_if_fail (data_id > 0);
+
+ gtk_object_set_data_by_id_full (object, data_id, data, NULL);
}
-/*****************************************
- * gtk_object_data_new:
- *
- * arguments:
- *
- * results:
- *****************************************/
+void
+gtk_object_set_data (GtkObject *object,
+ const gchar *key,
+ gpointer data)
+{
+ g_return_if_fail (key != NULL);
+
+ gtk_object_set_data_by_id_full (object, gtk_object_data_force_id (key), data, NULL);
+}
-static GtkObjectData*
-gtk_object_data_new ()
+void
+gtk_object_set_data_by_id_full (GtkObject *object,
+ GQuark data_id,
+ gpointer data,
+ GtkDestroyNotify destroy)
{
GtkObjectData *odata;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_OBJECT (object));
+ g_return_if_fail (data_id > 0);
- if (!object_data_mem_chunk)
- object_data_mem_chunk = g_mem_chunk_new ("object data mem chunk",
- sizeof (GtkObjectData),
- 1024, G_ALLOC_AND_FREE);
-
- odata = g_chunk_new (GtkObjectData, object_data_mem_chunk);
+ odata = object->object_data;
+ if (!data)
+ {
+ GtkObjectData *prev;
+
+ prev = NULL;
+
+ while (odata)
+ {
+ if (odata->id == data_id)
+ {
+ if (prev)
+ prev->next = odata->next;
+ else
+ object->object_data = odata->next;
+
+ GTK_OBJECT_DATA_DESTROY (odata);
+ return;
+ }
+
+ prev = odata;
+ odata = odata->next;
+ }
+ }
+ else
+ {
+ while (odata)
+ {
+ if (odata->id == data_id)
+ {
+ register GtkDestroyNotify dfunc;
+ register gpointer ddata;
- odata->id = 0;
- odata->data = NULL;
- odata->destroy = NULL;
- odata->next = NULL;
+ dfunc = odata->destroy;
+ ddata = odata->data;
+ odata->destroy = destroy;
+ odata->data = data;
- return odata;
-}
+ /* we need to have updated all structures prior to
+ * invokation of the destroy function
+ */
+ if (dfunc)
+ dfunc (ddata);
-/*****************************************
- * gtk_object_data_destroy:
- *
- * arguments:
- *
- * results:
- *****************************************/
+ return;
+ }
-static void
-gtk_object_data_destroy (GtkObjectData *odata)
-{
- g_return_if_fail (odata != NULL);
+ odata = odata->next;
+ }
+
+ if (gtk_object_data_free_list)
+ {
+ odata = gtk_object_data_free_list;
+ gtk_object_data_free_list = odata->next;
+ }
+ else
+ {
+ GtkObjectData *odata_block;
+ guint i;
- if (odata->destroy)
- odata->destroy (odata->data);
+ odata_block = g_new0 (GtkObjectData, GTK_OBJECT_DATA_BLOCK_SIZE);
+ for (i = 1; i < GTK_OBJECT_DATA_BLOCK_SIZE; i++)
+ {
+ (odata_block + i)->next = gtk_object_data_free_list;
+ gtk_object_data_free_list = (odata_block + i);
+ }
- g_mem_chunk_free (object_data_mem_chunk, odata);
+ odata = odata_block;
+ }
+
+ odata->id = data_id;
+ odata->data = data;
+ odata->destroy = destroy;
+ odata->next = object->object_data;
+
+ object->object_data = odata;
+ }
}
-/*****************************************
- * gtk_object_data_id_alloc:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-static guint*
-gtk_object_data_id_alloc ()
+void
+gtk_object_set_data_full (GtkObject *object,
+ const gchar *key,
+ gpointer data,
+ GtkDestroyNotify destroy)
{
- static guint next_id = 1;
- guint *ids;
-
- if (!object_data_id_list ||
- (object_data_id_index == OBJECT_DATA_ID_CHUNK))
- {
- ids = g_new (guint, OBJECT_DATA_ID_CHUNK);
- object_data_id_index = 0;
- object_data_id_list = g_slist_prepend (object_data_id_list, ids);
- }
- else
- {
- ids = object_data_id_list->data;
- }
+ g_return_if_fail (key != NULL);
- ids[object_data_id_index] = next_id++;
- return &ids[object_data_id_index++];
+ gtk_object_set_data_by_id_full (object, gtk_object_data_force_id (key), data, destroy);
}
-/*****************************************
- * gtk_object_collect_args:
- *
- * arguments:
- *
- * results:
- *****************************************/
-
-GtkArg*
-gtk_object_collect_args (guint *nargs,
- va_list args1,
- va_list args2)
+gpointer
+gtk_object_get_data_by_id (GtkObject *object,
+ GQuark data_id)
{
- GtkArg *args;
- GtkType type;
- gchar *name;
- gint done;
- gint i, n;
+ GtkObjectData *odata;
- n = 0;
- done = FALSE;
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
- while (!done)
+ if (data_id)
{
- name = va_arg (args1, char *);
- if (!name)
+ odata = object->object_data;
+ while (odata)
{
- done = TRUE;
- continue;
+ if (odata->id == data_id)
+ return odata->data;
+ odata = odata->next;
}
+ }
+
+ return NULL;
+}
- type = gtk_object_get_arg_type (name);
+gpointer
+gtk_object_get_data (GtkObject *object,
+ const gchar *key)
+{
+ guint id;
- switch (GTK_FUNDAMENTAL_TYPE (type))
- {
- case GTK_TYPE_INVALID:
- g_warning ("invalid arg name: \"%s\" %x\n", name, type);
- (void) va_arg (args1, long);
- continue;
- case GTK_TYPE_NONE:
- break;
- case GTK_TYPE_CHAR:
- case GTK_TYPE_BOOL:
- case GTK_TYPE_INT:
- case GTK_TYPE_UINT:
- case GTK_TYPE_ENUM:
- case GTK_TYPE_FLAGS:
- (void) va_arg (args1, gint);
- break;
- case GTK_TYPE_LONG:
- case GTK_TYPE_ULONG:
- (void) va_arg (args1, glong);
- break;
- case GTK_TYPE_FLOAT:
- (void) va_arg (args1, gfloat);
- break;
- case GTK_TYPE_DOUBLE:
- (void) va_arg (args1, gdouble);
- break;
- case GTK_TYPE_STRING:
- (void) va_arg (args1, gchar*);
- break;
- case GTK_TYPE_POINTER:
- case GTK_TYPE_BOXED:
- (void) va_arg (args1, gpointer);
- break;
- case GTK_TYPE_SIGNAL:
- (void) va_arg (args1, GtkFunction);
- (void) va_arg (args1, gpointer);
- break;
- case GTK_TYPE_FOREIGN:
- (void) va_arg (args1, gpointer);
- (void) va_arg (args1, GtkDestroyNotify);
- break;
- case GTK_TYPE_CALLBACK:
- (void) va_arg (args1, GtkCallbackMarshal);
- (void) va_arg (args1, gpointer);
- (void) va_arg (args1, GtkDestroyNotify);
- break;
- case GTK_TYPE_C_CALLBACK:
- (void) va_arg (args1, GtkFunction);
- (void) va_arg (args1, gpointer);
- break;
- case GTK_TYPE_ARGS:
- (void) va_arg (args1, gint);
- (void) va_arg (args1, GtkArg*);
- break;
- case GTK_TYPE_OBJECT:
- (void) va_arg (args1, GtkObject*);
- break;
- default:
- g_error ("unsupported type %s in args", gtk_type_name (type));
- break;
- }
+ g_return_val_if_fail (key != NULL, NULL);
- n += 1;
- }
+ id = gtk_object_data_try_key (key);
+ if (id)
+ return gtk_object_get_data_by_id (object, id);
- *nargs = n;
- args = NULL;
+ return NULL;
+}
- if (n > 0)
- {
- args = g_new0 (GtkArg, n);
+void
+gtk_object_remove_data_by_id (GtkObject *object,
+ GQuark data_id)
+{
+ if (data_id)
+ gtk_object_set_data_by_id_full (object, data_id, NULL, NULL);
+}
- for (i = 0; i < n; i++)
- {
- args[i].name = va_arg (args2, char *);
- args[i].type = gtk_object_get_arg_type (args[i].name);
+void
+gtk_object_remove_data (GtkObject *object,
+ const gchar *key)
+{
+ gint id;
- switch (GTK_FUNDAMENTAL_TYPE (args[i].type))
- {
- case GTK_TYPE_INVALID:
- (void) va_arg (args2, long);
- i -= 1;
- continue;
- case GTK_TYPE_NONE:
- break;
- case GTK_TYPE_CHAR:
- GTK_VALUE_CHAR(args[i]) = va_arg (args2, gint);
- break;
- case GTK_TYPE_BOOL:
- GTK_VALUE_BOOL(args[i]) = va_arg (args2, gint);
- break;
- case GTK_TYPE_INT:
- GTK_VALUE_INT(args[i]) = va_arg (args2, gint);
- break;
- case GTK_TYPE_UINT:
- GTK_VALUE_UINT(args[i]) = va_arg (args2, guint);
- break;
- case GTK_TYPE_ENUM:
- GTK_VALUE_ENUM(args[i]) = va_arg (args2, gint);
- break;
- case GTK_TYPE_FLAGS:
- GTK_VALUE_FLAGS(args[i]) = va_arg (args2, gint);
- break;
- case GTK_TYPE_LONG:
- GTK_VALUE_LONG(args[i]) = va_arg (args2, glong);
- break;
- case GTK_TYPE_ULONG:
- GTK_VALUE_ULONG(args[i]) = va_arg (args2, gulong);
- break;
- case GTK_TYPE_FLOAT:
- GTK_VALUE_FLOAT(args[i]) = va_arg (args2, gfloat);
- break;
- case GTK_TYPE_DOUBLE:
- GTK_VALUE_DOUBLE(args[i]) = va_arg (args2, gdouble);
- break;
- case GTK_TYPE_STRING:
- GTK_VALUE_STRING(args[i]) = va_arg (args2, gchar*);
- break;
- case GTK_TYPE_POINTER:
- GTK_VALUE_POINTER(args[i]) = va_arg (args2, gpointer);
- break;
- case GTK_TYPE_BOXED:
- GTK_VALUE_BOXED(args[i]) = va_arg (args2, gpointer);
- break;
- case GTK_TYPE_SIGNAL:
- GTK_VALUE_SIGNAL(args[i]).f = va_arg (args2, GtkFunction);
- GTK_VALUE_SIGNAL(args[i]).d = va_arg (args2, gpointer);
- break;
- case GTK_TYPE_FOREIGN:
- GTK_VALUE_FOREIGN(args[i]).data = va_arg (args2, gpointer);
- GTK_VALUE_FOREIGN(args[i]).notify =
- va_arg (args2, GtkDestroyNotify);
- break;
- case GTK_TYPE_CALLBACK:
- GTK_VALUE_CALLBACK(args[i]).marshal =
- va_arg (args2, GtkCallbackMarshal);
- GTK_VALUE_CALLBACK(args[i]).data = va_arg (args2, gpointer);
- GTK_VALUE_CALLBACK(args[i]).notify =
- va_arg (args2, GtkDestroyNotify);
- break;
- case GTK_TYPE_C_CALLBACK:
- GTK_VALUE_C_CALLBACK(args[i]).func = va_arg (args2, GtkFunction);
- GTK_VALUE_C_CALLBACK(args[i]).func_data =
- va_arg (args2, gpointer);
- break;
- case GTK_TYPE_ARGS:
- GTK_VALUE_ARGS(args[i]).n_args = va_arg (args2, gint);
- GTK_VALUE_ARGS(args[i]).args = va_arg (args2, GtkArg*);
- break;
- case GTK_TYPE_OBJECT:
- GTK_VALUE_OBJECT(args[i]) = va_arg (args2, GtkObject*);
- g_assert (GTK_VALUE_OBJECT(args[i]) == NULL ||
- GTK_CHECK_TYPE (GTK_VALUE_OBJECT(args[i]),
- args[i].type));
- break;
- default:
- g_error ("unsupported type %s in args",
- gtk_type_name (args[i].type));
- break;
- }
- }
- }
+ g_return_if_fail (key != NULL);
- return args;
+ id = gtk_object_data_try_key (key);
+ if (id)
+ gtk_object_set_data_by_id_full (object, id, NULL, NULL);
}
+void
+gtk_object_set_user_data (GtkObject *object,
+ gpointer data)
+{
+ if (!user_data_key_id)
+ user_data_key_id = g_quark_from_static_string (user_data_key);
+
+ gtk_object_set_data_by_id_full (object, user_data_key_id, data, NULL);
+}
+gpointer
+gtk_object_get_user_data (GtkObject *object)
+{
+ if (user_data_key_id)
+ return gtk_object_get_data_by_id (object, user_data_key_id);
+
+ return NULL;
+}
+
+/*******************************************
+ * GtkObject referencing and unreferencing
+ *
+ *******************************************/
#undef gtk_object_ref
#undef gtk_object_unref
#ifdef G_ENABLE_DEBUG
if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
{
- g_assert (g_slist_find (living_objs, object));
- living_objs = g_slist_remove (living_objs, object);
+ g_assert (g_hash_table_lookup (living_objs_ht, object) == object);
+ g_hash_table_remove (living_objs_ht, object);
obj_count--;
}
#endif /* G_ENABLE_DEBUG */
}
}
-#ifdef G_ENABLE_DEBUG
-
static GtkObject *gtk_trace_object = NULL;
-
void
-gtk_trace_referencing (gpointer *o,
+gtk_trace_referencing (GtkObject *object,
const gchar *func,
- guint local_frame,
+ guint dummy,
guint line,
gboolean do_ref)
{
- gboolean exists;
- GtkObject *object = (GtkObject*) o;
-
if (gtk_debug_flags & GTK_DEBUG_OBJECTS)
{
+ gboolean exists = TRUE;
+
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_OBJECT (object));
- exists = (g_slist_find (living_objs, object) != NULL);
+#ifdef G_ENABLE_DEBUG
+ exists = g_hash_table_lookup (living_objs_ht, object) != NULL;
+#endif /* G_ENABLE_DEBUG */
if (exists &&
(object == gtk_trace_object ||
gtk_trace_object == (void*)42))
- printf ("trace: object_%s: (%s:%p)->ref_count=%d%s (%s_f%02d:%d)\n",
- do_ref ? "ref" : "unref",
- gtk_type_name (GTK_OBJECT_TYPE (object)),
- object,
- object->ref_count,
- do_ref ? " + 1" : " - 1 ",
- func,
- local_frame,
- line);
-
- if (!exists)
- printf ("trace: object_%s(%p): no such object! (%s_f%02d:%d)\n",
- do_ref ? "ref" : "unref",
- object,
- func,
- local_frame,
- line);
+ fprintf (stdout, "trace: object_%s: (%s:%p)->ref_count=%d %s (%s:%d)\n",
+ do_ref ? "ref" : "unref",
+ gtk_type_name (GTK_OBJECT_TYPE (object)),
+ object,
+ object->ref_count,
+ do_ref ? "+ 1" : "- 1",
+ func,
+ line);
+ else if (!exists)
+ fprintf (stdout, "trace: object_%s(%p): no such object! (%s:%d)\n",
+ do_ref ? "ref" : "unref",
+ object,
+ func,
+ line);
}
if (do_ref)
else
gtk_object_unref (object);
}
-
-#endif /* G_ENABLE_DEBUG */
-