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 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.
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.
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.
20 #include "gtkobject.h"
21 #include "gtktypeutils.h"
24 typedef struct _GtkTypeNode GtkTypeNode;
31 GtkTypeInfo type_info;
37 static void gtk_type_insert (guint parent_type,
39 GtkTypeInfo *type_info);
40 static void gtk_type_class_init (GtkTypeNode *node);
41 static void gtk_type_object_init (GtkTypeNode *node,
43 static guint gtk_type_hash (GtkType *key);
44 static gint gtk_type_compare (GtkType *a,
46 static guint gtk_type_name_hash (const char *key);
47 static gint gtk_type_name_compare (const char *a,
49 static void gtk_type_init_builtin_types (void);
52 static int initialize = TRUE;
53 static GHashTable *type_hash_table = NULL;
54 static GHashTable *name_hash_table = NULL;
62 g_assert (sizeof (GtkType) >= 4);
65 type_hash_table = g_hash_table_new ((GHashFunc) gtk_type_hash,
66 (GCompareFunc) gtk_type_compare);
67 name_hash_table = g_hash_table_new ((GHashFunc) gtk_type_name_hash,
68 (GCompareFunc) gtk_type_name_compare);
69 gtk_type_init_builtin_types ();
74 gtk_type_unique (GtkType parent_type,
75 GtkTypeInfo *type_info)
77 static guint next_seqno = 0;
80 g_return_val_if_fail (type_info != NULL, 0);
86 if (parent_type == GTK_TYPE_INVALID)
87 new_type = next_seqno;
89 new_type = GTK_TYPE_MAKE (GTK_FUNDAMENTAL_TYPE (parent_type), next_seqno);
90 gtk_type_insert (parent_type, new_type, type_info);
96 gtk_type_name (GtkType type)
103 node = g_hash_table_lookup (type_hash_table, &type);
106 return node->type_info.type_name;
112 gtk_type_from_name (const gchar *name)
119 node = g_hash_table_lookup (name_hash_table, (gpointer) name);
128 gtk_type_parent (GtkType type)
135 node = g_hash_table_lookup (type_hash_table, &type);
137 if (node && node->parent)
138 return node->parent->type;
144 gtk_type_class (GtkType type)
151 node = g_hash_table_lookup (type_hash_table, &type);
152 g_return_val_if_fail (node != NULL, NULL);
154 if (node->init_class)
155 gtk_type_class_init (node);
161 gtk_type_new (GtkType type)
169 node = g_hash_table_lookup (type_hash_table, &type);
170 g_return_val_if_fail (node != NULL, NULL);
172 object = g_new0 (guchar, node->type_info.object_size);
173 ((GtkObject*) object)->klass = gtk_type_class (type);
174 gtk_type_object_init (node, object);
180 gtk_type_describe_heritage (GtkType type)
188 node = g_hash_table_lookup (type_hash_table, &type);
199 if (node->type_info.type_name)
200 g_print ("%s\n", node->type_info.type_name);
202 g_print ("<unnamed type>\n");
209 gtk_type_describe_tree (GtkType type,
212 static gint indent = 0;
222 node = g_hash_table_lookup (type_hash_table, &type);
224 for (i = 0; i < indent; i++)
227 if (node->type_info.type_name)
228 g_print ("%s", node->type_info.type_name);
230 g_print ("<unnamed type>");
233 g_print (" ( %d bytes )\n", node->type_info.object_size);
240 children = node->children;
243 child = children->data;
244 children = children->next;
246 gtk_type_describe_tree (child->type, show_size);
253 gtk_type_is_a (GtkType type,
261 node = g_hash_table_lookup (type_hash_table, &type);
265 if (node->type == is_a_type)
274 gtk_type_get_arg (GtkObject *object,
281 g_return_if_fail (object != NULL);
282 g_return_if_fail (arg != NULL);
287 node = g_hash_table_lookup (type_hash_table, &type);
289 if (node && node->type_info.arg_get_func)
290 (* node->type_info.arg_get_func) (object, arg, arg_id);
292 arg->type = GTK_TYPE_INVALID;
296 gtk_type_set_arg (GtkObject *object,
303 g_return_if_fail (object != NULL);
304 g_return_if_fail (arg != NULL);
309 node = g_hash_table_lookup (type_hash_table, &type);
311 if (node && node->type_info.arg_set_func)
312 (* node->type_info.arg_set_func) (object, arg, arg_id);
316 gtk_arg_copy (GtkArg *src_arg,
319 g_return_val_if_fail (src_arg != NULL, NULL);
323 dest_arg = g_new0 (GtkArg, 1);
324 dest_arg->name = src_arg->name;
327 dest_arg->type = src_arg->type;
328 dest_arg->d = src_arg->d;
330 if (src_arg->type == GTK_TYPE_STRING)
331 dest_arg->d.string_data = g_strdup (src_arg->d.string_data);
337 gtk_type_insert (GtkType parent_type,
339 GtkTypeInfo *type_info)
344 parent = g_hash_table_lookup (type_hash_table, &parent_type);
346 node = g_new (GtkTypeNode, 1);
348 node->init_class = TRUE;
350 node->type_info = *type_info;
351 node->parent = parent;
352 node->children = NULL;
355 node->parent->children = g_list_append (node->parent->children, node);
357 g_hash_table_insert (type_hash_table, &node->type, node);
358 g_hash_table_insert (name_hash_table, node->type_info.type_name, node);
362 gtk_type_class_init (GtkTypeNode *node)
364 GtkObjectClass *object_class;
366 if (node->init_class)
368 node->init_class = FALSE;
369 node->klass = g_new0 (guchar, node->type_info.class_size);
373 if (node->parent->init_class)
374 gtk_type_class_init (node->parent);
376 memcpy (node->klass, node->parent->klass, node->parent->type_info.class_size);
379 object_class = node->klass;
380 object_class->type = node->type;
381 object_class->signals = NULL;
382 object_class->nsignals = 0;
383 object_class->n_args = 0;
385 if (node->type_info.class_init_func)
386 (* node->type_info.class_init_func) (node->klass);
391 gtk_type_object_init (GtkTypeNode *node,
395 gtk_type_object_init (node->parent, object);
397 if (node->type_info.object_init_func)
398 (* node->type_info.object_init_func) (object);
402 gtk_type_hash (GtkType *key)
404 return GTK_TYPE_SEQNO (*key);
408 gtk_type_compare (GtkType *a,
411 g_return_val_if_fail(a != NULL && b != NULL, 0);
416 gtk_type_name_hash (const char *key)
422 result += (result << 3) + *key++;
428 gtk_type_name_compare (const char *a,
431 return (strcmp (a, b) == 0);
435 gtk_type_register_builtin (char *name,
440 info.type_name = name;
441 info.object_size = info.class_size = 0;
442 info.class_init_func = NULL;
443 info.object_init_func = NULL;
444 info.arg_set_func = NULL;
445 info.arg_get_func = NULL;
447 return gtk_type_unique (parent, &info);
450 extern void gtk_object_init_type (void);
452 GtkType gtk_type_builtins[GTK_TYPE_NUM_BUILTINS];
455 gtk_type_init_builtin_types ()
457 /* GTK_TYPE_INVALID has typeid 0. The first type id returned by
458 gtk_type_unique is 1, which is GTK_TYPE_NONE. And so on. */
463 } fundamental_info[] = {
464 { GTK_TYPE_NONE, "void" },
465 { GTK_TYPE_CHAR, "char" },
466 { GTK_TYPE_BOOL, "bool" },
467 { GTK_TYPE_INT, "int" },
468 { GTK_TYPE_UINT, "uint" },
469 { GTK_TYPE_LONG, "long" },
470 { GTK_TYPE_ULONG, "ulong" },
471 { GTK_TYPE_FLOAT, "float" },
472 { GTK_TYPE_DOUBLE, "double" },
473 { GTK_TYPE_STRING, "string" },
474 { GTK_TYPE_ENUM, "enum" },
475 { GTK_TYPE_FLAGS, "flags" },
476 { GTK_TYPE_BOXED, "boxed" },
477 { GTK_TYPE_FOREIGN, "foreign" },
478 { GTK_TYPE_CALLBACK, "callback" },
479 { GTK_TYPE_ARGS, "args" },
481 { GTK_TYPE_POINTER, "pointer" },
482 { GTK_TYPE_SIGNAL, "signal" },
483 { GTK_TYPE_C_CALLBACK, "c_callback" }
490 #include "gtktypebuiltins.c"
496 for (i = 0; i < sizeof (fundamental_info)/sizeof(fundamental_info[0]); i++)
499 id = gtk_type_register_builtin (fundamental_info[i].name,
501 g_assert (id == fundamental_info[i].enum_id);
504 gtk_object_init_type ();
506 for (i = 0; builtin_info[i].name; i++)
508 gtk_type_builtins[i] =
509 gtk_type_register_builtin (builtin_info[i].name,
510 builtin_info[i].parent);