1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
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.
8 *
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.
13 *
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.
18 */
19
20 #undef GTK_DISABLE_DEPRECATED
21
22 #include <config.h>
23 #include "gtksignal.h"
24 #include "gtkalias.h"
25
26 /* the real parameter limit is of course given by GSignal, bu we need
27 * an upper limit for the implementations. so this should be adjusted
28 * with any future changes on the GSignal side of things.
29 */
30 #define SIGNAL_MAX_PARAMS 12
31
32
33 /* --- functions --- */
34 guint
gtk_signal_newv(const gchar * name,GtkSignalRunType signal_flags,GType object_type,guint function_offset,GSignalCMarshaller marshaller,GType return_val,guint n_params,GType * params)35 gtk_signal_newv (const gchar *name,
36 GtkSignalRunType signal_flags,
37 GType object_type,
38 guint function_offset,
39 GSignalCMarshaller marshaller,
40 GType return_val,
41 guint n_params,
42 GType *params)
43 {
44 GClosure *closure;
45
46 g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0);
47
48 closure = function_offset ? g_signal_type_cclosure_new (object_type, function_offset) : NULL;
49
50 return g_signal_newv (name, object_type, (GSignalFlags)signal_flags, closure,
51 NULL, NULL, marshaller, return_val, n_params, params);
52 }
53
54 guint
gtk_signal_new(const gchar * name,GtkSignalRunType signal_flags,GType object_type,guint function_offset,GSignalCMarshaller marshaller,GType return_val,guint n_params,...)55 gtk_signal_new (const gchar *name,
56 GtkSignalRunType signal_flags,
57 GType object_type,
58 guint function_offset,
59 GSignalCMarshaller marshaller,
60 GType return_val,
61 guint n_params,
62 ...)
63 {
64 GType *params;
65 guint signal_id;
66
67 if (n_params)
68 {
69 va_list args;
70 guint i;
71
72 params = g_new (GType, n_params);
73 va_start (args, n_params);
74 for (i = 0; i < n_params; i++)
75 params[i] = va_arg (args, GType);
76 va_end (args);
77 }
78 else
79 params = NULL;
80 signal_id = gtk_signal_newv (name,
81 signal_flags,
82 object_type,
83 function_offset,
84 marshaller,
85 return_val,
86 n_params,
87 params);
88 g_free (params);
89
90 return signal_id;
91 }
92
93 void
gtk_signal_emit_stop_by_name(GtkObject * object,const gchar * name)94 gtk_signal_emit_stop_by_name (GtkObject *object,
95 const gchar *name)
96 {
97 g_return_if_fail (GTK_IS_OBJECT (object));
98
99 g_signal_stop_emission (object, g_signal_lookup (name, G_OBJECT_TYPE (object)), 0);
100 }
101
102 void
gtk_signal_connect_object_while_alive(GtkObject * object,const gchar * name,GCallback func,GtkObject * alive_object)103 gtk_signal_connect_object_while_alive (GtkObject *object,
104 const gchar *name,
105 GCallback func,
106 GtkObject *alive_object)
107 {
108 g_return_if_fail (GTK_IS_OBJECT (object));
109
110 g_signal_connect_closure_by_id (object,
111 g_signal_lookup (name, G_OBJECT_TYPE (object)), 0,
112 g_cclosure_new_object_swap (func, G_OBJECT (alive_object)),
113 FALSE);
114 }
115
116 void
gtk_signal_connect_while_alive(GtkObject * object,const gchar * name,GCallback func,gpointer func_data,GtkObject * alive_object)117 gtk_signal_connect_while_alive (GtkObject *object,
118 const gchar *name,
119 GCallback func,
120 gpointer func_data,
121 GtkObject *alive_object)
122 {
123 GClosure *closure;
124
125 g_return_if_fail (GTK_IS_OBJECT (object));
126
127 closure = g_cclosure_new (func, func_data, NULL);
128 g_object_watch_closure (G_OBJECT (alive_object), closure);
129 g_signal_connect_closure_by_id (object,
130 g_signal_lookup (name, G_OBJECT_TYPE (object)), 0,
131 closure,
132 FALSE);
133 }
134
135 gulong
gtk_signal_connect_full(GtkObject * object,const gchar * name,GCallback func,GtkCallbackMarshal unsupported,gpointer data,GDestroyNotify destroy_func,gint object_signal,gint after)136 gtk_signal_connect_full (GtkObject *object,
137 const gchar *name,
138 GCallback func,
139 GtkCallbackMarshal unsupported,
140 gpointer data,
141 GDestroyNotify destroy_func,
142 gint object_signal,
143 gint after)
144 {
145 g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
146 g_return_val_if_fail (unsupported == NULL, 0);
147
148 return g_signal_connect_closure_by_id (object,
149 g_signal_lookup (name, G_OBJECT_TYPE (object)), 0,
150 (object_signal
151 ? g_cclosure_new_swap
152 : g_cclosure_new) (func,
153 data,
154 (GClosureNotify) destroy_func),
155 after);
156 }
157
158 void
gtk_signal_compat_matched(GtkObject * object,GCallback func,gpointer data,GSignalMatchType match,guint action)159 gtk_signal_compat_matched (GtkObject *object,
160 GCallback func,
161 gpointer data,
162 GSignalMatchType match,
163 guint action)
164 {
165 guint n_handlers;
166
167 g_return_if_fail (GTK_IS_OBJECT (object));
168
169 switch (action)
170 {
171 case 0: n_handlers = g_signal_handlers_disconnect_matched (object, match, 0, 0, NULL, (gpointer) func, data); break;
172 case 1: n_handlers = g_signal_handlers_block_matched (object, match, 0, 0, NULL, (gpointer) func, data); break;
173 case 2: n_handlers = g_signal_handlers_unblock_matched (object, match, 0, 0, NULL, (gpointer) func, data); break;
174 default: n_handlers = 0; break;
175 }
176
177 if (!n_handlers)
178 g_warning ("unable to find signal handler for object(%s:%p) with func(%p) and data(%p)",
179 G_OBJECT_TYPE_NAME (object), object, func, data);
180 }
181
182 static inline gboolean
gtk_arg_to_value(GtkArg * arg,GValue * value)183 gtk_arg_to_value (GtkArg *arg,
184 GValue *value)
185 {
186 switch (G_TYPE_FUNDAMENTAL (arg->type))
187 {
188 case G_TYPE_CHAR: g_value_set_char (value, GTK_VALUE_CHAR (*arg)); break;
189 case G_TYPE_UCHAR: g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg)); break;
190 case G_TYPE_BOOLEAN: g_value_set_boolean (value, GTK_VALUE_BOOL (*arg)); break;
191 case G_TYPE_INT: g_value_set_int (value, GTK_VALUE_INT (*arg)); break;
192 case G_TYPE_UINT: g_value_set_uint (value, GTK_VALUE_UINT (*arg)); break;
193 case G_TYPE_LONG: g_value_set_long (value, GTK_VALUE_LONG (*arg)); break;
194 case G_TYPE_ULONG: g_value_set_ulong (value, GTK_VALUE_ULONG (*arg)); break;
195 case G_TYPE_ENUM: g_value_set_enum (value, GTK_VALUE_ENUM (*arg)); break;
196 case G_TYPE_FLAGS: g_value_set_flags (value, GTK_VALUE_FLAGS (*arg)); break;
197 case G_TYPE_FLOAT: g_value_set_float (value, GTK_VALUE_FLOAT (*arg)); break;
198 case G_TYPE_DOUBLE: g_value_set_double (value, GTK_VALUE_DOUBLE (*arg)); break;
199 case G_TYPE_STRING: g_value_set_string (value, GTK_VALUE_STRING (*arg)); break;
200 case G_TYPE_BOXED: g_value_set_boxed (value, GTK_VALUE_BOXED (*arg)); break;
201 case G_TYPE_POINTER: g_value_set_pointer (value, GTK_VALUE_POINTER (*arg)); break;
202 case G_TYPE_OBJECT: g_value_set_object (value, GTK_VALUE_POINTER (*arg)); break;
203 default:
204 return FALSE;
205 }
206 return TRUE;
207 }
208
209 static inline gboolean
gtk_arg_static_to_value(GtkArg * arg,GValue * value)210 gtk_arg_static_to_value (GtkArg *arg,
211 GValue *value)
212 {
213 switch (G_TYPE_FUNDAMENTAL (arg->type))
214 {
215 case G_TYPE_CHAR: g_value_set_char (value, GTK_VALUE_CHAR (*arg)); break;
216 case G_TYPE_UCHAR: g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg)); break;
217 case G_TYPE_BOOLEAN: g_value_set_boolean (value, GTK_VALUE_BOOL (*arg)); break;
218 case G_TYPE_INT: g_value_set_int (value, GTK_VALUE_INT (*arg)); break;
219 case G_TYPE_UINT: g_value_set_uint (value, GTK_VALUE_UINT (*arg)); break;
220 case G_TYPE_LONG: g_value_set_long (value, GTK_VALUE_LONG (*arg)); break;
221 case G_TYPE_ULONG: g_value_set_ulong (value, GTK_VALUE_ULONG (*arg)); break;
222 case G_TYPE_ENUM: g_value_set_enum (value, GTK_VALUE_ENUM (*arg)); break;
223 case G_TYPE_FLAGS: g_value_set_flags (value, GTK_VALUE_FLAGS (*arg)); break;
224 case G_TYPE_FLOAT: g_value_set_float (value, GTK_VALUE_FLOAT (*arg)); break;
225 case G_TYPE_DOUBLE: g_value_set_double (value, GTK_VALUE_DOUBLE (*arg)); break;
226 case G_TYPE_STRING: g_value_set_static_string (value, GTK_VALUE_STRING (*arg)); break;
227 case G_TYPE_BOXED: g_value_set_static_boxed (value, GTK_VALUE_BOXED (*arg)); break;
228 case G_TYPE_POINTER: g_value_set_pointer (value, GTK_VALUE_POINTER (*arg)); break;
229 case G_TYPE_OBJECT: g_value_set_object (value, GTK_VALUE_POINTER (*arg)); break;
230 default:
231 return FALSE;
232 }
233 return TRUE;
234 }
235
236 static inline gboolean
gtk_arg_set_from_value(GtkArg * arg,GValue * value,gboolean copy_string)237 gtk_arg_set_from_value (GtkArg *arg,
238 GValue *value,
239 gboolean copy_string)
240 {
241 switch (G_TYPE_FUNDAMENTAL (arg->type))
242 {
243 case G_TYPE_CHAR: GTK_VALUE_CHAR (*arg) = g_value_get_char (value); break;
244 case G_TYPE_UCHAR: GTK_VALUE_UCHAR (*arg) = g_value_get_uchar (value); break;
245 case G_TYPE_BOOLEAN: GTK_VALUE_BOOL (*arg) = g_value_get_boolean (value); break;
246 case G_TYPE_INT: GTK_VALUE_INT (*arg) = g_value_get_int (value); break;
247 case G_TYPE_UINT: GTK_VALUE_UINT (*arg) = g_value_get_uint (value); break;
248 case G_TYPE_LONG: GTK_VALUE_LONG (*arg) = g_value_get_long (value); break;
249 case G_TYPE_ULONG: GTK_VALUE_ULONG (*arg) = g_value_get_ulong (value); break;
250 case G_TYPE_ENUM: GTK_VALUE_ENUM (*arg) = g_value_get_enum (value); break;
251 case G_TYPE_FLAGS: GTK_VALUE_FLAGS (*arg) = g_value_get_flags (value); break;
252 case G_TYPE_FLOAT: GTK_VALUE_FLOAT (*arg) = g_value_get_float (value); break;
253 case G_TYPE_DOUBLE: GTK_VALUE_DOUBLE (*arg) = g_value_get_double (value); break;
254 case G_TYPE_BOXED: GTK_VALUE_BOXED (*arg) = g_value_get_boxed (value); break;
255 case G_TYPE_POINTER: GTK_VALUE_POINTER (*arg) = g_value_get_pointer (value); break;
256 case G_TYPE_OBJECT: GTK_VALUE_POINTER (*arg) = g_value_get_object (value); break;
257 case G_TYPE_STRING: if (copy_string)
258 GTK_VALUE_STRING (*arg) = g_value_dup_string (value);
259 else
260 GTK_VALUE_STRING (*arg) = (char *) g_value_get_string (value);
261 break;
262 default:
263 return FALSE;
264 }
265 return TRUE;
266 }
267
268 static inline gboolean
gtk_argloc_set_from_value(GtkArg * arg,GValue * value,gboolean copy_string)269 gtk_argloc_set_from_value (GtkArg *arg,
270 GValue *value,
271 gboolean copy_string)
272 {
273 switch (G_TYPE_FUNDAMENTAL (arg->type))
274 {
275 case G_TYPE_CHAR: *GTK_RETLOC_CHAR (*arg) = g_value_get_char (value); break;
276 case G_TYPE_UCHAR: *GTK_RETLOC_UCHAR (*arg) = g_value_get_uchar (value); break;
277 case G_TYPE_BOOLEAN: *GTK_RETLOC_BOOL (*arg) = g_value_get_boolean (value); break;
278 case G_TYPE_INT: *GTK_RETLOC_INT (*arg) = g_value_get_int (value); break;
279 case G_TYPE_UINT: *GTK_RETLOC_UINT (*arg) = g_value_get_uint (value); break;
280 case G_TYPE_LONG: *GTK_RETLOC_LONG (*arg) = g_value_get_long (value); break;
281 case G_TYPE_ULONG: *GTK_RETLOC_ULONG (*arg) = g_value_get_ulong (value); break;
282 case G_TYPE_ENUM: *GTK_RETLOC_ENUM (*arg) = g_value_get_enum (value); break;
283 case G_TYPE_FLAGS: *GTK_RETLOC_FLAGS (*arg) = g_value_get_flags (value); break;
284 case G_TYPE_FLOAT: *GTK_RETLOC_FLOAT (*arg) = g_value_get_float (value); break;
285 case G_TYPE_DOUBLE: *GTK_RETLOC_DOUBLE (*arg) = g_value_get_double (value); break;
286 case G_TYPE_BOXED: *GTK_RETLOC_BOXED (*arg) = g_value_get_boxed (value); break;
287 case G_TYPE_POINTER: *GTK_RETLOC_POINTER (*arg) = g_value_get_pointer (value); break;
288 case G_TYPE_OBJECT: *GTK_RETLOC_POINTER (*arg) = g_value_get_object (value); break;
289 case G_TYPE_STRING: if (copy_string)
290 *GTK_RETLOC_STRING (*arg) = g_value_dup_string (value);
291 else
292 *GTK_RETLOC_STRING (*arg) = (char *) g_value_get_string (value);
293 break;
294 default:
295 return FALSE;
296 }
297 return TRUE;
298 }
299
300 void
gtk_signal_emitv(GtkObject * object,guint signal_id,GtkArg * args)301 gtk_signal_emitv (GtkObject *object,
302 guint signal_id,
303 GtkArg *args)
304 {
305 GSignalQuery query;
306 GValue params[SIGNAL_MAX_PARAMS + 1] = { { 0, }, };
307 GValue rvalue = { 0, };
308 guint i;
309
310 g_return_if_fail (GTK_IS_OBJECT (object));
311
312 g_signal_query (signal_id, &query);
313 g_return_if_fail (query.signal_id != 0);
314 g_return_if_fail (g_type_is_a (GTK_OBJECT_TYPE (object), query.itype));
315 g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS);
316 if (query.n_params > 0)
317 g_return_if_fail (args != NULL);
318
319 g_value_init (params + 0, GTK_OBJECT_TYPE (object));
320 g_value_set_object (params + 0, G_OBJECT (object));
321 for (i = 0; i < query.n_params; i++)
322 {
323 GValue *value = params + 1 + i;
324 GtkArg *arg = args + i;
325
326 g_value_init (value, arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
327 if (!gtk_arg_static_to_value (arg, value))
328 {
329 g_warning ("%s: failed to convert arg type `%s' to value type `%s'",
330 G_STRLOC, g_type_name (arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE),
331 g_type_name (G_VALUE_TYPE (value)));
332 return;
333 }
334 }
335 if (query.return_type != G_TYPE_NONE)
336 g_value_init (&rvalue, query.return_type);
337
338 g_signal_emitv (params, signal_id, 0, &rvalue);
339
340 if (query.return_type != G_TYPE_NONE)
341 {
342 gtk_argloc_set_from_value (args + query.n_params, &rvalue, TRUE);
343 g_value_unset (&rvalue);
344 }
345 for (i = 0; i < query.n_params; i++)
346 g_value_unset (params + 1 + i);
347 g_value_unset (params + 0);
348 }
349
350 void
gtk_signal_emit(GtkObject * object,guint signal_id,...)351 gtk_signal_emit (GtkObject *object,
352 guint signal_id,
353 ...)
354 {
355 va_list var_args;
356
357 g_return_if_fail (GTK_IS_OBJECT (object));
358
359 va_start (var_args, signal_id);
360 g_signal_emit_valist (G_OBJECT (object), signal_id, 0, var_args);
361 va_end (var_args);
362 }
363
364 void
gtk_signal_emit_by_name(GtkObject * object,const gchar * name,...)365 gtk_signal_emit_by_name (GtkObject *object,
366 const gchar *name,
367 ...)
368 {
369 GSignalQuery query;
370 va_list var_args;
371
372 g_return_if_fail (GTK_IS_OBJECT (object));
373 g_return_if_fail (name != NULL);
374
375 g_signal_query (g_signal_lookup (name, GTK_OBJECT_TYPE (object)), &query);
376 g_return_if_fail (query.signal_id != 0);
377
378 va_start (var_args, name);
379 g_signal_emit_valist (G_OBJECT (object), query.signal_id, 0, var_args);
380 va_end (var_args);
381 }
382
383 void
gtk_signal_emitv_by_name(GtkObject * object,const gchar * name,GtkArg * args)384 gtk_signal_emitv_by_name (GtkObject *object,
385 const gchar *name,
386 GtkArg *args)
387 {
388 g_return_if_fail (GTK_IS_OBJECT (object));
389
390 gtk_signal_emitv (object, g_signal_lookup (name, GTK_OBJECT_TYPE (object)), args);
391 }
392
393 #define __GTK_SIGNAL_C__
394 #include "gtkaliasdef.c"
395