1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtksignal.h"
21 #include "gtkargcollector.c"
22 #include "gtkmarshal.c"
25 /* the real parameter limit is of course given by GSignal, bu we need
26 * an upper limit for the implementations. so this should be adjusted
27 * with any future changes on the GSignal side of things.
29 #define SIGNAL_MAX_PARAMS 12
32 /* --- functions --- */
34 gtk_signal_newv (const gchar *name,
35 GtkSignalRunType signal_flags,
37 guint function_offset,
38 GtkSignalMarshaller marshaller,
45 g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0);
47 closure = g_signal_type_cclosure_new (object_type, function_offset);
49 return g_signal_newv (name, object_type, signal_flags, closure, NULL, marshaller, return_val, n_params, params);
53 gtk_signal_new (const gchar *name,
54 GtkSignalRunType signal_flags,
56 guint function_offset,
57 GtkSignalMarshaller marshaller,
70 params = g_new (GtkType, n_params);
71 va_start (args, n_params);
72 for (i = 0; i < n_params; i++)
73 params[i] = va_arg (args, GtkType);
78 signal_id = gtk_signal_newv (name,
92 gtk_signal_emit_stop_by_name (GtkObject *object,
95 g_return_if_fail (GTK_IS_OBJECT (object));
97 g_signal_stop_emission (object, g_signal_lookup (name, G_OBJECT_TYPE (object)), 0);
101 gtk_signal_connect_object_while_alive (GtkObject *object,
104 GtkObject *alive_object)
106 g_return_if_fail (GTK_IS_OBJECT (object));
108 g_signal_connect_closure_by_id (object,
109 g_signal_lookup (signal, G_OBJECT_TYPE (object)), 0,
110 g_cclosure_new_object_swap (func, alive_object),
115 gtk_signal_connect_while_alive (GtkObject *object,
119 GtkObject *alive_object)
123 g_return_if_fail (GTK_IS_OBJECT (object));
125 closure = g_cclosure_new (func, func_data, NULL);
126 g_object_watch_closure (G_OBJECT (alive_object), closure);
127 g_signal_connect_closure_by_id (object,
128 g_signal_lookup (signal, G_OBJECT_TYPE (object)), 0,
134 gtk_signal_connect_full (GtkObject *object,
137 GtkCallbackMarshal unsupported,
139 GtkDestroyNotify destroy_func,
143 g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
144 g_return_val_if_fail (unsupported == NULL, 0);
146 return g_signal_connect_closure_by_id (object,
147 g_signal_lookup (name, G_OBJECT_TYPE (object)), 0,
149 ? g_cclosure_new_swap
150 : g_cclosure_new) (func,
152 (GClosureNotify) destroy_func),
157 gtk_signal_compat_matched (GtkObject *object,
160 GSignalMatchType match,
165 g_return_if_fail (GTK_IS_OBJECT (object));
169 case 0: n_handlers = g_signal_handlers_disconnect_matched (object, match, 0, 0, NULL, func, data); break;
170 case 1: n_handlers = g_signal_handlers_block_matched (object, match, 0, 0, NULL, func, data); break;
171 case 2: n_handlers = g_signal_handlers_unblock_matched (object, match, 0, 0, NULL, func, data); break;
172 default: n_handlers = 0; break;
176 g_warning ("unable to find signal handler for object(%s:%p) with func(%p) and data(%p)",
177 G_OBJECT_TYPE_NAME (object), object, func, data);
180 static inline gboolean
181 gtk_arg_to_value (GtkArg *arg,
184 switch (G_TYPE_FUNDAMENTAL (arg->type))
186 case G_TYPE_CHAR: g_value_set_char (value, GTK_VALUE_CHAR (*arg)); break;
187 case G_TYPE_UCHAR: g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg)); break;
188 case G_TYPE_BOOLEAN: g_value_set_boolean (value, GTK_VALUE_BOOL (*arg)); break;
189 case G_TYPE_INT: g_value_set_int (value, GTK_VALUE_INT (*arg)); break;
190 case G_TYPE_UINT: g_value_set_uint (value, GTK_VALUE_UINT (*arg)); break;
191 case G_TYPE_LONG: g_value_set_long (value, GTK_VALUE_LONG (*arg)); break;
192 case G_TYPE_ULONG: g_value_set_ulong (value, GTK_VALUE_ULONG (*arg)); break;
193 case G_TYPE_ENUM: g_value_set_enum (value, GTK_VALUE_ENUM (*arg)); break;
194 case G_TYPE_FLAGS: g_value_set_flags (value, GTK_VALUE_FLAGS (*arg)); break;
195 case G_TYPE_FLOAT: g_value_set_float (value, GTK_VALUE_FLOAT (*arg)); break;
196 case G_TYPE_DOUBLE: g_value_set_double (value, GTK_VALUE_DOUBLE (*arg)); break;
197 case G_TYPE_STRING: g_value_set_string (value, GTK_VALUE_STRING (*arg)); break;
198 case G_TYPE_BOXED: g_value_set_boxed (value, GTK_VALUE_BOXED (*arg)); break;
199 case G_TYPE_POINTER: g_value_set_pointer (value, GTK_VALUE_POINTER (*arg)); break;
200 case G_TYPE_OBJECT: g_value_set_object (value, GTK_VALUE_POINTER (*arg)); break;
207 static inline gboolean
208 gtk_arg_static_to_value (GtkArg *arg,
211 switch (G_TYPE_FUNDAMENTAL (arg->type))
213 case G_TYPE_CHAR: g_value_set_char (value, GTK_VALUE_CHAR (*arg)); break;
214 case G_TYPE_UCHAR: g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg)); break;
215 case G_TYPE_BOOLEAN: g_value_set_boolean (value, GTK_VALUE_BOOL (*arg)); break;
216 case G_TYPE_INT: g_value_set_int (value, GTK_VALUE_INT (*arg)); break;
217 case G_TYPE_UINT: g_value_set_uint (value, GTK_VALUE_UINT (*arg)); break;
218 case G_TYPE_LONG: g_value_set_long (value, GTK_VALUE_LONG (*arg)); break;
219 case G_TYPE_ULONG: g_value_set_ulong (value, GTK_VALUE_ULONG (*arg)); break;
220 case G_TYPE_ENUM: g_value_set_enum (value, GTK_VALUE_ENUM (*arg)); break;
221 case G_TYPE_FLAGS: g_value_set_flags (value, GTK_VALUE_FLAGS (*arg)); break;
222 case G_TYPE_FLOAT: g_value_set_float (value, GTK_VALUE_FLOAT (*arg)); break;
223 case G_TYPE_DOUBLE: g_value_set_double (value, GTK_VALUE_DOUBLE (*arg)); break;
224 case G_TYPE_STRING: g_value_set_static_string (value, GTK_VALUE_STRING (*arg)); break;
225 case G_TYPE_BOXED: g_value_set_static_boxed (value, GTK_VALUE_BOXED (*arg)); break;
226 case G_TYPE_POINTER: g_value_set_pointer (value, GTK_VALUE_POINTER (*arg)); break;
227 case G_TYPE_OBJECT: g_value_set_object (value, GTK_VALUE_POINTER (*arg)); break;
234 static inline gboolean
235 gtk_arg_set_from_value (GtkArg *arg,
237 gboolean copy_string)
239 switch (G_TYPE_FUNDAMENTAL (arg->type))
241 case G_TYPE_CHAR: GTK_VALUE_CHAR (*arg) = g_value_get_char (value); break;
242 case G_TYPE_UCHAR: GTK_VALUE_UCHAR (*arg) = g_value_get_uchar (value); break;
243 case G_TYPE_BOOLEAN: GTK_VALUE_BOOL (*arg) = g_value_get_boolean (value); break;
244 case G_TYPE_INT: GTK_VALUE_INT (*arg) = g_value_get_int (value); break;
245 case G_TYPE_UINT: GTK_VALUE_UINT (*arg) = g_value_get_uint (value); break;
246 case G_TYPE_LONG: GTK_VALUE_LONG (*arg) = g_value_get_long (value); break;
247 case G_TYPE_ULONG: GTK_VALUE_ULONG (*arg) = g_value_get_ulong (value); break;
248 case G_TYPE_ENUM: GTK_VALUE_ENUM (*arg) = g_value_get_enum (value); break;
249 case G_TYPE_FLAGS: GTK_VALUE_FLAGS (*arg) = g_value_get_flags (value); break;
250 case G_TYPE_FLOAT: GTK_VALUE_FLOAT (*arg) = g_value_get_float (value); break;
251 case G_TYPE_DOUBLE: GTK_VALUE_DOUBLE (*arg) = g_value_get_double (value); break;
252 case G_TYPE_BOXED: GTK_VALUE_BOXED (*arg) = g_value_get_boxed (value); break;
253 case G_TYPE_POINTER: GTK_VALUE_POINTER (*arg) = g_value_get_pointer (value); break;
254 case G_TYPE_OBJECT: GTK_VALUE_POINTER (*arg) = g_value_get_object (value); break;
255 case G_TYPE_STRING: if (copy_string)
256 GTK_VALUE_STRING (*arg) = g_value_dup_string (value);
258 GTK_VALUE_STRING (*arg) = g_value_get_string (value);
266 static inline gboolean
267 gtk_argloc_set_from_value (GtkArg *arg,
269 gboolean copy_string)
271 switch (G_TYPE_FUNDAMENTAL (arg->type))
273 case G_TYPE_CHAR: *GTK_RETLOC_CHAR (*arg) = g_value_get_char (value); break;
274 case G_TYPE_UCHAR: *GTK_RETLOC_UCHAR (*arg) = g_value_get_uchar (value); break;
275 case G_TYPE_BOOLEAN: *GTK_RETLOC_BOOL (*arg) = g_value_get_boolean (value); break;
276 case G_TYPE_INT: *GTK_RETLOC_INT (*arg) = g_value_get_int (value); break;
277 case G_TYPE_UINT: *GTK_RETLOC_UINT (*arg) = g_value_get_uint (value); break;
278 case G_TYPE_LONG: *GTK_RETLOC_LONG (*arg) = g_value_get_long (value); break;
279 case G_TYPE_ULONG: *GTK_RETLOC_ULONG (*arg) = g_value_get_ulong (value); break;
280 case G_TYPE_ENUM: *GTK_RETLOC_ENUM (*arg) = g_value_get_enum (value); break;
281 case G_TYPE_FLAGS: *GTK_RETLOC_FLAGS (*arg) = g_value_get_flags (value); break;
282 case G_TYPE_FLOAT: *GTK_RETLOC_FLOAT (*arg) = g_value_get_float (value); break;
283 case G_TYPE_DOUBLE: *GTK_RETLOC_DOUBLE (*arg) = g_value_get_double (value); break;
284 case G_TYPE_BOXED: *GTK_RETLOC_BOXED (*arg) = g_value_get_boxed (value); break;
285 case G_TYPE_POINTER: *GTK_RETLOC_POINTER (*arg) = g_value_get_pointer (value); break;
286 case G_TYPE_OBJECT: *GTK_RETLOC_POINTER (*arg) = g_value_get_object (value); break;
287 case G_TYPE_STRING: if (copy_string)
288 *GTK_RETLOC_STRING (*arg) = g_value_dup_string (value);
290 *GTK_RETLOC_STRING (*arg) = g_value_get_string (value);
299 gtk_signal_emitv (GtkObject *object,
304 GValue params[SIGNAL_MAX_PARAMS + 1] = { { 0, }, };
305 GValue rvalue = { 0, };
308 g_return_if_fail (GTK_IS_OBJECT (object));
310 g_signal_query (signal_id, &query);
311 g_return_if_fail (query.signal_id != 0);
312 g_return_if_fail (g_type_is_a (GTK_OBJECT_TYPE (object), query.itype));
313 g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS);
314 if (query.n_params > 0)
315 g_return_if_fail (args != NULL);
317 g_value_init (params + 0, GTK_OBJECT_TYPE (object));
318 g_value_set_object (params + 0, G_OBJECT (object));
319 for (i = 0; i < query.n_params; i++)
321 GValue *value = params + 1 + i;
322 GtkArg *arg = args + i;
324 g_value_init (value, arg->type);
325 if (!gtk_arg_static_to_value (arg, value))
327 g_warning ("%s: failed to convert arg type `%s' to value type `%s'",
328 G_STRLOC, g_type_name (arg->type), g_type_name (G_VALUE_TYPE (value)));
332 if (query.return_type != G_TYPE_NONE)
333 g_value_init (&rvalue, query.return_type);
335 g_signal_emitv (params, signal_id, 0, &rvalue);
337 if (query.return_type != G_TYPE_NONE)
339 gtk_argloc_set_from_value (args + query.n_params, &rvalue, TRUE);
340 g_value_unset (&rvalue);
342 for (i = 0; i < query.n_params; i++)
343 g_value_unset (params + 1 + i);
344 g_value_unset (params + 0);
348 gtk_signal_collect_args (GtkArg *args,
350 const GtkType *arg_types,
354 register GtkArg *last_arg;
355 register gboolean failed = FALSE;
357 for (last_arg = args + n_args; args < last_arg; args++)
359 register gchar *error;
362 args->type = *(arg_types++);
363 GTK_ARG_COLLECT_VALUE (args,
369 g_warning ("gtk_signal_collect_args(): %s", error);
374 args->type = return_type;
377 return_type = GTK_FUNDAMENTAL_TYPE (return_type);
378 if (return_type != G_TYPE_NONE)
380 if (return_type != 0) /* FIXME: check for IS_ARG */
382 GTK_VALUE_POINTER (*args) = va_arg (var_args, gpointer);
384 if (GTK_VALUE_POINTER (*args) == NULL)
387 g_warning ("gtk_signal_collect_args(): invalid NULL pointer for return argument type `%s'",
388 gtk_type_name (args->type));
394 g_warning ("gtk_signal_collect_args(): unsupported return argument type `%s'",
395 gtk_type_name (args->type));
399 GTK_VALUE_POINTER (*args) = NULL;
406 gtk_signal_emit (GtkObject *object,
410 GtkArg args[SIGNAL_MAX_PARAMS + 1];
415 g_return_if_fail (GTK_IS_OBJECT (object));
417 g_signal_query (signal_id, &query);
418 g_return_if_fail (query.signal_id != 0);
419 g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS);
421 va_start (var_args, signal_id);
422 abort = gtk_signal_collect_args (args,
430 gtk_signal_emitv (object, signal_id, args);
435 gtk_signal_emit (GtkObject *object,
441 g_return_if_fail (GTK_IS_OBJECT (object));
443 va_start (var_args, signal_id);
444 g_signal_emit_valist (G_OBJECT (object), signal_id, 0, var_args);
449 gtk_signal_emit_by_name (GtkObject *object,
453 GtkArg args[SIGNAL_MAX_PARAMS + 1];
458 g_return_if_fail (GTK_IS_OBJECT (object));
459 g_return_if_fail (name != NULL);
461 g_signal_query (g_signal_lookup (name, GTK_OBJECT_TYPE (object)), &query);
462 g_return_if_fail (query.signal_id != 0);
463 g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS);
465 va_start (var_args, name);
466 abort = gtk_signal_collect_args (args,
474 gtk_signal_emitv (object, query.signal_id, args);
478 gtk_signal_emitv_by_name (GtkObject *object,
482 g_return_if_fail (GTK_IS_OBJECT (object));
484 gtk_signal_emitv (object, g_signal_lookup (name, GTK_OBJECT_TYPE (object)), args);