gtksignal.c 13.5 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * 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.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19

20 21
#undef GTK_DISABLE_DEPRECATED

22
#include	<config.h>
23
#include	"gtksignal.h"
24
#include 	"gtkalias.h"
25

26 27 28 29 30
/* the real parameter limit is of course given by GSignal, bu we need
 * an upper limit for the implementations. so this should be adjusted
 * with any future changes on the GSignal side of things.
 */
#define	SIGNAL_MAX_PARAMS	12
31

32

33
/* --- functions --- */
34
guint
35
gtk_signal_newv (const gchar         *name,
36
		 GtkSignalRunType     signal_flags,
37 38
		 GtkType              object_type,
		 guint                function_offset,
39
		 GtkSignalMarshaller  marshaller,
40 41 42
		 GtkType              return_val,
		 guint                n_params,
		 GtkType             *params)
43
{
44
  GClosure *closure;
45
  
46
  g_return_val_if_fail (n_params < SIGNAL_MAX_PARAMS, 0);
47
  
Matthias Clasen's avatar
Matthias Clasen committed
48
  closure = function_offset ? g_signal_type_cclosure_new (object_type, function_offset) : NULL;
49
  
50 51
  return g_signal_newv (name, object_type, (GSignalFlags)signal_flags, closure,
			NULL, NULL, marshaller, return_val, n_params, params);
52 53 54
}

guint
55
gtk_signal_new (const gchar         *name,
56
		GtkSignalRunType     signal_flags,
57 58
		GtkType              object_type,
		guint                function_offset,
59
		GtkSignalMarshaller  marshaller,
60 61
		GtkType              return_val,
		guint                n_params,
62 63 64 65 66
		...)
{
  GtkType *params;
  guint signal_id;
  
67
  if (n_params)
68
    {
69 70
      va_list args;
      guint i;
71
      
72 73 74
      params = g_new (GtkType, n_params);
      va_start (args, n_params);
      for (i = 0; i < n_params; i++)
75 76 77 78 79 80
	params[i] = va_arg (args, GtkType);
      va_end (args);
    }
  else
    params = NULL;
  signal_id = gtk_signal_newv (name,
81
			       signal_flags,
82 83 84 85
			       object_type,
			       function_offset,
			       marshaller,
			       return_val,
86
			       n_params,
87 88 89 90 91 92
			       params);
  g_free (params);
  
  return signal_id;
}

93 94 95
void
gtk_signal_emit_stop_by_name (GtkObject   *object,
			      const gchar *name)
Elliot Lee's avatar
Elliot Lee committed
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);
Elliot Lee's avatar
Elliot Lee committed
100 101
}

102
void
103
gtk_signal_connect_object_while_alive (GtkObject    *object,
104
				       const gchar  *name,
105 106
				       GtkSignalFunc func,
				       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
117
gtk_signal_connect_while_alive (GtkObject    *object,
118
				const gchar  *name,
119 120 121
				GtkSignalFunc func,
				gpointer      func_data,
				GtkObject    *alive_object)
Elliot Lee's avatar
Elliot Lee committed
122
{
123
  GClosure *closure;
124

125
  g_return_if_fail (GTK_IS_OBJECT (object));
126

127 128
  closure = g_cclosure_new (func, func_data, NULL);
  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 132
				  closure,
				  FALSE);
133 134
}

135
gulong
136 137 138 139 140 141 142 143
gtk_signal_connect_full (GtkObject           *object,
			 const gchar         *name,
			 GtkSignalFunc        func,
			 GtkCallbackMarshal   unsupported,
			 gpointer             data,
			 GtkDestroyNotify     destroy_func,
			 gint                 object_signal,
			 gint                 after)
144
{
145 146
  g_return_val_if_fail (GTK_IS_OBJECT (object), 0);
  g_return_val_if_fail (unsupported == NULL, 0);
147
  
148 149 150 151 152 153 154 155
  return g_signal_connect_closure_by_id (object,
					 g_signal_lookup (name, G_OBJECT_TYPE (object)), 0,
					 (object_signal
					  ? g_cclosure_new_swap
					  : g_cclosure_new) (func,
							     data,
							     (GClosureNotify) destroy_func),
					 after);
Elliot Lee's avatar
Elliot Lee committed
156 157
}

158
void
159 160 161 162 163
gtk_signal_compat_matched (GtkObject       *object,
			   GtkSignalFunc    func,
			   gpointer         data,
			   GSignalMatchType match,
			   guint            action)
