]> Pileus Git - ~andy/gtk/blob - gtk/gtkargcollector.c
Added notice to look in AUTHORS and ChangeLog files for a list of changes.
[~andy/gtk] / gtk / gtkargcollector.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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* collect a single argument value from a va_list.
28  * this is implemented as a huge macro <shrug>, because we can't
29  * pass va_list variables by reference on some systems.
30  * the corresponding prototype would be:
31  * static inline gchar*
32  * gtk_arg_collect_value (GtkArg  *arg,
33  *                        va_list  var_args);
34  */
35 #define GTK_ARG_COLLECT_VALUE(arg, var_args, _error)    \
36 G_STMT_START { \
37   gchar *error_msg; \
38   GtkType fundamental_type; \
39   \
40   fundamental_type = GTK_FUNDAMENTAL_TYPE (arg->type); \
41   if (fundamental_type > GTK_TYPE_FUNDAMENTAL_LAST) \
42     { \
43       fundamental_type = gtk_type_get_varargs_type (fundamental_type); \
44       if (!fundamental_type) \
45         fundamental_type = GTK_FUNDAMENTAL_TYPE (arg->type); \
46     } \
47  \
48   error_msg = NULL; \
49   switch (fundamental_type) \
50     { \
51     case GTK_TYPE_INVALID: \
52       error_msg = g_strdup ("invalid untyped argument"); \
53       break; \
54  \
55     case GTK_TYPE_NONE: \
56       /* we just ignore this type, since it arithmetically just requires \
57        * us to not move the var_args pointer any further. callers need to \
58        * check for the validity of GTK_TYPE_NONE themselves. \
59        * \
60        * error_msg = g_strdup ("invalid argument type `void'"); \
61        */ \
62       break; \
63  \
64       /* everything smaller than an int is guarranteed to be \
65        * passed as an int \
66        */ \
67     case GTK_TYPE_CHAR: \
68       GTK_VALUE_CHAR (*arg) = va_arg (var_args, gint); \
69       break; \
70     case GTK_TYPE_UCHAR: \
71       GTK_VALUE_UCHAR (*arg) = va_arg (var_args, guint); \
72       break; \
73     case GTK_TYPE_BOOL: \
74       GTK_VALUE_BOOL (*arg) = va_arg (var_args, gint); \
75       break; \
76     case GTK_TYPE_INT: \
77       GTK_VALUE_INT (*arg) = va_arg (var_args, gint); \
78       break; \
79     case GTK_TYPE_UINT: \
80       GTK_VALUE_UINT (*arg) = va_arg (var_args, guint); \
81       break; \
82     case GTK_TYPE_ENUM: \
83       GTK_VALUE_ENUM (*arg) = va_arg (var_args, gint); \
84       break; \
85     case GTK_TYPE_FLAGS: \
86       GTK_VALUE_FLAGS (*arg) = va_arg (var_args, guint); \
87       break; \
88  \
89       /* we collect longs as glongs since they differ in size with \
90        * integers on some platforms \
91        */ \
92     case GTK_TYPE_LONG: \
93       GTK_VALUE_LONG (*arg) = va_arg (var_args, glong); \
94       break; \
95     case GTK_TYPE_ULONG: \
96       GTK_VALUE_ULONG (*arg) = va_arg (var_args, gulong); \
97       break; \
98  \
99       /* floats are always passed as doubles \
100        */ \
101     case GTK_TYPE_FLOAT: \
102       /* GTK_VALUE_FLOAT (*arg) = va_arg (var_args, gfloat); */ \
103       GTK_VALUE_FLOAT (*arg) = va_arg (var_args, gdouble); \
104       break; \
105     case GTK_TYPE_DOUBLE: \
106       GTK_VALUE_DOUBLE (*arg) = va_arg (var_args, gdouble); \
107       break; \
108  \
109       /* collect pointer values \
110        */ \
111     case GTK_TYPE_STRING: \
112       GTK_VALUE_STRING (*arg) = va_arg (var_args, gchar*); \
113       break; \
114     case GTK_TYPE_POINTER: \
115       GTK_VALUE_POINTER (*arg) = va_arg (var_args, gpointer); \
116       break; \
117     case GTK_TYPE_BOXED: \
118       GTK_VALUE_BOXED (*arg) = va_arg (var_args, gpointer); \
119       break; \
120  \
121       /* structured types \
122        */ \
123     case GTK_TYPE_SIGNAL: \
124       GTK_VALUE_SIGNAL (*arg).f = va_arg (var_args, GtkSignalFunc); \
125       GTK_VALUE_SIGNAL (*arg).d = va_arg (var_args, gpointer); \
126       break; \
127     case GTK_TYPE_ARGS: \
128       GTK_VALUE_ARGS (*arg).n_args = va_arg (var_args, gint); \
129       GTK_VALUE_ARGS (*arg).args = va_arg (var_args, GtkArg*); \
130       break; \
131     case GTK_TYPE_FOREIGN: \
132       GTK_VALUE_FOREIGN (*arg).data = va_arg (var_args, gpointer); \
133       GTK_VALUE_FOREIGN (*arg).notify = va_arg (var_args, GtkDestroyNotify); \
134       break; \
135     case GTK_TYPE_CALLBACK: \
136       GTK_VALUE_CALLBACK (*arg).marshal = va_arg (var_args, GtkCallbackMarshal); \
137       GTK_VALUE_CALLBACK (*arg).data = va_arg (var_args, gpointer); \
138       GTK_VALUE_CALLBACK (*arg).notify = va_arg (var_args, GtkDestroyNotify); \
139       break; \
140     case GTK_TYPE_C_CALLBACK: \
141       GTK_VALUE_C_CALLBACK (*arg).func = va_arg (var_args, GtkFunction); \
142       GTK_VALUE_C_CALLBACK (*arg).func_data = va_arg (var_args, gpointer); \
143       break; \
144  \
145       /* we do some extra sanity checking when collecting objects, \
146        * i.e. if the object pointer is not NULL, we check whether we \
147        * actually got an object pointer within the desired class branch. \
148        */ \
149     case GTK_TYPE_OBJECT: \
150       GTK_VALUE_OBJECT (*arg) = va_arg (var_args, GtkObject*); \
151       if (GTK_VALUE_OBJECT (*arg) != NULL) \
152         { \
153           register GtkObject *object = GTK_VALUE_OBJECT (*arg); \
154            \
155           if (object->klass == NULL) \
156             error_msg = g_strconcat ("invalid unclassed object pointer for argument type `", \
157                                      gtk_type_name (arg->type), \
158                                      "'", \
159                                      NULL); \
160           else if (!gtk_type_is_a (GTK_OBJECT_TYPE (object), arg->type)) \
161             error_msg = g_strconcat ("invalid object `", \
162                                      gtk_type_name (GTK_OBJECT_TYPE (object)), \
163                                      "' for argument type `", \
164                                      gtk_type_name (arg->type), \
165                                      "'", \
166                                      NULL); \
167         } \
168       break; \
169  \
170     default: \
171       error_msg = g_strconcat ("unsupported argument type `", \
172                                gtk_type_name (arg->type), \
173                                "'", \
174                                NULL); \
175       break; \
176     } \
177    \
178   _error = error_msg; /* return error_msg; */ \
179 } G_STMT_END