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