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