1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
21 * Modified by the GTK+ Team and others 1997-2000. 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/.
29 #include "gtkobject.h"
30 #include "gtkargcollector.c"
33 #define MAX_ARG_LENGTH (256)
36 /* --- typedefs --- */
37 typedef struct _GtkArgQueryData GtkArgQueryData;
40 /* --- structures --- */
41 struct _GtkArgQueryData
49 /* --- functions --- */
51 gtk_arg_type_new_static (GtkType base_class_type,
52 const gchar *arg_name,
53 guint class_n_args_offset,
54 GHashTable *arg_info_hash_table,
60 gchar class_part[MAX_ARG_LENGTH];
67 g_return_val_if_fail (arg_name != NULL, NULL);
68 g_return_val_if_fail (GTK_TYPE_IS_OBJECT (base_class_type), NULL);
69 g_return_val_if_fail (class_n_args_offset != 0, NULL);
70 g_return_val_if_fail (arg_info_hash_table != NULL, NULL);
71 g_return_val_if_fail (arg_type > GTK_TYPE_NONE, NULL);
72 g_return_val_if_fail (arg_id > 0, NULL);
73 g_return_val_if_fail ((arg_flags & GTK_ARG_READWRITE) != 0, NULL);
74 /* g_return_val_if_fail ((arg_flags & GTK_ARG_CHILD_ARG) == 0, NULL); */
76 arg_flags &= GTK_ARG_MASK;
78 arg_part = strchr (arg_name, ':');
79 if (!arg_part || (arg_part[0] != ':') || (arg_part[1] != ':'))
81 g_warning ("gtk_arg_type_new(): invalid arg name: \"%s\"\n", arg_name);
85 class_offset = (guint) (arg_part - arg_name);
86 strncpy (class_part, arg_name, class_offset);
87 class_part[class_offset] = 0;
89 class_type = gtk_type_from_name (class_part);
90 if (!gtk_type_is_a (class_type, base_class_type))
92 g_warning ("gtk_arg_type_new(): argument class in \"%s\" is not in the `%s' ancestry",
94 gtk_type_name (base_class_type));
98 p = gtk_type_class (class_type);
99 p += class_n_args_offset;
100 n_args_p = (guint*) p;
103 info = g_new (GtkArgInfo, 1);
104 info->class_type = class_type;
105 info->full_name = (gchar*) arg_name; /* _static */
106 info->name = info->full_name + class_offset + 2;
107 info->type = arg_type;
108 info->arg_flags = arg_flags;
109 info->arg_id = arg_id;
110 info->seq_id = *n_args_p;
112 g_hash_table_insert (arg_info_hash_table, info, info);
118 gtk_arg_name_strip_type (const gchar *arg_name)
120 gchar buffer[MAX_ARG_LENGTH];
125 if (!arg_name || strlen (arg_name) > MAX_ARG_LENGTH - 8)
128 p = strchr (arg_name, ':');
133 if ((p[0] != ':') || (p[1] != ':') || (p[2] == 0))
135 len = (guint) (p - arg_name);
136 strncpy (buffer, arg_name, len);
139 if (gtk_type_from_name (buffer) != GTK_TYPE_INVALID)
143 return (gchar*) arg_name;
147 gtk_arg_get_info (GtkType object_type,
148 GHashTable *arg_info_hash_table,
149 const gchar *arg_name,
153 gchar buffer[MAX_ARG_LENGTH];
161 if (!arg_name || strlen (arg_name) > MAX_ARG_LENGTH - 8)
162 return g_strdup ("argument name exceeds maximum size.");
164 /* split off the object-type part
166 p = strchr (arg_name, ':');
169 if ((p[0] != ':') || (p[1] != ':'))
170 return g_strconcat ("invalid argument syntax: \"",
174 len = (guint) (p - arg_name);
175 strncpy (buffer, arg_name, len);
178 otype = gtk_type_from_name (buffer);
179 if (otype != GTK_TYPE_INVALID)
183 otype = GTK_TYPE_INVALID;
185 /* split off the argument name
187 p = strchr (arg_name, ':');
190 if ((p[0] != ':') || (p[1] != ':'))
191 return g_strconcat ("invalid argument syntax: \"",
195 len = (guint) (p - arg_name);
196 strncpy (buffer, arg_name, len);
201 /* lookup the argument
203 if (otype != GTK_TYPE_INVALID)
207 info.class_type = otype;
208 info.name = (gchar*) arg_name;
210 *info_p = g_hash_table_lookup (arg_info_hash_table, &info);
211 if (*info_p && !gtk_type_is_a (object_type, (*info_p)->class_type))
217 while (!*info_p && GTK_TYPE_IS_OBJECT (otype))
221 info.class_type = otype;
222 info.name = (gchar*) arg_name;
224 *info_p = g_hash_table_lookup (arg_info_hash_table, &info);
226 otype = gtk_type_parent (otype);
231 return g_strconcat ("could not find argument \"",
234 gtk_type_name (object_type),
242 gtk_args_collect (GtkType object_type,
243 GHashTable *arg_info_hash_table,
245 GSList **info_list_p,
246 const gchar *first_arg_name,
251 const gchar *arg_name;
253 g_return_val_if_fail (arg_list_p != NULL, NULL);
255 g_return_val_if_fail (info_list_p != NULL, NULL);
257 g_return_val_if_fail (arg_info_hash_table != NULL, NULL);
261 arg_name = first_arg_name;
264 GtkArgInfo *info = NULL;
267 error = gtk_arg_get_info (object_type, arg_info_hash_table, arg_name, &info);
272 info_list = g_slist_prepend (info_list, info);
274 arg = gtk_arg_new (info->type);
275 arg->name = (gchar*) arg_name;
276 GTK_ARG_COLLECT_VALUE (arg, var_args, error);
277 arg_list = g_slist_prepend (arg_list, arg);
281 gtk_args_collect_cleanup (arg_list, info_list);
286 arg_name = va_arg (var_args, gchar*);
289 *arg_list_p = g_slist_reverse (arg_list);
290 *info_list_p = g_slist_reverse (info_list);
296 gtk_args_collect_cleanup (GSList *arg_list,
301 g_slist_free (info_list);
303 for (slist = arg_list; slist; slist = slist->next)
304 gtk_arg_free (slist->data, FALSE);
305 g_slist_free (arg_list);
309 gtk_args_query_foreach (gpointer key,
313 register GtkArgInfo *info;
314 register GtkArgQueryData *data;
316 g_assert (key == value); /* paranoid */
321 if (info->class_type == data->class_type)
322 data->arg_list = g_list_prepend (data->arg_list, info);
326 gtk_args_query (GtkType class_type,
327 GHashTable *arg_info_hash_table,
332 GtkArgQueryData query_data;
336 g_return_val_if_fail (n_args_p != NULL, NULL);
338 g_return_val_if_fail (arg_info_hash_table != NULL, NULL);
340 /* make sure the types class has been initialized, because
341 * the argument setup happens in the gtk_*_class_init() functions.
343 gtk_type_class (class_type);
345 query_data.arg_list = NULL;
346 query_data.class_type = class_type;
347 g_hash_table_foreach (arg_info_hash_table, gtk_args_query_foreach, &query_data);
349 if (query_data.arg_list)
351 register GList *list;
354 list = query_data.arg_list;
362 args = g_new0 (GtkArg, len);
365 *arg_flags = g_new (guint32, len);
374 g_assert (info->seq_id > 0 && info->seq_id <= len); /* paranoid */
376 args[info->seq_id - 1].type = info->type;
377 args[info->seq_id - 1].name = info->full_name;
379 (*arg_flags)[info->seq_id - 1] = info->arg_flags;
383 g_list_free (query_data.arg_list);
392 gtk_arg_new (GtkType arg_type)
396 arg = g_new0 (GtkArg, 1);
397 arg->type = arg_type;
404 gtk_arg_copy (GtkArg *src_arg,
407 g_return_val_if_fail (src_arg != NULL, NULL);
411 dest_arg = g_new0 (GtkArg, 1);
412 dest_arg->name = src_arg->name;
415 dest_arg->type = src_arg->type;
416 dest_arg->d = src_arg->d;
418 if (GTK_FUNDAMENTAL_TYPE (src_arg->type) == GTK_TYPE_STRING)
419 GTK_VALUE_STRING (*dest_arg) = g_strdup (GTK_VALUE_STRING (*src_arg));
425 gtk_arg_free (GtkArg *arg,
426 gboolean free_contents)
428 g_return_if_fail (arg != NULL);
436 gtk_arg_reset (GtkArg *arg)
438 GtkType fundamental_type;
440 g_return_if_fail (arg != NULL);
442 fundamental_type = GTK_FUNDAMENTAL_TYPE (arg->type);
444 if (fundamental_type == GTK_TYPE_STRING)
446 g_free (GTK_VALUE_STRING (*arg));
447 arg->type = GTK_TYPE_INVALID;
449 else if (arg->type != GTK_TYPE_INVALID)
450 arg->type = GTK_TYPE_INVALID;
454 gtk_arg_info_equal (gconstpointer arg_info_1,
455 gconstpointer arg_info_2)
457 register const GtkArgInfo *info1 = arg_info_1;
458 register const GtkArgInfo *info2 = arg_info_2;
460 return ((info1->class_type == info2->class_type) &&
461 strcmp (info1->name, info2->name) == 0);
465 gtk_arg_info_hash (gconstpointer arg_info)
467 register const GtkArgInfo *info = arg_info;
468 register const gchar *p;
469 register guint h = info->class_type >> 8;
471 for (p = info->name; *p; p++)
488 gtk_arg_values_equal (const GtkArg *arg1,
491 GtkType fundamental_type;
494 g_return_val_if_fail (arg1 != NULL, FALSE);
495 g_return_val_if_fail (arg2 != NULL, FALSE);
496 g_return_val_if_fail (GTK_FUNDAMENTAL_TYPE (arg1->type) ==
497 GTK_FUNDAMENTAL_TYPE (arg2->type), FALSE);
499 fundamental_type = GTK_FUNDAMENTAL_TYPE (arg1->type);
501 switch (fundamental_type)
503 case GTK_TYPE_INVALID:
507 equal = GTK_VALUE_CHAR (*arg1) == GTK_VALUE_CHAR (*arg2);
510 equal = (GTK_VALUE_BOOL (*arg1) != FALSE) == (GTK_VALUE_BOOL (*arg2) != FALSE);
513 equal = GTK_VALUE_INT (*arg1) == GTK_VALUE_INT (*arg2);
516 equal = GTK_VALUE_UINT (*arg1) == GTK_VALUE_UINT (*arg2);
519 equal = GTK_VALUE_LONG (*arg1) == GTK_VALUE_LONG (*arg2);
522 equal = GTK_VALUE_ULONG (*arg1) == GTK_VALUE_ULONG (*arg2);
525 equal = GTK_VALUE_FLOAT (*arg1) == GTK_VALUE_FLOAT (*arg2);
527 case GTK_TYPE_DOUBLE:
528 equal = GTK_VALUE_DOUBLE (*arg1) == GTK_VALUE_DOUBLE (*arg2);
530 case GTK_TYPE_STRING:
531 if (!GTK_VALUE_STRING (*arg1) ||
532 !GTK_VALUE_STRING (*arg2))
533 equal = GTK_VALUE_STRING (*arg1) == GTK_VALUE_STRING (*arg2);
535 equal = g_str_equal (GTK_VALUE_STRING (*arg1), GTK_VALUE_STRING (*arg2));
538 equal = GTK_VALUE_ENUM (*arg1) == GTK_VALUE_ENUM (*arg2);
541 equal = GTK_VALUE_FLAGS (*arg1) == GTK_VALUE_FLAGS (*arg2);
544 equal = GTK_VALUE_BOXED (*arg1) == GTK_VALUE_BOXED (*arg2);
547 equal = GTK_VALUE_OBJECT (*arg1) == GTK_VALUE_OBJECT (*arg2);
549 case GTK_TYPE_POINTER:
550 equal = GTK_VALUE_POINTER (*arg1) == GTK_VALUE_POINTER (*arg2);
552 case GTK_TYPE_SIGNAL:
553 equal = (GTK_VALUE_SIGNAL (*arg1).f == GTK_VALUE_SIGNAL (*arg2).f &&
554 GTK_VALUE_SIGNAL (*arg1).d == GTK_VALUE_SIGNAL (*arg2).d);
557 g_warning ("gtk_arg_values_equal() used with unknown type `%s'", gtk_type_name (arg1->type));
566 gtk_arg_to_valueloc (GtkArg *arg,
567 gpointer value_pointer)
569 GtkType fundamental_type;
571 g_return_if_fail (arg != NULL);
572 g_return_if_fail (value_pointer != NULL);
574 fundamental_type = GTK_FUNDAMENTAL_TYPE (arg->type);
576 switch (fundamental_type)
589 p_char = value_pointer;
590 *p_char = GTK_VALUE_CHAR (*arg);
593 p_uchar = value_pointer;
594 *p_uchar = GTK_VALUE_UCHAR (*arg);
597 p_boolean = value_pointer;
598 *p_boolean = GTK_VALUE_BOOL (*arg);
602 p_int = value_pointer;
603 *p_int = GTK_VALUE_INT (*arg);
607 p_uint = value_pointer;
608 *p_uint = GTK_VALUE_UINT (*arg);
611 p_long = value_pointer;
612 *p_long = GTK_VALUE_LONG (*arg);
615 p_ulong = value_pointer;
616 *p_ulong = GTK_VALUE_ULONG (*arg);
619 p_float = value_pointer;
620 *p_float = GTK_VALUE_FLOAT (*arg);
622 case GTK_TYPE_DOUBLE:
623 p_double = value_pointer;
624 *p_double = GTK_VALUE_DOUBLE (*arg);
626 case GTK_TYPE_STRING:
627 case GTK_TYPE_POINTER:
630 p_pointer = value_pointer;
631 *p_pointer = GTK_VALUE_POINTER (*arg);
633 case GTK_TYPE_SIGNAL:
635 case GTK_TYPE_INVALID:
636 /* it doesn't make much sense to retrive these values,
637 * they either are always read-only args, or require
640 g_warning ("gtk_arg_fill_retloc(): unsupported argument type `%s'",
641 gtk_type_name (arg->type));