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 (void);
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_get_arg (GtkObject *object,
280 g_return_if_fail (object != NULL);
281 g_return_if_fail (arg != NULL);
286 node = g_hash_table_lookup (type_hash_table, &type);
288 if (node && node->type_info.arg_get_func)
289 (* node->type_info.arg_get_func) (object, arg, arg_id);
291 arg->type = GTK_TYPE_INVALID;
295 gtk_type_set_arg (GtkObject *object,
302 g_return_if_fail (object != NULL);
303 g_return_if_fail (arg != NULL);
308 node = g_hash_table_lookup (type_hash_table, &type);
310 if (node && node->type_info.arg_set_func)
311 (* node->type_info.arg_set_func) (object, arg, arg_id);
315 gtk_arg_copy (GtkArg *src_arg,
318 g_return_val_if_fail (src_arg != NULL, NULL);
322 dest_arg = g_new0 (GtkArg, 1);
323 dest_arg->name = src_arg->name;
326 dest_arg->type = src_arg->type;
327 dest_arg->d = src_arg->d;
329 if (src_arg->type == GTK_TYPE_STRING)
330 dest_arg->d.string_data = g_strdup (src_arg->d.string_data);
336 gtk_type_insert (GtkType parent_type,
338 GtkTypeInfo *type_info)
343 parent = g_hash_table_lookup (type_hash_table, &parent_type);
345 node = g_new (GtkTypeNode, 1);
347 node->init_class = TRUE;
349 node->type_info = *type_info;
350 node->parent = parent;
351 node->children = NULL;
354 node->parent->children = g_list_append (node->parent->children, node);
356 g_hash_table_insert (type_hash_table, &node->type, node);
357 g_hash_table_insert (name_hash_table, node->type_info.type_name, node);
361 gtk_type_class_init (GtkTypeNode *node)
363 GtkObjectClass *object_class;
365 if (node->init_class)
367 node->init_class = FALSE;
368 node->klass = g_new0 (guchar, node->type_info.class_size);
372 if (node->parent->init_class)
373 gtk_type_class_init (node->parent);
375 memcpy (node->klass, node->parent->klass, node->parent->type_info.class_size);
378 object_class = node->klass;
379 object_class->type = node->type;
380 object_class->signals = NULL;
381 object_class->nsignals = 0;
382 object_class->n_args = 0;
384 if (node->type_info.class_init_func)
385 (* node->type_info.class_init_func) (node->klass);
390 gtk_type_object_init (GtkTypeNode *node,
394 gtk_type_object_init (node->parent, object);
396 if (node->type_info.object_init_func)
397 (* node->type_info.object_init_func) (object);
401 gtk_type_hash (GtkType *key)
403 return GTK_TYPE_SEQNO (*key);
407 gtk_type_compare (GtkType *a,
410 g_return_val_if_fail(a != NULL && b != NULL, 0);
415 gtk_type_name_hash (const char *key)
421 result += (result << 3) + *key++;
427 gtk_type_name_compare (const char *a,
430 return (strcmp (a, b) == 0);
434 gtk_type_register_builtin (char *name,
439 info.type_name = name;
440 info.object_size = info.class_size = 0;
441 info.class_init_func = NULL;
442 info.object_init_func = NULL;
443 info.arg_set_func = NULL;
444 info.arg_get_func = NULL;
446 return gtk_type_unique (parent, &info);
449 extern void gtk_object_init_type (void);
451 GtkType gtk_type_builtins[GTK_TYPE_NUM_BUILTINS];
454 gtk_type_init_builtin_types ()
456 /* GTK_TYPE_INVALID has typeid 0. The first type id returned by
457 gtk_type_unique is 1, which is GTK_TYPE_NONE. And so on. */
462 } fundamental_info[] = {
463 { GTK_TYPE_NONE, "void" },
464 { GTK_TYPE_CHAR, "char" },
465 { GTK_TYPE_BOOL, "bool" },
466 { GTK_TYPE_INT, "int" },
467 { GTK_TYPE_UINT, "uint" },
468 { GTK_TYPE_LONG, "long" },
469 { GTK_TYPE_ULONG, "ulong" },
470 { GTK_TYPE_FLOAT, "float" },
471 { GTK_TYPE_DOUBLE, "double" },
472 { GTK_TYPE_STRING, "string" },
473 { GTK_TYPE_ENUM, "enum" },
474 { GTK_TYPE_FLAGS, "flags" },
475 { GTK_TYPE_BOXED, "boxed" },
476 { GTK_TYPE_FOREIGN, "foreign" },
477 { GTK_TYPE_CALLBACK, "callback" },
478 { GTK_TYPE_ARGS, "args" },
480 { GTK_TYPE_POINTER, "pointer" },
481 { GTK_TYPE_SIGNAL, "signal" },
482 { GTK_TYPE_C_CALLBACK, "c_callback" }
489 #include "gtktypebuiltins.c"
495 for (i = 0; i < sizeof (fundamental_info)/sizeof(fundamental_info[0]); i++)
498 id = gtk_type_register_builtin (fundamental_info[i].name,
500 g_assert (id == fundamental_info[i].enum_id);
503 gtk_object_init_type ();
505 for (i = 0; builtin_info[i].name; i++)
507 gtk_type_builtins[i] =
508 gtk_type_register_builtin (builtin_info[i].name,
509 builtin_info[i].parent);