Elliot Lee's avatar
Elliot Lee committed
164
{
165
  guint n_handlers;
166
  
167
  g_return_if_fail (GTK_IS_OBJECT (object));
168 169 170

  switch (action)
    {
171 172 173
    case 0:  n_handlers = g_signal_handlers_disconnect_matched (object, match, 0, 0, NULL, (gpointer) func, data);	 break;
    case 1:  n_handlers = g_signal_handlers_block_matched (object, match, 0, 0, NULL, (gpointer) func, data);	 break;
    case 2:  n_handlers = g_signal_handlers_unblock_matched (object, match, 0, 0, NULL, (gpointer) func, data);	 break;
174 175
    default: n_handlers = 0;										 break;
    }
176
  
177
  if (!n_handlers)
178 179
    g_warning ("unable to find signal handler for object(%s:%p) with func(%p) and data(%p)",
	       G_OBJECT_TYPE_NAME (object), object, func, data);
Elliot Lee's avatar
Elliot Lee committed
180 181
}

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
static inline gboolean
gtk_arg_to_value (GtkArg *arg,
		  GValue *value)
{
  switch (G_TYPE_FUNDAMENTAL (arg->type))
    {
    case G_TYPE_CHAR:		g_value_set_char (value, GTK_VALUE_CHAR (*arg));	break;
    case G_TYPE_UCHAR:		g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg));	break;
    case G_TYPE_BOOLEAN:	g_value_set_boolean (value, GTK_VALUE_BOOL (*arg));	break;
    case G_TYPE_INT:		g_value_set_int (value, GTK_VALUE_INT (*arg));		break;
    case G_TYPE_UINT:		g_value_set_uint (value, GTK_VALUE_UINT (*arg));	break;
    case G_TYPE_LONG:		g_value_set_long (value, GTK_VALUE_LONG (*arg));	break;
    case G_TYPE_ULONG:		g_value_set_ulong (value, GTK_VALUE_ULONG (*arg));	break;
    case G_TYPE_ENUM:		g_value_set_enum (value, GTK_VALUE_ENUM (*arg));	break;
    case G_TYPE_FLAGS:		g_value_set_flags (value, GTK_VALUE_FLAGS (*arg));	break;
    case G_TYPE_FLOAT:		g_value_set_float (value, GTK_VALUE_FLOAT (*arg));	break;
    case G_TYPE_DOUBLE:		g_value_set_double (value, GTK_VALUE_DOUBLE (*arg));	break;
    case G_TYPE_STRING:		g_value_set_string (value, GTK_VALUE_STRING (*arg));	break;
    case G_TYPE_BOXED:		g_value_set_boxed (value, GTK_VALUE_BOXED (*arg));	break;
    case G_TYPE_POINTER:	g_value_set_pointer (value, GTK_VALUE_POINTER (*arg));	break;
    case G_TYPE_OBJECT:		g_value_set_object (value, GTK_VALUE_POINTER (*arg));	break;
    default:
      return FALSE;
    }
  return TRUE;
}

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
static inline gboolean
gtk_arg_static_to_value (GtkArg *arg,
			 GValue *value)
{
  switch (G_TYPE_FUNDAMENTAL (arg->type))
    {
    case G_TYPE_CHAR:		g_value_set_char (value, GTK_VALUE_CHAR (*arg));		break;
    case G_TYPE_UCHAR:		g_value_set_uchar (value, GTK_VALUE_UCHAR (*arg));		break;
    case G_TYPE_BOOLEAN:	g_value_set_boolean (value, GTK_VALUE_BOOL (*arg));		break;
    case G_TYPE_INT:		g_value_set_int (value, GTK_VALUE_INT (*arg));			break;
    case G_TYPE_UINT:		g_value_set_uint (value, GTK_VALUE_UINT (*arg));		break;
    case G_TYPE_LONG:		g_value_set_long (value, GTK_VALUE_LONG (*arg));		break;
    case G_TYPE_ULONG:		g_value_set_ulong (value, GTK_VALUE_ULONG (*arg));		break;
    case G_TYPE_ENUM:		g_value_set_enum (value, GTK_VALUE_ENUM (*arg));		break;
    case G_TYPE_FLAGS:		g_value_set_flags (value, GTK_VALUE_FLAGS (*arg));		break;
    case G_TYPE_FLOAT:		g_value_set_float (value, GTK_VALUE_FLOAT (*arg));		break;
    case G_TYPE_DOUBLE:		g_value_set_double (value, GTK_VALUE_DOUBLE (*arg));		break;
    case G_TYPE_STRING:		g_value_set_static_string (value, GTK_VALUE_STRING (*arg));	break;
    case G_TYPE_BOXED:		g_value_set_static_boxed (value, GTK_VALUE_BOXED (*arg));	break;
    case G_TYPE_POINTER:	g_value_set_pointer (value, GTK_VALUE_POINTER (*arg));		break;
    case G_TYPE_OBJECT:		g_value_set_object (value, GTK_VALUE_POINTER (*arg));		break;
    default:
      return FALSE;
    }
  return TRUE;
}

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
static inline gboolean
gtk_arg_set_from_value (GtkArg  *arg,
			GValue  *value,
			gboolean copy_string)
{
  switch (G_TYPE_FUNDAMENTAL (arg->type))
    {
    case G_TYPE_CHAR:		GTK_VALUE_CHAR (*arg) = g_value_get_char (value);	break;
    case G_TYPE_UCHAR:		GTK_VALUE_UCHAR (*arg) = g_value_get_uchar (value);	break;
    case G_TYPE_BOOLEAN:	GTK_VALUE_BOOL (*arg) = g_value_get_boolean (value);	break;
    case G_TYPE_INT:		GTK_VALUE_INT (*arg) = g_value_get_int (value);		break;
    case G_TYPE_UINT:		GTK_VALUE_UINT (*arg) = g_value_get_uint (value);	break;
    case G_TYPE_LONG:		GTK_VALUE_LONG (*arg) = g_value_get_long (value);	break;
    case G_TYPE_ULONG:		GTK_VALUE_ULONG (*arg) = g_value_get_ulong (value);	break;
    case G_TYPE_ENUM:		GTK_VALUE_ENUM (*arg) = g_value_get_enum (value);	break;
    case G_TYPE_FLAGS:		GTK_VALUE_FLAGS (*arg) = g_value_get_flags (value);	break;
    case G_TYPE_FLOAT:		GTK_VALUE_FLOAT (*arg) = g_value_get_float (value);	break;
    case G_TYPE_DOUBLE:		GTK_VALUE_DOUBLE (*arg) = g_value_get_double (value);	break;
    case G_TYPE_BOXED:		GTK_VALUE_BOXED (*arg) = g_value_get_boxed (value);	break;
    case G_TYPE_POINTER:	GTK_VALUE_POINTER (*arg) = g_value_get_pointer (value);	break;
    case G_TYPE_OBJECT:		GTK_VALUE_POINTER (*arg) = g_value_get_object (value);	break;
    case G_TYPE_STRING:		if (copy_string)
      GTK_VALUE_STRING (*arg) = g_value_dup_string (value);
    else
260
      GTK_VALUE_STRING (*arg) = (char *) g_value_get_string (value);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
    break;
    default:
      return FALSE;
    }
  return TRUE;
}

