From 347efc33b8007f5d2fe625d7c0e6a51fbb3a3438 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Thu, 9 Jul 1998 23:00:34 +0000 Subject: deleted most of the argument handling code, since that is now implemented Fri Jul 10 00:02:04 1998 Tim Janik * gtk/gtkcontainer.h: * gtk/gtkcontainer.c: deleted most of the argument handling code, since that is now implemented in gtkarg.c. similar to gtk_object_args_collect, we now export a new function gtk_container_child_args_collect(). for consistency with the object arguments, a few functions got renamed: gtk_container_child_arg_get -> gtk_container_child_get, gtk_container_child_arg_set -> gtk_container_child_set, gtk_container_child_arg_getv -> gtk_container_child_getv, gtk_container_child_arg_setv -> gtk_container_child_setv, gtk_container_add_with_argv -> gtk_container_addv. note, gtk_container_add_with_args() remained, because its equivalent would be gtk_container_add(,, ...) which would break all existing code. (gtk_container_add_child_arg_type): similar to gtk_object_add_arg_type, we expect the `arg_name' argument to be a const static string now. (gtk_container_get_child_arg_type): function removed. Thu Jul 9 07:03:04 1998 Tim Janik * gtk/gtkargcollector.c: new file which holds gtk_arg_collect_value(). this is a static inline function that collects command line arguments from a va_list. this file can just be included in all places that need this functionality. * gtk/gtkarg.h: * gtk/gtkarg.c: new files which implement most of the argument handling stuff from gtkobject.c. also collected a few more gtk_arg_* utility functions from else places. * gtk/gtkobject.h: * gtk/gtkobject.c: moved most of the argument handling code into gtkarg.c. we now export gtk_object_args_collect() as a non-public method with a blind va_list pointer. (gtk_object_add_arg_type): the `arg_name' argument is required to be a const static string now. (gtk_object_get_arg_type): function got removed. * gtk/gtkwidget.c: (gtk_widget_set): (gtk_widget_new): adaptions for gtk_object_args_collect(). * gtk/gtktypeutils.c (gtk_type_init_builtin_types): changed the internal fundamental type name so as to have a valid prefix, e.g. "bool"-> "gboolean", "string"->"GtkString" and somesuch, left "void" as is, though that should probably be something like GtkNone since the type itself is called GTK_TYPE_NONE. even the internal type names need to avoid name clashes and must live in their own namespace, several code portions rely on that. we should relly have typedefs such as typedef gchar* GtkString; so the fundamental type names can be used for code dumpers just like with all the Gtk/Gdk types. --- gtk/Makefile.am | 7 +- gtk/gtk.h | 1 + gtk/gtkarg.c | 458 ++++++++++++++++++++++ gtk/gtkarg.h | 94 +++++ gtk/gtkargcollector.c | 123 ++++++ gtk/gtkbindings.c | 47 ++- gtk/gtkbindings.h | 8 - gtk/gtkcontainer.c | 636 ++++++++++++------------------ gtk/gtkcontainer.h | 36 +- gtk/gtkobject.c | 1032 +++++++++++++++---------------------------------- gtk/gtkobject.h | 183 +++++---- gtk/gtksignal.c | 248 ++++-------- gtk/gtksignal.h | 6 +- gtk/gtktypeutils.c | 57 +-- gtk/gtktypeutils.h | 10 +- gtk/gtkwidget.c | 109 ++++-- gtk/testgtk.c | 46 ++- 17 files changed, 1594 insertions(+), 1507 deletions(-) create mode 100644 gtk/gtkarg.c create mode 100644 gtk/gtkarg.h create mode 100644 gtk/gtkargcollector.c (limited to 'gtk') diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 55a4083d9e..ce64ef32c0 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -8,9 +8,10 @@ libgtk_1_1_la_SOURCES = \ gtkaccelgroup.c \ gtkaccellabel.c \ gtkadjustment.c \ - gtkaspectframe.c \ gtkalignment.c \ + gtkarg.c \ gtkarrow.c \ + gtkaspectframe.c \ gtkbin.c \ gtkbindings.c \ gtkbbox.c \ @@ -108,9 +109,10 @@ gtkinclude_HEADERS = \ gtkaccelgroup.h \ gtkaccellabel.h \ gtkadjustment.h \ - gtkaspectframe.h \ gtkalignment.h \ + gtkarg.h \ gtkarrow.h \ + gtkaspectframe.h \ gtkbin.h \ gtkbindings.h \ gtkbbox.h \ @@ -268,6 +270,7 @@ EXTRA_DIST = \ makeenums.awk \ maketypes.awk \ makeenums.h \ + gtkargcollector.c \ gtktypebuiltins_vars.c \ gtktypebuiltins_ids.c \ gtktypebuiltins_evals.c \ diff --git a/gtk/gtk.h b/gtk/gtk.h index 2ff652d6d8..9720591457 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkarg.c b/gtk/gtkarg.c new file mode 100644 index 0000000000..47599109ee --- /dev/null +++ b/gtk/gtkarg.c @@ -0,0 +1,458 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include +#include +#include "gtkobject.h" +#include "gtkargcollector.c" + + +#define MAX_ARG_LENGTH (256) + + +/* --- typedefs --- */ +typedef struct _GtkArgQueryData GtkArgQueryData; + + +/* --- structures --- */ +struct _GtkArgQueryData +{ + GList *arg_list; + GtkType class_type; +}; + + + +/* --- functions --- */ +void +gtk_arg_type_new_static (GtkType base_class_type, + const gchar *arg_name, + guint class_n_args_offset, + GHashTable *arg_info_hash_table, + GtkType arg_type, + guint arg_flags, + guint arg_id) +{ + GtkArgInfo *info; + gchar class_part[MAX_ARG_LENGTH]; + gchar *arg_part; + GtkType class_type; + guint class_offset; + guint *n_args_p; + gchar *p; + + g_return_if_fail (arg_name != NULL); + g_return_if_fail (GTK_FUNDAMENTAL_TYPE (base_class_type) == GTK_TYPE_OBJECT); + g_return_if_fail (class_n_args_offset != 0); + g_return_if_fail (arg_info_hash_table != 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); + /* g_return_if_fail ((arg_flags & GTK_ARG_CHILD_ARG) == 0); */ + + arg_flags &= GTK_ARG_MASK; + + arg_part = strchr (arg_name, ':'); + if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':')) + { + g_warning ("gtk_arg_type_new(): invalid arg name: \"%s\"\n", arg_name); + return; + } + + class_offset = (guint) (arg_part - arg_name); + strncpy (class_part, arg_name, class_offset); + class_part[class_offset] = 0; + + class_type = gtk_type_from_name (class_part); + if (!gtk_type_is_a (class_type, base_class_type)) + { + g_warning ("gtk_arg_type_new(): argument class in \"%s\" is not in the `%s' ancestry", + arg_name, + gtk_type_name (base_class_type)); + return; + } + + p = gtk_type_class (class_type); + p += class_n_args_offset; + n_args_p = (guint*) p; + *n_args_p += 1; + + info = g_new (GtkArgInfo, 1); + info->class_type = class_type; + info->full_name = (gchar*) arg_name; /* _static */ + info->name = info->full_name + class_offset + 2; + info->type = arg_type; + info->arg_flags = arg_flags; + info->arg_id = arg_id; + info->seq_id = *n_args_p; + + g_hash_table_insert (arg_info_hash_table, info, info); +} + +gchar* +gtk_arg_name_strip_type (const gchar *arg_name) +{ + gchar buffer[MAX_ARG_LENGTH]; + gchar *p; + + /* security audit + */ + if (!arg_name || strlen (arg_name) > MAX_ARG_LENGTH - 8) + return NULL; + + p = strchr (arg_name, ':'); + if (p) + { + guint len; + + if ((p[0] != ':') || (p[1] != ':') || (p[2] == 0)) + return NULL; + len = (guint) (p - arg_name); + strncpy (buffer, arg_name, len); + buffer[len] = 0; + + if (gtk_type_from_name (buffer) != GTK_TYPE_INVALID) + return p + 2; + } + + return (gchar*) arg_name; +} + +gchar* +gtk_arg_get_info (GtkType object_type, + GHashTable *arg_info_hash_table, + const gchar *arg_name, + GtkArgInfo **info_p) +{ + GtkType otype; + gchar buffer[MAX_ARG_LENGTH]; + guint len; + gchar *p; + + *info_p = NULL; + + /* security audit + */ + if (!arg_name || strlen (arg_name) > MAX_ARG_LENGTH - 8) + return g_strdup ("argument name exceeds maximum size."); + + /* split off the object-type part + */ + p = strchr (arg_name, ':'); + if (p) + { + if ((p[0] != ':') || (p[1] != ':')) + return g_strconcat ("invalid argument syntax: \"", + arg_name, + "\"", + NULL); + len = (guint) (p - arg_name); + strncpy (buffer, arg_name, len); + buffer[len] = 0; + + otype = gtk_type_from_name (buffer); + if (otype != GTK_TYPE_INVALID) + arg_name = p + 2; + } + else + otype = GTK_TYPE_INVALID; + + /* split off the argument name + */ + p = strchr (arg_name, ':'); + if (p) + { + if ((p[0] != ':') || (p[1] != ':')) + return g_strconcat ("invalid argument syntax: \"", + arg_name, + "\"", + NULL); + len = (guint) (p - arg_name); + strncpy (buffer, arg_name, len); + buffer[len] = 0; + arg_name = buffer; + } + + /* lookup the argument + */ + if (otype != GTK_TYPE_INVALID) + { + GtkArgInfo info; + + info.class_type = otype; + info.name = (gchar*) arg_name; + + *info_p = g_hash_table_lookup (arg_info_hash_table, &info); + if (*info_p && !gtk_type_is_a (object_type, (*info_p)->class_type)) + *info_p = NULL; + } + else + { + otype = object_type; + while (!*info_p && GTK_FUNDAMENTAL_TYPE (otype) == GTK_TYPE_OBJECT) + { + GtkArgInfo info; + + info.class_type = otype; + info.name = (gchar*) arg_name; + + *info_p = g_hash_table_lookup (arg_info_hash_table, &info); + + otype = gtk_type_parent (otype); + } + } + + if (!*info_p) + return g_strconcat ("could not find argument \"", + arg_name, + "\" in the `", + gtk_type_name (object_type), + "' class ancestry", + NULL); + + return NULL; +} + +gchar* +gtk_args_collect (GtkType object_type, + GHashTable *arg_info_hash_table, + GSList **arg_list_p, + GSList **info_list_p, + gpointer var_args_p) +{ + GSList *arg_list; + GSList *info_list; + gchar *arg_name; + va_list *var_args = var_args_p; + + g_return_val_if_fail (arg_list_p != NULL, NULL); + *arg_list_p = NULL; + g_return_val_if_fail (info_list_p != NULL, NULL); + *info_list_p = 0; + g_return_val_if_fail (arg_info_hash_table != NULL, NULL); + + arg_list = NULL; + info_list = NULL; + arg_name = va_arg (*var_args, gchar*); + while (arg_name) + { + GtkArgInfo *info = NULL; + gchar *error; + + error = gtk_arg_get_info (object_type, arg_info_hash_table, arg_name, &info); + if (!error) + { + GtkArg *arg; + + info_list = g_slist_prepend (info_list, info); + + arg = gtk_arg_new (info->type); + arg->name = arg_name; + error = gtk_arg_collect_value (GTK_FUNDAMENTAL_TYPE (arg->type), arg, var_args); + arg_list = g_slist_prepend (arg_list, arg); + } + if (error) + { + gtk_args_collect_cleanup (arg_list, info_list); + + return error; + } + + arg_name = va_arg (*var_args, gchar*); + } + + *arg_list_p = g_slist_reverse (arg_list); + *info_list_p = g_slist_reverse (info_list); + + return NULL; +} + +void +gtk_args_collect_cleanup (GSList *arg_list, + GSList *info_list) +{ + GSList *slist; + + g_slist_free (info_list); + + for (slist = arg_list; slist; slist = slist->next) + gtk_arg_free (slist->data, FALSE); + g_slist_free (arg_list); +} + +static void +gtk_args_query_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + register GtkArgInfo *info; + register GtkArgQueryData *data; + + g_assert (key == value); /* paranoid */ + + info = value; + data = user_data; + + if (info->class_type == data->class_type) + data->arg_list = g_list_prepend (data->arg_list, info); +} + +GtkArg* +gtk_args_query (GtkType class_type, + GHashTable *arg_info_hash_table, + guint32 **arg_flags, + guint *n_args_p) +{ + GtkArg *args; + GtkArgQueryData query_data; + + if (arg_flags) + *arg_flags = NULL; + g_return_val_if_fail (n_args_p != NULL, NULL); + *n_args_p = 0; + g_return_val_if_fail (arg_info_hash_table != NULL, 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_hash_table, gtk_args_query_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; + } + + args = g_new0 (GtkArg, len); + *n_args_p = 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->full_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; +} + +GtkArg* +gtk_arg_new (GtkType arg_type) +{ + GtkArg *arg; + + arg = g_new0 (GtkArg, 1); + arg->type = arg_type; + arg->name = NULL; + + return arg; +} + +GtkArg* +gtk_arg_copy (GtkArg *src_arg, + GtkArg *dest_arg) +{ + g_return_val_if_fail (src_arg != NULL, NULL); + + if (!dest_arg) + { + dest_arg = g_new0 (GtkArg, 1); + dest_arg->name = src_arg->name; + } + + dest_arg->type = src_arg->type; + dest_arg->d = src_arg->d; + + if (src_arg->type == GTK_TYPE_STRING) + dest_arg->d.string_data = g_strdup (src_arg->d.string_data); + + return dest_arg; +} + +void +gtk_arg_free (GtkArg *arg, + gboolean free_contents) +{ + g_return_if_fail (arg != NULL); + + if (free_contents && + GTK_FUNDAMENTAL_TYPE (arg->type) == GTK_TYPE_STRING) + g_free (GTK_VALUE_STRING (*arg)); + g_free (arg); +} + +gint +gtk_arg_info_equal (gconstpointer arg_info_1, + gconstpointer arg_info_2) +{ + register const GtkArgInfo *info1 = arg_info_1; + register const GtkArgInfo *info2 = arg_info_2; + + return ((info1->class_type == info2->class_type) && + strcmp (info1->name, info2->name) == 0); +} + +guint +gtk_arg_info_hash (gconstpointer arg_info) +{ + register const GtkArgInfo *info = arg_info; + register const gchar *p; + register guint h = info->class_type >> 8; + + for (p = info->name; *p; p++) + { + register guint g; + + h = (h << 4) + *p; + g = h & 0xf0000000; + if (g) + { + h = h ^ (g >> 24); + h = h ^ g; + } + } + + return h; +} diff --git a/gtk/gtkarg.h b/gtk/gtkarg.h new file mode 100644 index 0000000000..7d4e6f777a --- /dev/null +++ b/gtk/gtkarg.h @@ -0,0 +1,94 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __GTK_ARG_H__ +#define __GTK_ARG_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + + + + +typedef struct _GtkArgInfo GtkArgInfo; + +struct _GtkArgInfo +{ + /* hash key portion */ + GtkType class_type; + gchar *name; + + GtkType type; + guint arg_flags; + gchar *full_name; + + /* private fields */ + guint arg_id; + guint seq_id; +}; + + +/* Non-public methods */ + +GtkArg* gtk_arg_new (GtkType arg_type); +GtkArg* gtk_arg_copy (GtkArg *src_arg, + GtkArg *dest_arg); +void gtk_arg_free (GtkArg *arg, + gboolean free_contents); +gchar* gtk_args_collect (GtkType object_type, + GHashTable *arg_info_hash_table, + GSList **arg_list_p, + GSList **info_list_p, + gpointer var_args_p); +void gtk_args_collect_cleanup (GSList *arg_list, + GSList *info_list); +gchar* gtk_arg_get_info (GtkType object_type, + GHashTable *arg_info_hash_table, + const gchar *arg_name, + GtkArgInfo **info_p); +void gtk_arg_type_new_static (GtkType base_class_type, + const gchar *arg_name, + guint class_n_args_offset, + GHashTable *arg_info_hash_table, + GtkType arg_type, + guint arg_flags, + guint arg_id); +GtkArg* gtk_args_query (GtkType class_type, + GHashTable *arg_info_hash_table, + guint32 **arg_flags, + guint *n_args_p); +gchar* gtk_arg_name_strip_type (const gchar *arg_name); +gint gtk_arg_info_equal (gconstpointer arg_info_1, + gconstpointer arg_info_2); +guint gtk_arg_info_hash (gconstpointer arg_info); + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_ARG_H__ */ diff --git a/gtk/gtkargcollector.c b/gtk/gtkargcollector.c new file mode 100644 index 0000000000..30b657d9c1 --- /dev/null +++ b/gtk/gtkargcollector.c @@ -0,0 +1,123 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* collect a single argument value from a va_list + */ +static inline gchar* +gtk_arg_collect_value (GtkType fundamental_type, + GtkArg *arg, + va_list *var_args) +{ + gchar *error_msg; + + error_msg = NULL; + switch (fundamental_type) + { + case GTK_TYPE_INVALID: + error_msg = g_strdup ("invalid untyped argument"); + break; + case GTK_TYPE_NONE: + error_msg = g_strdup ("invalid argument type `void'"); + break; + case GTK_TYPE_CHAR: + GTK_VALUE_CHAR (*arg) = va_arg (*var_args, gchar); + break; + case GTK_TYPE_BOOL: + GTK_VALUE_BOOL (*arg) = va_arg (*var_args, gboolean); + break; + case GTK_TYPE_INT: + GTK_VALUE_INT (*arg) = va_arg (*var_args, gint); + break; + case GTK_TYPE_UINT: + GTK_VALUE_UINT (*arg) = va_arg (*var_args, guint); + break; + case GTK_TYPE_ENUM: + GTK_VALUE_ENUM (*arg) = va_arg (*var_args, gint); + break; + case GTK_TYPE_FLAGS: + GTK_VALUE_FLAGS (*arg) = va_arg (*var_args, gint); + break; + case GTK_TYPE_LONG: + GTK_VALUE_LONG (*arg) = va_arg (*var_args, glong); + break; + case GTK_TYPE_ULONG: + GTK_VALUE_ULONG (*arg) = va_arg (*var_args, gulong); + break; + case GTK_TYPE_FLOAT: + GTK_VALUE_FLOAT (*arg) = va_arg (*var_args, gfloat); + break; + case GTK_TYPE_DOUBLE: + GTK_VALUE_DOUBLE (*arg) = va_arg (*var_args, gdouble); + break; + case GTK_TYPE_STRING: + GTK_VALUE_STRING (*arg) = va_arg (*var_args, gchar*); + break; + case GTK_TYPE_POINTER: + GTK_VALUE_POINTER (*arg) = va_arg (*var_args, gpointer); + break; + case GTK_TYPE_BOXED: + GTK_VALUE_BOXED (*arg) = va_arg (*var_args, gpointer); + break; + case GTK_TYPE_SIGNAL: + GTK_VALUE_SIGNAL (*arg).f = va_arg (*var_args, GtkFunction); + GTK_VALUE_SIGNAL (*arg).d = va_arg (*var_args, gpointer); + break; + case GTK_TYPE_FOREIGN: + GTK_VALUE_FOREIGN (*arg).data = va_arg (*var_args, gpointer); + GTK_VALUE_FOREIGN (*arg).notify = va_arg (*var_args, GtkDestroyNotify); + break; + case GTK_TYPE_CALLBACK: + GTK_VALUE_CALLBACK (*arg).marshal = va_arg (*var_args, GtkCallbackMarshal); + GTK_VALUE_CALLBACK (*arg).data = va_arg (*var_args, gpointer); + GTK_VALUE_CALLBACK (*arg).notify = va_arg (*var_args, GtkDestroyNotify); + break; + case GTK_TYPE_C_CALLBACK: + GTK_VALUE_C_CALLBACK (*arg).func = va_arg (*var_args, GtkFunction); + GTK_VALUE_C_CALLBACK (*arg).func_data = va_arg (*var_args, gpointer); + break; + case GTK_TYPE_ARGS: + GTK_VALUE_ARGS (*arg).n_args = va_arg (*var_args, gint); + GTK_VALUE_ARGS (*arg).args = va_arg (*var_args, GtkArg*); + break; + case GTK_TYPE_OBJECT: + GTK_VALUE_OBJECT (*arg) = va_arg (*var_args, GtkObject*); + if (GTK_VALUE_OBJECT (*arg) != NULL) + { + register GtkObject *object = GTK_VALUE_OBJECT (*arg); + + if (object->klass == NULL || + !gtk_type_is_a (GTK_OBJECT_TYPE (object), arg->type)) + error_msg = g_strconcat ("invalid object `", + gtk_type_name (GTK_OBJECT_TYPE (object)), + "' for argument type `", + gtk_type_name (arg->type), + "'", + NULL); + } + break; + default: + error_msg = g_strconcat ("unsupported argument type `", + gtk_type_name (arg->type), + "'", + NULL); + break; + } + + return error_msg; +} diff --git a/gtk/gtkbindings.c b/gtk/gtkbindings.c index 49a0dbacb7..50222147d3 100644 --- a/gtk/gtkbindings.c +++ b/gtk/gtkbindings.c @@ -30,6 +30,13 @@ /* --- defines --- */ #define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK) +#define BINDING_TYPE_INT (GTK_TYPE_INT) +#define BINDING_TYPE_LONG (GTK_TYPE_LONG) +#define BINDING_TYPE_FLOAT (GTK_TYPE_FLOAT) +#define BINDING_TYPE_DOUBLE (GTK_TYPE_DOUBLE) +#define BINDING_TYPE_STRING (GTK_TYPE_STRING) +#define BINDING_TYPE_IDENTIFIER (42) + /* --- variables --- */ static GHashTable *binding_entry_hash_table = NULL; @@ -61,7 +68,8 @@ binding_signal_free (GtkBindingSignal *sig) for (i = 0; i < sig->n_args; i++) { - if (sig->args[i].arg_type == GTK_BINDING_ARG_STRING) + if (sig->args[i].arg_type == BINDING_TYPE_STRING || + sig->args[i].arg_type == BINDING_TYPE_IDENTIFIER) g_free (sig->args[i].d.string_data); } g_free (sig->args); @@ -266,13 +274,7 @@ binding_compose_params (GtkBindingArg *args, params->name = NULL; switch (args->arg_type) { - case GTK_BINDING_ARG_STRING: - if (params->type == GTK_TYPE_STRING) - GTK_VALUE_STRING (*params) = args->d.string_data; - else - valid = FALSE; - break; - case GTK_BINDING_ARG_DOUBLE: + case BINDING_TYPE_DOUBLE: if (params->type == GTK_TYPE_FLOAT) GTK_VALUE_FLOAT (*params) = args->d.double_data; else if (params->type == GTK_TYPE_DOUBLE) @@ -280,7 +282,7 @@ binding_compose_params (GtkBindingArg *args, else valid = FALSE; break; - case GTK_BINDING_ARG_LONG: + case BINDING_TYPE_LONG: if (params->type == GTK_TYPE_BOOL && (args->d.long_data == 0 || args->d.long_data == 1)) @@ -302,6 +304,13 @@ binding_compose_params (GtkBindingArg *args, else valid = FALSE; break; + case BINDING_TYPE_STRING: + if (params->type == GTK_TYPE_STRING) + GTK_VALUE_STRING (*params) = args->d.string_data; + else + valid = FALSE; + break; + case BINDING_TYPE_IDENTIFIER: default: valid = FALSE; break; @@ -560,15 +569,15 @@ gtk_binding_entry_add_signall (GtkBindingSet *binding_set, arg->arg_type = tmp_arg->arg_type; switch (tmp_arg->arg_type) { - case GTK_BINDING_ARG_INT: - case GTK_BINDING_ARG_LONG: + case BINDING_TYPE_INT: + case BINDING_TYPE_LONG: arg->d.long_data = tmp_arg->d.long_data; break; - case GTK_BINDING_ARG_FLOAT: - case GTK_BINDING_ARG_DOUBLE: + case BINDING_TYPE_FLOAT: + case BINDING_TYPE_DOUBLE: arg->d.double_data = tmp_arg->d.double_data; break; - case GTK_BINDING_ARG_STRING: + case BINDING_TYPE_STRING: if (!tmp_arg->d.string_data) { g_warning ("gtk_binding_entry_add_signall(): value of `string' arg[%u] is `NULL'", n); @@ -630,19 +639,19 @@ gtk_binding_entry_add_signal (GtkBindingSet *binding_set, arg->arg_type = va_arg (args, GtkType); switch (arg->arg_type) { - case GTK_BINDING_ARG_INT: + case BINDING_TYPE_INT: arg->d.long_data = va_arg (args, gint); break; - case GTK_BINDING_ARG_LONG: + case BINDING_TYPE_LONG: arg->d.long_data = va_arg (args, glong); break; - case GTK_BINDING_ARG_FLOAT: + case BINDING_TYPE_FLOAT: arg->d.double_data = va_arg (args, gfloat); break; - case GTK_BINDING_ARG_DOUBLE: + case BINDING_TYPE_DOUBLE: arg->d.double_data = va_arg (args, gdouble); break; - case GTK_BINDING_ARG_STRING: + case BINDING_TYPE_STRING: arg->d.string_data = va_arg (args, gchar*); if (!arg->d.string_data) { diff --git a/gtk/gtkbindings.h b/gtk/gtkbindings.h index 5252299a85..15df76b3cb 100644 --- a/gtk/gtkbindings.h +++ b/gtk/gtkbindings.h @@ -61,14 +61,6 @@ gboolean gtk_pattern_match_simple (const gchar *pattern, const gchar *string); -/* type arguments for internal use only - */ -#define GTK_BINDING_ARG_INT (GTK_TYPE_INT) -#define GTK_BINDING_ARG_LONG (GTK_TYPE_LONG) -#define GTK_BINDING_ARG_FLOAT (GTK_TYPE_FLOAT) -#define GTK_BINDING_ARG_DOUBLE (GTK_TYPE_DOUBLE) -#define GTK_BINDING_ARG_STRING (GTK_TYPE_STRING) - /* Binding sets */ diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index eca39a568b..240d1b743b 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -116,15 +116,10 @@ static void gtk_container_children_callback (GtkWidget *widget, static void gtk_container_show_all (GtkWidget *widget); static void gtk_container_hide_all (GtkWidget *widget); -GtkArg* gtk_object_collect_args (guint *n_args, - GtkType (*) (const gchar*), - va_list args1, - va_list args2); - static guint container_signals[LAST_SIGNAL] = { 0 }; -static GHashTable *child_arg_info_ht = NULL; +static GHashTable *container_child_arg_info_ht = NULL; static GtkWidgetClass *parent_class = NULL; @@ -179,6 +174,9 @@ gtk_container_class_init (GtkContainerClass *class) parent_class = gtk_type_class (gtk_widget_get_type ()); + container_child_arg_info_ht = g_hash_table_new (gtk_arg_info_hash, + gtk_arg_info_equal); + vadjustment_key_id = g_quark_from_static_string (vadjustment_key); hadjustment_key_id = g_quark_from_static_string (hadjustment_key); @@ -255,48 +253,6 @@ gtk_container_class_init (GtkContainerClass *class) class->child_type = NULL; } -static void -gtk_container_get_child_arg (GtkContainer *container, - GtkWidget *child, - GtkType type, - GtkArg *arg, - guint arg_id) -{ - GtkContainerClass *class; - - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (child != NULL); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (arg != NULL); - - class = gtk_type_class (type); - if (class && class->get_child_arg) - class->get_child_arg (container, child, arg, arg_id); - else - arg->type = GTK_TYPE_INVALID; -} - -static void -gtk_container_set_child_arg (GtkContainer *container, - GtkWidget *child, - GtkType type, - GtkArg *arg, - guint arg_id) -{ - GtkContainerClass *class; - - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (child != NULL); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (arg != NULL); - - class = gtk_type_class (type); - if (class && class->set_child_arg) - class->set_child_arg (container, child, arg, arg_id); -} - GtkType gtk_container_child_type (GtkContainer *container) { @@ -315,419 +271,329 @@ gtk_container_child_type (GtkContainer *container) return slot; } +/**************************************************** + * GtkContainer child argument mechanism + * + ****************************************************/ + void -gtk_container_add_child_arg_type (const gchar *arg_name, - GtkType arg_type, - guint arg_flags, - guint arg_id) +gtk_container_add_with_args (GtkContainer *container, + GtkWidget *widget, + ...) { - GtkChildArgInfo *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) == GTK_ARG_READWRITE); + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (widget->parent == NULL); - arg_flags |= GTK_ARG_CHILD_ARG; - arg_flags &= GTK_ARG_MASK; + gtk_widget_ref (GTK_WIDGET (container)); + gtk_widget_ref (widget); - arg_part = strchr (arg_name, ':'); - if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':')) + gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget); + + if (widget->parent) { - g_warning ("gtk_container_add_arg_type(): invalid arg name: \"%s\"\n", arg_name); - return; - } - - strncpy (class_part, arg_name, (glong) (arg_part - arg_name)); - class_part[(glong) (arg_part - arg_name)] = '\0'; + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; + + va_start (var_args, widget); + error = gtk_object_args_collect (GTK_OBJECT_TYPE (container), + &arg_list, + &info_list, + &var_args); + va_end (var_args); + + if (error) + { + g_warning ("gtk_container_add_with_args(): %s", error); + g_free (error); + } + else + { + GSList *slist_arg; + GSList *slist_info; - class_type = gtk_type_from_name (class_part); - if (!class_type && !gtk_type_is_a (class_type, GTK_TYPE_CONTAINER)) - { - g_warning ("gtk_container_add_arg_type(): invalid class name in arg: \"%s\"\n", arg_name); - return; + slist_arg = arg_list; + slist_info = info_list; + while (slist_arg) + { + gtk_container_arg_set (container, widget, slist_arg->data, slist_info->data); + slist_arg = slist_arg->next; + slist_info = slist_info->next; + } + gtk_args_collect_cleanup (arg_list, info_list); + } } - info = g_new (GtkChildArgInfo, 1); - info->name = g_strdup (arg_name); - info->type = arg_type; - info->class_type = class_type; - info->arg_flags = arg_flags; - info->arg_id = arg_id; - info->seq_id = ++((GtkContainerClass*) gtk_type_class (class_type))->n_child_args; - - if (!child_arg_info_ht) - child_arg_info_ht = g_hash_table_new (g_str_hash, g_str_equal); - - g_hash_table_insert (child_arg_info_ht, info->name, info); -} - -typedef struct -{ - GList *arg_list; - GtkType class_type; -} GtkQueryChildArgData; - -static void -gtk_query_child_arg_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - register GtkChildArgInfo *info; - register GtkQueryChildArgData *data; - - info = value; - data = user_data; - - if (info->class_type == data->class_type) - data->arg_list = g_list_prepend (data->arg_list, info); + gtk_widget_unref (widget); + gtk_widget_unref (GTK_WIDGET (container)); } -GtkType -gtk_container_get_child_arg_type (const gchar *arg_name) +void +gtk_container_addv (GtkContainer *container, + GtkWidget *widget, + guint n_args, + GtkArg *args) { - GtkChildArgInfo *info; - gchar buffer[128]; - gchar *t; - - g_return_val_if_fail (arg_name != NULL, 0); - - if (!child_arg_info_ht) - return GTK_TYPE_INVALID; + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (widget->parent == NULL); - if (!arg_name || strlen (arg_name) > 120) - { - /* security audit - */ - g_warning ("gtk_container_get_child_arg_type(): argument `arg_name' exceeds maximum size."); - return GTK_TYPE_INVALID; - } + gtk_widget_ref (GTK_WIDGET (container)); + gtk_widget_ref (widget); - t = strchr (arg_name, ':'); - if (!t || (t[0] != ':') || (t[1] != ':')) + gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget); + + if (widget->parent) { - g_warning ("gtk_container_get_child_arg_type(): invalid arg name: \"%s\"\n", arg_name); - return GTK_TYPE_INVALID; - } + GtkArg *max_args; - t = strchr (t + 2, ':'); - if (t) - { - strncpy (buffer, arg_name, (long) (t - arg_name)); - buffer[(long) (t - arg_name)] = '\0'; - arg_name = buffer; + for (max_args = args + n_args; args < max_args; args++) + gtk_container_arg_set (container, widget, args, NULL); } - info = g_hash_table_lookup (child_arg_info_ht, arg_name); - if (info) - return info->type; - - return GTK_TYPE_INVALID; + gtk_widget_unref (widget); + gtk_widget_unref (GTK_WIDGET (container)); } -GtkArg* -gtk_container_query_child_args (GtkType class_type, - guint32 **arg_flags, - guint *n_args) +void +gtk_container_child_setv (GtkContainer *container, + GtkWidget *child, + guint n_args, + GtkArg *args) { - GtkArg *args; - GtkQueryChildArgData query_data; + GtkArg *max_args; - if (arg_flags) - *arg_flags = NULL; - g_return_val_if_fail (n_args != NULL, NULL); - *n_args = 0; - g_return_val_if_fail (gtk_type_is_a (class_type, GTK_TYPE_CONTAINER), NULL); - - if (!child_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 (child_arg_info_ht, gtk_query_child_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 == ((GtkContainerClass*) gtk_type_class (class_type))->n_child_args); /* paranoid */ - - args = g_new0 (GtkArg, len); - *n_args = len; - if (arg_flags) - *arg_flags = g_new (guint32, len); - - do - { - GtkChildArgInfo *info; - - info = list->data; - list = list->prev; + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); + g_return_if_fail (child != NULL); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent != NULL); + if (n_args) + g_return_if_fail (args != NULL); - g_assert (info->seq_id > 0 && info->seq_id <= len); /* paranoid */ + for (max_args = args + n_args; args < max_args; args++) + gtk_container_arg_set (container, child, args, NULL); +} - 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); +void +gtk_container_child_getv (GtkContainer *container, + GtkWidget *child, + guint n_args, + GtkArg *args) +{ + GtkArg *max_args; - g_list_free (query_data.arg_list); - } - else - args = NULL; + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_CONTAINER (container)); + g_return_if_fail (child != NULL); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent != NULL); + if (n_args) + g_return_if_fail (args != NULL); - return args; + for (max_args = args + n_args; args < max_args; args++) + gtk_container_arg_get (container, child, args, NULL); } void -gtk_container_child_arg_getv (GtkContainer *container, - GtkWidget *child, - guint n_args, - GtkArg *args) +gtk_container_child_set (GtkContainer *container, + GtkWidget *child, + ...) { - guint i; - + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; + g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (child != NULL); g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent != NULL); - if (!child_arg_info_ht) - return; + va_start (var_args, child); + error = gtk_object_args_collect (GTK_OBJECT_TYPE (container), + &arg_list, + &info_list, + &var_args); + va_end (var_args); - for (i = 0; i < n_args; i++) + if (error) { - GtkChildArgInfo *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 (child_arg_info_ht, lookup_name); - } - else - info = NULL; + g_warning ("gtk_container_child_set(): %s", error); + g_free (error); + } + else + { + GSList *slist_arg; + GSList *slist_info; - if (!info) + slist_arg = arg_list; + slist_info = info_list; + while (slist_arg) { - g_warning ("gtk_container_child_arg_getv(): invalid arg name: \"%s\"\n", - lookup_name); - args[i].type = GTK_TYPE_INVALID; - g_free (lookup_name); - continue; + gtk_container_arg_set (container, child, slist_arg->data, slist_info->data); + slist_arg = slist_arg->next; + slist_info = slist_info->next; } - else if (!gtk_type_is_a (GTK_OBJECT_TYPE (container), info->class_type)) - { - g_warning ("gtk_container_child_arg_getv(): invalid arg for %s: \"%s\"\n", - gtk_type_name (GTK_OBJECT_TYPE (container)), lookup_name); - args[i].type = GTK_TYPE_INVALID; - g_free (lookup_name); - continue; - } - else if (! (info->arg_flags & GTK_ARG_READABLE)) - { - g_warning ("gtk_container_child_arg_getv(): 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_container_get_child_arg (container, child, info->class_type, &args[i], info->arg_id); + gtk_args_collect_cleanup (arg_list, info_list); } } void -gtk_container_child_arg_set (GtkContainer *container, - GtkWidget *child, - ...) +gtk_container_arg_set (GtkContainer *container, + GtkWidget *child, + GtkArg *arg, + GtkArgInfo *info) { - GtkArg *args; - guint n_args; - va_list args1; - va_list args2; + GtkContainerClass *class; g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (child != NULL); g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (child->parent != NULL); - - va_start (args1, child); - va_start (args2, child); + g_return_if_fail (arg != NULL); + + if (!info) + { + gchar *error; + + error = gtk_arg_get_info (GTK_OBJECT_TYPE (container), + container_child_arg_info_ht, + arg->name, + &info); + if (error) + { + g_warning ("gtk_container_arg_set(): %s", error); + g_free (error); + return; + } + } - args = gtk_object_collect_args (&n_args, gtk_container_get_child_arg_type, args1, args2); - gtk_container_child_arg_setv (container, child, n_args, args); - g_free (args); + if (! (info->arg_flags & GTK_ARG_WRITABLE)) + { + g_warning ("gtk_container_arg_set(): argument \"%s\" is not writable", + info->full_name); + return; + } + if (info->type != arg->type) + { + g_warning ("gtk_container_arg_set(): argument \"%s\" has invalid type `%s'", + info->full_name, + gtk_type_name (arg->type)); + return; + } - va_end (args1); - va_end (args2); + class = gtk_type_class (info->class_type); + if (class->set_child_arg) + class->set_child_arg (container, child, arg, info->arg_id); } void -gtk_container_child_arg_setv (GtkContainer *container, - GtkWidget *child, - guint n_args, - GtkArg *args) +gtk_container_arg_get (GtkContainer *container, + GtkWidget *child, + GtkArg *arg, + GtkArgInfo *info) { - guint i; - + GtkContainerClass *class; + g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_CONTAINER (container)); g_return_if_fail (child != NULL); g_return_if_fail (GTK_IS_WIDGET (child)); - - if (!child_arg_info_ht) - return; - - for (i = 0; i < n_args; i++) + g_return_if_fail (arg != NULL); + + if (!info) { - GtkChildArgInfo *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; - - info = g_hash_table_lookup (child_arg_info_ht, lookup_name); - } - else - info = NULL; - - arg_ok = TRUE; - - if (!info) - { - g_warning ("gtk_container_child_arg_setv(): invalid arg name: \"%s\"\n", - lookup_name); - arg_ok = FALSE; - } - else if (info->type != args[i].type) - { - g_warning ("gtk_container_child_arg_setv(): invalid arg type for: \"%s\"\n", - lookup_name); - arg_ok = FALSE; - } - else if (!gtk_type_is_a (GTK_OBJECT_TYPE (container), info->class_type)) - { - g_warning ("gtk_container_child_arg_setv(): invalid arg for %s: \"%s\"\n", - gtk_type_name (GTK_OBJECT_TYPE (container)), lookup_name); - arg_ok = FALSE; - } - else if (! (info->arg_flags & GTK_ARG_WRITABLE)) + gchar *error; + + error = gtk_arg_get_info (GTK_OBJECT_TYPE (container), + container_child_arg_info_ht, + arg->name, + &info); + if (error) { - g_warning ("gtk_container_child_arg_setv(): arg is not supplied for write-access: \"%s\"\n", - lookup_name); - arg_ok = FALSE; + g_warning ("gtk_container_arg_get(): %s", error); + g_free (error); + arg->type = GTK_TYPE_INVALID; + return; } - - g_free (lookup_name); - - if (!arg_ok) - continue; - - gtk_container_set_child_arg (container, child, info->class_type, &args[i], info->arg_id); } -} - -void -gtk_container_add_with_args (GtkContainer *container, - GtkWidget *widget, - ...) -{ - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (widget->parent == NULL); - - gtk_widget_ref (GTK_WIDGET (container)); - gtk_widget_ref (widget); - - gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget); - if (widget->parent) + if (! (info->arg_flags & GTK_ARG_READABLE)) { - GtkArg *args; - guint n_args; - va_list args1; - va_list args2; - - va_start (args1, widget); - va_start (args2, widget); - - args = gtk_object_collect_args (&n_args, gtk_container_get_child_arg_type, args1, args2); - gtk_container_child_arg_setv (container, widget, n_args, args); - g_free (args); - - va_end (args1); - va_end (args2); + g_warning ("gtk_container_arg_get(): argument \"%s\" is not readable", + info->full_name); + arg->type = GTK_TYPE_INVALID; + return; } - - gtk_widget_unref (widget); - gtk_widget_unref (GTK_WIDGET (container)); + + class = gtk_type_class (info->class_type); + if (class->get_child_arg) + { + arg->type = info->type; + class->get_child_arg (container, child, arg, info->arg_id); + } + else + arg->type = GTK_TYPE_INVALID; } void -gtk_container_add_with_argv (GtkContainer *container, - GtkWidget *widget, - guint n_args, - GtkArg *args) +gtk_container_add_child_arg_type (const gchar *arg_name, + GtkType arg_type, + guint arg_flags, + guint arg_id) { - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_CONTAINER (container)); - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (widget->parent == 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_READWRITE) == GTK_ARG_READWRITE); + /* g_return_if_fail ((arg_flags & GTK_ARG_CHILD_ARG) != 0); */ - gtk_widget_ref (GTK_WIDGET (container)); - gtk_widget_ref (widget); + arg_flags |= GTK_ARG_CHILD_ARG; + arg_flags &= GTK_ARG_MASK; - gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget); + gtk_arg_type_new_static (GTK_TYPE_CONTAINER, + arg_name, + GTK_STRUCT_OFFSET (GtkContainerClass, n_child_args), + container_child_arg_info_ht, + arg_type, + arg_flags, + arg_id); +} - if (widget->parent) - gtk_container_child_arg_setv (container, widget, n_args, args); +gchar* +gtk_container_child_args_collect (GtkType object_type, + GSList **arg_list_p, + GSList **info_list_p, + gpointer var_args_p) +{ + return gtk_args_collect (object_type, + container_child_arg_info_ht, + arg_list_p, + info_list_p, + var_args_p); +} - gtk_widget_unref (widget); - gtk_widget_unref (GTK_WIDGET (container)); +GtkArg* +gtk_container_query_child_args (GtkType class_type, + guint32 **arg_flags, + guint *n_args) +{ + g_return_val_if_fail (n_args != NULL, NULL); + *n_args = 0; + g_return_val_if_fail (gtk_type_is_a (class_type, GTK_TYPE_CONTAINER), NULL); + + return gtk_args_query (class_type, container_child_arg_info_ht, arg_flags, n_args); } + static void gtk_container_add_unimplemented (GtkContainer *container, GtkWidget *widget) diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h index f314884655..dce36262bd 100644 --- a/gtk/gtkcontainer.h +++ b/gtk/gtkcontainer.h @@ -134,15 +134,15 @@ void gtk_container_resize_children (GtkContainer *container); GtkType gtk_container_child_type (GtkContainer *container); +/* the `arg_name' argument needs to be a const static string */ void gtk_container_add_child_arg_type (const gchar *arg_name, GtkType arg_type, guint arg_flags, guint arg_id); -GtkType gtk_container_get_child_arg_type (const gchar *arg_name); /* Allocate a GtkArg array of size nargs that hold the * names and types of the args that can be used with - * gtk_container_child_arg_getv/gtk_container_child_arg_setv. + * gtk_container_child_getv/gtk_container_child_setv. * if (arg_flags!=NULL), * (*arg_flags) will be set to point to a newly allocated * guint array that holds the flags of the args. @@ -153,16 +153,16 @@ GtkArg* gtk_container_query_child_args (GtkType class_type, guint32 **arg_flags, guint *nargs); -/* gtk_container_child_arg_getv() sets an arguments type and value, or just +/* gtk_container_child_getv() sets an arguments type and value, or just * its type to GTK_TYPE_INVALID. - * if arg->type == GTK_TYPE_STRING, it's the callers response to - * do a g_free (GTK_VALUE_STRING (arg)); + * if GTK_FUNDAMENTAL_TYPE (arg->type) == GTK_TYPE_STRING, it's the callers + * response to do a g_free (GTK_VALUE_STRING (arg)); */ -void gtk_container_child_arg_getv (GtkContainer *container, +void gtk_container_child_getv (GtkContainer *container, GtkWidget *child, guint n_args, GtkArg *args); -void gtk_container_child_arg_setv (GtkContainer *container, +void gtk_container_child_setv (GtkContainer *container, GtkWidget *child, guint n_args, GtkArg *args); @@ -175,22 +175,36 @@ void gtk_container_child_arg_setv (GtkContainer *container, void gtk_container_add_with_args (GtkContainer *container, GtkWidget *widget, ...); -void gtk_container_add_with_argv (GtkContainer *container, +void gtk_container_addv (GtkContainer *container, GtkWidget *widget, guint n_args, GtkArg *args); -void gtk_container_child_arg_set (GtkContainer *container, +void gtk_container_child_set (GtkContainer *container, GtkWidget *child, ...); /* Non-public methods */ + void gtk_container_queue_resize (GtkContainer *container); void gtk_container_clear_resize_widgets (GtkContainer *container); - +void gtk_container_arg_set (GtkContainer *container, + GtkWidget *child, + GtkArg *arg, + GtkArgInfo *info); +void gtk_container_arg_get (GtkContainer *container, + GtkWidget *child, + GtkArg *arg, + GtkArgInfo *info); +gchar* gtk_container_child_args_collect (GtkType object_type, + GSList **arg_list_p, + GSList **info_list_p, + gpointer var_args_p); + + /* Deprecated methods */ -/* completely non-functional */ +/* Completely non-functional */ void gtk_container_disable_resize (GtkContainer *container); void gtk_container_enable_resize (GtkContainer *container); diff --git a/gtk/gtkobject.c b/gtk/gtkobject.c index 01a704c2d6..78dd409713 100644 --- a/gtk/gtkobject.c +++ b/gtk/gtkobject.c @@ -35,12 +35,13 @@ enum { 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 { @@ -50,16 +51,6 @@ struct _GtkObjectData GtkObjectData *next; }; -struct _GtkArgInfo -{ - gchar *name; - GtkType type; - GtkType class_type; - guint arg_flags; - guint arg_id; - guint seq_id; -}; - void gtk_object_init_type (void); static void gtk_object_base_class_init (GtkObjectClass *klass); @@ -76,14 +67,9 @@ 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, - GtkType (*) (const gchar*), - va_list args1, - va_list args2); - static guint object_signals[LAST_SIGNAL] = { 0 }; -static GHashTable *arg_info_ht = NULL; +static GHashTable *object_arg_info_ht = NULL; static const gchar *user_data_key = "user_data"; static guint user_data_key_id = 0; @@ -185,10 +171,18 @@ gtk_object_class_init (GtkObjectClass *class) 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", @@ -291,30 +285,41 @@ gtk_object_set_arg (GtkObject *object, 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 ("gtk_object_set_arg(): invalid signal argument: \"%s\"\n", arg->name); - 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 ("gtk_object_set_arg(): invalid signal argument: \"%s\"\n", arg->name); - return; + gtk_signal_connect_full (object, + arg_name + n + 2, + (GtkSignalFunc) 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: break; @@ -610,464 +615,368 @@ gtk_object_notify_weaks (GtkObject *object) } } -/***************************************** - * gtk_object_new: - * - * arguments: +/**************************************************** + * GtkObject argument mechanism and object creation * - * results: - *****************************************/ + ****************************************************/ GtkObject* -gtk_object_new (GtkType type, +gtk_object_new (GtkType object_type, ...) { - GtkObject *obj; - GtkArg *args; - guint nargs; - va_list args1; - va_list args2; - - obj = gtk_type_new (type); + GtkObject *object; + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; - va_start (args1, type); - va_start (args2, type); + g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (object_type) == GTK_TYPE_OBJECT, NULL); - args = gtk_object_collect_args (&nargs, gtk_object_get_arg_type, args1, args2); - gtk_object_setv (obj, nargs, args); - g_free (args); + object = gtk_type_new (object_type); - va_end (args1); - va_end (args2); + 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 (GtkType 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) { - guint 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 (max_args = args + n_args; args < max_args; args++) + gtk_object_arg_get (object, args, NULL); +} + +void +gtk_object_set (GtkObject *object, + ...) +{ + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; - for (i = 0; i < nargs; i++) + g_return_if_fail (object != NULL); + 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) { - GtkArgInfo *info; - gchar *lookup_name; - gchar *d; - GtkObjectClass *oclass; - - - /* 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; + g_warning ("gtk_object_set(): %s", error); + g_free (error); + } + else + { + GSList *slist_arg; + GSList *slist_info; - if (!info) - { - g_warning ("gtk_object_getv(): 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)) + slist_arg = arg_list; + slist_info = info_list; + while (slist_arg) { - g_warning ("gtk_object_getv(): 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; + gtk_object_arg_set (object, slist_arg->data, slist_info->data); + slist_arg = slist_arg->next; + slist_info = slist_info->next; } - else if (! (info->arg_flags & GTK_ARG_READABLE)) - { - g_warning ("gtk_object_getv(): 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; - - oclass = gtk_type_class (info->class_type); - if (oclass && oclass->get_arg) - oclass->get_arg (object, &args[i], info->arg_id); - else - args[i].type = GTK_TYPE_INVALID; - -#if 0 - gtk_type_get_arg (object, info->class_type, &args[i], info->arg_id); -#endif + gtk_args_collect_cleanup (arg_list, info_list); } } -/***************************************** - * 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) +void +gtk_object_arg_set (GtkObject *object, + GtkArg *arg, + GtkArgInfo *info) { - 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_TYPE_OBJECT), NULL); - - if (!arg_info_ht) - return NULL; + GtkObjectClass *oclass; - /* 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); + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_OBJECT (object)); + g_return_if_fail (arg != NULL); - if (query_data.arg_list) + if (!info) { - register GList *list; - register guint len; + gchar *error; - list = query_data.arg_list; - len = 1; - while (list->next) + error = gtk_arg_get_info (GTK_OBJECT_TYPE (object), + object_arg_info_ht, + arg->name, + &info); + if (error) { - 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; + g_warning ("gtk_object_arg_set(): %s", error); + g_free (error); + return; } - while (list); - - g_list_free (query_data.arg_list); } - else - args = NULL; - - return args; -} - -/***************************************** - * gtk_object_set: - * - * arguments: - * - * results: - *****************************************/ - -void -gtk_object_set (GtkObject *object, - ...) -{ - GtkArg *args; - guint nargs; - va_list args1; - va_list args2; - - g_return_if_fail (object != NULL); - - va_start (args1, object); - va_start (args2, object); - - args = gtk_object_collect_args (&nargs, gtk_object_get_arg_type, args1, args2); - gtk_object_setv (object, nargs, args); - g_free (args); - - va_end (args1); - va_end (args2); + + if (! (info->arg_flags & GTK_ARG_WRITABLE)) + { + g_warning ("gtk_object_arg_set(): argument \"%s\" is not writable", + info->full_name); + return; + } + if (info->type != arg->type) + { + g_warning ("gtk_object_arg_set(): argument \"%s\" has invalid type `%s'", + info->full_name, + gtk_type_name (arg->type)); + return; + } + + oclass = gtk_type_class (info->class_type); + if (oclass->set_arg) + oclass->set_arg (object, arg, info->arg_id); } -/***************************************** - * gtk_object_setv: - * - * arguments: - * - * results: - *****************************************/ - void -gtk_object_setv (GtkObject *object, - guint nargs, - GtkArg *args) +gtk_object_arg_get (GtkObject *object, + GtkArg *arg, + GtkArgInfo *info) { - guint i; - + GtkObjectClass *oclass; + g_return_if_fail (object != NULL); - g_return_if_fail (GTK_OBJECT (object)); - - if (!arg_info_ht) - return; + g_return_if_fail (GTK_IS_OBJECT (object)); + g_return_if_fail (arg != NULL); - for (i = 0; i < nargs; i++) + if (!info) { - GtkArgInfo *info; - gchar *lookup_name; - gchar *d; - gboolean arg_ok; - GtkObjectClass *oclass; - - 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) + error = gtk_arg_get_info (GTK_OBJECT_TYPE (object), + object_arg_info_ht, + arg->name, + &info); + if (error) { - g_warning ("gtk_object_setv(): invalid arg name: \"%s\"\n", - lookup_name); - arg_ok = FALSE; - } - else if (info->type != args[i].type) - { - g_warning ("gtk_object_setv(): 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 ("gtk_object_setv(): 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)) - { - g_warning ("gtk_object_setv(): arg is not supplied for write-access: \"%s\"\n", - lookup_name); - arg_ok = FALSE; + g_warning ("gtk_object_arg_get(): %s", error); + g_free (error); + arg->type = GTK_TYPE_INVALID; + return; } - - g_free (lookup_name); - - if (!arg_ok) - continue; - - oclass = gtk_type_class (info->class_type); - if (oclass && oclass->set_arg) - oclass->set_arg (object, &args[i], info->arg_id); - -#if 0 - gtk_type_set_arg (object, info->class_type, &args[i], info->arg_id); -#endif } + + if (! (info->arg_flags & GTK_ARG_READABLE)) + { + g_warning ("gtk_object_arg_get(): argument \"%s\" is not readable", + info->full_name); + arg->type = GTK_TYPE_INVALID; + return; + } + + oclass = gtk_type_class (info->class_type); + if (oclass->get_arg) + { + arg->type = info->type; + oclass->get_arg (object, arg, info->arg_id); + } + else + arg->type = GTK_TYPE_INVALID; } -/***************************************** - * 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); g_return_if_fail ((arg_flags & GTK_ARG_CHILD_ARG) == 0); - - arg_flags &= GTK_ARG_MASK; - arg_part = strchr (arg_name, ':'); - if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':')) - { - g_warning ("invalid arg name: \"%s\"\n", arg_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) - { - g_warning ("gtk_object_add_arg_type(): invalid class name in arg: \"%s\"\n", arg_name); - return; - } + 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); +} - 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; - info->arg_id = arg_id; - info->seq_id = ++((GtkObjectClass*) gtk_type_class (class_type))->n_args; +gchar* +gtk_object_args_collect (GtkType object_type, + GSList **arg_list_p, + GSList **info_list_p, + gpointer var_args_p) +{ + return gtk_args_collect (object_type, + object_arg_info_ht, + arg_list_p, + info_list_p, + var_args_p); +} - if (!arg_info_ht) - arg_info_ht = g_hash_table_new (g_str_hash, g_str_equal); +GtkArg* +gtk_object_query_args (GtkType class_type, + guint32 **arg_flags, + guint *n_args) +{ + 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); - g_hash_table_insert (arg_info_ht, info->name, info); + return gtk_args_query (class_type, object_arg_info_ht, arg_flags, n_args); } -/***************************************** - * gtk_object_get_arg_type: - * - * arguments: +/******************************************************** + * GtkObject and GtkObjectClass cast checking functions * - * results: - *****************************************/ + ********************************************************/ -GtkType -gtk_object_get_arg_type (const gchar *arg_name) +static gchar* +gtk_object_descriptive_type_name (GtkType type) { - GtkArgInfo *info; - gchar buffer[128]; - gchar *t; + gchar *name; - g_return_val_if_fail (arg_name != NULL, 0); + name = gtk_type_name (type); + if (!name) + name = "(unknown)"; - if (!arg_info_ht) - return GTK_TYPE_INVALID; + return name; +} - if (!arg_name || strlen (arg_name) > 120) +GtkObject* +gtk_object_check_cast (GtkObject *obj, + GtkType cast_type) +{ + if (!obj) { - /* security audit - */ - g_warning ("gtk_object_get_arg_type(): argument `arg_name' exceeds maximum size."); - return GTK_TYPE_INVALID; + g_warning ("invalid cast from (NULL) pointer to `%s'", + gtk_object_descriptive_type_name (cast_type)); + return obj; } - - t = strchr (arg_name, ':'); - if (!t || (t[0] != ':') || (t[1] != ':')) + if (!obj->klass) { - g_warning ("gtk_object_get_arg_type(): invalid arg name: \"%s\"\n", arg_name); - return GTK_TYPE_INVALID; + g_warning ("invalid unclassed pointer in cast to `%s'", + gtk_object_descriptive_type_name (cast_type)); + return obj; } - - t = strchr (t + 2, ':'); - if (t) + if (obj->klass->type < GTK_TYPE_OBJECT) { - strncpy (buffer, arg_name, (long) (t - arg_name)); - buffer[(long) (t - arg_name)] = '\0'; - arg_name = buffer; + g_warning ("invalid class type `%s' in cast to `%s'", + gtk_object_descriptive_type_name (obj->klass->type), + gtk_object_descriptive_type_name (cast_type)); + return obj; } + if (!gtk_type_is_a (obj->klass->type, cast_type)) + { + g_warning ("invalid cast from `%s' to `%s'", + gtk_object_descriptive_type_name (obj->klass->type), + gtk_object_descriptive_type_name (cast_type)); + return obj; + } + + return obj; +} - info = g_hash_table_lookup (arg_info_ht, arg_name); - if (info) - return info->type; +GtkObjectClass* +gtk_object_check_class_cast (GtkObjectClass *klass, + GtkType cast_type) +{ + if (!klass) + { + g_warning ("invalid class cast from (NULL) pointer to `%s'", + gtk_object_descriptive_type_name (cast_type)); + return klass; + } + if (klass->type < GTK_TYPE_OBJECT) + { + g_warning ("invalid class type `%s' in class cast to `%s'", + gtk_object_descriptive_type_name (klass->type), + gtk_object_descriptive_type_name (cast_type)); + return klass; + } + if (!gtk_type_is_a (klass->type, cast_type)) + { + g_warning ("invalid class cast from `%s' to `%s'", + gtk_object_descriptive_type_name (klass->type), + gtk_object_descriptive_type_name (cast_type)); + return klass; + } - return GTK_TYPE_INVALID; + return klass; } /***************************************** @@ -1256,14 +1165,6 @@ gtk_object_remove_data (GtkObject *object, gtk_object_set_data_by_id_full (object, id, NULL, NULL); } -/***************************************** - * gtk_object_set_user_data: - * - * arguments: - * - * results: - *****************************************/ - void gtk_object_set_user_data (GtkObject *object, gpointer data) @@ -1274,14 +1175,6 @@ gtk_object_set_user_data (GtkObject *object, gtk_object_set_data_by_id_full (object, user_data_key_id, data, NULL); } -/***************************************** - * gtk_object_get_user_data: - * - * arguments: - * - * results: - *****************************************/ - gpointer gtk_object_get_user_data (GtkObject *object) { @@ -1291,297 +1184,10 @@ gtk_object_get_user_data (GtkObject *object) return NULL; } -/***************************************** - * gtk_object_check_cast: +/******************************************* + * GtkObject referencing and unreferencing * - * arguments: - * - * results: - *****************************************/ - -static gchar* -gtk_object_descriptive_type_name (GtkType type) -{ - gchar *name; - - name = gtk_type_name (type); - if (!name) - name = "(unknown)"; - - return name; -} - -GtkObject* -gtk_object_check_cast (GtkObject *obj, - GtkType cast_type) -{ - if (!obj) - { - g_warning ("invalid cast from (NULL) pointer to `%s'", - gtk_object_descriptive_type_name (cast_type)); - return obj; - } - if (!obj->klass) - { - g_warning ("invalid unclassed pointer in cast to `%s'", - gtk_object_descriptive_type_name (cast_type)); - return obj; - } - if (obj->klass->type < GTK_TYPE_OBJECT) - { - g_warning ("invalid class type `%s' in cast to `%s'", - gtk_object_descriptive_type_name (obj->klass->type), - gtk_object_descriptive_type_name (cast_type)); - return obj; - } - if (!gtk_type_is_a (obj->klass->type, cast_type)) - { - g_warning ("invalid cast from `%s' to `%s'", - gtk_object_descriptive_type_name (obj->klass->type), - gtk_object_descriptive_type_name (cast_type)); - return obj; - } - - return obj; -} - -/***************************************** - * gtk_object_check_class_cast: - * - * arguments: - * - * results: - *****************************************/ - -GtkObjectClass* -gtk_object_check_class_cast (GtkObjectClass *klass, - GtkType cast_type) -{ - if (!klass) - { - g_warning ("invalid class cast from (NULL) pointer to `%s'", - gtk_object_descriptive_type_name (cast_type)); - return klass; - } - if (klass->type < GTK_TYPE_OBJECT) - { - g_warning ("invalid class type `%s' in class cast to `%s'", - gtk_object_descriptive_type_name (klass->type), - gtk_object_descriptive_type_name (cast_type)); - return klass; - } - if (!gtk_type_is_a (klass->type, cast_type)) - { - g_warning ("invalid class cast from `%s' to `%s'", - gtk_object_descriptive_type_name (klass->type), - gtk_object_descriptive_type_name (cast_type)); - return klass; - } - - return klass; -} - -/***************************************** - * gtk_object_collect_args: - * - * arguments: - * - * results: - *****************************************/ - -GtkArg* -gtk_object_collect_args (guint *nargs, - GtkType (*get_arg_type) (const gchar*), - va_list args1, - va_list args2) -{ - GtkArg *args; - GtkType type; - gchar *name; - gint done; - gint i, n; - - n = 0; - done = FALSE; - - while (!done) - { - name = va_arg (args1, char *); - if (!name) - { - done = TRUE; - continue; - } - - type = get_arg_type (name); - - switch (GTK_FUNDAMENTAL_TYPE (type)) - { - case GTK_TYPE_INVALID: - g_warning ("GTK: 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; - } - - n += 1; - } - - *nargs = n; - args = NULL; - - if (n > 0) - { - args = g_new0 (GtkArg, n); - - for (i = 0; i < n; i++) - { - args[i].name = va_arg (args2, char *); - args[i].type = get_arg_type (args[i].name); - - 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; - } - } - } - - return args; -} - - + *******************************************/ #undef gtk_object_ref #undef gtk_object_unref diff --git a/gtk/gtkobject.h b/gtk/gtkobject.h index 945a1131c6..90382c42ad 100644 --- a/gtk/gtkobject.h +++ b/gtk/gtkobject.h @@ -20,6 +20,7 @@ #define __GTK_OBJECT_H__ +#include #include #include #include @@ -32,6 +33,13 @@ extern "C" { +#ifdef offsetof +#define GTK_STRUCT_OFFSET(struct, field) ((gint) offsetof (struct, field)) +#else /* !offsetof */ +#define GTK_STRUCT_OFFSET(struct, field) ((gint) ((gchar*) &((struct*) 0)->field)) +#endif /* !offsetof */ + + /* The debugging versions of the casting macros make sure the cast is "ok" * before proceeding, but they are definately slower than their less * careful counterparts as they involve no less than 3 function calls. @@ -127,8 +135,8 @@ typedef enum GTK_ARG_WRITABLE = 1 << 1, GTK_ARG_CONSTRUCT = 1 << 2, GTK_ARG_CHILD_ARG = 1 << 3, - GTK_ARG_MASK = 0x0f, - + GTK_ARG_MASK = 0x0f, + /* aliases */ GTK_ARG_READWRITE = GTK_ARG_READABLE | GTK_ARG_WRITABLE @@ -189,7 +197,7 @@ struct _GtkObjectClass /* The number of arguments per class. */ guint n_args; - + /* Non overridable class methods to set and get per class arguments */ void (*set_arg) (GtkObject *object, GtkArg *arg, @@ -225,18 +233,12 @@ typedef void (*GtkSignalMarshaller) (GtkObject *object, GtkArg *args); -/* Get the type identifier for GtkObject's. - */ -GtkType gtk_object_get_type (void); -/* Append "signals" to those already defined in "class". - */ -void gtk_object_class_add_signals (GtkObjectClass *klass, - guint *signals, - guint nsignals); +/* Application-level methods */ -/* Append a user defined signal without default handler to a class. - */ +GtkType gtk_object_get_type (void); + +/* Append a user defined signal without default handler to a class. */ guint gtk_object_class_user_signal_new (GtkObjectClass *klass, const gchar *name, GtkSignalRunType signal_flags, @@ -251,40 +253,29 @@ guint gtk_object_class_user_signal_newv (GtkObjectClass *klass, GtkType return_val, guint nparams, GtkType *params); -/* Outdated */ -guint gtk_object_class_add_user_signal (GtkObjectClass *klass, - const gchar *name, - GtkSignalMarshaller marshaller, - GtkType return_val, - guint nparams, - ...); - -GtkObject* gtk_object_new (GtkType type, - ...); - -GtkObject* gtk_object_newv (GtkType type, - guint nargs, - GtkArg *args); +GtkObject* gtk_object_new (GtkType type, + ...); +GtkObject* gtk_object_newv (GtkType object_type, + guint n_args, + GtkArg *args); void gtk_object_sink (GtkObject *object); void gtk_object_ref (GtkObject *object); void gtk_object_unref (GtkObject *object); - void gtk_object_weakref (GtkObject *object, GtkDestroyNotify notify, gpointer data); void gtk_object_weakunref (GtkObject *object, GtkDestroyNotify notify, gpointer data); - void gtk_object_destroy (GtkObject *object); /* gtk_object_getv() sets an arguments type and value, or just * its type to GTK_TYPE_INVALID. - * if arg->type == GTK_TYPE_STRING, it's the callers response to - * do a g_free (GTK_VALUE_STRING (arg)); + * if GTK_FUNDAMENTAL_TYPE (arg->type) == GTK_TYPE_STRING, it's + * the callers response to do a g_free (GTK_VALUE_STRING (arg)); */ void gtk_object_getv (GtkObject *object, - guint nargs, + guint n_args, GtkArg *args); /* gtk_object_set() takes a variable argument list of the form: @@ -294,9 +285,8 @@ void gtk_object_getv (GtkObject *object, */ void gtk_object_set (GtkObject *object, ...); - void gtk_object_setv (GtkObject *object, - guint nargs, + guint n_args, GtkArg *args); /* Allocate a GtkArg array of size nargs that hold the @@ -307,49 +297,67 @@ void gtk_object_setv (GtkObject *object, * It is the callers response to do a * g_free (returned_args); g_free (*arg_flags). */ -GtkArg* gtk_object_query_args (GtkType class_type, +GtkArg* gtk_object_query_args (GtkType class_type, guint32 **arg_flags, - guint *nargs); - -void gtk_object_add_arg_type (const gchar *arg_name, - GtkType arg_type, - guint arg_flags, - guint arg_id); - -GtkType gtk_object_get_arg_type (const gchar *arg_name); + guint *n_args); /* Set 'data' to the "object_data" field of the object. The * data is indexed by the "key". If there is already data * associated with "key" then the new data will replace it. * If 'data' is NULL then this call is equivalent to * 'gtk_object_remove_data'. + * The gtk_object_set_data_full variant acts just the same, + * but takes an additional argument which is a function to + * be called when the data is removed. + * `gtk_object_remove_data' is equivalent to the above, + * where 'data' is NULL + * `gtk_object_get_data' gets the data associated with "key". */ -void gtk_object_set_data (GtkObject *object, - const gchar *key, - gpointer data); - -/* Like gtk_object_set_data, but takes an additional argument - * which is a function to be called when the data is removed. - */ -void gtk_object_set_data_full (GtkObject *object, - const gchar *key, - gpointer data, +void gtk_object_set_data (GtkObject *object, + const gchar *key, + gpointer data); +void gtk_object_set_data_full (GtkObject *object, + const gchar *key, + gpointer data, GtkDestroyNotify destroy); - -/* Get the data associated with "key". +void gtk_object_remove_data (GtkObject *object, + const gchar *key); +gpointer gtk_object_get_data (GtkObject *object, + const gchar *key); + +/* Set/get the "user_data" object data field of "object". It should + * be noted that these functions are no different than calling + * `gtk_object_set_data'/`gtk_object_get_data' with a key of "user_data". + * They are merely provided as a convenience. */ -gpointer gtk_object_get_data (GtkObject *object, - const gchar *key); +void gtk_object_set_user_data (GtkObject *object, + gpointer data); +gpointer gtk_object_get_user_data (GtkObject *object); -/* Remove the data associated with "key". This call is - * equivalent to 'gtk_object_set_data' where 'data' is NULL. - */ -void gtk_object_remove_data (GtkObject *object, - const gchar *key); -/* Object data functions that operate on key ids. - * These functions are meant for *internal* use only. +/* Object-level methods */ + +/* Append "signals" to those already defined in "class". */ +void gtk_object_class_add_signals (GtkObjectClass *klass, + guint *signals, + guint nsignals); +/* the `arg_name' argument needs to be a const static string */ +void gtk_object_add_arg_type (const gchar *arg_name, + GtkType arg_type, + guint arg_flags, + guint arg_id); + +/* The next two functions are provided to check an object/class pointer + * for its validity. Appropriate warning messages will be put out if + * the object or class pointers are invalid. */ +GtkObject* gtk_object_check_cast (GtkObject *obj, + GtkType cast_type); + +GtkObjectClass* gtk_object_check_class_cast (GtkObjectClass *klass, + GtkType cast_type); + +/* Object data method variants that operate on key ids. */ void gtk_object_set_data_by_id (GtkObject *object, GQuark data_id, gpointer data); @@ -364,35 +372,42 @@ void gtk_object_remove_data_by_id (GtkObject *object, #define gtk_object_data_try_key g_quark_try_string #define gtk_object_data_force_id g_quark_from_string -/* Set the "user_data" object data field of "object". It should - * be noted that this is no different than calling 'gtk_object_set_data' - * with a key of "user_data". It is merely provided as a convenience. - */ -void gtk_object_set_user_data (GtkObject *object, - gpointer data); - -/* Get the "user_data" object data field of "object". It should - * be noted that this is no different than calling 'gtk_object_get_data' - * with a key of "user_data". It is merely provided as a convenience. - */ -gpointer gtk_object_get_user_data (GtkObject *object); - -GtkObject* gtk_object_check_cast (GtkObject *obj, - GtkType cast_type); -GtkObjectClass* gtk_object_check_class_cast (GtkObjectClass *klass, - GtkType cast_type); +/* Non-public methods */ +void gtk_object_arg_set (GtkObject *object, + GtkArg *arg, + GtkArgInfo *info); +void gtk_object_arg_get (GtkObject *object, + GtkArg *arg, + GtkArgInfo *info); +gchar* gtk_object_args_collect (GtkType object_type, + GSList **arg_list_p, + GSList **info_list_p, + gpointer var_args_p); void gtk_trace_referencing (GtkObject *object, const gchar *func, guint dummy, guint line, gboolean do_ref); - -#if G_ENABLE_DEBUG +#if G_ENABLE_DEBUG # define gtk_object_ref(o) G_STMT_START{gtk_trace_referencing((o),G_GNUC_PRETTY_FUNCTION,0,__LINE__,1);}G_STMT_END # define gtk_object_unref(o) G_STMT_START{gtk_trace_referencing((o),G_GNUC_PRETTY_FUNCTION,0,__LINE__,0);}G_STMT_END -#endif /* G_ENABLE_DEBUG && __GNUC__ */ +#endif /* G_ENABLE_DEBUG */ + + +/* Deprecated methods */ + +/* Use gtk_object_class_user_signal_new() instead */ +guint gtk_object_class_add_user_signal (GtkObjectClass *klass, + const gchar *name, + GtkSignalMarshaller marshaller, + GtkType return_val, + guint nparams, + ...); + + + diff --git a/gtk/gtksignal.c b/gtk/gtksignal.c index c9dc7d0e16..2fcbd3969b 100644 --- a/gtk/gtksignal.c +++ b/gtk/gtksignal.c @@ -20,13 +20,14 @@ #include #include #include "gtksignal.h" +#include "gtkargcollector.c" #define SIGNAL_BLOCK_SIZE (100) #define HANDLER_BLOCK_SIZE (200) #define EMISSION_BLOCK_SIZE (100) #define DISCONNECT_INFO_BLOCK_SIZE (64) -#define MAX_SIGNAL_PARAMS (32) +#define MAX_SIGNAL_PARAMS (31) enum { @@ -155,11 +156,11 @@ static gint gtk_emission_check (GList *emissions, static gint gtk_handlers_run (GtkHandler *handlers, GtkHandlerInfo *info, gint after); -static void gtk_params_get (GtkArg *params, +static gboolean gtk_signal_collect_params (GtkArg *params, guint nparams, GtkType *param_types, - GtkType return_val, - va_list args); + GtkType return_type, + va_list var_args); #define LOOKUP_SIGNAL_ID(signal_id) ( \ signal_id > 0 && signal_id < gtk_n_signals ? \ @@ -276,7 +277,7 @@ gtk_signal_newv (const gchar *r_name, g_return_val_if_fail (r_name != NULL, 0); g_return_val_if_fail (marshaller != NULL, 0); - g_return_val_if_fail (nparams <= MAX_SIGNAL_PARAMS, 0); + g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0); if (nparams) g_return_val_if_fail (params != NULL, 0); @@ -367,7 +368,7 @@ gtk_signal_new (const gchar *name, va_list args; guint signal_id; - g_return_val_if_fail (nparams <= MAX_SIGNAL_PARAMS, 0); + g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0); if (nparams > 0) { @@ -495,7 +496,8 @@ gtk_signal_emit (GtkObject *object, { GtkSignal *signal; va_list args; - GtkArg params[MAX_SIGNAL_PARAMS]; + GtkArg params[MAX_SIGNAL_PARAMS + 1]; + gboolean abort; g_return_if_fail (object != NULL); g_return_if_fail (signal_id >= 1); @@ -505,14 +507,15 @@ gtk_signal_emit (GtkObject *object, g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type)); va_start (args, signal_id); - gtk_params_get (params, - signal->nparams, - signal->params, - signal->return_val, - args); + abort = gtk_signal_collect_params (params, + signal->nparams, + signal->params, + signal->return_val, + args); va_end (args); - gtk_signal_real_emit (object, signal, params); + if (!abort) + gtk_signal_real_emit (object, signal, params); } void @@ -561,22 +564,24 @@ gtk_signal_emit_by_name (GtkObject *object, if (signal_id >= 1) { GtkSignal *signal; - GtkArg params[MAX_SIGNAL_PARAMS]; + GtkArg params[MAX_SIGNAL_PARAMS + 1]; va_list args; + gboolean abort; signal = LOOKUP_SIGNAL_ID (signal_id); g_return_if_fail (signal != NULL); g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object), signal->object_type)); va_start (args, name); - gtk_params_get (params, - signal->nparams, - signal->params, - signal->return_val, - args); + abort = gtk_signal_collect_params (params, + signal->nparams, + signal->params, + signal->return_val, + args); va_end (args); - gtk_signal_real_emit (object, signal, params); + if (!abort) + gtk_signal_real_emit (object, signal, params); } else { @@ -1794,163 +1799,62 @@ gtk_handlers_run (GtkHandler *handlers, return EMISSION_CONTINUE; } -static void -gtk_params_get (GtkArg *params, - guint nparams, - GtkType *param_types, - GtkType return_val, - va_list args) +static gboolean +gtk_signal_collect_params (GtkArg *params, + guint n_params, + GtkType *param_types, + GtkType return_type, + va_list var_args) { - gint i; - - for (i = 0; i < nparams; i++) + register GtkArg *last_param; + register gboolean failed = FALSE; + + for (last_param = params + n_params; params < last_param; params++) { - params[i].type = param_types[i]; - params[i].name = NULL; - - switch (GTK_FUNDAMENTAL_TYPE (param_types[i])) + register gchar *error; + + params->type = *(param_types++); + params->name = NULL; + error = gtk_arg_collect_value (GTK_FUNDAMENTAL_TYPE (params->type), + params, + &var_args); + if (error) { - case GTK_TYPE_INVALID: - break; - case GTK_TYPE_NONE: - break; - case GTK_TYPE_CHAR: - GTK_VALUE_CHAR(params[i]) = va_arg (args, gint); - break; - case GTK_TYPE_BOOL: - GTK_VALUE_BOOL(params[i]) = va_arg (args, gint); - break; - case GTK_TYPE_INT: - GTK_VALUE_INT(params[i]) = va_arg (args, gint); - break; - case GTK_TYPE_UINT: - GTK_VALUE_UINT(params[i]) = va_arg (args, guint); - break; - case GTK_TYPE_ENUM: - GTK_VALUE_ENUM(params[i]) = va_arg (args, gint); - break; - case GTK_TYPE_FLAGS: - GTK_VALUE_FLAGS(params[i]) = va_arg (args, gint); - break; - case GTK_TYPE_LONG: - GTK_VALUE_LONG(params[i]) = va_arg (args, glong); - break; - case GTK_TYPE_ULONG: - GTK_VALUE_ULONG(params[i]) = va_arg (args, gulong); - break; - case GTK_TYPE_FLOAT: - GTK_VALUE_FLOAT(params[i]) = va_arg (args, gfloat); - break; - case GTK_TYPE_DOUBLE: - GTK_VALUE_DOUBLE(params[i]) = va_arg (args, gdouble); - break; - case GTK_TYPE_STRING: - GTK_VALUE_STRING(params[i]) = va_arg (args, gchar*); - break; - case GTK_TYPE_POINTER: - GTK_VALUE_POINTER(params[i]) = va_arg (args, gpointer); - break; - case GTK_TYPE_BOXED: - GTK_VALUE_BOXED(params[i]) = va_arg (args, gpointer); - break; - case GTK_TYPE_SIGNAL: - GTK_VALUE_SIGNAL(params[i]).f = va_arg (args, GtkFunction); - GTK_VALUE_SIGNAL(params[i]).d = va_arg (args, gpointer); - break; - case GTK_TYPE_FOREIGN: - GTK_VALUE_FOREIGN(params[i]).data = va_arg (args, gpointer); - GTK_VALUE_FOREIGN(params[i]).notify = - va_arg (args, GtkDestroyNotify); - break; - case GTK_TYPE_CALLBACK: - GTK_VALUE_CALLBACK(params[i]).marshal = - va_arg (args, GtkCallbackMarshal); - GTK_VALUE_CALLBACK(params[i]).data = va_arg (args, gpointer); - GTK_VALUE_CALLBACK(params[i]).notify = - va_arg (args, GtkDestroyNotify); - break; - case GTK_TYPE_C_CALLBACK: - GTK_VALUE_C_CALLBACK(params[i]).func = va_arg (args, GtkFunction); - GTK_VALUE_C_CALLBACK(params[i]).func_data = va_arg (args, gpointer); - break; - case GTK_TYPE_ARGS: - GTK_VALUE_ARGS(params[i]).n_args = va_arg (args, gint); - GTK_VALUE_ARGS(params[i]).args = va_arg (args, GtkArg*); - break; - case GTK_TYPE_OBJECT: - GTK_VALUE_OBJECT(params[i]) = va_arg (args, GtkObject*); - if (GTK_VALUE_OBJECT(params[i]) != NULL && - !GTK_CHECK_TYPE (GTK_VALUE_OBJECT(params[i]), params[i].type)) - g_warning ("signal arg `%s' is not of type `%s'", - gtk_type_name (GTK_OBJECT_TYPE (GTK_VALUE_OBJECT(params[i]))), - gtk_type_name (params[i].type)); - break; - default: - g_error ("unsupported type `%s' in signal arg", - gtk_type_name (params[i].type)); - break; + failed = TRUE; + g_warning ("gtk_signal_collect_params(): %s", error); + g_free (error); } } - - params[i].type = return_val; - params[i].name = NULL; - - switch (GTK_FUNDAMENTAL_TYPE (return_val)) + + params->type = return_type; + params->name = NULL; + + return_type = GTK_FUNDAMENTAL_TYPE (return_type); + if (return_type != GTK_TYPE_NONE) { - case GTK_TYPE_INVALID: - break; - case GTK_TYPE_NONE: - break; - case GTK_TYPE_CHAR: - params[i].d.pointer_data = va_arg (args, gchar*); - break; - case GTK_TYPE_BOOL: - params[i].d.pointer_data = va_arg (args, gint*); - break; - case GTK_TYPE_INT: - params[i].d.pointer_data = va_arg (args, gint*); - break; - case GTK_TYPE_UINT: - params[i].d.pointer_data = va_arg (args, guint*); - break; - case GTK_TYPE_ENUM: - params[i].d.pointer_data = va_arg (args, gint*); - break; - case GTK_TYPE_FLAGS: - params[i].d.pointer_data = va_arg (args, gint*); - break; - case GTK_TYPE_LONG: - params[i].d.pointer_data = va_arg (args, glong*); - break; - case GTK_TYPE_ULONG: - params[i].d.pointer_data = va_arg (args, gulong*); - break; - case GTK_TYPE_FLOAT: - params[i].d.pointer_data = va_arg (args, gfloat*); - break; - case GTK_TYPE_DOUBLE: - params[i].d.pointer_data = va_arg (args, gdouble*); - break; - case GTK_TYPE_STRING: - params[i].d.pointer_data = va_arg (args, gchar**); - break; - case GTK_TYPE_POINTER: - params[i].d.pointer_data = va_arg (args, gpointer*); - break; - case GTK_TYPE_BOXED: - params[i].d.pointer_data = va_arg (args, gpointer*); - break; - case GTK_TYPE_OBJECT: - params[i].d.pointer_data = va_arg (args, GtkObject**); - break; - case GTK_TYPE_SIGNAL: - case GTK_TYPE_FOREIGN: - case GTK_TYPE_CALLBACK: - case GTK_TYPE_C_CALLBACK: - case GTK_TYPE_ARGS: - default: - g_error ("Gtk: unsupported type `%s' in signal return", - gtk_type_name (return_val)); - break; + if ((return_type >= GTK_TYPE_CHAR && + return_type <= GTK_TYPE_BOXED) || + (return_type == GTK_TYPE_POINTER) || + (return_type == GTK_TYPE_OBJECT)) + { + GTK_VALUE_POINTER (*params) = va_arg (var_args, gpointer); + + if (GTK_VALUE_POINTER (*params) == NULL) + { + failed = TRUE; + g_warning ("gtk_signal_collect_params(): invalid NULL pointer for return argument type `%s'", + gtk_type_name (params->type)); + } + } + else + { + failed = TRUE; + g_warning ("gtk_signal_collect_params(): unsupported return argument type `%s'", + gtk_type_name (params->type)); + } } + else + GTK_VALUE_POINTER (*params) = NULL; + + return failed; } diff --git a/gtk/gtksignal.h b/gtk/gtksignal.h index bc2c9c612f..5ca9346314 100644 --- a/gtk/gtksignal.h +++ b/gtk/gtksignal.h @@ -31,11 +31,7 @@ extern "C" { #endif /* __cplusplus */ -#ifdef offsetof -#define GTK_SIGNAL_OFFSET(t, f) ((gint) offsetof (t, f)) -#else /* offsetof */ -#define GTK_SIGNAL_OFFSET(t, f) ((gint) ((gchar*) &((t*) 0)->f)) -#endif /* offsetof */ +#define GTK_SIGNAL_OFFSET(struct, field) (GTK_STRUCT_OFFSET (struct, field)) typedef void (*GtkSignalMarshal) (GtkObject *object, diff --git a/gtk/gtktypeutils.c b/gtk/gtktypeutils.c index 8672f408fb..ac0f9323d5 100644 --- a/gtk/gtktypeutils.c +++ b/gtk/gtktypeutils.c @@ -474,27 +474,6 @@ gtk_type_is_a (GtkType type, return FALSE; } -GtkArg* -gtk_arg_copy (GtkArg *src_arg, - GtkArg *dest_arg) -{ - g_return_val_if_fail (src_arg != NULL, NULL); - - if (!dest_arg) - { - dest_arg = g_new0 (GtkArg, 1); - dest_arg->name = src_arg->name; - } - - dest_arg->type = src_arg->type; - dest_arg->d = src_arg->d; - - if (src_arg->type == GTK_TYPE_STRING) - dest_arg->d.string_data = g_strdup (src_arg->d.string_data); - - return dest_arg; -} - static void gtk_type_class_init (GtkTypeNode *node) { @@ -706,25 +685,25 @@ gtk_type_init_builtin_types (void) gchar *name; } fundamental_info[] = { { GTK_TYPE_NONE, "void" }, - { GTK_TYPE_CHAR, "char" }, - { GTK_TYPE_BOOL, "bool" }, - { GTK_TYPE_INT, "int" }, - { GTK_TYPE_UINT, "uint" }, - { GTK_TYPE_LONG, "long" }, - { GTK_TYPE_ULONG, "ulong" }, - { GTK_TYPE_FLOAT, "float" }, - { GTK_TYPE_DOUBLE, "double" }, - { GTK_TYPE_STRING, "string" }, - { GTK_TYPE_ENUM, "enum" }, - { GTK_TYPE_FLAGS, "flags" }, - { GTK_TYPE_BOXED, "boxed" }, - { GTK_TYPE_FOREIGN, "foreign" }, - { GTK_TYPE_CALLBACK, "callback" }, - { GTK_TYPE_ARGS, "args" }, + { GTK_TYPE_CHAR, "gchar" }, + { GTK_TYPE_BOOL, "gboolean" }, + { GTK_TYPE_INT, "gint" }, + { GTK_TYPE_UINT, "guint" }, + { GTK_TYPE_LONG, "glong" }, + { GTK_TYPE_ULONG, "gulong" }, + { GTK_TYPE_FLOAT, "gfloat" }, + { GTK_TYPE_DOUBLE, "gdouble" }, + { GTK_TYPE_STRING, "GtkString" }, + { GTK_TYPE_ENUM, "GtkEnum" }, + { GTK_TYPE_FLAGS, "GtkFlags" }, + { GTK_TYPE_BOXED, "GtkBoxed" }, + { GTK_TYPE_FOREIGN, "GtkForeign" }, + { GTK_TYPE_CALLBACK, "GtkCallback" }, + { GTK_TYPE_ARGS, "GtkArgs" }, - { GTK_TYPE_POINTER, "pointer" }, - { GTK_TYPE_SIGNAL, "signal" }, - { GTK_TYPE_C_CALLBACK, "c_callback" } + { GTK_TYPE_POINTER, "gpointer" }, + { GTK_TYPE_SIGNAL, "GtkSignal" }, + { GTK_TYPE_C_CALLBACK, "GtkCCallback" } }; struct { gchar *type_name; diff --git a/gtk/gtktypeutils.h b/gtk/gtktypeutils.h index 5b2c4b25fa..98e4968315 100644 --- a/gtk/gtktypeutils.h +++ b/gtk/gtktypeutils.h @@ -82,12 +82,8 @@ typedef struct _GtkEnumValue GtkFlagValue; typedef void (*GtkClassInitFunc) (gpointer klass); typedef void (*GtkObjectInitFunc) (gpointer object); -typedef void (*GtkArgGetFunc) (GtkObject *object, - GtkArg *arg, - guint arg_id); -typedef void (*GtkArgSetFunc) (GtkObject *object, - GtkArg *arg, - guint arg_id); +typedef void (*GtkArgGetFunc) (GtkObject*, GtkArg*, guint); +typedef void (*GtkArgSetFunc) (GtkObject*, GtkArg*, guint); typedef gint (*GtkFunction) (gpointer data); typedef void (*GtkCallbackMarshal) (GtkObject *object, gpointer data, @@ -216,8 +212,6 @@ GtkType gtk_type_register_flags (const gchar *type_name, GtkFlagValue *values); GtkEnumValue* gtk_type_enum_get_values (GtkType enum_type); GtkFlagValue* gtk_type_flags_get_values (GtkType flags_type); -GtkArg* gtk_arg_copy (GtkArg *src_arg, - GtkArg *dest_arg); #ifdef __cplusplus diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index a0a0bcebe0..1b4afb1c80 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -208,11 +208,6 @@ static void gtk_widget_set_style_internal (GtkWidget *widget, static void gtk_widget_set_style_recurse (GtkWidget *widget, gpointer client_data); -extern GtkArg* gtk_object_collect_args (guint *nargs, - GtkType (*) (const gchar*), - va_list args1, - va_list args2); - static GtkWidgetAuxInfo* gtk_widget_aux_info_new (void); static void gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info); @@ -1018,30 +1013,48 @@ gtk_widget_init (GtkWidget *widget) *****************************************/ GtkWidget* -gtk_widget_new (guint type, +gtk_widget_new (guint widget_type, ...) { - GtkObject *obj; - GtkArg *args; - guint nargs; - va_list args1; - va_list args2; - - g_return_val_if_fail (gtk_type_is_a (type, gtk_widget_get_type ()), NULL); + GtkObject *object; + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; - obj = gtk_type_new (type); + g_return_val_if_fail (gtk_type_is_a (widget_type, GTK_TYPE_WIDGET), NULL); - va_start (args1, type); - va_start (args2, type); + object = gtk_type_new (widget_type); - args = gtk_object_collect_args (&nargs, gtk_object_get_arg_type, args1, args2); - gtk_object_setv (obj, nargs, args); - g_free (args); + va_start (var_args, widget_type); + error = gtk_object_args_collect (GTK_OBJECT_TYPE (object), + &arg_list, + &info_list, + &var_args); + va_end (var_args); - va_end (args1); - va_end (args2); + if (error) + { + g_warning ("gtk_widget_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 GTK_WIDGET (obj); + return GTK_WIDGET (object); } /***************************************** @@ -1108,22 +1121,44 @@ void gtk_widget_set (GtkWidget *widget, ...) { - GtkArg *args; - guint nargs; - va_list args1; - va_list args2; - + GtkObject *object; + va_list var_args; + GSList *arg_list = NULL; + GSList *info_list = NULL; + gchar *error; + g_return_if_fail (widget != NULL); - - va_start (args1, widget); - va_start (args2, widget); - - args = gtk_object_collect_args (&nargs, gtk_object_get_arg_type, args1, args2); - gtk_object_setv (GTK_OBJECT (widget), nargs, args); - g_free (args); - - va_end (args1); - va_end (args2); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + object = GTK_OBJECT (widget); + + va_start (var_args, widget); + error = gtk_object_args_collect (GTK_OBJECT_TYPE (object), + &arg_list, + &info_list, + &var_args); + va_end (var_args); + + if (error) + { + g_warning ("gtk_widget_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); + } } /***************************************** diff --git a/gtk/testgtk.c b/gtk/testgtk.c index d614dc28b6..efe14dc18c 100644 --- a/gtk/testgtk.c +++ b/gtk/testgtk.c @@ -870,8 +870,7 @@ statusbar_popped (GtkStatusbar *statusbar, } static void -statusbar_contexts (GtkWidget *button, - GtkStatusbar *statusbar) +statusbar_contexts (GtkStatusbar *statusbar) { gchar *string; @@ -902,8 +901,7 @@ statusbar_contexts (GtkWidget *button, } static void -statusbar_dump_stack (GtkWidget *button, - GtkStatusbar *statusbar) +statusbar_dump_stack (GtkStatusbar *statusbar) { GSList *list; @@ -960,38 +958,38 @@ create_statusbar (void) NULL); button = gtk_widget_new (gtk_button_get_type (), - "GtkButton::label", "push something", - "GtkWidget::visible", TRUE, - "GtkWidget::parent", box2, - "GtkObject::signal::clicked", statusbar_push, statusbar, + "label", "push something", + "visible", TRUE, + "parent", box2, + "signal::clicked", statusbar_push, statusbar, NULL); button = gtk_widget_new (gtk_button_get_type (), - "GtkButton::label", "pop", - "GtkWidget::visible", TRUE, - "GtkWidget::parent", box2, - "GtkObject::signal::clicked", statusbar_pop, statusbar, + "label", "pop", + "visible", TRUE, + "parent", box2, + "signal_after::clicked", statusbar_pop, statusbar, NULL); button = gtk_widget_new (gtk_button_get_type (), - "GtkButton::label", "steal #4", - "GtkWidget::visible", TRUE, - "GtkWidget::parent", box2, - "GtkObject::signal::clicked", statusbar_steal, statusbar, + "label", "steal #4", + "visible", TRUE, + "parent", box2, + "signal_after::clicked", statusbar_steal, statusbar, NULL); button = gtk_widget_new (gtk_button_get_type (), - "GtkButton::label", "dump stack", - "GtkWidget::visible", TRUE, - "GtkWidget::parent", box2, - "GtkObject::signal::clicked", statusbar_dump_stack, statusbar, + "label", "dump stack", + "visible", TRUE, + "parent", box2, + "object_signal::clicked", statusbar_dump_stack, statusbar, NULL); button = gtk_widget_new (gtk_button_get_type (), - "GtkButton::label", "test contexts", - "GtkWidget::visible", TRUE, - "GtkWidget::parent", box2, - "GtkObject::signal::clicked", statusbar_contexts, statusbar, + "label", "test contexts", + "visible", TRUE, + "parent", box2, + "object_signal_after::clicked", statusbar_contexts, statusbar, NULL); separator = gtk_hseparator_new (); -- cgit v1.2.1