]> Pileus Git - ~andy/gtk/blob - gtk/gtksignal.c
get rid of object_signal:: GtkObject argument uses, use GObject
[~andy/gtk] / gtk / gtksignal.c
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 #include        "gtksignal.h"
21 #include        "gtkargcollector.c"
22 #include        "gtkmarshal.c"
23
24
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.
28  */
29 #define SIGNAL_MAX_PARAMS       12
30
31
32 /* --- functions --- */
33 guint
34 gtk_signal_newv (const gchar         *name,
35                  GtkSignalRunType     signal_flags,
36                  GtkType              object_type,
37                  guint                function_offset,
38                  GtkSignalMarshaller  marshaller,
39                  GtkType              return_val,
40                  guint                n_params,
41                  GtkType             *params)
42 {
43   GClosure *closure;
44   
45   g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0);
46   
47   closure = g_signal_type_cclosure_new (object_type, function_offset);
48   
49   return g_signal_newv (name, object_type, signal_flags, closure, NULL, marshaller, return_val, n_params, params);
50 }
51
52 guint
53 gtk_signal_new (const gchar         *name,
54                 GtkSignalRunType     signal_flags,
55                 GtkType              object_type,
56                 guint                function_offset,
57                 GtkSignalMarshaller  marshaller,
58                 GtkType              return_val,
59                 guint                n_params,
60                 ...)
61 {
62   GtkType *params;
63   guint signal_id;
64   
65   if (n_params)
66     {
67       va_list args;
68       guint i;
69       
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);
74       va_end (args);
75     }
76   else
77     params = NULL;
78   signal_id = gtk_signal_newv (name,
79                                signal_flags,
80                                object_type,
81                                function_offset,
82                                marshaller,
83                                return_val,
84                                n_params,
85                                params);
86   g_free (params);
87   
88   return signal_id;
89 }
90
91 void
92 gtk_signal_emit_stop_by_name (GtkObject   *object,
93                               const gchar *name)
94 {
95   g_return_if_fail (GTK_IS_OBJECT (object));
96   
97   g_signal_stop_emission (object, g_signal_lookup (name, G_OBJECT_TYPE (object)), 0);
98 }
99
100 void
101 gtk_signal_connect_object_while_alive (GtkObject    *object,
102                                        const gchar  *signal,
103                                        GtkSignalFunc func,
104                                        GtkObject    *alive_object)
105 {
106   g_return_if_fail (GTK_IS_OBJECT (object));
107   
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),
111                                   FALSE);
112 }
113
114 void
115 gtk_signal_connect_while_alive (GtkObject    *object,
116                                 const gchar  *signal,
117                                 GtkSignalFunc func,
118                                 gpointer      func_data,
119                                 GtkObject    *alive_object)
120 {
121   GClosure *closure;
122
123   g_return_if_fail (GTK_IS_OBJECT (object));
124
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,
129                                   closure,
130                                   FALSE);
131 }
132
133 guint
134 gtk_signal_connect_full (GtkObject           *object,
135                          const gchar         *name,
136                          GtkSignalFunc        func,
137                          GtkCallbackMarshal   unsupported,
138                          gpointer             data,
139                          GtkDestroyNotify     destroy_func,
140                          gint                 object_signal,
141                          gint                 after)
142 {
143   g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
144   g_return_val_if_fail (unsupported == NULL, 0);
145   
146   return g_signal_connect_closure_by_id (object,
147                                          g_signal_lookup (name, G_OBJECT_TYPE (object)), 0,
148                                          (object_signal
149                                           ? g_cclosure_new_swap
150                                           : g_cclosure_new) (func,
151                                                              data,
152                                                              (GClosureNotify) destroy_func),
153                                          after);
154 }
155
156 void
157 gtk_signal_compat_matched (GtkObject       *object,
158                            GtkSignalFunc    func,
159                            gpointer         data,
160                            GSignalMatchType match,
161                            guint            action)
162 {
163   guint n_handlers;
164   
165   g_return_if_fail (GTK_IS_OBJECT (object));
166
167   switch (action)
168     {
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;
173     }
174   
175   if (!n_handlers)
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);
178 }
179
180 static inline gboolean
181 gtk_arg_to_value (GtkArg *arg,
182                   GValue *value)
183 {
184   switch (G_TYPE_FUNDAMENTAL (arg->type))
185     {
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;
201     default:
202       return FALSE;
203     }
204   return TRUE;
205 }
206
207 static inline gboolean
208 gtk_arg_static_to_value (GtkArg *arg,
209                          GValue *value)
210 {
211   switch (G_TYPE_FUNDAMENTAL (arg->type))
212     {
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;
228     default:
229       return FALSE;
230     }
231   return TRUE;
232 }
233
234 static inline gboolean
235 gtk_arg_set_from_value (GtkArg  *arg,
236                         GValue  *value,
237                         gboolean copy_string)
238 {
239   switch (G_TYPE_FUNDAMENTAL (arg->type))
240     {
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);
257     else
258       GTK_VALUE_STRING (*arg) = g_value_get_string (value);
259     break;
260     default:
261       return FALSE;
262     }
263   return TRUE;
264 }
265
266 static inline gboolean
267 gtk_argloc_set_from_value (GtkArg  *arg,
268                            GValue  *value,
269                            gboolean copy_string)
270 {
271   switch (G_TYPE_FUNDAMENTAL (arg->type))
272     {
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);
289     else
290       *GTK_RETLOC_STRING (*arg) = g_value_get_string (value);
291     break;
292     default:
293       return FALSE;
294     }
295   return TRUE;
296 }
297
298 void
299 gtk_signal_emitv (GtkObject *object,
300                   guint      signal_id,
301                   GtkArg    *args)
302 {
303   GSignalQuery query;
304   GValue params[SIGNAL_MAX_PARAMS + 1] = { { 0, }, };
305   GValue rvalue = { 0, };
306   guint i;
307   
308   g_return_if_fail (GTK_IS_OBJECT (object));
309   
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);
316   
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++)
320     {
321       GValue *value = params + 1 + i;
322       GtkArg *arg = args + i;
323       
324       g_value_init (value, arg->type);
325       if (!gtk_arg_static_to_value (arg, value))
326         {
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)));
329           return;
330         }
331     }
332   if (query.return_type != G_TYPE_NONE)
333     g_value_init (&rvalue, query.return_type);
334   
335   g_signal_emitv (params, signal_id, 0, &rvalue);
336   
337   if (query.return_type != G_TYPE_NONE)
338     {
339       gtk_argloc_set_from_value (args + query.n_params, &rvalue, TRUE);
340       g_value_unset (&rvalue);
341     }
342   for (i = 0; i < query.n_params; i++)
343     g_value_unset (params + 1 + i);
344   g_value_unset (params + 0);
345 }
346
347 static gboolean
348 gtk_signal_collect_args (GtkArg        *args,
349                          guint          n_args,
350                          const GtkType *arg_types,
351                          GtkType        return_type,
352                          va_list        var_args)
353 {
354   register GtkArg *last_arg;
355   register gboolean failed = FALSE;
356   
357   for (last_arg = args + n_args; args < last_arg; args++)
358     {
359       register gchar *error;
360       
361       args->name = NULL;
362       args->type = *(arg_types++);
363       GTK_ARG_COLLECT_VALUE (args,
364                              var_args,
365                              error);
366       if (error)
367         {
368           failed = TRUE;
369           g_warning ("gtk_signal_collect_args(): %s", error);
370           g_free (error);
371         }
372     }
373   
374   args->type = return_type;
375   args->name = NULL;
376   
377   return_type = GTK_FUNDAMENTAL_TYPE (return_type);
378   if (return_type != G_TYPE_NONE)
379     {
380       if (return_type != 0) /* FIXME: check for IS_ARG */
381         {
382           GTK_VALUE_POINTER (*args) = va_arg (var_args, gpointer);
383           
384           if (GTK_VALUE_POINTER (*args) == NULL)
385             {
386               failed = TRUE;
387               g_warning ("gtk_signal_collect_args(): invalid NULL pointer for return argument type `%s'",
388                          gtk_type_name (args->type));
389             }
390         }
391       else
392         {
393           failed = TRUE;
394           g_warning ("gtk_signal_collect_args(): unsupported return argument type `%s'",
395                      gtk_type_name (args->type));
396         }
397     }
398   else
399     GTK_VALUE_POINTER (*args) = NULL;
400   
401   return failed;
402 }
403
404 #if 0
405 void
406 gtk_signal_emit (GtkObject *object,
407                  guint      signal_id,
408                  ...)
409 {
410   GtkArg args[SIGNAL_MAX_PARAMS + 1];
411   GSignalQuery query;
412   gboolean abort;
413   va_list var_args;
414   
415   g_return_if_fail (GTK_IS_OBJECT (object));
416   
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);
420   
421   va_start (var_args, signal_id);
422   abort = gtk_signal_collect_args (args,
423                                    query.n_params,
424                                    query.param_types,
425                                    query.return_type,
426                                    var_args);
427   va_end (var_args);
428   
429   if (!abort)
430     gtk_signal_emitv (object, signal_id, args);
431 }
432 #endif
433
434 void
435 gtk_signal_emit (GtkObject *object,
436                  guint      signal_id,
437                  ...)
438 {
439   va_list var_args;
440   
441   g_return_if_fail (GTK_IS_OBJECT (object));
442
443   va_start (var_args, signal_id);
444   g_signal_emit_valist (G_OBJECT (object), signal_id, 0, var_args);
445   va_end (var_args);
446 }
447
448 void
449 gtk_signal_emit_by_name (GtkObject   *object,
450                          const gchar *name,
451                          ...)
452 {
453   GtkArg args[SIGNAL_MAX_PARAMS + 1];
454   GSignalQuery query;
455   gboolean abort;
456   va_list var_args;
457   
458   g_return_if_fail (GTK_IS_OBJECT (object));
459   g_return_if_fail (name != NULL);
460   
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);
464   
465   va_start (var_args, name);
466   abort = gtk_signal_collect_args (args,
467                                    query.n_params,
468                                    query.param_types,
469                                    query.return_type,
470                                    var_args);
471   va_end (var_args);
472   
473   if (!abort)
474     gtk_signal_emitv (object, query.signal_id, args);
475 }
476
477 void
478 gtk_signal_emitv_by_name (GtkObject   *object,
479                           const gchar *name,
480                           GtkArg      *args)
481 {
482   g_return_if_fail (GTK_IS_OBJECT (object));
483   
484   gtk_signal_emitv (object, g_signal_lookup (name, GTK_OBJECT_TYPE (object)), args);
485 }