* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-#include <string.h>
-#include "gtkobject.h"
-#include "gtktypeutils.h"
-
-
-typedef struct _GtkTypeNode GtkTypeNode;
-
-struct _GtkTypeNode
-{
- GtkType type;
- gint init_class;
- gpointer klass;
- GtkTypeInfo type_info;
- GtkTypeNode *parent;
- GList *children;
-};
-
-
-static void gtk_type_insert (guint parent_type,
- GtkType type,
- GtkTypeInfo *type_info);
-static void gtk_type_class_init (GtkTypeNode *node);
-static void gtk_type_object_init (GtkTypeNode *node,
- gpointer object);
-static guint gtk_type_hash (GtkType *key);
-static gint gtk_type_compare (GtkType *a,
- GtkType *b);
-static guint gtk_type_name_hash (const char *key);
-static gint gtk_type_name_compare (const char *a,
- const char *b);
-static void gtk_type_init_builtin_types (void);
-
-
-static int initialize = TRUE;
-static GHashTable *type_hash_table = NULL;
-static GHashTable *name_hash_table = NULL;
-
-
-void
-gtk_type_init ()
-{
- if (initialize)
- {
- g_assert (sizeof (GtkType) >= 4);
-
- initialize = FALSE;
- type_hash_table = g_hash_table_new ((GHashFunc) gtk_type_hash,
- (GCompareFunc) gtk_type_compare);
- name_hash_table = g_hash_table_new ((GHashFunc) gtk_type_name_hash,
- (GCompareFunc) gtk_type_name_compare);
- gtk_type_init_builtin_types ();
- }
-}
-
-GtkType
-gtk_type_unique (GtkType parent_type,
- GtkTypeInfo *type_info)
-{
- static guint next_seqno = 0;
- GtkType new_type;
-
- g_return_val_if_fail (type_info != NULL, 0);
- if (initialize)
- gtk_type_init ();
-
- next_seqno++;
- if (parent_type == GTK_TYPE_INVALID)
- new_type = next_seqno;
- else
- new_type = GTK_TYPE_MAKE (GTK_FUNDAMENTAL_TYPE (parent_type), next_seqno);
- gtk_type_insert (parent_type, new_type, type_info);
-
- return new_type;
-}
-
-gchar*
-gtk_type_name (GtkType type)
-{
- GtkTypeNode *node;
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
-
- if (node)
- return node->type_info.type_name;
-
- return NULL;
-}
-
-GtkType
-gtk_type_from_name (const gchar *name)
-{
- GtkTypeNode *node;
-
- if (initialize)
- gtk_type_init ();
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
- node = g_hash_table_lookup (name_hash_table, (gpointer) name);
+#include <string.h> /* strcmp */
- if (node)
- return node->type;
+#include "gtktypeutils.h"
+#include "gtkobject.h"
- return 0;
-}
+/* --- functions --- */
GtkType
-gtk_type_parent (GtkType type)
+gtk_type_unique (GtkType parent_type,
+ const GtkTypeInfo *gtkinfo)
{
- GtkTypeNode *node;
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
-
- if (node && node->parent)
- return node->parent->type;
-
- return 0;
+ GTypeInfo tinfo = { 0, };
+
+ g_return_val_if_fail (GTK_TYPE_IS_OBJECT (parent_type), 0);
+ g_return_val_if_fail (gtkinfo != NULL, 0);
+ g_return_val_if_fail (gtkinfo->type_name != NULL, 0);
+ g_return_val_if_fail (g_type_from_name (gtkinfo->type_name) == 0, 0);
+
+ tinfo.class_size = gtkinfo->class_size;
+ tinfo.base_init = gtkinfo->base_class_init_func;
+ tinfo.base_finalize = NULL;
+ tinfo.class_init = (GClassInitFunc) gtkinfo->class_init_func;
+ tinfo.class_finalize = NULL;
+ tinfo.class_data = NULL;
+ tinfo.instance_size = gtkinfo->object_size;
+ tinfo.n_preallocs = 0;
+ tinfo.instance_init = gtkinfo->object_init_func;
+
+ return g_type_register_static (parent_type, gtkinfo->type_name, &tinfo, 0);
}
gpointer
gtk_type_class (GtkType type)
{
- GtkTypeNode *node;
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
- g_return_val_if_fail (node != NULL, NULL);
+ static GQuark quark_static_class = 0;
+ gpointer class;
+
+ if (!G_TYPE_IS_ENUM (type) && !G_TYPE_IS_FLAGS (type))
+ g_return_val_if_fail (GTK_TYPE_IS_OBJECT (type), NULL);
+
+ /* ok, this is a bit ugly, GLib reference counts classes,
+ * and gtk_type_class() used to always return static classes.
+ * while we coud be faster with just peeking the glib class
+ * for the normal code path, we can't be sure that that
+ * class stays around (someone else might be holding the
+ * reference count and is going to drop it later). so to
+ * ensure that Gtk actually holds a static reference count
+ * on the class, we use GType qdata to store referenced
+ * classes, and only return those.
+ */
+
+ class = g_type_get_qdata (type, quark_static_class);
+ if (!class)
+ {
+ if (!quark_static_class)
+ quark_static_class = g_quark_from_static_string ("GtkStaticTypeClass");
- if (node->init_class)
- gtk_type_class_init (node);
+ class = g_type_class_ref (type);
+ g_assert (class != NULL);
+ g_type_set_qdata (type, quark_static_class, class);
+ }
- return node->klass;
+ return class;
}
gpointer
gtk_type_new (GtkType type)
{
- GtkTypeNode *node;
gpointer object;
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
- g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (GTK_TYPE_IS_OBJECT (type), NULL);
- object = g_new0 (guchar, node->type_info.object_size);
- ((GtkObject*) object)->klass = gtk_type_class (type);
- gtk_type_object_init (node, object);
+ object = g_object_new (type, NULL);
return object;
}
-void
-gtk_type_describe_heritage (GtkType type)
-{
- GtkTypeNode *node;
- gint first;
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
- first = TRUE;
-
- while (node)
- {
- if (first)
- {
- first = FALSE;
- g_print ("is a ");
- }
-
- if (node->type_info.type_name)
- g_print ("%s\n", node->type_info.type_name);
- else
- g_print ("<unnamed type>\n");
-
- node = node->parent;
- }
-}
-
-void
-gtk_type_describe_tree (GtkType type,
- gint show_size)
-{
- static gint indent = 0;
- GtkTypeNode *node;
- GtkTypeNode *child;
- GList *children;
- gint old_indent;
- gint i;
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
-
- for (i = 0; i < indent; i++)
- g_print (" ");
-
- if (node->type_info.type_name)
- g_print ("%s", node->type_info.type_name);
- else
- g_print ("<unnamed type>");
-
- if (show_size)
- g_print (" ( %d bytes )\n", node->type_info.object_size);
- else
- g_print ("\n");
-
- old_indent = indent;
- indent += 4;
-
- children = node->children;
- while (children)
- {
- child = children->data;
- children = children->next;
-
- gtk_type_describe_tree (child->type, show_size);
- }
-
- indent = old_indent;
-}
-
-gint
-gtk_type_is_a (GtkType type,
- GtkType is_a_type)
-{
- GtkTypeNode *node;
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
-
- while (node)
- {
- if (node->type == is_a_type)
- return TRUE;
- node = node->parent;
- }
-
- return FALSE;
-}
-
-void
-gtk_type_get_arg (GtkObject *object,
- GtkType type,
- GtkArg *arg,
- guint arg_id)
-{
- GtkTypeNode *node;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (arg != NULL);
-
- if (initialize)
- gtk_type_init ();
+/* includes for various places
+ * with enum definitions
+ */
+#define GTK_ENABLE_BROKEN
+#include "makeenums.h"
+/* type variable declarations
+ */
+#include "gtktypebuiltins_vars.c"
+GType GTK_TYPE_IDENTIFIER = 0;
+#include "gtktypebuiltins_evals.c" /* enum value definition arrays */
- node = g_hash_table_lookup (type_hash_table, &type);
+/* Hack to communicate with GLib object debugging for now
+ */
+#ifdef G_OS_WIN32
+#define IMPORT __declspec(dllimport)
+#else
+#define IMPORT
+#endif
- if (node && node->type_info.arg_get_func)
- (* node->type_info.arg_get_func) (object, arg, arg_id);
- else
- arg->type = GTK_TYPE_INVALID;
-}
+#include <gtk.h> /* for gtktypebuiltins_ids.c */
+#include <gdk.h> /* gtktypebuiltins_ids.c */
void
-gtk_type_set_arg (GtkObject *object,
- GtkType type,
- GtkArg *arg,
- guint arg_id)
-{
- GtkTypeNode *node;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (arg != NULL);
-
- if (initialize)
- gtk_type_init ();
-
- node = g_hash_table_lookup (type_hash_table, &type);
-
- if (node && node->type_info.arg_set_func)
- (* node->type_info.arg_set_func) (object, arg, arg_id);
-}
-
-GtkArg*
-gtk_arg_copy (GtkArg *src_arg,
- GtkArg *dest_arg)
+gtk_type_init (GTypeDebugFlags debug_flags)
{
- g_return_val_if_fail (src_arg != NULL, NULL);
-
- if (!dest_arg)
+ static gboolean initialized = FALSE;
+
+ if (!initialized)
{
- dest_arg = g_new0 (GtkArg, 1);
- dest_arg->name = src_arg->name;
- }
-
- dest_arg->type = src_arg->type;
- dest_arg->d = src_arg->d;
-
- if (src_arg->type == GTK_TYPE_STRING)
- dest_arg->d.string_data = g_strdup (src_arg->d.string_data);
-
- return dest_arg;
-}
-
-static void
-gtk_type_insert (GtkType parent_type,
- GtkType type,
- GtkTypeInfo *type_info)
-{
- GtkTypeNode *node;
- GtkTypeNode *parent;
-
- parent = g_hash_table_lookup (type_hash_table, &parent_type);
-
- node = g_new (GtkTypeNode, 1);
- node->type = type;
- node->init_class = TRUE;
- node->klass = NULL;
- node->type_info = *type_info;
- node->parent = parent;
- node->children = NULL;
-
- if (node->parent)
- node->parent->children = g_list_append (node->parent->children, node);
-
- g_hash_table_insert (type_hash_table, &node->type, node);
- g_hash_table_insert (name_hash_table, node->type_info.type_name, node);
-}
-
-static void
-gtk_type_class_init (GtkTypeNode *node)
-{
- GtkObjectClass *object_class;
-
- if (node->init_class)
- {
- node->init_class = FALSE;
- node->klass = g_new0 (guchar, node->type_info.class_size);
-
- if (node->parent)
+ static struct {
+ gchar *type_name;
+ GtkType *type_id;
+ GtkType parent;
+ gconstpointer pointer1;
+ gpointer pointer2;
+ } builtin_info[GTK_TYPE_N_BUILTINS + 1] = {
+#include "gtktypebuiltins_ids.c" /* type entries */
+ { NULL }
+ };
+ GTypeInfo tinfo = { 0, };
+ guint i;
+
+ initialized = TRUE;
+
+ /* initialize GLib type system
+ */
+ g_type_init (debug_flags);
+
+ /* GTK_TYPE_OBJECT
+ */
+ gtk_object_get_type ();
+
+ /* GTK_TYPE_IDENTIFIER
+ */
+ GTK_TYPE_IDENTIFIER = g_type_register_static (G_TYPE_STRING, "GtkIdentifier", &tinfo, 0);
+
+ /* enums and flags
+ */
+ for (i = 0; i < GTK_TYPE_N_BUILTINS; i++)
{
- if (node->parent->init_class)
- gtk_type_class_init (node->parent);
-
- memcpy (node->klass, node->parent->klass, node->parent->type_info.class_size);
+ GtkType type_id = 0;
+
+ if (builtin_info[i].parent == G_TYPE_ENUM)
+ type_id = g_enum_register_static (builtin_info[i].type_name, builtin_info[i].pointer1);
+ else if (builtin_info[i].parent == G_TYPE_FLAGS)
+ type_id = g_flags_register_static (builtin_info[i].type_name, builtin_info[i].pointer1);
+ else if (builtin_info[i].parent == GTK_TYPE_BOXED)
+ {
+ static const gchar *copy_types[] = {
+ "GtkSelectionData", "GtkBorder", "GtkTextIter", "PangoTabArray",
+ "PangoFontDescription", "GtkTreeIter", "GtkTreePath", "GtkRequisition"
+ };
+ gboolean ref_counted = TRUE;
+ guint j;
+
+ for (j = 0; j < sizeof (copy_types) / sizeof (copy_types[0]); j++)
+ if (strcmp (copy_types[j], builtin_info[i].type_name) == 0)
+ {
+ ref_counted = FALSE;
+ break;
+ }
+ if (builtin_info[i].pointer1 && builtin_info[i].pointer2)
+ type_id = g_boxed_type_register_static (builtin_info[i].type_name,
+ NULL,
+ builtin_info[i].pointer1,
+ builtin_info[i].pointer2,
+ ref_counted);
+ else
+ type_id = g_type_register_static (GTK_TYPE_BOXED, builtin_info[i].type_name, &tinfo, 0);
+ }
+ else
+ g_assert_not_reached ();
+
+ *builtin_info[i].type_id = type_id;
}
-
- object_class = node->klass;
- object_class->type = node->type;
- object_class->signals = NULL;
- object_class->nsignals = 0;
- object_class->n_args = 0;
-
- if (node->type_info.class_init_func)
- (* node->type_info.class_init_func) (node->klass);
}
}
-static void
-gtk_type_object_init (GtkTypeNode *node,
- gpointer object)
+GtkEnumValue*
+gtk_type_enum_get_values (GtkType enum_type)
{
- if (node->parent)
- gtk_type_object_init (node->parent, object);
-
- if (node->type_info.object_init_func)
- (* node->type_info.object_init_func) (object);
-}
+ GEnumClass *class;
-static guint
-gtk_type_hash (GtkType *key)
-{
- return GTK_TYPE_SEQNO (*key);
+ g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
+
+ class = gtk_type_class (enum_type);
+
+ return class->values;
}
-static gint
-gtk_type_compare (GtkType *a,
- GtkType *b)
+GtkFlagValue*
+gtk_type_flags_get_values (GtkType flags_type)
{
- g_return_val_if_fail(a != NULL && b != NULL, 0);
- return (*a == *b);
-}
+ GFlagsClass *class;
-static guint
-gtk_type_name_hash (const char *key)
-{
- guint result;
+ g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
- result = 0;
- while (*key)
- result += (result << 3) + *key++;
+ class = gtk_type_class (flags_type);
- return result;
+ return class->values;
}
-static gint
-gtk_type_name_compare (const char *a,
- const char *b)
+GtkEnumValue*
+gtk_type_enum_find_value (GtkType enum_type,
+ const gchar *value_name)
{
- return (strcmp (a, b) == 0);
-}
+ GtkEnumValue *value;
+ GEnumClass *class;
-static GtkType
-gtk_type_register_builtin (char *name,
- GtkType parent)
-{
- GtkTypeInfo info;
+ g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
+ g_return_val_if_fail (value_name != NULL, NULL);
- info.type_name = name;
- info.object_size = info.class_size = 0;
- info.class_init_func = NULL;
- info.object_init_func = NULL;
- info.arg_set_func = NULL;
- info.arg_get_func = NULL;
+ class = gtk_type_class (enum_type);
+ value = g_enum_get_value_by_name (class, value_name);
+ if (!value)
+ value = g_enum_get_value_by_nick (class, value_name);
- return gtk_type_unique (parent, &info);
+ return value;
}
-extern void gtk_object_init_type (void);
-
-GtkType gtk_type_builtins[GTK_TYPE_NUM_BUILTINS];
-
-static void
-gtk_type_init_builtin_types ()
+GtkFlagValue*
+gtk_type_flags_find_value (GtkType flags_type,
+ const gchar *value_name)
{
- /* GTK_TYPE_INVALID has typeid 0. The first type id returned by
- gtk_type_unique is 1, which is GTK_TYPE_NONE. And so on. */
-
- static struct {
- GtkType enum_id;
- gchar *name;
- } fundamental_info[] = {
- { GTK_TYPE_NONE, "void" },
- { GTK_TYPE_CHAR, "char" },
- { GTK_TYPE_BOOL, "bool" },
- { GTK_TYPE_INT, "int" },
- { GTK_TYPE_UINT, "uint" },
- { GTK_TYPE_LONG, "long" },
- { GTK_TYPE_ULONG, "ulong" },
- { GTK_TYPE_FLOAT, "float" },
- { GTK_TYPE_DOUBLE, "double" },
- { GTK_TYPE_STRING, "string" },
- { GTK_TYPE_ENUM, "enum" },
- { GTK_TYPE_FLAGS, "flags" },
- { GTK_TYPE_BOXED, "boxed" },
- { GTK_TYPE_FOREIGN, "foreign" },
- { GTK_TYPE_CALLBACK, "callback" },
- { GTK_TYPE_ARGS, "args" },
-
- { GTK_TYPE_POINTER, "pointer" },
- { GTK_TYPE_SIGNAL, "signal" },
- { GTK_TYPE_C_CALLBACK, "c_callback" }
- };
-
- static struct {
- char *name;
- GtkType parent;
- } builtin_info[] = {
-#include "gtktypebuiltins.c"
- { NULL }
- };
-
- int i;
-
- for (i = 0; i < sizeof (fundamental_info)/sizeof(fundamental_info[0]); i++)
- {
- GtkType id;
- id = gtk_type_register_builtin (fundamental_info[i].name,
- GTK_TYPE_INVALID);
- g_assert (id == fundamental_info[i].enum_id);
- }
+ GtkFlagValue *value;
+ GFlagsClass *class;
- gtk_object_init_type ();
+ g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
+ g_return_val_if_fail (value_name != NULL, NULL);
- for (i = 0; builtin_info[i].name; i++)
- {
- gtk_type_builtins[i] =
- gtk_type_register_builtin (builtin_info[i].name,
- builtin_info[i].parent);
- }
+ class = gtk_type_class (flags_type);
+ value = g_flags_get_value_by_name (class, value_name);
+ if (!value)
+ value = g_flags_get_value_by_nick (class, value_name);
+
+ return value;
}