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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "gtkobject.h"
20 #include "gtktypeutils.h"
23 typedef struct _GtkTypeNode GtkTypeNode;
30 GtkTypeInfo type_info;
36 static void gtk_type_insert (guint parent_type,
38 GtkTypeInfo *type_info);
39 static void gtk_type_class_init (GtkTypeNode *node);
40 static void gtk_type_object_init (GtkTypeNode *node,
42 static guint gtk_type_hash (GtkType *key);
43 static gint gtk_type_compare (GtkType *a,
45 static guint gtk_type_name_hash (const char *key);
46 static gint gtk_type_name_compare (const char *a,
48 static void gtk_type_init_builtin_types ();
51 static int initialize = TRUE;
52 static GHashTable *type_hash_table = NULL;
53 static GHashTable *name_hash_table = NULL;
61 g_assert (sizeof (GtkType) >= 4);
64 type_hash_table = g_hash_table_new ((GHashFunc) gtk_type_hash,
65 (GCompareFunc) gtk_type_compare);
66 name_hash_table = g_hash_table_new ((GHashFunc) gtk_type_name_hash,
67 (GCompareFunc) gtk_type_name_compare);
68 gtk_type_init_builtin_types ();
73 gtk_type_unique (GtkType parent_type,
74 GtkTypeInfo *type_info)
76 static guint next_seqno = 0;
79 g_return_val_if_fail (type_info != NULL, 0);
85 if (parent_type == GTK_TYPE_INVALID)
86 new_type = next_seqno;
88 new_type = GTK_TYPE_MAKE (GTK_FUNDAMENTAL_TYPE (parent_type), next_seqno);
89 gtk_type_insert (parent_type, new_type, type_info);
95 gtk_type_name (GtkType type)
102 node = g_hash_table_lookup (type_hash_table, &type);
105 return node->type_info.type_name;
111 gtk_type_from_name (const gchar *name)
118 node = g_hash_table_lookup (name_hash_table, (gpointer) name);
127 gtk_type_parent (GtkType type)
134 node = g_hash_table_lookup (type_hash_table, &type);
136 if (node && node->parent)
137 return node->parent->type;
143 gtk_type_class (GtkType type)
150 node = g_hash_table_lookup (type_hash_table, &type);
151 g_return_val_if_fail (node != NULL, NULL);
153 if (node->init_class)
154 gtk_type_class_init (node);
160 gtk_type_new (GtkType type)
168 node = g_hash_table_lookup (type_hash_table, &type);
169 g_return_val_if_fail (node != NULL, NULL);
171 object = g_new0 (guchar, node->type_info.object_size);
172 ((GtkObject*) object)->klass = gtk_type_class (type);
173 gtk_type_object_init (node, object);
179 gtk_type_describe_heritage (GtkType type)
187 node = g_hash_table_lookup (type_hash_table, &type);
198 if (node->type_info.type_name)
199 g_print ("%s\n", node->type_info.type_name);
201 g_print ("<unnamed type>\n");
208 gtk_type_describe_tree (GtkType type,
211 static gint indent = 0;
221 node = g_hash_table_lookup (type_hash_table, &type);
223 for (i = 0; i < indent; i++)
226 if (node->type_info.type_name)
227 g_print ("%s", node->type_info.type_name);
229 g_print ("<unnamed type>");
232 g_print (" ( %d bytes )\n", node->type_info.object_size);
239 children = node->children;
242 child = children->data;
243 children = children->next;
245 gtk_type_describe_tree (child->type, show_size);
252 gtk_type_is_a (GtkType type,
260 node = g_hash_table_lookup (type_hash_table, &type);
264 if (node->type == is_a_type)
273 gtk_type_set_arg (GtkObject *object,
282 node = g_hash_table_lookup (type_hash_table, &type);
284 if (node->type_info.arg_func)
285 (* node->type_info.arg_func) (object, arg);
289 gtk_type_insert (GtkType parent_type,
291 GtkTypeInfo *type_info)
296 parent = g_hash_table_lookup (type_hash_table, &parent_type);
298 node = g_new (GtkTypeNode, 1);
300 node->init_class = TRUE;
302 node->type_info = *type_info;
303 node->parent = parent;
304 node->children = NULL;
307 node->parent->children = g_list_append (node->parent->children, node);
309 g_hash_table_insert (type_hash_table, &node->type, node);
310 g_hash_table_insert (name_hash_table, node->type_info.type_name, node);
314 gtk_type_class_init (GtkTypeNode *node)
316 GtkObjectClass *object_class;
318 if (node->init_class)
320 node->init_class = FALSE;
321 node->klass = g_new0 (guchar, node->type_info.class_size);
325 if (node->parent->init_class)
326 gtk_type_class_init (node->parent);
328 memcpy (node->klass, node->parent->klass, node->parent->type_info.class_size);
331 object_class = node->klass;
332 object_class->type = node->type;
334 if (node->type_info.class_init_func)
335 (* node->type_info.class_init_func) (node->klass);
340 gtk_type_object_init (GtkTypeNode *node,
344 gtk_type_object_init (node->parent, object);
346 if (node->type_info.object_init_func)
347 (* node->type_info.object_init_func) (object);
351 gtk_type_hash (GtkType *key)
353 return GTK_TYPE_SEQNO (*key);
357 gtk_type_compare (GtkType *a,
360 g_return_val_if_fail(a != NULL && b != NULL, 0);
365 gtk_type_name_hash (const char *key)
371 result += (result << 3) + *key++;
377 gtk_type_name_compare (const char *a,
380 return (strcmp (a, b) == 0);
384 gtk_type_register_builtin (char *name,
389 info.type_name = name;
390 info.object_size = info.class_size = 0;
391 info.class_init_func = NULL;
392 info.object_init_func = NULL;
393 info.arg_func = NULL;
395 return gtk_type_unique (parent, &info);
398 extern void gtk_object_init_type ();
400 GtkType gtk_type_builtins[GTK_TYPE_NUM_BUILTINS];
403 gtk_type_init_builtin_types ()
405 /* GTK_TYPE_INVALID has typeid 0. The first type id returned by
406 gtk_type_unique is 1, which is GTK_TYPE_NONE. And so on. */
411 } fundamental_info[] = {
412 { GTK_TYPE_NONE, "void" },
413 { GTK_TYPE_CHAR, "char" },
414 { GTK_TYPE_BOOL, "bool" },
415 { GTK_TYPE_INT, "int" },
416 { GTK_TYPE_UINT, "uint" },
417 { GTK_TYPE_LONG, "long" },
418 { GTK_TYPE_ULONG, "ulong" },
419 { GTK_TYPE_FLOAT, "float" },
420 { GTK_TYPE_STRING, "string" },
421 { GTK_TYPE_ENUM, "enum" },
422 { GTK_TYPE_FLAGS, "flags" },
423 { GTK_TYPE_BOXED, "boxed" },
424 { GTK_TYPE_FOREIGN, "foreign" },
425 { GTK_TYPE_CALLBACK, "callback" },
426 { GTK_TYPE_ARGS, "args" },
428 { GTK_TYPE_POINTER, "pointer" },
429 { GTK_TYPE_SIGNAL, "signal" },
430 { GTK_TYPE_C_CALLBACK, "c_callback" }
437 #include "gtktypebuiltins.c"
443 for (i = 0; i < sizeof (fundamental_info)/sizeof(fundamental_info[0]); i++)
446 id = gtk_type_register_builtin (fundamental_info[i].name,
448 g_assert (id == fundamental_info[i].enum_id);
451 gtk_object_init_type ();
453 for (i = 0; builtin_info[i].name; i++)
455 gtk_type_builtins[i] =
456 gtk_type_register_builtin (builtin_info[i].name,
457 builtin_info[i].parent);