*
* 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
+ * 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
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
#include "gtksignal.h"
+#include "gtkargcollector.c"
-#define MAX_PARAMS 20
-#define DONE 1
-#define RESTART 2
+#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 (31)
+
+enum
+{
+ EMISSION_CONTINUE,
+ EMISSION_RESTART,
+ EMISSION_DONE
+};
-#define GTK_RUN_TYPE(x) ((x) & GTK_RUN_MASK)
+#define GTK_RUN_TYPE(x) ((x) & GTK_RUN_BOTH)
-typedef struct _GtkSignal GtkSignal;
-typedef struct _GtkSignalInfo GtkSignalInfo;
-typedef struct _GtkHandler GtkHandler;
-typedef struct _GtkHandlerInfo GtkHandlerInfo;
-typedef struct _GtkEmission GtkEmission;
+typedef struct _GtkSignal GtkSignal;
+typedef struct _GtkSignalHash GtkSignalHash;
+typedef struct _GtkHandler GtkHandler;
+typedef struct _GtkEmission GtkEmission;
+typedef struct _GtkEmissionHookData GtkEmissionHookData;
+typedef struct _GtkDisconnectInfo GtkDisconnectInfo;
typedef void (*GtkSignalMarshaller0) (GtkObject *object,
- gpointer data);
+ gpointer data);
-struct _GtkSignalInfo
+struct _GtkSignal
{
- gchar *name;
- GtkType object_type;
- guint signal_type;
+ guint signal_id;
+ GtkType object_type;
+ gchar *name;
+ guint function_offset;
+ GtkSignalMarshaller marshaller;
+ GtkType return_val;
+ guint signal_flags : 16;
+ guint nparams : 16;
+ GtkType *params;
+ GHookList *hook_list;
};
-struct _GtkSignal
+struct _GtkSignalHash
{
- GtkSignalInfo info;
- guint function_offset;
- GtkSignalRunType run_type;
- GtkSignalMarshaller marshaller;
- GtkType return_val;
- GtkType *params;
- guint nparams;
+ GtkType object_type;
+ GQuark quark;
+ guint signal_id;
};
struct _GtkHandler
{
- guint id : 28;
- guint blocked : 1;
- guint object_signal : 1;
- guint after : 1;
- guint no_marshal : 1;
- guint16 ref_count;
- guint16 signal_type;
- GtkSignalFunc func;
- gpointer func_data;
+ guint id;
+ GtkHandler *next;
+ GtkHandler *prev;
+ guint blocked : 20;
+ guint object_signal : 1;
+ guint after : 1;
+ guint no_marshal : 1;
+ guint16 ref_count;
+ guint16 signal_id;
+ GtkSignalFunc func;
+ gpointer func_data;
GtkSignalDestroy destroy_func;
- GtkHandler *prev;
- GtkHandler *next;
};
-struct _GtkHandlerInfo
+struct _GtkEmission
+{
+ GtkObject *object;
+ guint16 signal_id;
+ guint in_hook : 1;
+ GtkEmission *next;
+};
+
+struct _GtkEmissionHookData
{
GtkObject *object;
- GtkSignalMarshaller marshaller;
+ guint signal_id;
+ guint n_params;
GtkArg *params;
- GtkType *param_types;
- GtkType return_val;
- GtkSignalRunType run_type;
- guint nparams;
- guint signal_type;
};
-struct _GtkEmission
+struct _GtkDisconnectInfo
{
- GtkObject *object;
- guint signal_type;
+ GtkObject *object1;
+ guint disconnect_handler1;
+ guint signal_handler;
+ GtkObject *object2;
+ guint disconnect_handler2;
};
-static void gtk_signal_init (void);
-static guint gtk_signal_hash (guint *key);
-static gint gtk_signal_compare (guint *a,
- guint *b);
-static guint gtk_signal_info_hash (GtkSignalInfo *a);
-static gint gtk_signal_info_compare (GtkSignalInfo *a,
- GtkSignalInfo *b);
+static guint gtk_signal_hash (gconstpointer h);
+static gint gtk_signal_compare (gconstpointer h1,
+ gconstpointer h2);
static GtkHandler* gtk_signal_handler_new (void);
-static void gtk_signal_handler_ref (GtkHandler *handler);
-static void gtk_signal_handler_unref (GtkHandler *handler,
+static void gtk_signal_handler_ref (GtkHandler *handler);
+static void gtk_signal_handler_unref (GtkHandler *handler,
GtkObject *object);
-static void gtk_signal_handler_insert (GtkObject *object,
+static void gtk_signal_handler_insert (GtkObject *object,
GtkHandler *handler);
-static void gtk_signal_real_emit (GtkObject *object,
- guint signal_type,
- va_list args);
-static GtkHandler* gtk_signal_get_handlers (GtkObject *object,
- guint signal_type);
-static guint gtk_signal_connect_by_type (GtkObject *object,
- guint signal_type,
+static void gtk_signal_real_emit (GtkObject *object,
+ guint signal_id,
+ GtkArg *params);
+static guint gtk_signal_connect_by_type (GtkObject *object,
+ guint signal_id,
GtkSignalFunc func,
gpointer func_data,
GtkSignalDestroy destroy_func,
- gint object_signal,
- gint after,
- gint no_marshal);
-static GtkEmission* gtk_emission_new (void);
-static void gtk_emission_destroy (GtkEmission *emission);
-static void gtk_emission_add (GList **emissions,
+ gint object_signal,
+ gint after,
+ gint no_marshal);
+static guint gtk_alive_disconnecter (GtkDisconnectInfo *info);
+static GtkEmission* gtk_emission_new (void);
+static void gtk_emission_add (GtkEmission **emissions,
GtkObject *object,
- guint signal_type);
-static void gtk_emission_remove (GList **emissions,
+ guint signal_type);
+static void gtk_emission_remove (GtkEmission **emissions,
GtkObject *object,
- guint signal_type);
-static gint gtk_emission_check (GList *emissions,
+ guint signal_type);
+static gint gtk_emission_check (GtkEmission *emissions,
GtkObject *object,
- guint signal_type);
-static gint gtk_handlers_run (GtkHandler *handlers,
- GtkHandlerInfo *info,
- gint after);
-static void gtk_params_get (GtkArg *params,
- guint nparams,
- GtkType *param_types,
- GtkType return_val,
- va_list args);
+ guint signal_type);
+static gint gtk_handlers_run (GtkHandler *handlers,
+ GtkSignal *signal,
+ GtkObject *object,
+ GtkArg *params,
+ gint after);
+static gboolean gtk_emission_hook_marshaller (GHook *hook,
+ gpointer data);
+static gboolean gtk_signal_collect_params (GtkArg *params,
+ guint nparams,
+ GtkType *param_types,
+ GtkType return_type,
+ va_list var_args);
+
+#define LOOKUP_SIGNAL_ID(signal_id) ( \
+ signal_id > 0 && signal_id < _gtk_private_n_signals ? \
+ (GtkSignal*) _gtk_private_signals + signal_id : \
+ (GtkSignal*) 0 \
+)
+
+
+static GtkSignalMarshal global_marshaller = NULL;
+static GtkSignalDestroy global_destroy_notify = NULL;
+
+static guint gtk_handler_id = 1;
+static guint gtk_handler_quark = 0;
+static GHashTable *gtk_signal_hash_table = NULL;
+ GtkSignal *_gtk_private_signals = NULL;
+ guint _gtk_private_n_signals = 0;
+static GMemChunk *gtk_signal_hash_mem_chunk = NULL;
+static GMemChunk *gtk_disconnect_info_mem_chunk = NULL;
+static GtkHandler *gtk_handler_free_list = NULL;
+static GtkEmission *gtk_free_emissions = NULL;
+
+
+
+static GtkEmission *current_emissions = NULL;
+static GtkEmission *stop_emissions = NULL;
+static GtkEmission *restart_emissions = NULL;
+
+static GtkSignal*
+gtk_signal_next_and_invalidate (void)
+{
+ static guint gtk_n_free_signals = 0;
+ register GtkSignal *signal;
+ register guint new_signal_id;
+
+ /* don't keep *any* GtkSignal pointers across invokation of this function!!!
+ */
+
+ if (gtk_n_free_signals == 0)
+ {
+ register guint i;
+ register guint size;
+
+ /* nearest pow
+ */
+ size = _gtk_private_n_signals + SIGNAL_BLOCK_SIZE;
+ size *= sizeof (GtkSignal);
+ i = 1;
+ while (i < size)
+ i <<= 1;
+ size = i;
+
+ _gtk_private_signals = g_realloc (_gtk_private_signals, size);
+
+ gtk_n_free_signals = size / sizeof (GtkSignal) - _gtk_private_n_signals;
+
+ memset (_gtk_private_signals + _gtk_private_n_signals, 0, gtk_n_free_signals * sizeof (GtkSignal));
+ }
+
+ new_signal_id = _gtk_private_n_signals++;
+ gtk_n_free_signals--;
+ g_assert (_gtk_private_n_signals < 65535);
+
+ signal = LOOKUP_SIGNAL_ID (new_signal_id);
+ if (signal)
+ signal->signal_id = new_signal_id;
+
+ return signal;
+}
-static gint initialize = TRUE;
-static GHashTable *signal_hash_table = NULL;
-static GHashTable *signal_info_hash_table = NULL;
-static guint next_signal = 1;
-static guint next_handler_id = 1;
+static inline GtkHandler*
+gtk_signal_get_handlers (GtkObject *object,
+ guint signal_id)
+{
+ GtkHandler *handlers;
+
+ handlers = gtk_object_get_data_by_id (object, gtk_handler_quark);
+
+ while (handlers)
+ {
+ if (handlers->signal_id == signal_id)
+ return handlers;
+ handlers = handlers->next;
+ }
+
+ return NULL;
+}
-static const gchar *handler_key = "gtk-signal-handlers";
-static guint handler_key_id = 0;
+void
+gtk_signal_init (void)
+{
+ if (!gtk_handler_quark)
+ {
+ GtkSignal *zero;
+
+ zero = gtk_signal_next_and_invalidate ();
+ g_assert (zero == NULL);
+
+ gtk_handler_quark = g_quark_from_static_string ("gtk-signal-handlers");
+
+ gtk_signal_hash_mem_chunk =
+ g_mem_chunk_new ("GtkSignalHash mem chunk",
+ sizeof (GtkSignalHash),
+ sizeof (GtkSignalHash) * SIGNAL_BLOCK_SIZE,
+ G_ALLOC_ONLY);
+ gtk_disconnect_info_mem_chunk =
+ g_mem_chunk_new ("GtkDisconnectInfo mem chunk",
+ sizeof (GtkDisconnectInfo),
+ sizeof (GtkDisconnectInfo) * DISCONNECT_INFO_BLOCK_SIZE,
+ G_ALLOC_AND_FREE);
+ gtk_handler_free_list = NULL;
+ gtk_free_emissions = NULL;
+
+ gtk_signal_hash_table = g_hash_table_new (gtk_signal_hash,
+ gtk_signal_compare);
+ }
+}
-static GMemChunk *handler_mem_chunk = NULL;
-static GMemChunk *emission_mem_chunk = NULL;
+guint
+gtk_signal_newv (const gchar *r_name,
+ GtkSignalRunType signal_flags,
+ GtkType object_type,
+ guint function_offset,
+ GtkSignalMarshaller marshaller,
+ GtkType return_val,
+ guint nparams,
+ GtkType *params)
+{
+ GtkSignal *signal;
+ GtkSignalHash *hash;
+ GQuark quark;
+ guint i;
+ gchar *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);
+ if (nparams)
+ g_return_val_if_fail (params != NULL, 0);
+
+ if (!gtk_handler_quark)
+ gtk_signal_init ();
+
+
+ name = g_strdup (r_name);
+ g_strdelimit (name, NULL, '_');
-static GList *current_emissions = NULL;
-static GList *stop_emissions = NULL;
-static GList *restart_emissions = NULL;
+ quark = gtk_signal_lookup (name, object_type);
+ if (quark)
+ {
+ g_warning ("gtk_signal_newv(): signal \"%s\" already exists in the `%s' class ancestry\n",
+ r_name,
+ gtk_type_name (object_type));
+ g_free (name);
+ return 0;
+ }
+
+ if (return_val != GTK_TYPE_NONE &&
+ (signal_flags & GTK_RUN_BOTH) == GTK_RUN_FIRST)
+ {
+ g_warning ("gtk_signal_newv(): signal \"%s\" - return value `%s' incompatible with GTK_RUN_FIRST",
+ name, gtk_type_name (return_val));
+ g_free (name);
+ return 0;
+ }
+
+ signal = gtk_signal_next_and_invalidate ();
+
+ /* signal->signal_id already set */
+
+ signal->object_type = object_type;
+ signal->name = name;
+ signal->function_offset = function_offset;
+ signal->marshaller = marshaller;
+ signal->return_val = return_val;
+ signal->signal_flags = signal_flags;
+ signal->nparams = nparams;
+ signal->hook_list = NULL;
+
+ if (nparams > 0)
+ {
+ signal->params = g_new (GtkType, nparams);
+
+ for (i = 0; i < nparams; i++)
+ signal->params[i] = params[i];
+ }
+ else
+ signal->params = NULL;
-static GtkSignalMarshal marshal = NULL;
-static GtkSignalDestroy destroy = NULL;
+ /* insert "signal_name" into hash table
+ */
+ hash = g_chunk_new (GtkSignalHash, gtk_signal_hash_mem_chunk);
+ hash->object_type = object_type;
+ hash->quark = g_quark_from_string (signal->name);
+ hash->signal_id = signal->signal_id;
+ g_hash_table_insert (gtk_signal_hash_table, hash, GUINT_TO_POINTER (hash->signal_id));
+ /* insert "signal-name" into hash table
+ */
+ g_strdelimit (signal->name, NULL, '-');
+ quark = g_quark_from_static_string (signal->name);
+ if (quark != hash->quark)
+ {
+ hash = g_chunk_new (GtkSignalHash, gtk_signal_hash_mem_chunk);
+ hash->object_type = object_type;
+ hash->quark = quark;
+ hash->signal_id = signal->signal_id;
+ g_hash_table_insert (gtk_signal_hash_table, hash, GUINT_TO_POINTER (hash->signal_id));
+ }
+
+ return signal->signal_id;
+}
guint
-gtk_signal_new (const gchar *name,
- GtkSignalRunType run_type,
- GtkType object_type,
- guint function_offset,
+gtk_signal_new (const gchar *name,
+ GtkSignalRunType signal_flags,
+ GtkType object_type,
+ guint function_offset,
GtkSignalMarshaller marshaller,
- GtkType return_val,
- guint nparams,
+ GtkType return_val,
+ guint nparams,
...)
{
GtkType *params;
guint i;
va_list args;
- guint return_id;
+ guint signal_id;
- g_return_val_if_fail (nparams < 16, 0);
+ g_return_val_if_fail (nparams < MAX_SIGNAL_PARAMS, 0);
if (nparams > 0)
{
else
params = NULL;
- return_id = gtk_signal_newv (name,
- run_type,
+ signal_id = gtk_signal_newv (name,
+ signal_flags,
object_type,
function_offset,
marshaller,
g_free (params);
- return return_id;
+ return signal_id;
}
guint
-gtk_signal_newv (const gchar *name,
- GtkSignalRunType run_type,
- GtkType object_type,
- guint function_offset,
- GtkSignalMarshaller marshaller,
- GtkType return_val,
- guint nparams,
- GtkType *params)
+gtk_signal_lookup (const gchar *name,
+ GtkType object_type)
{
- GtkSignal *signal;
- GtkSignalInfo info;
- guint *type;
- guint i;
-
+ GtkSignalHash hash;
+ GtkType lookup_type;
+ gpointer class = NULL;
+
g_return_val_if_fail (name != NULL, 0);
- g_return_val_if_fail (marshaller != NULL, 0);
- g_return_val_if_fail (nparams < 16, 0);
- if (nparams)
- g_return_val_if_fail (params != NULL, 0);
-
- if (initialize)
- gtk_signal_init ();
-
- info.name = (char*)name;
- info.object_type = object_type;
+ g_return_val_if_fail (gtk_type_is_a (object_type, GTK_TYPE_OBJECT), 0);
- type = g_hash_table_lookup (signal_info_hash_table, &info);
- if (type)
+ relookup:
+
+ lookup_type = object_type;
+ hash.quark = g_quark_try_string (name);
+ if (hash.quark)
{
- g_warning ("gtk_signal_newv(): signal \"%s\" already exists in the `%s' class ancestry\n",
- name, gtk_type_name (object_type));
- return 0;
+ while (lookup_type)
+ {
+ guint signal_id;
+
+ hash.object_type = lookup_type;
+
+ signal_id = GPOINTER_TO_UINT (g_hash_table_lookup (gtk_signal_hash_table, &hash));
+ if (signal_id)
+ return signal_id;
+
+ lookup_type = gtk_type_parent (lookup_type);
+ }
}
-
- signal = g_new (GtkSignal, 1);
- signal->info.name = g_strdup (name);
- signal->info.object_type = object_type;
- signal->info.signal_type = next_signal++;
- signal->function_offset = function_offset;
- signal->run_type = run_type;
- signal->marshaller = marshaller;
- signal->return_val = return_val;
- signal->nparams = nparams;
-
- if (nparams > 0)
+
+ if (!class)
{
- signal->params = g_new (GtkType, nparams);
-
- for (i = 0; i < nparams; i++)
- signal->params[i] = params[i];
+ class = gtk_type_class (object_type);
+ goto relookup;
}
- else
- signal->params = NULL;
-
- g_hash_table_insert (signal_hash_table, &signal->info.signal_type, signal);
- g_hash_table_insert (signal_info_hash_table, &signal->info, &signal->info.signal_type);
-
- return signal->info.signal_type;
+
+ return 0;
}
GtkSignalQuery*
g_return_val_if_fail (signal_id >= 1, NULL);
- signal = g_hash_table_lookup (signal_hash_table, &signal_id);
+ signal = LOOKUP_SIGNAL_ID (signal_id);
if (signal)
{
query = g_new (GtkSignalQuery, 1);
- query->object_type = signal->info.object_type;
+ query->object_type = signal->object_type;
query->signal_id = signal_id;
- query->signal_name = signal->info.name;
+ query->signal_name = signal->name;
query->is_user_signal = signal->function_offset == 0;
- query->run_type = signal->run_type;
+ query->signal_flags = signal->signal_flags;
query->return_val = signal->return_val;
query->nparams = signal->nparams;
query->params = signal->params;
return query;
}
-guint
-gtk_signal_lookup (const gchar *name,
- GtkType object_type)
-{
- GtkSignalInfo info;
-
- g_return_val_if_fail (name != NULL, 0);
- g_return_val_if_fail (gtk_type_is_a (object_type, GTK_TYPE_OBJECT), 0);
-
- if (initialize)
- gtk_signal_init ();
-
- info.name = (char*)name;
-
- while (object_type)
- {
- guint *type;
-
- info.object_type = object_type;
-
- type = g_hash_table_lookup (signal_info_hash_table, &info);
- if (type)
- return *type;
-
- object_type = gtk_type_parent (object_type);
- }
-
- return 0;
-}
-
gchar*
gtk_signal_name (guint signal_id)
{
g_return_val_if_fail (signal_id >= 1, NULL);
- signal = g_hash_table_lookup (signal_hash_table, &signal_id);
+ signal = LOOKUP_SIGNAL_ID (signal_id);
if (signal)
- return signal->info.name;
+ return signal->name;
return NULL;
}
+void
+gtk_signal_emitv (GtkObject *object,
+ guint signal_id,
+ GtkArg *params)
+{
+ GtkSignal *signal;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (signal_id >= 1);
+
+ 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));
+
+ if (signal->nparams > 0)
+ g_return_if_fail (params != NULL);
+
+ gtk_signal_real_emit (object, signal_id, params);
+}
+
void
gtk_signal_emit (GtkObject *object,
- guint signal_id,
+ guint signal_id,
...)
{
- va_list args;
-
+ GtkSignal *signal;
+ va_list args;
+ GtkArg params[MAX_SIGNAL_PARAMS + 1];
+ gboolean abort;
+
g_return_if_fail (object != NULL);
g_return_if_fail (signal_id >= 1);
- if (initialize)
- gtk_signal_init ();
-
+ 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, signal_id);
+ abort = gtk_signal_collect_params (params,
+ signal->nparams,
+ signal->params,
+ signal->return_val,
+ args);
+ va_end (args);
+
+ if (!abort)
+ gtk_signal_real_emit (object, signal_id, params);
+}
+
+void
+gtk_signal_emitv_by_name (GtkObject *object,
+ const gchar *name,
+ GtkArg *params)
+{
+ guint signal_id;
- gtk_signal_real_emit (object, signal_id, args);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (params != NULL);
- va_end (args);
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+
+ if (signal_id >= 1)
+ {
+ GtkSignal *signal;
+
+ 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));
+
+ gtk_signal_real_emit (object, signal_id, params);
+ }
+ else
+ {
+ g_warning ("gtk_signal_emitv_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
+ }
}
void
-gtk_signal_emit_by_name (GtkObject *object,
- const gchar *name,
+gtk_signal_emit_by_name (GtkObject *object,
+ const gchar *name,
...)
{
- guint type;
- va_list args;
+ guint signal_id;
g_return_if_fail (object != NULL);
g_return_if_fail (name != NULL);
- if (initialize)
- gtk_signal_init ();
-
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (type >= 1)
+ if (signal_id >= 1)
{
- va_start (args, name);
-
- gtk_signal_real_emit (object, type, args);
+ GtkSignal *signal;
+ 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);
+ abort = gtk_signal_collect_params (params,
+ signal->nparams,
+ signal->params,
+ signal->return_val,
+ args);
va_end (args);
+
+ if (!abort)
+ gtk_signal_real_emit (object, signal_id, params);
}
else
{
g_warning ("gtk_signal_emit_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
}
}
void
gtk_signal_emit_stop (GtkObject *object,
- guint signal_id)
+ guint signal_id)
{
+ gint state;
+
g_return_if_fail (object != NULL);
g_return_if_fail (signal_id >= 1);
- if (initialize)
- gtk_signal_init ();
-
- if (gtk_emission_check (current_emissions, object, signal_id))
- gtk_emission_add (&stop_emissions, object, signal_id);
+ state = gtk_emission_check (current_emissions, object, signal_id);
+ if (state > 1)
+ g_warning ("gtk_signal_emit_stop(): emission (%u) for object `%s' cannot be stopped from emission hook",
+ signal_id,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
+ else if (state)
+ {
+ if (!gtk_emission_check (stop_emissions, object, signal_id))
+ gtk_emission_add (&stop_emissions, object, signal_id);
+ }
else
g_warning ("gtk_signal_emit_stop(): no current emission (%u) for object `%s'",
- signal_id, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ signal_id,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
}
void
-gtk_signal_emit_stop_by_name (GtkObject *object,
+gtk_signal_emit_stop_by_name (GtkObject *object,
const gchar *name)
{
- guint type;
+ guint signal_id;
g_return_if_fail (object != NULL);
g_return_if_fail (name != NULL);
- if (initialize)
- gtk_signal_init ();
-
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (type)
- gtk_signal_emit_stop (object, type);
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (signal_id)
+ gtk_signal_emit_stop (object, signal_id);
else
g_warning ("gtk_signal_emit_stop_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
}
guint
-gtk_signal_connect (GtkObject *object,
- const gchar *name,
- GtkSignalFunc func,
- gpointer func_data)
+gtk_signal_n_emissions (GtkObject *object,
+ guint signal_id)
{
- guint type;
+ GtkEmission *emission;
+ guint n;
g_return_val_if_fail (object != NULL, 0);
+ g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
- if (initialize)
- gtk_signal_init ();
+ n = 0;
+ for (emission = current_emissions; emission; emission = emission->next)
+ {
+ if (emission->object == object && emission->signal_id == signal_id)
+ n++;
+ }
+
+ return n;
+}
+
+guint
+gtk_signal_n_emissions_by_name (GtkObject *object,
+ const gchar *name)
+{
+ guint signal_id;
+ guint n;
+
+ g_return_val_if_fail (object != NULL, 0);
+ g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
+ g_return_val_if_fail (name != NULL, 0);
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (!type)
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (signal_id)
+ n = gtk_signal_n_emissions (object, signal_id);
+ else
+ {
+ g_warning ("gtk_signal_n_emissions_by_name(): could not find signal \"%s\" in the `%s' class ancestry",
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
+ n = 0;
+ }
+
+ return n;
+}
+
+guint
+gtk_signal_connect (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ gpointer func_data)
+{
+ guint signal_id;
+
+ g_return_val_if_fail (object != NULL, 0);
+ g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
+
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!signal_id)
{
g_warning ("gtk_signal_connect(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
return 0;
}
- return gtk_signal_connect_by_type (object, type,
+ return gtk_signal_connect_by_type (object, signal_id,
func, func_data, NULL,
FALSE, FALSE, FALSE);
}
guint
-gtk_signal_connect_after (GtkObject *object,
- const gchar *name,
- GtkSignalFunc func,
- gpointer func_data)
+gtk_signal_connect_after (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
+ gpointer func_data)
{
- guint type;
+ guint signal_id;
g_return_val_if_fail (object != NULL, 0);
- if (initialize)
- gtk_signal_init ();
-
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (!type)
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!signal_id)
{
g_warning ("gtk_signal_connect_after(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
return 0;
}
- return gtk_signal_connect_by_type (object, type,
+ return gtk_signal_connect_by_type (object, signal_id,
func, func_data, NULL,
FALSE, TRUE, FALSE);
}
-guint
-gtk_signal_connect_full (GtkObject *object,
- const gchar *name,
- GtkSignalFunc func,
+guint
+gtk_signal_connect_full (GtkObject *object,
+ const gchar *name,
+ GtkSignalFunc func,
GtkCallbackMarshal marshal,
- gpointer func_data,
+ gpointer func_data,
GtkDestroyNotify destroy_func,
- gint object_signal,
- gint after)
+ gint object_signal,
+ gint after)
{
- guint type;
+ guint signal_id;
g_return_val_if_fail (object != NULL, 0);
- if (initialize)
- gtk_signal_init ();
-
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (!type)
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!signal_id)
{
g_warning ("gtk_signal_connect_full(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
return 0;
}
if (marshal)
- return gtk_signal_connect_by_type (object, type, (GtkSignalFunc) marshal,
+ return gtk_signal_connect_by_type (object, signal_id, (GtkSignalFunc) marshal,
func_data, destroy_func,
object_signal, after, TRUE);
else
- return gtk_signal_connect_by_type (object, type, func,
+ return gtk_signal_connect_by_type (object, signal_id, func,
func_data, destroy_func,
object_signal, after, FALSE);
}
guint
-gtk_signal_connect_interp (GtkObject *object,
- const gchar *name,
- GtkCallbackMarshal func,
- gpointer func_data,
- GtkDestroyNotify destroy_func,
- gint after)
-{
- return gtk_signal_connect_full (object, name, NULL, func,
- func_data, destroy_func, FALSE, after);
-}
-
-guint
-gtk_signal_connect_object (GtkObject *object,
- const gchar *name,
+gtk_signal_connect_object (GtkObject *object,
+ const gchar *name,
GtkSignalFunc func,
- GtkObject *slot_object)
+ GtkObject *slot_object)
{
- guint type;
+ guint signal_id;
g_return_val_if_fail (object != NULL, 0);
- /* slot_object needs to be treated as ordinary pointer */
-
- if (initialize)
- gtk_signal_init ();
+ /* slot_object needs to be treated as ordinary pointer
+ */
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (!type)
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!signal_id)
{
g_warning ("gtk_signal_connect_object(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
return 0;
}
- return gtk_signal_connect_by_type (object, type,
+ return gtk_signal_connect_by_type (object, signal_id,
func, slot_object, NULL,
TRUE, FALSE, FALSE);
}
guint
gtk_signal_connect_object_after (GtkObject *object,
const gchar *name,
- GtkSignalFunc func,
+ GtkSignalFunc func,
GtkObject *slot_object)
{
- guint type;
+ guint signal_id;
g_return_val_if_fail (object != NULL, 0);
- if (initialize)
- gtk_signal_init ();
-
- type = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
- if (!type)
+ signal_id = gtk_signal_lookup (name, GTK_OBJECT_TYPE (object));
+ if (!signal_id)
{
g_warning ("gtk_signal_connect_object_after(): could not find signal \"%s\" in the `%s' class ancestry",
- name, gtk_type_name (GTK_OBJECT_TYPE (object)));
+ name,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
return 0;
}
- return gtk_signal_connect_by_type (object, type,
+ return gtk_signal_connect_by_type (object, signal_id,
func, slot_object, NULL,
TRUE, TRUE, FALSE);
}
-typedef struct _GtkDisconnectInfo GtkDisconnectInfo;
-struct _GtkDisconnectInfo
-{
- GtkObject *object1;
- guint disconnect_handler1;
- guint signal_handler;
- GtkObject *object2;
- guint disconnect_handler2;
-};
-
-static guint
-gtk_alive_disconnecter (GtkDisconnectInfo *info)
-{
- g_return_val_if_fail (info != NULL, 0);
-
- gtk_signal_disconnect (info->object1, info->disconnect_handler1);
- gtk_signal_disconnect (info->object1, info->signal_handler);
- gtk_signal_disconnect (info->object2, info->disconnect_handler2);
- g_free (info);
-
- return 0;
-}
-
void
-gtk_signal_connect_while_alive (GtkObject *object,
- const gchar *signal,
- GtkSignalFunc func,
- gpointer func_data,
- GtkObject *alive_object)
+gtk_signal_connect_while_alive (GtkObject *object,
+ const gchar *signal,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkObject *alive_object)
{
GtkDisconnectInfo *info;
g_return_if_fail (alive_object != NULL);
g_return_if_fail (GTK_IS_OBJECT (alive_object));
- info = g_new (GtkDisconnectInfo, 1);
+ info = g_chunk_new (GtkDisconnectInfo, gtk_disconnect_info_mem_chunk);
info->object1 = object;
info->object2 = alive_object;
info->signal_handler = gtk_signal_connect (object, signal, func, func_data);
- info->disconnect_handler1 = gtk_signal_connect_object (info->object1,
- "destroy",
- GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
- (GtkObject*) info);
- info->disconnect_handler2 = gtk_signal_connect_object (info->object2,
- "destroy",
- GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
- (GtkObject*) info);
+ info->disconnect_handler1 =
+ gtk_signal_connect_object (info->object1,
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
+ (GtkObject*) info);
+ info->disconnect_handler2 =
+ gtk_signal_connect_object (info->object2,
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
+ (GtkObject*) info);
}
void
-gtk_signal_connect_object_while_alive (GtkObject *object,
- const gchar *signal,
- GtkSignalFunc func,
- GtkObject *alive_object)
+gtk_signal_connect_object_while_alive (GtkObject *object,
+ const gchar *signal,
+ GtkSignalFunc func,
+ GtkObject *alive_object)
{
GtkDisconnectInfo *info;
g_return_if_fail (alive_object != NULL);
g_return_if_fail (GTK_IS_OBJECT (alive_object));
- info = g_new (GtkDisconnectInfo, 1);
+ info = g_chunk_new (GtkDisconnectInfo, gtk_disconnect_info_mem_chunk);
info->object1 = object;
info->object2 = alive_object;
info->signal_handler = gtk_signal_connect_object (object, signal, func, alive_object);
- info->disconnect_handler1 = gtk_signal_connect_object (info->object1,
- "destroy",
- GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
- (GtkObject*) info);
- info->disconnect_handler2 = gtk_signal_connect_object (info->object2,
- "destroy",
- GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
- (GtkObject*) info);
+ info->disconnect_handler1 =
+ gtk_signal_connect_object (info->object1,
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
+ (GtkObject*) info);
+ info->disconnect_handler2 =
+ gtk_signal_connect_object (info->object2,
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_alive_disconnecter),
+ (GtkObject*) info);
}
void
gtk_signal_disconnect (GtkObject *object,
- guint handler_id)
+ guint handler_id)
{
GtkHandler *handler;
g_return_if_fail (object != NULL);
g_return_if_fail (handler_id > 0);
- handler = gtk_object_get_data_by_id (object, handler_key_id);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
while (handler)
{
if (handler->id == handler_id)
{
handler->id = 0;
- handler->blocked = TRUE;
+ handler->blocked += 1;
gtk_signal_handler_unref (handler, object);
return;
}
g_warning ("gtk_signal_disconnect(): could not find handler (%u)", handler_id);
}
+void
+gtk_signal_disconnect_by_func (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer data)
+{
+ GtkHandler *handler;
+ gint found_one;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (func != NULL);
+
+ found_one = FALSE;
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
+
+ while (handler)
+ {
+ GtkHandler *handler_next;
+
+ handler_next = handler->next;
+ if ((handler->id > 0) &&
+ (handler->func == func) &&
+ (handler->func_data == data))
+ {
+ found_one = TRUE;
+ handler->id = 0;
+ handler->blocked += 1;
+ gtk_signal_handler_unref (handler, object);
+ }
+ handler = handler_next;
+ }
+
+ if (!found_one)
+ g_warning ("gtk_signal_disconnect_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
+}
+
void
gtk_signal_disconnect_by_data (GtkObject *object,
- gpointer data)
+ gpointer data)
{
GtkHandler *handler;
gint found_one;
g_return_if_fail (object != NULL);
found_one = FALSE;
- handler = gtk_object_get_data_by_id (object, handler_key_id);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
while (handler)
{
GtkHandler *handler_next;
handler_next = handler->next;
- if (handler->func_data == data &&
- handler->id > 0)
+ if ((handler->id > 0) &&
+ (handler->func_data == data))
{
found_one = TRUE;
handler->id = 0;
- handler->blocked = TRUE;
+ handler->blocked += 1;
gtk_signal_handler_unref (handler, object);
}
handler = handler_next;
gtk_signal_handler_block (GtkObject *object,
guint handler_id)
{
- GtkHandler *tmp;
+ GtkHandler *handler;
g_return_if_fail (object != NULL);
g_return_if_fail (handler_id > 0);
- tmp = gtk_object_get_data_by_id (object, handler_key_id);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
- while (tmp)
+ while (handler)
{
- if (tmp->id == handler_id)
+ if (handler->id == handler_id)
{
- tmp->blocked = TRUE;
+ handler->blocked += 1;
return;
}
-
- tmp = tmp->next;
+ handler = handler->next;
}
g_warning ("gtk_signal_handler_block(): could not find handler (%u)", handler_id);
}
+void
+gtk_signal_handler_block_by_func (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer data)
+{
+ GtkHandler *handler;
+ gint found_one;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (func != NULL);
+
+ found_one = FALSE;
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
+
+ while (handler)
+ {
+ if ((handler->id > 0) &&
+ (handler->func == func) &&
+ (handler->func_data == data))
+ {
+ found_one = TRUE;
+ handler->blocked += 1;
+ }
+ handler = handler->next;
+ }
+
+ if (!found_one)
+ g_warning ("gtk_signal_handler_block_by_func(): could not find handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
+}
+
void
gtk_signal_handler_block_by_data (GtkObject *object,
gpointer data)
g_return_if_fail (object != NULL);
- if (initialize)
- gtk_signal_init ();
-
found_one = FALSE;
- handler = gtk_object_get_data_by_id (object, handler_key_id);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
while (handler)
{
- if (handler->func_data == data &&
- handler->id > 0)
+ if ((handler->id > 0) &&
+ (handler->func_data == data))
{
found_one = TRUE;
- handler->blocked = TRUE;
+ handler->blocked += 1;
}
-
handler = handler->next;
}
g_return_if_fail (object != NULL);
g_return_if_fail (handler_id > 0);
- if (initialize)
- gtk_signal_init ();
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
+
+ while (handler)
+ {
+ if (handler->id == handler_id)
+ {
+ if (handler->blocked > 0)
+ handler->blocked -= 1;
+ else
+ g_warning ("gtk_signal_handler_unblock(): handler (%u) is not blocked", handler_id);
+ return;
+ }
+ handler = handler->next;
+ }
+
+ g_warning ("gtk_signal_handler_unblock(): could not find handler (%u)", handler_id);
+}
+
+void
+gtk_signal_handler_unblock_by_func (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer data)
+{
+ GtkHandler *handler;
+ gint found_one;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (func != NULL);
- handler = gtk_object_get_data_by_id (object, handler_key_id);
+ found_one = FALSE;
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
while (handler)
{
- if (handler->id == handler_id)
+ if ((handler->id > 0) &&
+ (handler->func == func) &&
+ (handler->func_data == data) &&
+ (handler->blocked > 0))
{
- handler->blocked = FALSE;
- return;
+ handler->blocked -= 1;
+ found_one = TRUE;
}
-
handler = handler->next;
}
- g_warning ("gtk_signal_handler_unblock(): could not find handler (%u)", handler_id);
+ if (!found_one)
+ g_warning ("gtk_signal_handler_unblock_by_func(): could not find blocked handler (0x%0lX) containing data (0x%0lX)", (long) func, (long) data);
}
void
g_return_if_fail (object != NULL);
- if (initialize)
- gtk_signal_init ();
-
found_one = FALSE;
- handler = gtk_object_get_data_by_id (object, handler_key_id);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
while (handler)
{
- if (handler->func_data == data &&
- handler->id > 0)
+ if ((handler->id > 0) &&
+ (handler->func_data == data) &&
+ (handler->blocked > 0))
{
+ handler->blocked -= 1;
found_one = TRUE;
- handler->blocked = FALSE;
}
-
handler = handler->next;
}
if (!found_one)
- g_warning ("gtk_signal_handler_unblock_by_data(): could not find handler containing data (0x%0lX)", (long) data);
+ g_warning ("gtk_signal_handler_unblock_by_data(): could not find blocked handler containing data (0x%0lX)", (long) data);
}
void
* handler_key data on each removal
*/
- handler = gtk_object_get_data_by_id (object, handler_key_id);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
if (handler)
{
handler = handler->next;
GtkHandler *next;
next = handler->next;
- gtk_signal_handler_unref (handler, object);
+ if (handler->id > 0)
+ gtk_signal_handler_unref (handler, object);
handler = next;
}
- handler = gtk_object_get_data_by_id (object, handler_key_id);
- gtk_signal_handler_unref (handler, object);
+ handler = gtk_object_get_data_by_id (object, gtk_handler_quark);
+ if (handler->id > 0)
+ gtk_signal_handler_unref (handler, object);
}
}
-void
-gtk_signal_default_marshaller (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *params)
-{
- GtkSignalMarshaller0 rfunc;
-
- rfunc = (GtkSignalMarshaller0) func;
-
- (* rfunc) (object, func_data);
-}
-
void
gtk_signal_set_funcs (GtkSignalMarshal marshal_func,
GtkSignalDestroy destroy_func)
{
- marshal = marshal_func;
- destroy = destroy_func;
-}
-
-
-static void
-gtk_signal_init ()
-{
- if (initialize)
- {
- initialize = FALSE;
- signal_hash_table = g_hash_table_new ((GHashFunc) gtk_signal_hash,
- (GCompareFunc) gtk_signal_compare);
- signal_info_hash_table = g_hash_table_new ((GHashFunc) gtk_signal_info_hash,
- (GCompareFunc) gtk_signal_info_compare);
- }
+ global_marshaller = marshal_func;
+ global_destroy_notify = destroy_func;
}
static guint
-gtk_signal_hash (guint *key)
+gtk_signal_hash (gconstpointer h)
{
- return *key;
+ register const GtkSignalHash *hash = h;
+
+ return hash->object_type ^ hash->quark;
}
static gint
-gtk_signal_compare (guint *a,
- guint *b)
+gtk_signal_compare (gconstpointer h1,
+ gconstpointer h2)
{
- return (*a == *b);
+ register const GtkSignalHash *hash1 = h1;
+ register const GtkSignalHash *hash2 = h2;
+
+ return (hash1->quark == hash2->quark &&
+ hash1->object_type == hash2->object_type);
}
static guint
-gtk_signal_info_hash (GtkSignalInfo *a)
-{
- return (g_str_hash (a->name) + a->object_type);
-}
-
-static gint
-gtk_signal_info_compare (GtkSignalInfo *a,
- GtkSignalInfo *b)
+gtk_alive_disconnecter (GtkDisconnectInfo *info)
{
- return ((a->object_type == b->object_type) &&
- g_str_equal (a->name, b->name));
+ g_return_val_if_fail (info != NULL, 0);
+
+ gtk_signal_disconnect (info->object1, info->disconnect_handler1);
+ gtk_signal_disconnect (info->object1, info->signal_handler);
+ gtk_signal_disconnect (info->object2, info->disconnect_handler2);
+
+ g_mem_chunk_free (gtk_disconnect_info_mem_chunk, info);
+
+ return 0;
}
static GtkHandler*
-gtk_signal_handler_new ()
+gtk_signal_handler_new (void)
{
GtkHandler *handler;
-
- if (!handler_mem_chunk)
- handler_mem_chunk = g_mem_chunk_new ("handler mem chunk", sizeof (GtkHandler),
- 1024, G_ALLOC_AND_FREE);
-
- handler = g_chunk_new (GtkHandler, handler_mem_chunk);
+
+ if (!gtk_handler_free_list)
+ {
+ GtkHandler *handler_block;
+ guint i;
+
+ handler_block = g_new0 (GtkHandler, HANDLER_BLOCK_SIZE);
+ for (i = 1; i < HANDLER_BLOCK_SIZE; i++)
+ {
+ (handler_block + i)->next = gtk_handler_free_list;
+ gtk_handler_free_list = (handler_block + i);
+ }
+
+ handler = handler_block;
+ }
+ else
+ {
+ handler = gtk_handler_free_list;
+ gtk_handler_free_list = handler->next;
+ }
handler->id = 0;
- handler->ref_count = 1;
- handler->signal_type = 0;
- handler->blocked = FALSE;
+ handler->blocked = 0;
+ handler->signal_id = 0;
handler->object_signal = FALSE;
handler->after = FALSE;
handler->no_marshal = FALSE;
+ handler->ref_count = 1;
handler->func = NULL;
handler->func_data = NULL;
handler->destroy_func = NULL;
{
if (!handler->ref_count)
{
- /* FIXME: i wanna get removed some when */
+ /* FIXME: i wanna get removed somewhen */
g_warning ("gtk_signal_handler_unref(): handler with ref_count==0!");
return;
}
handler->ref_count -= 1;
+
if (handler->ref_count == 0)
{
- if (!handler->func && destroy)
- (* destroy) (handler->func_data);
- else if (handler->destroy_func)
+ if (handler->destroy_func)
(* handler->destroy_func) (handler->func_data);
-
+ else if (!handler->func && global_destroy_notify)
+ (* global_destroy_notify) (handler->func_data);
if (handler->prev)
handler->prev->next = handler->next;
+ else if (handler->next)
+ gtk_object_set_data_by_id (object, gtk_handler_quark, handler->next);
else
- gtk_object_set_data_by_id (object, handler_key_id, handler->next);
+ {
+ GTK_OBJECT_UNSET_FLAGS (object, GTK_CONNECTED);
+ gtk_object_set_data_by_id (object, gtk_handler_quark, NULL);
+ }
if (handler->next)
handler->next->prev = handler->prev;
- g_mem_chunk_free (handler_mem_chunk, handler);
+ handler->next = gtk_handler_free_list;
+ gtk_handler_free_list = handler;
}
}
/* FIXME: remove */ g_assert (handler->next == NULL);
/* FIXME: remove */ g_assert (handler->prev == NULL);
- tmp = gtk_object_get_data_by_id (object, handler_key_id);
+ tmp = gtk_object_get_data_by_id (object, gtk_handler_quark);
if (!tmp)
{
- if (!handler_key_id)
- handler_key_id = gtk_object_data_force_id (handler_key);
- gtk_object_set_data_by_id (object, handler_key_id, handler);
+ GTK_OBJECT_SET_FLAGS (object, GTK_CONNECTED);
+ gtk_object_set_data_by_id (object, gtk_handler_quark, handler);
}
else
while (tmp)
{
- if (tmp->signal_type < handler->signal_type)
+ if (tmp->signal_id < handler->signal_id)
{
if (tmp->prev)
{
handler->prev = tmp->prev;
}
else
- gtk_object_set_data_by_id (object, handler_key_id, handler);
+ gtk_object_set_data_by_id (object, gtk_handler_quark, handler);
tmp->prev = handler;
handler->next = tmp;
break;
}
}
+
+#ifdef G_ENABLE_DEBUG
+/* value typically set via gdb */
+static GtkObject *gtk_trace_signal_object = NULL;
+#endif /* G_ENABLE_DEBUG */
+
+
static void
gtk_signal_real_emit (GtkObject *object,
- guint signal_type,
- va_list args)
+ guint signal_id,
+ GtkArg *params)
{
- GtkSignal *signal;
- GtkHandler *handlers;
- GtkHandlerInfo info;
- guchar **signal_func_offset;
- GtkArg params[MAX_PARAMS];
-
- signal = g_hash_table_lookup (signal_hash_table, &signal_type);
- g_return_if_fail (signal != NULL);
- g_return_if_fail (gtk_type_is_a (GTK_OBJECT_TYPE (object),
- signal->info.object_type));
-
- if ((signal->run_type & GTK_RUN_NO_RECURSE) &&
- gtk_emission_check (current_emissions, object, signal_type))
+ GtkSignal signal;
+ GtkHandler *handlers;
+ GtkSignalFunc signal_func;
+ GtkEmission *emission;
+
+ /* gtk_handlers_run() expects a reentrant GtkSignal*, so we allocate
+ * it locally on the stack. we save some lookups ourselves with this as well.
+ */
+ signal = *LOOKUP_SIGNAL_ID (signal_id);
+ if (signal.function_offset)
+ signal_func = G_STRUCT_MEMBER (GtkSignalFunc, object->klass, signal.function_offset);
+ else
+ signal_func = NULL;
+
+#ifdef G_ENABLE_DEBUG
+ if (gtk_debug_flags & GTK_DEBUG_SIGNALS ||
+ object == gtk_trace_signal_object)
+ g_message ("%s::%s emitted (object=%p class-method=%p)\n",
+ gtk_type_name (GTK_OBJECT_TYPE (object)),
+ signal.name,
+ object,
+ signal_func);
+#endif /* G_ENABLE_DEBUG */
+
+ if (signal.signal_flags & GTK_RUN_NO_RECURSE)
{
- gtk_emission_add (&restart_emissions, object, signal_type);
- return;
+ gint state;
+
+ state = gtk_emission_check (current_emissions, object, signal_id);
+ if (state)
+ {
+ if (state > 1)
+ g_warning ("gtk_signal_real_emit(): emission (%u) for object `%s' cannot be restarted from emission hook",
+ signal_id,
+ gtk_type_name (GTK_OBJECT_TYPE (object)));
+ else if (!gtk_emission_check (restart_emissions, object, signal_id))
+ gtk_emission_add (&restart_emissions, object, signal_id);
+
+ return;
+ }
}
- gtk_params_get (params, signal->nparams, signal->params,
- signal->return_val, args);
+ gtk_object_ref (object);
- gtk_emission_add (¤t_emissions, object, signal_type);
+ gtk_emission_add (¤t_emissions, object, signal_id);
+ emission = current_emissions;
- gtk_object_ref (object);
+ emission_restart:
-restart:
- if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_LAST && signal->function_offset != 0)
+ if (signal.signal_flags & GTK_RUN_FIRST && signal_func)
{
- signal_func_offset = (guchar**) ((guchar*) object->klass +
- signal->function_offset);
- if (*signal_func_offset)
- (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset,
- NULL, params);
+ signal.marshaller (object, signal_func, NULL, params);
+
+ if (stop_emissions && gtk_emission_check (stop_emissions, object, signal_id))
+ {
+ gtk_emission_remove (&stop_emissions, object, signal_id);
+ goto emission_done;
+ }
+ else if (restart_emissions &&
+ signal.signal_flags & GTK_RUN_NO_RECURSE &&
+ gtk_emission_check (restart_emissions, object, signal_id))
+ {
+ gtk_emission_remove (&restart_emissions, object, signal_id);
+
+ goto emission_restart;
+ }
}
- info.object = object;
- info.marshaller = signal->marshaller;
- info.params = params;
- info.param_types = signal->params;
- info.return_val = signal->return_val;
- info.nparams = signal->nparams;
- info.run_type = signal->run_type;
- info.signal_type = signal_type;
-
- handlers = gtk_signal_get_handlers (object, signal_type);
- switch (gtk_handlers_run (handlers, &info, FALSE))
+ if (signal.hook_list && !GTK_OBJECT_DESTROYED (object))
{
- case DONE:
- goto done;
- case RESTART:
- goto restart;
+ GtkEmissionHookData data;
+
+ data.object = object;
+ data.n_params = signal.nparams;
+ data.params = params;
+ data.signal_id = signal_id;
+ emission->in_hook = 1;
+ g_hook_list_marshal_check (signal.hook_list, TRUE, gtk_emission_hook_marshaller, &data);
+ emission->in_hook = 0;
}
-
- if (GTK_RUN_TYPE (signal->run_type) != GTK_RUN_FIRST && signal->function_offset != 0)
+
+ if (GTK_OBJECT_CONNECTED (object))
{
- signal_func_offset = (guchar**) ((guchar*) object->klass +
- signal->function_offset);
- if (*signal_func_offset)
- (* signal->marshaller) (object, (GtkSignalFunc) *signal_func_offset,
- NULL, params);
+ handlers = gtk_signal_get_handlers (object, signal_id);
+ if (handlers)
+ {
+ gint return_val;
+
+ return_val = gtk_handlers_run (handlers, &signal, object, params, FALSE);
+ switch (return_val)
+ {
+ case EMISSION_CONTINUE:
+ break;
+ case EMISSION_RESTART:
+ goto emission_restart;
+ case EMISSION_DONE:
+ goto emission_done;
+ }
+ }
}
- handlers = gtk_signal_get_handlers (object, signal_type);
- switch (gtk_handlers_run (handlers, &info, TRUE))
+ if (signal.signal_flags & GTK_RUN_LAST && signal_func)
{
- case DONE:
- goto done;
- case RESTART:
- goto restart;
+ signal.marshaller (object, signal_func, NULL, params);
+
+ if (stop_emissions && gtk_emission_check (stop_emissions, object, signal_id))
+ {
+ gtk_emission_remove (&stop_emissions, object, signal_id);
+ goto emission_done;
+ }
+ else if (restart_emissions &&
+ signal.signal_flags & GTK_RUN_NO_RECURSE &&
+ gtk_emission_check (restart_emissions, object, signal_id))
+ {
+ gtk_emission_remove (&restart_emissions, object, signal_id);
+
+ goto emission_restart;
+ }
}
-done:
+ if (GTK_OBJECT_CONNECTED (object))
+ {
+ handlers = gtk_signal_get_handlers (object, signal_id);
+ if (handlers)
+ {
+ gint return_val;
+
+ return_val = gtk_handlers_run (handlers, &signal, object, params, TRUE);
+ switch (return_val)
+ {
+ case EMISSION_CONTINUE:
+ break;
+ case EMISSION_RESTART:
+ goto emission_restart;
+ case EMISSION_DONE:
+ goto emission_done;
+ }
+ }
+ }
- gtk_emission_remove (¤t_emissions, object, signal_type);
+ emission_done:
+ if (restart_emissions && signal.signal_flags & GTK_RUN_NO_RECURSE)
+ gtk_emission_remove (&restart_emissions, object, signal_id);
- if (signal->run_type & GTK_RUN_NO_RECURSE)
- gtk_emission_remove (&restart_emissions, object, signal_type);
+ gtk_emission_remove (¤t_emissions, object, signal_id);
gtk_object_unref (object);
}
-static GtkHandler*
-gtk_signal_get_handlers (GtkObject *object,
- guint signal_type)
+guint
+gtk_signal_handler_pending (GtkObject *object,
+ guint signal_id,
+ gboolean may_be_blocked)
{
GtkHandler *handlers;
+ guint handler_id;
- g_return_val_if_fail (object != NULL, NULL);
- g_return_val_if_fail (signal_type >= 1, NULL);
-
- handlers = gtk_object_get_data_by_id (object, handler_key_id);
+ g_return_val_if_fail (object != NULL, 0);
+ g_return_val_if_fail (signal_id >= 1, 0);
+
+ if (GTK_OBJECT_CONNECTED (object))
+ handlers = gtk_signal_get_handlers (object, signal_id);
+ else
+ return 0;
- while (handlers)
+ handler_id = 0;
+ while (handlers && handlers->signal_id == signal_id)
{
- if (handlers->signal_type == signal_type)
- return handlers;
+ if (handlers->id > 0 &&
+ (may_be_blocked || handlers->blocked == FALSE))
+ {
+ handler_id = handlers->id;
+ break;
+ }
+
handlers = handlers->next;
}
- return NULL;
+ return handler_id;
}
guint
-gtk_signal_handler_pending (GtkObject *object,
- guint signal_id,
- gboolean may_be_blocked)
+gtk_signal_handler_pending_by_func (GtkObject *object,
+ guint signal_id,
+ gboolean may_be_blocked,
+ GtkSignalFunc func,
+ gpointer data)
{
GtkHandler *handlers;
guint handler_id;
g_return_val_if_fail (object != NULL, 0);
+ g_return_val_if_fail (func != NULL, 0);
g_return_val_if_fail (signal_id >= 1, 0);
-
- handlers = gtk_signal_get_handlers (object, signal_id);
+
+ if (GTK_OBJECT_CONNECTED (object))
+ handlers = gtk_signal_get_handlers (object, signal_id);
+ else
+ return 0;
handler_id = 0;
- while (handlers && handlers->signal_type == signal_id)
+ while (handlers && handlers->signal_id == signal_id)
{
if (handlers->id > 0 &&
- (may_be_blocked ||
- !handlers->blocked))
+ handlers->func == func &&
+ handlers->func_data == data &&
+ (may_be_blocked || handlers->blocked == 0))
{
handler_id = handlers->id;
break;
return handler_id;
}
+gint
+gtk_signal_handler_pending_by_id (GtkObject *object,
+ guint handler_id,
+ gboolean may_be_blocked)
+{
+ GtkHandler *handlers;
+
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (handler_id >= 1, FALSE);
+
+ if (GTK_OBJECT_CONNECTED (object))
+ handlers = gtk_object_get_data_by_id (object, gtk_handler_quark);
+ else
+ return FALSE;
+
+ while (handlers)
+ {
+ if (handlers->id == handler_id)
+ return may_be_blocked || handlers->blocked == 0;
+
+ handlers = handlers->next;
+ }
+
+ return FALSE;
+}
+
+guint
+gtk_signal_add_emission_hook (guint signal_id,
+ GtkEmissionHook hook_func,
+ gpointer data)
+{
+ return gtk_signal_add_emission_hook_full (signal_id, hook_func, data, NULL);
+}
+
+guint
+gtk_signal_add_emission_hook_full (guint signal_id,
+ GtkEmissionHook hook_func,
+ gpointer data,
+ GDestroyNotify destroy)
+{
+ static guint seq_hook_id = 1;
+ GtkSignal *signal;
+ GHook *hook;
+
+ g_return_val_if_fail (signal_id > 0, 0);
+ g_return_val_if_fail (hook_func != NULL, 0);
+
+ signal = LOOKUP_SIGNAL_ID (signal_id);
+ g_return_val_if_fail (signal != NULL, 0);
+ if (signal->signal_flags & GTK_RUN_NO_HOOKS)
+ {
+ g_warning ("gtk_signal_add_emission_hook_full(): signal \"%s\" does not support emission hooks",
+ signal->name);
+ return 0;
+ }
+
+ if (!signal->hook_list)
+ {
+ signal->hook_list = g_new (GHookList, 1);
+ g_hook_list_init (signal->hook_list, sizeof (GHook));
+ }
+
+ hook = g_hook_alloc (signal->hook_list);
+ hook->data = data;
+ hook->func = hook_func;
+ hook->destroy = destroy;
+
+ signal->hook_list->seq_id = seq_hook_id;
+ g_hook_prepend (signal->hook_list, hook);
+ seq_hook_id = signal->hook_list->seq_id;
+
+ return hook->hook_id;
+}
+
+void
+gtk_signal_remove_emission_hook (guint signal_id,
+ guint hook_id)
+{
+ GtkSignal *signal;
+
+ g_return_if_fail (signal_id > 0);
+ g_return_if_fail (hook_id > 0);
+
+ signal = LOOKUP_SIGNAL_ID (signal_id);
+ g_return_if_fail (signal != NULL);
+
+ if (!signal->hook_list || !g_hook_destroy (signal->hook_list, hook_id))
+ g_warning ("gtk_signal_remove_emission_hook(): could not find hook (%u)", hook_id);
+}
+
+static gboolean
+gtk_emission_hook_marshaller (GHook *hook,
+ gpointer data_p)
+{
+ GtkEmissionHookData *data = data_p;
+ GtkEmissionHook func;
+
+ func = hook->func;
+
+ if (!GTK_OBJECT_DESTROYED (data->object))
+ return func (data->object, data->signal_id,
+ data->n_params, data->params,
+ hook->data);
+ else
+ return TRUE;
+}
+
static guint
-gtk_signal_connect_by_type (GtkObject *object,
- guint signal_type,
+gtk_signal_connect_by_type (GtkObject *object,
+ guint signal_id,
GtkSignalFunc func,
- gpointer func_data,
+ gpointer func_data,
GtkSignalDestroy destroy_func,
- gint object_signal,
- gint after,
- gint no_marshal)
+ gint object_signal,
+ gint after,
+ gint no_marshal)
{
GtkObjectClass *class;
GtkHandler *handler;
gint found_it;
-
+ GtkSignal *signal;
+
g_return_val_if_fail (object != NULL, 0);
g_return_val_if_fail (object->klass != NULL, 0);
+ signal = LOOKUP_SIGNAL_ID (signal_id);
+
/* Search through the signals for this object and make
* sure the one we are adding is valid. We need to perform
* the lookup on the objects parents as well. If it isn't
* valid then issue a warning and return.
+ * As of now (1998-05-27) this lookup shouldn't be neccessarry
+ * anymore since gtk_signal_lookup() has been reworked to only
+ * return correct signal ids per class-branch.
*/
found_it = FALSE;
class = object->klass;
nsignals = class->nsignals;
for (i = 0; i < nsignals; i++)
- if (object_signals[i] == signal_type)
+ if (object_signals[i] == signal_id)
{
found_it = TRUE;
break;
if (!found_it)
{
g_warning ("gtk_signal_connect_by_type(): could not find signal id (%u) in the `%s' class ancestry",
- signal_type,
- gtk_type_name (class->type));
+ signal_id,
+ gtk_type_name (object->klass->type));
return 0;
}
handler = gtk_signal_handler_new ();
- handler->id = next_handler_id++;
- handler->signal_type = signal_type;
- handler->object_signal = object_signal;
+ handler->id = gtk_handler_id++;
+ handler->signal_id = signal_id;
+ handler->object_signal = object_signal != FALSE;
handler->func = func;
handler->func_data = func_data;
handler->destroy_func = destroy_func;
}
static GtkEmission*
-gtk_emission_new ()
+gtk_emission_new (void)
{
GtkEmission *emission;
- if (!emission_mem_chunk)
- emission_mem_chunk = g_mem_chunk_new ("emission mem chunk", sizeof (GtkEmission),
- 1024, G_ALLOC_AND_FREE);
-
- emission = g_chunk_new (GtkEmission, emission_mem_chunk);
-
+ if (!gtk_free_emissions)
+ {
+ GtkEmission *emission_block;
+ guint i;
+
+ emission_block = g_new0 (GtkEmission, EMISSION_BLOCK_SIZE);
+ for (i = 1; i < EMISSION_BLOCK_SIZE; i++)
+ {
+ (emission_block + i)->next = gtk_free_emissions;
+ gtk_free_emissions = (emission_block + i);
+ }
+
+ emission = emission_block;
+ }
+ else
+ {
+ emission = gtk_free_emissions;
+ gtk_free_emissions = emission->next;
+ }
+
emission->object = NULL;
- emission->signal_type = 0;
+ emission->signal_id = 0;
+ emission->in_hook = 0;
+ emission->next = NULL;
return emission;
}
static void
-gtk_emission_destroy (GtkEmission *emission)
-{
- g_mem_chunk_free (emission_mem_chunk, emission);
-}
-
-static void
-gtk_emission_add (GList **emissions,
- GtkObject *object,
- guint signal_type)
+gtk_emission_add (GtkEmission **emissions,
+ GtkObject *object,
+ guint signal_id)
{
GtkEmission *emission;
emission = gtk_emission_new ();
emission->object = object;
- emission->signal_type = signal_type;
-
- *emissions = g_list_prepend (*emissions, emission);
+ emission->signal_id = signal_id;
+
+ emission->next = *emissions;
+ *emissions = emission;
}
static void
-gtk_emission_remove (GList **emissions,
- GtkObject *object,
- guint signal_type)
+gtk_emission_remove (GtkEmission **emissions,
+ GtkObject *object,
+ guint signal_id)
{
- GtkEmission *emission;
- GList *tmp;
+ GtkEmission *emission, *last;
g_return_if_fail (emissions != NULL);
-
- tmp = *emissions;
- while (tmp)
+
+ last = NULL;
+ emission = *emissions;
+ while (emission)
{
- emission = tmp->data;
-
- if ((emission->object == object) &&
- (emission->signal_type == signal_type))
+ if (emission->object == object && emission->signal_id == signal_id)
{
- gtk_emission_destroy (emission);
- *emissions = g_list_remove_link (*emissions, tmp);
- g_list_free (tmp);
+ if (last)
+ last->next = emission->next;
+ else
+ *emissions = emission->next;
+
+ emission->next = gtk_free_emissions;
+ gtk_free_emissions = emission;
break;
}
-
- tmp = tmp->next;
+
+ last = emission;
+ emission = last->next;
}
}
static gint
-gtk_emission_check (GList *emissions,
- GtkObject *object,
- guint signal_type)
+gtk_emission_check (GtkEmission *emission,
+ GtkObject *object,
+ guint signal_id)
{
- GtkEmission *emission;
- GList *tmp;
-
- tmp = emissions;
- while (tmp)
+ while (emission)
{
- emission = tmp->data;
- tmp = tmp->next;
-
- if ((emission->object == object) &&
- (emission->signal_type == signal_type))
- return TRUE;
+ if (emission->object == object && emission->signal_id == signal_id)
+ return 1 + emission->in_hook;
+ emission = emission->next;
}
return FALSE;
}
static gint
-gtk_handlers_run (GtkHandler *handlers,
- GtkHandlerInfo *info,
- gint after)
+gtk_handlers_run (GtkHandler *handlers,
+ GtkSignal *signal,
+ GtkObject *object,
+ GtkArg *params,
+ gint after)
{
- while (handlers && handlers->signal_type == info->signal_type)
+ /* *signal is a local copy on the stack of gtk_signal_real_emit(),
+ * so we don't need to look it up every time we invoked a function.
+ */
+ while (handlers && handlers->signal_id == signal->signal_id)
{
GtkHandler *handlers_next;
gtk_signal_handler_ref (handlers);
- if (!handlers->blocked && (handlers->after == after))
+ if (!handlers->blocked && handlers->after == after)
{
if (handlers->func)
{
if (handlers->no_marshal)
- (* (GtkCallbackMarshal)handlers->func) (info->object,
- handlers->func_data,
- info->nparams,
- info->params);
+ (* (GtkCallbackMarshal) handlers->func) (object,
+ handlers->func_data,
+ signal->nparams,
+ params);
else if (handlers->object_signal)
- (* info->marshaller) ((GtkObject*) handlers->func_data, /* don't GTK_OBJECT() cast */
- handlers->func,
- handlers->func_data,
- info->params);
+ /* don't cast with GTK_OBJECT () */
+ (* signal->marshaller) ((GtkObject*) handlers->func_data,
+ handlers->func,
+ object,
+ params);
else
- (* info->marshaller) (info->object,
- handlers->func,
- handlers->func_data,
- info->params);
+ (* signal->marshaller) (object,
+ handlers->func,
+ handlers->func_data,
+ params);
}
- else if (marshal)
- (* marshal) (info->object,
- handlers->func_data,
- info->nparams,
- info->params,
- info->param_types,
- info->return_val);
+ else if (global_marshaller)
+ (* global_marshaller) (object,
+ handlers->func_data,
+ signal->nparams,
+ params,
+ signal->params,
+ signal->return_val);
- if (gtk_emission_check (stop_emissions, info->object,
- info->signal_type))
+ if (stop_emissions && gtk_emission_check (stop_emissions,
+ object,
+ signal->signal_id))
{
- gtk_emission_remove (&stop_emissions, info->object,
- info->signal_type);
+ gtk_emission_remove (&stop_emissions, object, signal->signal_id);
- if (info->run_type & GTK_RUN_NO_RECURSE)
- gtk_emission_remove (&restart_emissions, info->object,
- info->signal_type);
- gtk_signal_handler_unref (handlers, info->object);
- return DONE;
+ gtk_signal_handler_unref (handlers, object);
+
+ return EMISSION_DONE;
}
- else if ((info->run_type & GTK_RUN_NO_RECURSE) &&
- gtk_emission_check (restart_emissions, info->object,
- info->signal_type))
+ else if (restart_emissions &&
+ signal->signal_flags & GTK_RUN_NO_RECURSE &&
+ gtk_emission_check (restart_emissions, object, signal->signal_id))
{
- gtk_emission_remove (&restart_emissions, info->object,
- info->signal_type);
- gtk_signal_handler_unref (handlers, info->object);
- return RESTART;
+ gtk_emission_remove (&restart_emissions, object, signal->signal_id);
+
+ gtk_signal_handler_unref (handlers, object);
+
+ return EMISSION_RESTART;
}
}
handlers_next = handlers->next;
- gtk_signal_handler_unref (handlers, info->object);
+ gtk_signal_handler_unref (handlers, object);
handlers = handlers_next;
}
- return 0;
+ 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->name = NULL;
+ params->type = *(param_types++);
+ GTK_ARG_COLLECT_VALUE (params,
+ var_args,
+ error);
+ 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 ("unsupported type `%s' in signal return",
- gtk_type_name (return_val));
- break;
+ if ((return_type >= GTK_TYPE_FLAT_FIRST &&
+ return_type <= GTK_TYPE_FLAT_LAST) ||
+ (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;
}