]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktypeutils.c
Add check for db2html
[~andy/gtk] / gtk / gtktypeutils.c
index b27b9c6dd497bd0f75511031fcc235909f135efc..f607c5a217b4612d83e6718cb1a85e991e026cf1 100644 (file)
  *
  * 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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 ();
 
-  node = g_hash_table_lookup (name_hash_table, (gpointer) name);
+/*
+ * 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/. 
+ */
 
-  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;
+  GTypeInfo tinfo = { 0, };
 
-  if (initialize)
-    gtk_type_init ();
+  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);
 
-  node = g_hash_table_lookup (type_hash_table, &type);
+  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;
 
-  if (node && node->parent)
-    return node->parent->type;
-
-  return 0;
+  return g_type_register_static (parent_type, gtkinfo->type_name, &tinfo);
 }
 
 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_type_create_instance (type);
 
   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");
+/* includes for various places
+ * with enum definitions
+ */
+#include "makeenums.h"
+/* type variable declarations
+ */
+#include "gtktypebuiltins_vars.c"
+GType GTK_TYPE_IDENTIFIER = 0;
+#include "gtktypebuiltins_evals.c"       /* enum value definition arrays */
 
-      node = node->parent;
-    }
-}
+/* Hack to communicate with GLib object debugging for now
+ */
+extern gboolean glib_debug_objects;
 
 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)
+gtk_type_init (void)
 {
-  GtkTypeNode *node;
-
-  if (initialize)
-    gtk_type_init ();
-
-  node = g_hash_table_lookup (type_hash_table, &type);
-
-  while (node)
+  static gboolean initialized = FALSE;
+  
+  if (!initialized)
     {
-      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 ();
-
-  node = g_hash_table_lookup (type_hash_table, &type);
-
-  if (node && node->type_info.arg_get_func)
-    (* node->type_info.arg_get_func) (object, arg, arg_id);
-  else
-    arg->type = GTK_TYPE_INVALID;
-}
-
-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);
-}
-
-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 const struct {
+       GtkType type_id;
+       gchar *name;
+      } fundamental_info[] = {
+       { GTK_TYPE_POINTER,     "gpointer" },
+       { GTK_TYPE_SIGNAL,      "GtkSignal" },
+      };
+      static struct {
+       gchar              *type_name;
+       GtkType            *type_id;
+       GtkType             parent;
+       const GtkEnumValue *values;
+      } builtin_info[GTK_TYPE_N_BUILTINS + 1] = {
+#include "gtktypebuiltins_ids.c"       /* type entries */
+       { NULL }
+      };
+      GTypeFundamentalInfo finfo = { 0, };
+      GTypeInfo tinfo = { 0, };
+      GtkType type_id;
+      guint i;
+
+      initialized = TRUE;
+
+      glib_debug_objects = gtk_debug_flags & GTK_DEBUG_OBJECTS != 0;
+      
+      /* initialize GLib type system
+       */
+      g_type_init ();
+      
+      /* GTK_TYPE_OBJECT
+       */
+      gtk_object_get_type ();
+
+      /* compatibility fundamentals
+       */
+      for (i = 0; i < sizeof (fundamental_info) / sizeof (fundamental_info[0]); i++)
+       {
+         type_id = g_type_register_fundamental (fundamental_info[i].type_id,
+                                                fundamental_info[i].name,
+                                                &tinfo,
+                                                &finfo);
+         g_assert (type_id == fundamental_info[i].type_id);
+       }
 
-static void
-gtk_type_class_init (GtkTypeNode *node)
-{
-  GtkObjectClass *object_class;
+      /* GTK_TYPE_IDENTIFIER
+       */
+      GTK_TYPE_IDENTIFIER = g_type_register_static (G_TYPE_STRING, "GtkIdentifier", &tinfo);
 
-  if (node->init_class)
-    {
-      node->init_class = FALSE;
-      node->klass = g_new0 (guchar, node->type_info.class_size);
+      /* GTK_TYPE_BOXED
+       */
+      finfo.type_flags = G_TYPE_FLAG_DERIVABLE;
+      type_id = g_type_register_fundamental (GTK_TYPE_BOXED, "GtkBoxed", &tinfo, &finfo);
+      g_assert (type_id == GTK_TYPE_BOXED);
 
-      if (node->parent)
+      /* 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].values);
+         else if (builtin_info[i].parent == G_TYPE_FLAGS)
+           type_id = g_flags_register_static (builtin_info[i].type_name, builtin_info[i].values);
+         else if (builtin_info[i].parent == GTK_TYPE_BOXED)
+           type_id = g_type_register_static (GTK_TYPE_BOXED, builtin_info[i].type_name, &tinfo);
+         else
+           g_assert_not_reached ();
+
+         *builtin_info[i].type_id = type_id;
        }
-
-      object_class = node->klass;
-      object_class->type = node->type;
-      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;
 }