static inline gboolean
gtk_argloc_set_from_value (GtkArg  *arg,
			   GValue  *value,
			   gboolean copy_string)
{
  switch (G_TYPE_FUNDAMENTAL (arg->type))
    {
    case G_TYPE_CHAR:		*GTK_RETLOC_CHAR (*arg) = g_value_get_char (value);	  break;
    case G_TYPE_UCHAR:		*GTK_RETLOC_UCHAR (*arg) = g_value_get_uchar (value);	  break;
    case G_TYPE_BOOLEAN:	*GTK_RETLOC_BOOL (*arg) = g_value_get_boolean (value);	  break;
    case G_TYPE_INT:		*GTK_RETLOC_INT (*arg) = g_value_get_int (value);	  break;
    case G_TYPE_UINT:		*GTK_RETLOC_UINT (*arg) = g_value_get_uint (value);	  break;
    case G_TYPE_LONG:		*GTK_RETLOC_LONG (*arg) = g_value_get_long (value);	  break;
    case G_TYPE_ULONG:		*GTK_RETLOC_ULONG (*arg) = g_value_get_ulong (value);	  break;
    case G_TYPE_ENUM:		*GTK_RETLOC_ENUM (*arg) = g_value_get_enum (value);	  break;
    case G_TYPE_FLAGS:		*GTK_RETLOC_FLAGS (*arg) = g_value_get_flags (value);	  break;
    case G_TYPE_FLOAT:		*GTK_RETLOC_FLOAT (*arg) = g_value_get_float (value);	  break;
    case G_TYPE_DOUBLE:		*GTK_RETLOC_DOUBLE (*arg) = g_value_get_double (value);	  break;
    case G_TYPE_BOXED:		*GTK_RETLOC_BOXED (*arg) = g_value_get_boxed (value);	  break;
    case G_TYPE_POINTER:	*GTK_RETLOC_POINTER (*arg) = g_value_get_pointer (value); break;
    case G_TYPE_OBJECT:		*GTK_RETLOC_POINTER (*arg) = g_value_get_object (value);  break;
    case G_TYPE_STRING:		if (copy_string)
      *GTK_RETLOC_STRING (*arg) = g_value_dup_string (value);
    else
292
      *GTK_RETLOC_STRING (*arg) = (char *) g_value_get_string (value);
293 294 295 296 297
    break;
    default:
      return FALSE;
    }
  return TRUE;
Elliot Lee's avatar
Elliot Lee committed
298 299 300
}

void
301 302 303
gtk_signal_emitv (GtkObject *object,
		  guint      signal_id,
		  GtkArg    *args)
Elliot Lee's avatar
Elliot Lee committed
304
{
305 306 307 308
  GSignalQuery query;
  GValue params[SIGNAL_MAX_PARAMS + 1] = { { 0, }, };
  GValue rvalue = { 0, };
  guint i;
309
  
310
  g_return_if_fail (GTK_IS_OBJECT (object));
311
  
312 313
  g_signal_query (signal_id, &query);
  g_return_if_fail (query.signal_id != 0);
314
  g_return_if_fail (g_type_is_a (GTK_OBJECT_TYPE (object), query.itype));
315 316 317
  g_return_if_fail (query.n_params < SIGNAL_MAX_PARAMS);
  if (query.n_params > 0)
    g_return_if_fail (args != NULL);
318
  
319 320 321
  g_value_init (params + 0, GTK_OBJECT_TYPE (object));
  g_value_set_object (params + 0, G_OBJECT (object));
  for (i = 0; i < query.n_params; i++)
322
    {
323 324 325
      GValue *value = params + 1 + i;
      GtkArg *arg = args + i;
      
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 331
		     G_STRLOC, g_type_name (arg->type & ~G_SIGNAL_TYPE_STATIC_SCOPE),
		     g_type_name (G_VALUE_TYPE (value)));
332 333
	  return;
	}
334
    }
335 336
  if (query.return_type != G_TYPE_NONE)
    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 343
      gtk_argloc_set_from_value (args + query.n_params, &rvalue, TRUE);
      g_value_unset (&rvalue);
344
    }
345 346 347
  for (i = 0; i < query.n_params; i++)
    g_value_unset (params + 1 + i);
  g_value_unset (params + 0);
348 349
}

350 351 352 353 354 355 356 357 358 359 360 361 362
void
gtk_signal_emit (GtkObject *object,
		 guint      signal_id,
		 ...)
{
  va_list var_args;
  
  g_return_if_fail (GTK_IS_OBJECT (object));

  va_start (var_args, signal_id);
  g_signal_emit_valist (G_OBJECT (object), signal_id, 0, var_args);
  va_end (var_args);
}
Elliot Lee's avatar
Elliot Lee committed
363

364 365 366 367
void
gtk_signal_emit_by_name (GtkObject   *object,
			 const gchar *name,
			 ...)
Elliot Lee's avatar
Elliot Lee committed
368
{
369 370 371 372 373
  GSignalQuery query;
  va_list var_args;
  
  g_return_if_fail (GTK_IS_OBJECT (object));
  g_return_if_fail (name != NULL);
374
  
375 376
  g_signal_query (g_signal_lookup (name, GTK_OBJECT_TYPE (object)), &query);
  g_return_if_fail (query.signal_id != 0);
377
  
378
  va_start (var_args, name);
Tim Janik's avatar
Tim Janik committed
379
  g_signal_emit_valist (G_OBJECT (object), query.signal_id, 0, var_args);
380
  va_end (var_args);
Elliot Lee's avatar
Elliot Lee committed
381 382
}

383
void
384 385 386
gtk_signal_emitv_by_name (GtkObject   *object,
			  const gchar *name,
			  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);
Elliot Lee's avatar
Elliot Lee committed
391
}
392 393 394

#define __GTK_SIGNAL_C__
#include "gtkaliasdef.c"