summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Janik <timj@gtk.org>2000-05-12 15:22:31 +0000
committerTim Janik <timj@src.gnome.org>2000-05-12 15:22:31 +0000
commit397ad5881e972da23eccca1b20bbcfe2e8648f11 (patch)
tree392cc662981c0430ccd314af5347f306a01e4725
parent5947f92d3a45c428ceeb3fe933c96a4c7f7d3a8b (diff)
downloadglib-397ad5881e972da23eccca1b20bbcfe2e8648f11.tar.gz
add reserved fundamental ids for gtk types (for transition time). added
Fri May 5 01:15:48 2000 Tim Janik <timj@gtk.org> * gtype.h: add reserved fundamental ids for gtk types (for transition time). added G_TYPE_FUNDAMENTAL_MAX for gtk. Mon Apr 17 20:45:50 2000 Tim Janik <timj@gtk.org> * glib-gobject.c (g_object_base_class_finalize): oops, don't unset n_params prior to destructing them. Tue Apr 11 04:28:10 2000 Tim Janik <timj@gtk.org> * fixed a couple of bugs in the initial parameter/object implementations, after getting beast running on GObject and GValue. Fri Apr 7 04:27:49 2000 Tim Janik <timj@gtk.org> * glib-gobject.[hc]: completed parameter set/get implementations, along with asyncronous parameter changed notification queue. Sun Apr 2 04:54:36 2000 Tim Janik <timj@gtk.org> * glib-gobject.[hc]: GObject implementation, that is facilities for setting/getting quarked data and reference counting. * glib-gparamspecs.[hc]: first actuall parameter implementations for GLib, so far we have: char, uchar, bool, int, uint, long, ulong, enum, flags, float, double, string and object. each of these GParamSpecs is a new instantiatable type in its own respect, so the .c file derives 13 new types from G_TYPE_PARAM and defines over 50 (*2) conversion facilities. * glib-gvaluecollector.h: generic varargs handling stubs for GParamSpecs, private header file (does get installed for inclusion into user code though). * glib-gvalue.[hc]: GValue functionality implementation. * glib-gparam.[hc]: basis GParamSpec implementation for the virtual base type G_TYPE_PARAM. * glib-genums.[hc]: enum/flags type implementation, based on bseenum.[hc]. * glib-extra.[hc]: GLib additions, including 1.3 compatibility routines and various other functions, from string manipulation over list manipulation up to a unix signal GSource. * glib-gtype.[hc]: GLib Type System implementation, heavily based on BSE's dynamic type system.
-rw-r--r--gobject/ChangeLog50
-rw-r--r--gobject/Makefile.am83
-rw-r--r--gobject/genums.c306
-rw-r--r--gobject/genums.h118
-rw-r--r--gobject/gobject-query.c219
-rw-r--r--gobject/gobject.c751
-rw-r--r--gobject/gobject.h165
-rw-r--r--gobject/gparam.c318
-rw-r--r--gobject/gparam.h186
-rw-r--r--gobject/gparamspecs.c2004
-rw-r--r--gobject/gparamspecs.h335
-rw-r--r--gobject/gtype.c1825
-rw-r--r--gobject/gtype.h304
-rw-r--r--gobject/gvalue.c374
-rw-r--r--gobject/gvalue.h92
-rw-r--r--gobject/gvaluecollector.h174
16 files changed, 7304 insertions, 0 deletions
diff --git a/gobject/ChangeLog b/gobject/ChangeLog
new file mode 100644
index 000000000..5f3717e84
--- /dev/null
+++ b/gobject/ChangeLog
@@ -0,0 +1,50 @@
+Fri May 5 01:15:48 2000 Tim Janik <timj@gtk.org>
+
+ * gtype.h: add reserved fundamental ids for gtk types (for transition
+ time). added G_TYPE_FUNDAMENTAL_MAX for gtk.
+
+Mon Apr 17 20:45:50 2000 Tim Janik <timj@gtk.org>
+
+ * glib-gobject.c (g_object_base_class_finalize): oops, don't unset
+ n_params prior to destructing them.
+
+Tue Apr 11 04:28:10 2000 Tim Janik <timj@gtk.org>
+
+ * fixed a couple of bugs in the initial parameter/object
+ implementations, after getting beast running on GObject and GValue.
+
+Fri Apr 7 04:27:49 2000 Tim Janik <timj@gtk.org>
+
+ * glib-gobject.[hc]: completed parameter set/get implementations,
+ along with asyncronous parameter changed notification queue.
+
+Sun Apr 2 04:54:36 2000 Tim Janik <timj@gtk.org>
+
+ * glib-gobject.[hc]: GObject implementation, that is facilities
+ for setting/getting quarked data and reference counting.
+
+ * glib-gparamspecs.[hc]: first actuall parameter implementations
+ for GLib, so far we have: char, uchar, bool, int, uint, long,
+ ulong, enum, flags, float, double, string and object. each of these
+ GParamSpecs is a new instantiatable type in its own respect,
+ so the .c file derives 13 new types from G_TYPE_PARAM and
+ defines over 50 (*2) conversion facilities.
+
+ * glib-gvaluecollector.h: generic varargs handling stubs for
+ GParamSpecs, private header file (does get installed for
+ inclusion into user code though).
+
+ * glib-gvalue.[hc]: GValue functionality implementation.
+
+ * glib-gparam.[hc]: basis GParamSpec implementation for
+ the virtual base type G_TYPE_PARAM.
+
+ * glib-genums.[hc]: enum/flags type implementation, based on
+ bseenum.[hc].
+
+ * glib-extra.[hc]: GLib additions, including 1.3 compatibility
+ routines and various other functions, from string manipulation
+ over list manipulation up to a unix signal GSource.
+
+ * glib-gtype.[hc]: GLib Type System implementation, heavily
+ based on BSE's dynamic type system.
diff --git a/gobject/Makefile.am b/gobject/Makefile.am
new file mode 100644
index 000000000..80ac2de46
--- /dev/null
+++ b/gobject/Makefile.am
@@ -0,0 +1,83 @@
+# GObject - GLib Type, Object, Parameter and Signal Library
+# Copyright (C) 1997,98,99,2000 Tim Janik and Red Hat, Inc.
+#
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS =
+
+INCLUDES = -I$(top_srcdir) @GLIB_DEBUG_FLAGS@
+
+# libraries to compile and install
+lib_LTLIBRARIES = libgobject.la
+
+# provide g_logv() domain
+DEFS += -DG_LOG_DOMAIN=g_log_domain_gobject
+
+# libtool stuff: set version and export symbols for resolving
+libgobjectincludedir = $(includedir)/gobject
+libgobject_la_LDFLAGS = @STRIP_BEGIN@ \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -release $(LT_RELEASE) \
+ -export-dynamic \
+@STRIP_END@
+libgobject_la_LIBADD = # $(libglib)
+
+#
+# setup source file variables
+#
+# GObject header files for public installation (non-generated)
+gobject_public_h_sources = @STRIP_BEGIN@ \
+ gvalue.h \
+ gparam.h \
+ gparamspecs.h \
+ genums.h \
+ gobject.h \
+ gtype.h \
+ gvaluecollector.h \
+@STRIP_END@
+# private GObject header files
+gobject_private_h_sources = @STRIP_BEGIN@ \
+@STRIP_END@
+
+# GObject C sources to build the library from
+gobject_c_sources = @STRIP_BEGIN@ \
+ gvalue.c \
+ gparam.c \
+ gparamspecs.c \
+ genums.c \
+ gobject.c \
+ gtype.c \
+@STRIP_END@
+
+# non-header sources (headers should be specified in the above variables)
+# that don't serve as direct make target sources, i.e. they don't have
+# their own .lo rules and don't get publically installed
+gobject_extra_sources = @STRIP_BEGIN@ \
+@STRIP_END@
+
+#
+# setup GObject sources and their dependancies
+#
+gobject_h_sources = $(gobject_private_h_sources) $(gobject_public_h_sources) # $(gobject_built_public_sources)
+libgobjectinclude_HEADERS = $(gobject_public_h_sources) # $(gobject_built_public_sources)
+libgobject_la_SOURCES = $(gobject_c_sources)
+MAINTAINERCLEANFILES += # $(gobject_built_public_sources) $(gobject_built_sources)
+EXTRA_HEADERS +=
+EXTRA_DIST += $(gobject_private_h_sources)
+EXTRA_DIST += $(gobject_extra_sources) # $(gobject_built_sources) $(gobject_built_public_sources)
+
+#
+# programs to compile and install
+#
+bin_PROGRAMS = gobject-query
+# source files
+gobject_query_SOURCES = gobject-query.c
+# link programs against libgobject
+progs_LDADD = ../libglib.la libgobject.la
+gobject_query_LDADD = $(progs_LDADD)
+
+#
+# auxillary files
+#
+EXTRA_DIST += \
+ TODO
diff --git a/gobject/genums.c b/gobject/genums.c
new file mode 100644
index 000000000..3fcadb53f
--- /dev/null
+++ b/gobject/genums.c
@@ -0,0 +1,306 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "genums.h"
+
+
+/* --- prototypes --- */
+extern void g_enum_types_init (void);
+static void g_enum_class_init (GEnumClass *class,
+ gpointer class_data);
+static void g_flags_class_init (GFlagsClass *class,
+ gpointer class_data);
+
+
+/* --- functions --- */
+void
+g_enum_types_init (void) /* sync with glib-gtype.c */
+{
+ static gboolean initialized = FALSE;
+ static const GTypeFundamentalInfo finfo = {
+ G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE,
+ 0 /* n_collect_bytes */,
+ NULL /* GTypeParamCollector */,
+ };
+ static GTypeInfo info = {
+ 0 /* class_size */,
+ NULL /* base_init */,
+ NULL /* base_finalize */,
+ NULL /* class_init */,
+ NULL /* class_finalize */,
+ NULL /* class_data */,
+ };
+ GType type;
+
+ g_return_if_fail (initialized == FALSE);
+ initialized = TRUE;
+
+ /* G_TYPE_ENUM
+ */
+ info.class_size = sizeof (GEnumClass);
+ type = g_type_register_fundamental (G_TYPE_ENUM, "GEnum", &finfo, &info);
+ g_assert (type == G_TYPE_ENUM);
+
+ /* G_TYPE_FLAGS
+ */
+ info.class_size = sizeof (GFlagsClass);
+ type = g_type_register_fundamental (G_TYPE_FLAGS, "GFlags", &finfo, &info);
+ g_assert (type == G_TYPE_FLAGS);
+}
+
+GType
+g_enum_register_static (const gchar *name,
+ const GEnumValue *const_static_values)
+{
+ GTypeInfo enum_type_info = {
+ sizeof (GEnumClass),
+ NULL /* base_init */,
+ NULL /* base_finalize */,
+ (GClassInitFunc) g_enum_class_init,
+ NULL /* class_finalize */,
+ NULL /* class_data */,
+ };
+ GType type;
+
+ g_return_val_if_fail (name != NULL, 0);
+ g_return_val_if_fail (const_static_values != NULL, 0);
+
+ enum_type_info.class_data = const_static_values;
+
+ type = g_type_register_static (G_TYPE_ENUM, name, &enum_type_info);
+
+ return type;
+}
+
+GType
+g_flags_register_static (const gchar *name,
+ const GFlagsValue *const_static_values)
+{
+ GTypeInfo flags_type_info = {
+ sizeof (GFlagsClass),
+ NULL /* base_init */,
+ NULL /* base_finalize */,
+ (GClassInitFunc) g_flags_class_init,
+ NULL /* class_finalize */,
+ NULL /* class_data */,
+ };
+ GType type;
+
+ g_return_val_if_fail (name != NULL, 0);
+ g_return_val_if_fail (const_static_values != NULL, 0);
+
+ flags_type_info.class_data = const_static_values;
+
+ type = g_type_register_static (G_TYPE_FLAGS, name, &flags_type_info);
+
+ return type;
+}
+
+void
+g_enum_complete_type_info (GType g_enum_type,
+ GTypeInfo *info,
+ const GEnumValue *const_values)
+{
+ g_return_if_fail (G_TYPE_IS_ENUM (g_enum_type));
+ g_return_if_fail (info != NULL);
+ g_return_if_fail (const_values != NULL);
+
+ info->class_size = sizeof (GEnumClass);
+ info->base_init = NULL;
+ info->base_finalize = NULL;
+ info->class_init = (GClassInitFunc) g_enum_class_init;
+ info->class_finalize = NULL;
+ info->class_data = const_values;
+}
+
+void
+g_flags_complete_type_info (GType g_flags_type,
+ GTypeInfo *info,
+ const GFlagsValue *const_values)
+{
+ g_return_if_fail (G_TYPE_IS_FLAGS (g_flags_type));
+ g_return_if_fail (info != NULL);
+ g_return_if_fail (const_values != NULL);
+
+ info->class_size = sizeof (GFlagsClass);
+ info->base_init = NULL;
+ info->base_finalize = NULL;
+ info->class_init = (GClassInitFunc) g_flags_class_init;
+ info->class_finalize = NULL;
+ info->class_data = const_values;
+}
+
+static void
+g_enum_class_init (GEnumClass *class,
+ gpointer class_data)
+{
+ g_return_if_fail (G_IS_ENUM_CLASS (class));
+
+ class->minimum = 0;
+ class->maximum = 0;
+ class->n_values = 0;
+ class->values = class_data;
+
+ if (class->values)
+ {
+ GEnumValue *values;
+
+ class->minimum = class->values->value;
+ class->maximum = class->values->value;
+ for (values = class->values; values->value_name; values++)
+ {
+ class->minimum = MIN (class->minimum, values->value);
+ class->maximum = MAX (class->maximum, values->value);
+ class->n_values++;
+ }
+ }
+}
+
+static void
+g_flags_class_init (GFlagsClass *class,
+ gpointer class_data)
+{
+ g_return_if_fail (G_IS_FLAGS_CLASS (class));
+
+ class->mask = 0;
+ class->n_values = 0;
+ class->values = class_data;
+
+ if (class->values)
+ {
+ GFlagsValue *values;
+
+ for (values = class->values; values->value_name; values++)
+ {
+ class->mask |= values->value;
+ class->n_values++;
+ }
+ }
+}
+
+GEnumValue*
+g_enum_get_value_by_name (GEnumClass *enum_class,
+ const gchar *name)
+{
+ g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ if (enum_class->n_values)
+ {
+ GEnumValue *enum_value;
+
+ for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
+ if (strcmp (name, enum_value->value_name) == 0)
+ return enum_value;
+ }
+
+ return NULL;
+}
+
+GFlagsValue*
+g_flags_get_value_by_name (GFlagsClass *flags_class,
+ const gchar *name)
+{
+ g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ if (flags_class->n_values)
+ {
+ GFlagsValue *flags_value;
+
+ for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
+ if (strcmp (name, flags_value->value_name) == 0)
+ return flags_value;
+ }
+
+ return NULL;
+}
+
+GEnumValue*
+g_enum_get_value_by_nick (GEnumClass *enum_class,
+ const gchar *nick)
+{
+ g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
+ g_return_val_if_fail (nick != NULL, NULL);
+
+ if (enum_class->n_values)
+ {
+ GEnumValue *enum_value;
+
+ for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
+ if (enum_value->value_nick && strcmp (nick, enum_value->value_nick) == 0)
+ return enum_value;
+ }
+
+ return NULL;
+}
+
+GFlagsValue*
+g_flags_get_value_by_nick (GFlagsClass *flags_class,
+ const gchar *nick)
+{
+ g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
+ g_return_val_if_fail (nick != NULL, NULL);
+
+ if (flags_class->n_values)
+ {
+ GFlagsValue *flags_value;
+
+ for (flags_value = flags_class->values; flags_value->value_nick; flags_value++)
+ if (flags_value->value_nick && strcmp (nick, flags_value->value_nick) == 0)
+ return flags_value;
+ }
+
+ return NULL;
+}
+
+GEnumValue*
+g_enum_get_value (GEnumClass *enum_class,
+ gint value)
+{
+ g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
+
+ if (enum_class->n_values)
+ {
+ GEnumValue *enum_value;
+
+ for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
+ if (enum_value->value == value)
+ return enum_value;
+ }
+
+ return NULL;
+}
+
+GFlagsValue*
+g_flags_get_first_value (GFlagsClass *flags_class,
+ guint value)
+{
+ g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
+
+ if (flags_class->n_values)
+ {
+ GFlagsValue *flags_value;
+
+ for (flags_value = flags_class->values; flags_value->value_name; flags_value++)
+ if ((flags_value->value & value) > 0)
+ return flags_value;
+ }
+
+ return NULL;
+}
diff --git a/gobject/genums.h b/gobject/genums.h
new file mode 100644
index 000000000..4e90c6717
--- /dev/null
+++ b/gobject/genums.h
@@ -0,0 +1,118 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ */
+#ifndef __G_ENUMS_H__
+#define __G_ENUMS_H__
+
+#include <gobject/gtype.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define G_TYPE_IS_ENUM(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_ENUM)
+#define G_ENUM_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define G_ENUM_NAME(class) (g_type_name (G_ENUM_TYPE (class)))
+#define G_ENUM_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_ENUM, GEnumClass))
+#define G_IS_ENUM_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_ENUM))
+#define G_TYPE_IS_FLAGS(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_FLAGS)
+#define G_FLAGS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define G_FLAGS_NAME(class) (g_type_name (G_FLAGS_TYPE (class)))
+#define G_FLAGS_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_FLAGS, GFlagsClass))
+#define G_IS_FLAGS_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_FLAGS))
+
+
+/* --- enum/flag values & classes --- */
+typedef struct _GEnumClass GEnumClass;
+typedef struct _GFlagsClass GFlagsClass;
+typedef struct _GEnumValue GEnumValue;
+typedef struct _GFlagsValue GFlagsValue;
+struct _GEnumClass
+{
+ GTypeClass g_type_class;
+
+ gint minimum;
+ gint maximum;
+ guint n_values;
+ GEnumValue *values;
+};
+struct _GFlagsClass
+{
+ GTypeClass g_type_class;
+
+ guint mask;
+ guint n_values;
+ GFlagsValue *values;
+};
+struct _GEnumValue
+{
+ gint value;
+ gchar *value_name;
+ gchar *value_nick;
+};
+struct _GFlagsValue
+{
+ guint value;
+ gchar *value_name;
+ gchar *value_nick;
+};
+
+
+/* --- prototypes --- */
+GEnumValue* g_enum_get_value (GEnumClass *enum_class,
+ gint value);
+GEnumValue* g_enum_get_value_by_name (GEnumClass *enum_class,
+ const gchar *name);
+GEnumValue* g_enum_get_value_by_nick (GEnumClass *enum_class,
+ const gchar *nick);
+GFlagsValue* g_flags_get_first_value (GFlagsClass *flags_class,
+ guint value);
+GFlagsValue* g_flags_get_value_by_name (GFlagsClass *flags_class,
+ const gchar *name);
+GFlagsValue* g_flags_get_value_by_nick (GFlagsClass *flags_class,
+ const gchar *nick);
+
+
+/* --- registration functions --- */
+/* const_static_values is a NULL terminated array of enum/flags
+ * values that is taken over!
+ */
+GType g_enum_register_static (const gchar *name,
+ const GEnumValue *const_static_values);
+GType g_flags_register_static (const gchar *name,
+ const GFlagsValue *const_static_values);
+/* functions to complete the type information
+ * for enums/flags implemented by plugins
+ */
+void g_enum_complete_type_info (GType g_enum_type,
+ GTypeInfo *info,
+ const GEnumValue *const_values);
+void g_flags_complete_type_info (GType g_flags_type,
+ GTypeInfo *info,
+ const GFlagsValue *const_values);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_ENUMS_H__ */
diff --git a/gobject/gobject-query.c b/gobject/gobject-query.c
new file mode 100644
index 000000000..6ee1b496f
--- /dev/null
+++ b/gobject/gobject-query.c
@@ -0,0 +1,219 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 <glib-object.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static gchar *indent_inc = NULL;
+static guint spacing = 1;
+static FILE *f_out = NULL;
+static GType root = 0;
+static gboolean recursion = TRUE;
+
+#if 0
+# define O_SPACE "\\as"
+# define O_ESPACE " "
+# define O_BRANCH "\\aE"
+# define O_VLINE "\\al"
+# define O_LLEAF "\\aL"
+# define O_KEY_FILL "_"
+#else
+# define O_SPACE " "
+# define O_ESPACE ""
+# define O_BRANCH "+"
+# define O_VLINE "|"
+# define O_LLEAF "`"
+# define O_KEY_FILL "_"
+#endif
+
+static void
+show_nodes (GType type,
+ GType sibling,
+ const gchar *indent)
+{
+ GType *children;
+ guint i;
+
+ if (!type)
+ return;
+
+ children = g_type_children (type, NULL);
+
+ if (type != root)
+ for (i = 0; i < spacing; i++)
+ fprintf (f_out, "%s%s\n", indent, O_VLINE);
+
+ fprintf (f_out, "%s%s%s%s",
+ indent,
+ sibling ? O_BRANCH : (type != root ? O_LLEAF : O_SPACE),
+ O_ESPACE,
+ g_type_name (type));
+
+ for (i = strlen (g_type_name (type)); i <= strlen (indent_inc); i++)
+ fputs (O_KEY_FILL, f_out);
+
+ fputc ('\n', f_out);
+
+ if (children && recursion)
+ {
+ gchar *new_indent;
+ GType *child;
+
+ if (sibling)
+ new_indent = g_strconcat (indent, O_VLINE, indent_inc, NULL);
+ else
+ new_indent = g_strconcat (indent, O_SPACE, indent_inc, NULL);
+
+ for (child = children; *child; child++)
+ show_nodes (child[0], child[1], new_indent);
+
+ g_free (new_indent);
+ }
+
+ g_free (children);
+}
+
+static gint
+help (gchar *arg)
+{
+ fprintf (stderr, "usage: query <qualifier> [-r <type>] [-{i|b} \"\"] [-s #] [-{h|x|y}]\n");
+ fprintf (stderr, " -r specifiy root type\n");
+ fprintf (stderr, " -n don't descend type tree\n");
+ fprintf (stderr, " -h guess what ;)\n");
+ fprintf (stderr, " -b specifiy indent string\n");
+ fprintf (stderr, " -i specifiy incremental indent string\n");
+ fprintf (stderr, " -s specifiy line spacing\n");
+ fprintf (stderr, "qualifiers:\n");
+ fprintf (stderr, " froots iterate over fundamental roots\n");
+ fprintf (stderr, " tree print BSE type tree\n");
+
+ return arg != NULL;
+}
+
+int
+main (gint argc,
+ gchar *argv[])
+{
+ gboolean gen_froots = 0;
+ gboolean gen_tree = 0;
+ guint i;
+ gchar *iindent = "";
+
+ f_out = stdout;
+
+ g_type_init ();
+
+ root = G_TYPE_OBJECT;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp ("-s", argv[i]) == 0)
+ {
+ i++;
+ if (i < argc)
+ spacing = atoi (argv[i]);
+ }
+ else if (strcmp ("-i", argv[i]) == 0)
+ {
+ i++;
+ if (i < argc)
+ {
+ char *p;
+ guint n;
+
+ p = argv[i];
+ while (*p)
+ p++;
+ n = p - argv[i];
+ indent_inc = g_new (gchar, n * strlen (O_SPACE) + 1);
+ *indent_inc = 0;
+ while (n)
+ {
+ n--;
+ strcpy (indent_inc, O_SPACE);
+ }
+ }
+ }
+ else if (strcmp ("-b", argv[i]) == 0)
+ {
+ i++;
+ if (i < argc)
+ iindent = argv[i];
+ }
+ else if (strcmp ("-r", argv[i]) == 0)
+ {
+ i++;
+ if (i < argc)
+ root = g_type_from_name (argv[i]);
+ }
+ else if (strcmp ("-n", argv[i]) == 0)
+ {
+ recursion = FALSE;
+ }
+ else if (strcmp ("froots", argv[i]) == 0)
+ {
+ gen_froots = 1;
+ }
+ else if (strcmp ("tree", argv[i]) == 0)
+ {
+ gen_tree = 1;
+ }
+ else if (strcmp ("-h", argv[i]) == 0)
+ {
+ return help (NULL);
+ }
+ else if (strcmp ("--help", argv[i]) == 0)
+ {
+ return help (NULL);
+ }
+ else
+ return help (argv[i]);
+ }
+ if (!gen_froots && !gen_tree)
+ return help (argv[i-1]);
+
+ if (!indent_inc)
+ {
+ indent_inc = g_new (gchar, strlen (O_SPACE) + 1);
+ *indent_inc = 0;
+ strcpy (indent_inc, O_SPACE);
+ strcpy (indent_inc, O_SPACE);
+ strcpy (indent_inc, O_SPACE);
+ }
+
+ if (gen_tree)
+ show_nodes (root, 0, iindent);
+ if (gen_froots)
+ {
+ root = ~0;
+ for (i = 0; i < 256; i++)
+ {
+ gchar *name = g_type_name (i);
+
+ if (name)
+ show_nodes (i, 0, iindent);
+ }
+ }
+
+ return 0;
+}
diff --git a/gobject/gobject.c b/gobject/gobject.c
new file mode 100644
index 000000000..8d54b349a
--- /dev/null
+++ b/gobject/gobject.c
@@ -0,0 +1,751 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "gobject.h"
+
+
+#include "gvalue.h"
+#include "gvaluecollector.h"
+
+
+#define DEBUG_OBJECTS
+
+
+/* --- macros --- */
+#define PARAM_SPEC_PARAM_ID(pspec) (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_param_id)))
+
+
+/* --- prototypes --- */
+extern void g_object_type_init (void);
+static void g_object_base_class_init (GObjectClass *class);
+static void g_object_base_class_finalize (GObjectClass *class);
+static void g_object_do_class_init (GObjectClass *class);
+static void g_object_do_init (GObject *object);
+static void g_object_do_queue_param_changed (GObject *object,
+ GParamSpec *pspec);
+static void g_object_do_dispatch_param_changed (GObject *object,
+ GParamSpec *pspec);
+static void g_object_last_unref (GObject *object);
+static void g_object_do_shutdown (GObject *object);
+static void g_object_do_finalize (GObject *object);
+
+
+/* --- variables --- */
+static GQuark quark_param_id = 0;
+static GQuark quark_param_changed_queue = 0;
+static GHashTable *param_spec_hash_table = NULL;
+
+
+/* --- functions --- */
+#ifdef DEBUG_OBJECTS
+static guint debug_objects_count = 0;
+static GHashTable *debug_objects_ht = NULL;
+static void
+debug_objects_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GObject *object = value;
+
+ g_message ("[%p] stale %s\tref_count=%u",
+ object,
+ G_OBJECT_TYPE_NAME (object),
+ object->ref_count);
+}
+static void
+debug_objects_atexit (void)
+{
+ if (debug_objects_ht)
+ {
+ g_message ("stale GObjects: %u", debug_objects_count);
+ g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
+ }
+}
+#endif DEBUG_OBJECTS
+
+void
+g_object_type_init (void) /* sync with glib-gtype.c */
+{
+ static gboolean initialized = FALSE;
+ static const GTypeFundamentalInfo finfo = {
+ G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
+ 0 /* n_collect_bytes */,
+ NULL /* GTypeParamCollector */,
+ };
+ static GTypeInfo info = {
+ sizeof (GObjectClass),
+ (GBaseInitFunc) g_object_base_class_init,
+ (GBaseFinalizeFunc) g_object_base_class_finalize,
+ (GClassInitFunc) g_object_do_class_init,
+ NULL /* class_destroy */,
+ NULL /* class_data */,
+ sizeof (GObject),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) g_object_do_init,
+ };
+ GType type;
+
+ g_return_if_fail (initialized == FALSE);
+ initialized = TRUE;
+
+ /* G_TYPE_OBJECT
+ */
+ type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &finfo, &info);
+ g_assert (type == G_TYPE_OBJECT);
+
+#ifdef DEBUG_OBJECTS
+ g_atexit (debug_objects_atexit);
+#endif DEBUG_OBJECTS
+}
+
+static void
+g_object_base_class_init (GObjectClass *class)
+{
+ /* reset instance specific fields and methods that don't get inherited */
+ class->n_param_specs = 0;
+ class->param_specs = NULL;
+ class->get_param = NULL;
+ class->set_param = NULL;
+}
+
+static void
+g_object_base_class_finalize (GObjectClass *class)
+{
+ guint i;
+
+ g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
+
+ for (i = 0; i < class->n_param_specs; i++)
+ {
+ GParamSpec *pspec = class->param_specs[i];
+
+ g_param_spec_hash_table_remove (param_spec_hash_table, pspec);
+ g_param_spec_set_qdata (pspec, quark_param_id, NULL);
+ g_param_spec_unref (pspec);
+ }
+ class->n_param_specs = 0;
+ g_free (class->param_specs);
+ class->param_specs = NULL;
+}
+
+static void
+g_object_do_class_init (GObjectClass *class)
+{
+ quark_param_id = g_quark_from_static_string ("glib-object-param-id");
+ quark_param_changed_queue = g_quark_from_static_string ("glib-object-param-changed-queue");
+ param_spec_hash_table = g_param_spec_hash_table_new ();
+
+ class->queue_param_changed = g_object_do_queue_param_changed;
+ class->dispatch_param_changed = g_object_do_dispatch_param_changed;
+ class->shutdown = g_object_do_shutdown;
+ class->finalize = g_object_do_finalize;
+}
+
+void
+g_object_class_install_param (GObjectClass *class,
+ guint param_id,
+ GParamSpec *pspec /* 1 ref_count taken over */)
+{
+ guint i;
+
+ g_return_if_fail (G_IS_OBJECT_CLASS (class));
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ if (pspec->flags & G_PARAM_WRITABLE)
+ g_return_if_fail (class->set_param != NULL);
+ if (pspec->flags & G_PARAM_READABLE)
+ g_return_if_fail (class->get_param != NULL);
+ g_return_if_fail (param_id > 0);
+ g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
+
+ /* expensive paranoia checks ;( */
+ for (i = 0; i < class->n_param_specs; i++)
+ if (PARAM_SPEC_PARAM_ID (class->param_specs[i]) == param_id)
+ {
+ g_warning (G_STRLOC ": class `%s' already contains a parameter `%s' with id %u, "
+ "cannot install parameter `%s'",
+ G_OBJECT_CLASS_NAME (class),
+ class->param_specs[i]->name,
+ param_id,
+ pspec->name);
+ return;
+ }
+ if (g_object_class_find_param_spec (class, pspec->name))
+ {
+ g_warning (G_STRLOC ": class `%s' already contains a parameter named `%s'",
+ G_OBJECT_CLASS_NAME (class),
+ pspec->name);
+ return;
+ }
+
+ g_param_spec_set_qdata (pspec, quark_param_id, GUINT_TO_POINTER (param_id));
+ g_param_spec_hash_table_insert (param_spec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
+ i = class->n_param_specs++;
+ class->param_specs = g_renew (GParamSpec*, class->param_specs, class->n_param_specs);
+ class->param_specs[i] = pspec;
+}
+
+GParamSpec*
+g_object_class_find_param_spec (GObjectClass *class,
+ const gchar *param_name)
+{
+ g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
+ g_return_val_if_fail (param_name != NULL, NULL);
+
+ return g_param_spec_hash_table_lookup (param_spec_hash_table,
+ param_name,
+ G_OBJECT_CLASS_TYPE (class),
+ TRUE, NULL);
+}
+
+static void
+g_object_do_init (GObject *object)
+{
+ object->ref_count = 1;
+ object->qdata = NULL;
+
+#ifdef DEBUG_OBJECTS
+ if (!debug_objects_ht)
+ debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
+ debug_objects_count++;
+ g_hash_table_insert (debug_objects_ht, object, object);
+#endif DEBUG_OBJECTS
+}
+
+static void
+g_object_last_unref (GObject *object)
+{
+ g_return_if_fail (object->ref_count > 0);
+
+ if (object->ref_count == 1) /* may have been re-referenced meanwhile */
+ G_OBJECT_GET_CLASS (object)->shutdown (object);
+
+ object->ref_count -= 1;
+
+ if (object->ref_count == 0) /* may have been re-referenced meanwhile */
+ G_OBJECT_GET_CLASS (object)->finalize (object);
+}
+
+static void
+g_object_do_shutdown (GObject *object)
+{
+ /* this function needs to be always present for unconditional
+ * chaining, we also might add some code here later.
+ * beware though, subclasses may invoke shutdown() arbitrarily.
+ */
+}
+
+static void
+g_object_do_finalize (GObject *object)
+{
+ g_datalist_clear (&object->qdata);
+
+#ifdef DEBUG_OBJECTS
+ g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
+
+ g_hash_table_remove (debug_objects_ht, object);
+ debug_objects_count--;
+#endif DEBUG_OBJECTS
+
+ g_type_free_instance ((GTypeInstance*) object);
+}
+
+gpointer
+g_object_new (GType object_type,
+ const gchar *first_param_name,
+ ...)
+{
+ GObject *object;
+ va_list var_args;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+
+ va_start (var_args, first_param_name);
+ object = g_object_new_valist (object_type, first_param_name, var_args);
+ va_end (var_args);
+
+ return object;
+}
+
+gpointer
+g_object_new_valist (GType object_type,
+ const gchar *first_param_name,
+ va_list var_args)
+{
+ GObject *object;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+
+ object = (GObject*) g_type_create_instance (object_type);
+ if (first_param_name)
+ g_object_set_valist (object, first_param_name, var_args);
+
+ return object;
+}
+
+static void
+g_object_do_dispatch_param_changed (GObject *object,
+ GParamSpec *pspec)
+{
+ g_message ("NOTIFICATION: parameter `%s' changed on object `%s'",
+ pspec->name,
+ G_OBJECT_TYPE_NAME (object));
+}
+
+static gboolean
+notify_param_changed_handler (gpointer data)
+{
+ GObject *object;
+ GObjectClass *class;
+ GSList *slist;
+
+ /* FIXME: need GDK_THREADS lock */
+
+ object = G_OBJECT (data);
+ class = G_OBJECT_GET_CLASS (object);
+ slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
+
+ /* a reference count is still being held */
+
+ for (; slist; slist = slist->next)
+ if (slist->data)
+ {
+ GParamSpec *pspec = slist->data;
+
+ slist->data = NULL;
+ class->dispatch_param_changed (object, pspec);
+ }
+
+ g_datalist_id_set_data (&object->qdata, quark_param_changed_queue, NULL);
+
+ return FALSE;
+}
+
+static void
+g_object_do_queue_param_changed (GObject *object,
+ GParamSpec *pspec)
+{
+ GSList *slist, *last = NULL;
+
+ /* if this is a recursive call on this object (i.e. pspecs are queued
+ * for notification, while param_changed notification is currently in
+ * progress), we simply add them to the queue that is currently being
+ * dispatched. otherwise, we later dispatch parameter changed notification
+ * asyncronously from an idle handler untill the queue is completely empty.
+ */
+
+ slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
+ for (; slist; last = slist, slist = last->next)
+ if (slist->data == pspec)
+ return;
+
+ if (!last)
+ {
+ g_object_ref (object);
+ g_idle_add_full (G_NOTIFY_PRIORITY,
+ notify_param_changed_handler,
+ object,
+ (GDestroyNotify) g_object_unref);
+ g_object_set_qdata_full (object,
+ quark_param_changed_queue,
+ g_slist_prepend (NULL, pspec),
+ (GDestroyNotify) g_slist_free);
+ }
+ else
+ last->next = g_slist_prepend (NULL, pspec);
+}
+
+static inline void
+object_get_param (GObject *object,
+ GValue *value,
+ GParamSpec *pspec,
+ const gchar *trailer)
+{
+ GObjectClass *class;
+
+ g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type)); /* paranoid */
+
+ class = g_type_class_peek (pspec->owner_type);
+
+ class->get_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
+}
+
+static inline void
+object_set_param (GObject *object,
+ GValue *value,
+ GParamSpec *pspec,
+ const gchar *trailer)
+{
+ GObjectClass *class;
+
+ g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type)); /* paranoid */
+
+ class = g_type_class_peek (pspec->owner_type);
+
+ class->set_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
+
+ class->queue_param_changed (object, pspec);
+}
+
+void
+g_object_set_valist (GObject *object,
+ const gchar *first_param_name,
+ va_list var_args)
+{
+ const gchar *name;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ g_object_ref (object);
+
+ name = first_param_name;
+
+ while (name)
+ {
+ const gchar *trailer = NULL;
+ GValue value = { 0, };
+ GParamSpec *pspec;
+ gchar *error = NULL;
+
+ pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+ name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
+ if (!pspec)
+ {
+ g_warning ("%s: object class `%s' has no parameter named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (object),
+ name);
+ break;
+ }
+ if (!(pspec->flags & G_PARAM_WRITABLE))
+ {
+ g_warning ("%s: parameter `%s' of object class `%s' is not writable",
+ G_STRLOC,
+ pspec->name,
+ G_OBJECT_TYPE_NAME (object));
+ break;
+ }
+
+ g_value_init (&value, G_PARAM_SPEC_TYPE (pspec));
+
+ G_PARAM_COLLECT_VALUE (&value, pspec, var_args, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occoured
+ */
+ break;
+ }
+
+ object_set_param (object, &value, pspec, trailer);
+
+ g_value_unset (&value);
+
+ name = va_arg (var_args, gchar*);
+ }
+
+ g_object_unref (object);
+}
+
+void
+g_object_get_valist (GObject *object,
+ const gchar *first_param_name,
+ va_list var_args)
+{
+ const gchar *name;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ g_object_ref (object);
+
+ name = first_param_name;
+
+ while (name)
+ {
+ const gchar *trailer = NULL;
+ GValue value = { 0, };
+ GParamSpec *pspec;
+ gchar *error = NULL;
+
+ pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+ name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
+ if (!pspec)
+ {
+ g_warning ("%s: object class `%s' has no parameter named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (object),
+ name);
+ break;
+ }
+ if (!(pspec->flags & G_PARAM_READABLE))
+ {
+ g_warning ("%s: parameter `%s' of object class `%s' is not readable",
+ G_STRLOC,
+ pspec->name,
+ G_OBJECT_TYPE_NAME (object));
+ break;
+ }
+
+ g_value_init (&value, G_PARAM_SPEC_TYPE (pspec));
+
+ object_get_param (object, &value, pspec, trailer);
+
+ G_PARAM_LCOPY_VALUE (&value, pspec, var_args, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occoured
+ */
+ break;
+ }
+
+ g_value_unset (&value);
+
+ name = va_arg (var_args, gchar*);
+ }
+
+ g_object_unref (object);
+}
+
+void
+g_object_set (GObject *object,
+ const gchar *first_param_name,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ va_start (var_args, first_param_name);
+ g_object_set_valist (object, first_param_name, var_args);
+ va_end (var_args);
+}
+
+void
+g_object_get (GObject *object,
+ const gchar *first_param_name,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ va_start (var_args, first_param_name);
+ g_object_get_valist (object, first_param_name, var_args);
+ va_end (var_args);
+}
+
+void
+g_object_set_param (GObject *object,
+ const gchar *param_name,
+ const GValue *value)
+{
+ GParamSpec *pspec;
+ const gchar *trailer;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (param_name != NULL);
+ g_return_if_fail (G_IS_VALUE (value));
+
+ g_object_ref (object);
+
+ pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+ param_name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
+ if (!pspec)
+ g_warning ("%s: object class `%s' has no parameter named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (object),
+ param_name);
+ else
+ {
+ GValue tmp_value = { 0, };
+
+ /* provide a copy to work from and convert if necessary */
+ g_value_init (&tmp_value, G_PARAM_SPEC_TYPE (pspec));
+
+ if (!g_value_convert (value, &tmp_value) ||
+ g_value_validate (&tmp_value, pspec))
+ g_warning ("%s: can't convert `%s' value to parameter `%s' of type `%s'",
+ G_STRLOC,
+ G_VALUE_TYPE_NAME (value),
+ pspec->name,
+ G_PARAM_SPEC_TYPE_NAME (pspec));
+ else
+ object_set_param (object, &tmp_value, pspec, trailer);
+
+ g_value_unset (&tmp_value);
+ }
+
+ g_object_unref (object);
+}
+
+void
+g_object_get_param (GObject *object,
+ const gchar *param_name,
+ GValue *value)
+{
+ GParamSpec *pspec;
+ const gchar *trailer;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (param_name != NULL);
+ g_return_if_fail (G_IS_VALUE (value));
+
+ g_object_ref (object);
+
+ pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+ param_name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
+ if (!pspec)
+ g_warning ("%s: object class `%s' has no parameter named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (object),
+ param_name);
+ else
+ {
+ GValue tmp_value = { 0, };
+
+ /* provide a copy to work from and later convert if necessary, so
+ * _get_param() implementations need *not* care about freeing values
+ * that might be already set in the parameter to get.
+ * (though, at this point, GValue should exclusively be modified
+ * through the accessor functions anyways)
+ */
+ g_value_init (&tmp_value, G_PARAM_SPEC_TYPE (pspec));
+
+ if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_TYPE (pspec)))
+ g_warning ("%s: can't retrive parameter `%s' of type `%s' as value of type `%s'",
+ G_STRLOC,
+ pspec->name,
+ G_PARAM_SPEC_TYPE_NAME (pspec),
+ G_VALUE_TYPE_NAME (value));
+ else
+ {
+ object_get_param (object, &tmp_value, pspec, trailer);
+ g_value_convert (&tmp_value, value);
+ /* g_value_validate (value, pspec); */
+ }
+
+ g_value_unset (&tmp_value);
+ }
+
+ g_object_unref (object);
+}
+
+void
+g_object_queue_param_changed (GObject *object,
+ const gchar *param_name)
+{
+ GParamSpec *pspec;
+
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (param_name != NULL);
+
+ pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+ param_name,
+ G_OBJECT_TYPE (object),
+ TRUE, NULL);
+ if (!pspec)
+ g_warning ("%s: object class `%s' has no parameter named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (object),
+ param_name);
+ else
+ G_OBJECT_GET_CLASS (object)->queue_param_changed (object, pspec);
+}
+
+GObject*
+g_object_ref (GObject *object)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (object->ref_count > 0, NULL);
+
+ object->ref_count += 1;
+
+ return object;
+}
+
+void
+g_object_unref (GObject *object)
+{
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (object->ref_count > 0);
+
+ if (object->ref_count > 1)
+ object->ref_count -= 1;
+ else
+ g_object_last_unref (object);
+}
+
+gpointer
+g_object_get_qdata (GObject *object,
+ GQuark quark)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+
+ return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
+}
+
+void
+g_object_set_qdata (GObject *object,
+ GQuark quark,
+ gpointer data)
+{
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (quark > 0);
+
+ g_datalist_id_set_data (&object->qdata, quark, data);
+}
+
+void
+g_object_set_qdata_full (GObject *object,
+ GQuark quark,
+ gpointer data,
+ GDestroyNotify destroy)
+{
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (quark > 0);
+
+ g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
+}
+
+gpointer
+g_object_steal_qdata (GObject *object,
+ GQuark quark)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (quark > 0, NULL);
+
+ return g_datalist_id_remove_no_notify (&object->qdata, quark);
+}
diff --git a/gobject/gobject.h b/gobject/gobject.h
new file mode 100644
index 000000000..69c718d98
--- /dev/null
+++ b/gobject/gobject.h
@@ -0,0 +1,165 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ */
+#ifndef __G_GOBJECT_H__
+#define __G_GOBJECT_H__
+
+#include <gobject/gtype.h>
+#include <gobject/gparam.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define G_TYPE_IS_OBJECT(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT)
+#define G_OBJECT(object) (G_IS_OBJECT (object) ? ((GObject*) (object)) : \
+ G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
+#define G_OBJECT_CLASS(class) (G_IS_OBJECT_CLASS (class) ? ((GObjectClass*) (class)) : \
+ G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_OBJECT, GObjectClass))
+#define G_IS_OBJECT(object) (((GObject*) (object)) != NULL && \
+ G_IS_OBJECT_CLASS (((GTypeInstance*) (object))->g_class))
+#define G_IS_OBJECT_CLASS(class) (((GTypeClass*) (class)) != NULL && \
+ G_TYPE_IS_OBJECT (((GTypeClass*) (class))->g_type))
+#define G_OBJECT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), G_TYPE_OBJECT, GObjectClass))
+#define G_OBJECT_TYPE(object) (G_TYPE_FROM_INSTANCE (object))
+#define G_OBJECT_TYPE_NAME(object) (g_type_name (G_OBJECT_TYPE (object)))
+#define G_OBJECT_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
+#define G_OBJECT_CLASS_NAME(class) (g_type_name (G_OBJECT_CLASS_TYPE (class)))
+
+#define G_NOTIFY_PRIORITY (G_PRIORITY_HIGH_IDLE + 20)
+
+
+/* --- typedefs & structures --- */
+typedef struct _GObject GObject;
+typedef struct _GObjectClass GObjectClass;
+typedef void (*GObjectGetParamFunc) (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec,
+ const gchar *trailer);
+typedef void (*GObjectSetParamFunc) (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec,
+ const gchar *trailer);
+typedef void (*GObjectFinalizeFunc) (GObject *object);
+struct _GObject
+{
+ GTypeInstance g_type_instance;
+
+ /*< private >*/
+ guint ref_count;
+ GData *qdata;
+};
+struct _GObjectClass
+{
+ GTypeClass g_type_class;
+
+ guint n_param_specs;
+ GParamSpec **param_specs;
+
+ void (*get_param) (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec,
+ const gchar *trailer);
+ void (*set_param) (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec,
+ const gchar *trailer);
+ void (*queue_param_changed) (GObject *object,
+ GParamSpec *pspec);
+ void (*dispatch_param_changed) (GObject *object,
+ GParamSpec *pspec);
+ void (*shutdown) (GObject *object);
+ void (*finalize) (GObject *object);
+};
+
+
+/* --- prototypes --- */
+void g_object_class_install_param (GObjectClass *oclass,
+ guint param_id,
+ GParamSpec *pspec /* +1 ref */);
+GParamSpec* g_object_class_find_param_spec (GObjectClass *oclass,
+ const gchar *param_name);
+gpointer g_object_new (GType object_type,
+ const gchar *first_param_name,
+ ...);
+gpointer g_object_new_valist (GType object_type,
+ const gchar *first_param_name,
+ va_list var_args);
+void g_object_set (GObject *object,
+ const gchar *first_param_name,
+ ...);
+void g_object_get (GObject *object,
+ const gchar *first_param_name,
+ ...);
+void g_object_set_valist (GObject *object,
+ const gchar *first_param_name,
+ va_list var_args);
+void g_object_get_valist (GObject *object,
+ const gchar *first_param_name,
+ va_list var_args);
+void g_object_set_param (GObject *object,
+ const gchar *param_name,
+ const GValue *value);
+void g_object_get_param (GObject *object,
+ const gchar *param_name,
+ GValue *value);
+void g_object_queue_param_changed (GObject *object,
+ const gchar *param_name);
+GObject* g_object_ref (GObject *object);
+void g_object_unref (GObject *object);
+gpointer g_object_get_qdata (GObject *object,
+ GQuark quark);
+void g_object_set_qdata (GObject *object,
+ GQuark quark,
+ gpointer data);
+void g_object_set_qdata_full (GObject *object,
+ GQuark quark,
+ gpointer data,
+ GDestroyNotify destroy);
+gpointer g_object_steal_qdata (GObject *object,
+ GQuark quark);
+
+
+/* --- implementation macros --- */
+#define G_WARN_INVALID_PARAM_ID(object, param_id, pspec) \
+G_STMT_START { \
+ GObject *_object = (GObject*) (object); \
+ GParamSpec *_pspec = (GParamSpec*) (pspec); \
+ guint _param_id = (param_id); \
+ g_warning ("%s: invalid parameter id %u for \"%s\" of type `%s' in `%s'", \
+ G_STRLOC, \
+ _param_id, \
+ _pspec->name, \
+ g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \
+ BSE_OBJECT_TYPE_NAME (_object)); \
+} G_STMT_END
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_GOBJECT_H__ */
diff --git a/gobject/gparam.c b/gobject/gparam.c
new file mode 100644
index 000000000..e29b1a7c5
--- /dev/null
+++ b/gobject/gparam.c
@@ -0,0 +1,318 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "gparam.h"
+
+
+#include <string.h>
+
+
+
+/* --- defines --- */
+#define G_PARAM_SPEC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
+
+
+/* --- prototypes --- */
+extern void g_param_types_init (void);
+extern void g_param_spec_types_init (void); /* sync with glib-gparamspecs.c */
+static void g_param_spec_class_base_init (GParamSpecClass *class);
+static void g_param_spec_class_base_finalize (GParamSpecClass *class);
+static void g_param_spec_class_init (GParamSpecClass *class,
+ gpointer class_data);
+static void g_param_spec_init (GParamSpec *pspec);
+static void g_param_spec_finalize (GParamSpec *pspec);
+
+
+/* --- functions --- */
+void
+g_param_types_init (void) /* sync with glib-gtype.c */
+{
+ static const GTypeFundamentalInfo finfo = {
+ (G_TYPE_FLAG_CLASSED |
+ G_TYPE_FLAG_INSTANTIATABLE |
+ G_TYPE_FLAG_DERIVABLE |
+ G_TYPE_FLAG_DEEP_DERIVABLE),
+ 0 /* n_collect_bytes */,
+ NULL /* GTypeParamCollector */,
+ };
+ static const GTypeInfo param_spec_info = {
+ sizeof (GParamSpecClass),
+
+ (GBaseInitFunc) g_param_spec_class_base_init,
+ (GBaseFinalizeFunc) g_param_spec_class_base_finalize,
+ (GClassInitFunc) g_param_spec_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL /* class_data */,
+
+ sizeof (GParamSpec),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) g_param_spec_init,
+ };
+ GType type;
+
+ type = g_type_register_fundamental (G_TYPE_PARAM, "GParam", &finfo, &param_spec_info);
+ g_assert (type == G_TYPE_PARAM);
+
+ /* derived param specs
+ */
+ g_param_spec_types_init ();
+}
+
+static void
+g_param_spec_class_base_init (GParamSpecClass *class)
+{
+}
+
+static void
+g_param_spec_class_base_finalize (GParamSpecClass *class)
+{
+}
+
+static void
+g_param_spec_class_init (GParamSpecClass *class,
+ gpointer class_data)
+{
+ class->finalize = g_param_spec_finalize;
+ class->param_init = NULL;
+ class->param_free_value = NULL;
+ class->param_validate = NULL;
+ class->param_values_cmp = NULL;
+ class->param_copy_value = NULL;
+ class->collect_type = 0;
+ class->param_collect_value = NULL;
+ class->lcopy_type = 0;
+ class->param_lcopy_value = NULL;
+}
+
+static void
+g_param_spec_init (GParamSpec *pspec)
+{
+ pspec->name = NULL;
+ pspec->nick = NULL;
+ pspec->blurb = NULL;
+ pspec->flags = 0;
+ pspec->owner_type = 0;
+ pspec->qdata = NULL;
+ pspec->ref_count = 1;
+}
+
+static void
+g_param_spec_finalize (GParamSpec *pspec)
+{
+ g_datalist_clear (&pspec->qdata);
+
+ g_free (pspec->name);
+ g_free (pspec->nick);
+ g_free (pspec->blurb);
+
+ g_type_free_instance ((GTypeInstance*) pspec);
+}
+
+GParamSpec*
+g_param_spec_ref (GParamSpec *pspec)
+{
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
+ g_return_val_if_fail (pspec->ref_count > 0, NULL);
+
+ pspec->ref_count += 1;
+
+ return pspec;
+}
+
+void
+g_param_spec_unref (GParamSpec *pspec)
+{
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (pspec->ref_count > 0);
+
+ pspec->ref_count -= 1;
+ if (pspec->ref_count == 0)
+ G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
+}
+
+gpointer
+g_param_spec_internal (GType param_type,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamFlags flags)
+{
+ GParamSpec *pspec;
+
+ g_return_val_if_fail (G_TYPE_IS_PARAM (param_type) && param_type != G_TYPE_PARAM, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ pspec = (gpointer) g_type_create_instance (param_type);
+ pspec->name = g_strdup (name);
+ g_strcanon (pspec->name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
+ pspec->nick = g_strdup (nick ? nick : pspec->name);
+ pspec->blurb = g_strdup (blurb);
+ pspec->flags = (flags & G_PARAM_USER_MASK) | (flags & G_PARAM_MASK);
+
+ return pspec;
+}
+
+gpointer
+g_param_spec_get_qdata (GParamSpec *pspec,
+ GQuark quark)
+{
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
+
+ return quark ? g_datalist_id_get_data (&pspec->qdata, quark) : NULL;
+}
+
+void
+g_param_spec_set_qdata (GParamSpec *pspec,
+ GQuark quark,
+ gpointer data)
+{
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (quark > 0);
+
+ g_datalist_id_set_data (&pspec->qdata, quark, data);
+}
+
+void
+g_param_spec_set_qdata_full (GParamSpec *pspec,
+ GQuark quark,
+ gpointer data,
+ GDestroyNotify destroy)
+{
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (quark > 0);
+
+ g_datalist_id_set_data_full (&pspec->qdata, quark, data, data ? destroy : NULL);
+}
+
+gpointer
+g_param_spec_steal_qdata (GParamSpec *pspec,
+ GQuark quark)
+{
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
+ g_return_val_if_fail (quark > 0, NULL);
+
+ return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
+}
+
+static guint
+param_spec_hash (gconstpointer key_spec)
+{
+ const GParamSpec *key = key_spec;
+ const gchar *p;
+ guint h = key->owner_type;
+
+ for (p = key->name; *p; p++)
+ h = (h << 5) - h + *p;
+
+ return h;
+}
+
+static gint
+param_spec_equals (gconstpointer key_spec_1,
+ gconstpointer key_spec_2)
+{
+ const GParamSpec *key1 = key_spec_1;
+ const GParamSpec *key2 = key_spec_2;
+
+ return (key1->owner_type == key2->owner_type &&
+ strcmp (key1->name, key2->name) == 0);
+}
+
+GHashTable*
+g_param_spec_hash_table_new (void)
+{
+ return g_hash_table_new (param_spec_hash, param_spec_equals);
+}
+
+void
+g_param_spec_hash_table_insert (GHashTable *hash_table,
+ GParamSpec *pspec,
+ GType owner_type)
+{
+ g_return_if_fail (hash_table != NULL);
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (pspec->name != NULL);
+ if (pspec->owner_type != owner_type)
+ g_return_if_fail (pspec->owner_type == 0);
+
+ if (strchr (pspec->name, ':'))
+ g_warning (G_STRLOC ": parameter name `%s' contains field-delimeter",
+ pspec->name);
+ else
+ {
+ pspec->owner_type = owner_type;
+ g_hash_table_insert (hash_table, pspec, pspec);
+ }
+}
+
+void
+g_param_spec_hash_table_remove (GHashTable *hash_table,
+ GParamSpec *pspec)
+{
+ g_return_if_fail (hash_table != NULL);
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+
+ g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) != NULL); // FIXME: paranoid
+
+ g_hash_table_remove (hash_table, pspec);
+ g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) == NULL); // FIXME: paranoid
+ pspec->owner_type = 0;
+}
+
+GParamSpec*
+g_param_spec_hash_table_lookup (GHashTable *hash_table,
+ const gchar *param_name,
+ GType owner_type,
+ gboolean try_ancestors,
+ const gchar **trailer)
+{
+ GParamSpec *pspec;
+ GParamSpec key;
+ gchar *delim;
+
+ g_return_val_if_fail (hash_table != NULL, NULL);
+ g_return_val_if_fail (param_name != NULL, NULL);
+
+ key.owner_type = owner_type;
+ delim = strchr (param_name, ':');
+ if (delim)
+ key.name = g_strndup (param_name, delim - param_name);
+ else
+ key.name = g_strdup (param_name);
+ g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
+
+ if (trailer)
+ *trailer = delim;
+
+ pspec = g_hash_table_lookup (hash_table, &key);
+ if (!pspec && try_ancestors)
+ {
+ key.owner_type = g_type_parent (key.owner_type);
+ while (key.owner_type)
+ {
+ pspec = g_hash_table_lookup (hash_table, &key);
+ if (pspec)
+ break;
+ key.owner_type = g_type_parent (key.owner_type);
+ }
+ }
+
+ g_free (key.name);
+
+ return pspec;
+}
diff --git a/gobject/gparam.h b/gobject/gparam.h
new file mode 100644
index 000000000..fb6ef1ecf
--- /dev/null
+++ b/gobject/gparam.h
@@ -0,0 +1,186 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ *
+ * gparam.h: GParamSpec base class implementation
+ */
+#ifndef __G_PARAM_H__
+#define __G_PARAM_H__
+
+
+#include <gobject/gtype.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define G_TYPE_IS_PARAM(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_PARAM)
+#define G_PARAM_SPEC_TYPE(pspec) (G_TYPE_FROM_INSTANCE (pspec))
+#define G_PARAM_SPEC_TYPE_NAME(pspec) (g_type_name (G_PARAM_SPEC_TYPE (pspec)))
+#define G_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM, GParamSpec))
+#define G_IS_PARAM_SPEC(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM))
+#define G_PARAM_SPEC_GET_CLASS(pspec) (G_TYPE_INSTANCE_GET_CLASS ((pspec), G_TYPE_PARAM, GParamSpecClass))
+#define G_IS_VALUE(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM))
+
+
+/* --- flags --- */
+typedef enum
+{
+ G_PARAM_READABLE = 1 << 0,
+ G_PARAM_WRITABLE = 1 << 1,
+ G_PARAM_MASK = 0x000f,
+ /* bits in the range 0xfff0 are reserved for 3rd party usage */
+ G_PARAM_USER_MASK = 0xfff0
+} GParamFlags;
+
+
+/* --- typedefs & structures --- */
+typedef struct _GParamSpecClass GParamSpecClass;
+typedef struct _GParamSpec GParamSpec;
+typedef struct _GValue GValue;
+typedef union _GParamCValue GParamCValue;
+typedef void (*GValueExchange) (GValue*, GValue*);
+struct _GParamSpecClass
+{
+ GTypeClass g_type_class;
+
+ void (*finalize) (GParamSpec *pspec);
+
+ /* GParam methods */
+ void (*param_init) (GValue *value,
+ GParamSpec *pspec);
+ void (*param_free_value) (GValue *value);
+ gboolean (*param_validate) (GValue *value,
+ GParamSpec *pspec);
+ gint (*param_values_cmp) (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec);
+ void (*param_copy_value) (const GValue *src_value,
+ GValue *dest_value);
+ /* varargs functionality (optional) */
+ guint collect_type;
+ gchar* (*param_collect_value) (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value);
+ guint lcopy_type;
+ gchar* (*param_lcopy_value) (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value);
+};
+struct _GParamSpec
+{
+ GTypeInstance g_instance;
+
+ gchar *name;
+ gchar *nick;
+ gchar *blurb;
+ GParamFlags flags;
+
+ /*< private >*/
+ GType owner_type;
+ GData *qdata;
+ guint ref_count;
+};
+
+
+/* --- prototypes --- */
+GParamSpec* g_param_spec_ref (GParamSpec *pspec);
+void g_param_spec_unref (GParamSpec *pspec);
+gpointer g_param_spec_get_qdata (GParamSpec *pspec,
+ GQuark quark);
+void g_param_spec_set_qdata (GParamSpec *pspec,
+ GQuark quark,
+ gpointer data);
+void g_param_spec_set_qdata_full (GParamSpec *pspec,
+ GQuark quark,
+ gpointer data,
+ GDestroyNotify destroy);
+gpointer g_param_spec_steal_qdata (GParamSpec *pspec,
+ GQuark quark);
+
+
+/* --- private --- */
+gpointer g_param_spec_internal (GType param_type,
+ const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamFlags flags);
+GHashTable* g_param_spec_hash_table_new (void);
+void g_param_spec_hash_table_insert (GHashTable *hash_table,
+ GParamSpec *pspec,
+ GType owner_type);
+void g_param_spec_hash_table_remove (GHashTable *hash_table,
+ GParamSpec *pspec);
+GParamSpec* g_param_spec_hash_table_lookup (GHashTable *hash_table,
+ const gchar *param_name,
+ GType owner_type,
+ gboolean try_ancestors,
+ const gchar **trailer);
+
+
+/* contracts:
+ *
+ * class functions may not evaluate param->pspec directly,
+ * instead, pspec will be passed as argument if required.
+ *
+ * void param_init (GParam *param, GParamSpec *pspec):
+ * initialize param's value to default if pspec is given,
+ * and to zero-equivalent (a value that doesn't need to be
+ * free()ed later on) otherwise.
+ *
+ * void param_free_value (GParam *param):
+ * free param's value if required, zero-reinitialization
+ * of the value is not required. (this class function
+ * may be NULL for param types that don't need to free
+ * values, such as ints or floats).
+ *
+ * gboolean param_validate (GParam *param, GParamSpec *pspec):
+ * modify param's value in the least destructive way, so
+ * that it complies with pspec's requirements (i.e.
+ * according to minimum/maximum ranges etc...). return
+ * whether modification was necessary.
+ *
+ * gint param_values_cmp (GParam *param1, GParam *param2, GParamSpec*):
+ * return param1 - param2, i.e. <0 if param1 < param2,
+ * >0 if param1 > param2, and 0 if they are equal
+ * (passing pspec is optional, but recommended)
+ *
+ * void param_copy_value (GParam *param_src, GParam *param_dest):
+ * copy value from param_src to param_dest, param_dest is
+ * already free()d and zero-initialized, so its value can
+ * simply be overwritten. (may be NULL for memcpy)
+ *
+ * gchar* param_collect_value ():
+ * class function may be NULL.
+ *
+ * gchar* param_lcopy_value ():
+ * class function may be NULL.
+ *
+ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_PARAM_H__ */
diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c
new file mode 100644
index 000000000..628d134b8
--- /dev/null
+++ b/gobject/gparamspecs.c
@@ -0,0 +1,2004 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "gparamspecs.h"
+
+#include "gvaluecollector.h"
+#include <string.h>
+#include "../config.h" /* for SIZEOF_LONG */
+
+#define G_FLOAT_EPSILON (1e-30)
+#define G_DOUBLE_EPSILON (1e-90)
+
+
+/* --- prototypes --- */
+extern void g_param_spec_types_init (void);
+
+
+/* --- param spec functions --- */
+static void
+param_spec_char_init (GParamSpec *pspec)
+{
+ GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
+
+ cspec->minimum = 0x7f;
+ cspec->maximum = 0x80;
+ cspec->default_value = 0;
+}
+
+static void
+param_char_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
+}
+
+static gboolean
+param_char_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
+ gint oval = value->data[0].v_int;
+
+ value->data[0].v_int = CLAMP (value->data[0].v_int, cspec->minimum, cspec->maximum);
+
+ return value->data[0].v_int != oval;
+}
+
+static gchar*
+param_char_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gint8 *int8_p = collect_value->v_pointer;
+
+ if (!int8_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *int8_p = value->data[0].v_int;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_uchar_init (GParamSpec *pspec)
+{
+ GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
+
+ uspec->minimum = 0;
+ uspec->maximum = 0xff;
+ uspec->default_value = 0;
+}
+
+static void
+param_uchar_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
+}
+
+static gboolean
+param_uchar_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
+ guint oval = value->data[0].v_uint;
+
+ value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
+
+ return value->data[0].v_uint != oval;
+}
+
+static void
+param_bool_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_int = G_PARAM_SPEC_BOOL (pspec)->default_value;
+}
+
+static gboolean
+param_bool_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ gint oval = value->data[0].v_int;
+
+ value->data[0].v_int = value->data[0].v_int != FALSE;
+
+ return value->data[0].v_int != oval;
+}
+
+static gchar*
+param_bool_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gboolean *bool_p = collect_value->v_pointer;
+
+ if (!bool_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *bool_p = value->data[0].v_int;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_int_init (GParamSpec *pspec)
+{
+ GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
+
+ ispec->minimum = 0x7fffffff;
+ ispec->maximum = 0x80000000;
+ ispec->default_value = 0;
+}
+
+static void
+param_int_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
+}
+
+static gboolean
+param_int_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
+ gint oval = value->data[0].v_int;
+
+ value->data[0].v_int = CLAMP (value->data[0].v_int, ispec->minimum, ispec->maximum);
+
+ return value->data[0].v_int != oval;
+}
+
+static gint
+param_int_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ if (value1->data[0].v_int < value2->data[0].v_int)
+ return -1;
+ else
+ return value1->data[0].v_int - value2->data[0].v_int;
+}
+
+static gchar*
+param_int_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ value->data[0].v_int = collect_value->v_int;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_int_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gint *int_p = collect_value->v_pointer;
+
+ if (!int_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *int_p = value->data[0].v_int;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_uint_init (GParamSpec *pspec)
+{
+ GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
+
+ uspec->minimum = 0;
+ uspec->maximum = 0xffffffff;
+ uspec->default_value = 0;
+}
+
+static void
+param_uint_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
+}
+
+static gboolean
+param_uint_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
+ guint oval = value->data[0].v_uint;
+
+ value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
+
+ return value->data[0].v_uint != oval;
+}
+
+static gint
+param_uint_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ if (value1->data[0].v_uint < value2->data[0].v_uint)
+ return -1;
+ else
+ return value1->data[0].v_uint - value2->data[0].v_uint;
+}
+
+static void
+param_spec_long_init (GParamSpec *pspec)
+{
+ GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
+
+#if SIZEOF_LONG == 4
+ lspec->minimum = 0x7fffffff;
+ lspec->maximum = 0x80000000;
+#else /* SIZEOF_LONG != 4 (8) */
+ lspec->minimum = 0x7fffffffffffffff;
+ lspec->maximum = 0x8000000000000000;
+#endif
+ lspec->default_value = 0;
+}
+
+static void
+param_long_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
+}
+
+static gboolean
+param_long_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
+ glong oval = value->data[0].v_long;
+
+ value->data[0].v_long = CLAMP (value->data[0].v_long, lspec->minimum, lspec->maximum);
+
+ return value->data[0].v_long != oval;
+}
+
+static gint
+param_long_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ if (value1->data[0].v_long < value2->data[0].v_long)
+ return -1;
+ else
+ return value1->data[0].v_long - value2->data[0].v_long;
+}
+
+static gchar*
+param_long_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ value->data[0].v_long = collect_value->v_long;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_long_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ glong *long_p = collect_value->v_pointer;
+
+ if (!long_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *long_p = value->data[0].v_long;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_ulong_init (GParamSpec *pspec)
+{
+ GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
+
+ uspec->minimum = 0;
+#if SIZEOF_LONG == 4
+ uspec->maximum = 0xffffffff;
+#else /* SIZEOF_LONG != 4 (8) */
+ uspec->maximum = 0xffffffffffffffff;
+#endif
+ uspec->default_value = 0;
+}
+
+static void
+param_ulong_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
+}
+
+static gboolean
+param_ulong_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
+ gulong oval = value->data[0].v_ulong;
+
+ value->data[0].v_ulong = CLAMP (value->data[0].v_ulong, uspec->minimum, uspec->maximum);
+
+ return value->data[0].v_ulong != oval;
+}
+
+static gint
+param_ulong_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ if (value1->data[0].v_ulong < value2->data[0].v_ulong)
+ return -1;
+ else
+ return value1->data[0].v_ulong - value2->data[0].v_ulong;
+}
+
+static void
+param_spec_enum_init (GParamSpec *pspec)
+{
+ GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
+
+ espec->enum_class = NULL;
+ espec->default_value = 0;
+}
+
+static void
+param_spec_enum_finalize (GParamSpec *pspec)
+{
+ GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
+ GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_ENUM));
+
+ if (espec->enum_class)
+ {
+ g_type_class_unref (espec->enum_class);
+ espec->enum_class = NULL;
+ }
+
+ parent_class->finalize (pspec);
+}
+
+static void
+param_enum_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
+}
+
+static gboolean
+param_enum_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
+ glong oval = value->data[0].v_long;
+
+ if (!espec->enum_class ||
+ !g_enum_get_value (espec->enum_class, value->data[0].v_long))
+ value->data[0].v_long = espec->default_value;
+
+ return value->data[0].v_long != oval;
+}
+
+static gchar*
+param_enum_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ value->data[0].v_long = collect_value->v_int;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_enum_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gint *int_p = collect_value->v_pointer;
+
+ if (!int_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *int_p = value->data[0].v_long;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_flags_init (GParamSpec *pspec)
+{
+ GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
+
+ fspec->flags_class = NULL;
+ fspec->default_value = 0;
+}
+
+static void
+param_spec_flags_finalize (GParamSpec *pspec)
+{
+ GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
+ GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_FLAGS));
+
+ if (fspec->flags_class)
+ {
+ g_type_class_unref (fspec->flags_class);
+ fspec->flags_class = NULL;
+ }
+
+ parent_class->finalize (pspec);
+}
+
+static void
+param_flags_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
+}
+
+static gboolean
+param_flags_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
+ gulong oval = value->data[0].v_ulong;
+
+ if (fspec->flags_class)
+ value->data[0].v_ulong &= fspec->flags_class->mask;
+ else
+ value->data[0].v_ulong = fspec->default_value;
+
+ return value->data[0].v_ulong != oval;
+}
+
+static void
+param_spec_float_init (GParamSpec *pspec)
+{
+ GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
+
+ fspec->minimum = G_MINFLOAT;
+ fspec->maximum = G_MAXFLOAT;
+ fspec->default_value = 0;
+ fspec->epsilon = G_FLOAT_EPSILON;
+}
+
+static void
+param_float_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
+}
+
+static gboolean
+param_float_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
+ gfloat oval = value->data[0].v_float;
+
+ value->data[0].v_float = CLAMP (value->data[0].v_float, fspec->minimum, fspec->maximum);
+
+ return value->data[0].v_float != oval;
+}
+
+static gint
+param_float_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ gfloat epsilon = pspec ? G_PARAM_SPEC_FLOAT (pspec)->epsilon : G_FLOAT_EPSILON;
+
+ if (value1->data[0].v_float < value2->data[0].v_float)
+ return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
+ else
+ return value1->data[0].v_float - value2->data[0].v_float > epsilon;
+}
+
+static gchar*
+param_float_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ value->data[0].v_float = collect_value->v_double;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_float_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gfloat *float_p = collect_value->v_pointer;
+
+ if (!float_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *float_p = value->data[0].v_float;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_double_init (GParamSpec *pspec)
+{
+ GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
+
+ dspec->minimum = G_MINDOUBLE;
+ dspec->maximum = G_MAXDOUBLE;
+ dspec->default_value = 0;
+ dspec->epsilon = G_DOUBLE_EPSILON;
+}
+
+static void
+param_double_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
+}
+
+static gboolean
+param_double_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
+ gdouble oval = value->data[0].v_double;
+
+ value->data[0].v_double = CLAMP (value->data[0].v_double, dspec->minimum, dspec->maximum);
+
+ return value->data[0].v_double != oval;
+}
+
+static gint
+param_double_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ gdouble epsilon = pspec ? G_PARAM_SPEC_DOUBLE (pspec)->epsilon : G_DOUBLE_EPSILON;
+
+ if (value1->data[0].v_double < value2->data[0].v_double)
+ return - (value2->data[0].v_double - value1->data[0].v_double > epsilon);
+ else
+ return value1->data[0].v_double - value2->data[0].v_double > epsilon;
+}
+
+static gchar*
+param_double_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ value->data[0].v_double = collect_value->v_double;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_double_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gdouble *double_p = collect_value->v_pointer;
+
+ if (!double_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *double_p = value->data[0].v_double;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_string_init (GParamSpec *pspec)
+{
+ GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
+
+ sspec->default_value = NULL;
+ sspec->cset_first = NULL;
+ sspec->cset_nth = NULL;
+ sspec->substitutor = '_';
+ sspec->null_fold_if_empty = FALSE;
+ sspec->ensure_non_null = FALSE;
+}
+
+static void
+param_spec_string_finalize (GParamSpec *pspec)
+{
+ GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
+ GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_STRING));
+
+ g_free (sspec->default_value);
+ g_free (sspec->cset_first);
+ g_free (sspec->cset_nth);
+ sspec->default_value = NULL;
+ sspec->cset_first = NULL;
+ sspec->cset_nth = NULL;
+
+ parent_class->finalize (pspec);
+}
+
+static void
+param_string_init (GValue *value,
+ GParamSpec *pspec)
+{
+ if (pspec)
+ value->data[0].v_pointer = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
+}
+
+static void
+param_string_free_value (GValue *value)
+{
+ g_free (value->data[0].v_pointer);
+}
+
+static gboolean
+param_string_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
+ gchar *string = value->data[0].v_pointer;
+ guint changed = 0;
+
+ if (string && string[0])
+ {
+ gchar *s;
+
+ if (sspec->cset_first && !strchr (sspec->cset_first, string[0]))
+ {
+ string[0] = sspec->substitutor;
+ changed++;
+ }
+ if (sspec->cset_nth)
+ for (s = string + 1; *s; s++)
+ if (!strchr (sspec->cset_nth, *s))
+ {
+ *s = sspec->substitutor;
+ changed++;
+ }
+ }
+ if (sspec->null_fold_if_empty && string && string[0] == 0)
+ {
+ g_free (value->data[0].v_pointer);
+ value->data[0].v_pointer = NULL;
+ changed++;
+ string = value->data[0].v_pointer;
+ }
+ if (sspec->ensure_non_null && !string)
+ {
+ value->data[0].v_pointer = g_strdup ("");
+ changed++;
+ string = value->data[0].v_pointer;
+ }
+
+ return changed;
+}
+
+static gint
+param_string_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ if (!value1->data[0].v_pointer)
+ return value2->data[0].v_pointer != NULL ? -1 : 0;
+ else if (!value2->data[0].v_pointer)
+ return value1->data[0].v_pointer != NULL;
+ else
+ return strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
+}
+
+static void
+param_string_copy_value (const GValue *src_value,
+ GValue *dest_value)
+{
+ dest_value->data[0].v_pointer = g_strdup (src_value->data[0].v_pointer);
+}
+
+static gchar*
+param_string_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ value->data[0].v_pointer = g_strdup (collect_value->v_pointer);
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_string_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ gchar **string_p = collect_value->v_pointer;
+
+ if (!string_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *string_p = g_strdup (value->data[0].v_pointer);
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+param_spec_object_init (GParamSpec *pspec)
+{
+ GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
+
+ ospec->object_type = G_TYPE_OBJECT;
+}
+
+static void
+param_object_init (GValue *value,
+ GParamSpec *pspec)
+{
+ value->data[0].v_pointer = NULL;
+}
+
+static void
+param_object_free_value (GValue *value)
+{
+ if (value->data[0].v_pointer)
+ g_object_unref (value->data[0].v_pointer);
+}
+
+static gboolean
+param_object_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
+ GObject *object = value->data[0].v_pointer;
+ guint changed = 0;
+
+ if (object && !g_type_is_a (G_OBJECT_TYPE (object), ospec->object_type))
+ {
+ g_object_unref (object);
+ value->data[0].v_pointer = NULL;
+ changed++;
+ }
+
+ return changed;
+}
+
+static gint
+param_object_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ return value1->data[0].v_pointer != value2->data[0].v_pointer;
+}
+
+static void
+param_object_copy_value (const GValue *src_value,
+ GValue *dest_value)
+{
+ if (src_value->data[0].v_pointer)
+ dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
+ else
+ dest_value->data[0].v_pointer = NULL;
+}
+
+static gchar*
+param_object_collect_value (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ if (collect_value->v_pointer)
+ {
+ GObject *object = collect_value->v_pointer;
+
+ if (object->g_type_instance.g_class == NULL)
+ return g_strconcat ("invalid unclassed object pointer for param type `",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)),
+ "'",
+ NULL);
+ else if (pspec && !g_type_is_a (G_OBJECT_TYPE (object), G_PARAM_SPEC_OBJECT (pspec)->object_type))
+ return g_strconcat ("invalid object `",
+ G_OBJECT_TYPE_NAME (object),
+ "' for param type `",
+ g_type_name (G_PARAM_SPEC_TYPE (pspec)),
+ "' which requires `",
+ g_type_name (G_PARAM_SPEC_OBJECT (pspec)->object_type),
+ "'",
+ NULL);
+ value->data[0].v_pointer = g_object_ref (object);
+ }
+ else
+ value->data[0].v_pointer = NULL;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static gchar*
+param_object_lcopy_value (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value)
+{
+ GObject **object_p = collect_value->v_pointer;
+
+ if (!object_p)
+ return g_strdup_printf ("value location for `%s' passed as NULL",
+ g_type_name (pspec ? G_PARAM_SPEC_TYPE (pspec) : G_VALUE_TYPE (value)));
+
+ *object_p = value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
+
+ *collect_type = 0;
+ return NULL;
+}
+
+static void
+value_exch_memcpy (GValue *value1,
+ GValue *value2)
+{
+ GValue tmp_value;
+ memcpy (&tmp_value.data, &value1->data, sizeof (value1->data));
+ memcpy (&value1->data, &value2->data, sizeof (value1->data));
+ memcpy (&value2->data, &tmp_value.data, sizeof (value2->data));
+}
+
+static void
+value_exch_long_int (GValue *value1,
+ GValue *value2)
+{
+ glong tmp = value1->data[0].v_long;
+ value1->data[0].v_long = value2->data[0].v_int;
+ value2->data[0].v_int = tmp;
+}
+
+static void
+value_exch_long_uint (GValue *value1,
+ GValue *value2)
+{
+ glong tmp = value1->data[0].v_long;
+ value1->data[0].v_long = value2->data[0].v_uint;
+ value2->data[0].v_uint = tmp;
+}
+
+static void
+value_exch_ulong_int (GValue *value1,
+ GValue *value2)
+{
+ gulong tmp = value1->data[0].v_ulong;
+ value1->data[0].v_ulong = value2->data[0].v_int;
+ value2->data[0].v_int = tmp;
+}
+
+static void
+value_exch_ulong_uint (GValue *value1,
+ GValue *value2)
+{
+ gulong tmp = value1->data[0].v_ulong;
+ value1->data[0].v_ulong = value2->data[0].v_uint;
+ value2->data[0].v_uint = tmp;
+}
+
+static void
+value_exch_float_int (GValue *value1,
+ GValue *value2)
+{
+ gfloat tmp = value1->data[0].v_float;
+ value1->data[0].v_float = value2->data[0].v_int;
+ value2->data[0].v_int = 0.5 + tmp;
+}
+
+static void
+value_exch_float_uint (GValue *value1,
+ GValue *value2)
+{
+ gfloat tmp = value1->data[0].v_float;
+ value1->data[0].v_float = value2->data[0].v_uint;
+ value2->data[0].v_uint = 0.5 + tmp;
+}
+
+static void
+value_exch_float_long (GValue *value1,
+ GValue *value2)
+{
+ gfloat tmp = value1->data[0].v_float;
+ value1->data[0].v_float = value2->data[0].v_long;
+ value2->data[0].v_long = 0.5 + tmp;
+}
+
+static void
+value_exch_float_ulong (GValue *value1,
+ GValue *value2)
+{
+ gfloat tmp = value1->data[0].v_float;
+ value1->data[0].v_float = value2->data[0].v_ulong;
+ value2->data[0].v_ulong = 0.5 + tmp;
+}
+
+static void
+value_exch_double_int (GValue *value1,
+ GValue *value2)
+{
+ gdouble tmp = value1->data[0].v_double;
+ value1->data[0].v_double = value2->data[0].v_int;
+ value2->data[0].v_int = 0.5 + tmp;
+}
+
+static void
+value_exch_double_uint (GValue *value1,
+ GValue *value2)
+{
+ gdouble tmp = value1->data[0].v_double;
+ value1->data[0].v_double = value2->data[0].v_uint;
+ value2->data[0].v_uint = 0.5 + tmp;
+}
+
+static void
+value_exch_double_long (GValue *value1,
+ GValue *value2)
+{
+ gdouble tmp = value1->data[0].v_double;
+ value1->data[0].v_double = value2->data[0].v_long;
+ value2->data[0].v_long = 0.5 + tmp;
+}
+
+static void
+value_exch_double_ulong (GValue *value1,
+ GValue *value2)
+{
+ gdouble tmp = value1->data[0].v_double;
+ value1->data[0].v_double = value2->data[0].v_ulong;
+ value2->data[0].v_ulong = 0.5 + tmp;
+}
+
+static void
+value_exch_double_float (GValue *value1,
+ GValue *value2)
+{
+ gdouble tmp = value1->data[0].v_double;
+ value1->data[0].v_double = value2->data[0].v_float;
+ value2->data[0].v_float = tmp;
+}
+
+
+/* --- type initialization --- */
+typedef struct {
+ void (*finalize) (GParamSpec *pspec);
+ void (*param_init) (GValue *value,
+ GParamSpec *pspec);
+ void (*param_free_value) (GValue *value);
+ gboolean (*param_validate) (GValue *value,
+ GParamSpec *pspec);
+ gint (*param_values_cmp) (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec);
+ void (*param_copy_value) (const GValue *src_value,
+ GValue *dest_value);
+ guint collect_type;
+ gchar* (*param_collect_value) (GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value);
+ guint lcopy_type;
+ gchar* (*param_lcopy_value) (const GValue *value,
+ GParamSpec *pspec,
+ guint nth_value,
+ GType *collect_type,
+ GParamCValue *collect_value);
+} ParamSpecClassInfo;
+
+static void
+param_spec_class_init (gpointer g_class,
+ gpointer class_data)
+{
+ GParamSpecClass *class = g_class;
+ ParamSpecClassInfo *info = class_data;
+
+ if (info->finalize)
+ class->finalize = info->finalize;
+ if (info->param_init)
+ class->param_init = info->param_init;
+ if (info->param_free_value)
+ class->param_free_value = info->param_free_value;
+ if (info->param_validate)
+ class->param_validate = info->param_validate;
+ if (info->param_values_cmp)
+ class->param_values_cmp = info->param_values_cmp;
+ if (info->param_copy_value)
+ class->param_copy_value = info->param_copy_value;
+ class->collect_type = info->collect_type;
+ class->param_collect_value = info->param_collect_value;
+ class->lcopy_type = info->lcopy_type;
+ class->param_lcopy_value = info->param_lcopy_value;
+}
+
+void
+g_param_spec_types_init (void) /* sync with glib-gparam.c */
+{
+ GTypeInfo info = {
+ sizeof (GParamSpecClass), /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_destroy */
+ param_spec_class_init, /* class_init */
+ NULL, /* class_destroy */
+ NULL, /* class_data */
+ 0, /* instance_size */
+ 16, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+ GType type;
+
+ /* G_TYPE_PARAM_CHAR
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_char_init, /* param_init */
+ NULL, /* param_free_value */
+ param_char_validate, /* param_validate */
+ param_int_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_int_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_char_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecChar);
+ info.instance_init = (GInstanceInitFunc) param_spec_char_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamChar", &info);
+ g_assert (type == G_TYPE_PARAM_CHAR);
+ }
+
+ /* G_TYPE_PARAM_UCHAR
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_uchar_init, /* param_init */
+ NULL, /* param_free_value */
+ param_uchar_validate, /* param_validate */
+ param_uint_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_int_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_char_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecUChar);
+ info.instance_init = (GInstanceInitFunc) param_spec_uchar_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamUChar", &info);
+ g_assert (type == G_TYPE_PARAM_UCHAR);
+ }
+
+ /* G_TYPE_PARAM_BOOL
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_bool_init, /* param_init */
+ NULL, /* param_free_value */
+ param_bool_validate, /* param_validate */
+ param_int_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_int_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_bool_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecBool);
+ info.instance_init = (GInstanceInitFunc) NULL;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamBool", &info);
+ g_assert (type == G_TYPE_PARAM_BOOL);
+ }
+
+ /* G_TYPE_PARAM_INT
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_int_init, /* param_init */
+ NULL, /* param_free_value */
+ param_int_validate, /* param_validate */
+ param_int_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_int_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_int_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecInt);
+ info.instance_init = (GInstanceInitFunc) param_spec_int_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamInt", &info);
+ g_assert (type == G_TYPE_PARAM_INT);
+ }
+
+ /* G_TYPE_PARAM_UINT
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_uint_init, /* param_init */
+ NULL, /* param_free_value */
+ param_uint_validate, /* param_validate */
+ param_uint_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_int_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_int_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecUInt);
+ info.instance_init = (GInstanceInitFunc) param_spec_uint_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamUInt", &info);
+ g_assert (type == G_TYPE_PARAM_UINT);
+ }
+
+ /* G_TYPE_PARAM_LONG
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_long_init, /* param_init */
+ NULL, /* param_free_value */
+ param_long_validate, /* param_validate */
+ param_long_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_LONG, /* collect_type */
+ param_long_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_long_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecLong);
+ info.instance_init = (GInstanceInitFunc) param_spec_long_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamLong", &info);
+ g_assert (type == G_TYPE_PARAM_LONG);
+ }
+
+ /* G_TYPE_PARAM_ULONG
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_ulong_init, /* param_init */
+ NULL, /* param_free_value */
+ param_ulong_validate, /* param_validate */
+ param_ulong_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_LONG, /* collect_type */
+ param_long_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_long_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecULong);
+ info.instance_init = (GInstanceInitFunc) param_spec_ulong_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamULong", &info);
+ g_assert (type == G_TYPE_PARAM_ULONG);
+ }
+
+ /* G_TYPE_PARAM_ENUM
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ param_spec_enum_finalize, /* finalize */
+ param_enum_init, /* param_init */
+ NULL, /* param_free_value */
+ param_enum_validate, /* param_validate */
+ param_long_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_enum_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_enum_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecEnum);
+ info.instance_init = (GInstanceInitFunc) param_spec_enum_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamEnum", &info);
+ g_assert (type == G_TYPE_PARAM_ENUM);
+ }
+
+ /* G_TYPE_PARAM_FLAGS
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ param_spec_flags_finalize,/* finalize */
+ param_flags_init, /* param_init */
+ NULL, /* param_free_value */
+ param_flags_validate, /* param_validate */
+ param_ulong_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_INT, /* collect_type */
+ param_enum_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_enum_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecFlags);
+ info.instance_init = (GInstanceInitFunc) param_spec_flags_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamFlags", &info);
+ g_assert (type == G_TYPE_PARAM_FLAGS);
+ }
+
+ /* G_TYPE_PARAM_FLOAT
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_float_init, /* param_init */
+ NULL, /* param_free_value */
+ param_float_validate, /* param_validate */
+ param_float_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_DOUBLE, /* collect_type */
+ param_float_collect_value,/* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_float_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecFloat);
+ info.instance_init = (GInstanceInitFunc) param_spec_float_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamFloat", &info);
+ g_assert (type == G_TYPE_PARAM_FLOAT);
+ }
+
+ /* G_TYPE_PARAM_DOUBLE
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_double_init, /* param_init */
+ NULL, /* param_free_value */
+ param_double_validate, /* param_validate */
+ param_double_values_cmp, /* param_values_cmp */
+ NULL, /* param_copy_value */
+ G_VALUE_COLLECT_DOUBLE, /* collect_type */
+ param_double_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_double_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecDouble);
+ info.instance_init = (GInstanceInitFunc) param_spec_double_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamDouble", &info);
+ g_assert (type == G_TYPE_PARAM_DOUBLE);
+ }
+
+ /* G_TYPE_PARAM_STRING
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ param_spec_string_finalize, /* finalize */
+ param_string_init, /* param_init */
+ param_string_free_value, /* param_free_value */
+ param_string_validate, /* param_validate */
+ param_string_values_cmp, /* param_values_cmp */
+ param_string_copy_value, /* param_copy_value */
+ G_VALUE_COLLECT_POINTER, /* collect_type */
+ param_string_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_string_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecString);
+ info.instance_init = (GInstanceInitFunc) param_spec_string_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamString", &info);
+ g_assert (type == G_TYPE_PARAM_STRING);
+ }
+
+ /* G_TYPE_PARAM_OBJECT
+ */
+ {
+ static const ParamSpecClassInfo class_info = {
+ NULL, /* finalize */
+ param_object_init, /* param_init */
+ param_object_free_value, /* param_free_value */
+ param_object_validate, /* param_validate */
+ param_object_values_cmp, /* param_values_cmp */
+ param_object_copy_value, /* param_copy_value */
+ G_VALUE_COLLECT_POINTER, /* collect_type */
+ param_object_collect_value, /* param_collect_value */
+ G_VALUE_COLLECT_POINTER, /* lcopy_type */
+ param_object_lcopy_value, /* param_lcopy_value */
+ };
+ info.class_data = &class_info;
+ info.instance_size = sizeof (GParamSpecObject);
+ info.instance_init = (GInstanceInitFunc) param_spec_object_init;
+ type = g_type_register_static (G_TYPE_PARAM, "GParamObject", &info);
+ g_assert (type == G_TYPE_PARAM_OBJECT);
+ }
+
+ g_value_register_exchange_func (G_TYPE_PARAM_CHAR, G_TYPE_PARAM_UCHAR, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_CHAR, G_TYPE_PARAM_BOOL, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_CHAR, G_TYPE_PARAM_INT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_CHAR, G_TYPE_PARAM_UINT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_CHAR, G_TYPE_PARAM_ENUM, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_CHAR, G_TYPE_PARAM_FLAGS, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UCHAR, G_TYPE_PARAM_BOOL, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UCHAR, G_TYPE_PARAM_INT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UCHAR, G_TYPE_PARAM_UINT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UCHAR, G_TYPE_PARAM_ENUM, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UCHAR, G_TYPE_PARAM_FLAGS, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_BOOL, G_TYPE_PARAM_INT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_BOOL, G_TYPE_PARAM_UINT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_BOOL, G_TYPE_PARAM_ENUM, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_BOOL, G_TYPE_PARAM_FLAGS, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_INT, G_TYPE_PARAM_UINT, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_INT, G_TYPE_PARAM_ENUM, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_INT, G_TYPE_PARAM_FLAGS, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UINT, G_TYPE_PARAM_ENUM, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_UINT, G_TYPE_PARAM_FLAGS, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_CHAR, value_exch_long_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_UCHAR, value_exch_long_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_BOOL, value_exch_long_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_INT, value_exch_long_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_UINT, value_exch_long_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_ULONG, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_ENUM, value_exch_long_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_LONG, G_TYPE_PARAM_FLAGS, value_exch_long_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_CHAR, value_exch_ulong_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_UCHAR, value_exch_ulong_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_BOOL, value_exch_ulong_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_INT, value_exch_ulong_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_UINT, value_exch_ulong_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_ENUM, value_exch_ulong_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_ULONG, G_TYPE_PARAM_FLAGS, value_exch_ulong_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_ENUM, G_TYPE_PARAM_FLAGS, value_exch_memcpy);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_CHAR, value_exch_float_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_UCHAR, value_exch_float_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_BOOL, value_exch_float_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_INT, value_exch_float_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_UINT, value_exch_float_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_LONG, value_exch_float_long);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_ULONG, value_exch_float_ulong);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_ENUM, value_exch_float_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_FLOAT, G_TYPE_PARAM_FLAGS, value_exch_float_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_CHAR, value_exch_double_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_UCHAR, value_exch_double_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_BOOL, value_exch_double_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_INT, value_exch_double_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_UINT, value_exch_double_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_LONG, value_exch_double_long);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_ULONG, value_exch_double_ulong);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_ENUM, value_exch_double_int);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_FLAGS, value_exch_double_uint);
+ g_value_register_exchange_func (G_TYPE_PARAM_DOUBLE, G_TYPE_PARAM_FLOAT, value_exch_double_float);
+}
+
+
+/* --- GValue functions --- */
+void
+g_value_set_char (GValue *value,
+ gint8 v_char)
+{
+ g_return_if_fail (G_IS_VALUE_CHAR (value));
+
+ value->data[0].v_int = v_char;
+}
+
+gint8
+g_value_get_char (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_CHAR (value), 0);
+
+ return value->data[0].v_int;
+}
+
+void
+g_value_set_uchar (GValue *value,
+ guint8 v_uchar)
+{
+ g_return_if_fail (G_IS_VALUE_UCHAR (value));
+
+ value->data[0].v_uint = v_uchar;
+}
+
+guint8
+g_value_get_uchar (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_UCHAR (value), 0);
+
+ return value->data[0].v_uint;
+}
+
+void
+g_value_set_bool (GValue *value,
+ gboolean v_bool)
+{
+ g_return_if_fail (G_IS_VALUE_BOOL (value));
+
+ value->data[0].v_int = v_bool;
+}
+
+gboolean
+g_value_get_bool (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_BOOL (value), 0);
+
+ return value->data[0].v_int;
+}
+
+void
+g_value_set_int (GValue *value,
+ gint v_int)
+{
+ g_return_if_fail (G_IS_VALUE_INT (value));
+
+ value->data[0].v_int = v_int;
+}
+
+gint
+g_value_get_int (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_INT (value), 0);
+
+ return value->data[0].v_int;
+}
+
+void
+g_value_set_uint (GValue *value,
+ guint v_uint)
+{
+ g_return_if_fail (G_IS_VALUE_UINT (value));
+
+ value->data[0].v_uint = v_uint;
+}
+
+guint
+g_value_get_uint (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_UINT (value), 0);
+
+ return value->data[0].v_uint;
+}
+
+void
+g_value_set_long (GValue *value,
+ glong v_long)
+{
+ g_return_if_fail (G_IS_VALUE_LONG (value));
+
+ value->data[0].v_long = v_long;
+}
+
+glong
+g_value_get_long (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_LONG (value), 0);
+
+ return value->data[0].v_long;
+}
+
+void
+g_value_set_ulong (GValue *value,
+ gulong v_ulong)
+{
+ g_return_if_fail (G_IS_VALUE_ULONG (value));
+
+ value->data[0].v_ulong = v_ulong;
+}
+
+gulong
+g_value_get_ulong (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_ULONG (value), 0);
+
+ return value->data[0].v_ulong;
+}
+
+void
+g_value_set_enum (GValue *value,
+ gint v_enum)
+{
+ g_return_if_fail (G_IS_VALUE_ENUM (value));
+
+ value->data[0].v_long = v_enum;
+}
+
+gint
+g_value_get_enum (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_ENUM (value), 0);
+
+ return value->data[0].v_long;
+}
+
+void
+g_value_set_flags (GValue *value,
+ guint v_flags)
+{
+ g_return_if_fail (G_IS_VALUE_FLAGS (value));
+
+ value->data[0].v_ulong = v_flags;
+}
+
+guint
+g_value_get_flags (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_FLAGS (value), 0);
+
+ return value->data[0].v_ulong;
+}
+
+void
+g_value_set_float (GValue *value,
+ gfloat v_float)
+{
+ g_return_if_fail (G_IS_VALUE_FLOAT (value));
+
+ value->data[0].v_float = v_float;
+}
+
+gfloat
+g_value_get_float (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_FLOAT (value), 0);
+
+ return value->data[0].v_float;
+}
+
+void
+g_value_set_double (GValue *value,
+ gdouble v_double)
+{
+ g_return_if_fail (G_IS_VALUE_DOUBLE (value));
+
+ value->data[0].v_double = v_double;
+}
+
+gdouble
+g_value_get_double (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_DOUBLE (value), 0);
+
+ return value->data[0].v_double;
+}
+
+void
+g_value_set_string (GValue *value,
+ const gchar *v_string)
+{
+ g_return_if_fail (G_IS_VALUE_STRING (value));
+
+ g_free (value->data[0].v_pointer);
+ value->data[0].v_pointer = g_strdup (v_string);
+}
+
+gchar*
+g_value_get_string (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_STRING (value), NULL);
+
+ return value->data[0].v_pointer;
+}
+
+gchar*
+g_value_dup_string (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_STRING (value), NULL);
+
+ return g_strdup (value->data[0].v_pointer);
+}
+
+void
+g_value_set_object (GValue *value,
+ GObject *v_object)
+{
+ g_return_if_fail (G_IS_VALUE_OBJECT (value));
+ if (v_object)
+ g_return_if_fail (G_IS_OBJECT (v_object));
+
+ if (value->data[0].v_pointer)
+ g_object_unref (value->data[0].v_pointer);
+ value->data[0].v_pointer = v_object;
+ if (value->data[0].v_pointer)
+ g_object_ref (value->data[0].v_pointer);
+}
+
+GObject*
+g_value_get_object (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
+
+ return value->data[0].v_pointer;
+}
+
+GObject*
+g_value_dup_object (GValue *value)
+{
+ g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
+
+ return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
+}
+
+
+/* --- GParamSpec initialization --- */
+GParamSpec*
+g_param_spec_char (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gint8 minimum,
+ gint8 maximum,
+ gint8 default_value,
+ GParamFlags flags)
+{
+ GParamSpecChar *cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ cspec->minimum = minimum;
+ cspec->maximum = maximum;
+ cspec->default_value = default_value;
+
+ return G_PARAM_SPEC (cspec);
+}
+
+GParamSpec*
+g_param_spec_uchar (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ guint8 minimum,
+ guint8 maximum,
+ guint8 default_value,
+ GParamFlags flags)
+{
+ GParamSpecUChar *uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ uspec->minimum = minimum;
+ uspec->maximum = maximum;
+ uspec->default_value = default_value;
+
+ return G_PARAM_SPEC (uspec);
+}
+
+GParamSpec*
+g_param_spec_bool (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean default_value,
+ GParamFlags flags)
+{
+ GParamSpecBool *bspec = g_param_spec_internal (G_TYPE_PARAM_BOOL,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ bspec->default_value = default_value;
+
+ return G_PARAM_SPEC (bspec);
+}
+
+GParamSpec*
+g_param_spec_int (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gint minimum,
+ gint maximum,
+ gint default_value,
+ GParamFlags flags)
+{
+ GParamSpecInt *ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ ispec->minimum = minimum;
+ ispec->maximum = maximum;
+ ispec->default_value = default_value;
+
+ return G_PARAM_SPEC (ispec);
+}
+
+GParamSpec*
+g_param_spec_uint (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ guint minimum,
+ guint maximum,
+ guint default_value,
+ GParamFlags flags)
+{
+ GParamSpecUInt *uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ uspec->minimum = minimum;
+ uspec->maximum = maximum;
+ uspec->default_value = default_value;
+
+ return G_PARAM_SPEC (uspec);
+}
+
+GParamSpec*
+g_param_spec_long (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ glong minimum,
+ glong maximum,
+ glong default_value,
+ GParamFlags flags)
+{
+ GParamSpecLong *lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ lspec->minimum = minimum;
+ lspec->maximum = maximum;
+ lspec->default_value = default_value;
+
+ return G_PARAM_SPEC (lspec);
+}
+
+GParamSpec*
+g_param_spec_ulong (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gulong minimum,
+ gulong maximum,
+ gulong default_value,
+ GParamFlags flags)
+{
+ GParamSpecULong *uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ uspec->minimum = minimum;
+ uspec->maximum = maximum;
+ uspec->default_value = default_value;
+
+ return G_PARAM_SPEC (uspec);
+}
+
+GParamSpec*
+g_param_spec_enum (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GType enum_type,
+ gint default_value,
+ GParamFlags flags)
+{
+ GParamSpecEnum *espec;
+
+ g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
+
+ espec = g_param_spec_internal (G_TYPE_PARAM_ENUM,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ espec->enum_class = g_type_class_ref (enum_type);
+ espec->default_value = default_value;
+
+ return G_PARAM_SPEC (espec);
+}
+
+GParamSpec*
+g_param_spec_flags (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GType flags_type,
+ guint default_value,
+ GParamFlags flags)
+{
+ GParamSpecFlags *fspec;
+
+ g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
+
+ fspec = g_param_spec_internal (G_TYPE_PARAM_FLAGS,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ fspec->flags_class = g_type_class_ref (flags_type);
+ fspec->default_value = default_value;
+
+ return G_PARAM_SPEC (fspec);
+}
+
+GParamSpec*
+g_param_spec_float (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gfloat minimum,
+ gfloat maximum,
+ gfloat default_value,
+ GParamFlags flags)
+{
+ GParamSpecFloat *fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ fspec->minimum = minimum;
+ fspec->maximum = maximum;
+ fspec->default_value = default_value;
+
+ return G_PARAM_SPEC (fspec);
+}
+
+GParamSpec*
+g_param_spec_double (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gdouble minimum,
+ gdouble maximum,
+ gdouble default_value,
+ GParamFlags flags)
+{
+ GParamSpecDouble *dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
+ name,
+ nick,
+ blurb,
+ flags);
+
+ dspec->minimum = minimum;
+ dspec->maximum = maximum;
+ dspec->default_value = default_value;
+
+ return G_PARAM_SPEC (dspec);
+}
+
+GParamSpec*
+g_param_spec_string (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const gchar *default_value,
+ GParamFlags flags)
+{
+ GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
+ name,
+ nick,
+ blurb,
+ flags);
+ g_free (sspec->default_value);
+ sspec->default_value = g_strdup (default_value);
+
+ return G_PARAM_SPEC (sspec);
+}
+
+GParamSpec*
+g_param_spec_string_c (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const gchar *default_value,
+ GParamFlags flags)
+{
+ GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
+ name,
+ nick,
+ blurb,
+ flags);
+ g_free (sspec->default_value);
+ sspec->default_value = g_strdup (default_value);
+ g_free (sspec->cset_first);
+ sspec->cset_first = g_strdup (G_CSET_a_2_z "_" G_CSET_A_2_Z);
+ g_free (sspec->cset_nth);
+ sspec->cset_nth = g_strdup (G_CSET_a_2_z
+ "_0123456789"
+ /* G_CSET_LATINS G_CSET_LATINC */
+ G_CSET_A_2_Z);
+
+ return G_PARAM_SPEC (sspec);
+}
+
+GParamSpec*
+g_param_spec_object (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GType object_type,
+ GParamFlags flags)
+{
+ GParamSpecObject *ospec;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+
+ ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
+ name,
+ nick,
+ blurb,
+ flags);
+ ospec->object_type = object_type;
+
+ return G_PARAM_SPEC (ospec);
+}
diff --git a/gobject/gparamspecs.h b/gobject/gparamspecs.h
new file mode 100644
index 000000000..1becdefe8
--- /dev/null
+++ b/gobject/gparamspecs.h
@@ -0,0 +1,335 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ *
+ * gparamspecs.h: GLib default param specs
+ */
+#ifndef __G_PARAMSPECS_H__
+#define __G_PARAMSPECS_H__
+
+
+#include <gobject/gvalue.h>
+#include <gobject/genums.h>
+#include <gobject/gobject.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define G_IS_VALUE_CHAR(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_CHAR))
+#define G_IS_PARAM_SPEC_CHAR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CHAR))
+#define G_PARAM_SPEC_CHAR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CHAR, GParamSpecChar))
+#define G_IS_VALUE_UCHAR(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_UCHAR))
+#define G_IS_PARAM_SPEC_UCHAR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UCHAR))
+#define G_PARAM_SPEC_UCHAR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UCHAR, GParamSpecUChar))
+#define G_IS_VALUE_BOOL(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_BOOL))
+#define G_IS_PARAM_SPEC_BOOL(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_BOOL))
+#define G_PARAM_SPEC_BOOL(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_BOOL, GParamSpecBool))
+#define G_IS_VALUE_INT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_INT))
+#define G_IS_PARAM_SPEC_INT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_INT))
+#define G_PARAM_SPEC_INT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_INT, GParamSpecInt))
+#define G_IS_VALUE_UINT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_UINT))
+#define G_IS_PARAM_SPEC_UINT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UINT))
+#define G_PARAM_SPEC_UINT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UINT, GParamSpecUInt))
+#define G_IS_VALUE_LONG(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_LONG))
+#define G_IS_PARAM_SPEC_LONG(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_LONG))
+#define G_PARAM_SPEC_LONG(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_LONG, GParamSpecLong))
+#define G_IS_VALUE_ULONG(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_ULONG))
+#define G_IS_PARAM_SPEC_ULONG(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ULONG))
+#define G_PARAM_SPEC_ULONG(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ULONG, GParamSpecULong))
+#define G_IS_VALUE_ENUM(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_ENUM))
+#define G_IS_PARAM_SPEC_ENUM(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ENUM))
+#define G_PARAM_SPEC_ENUM(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ENUM, GParamSpecEnum))
+#define G_IS_VALUE_FLAGS(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_FLAGS))
+#define G_IS_PARAM_SPEC_FLAGS(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLAGS))
+#define G_PARAM_SPEC_FLAGS(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLAGS, GParamSpecFlags))
+#define G_IS_VALUE_FLOAT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_FLOAT))
+#define G_IS_PARAM_SPEC_FLOAT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLOAT))
+#define G_PARAM_SPEC_FLOAT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLOAT, GParamSpecFloat))
+#define G_IS_VALUE_DOUBLE(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_DOUBLE))
+#define G_IS_PARAM_SPEC_DOUBLE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_DOUBLE))
+#define G_PARAM_SPEC_DOUBLE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_DOUBLE, GParamSpecDouble))
+#define G_IS_VALUE_STRING(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_STRING))
+#define G_IS_PARAM_SPEC_STRING(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_STRING))
+#define G_PARAM_SPEC_STRING(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_STRING, GParamSpecString))
+#define G_IS_VALUE_OBJECT(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM_OBJECT))
+#define G_IS_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT))
+#define G_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject))
+
+
+/* --- typedefs & structures --- */
+typedef struct _GParamSpecChar GParamSpecChar;
+typedef struct _GParamSpecUChar GParamSpecUChar;
+typedef struct _GParamSpecBool GParamSpecBool;
+typedef struct _GParamSpecInt GParamSpecInt;
+typedef struct _GParamSpecUInt GParamSpecUInt;
+typedef struct _GParamSpecLong GParamSpecLong;
+typedef struct _GParamSpecULong GParamSpecULong;
+typedef struct _GParamSpecEnum GParamSpecEnum;
+typedef struct _GParamSpecFlags GParamSpecFlags;
+typedef struct _GParamSpecFloat GParamSpecFloat;
+typedef struct _GParamSpecDouble GParamSpecDouble;
+typedef struct _GParamSpecString GParamSpecString;
+typedef struct _GParamSpecObject GParamSpecObject;
+struct _GParamSpecChar
+{
+ GParamSpec parent_instance;
+
+ gint8 minimum;
+ gint8 maximum;
+ gint8 default_value;
+};
+struct _GParamSpecUChar
+{
+ GParamSpec parent_instance;
+
+ guint8 minimum;
+ guint8 maximum;
+ guint8 default_value;
+};
+struct _GParamSpecBool
+{
+ GParamSpec parent_instance;
+
+ gboolean default_value;
+};
+struct _GParamSpecInt
+{
+ GParamSpec parent_instance;
+
+ gint minimum;
+ gint maximum;
+ gint default_value;
+};
+struct _GParamSpecUInt
+{
+ GParamSpec parent_instance;
+
+ guint minimum;
+ guint maximum;
+ guint default_value;
+};
+struct _GParamSpecLong
+{
+ GParamSpec parent_instance;
+
+ glong minimum;
+ glong maximum;
+ glong default_value;
+};
+struct _GParamSpecULong
+{
+ GParamSpec parent_instance;
+
+ gulong minimum;
+ gulong maximum;
+ gulong default_value;
+};
+struct _GParamSpecEnum
+{
+ GParamSpec parent_instance;
+
+ GEnumClass *enum_class;
+ glong default_value;
+};
+struct _GParamSpecFlags
+{
+ GParamSpec parent_instance;
+
+ GFlagsClass *flags_class;
+ gulong default_value;
+};
+struct _GParamSpecFloat
+{
+ GParamSpec parent_instance;
+
+ gfloat minimum;
+ gfloat maximum;
+ gfloat default_value;
+ gfloat epsilon;
+};
+struct _GParamSpecDouble
+{
+ GParamSpec parent_instance;
+
+ gdouble minimum;
+ gdouble maximum;
+ gdouble default_value;
+ gdouble epsilon;
+};
+struct _GParamSpecString
+{
+ GParamSpec parent_instance;
+
+ gchar *default_value;
+ gchar *cset_first;
+ gchar *cset_nth;
+ gchar substitutor;
+ guint null_fold_if_empty : 1;
+ guint ensure_non_null : 1;
+};
+struct _GParamSpecObject
+{
+ GParamSpec parent_instance;
+
+ GType object_type;
+};
+
+
+/* --- GValue prototypes --- */
+void g_value_set_char (GValue *value,
+ gint8 v_char);
+gint8 g_value_get_char (GValue *value);
+void g_value_set_uchar (GValue *value,
+ guint8 v_uchar);
+guint8 g_value_get_uchar (GValue *value);
+void g_value_set_bool (GValue *value,
+ gboolean v_bool);
+gboolean g_value_get_bool (GValue *value);
+void g_value_set_int (GValue *value,
+ gint v_int);
+gint g_value_get_int (GValue *value);
+void g_value_set_uint (GValue *value,
+ guint v_uint);
+guint g_value_get_uint (GValue *value);
+void g_value_set_long (GValue *value,
+ glong v_long);
+glong g_value_get_long (GValue *value);
+void g_value_set_ulong (GValue *value,
+ gulong v_ulong);
+gulong g_value_get_ulong (GValue *value);
+void g_value_set_enum (GValue *value,
+ gint v_enum);
+gint g_value_get_enum (GValue *value);
+void g_value_set_flags (GValue *value,
+ guint v_flags);
+guint g_value_get_flags (GValue *value);
+void g_value_set_float (GValue *value,
+ gfloat v_float);
+gfloat g_value_get_float (GValue *value);
+void g_value_set_double (GValue *value,
+ gdouble v_double);
+gdouble g_value_get_double (GValue *value);
+void g_value_set_string (GValue *value,
+ const gchar *v_string);
+gchar* g_value_get_string (GValue *value);
+gchar* g_value_dup_string (GValue *value);
+void g_value_set_object (GValue *value,
+ GObject *v_object);
+GObject* g_value_get_object (GValue *value);
+GObject* g_value_dup_object (GValue *value);
+
+
+/* --- GParamSpec prototypes --- */
+GParamSpec* g_param_spec_char (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gint8 minimum,
+ gint8 maximum,
+ gint8 default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_uchar (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ guint8 minimum,
+ guint8 maximum,
+ guint8 default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_bool (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_int (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gint minimum,
+ gint maximum,
+ gint default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_uint (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ guint minimum,
+ guint maximum,
+ guint default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_long (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ glong minimum,
+ glong maximum,
+ glong default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_ulong (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gulong minimum,
+ gulong maximum,
+ gulong default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_enum (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GType enum_type,
+ gint default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_flags (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GType flags_type,
+ guint default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_float (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gfloat minimum,
+ gfloat maximum,
+ gfloat default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_double (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gdouble minimum,
+ gdouble maximum,
+ gdouble default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_string (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const gchar *default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_string_c (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const gchar *default_value,
+ GParamFlags flags);
+GParamSpec* g_param_spec_object (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GType object_type,
+ GParamFlags flags);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_PARAMSPECS_H__ */
diff --git a/gobject/gtype.c b/gobject/gtype.c
new file mode 100644
index 000000000..1b6a313d1
--- /dev/null
+++ b/gobject/gtype.c
@@ -0,0 +1,1825 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "gtype.h"
+
+#include "genums.h"
+#include "gobject.h"
+#include <string.h>
+
+#define FIXME_DISABLE_PREALLOCATIONS
+
+/* NOTE: some functions (some internal variants and exported ones)
+ * invalidate data portions of the TypeNodes. if external functions/callbacks
+ * are called, pointers to memory maintained by TypeNodes have to be looked up
+ * again. this affects most of the struct TypeNode fields, e.g. ->children or
+ * ->iface_entries (not ->supers[] as of recently), as all those memory portions can
+ * get realloc()ed during callback invocation.
+ *
+ * TODO:
+ * - g_type_from_name() should do an ordered array lookup after fetching the
+ * the quark, instead of a second hashtable lookup.
+ *
+ * FIXME:
+ * - force interface initialization for already existing classes
+ */
+
+#define G_TYPE_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
+ G_TYPE_FLAG_INSTANTIATABLE | \
+ G_TYPE_FLAG_DERIVABLE | \
+ G_TYPE_FLAG_DEEP_DERIVABLE)
+#define g_type_plugin_ref(p) ((p)->vtable->plugin_ref (p))
+#define g_type_plugin_unref(p) ((p)->vtable->plugin_unref (p))
+#define g_type_plugin_complete_type_info(p,t,i) ((p)->vtable->complete_type_info ((p), (t), (i)))
+#define g_type_plugin_complete_interface_info(p,f,t,i) ((p)->vtable->complete_interface_info ((p), (f), (t), (i)))
+
+typedef struct _TypeNode TypeNode;
+typedef struct _CommonData CommonData;
+typedef struct _IFaceData IFaceData;
+typedef struct _ClassData ClassData;
+typedef struct _InstanceData InstanceData;
+typedef union _TypeData TypeData;
+typedef struct _IFaceEntry IFaceEntry;
+typedef struct _IFaceHolder IFaceHolder;
+
+
+/* --- prototypes --- */
+static inline GTypeFundamentalInfo* type_node_fundamental_info (TypeNode *node);
+static void type_data_make (TypeNode *node,
+ const GTypeInfo *info);
+static inline void type_data_ref (TypeNode *node);
+static inline void type_data_unref (TypeNode *node);
+static void type_data_last_unref (GType type);
+
+
+/* --- structures --- */
+struct _TypeNode
+{
+ GTypePlugin *plugin;
+ guint n_children : 12;
+ guint n_supers : 8;
+ guint n_ifaces : 9;
+ guint is_classed : 1;
+ guint is_instantiatable : 1;
+ guint is_iface : 1;
+ GType *children;
+ TypeData *data;
+ GQuark qname;
+ GData *static_gdata;
+ union {
+ IFaceEntry *iface_entries;
+ IFaceHolder *iholders;
+ } private;
+ GType supers[1]; /* flexible array */
+};
+#define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
+#define MAX_N_SUPERS (255)
+#define MAX_N_CHILDREN (4095)
+#define MAX_N_IFACES (511)
+
+struct _IFaceHolder
+{
+ GType instance_type;
+ GInterfaceInfo *info;
+ GTypePlugin *plugin;
+ IFaceHolder *next;
+};
+struct _CommonData
+{
+ guint ref_count;
+};
+struct _IFaceData
+{
+ CommonData common;
+ guint vtable_size;
+ GBaseInitFunc vtable_init_base;
+ GBaseFinalizeFunc vtable_finalize_base;
+};
+struct _ClassData
+{
+ CommonData common;
+ guint class_size;
+ GBaseInitFunc class_init_base;
+ GBaseFinalizeFunc class_finalize_base;
+ GClassInitFunc class_init;
+ GClassFinalizeFunc class_finalize;
+ gconstpointer class_data;
+ gpointer class;
+};
+struct _InstanceData
+{
+ CommonData common;
+ guint class_size;
+ GBaseInitFunc class_init_base;
+ GBaseFinalizeFunc class_finalize_base;
+ GClassInitFunc class_init;
+ GClassFinalizeFunc class_finalize;
+ gconstpointer class_data;
+ gpointer class;
+ guint16 instance_size;
+ guint16 n_preallocs;
+ GInstanceInitFunc instance_init;
+ GMemChunk *mem_chunk;
+};
+union _TypeData
+{
+ CommonData common;
+ IFaceData iface;
+ ClassData class;
+ InstanceData instance;
+};
+struct _IFaceEntry
+{
+ GType iface_type;
+ GTypeInterface *vtable;
+};
+
+
+/* --- externs --- */
+const char *g_log_domain_gobject = "GLib-Object";
+GType _g_type_fundamental_last = 0;
+
+
+/* --- type nodes --- */
+static GHashTable *g_type_nodes_ht = NULL;
+static GType *g_branch_seqnos = NULL;
+static TypeNode ***g_type_nodes = NULL;
+
+static inline TypeNode*
+LOOKUP_TYPE_NODE (register GType utype)
+{
+ register GType ftype = G_TYPE_FUNDAMENTAL (utype);
+ register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
+
+ if (ftype < G_TYPE_FUNDAMENTAL_LAST && b_seqno < g_branch_seqnos[ftype])
+ return g_type_nodes[ftype][b_seqno];
+ else
+ return NULL;
+}
+#define NODE_TYPE(node) (node->supers[0])
+#define NODE_PARENT_TYPE(node) (node->supers[1])
+#define NODE_NAME(node) (g_quark_to_string (node->qname))
+
+static TypeNode*
+type_node_any_new (TypeNode *pnode,
+ GType ftype,
+ const gchar *name,
+ GTypePlugin *plugin,
+ GTypeFlags type_flags)
+{
+ guint branch_last, n_supers = pnode ? pnode->n_supers + 1 : 0;
+ GType type;
+ TypeNode *node;
+ guint i, node_size = 0;
+
+ branch_last = g_branch_seqnos[ftype]++;
+ type = G_TYPE_DERIVE_ID (ftype, branch_last);
+ if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (g_branch_seqnos[ftype] - 1))
+ g_type_nodes[ftype] = g_renew (TypeNode*, g_type_nodes[ftype], 1 << g_bit_storage (g_branch_seqnos[ftype] - 1));
+
+ if (!pnode)
+ node_size += sizeof (GTypeFundamentalInfo); /* fundamental type */
+ node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
+ node_size += sizeof (GType[1 + n_supers + 1]); /* self + anchestors + 0 for ->supers[] */
+ node = g_malloc0 (node_size);
+ if (!pnode) /* fundamental type */
+ node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
+ g_type_nodes[ftype][branch_last] = node;
+
+ node->n_supers = n_supers;
+ if (!pnode)
+ {
+ node->supers[0] = type;
+ node->supers[1] = 0;
+
+ node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
+ node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
+ node->is_iface = G_TYPE_IS_INTERFACE (type);
+
+ node->n_ifaces = 0;
+ if (node->is_iface)
+ node->private.iholders = NULL;
+ else
+ node->private.iface_entries = NULL;
+ }
+ else
+ {
+ node->supers[0] = type;
+ memcpy (node->supers + 1, pnode->supers, sizeof (GType[1 + pnode->n_supers + 1]));
+
+ node->is_classed = pnode->is_classed;
+ node->is_instantiatable = pnode->is_instantiatable;
+ node->is_iface = pnode->is_iface;
+
+ if (node->is_iface)
+ {
+ node->n_ifaces = 0;
+ node->private.iholders = NULL;
+ }
+ else
+ {
+ node->n_ifaces = pnode->n_ifaces;
+ node->private.iface_entries = g_memdup (pnode->private.iface_entries,
+ sizeof (pnode->private.iface_entries[0]) * node->n_ifaces);
+ }
+
+ i = pnode->n_children++;
+ pnode->children = g_renew (GType, pnode->children, pnode->n_children);
+ pnode->children[i] = type;
+ }
+
+ node->plugin = plugin;
+ node->n_children = 0;
+ node->children = NULL;
+ node->data = NULL;
+ node->qname = g_quark_from_string (name);
+ node->static_gdata = NULL;
+
+ g_hash_table_insert (g_type_nodes_ht,
+ GUINT_TO_POINTER (node->qname),
+ GUINT_TO_POINTER (type));
+
+ return node;
+}
+
+static inline GTypeFundamentalInfo*
+type_node_fundamental_info (TypeNode *node)
+{
+ GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
+
+ if (ftype != NODE_TYPE (node))
+ node = LOOKUP_TYPE_NODE (ftype);
+
+ return node ? G_STRUCT_MEMBER_P (node, - sizeof (GTypeFundamentalInfo)) : NULL;
+}
+
+static TypeNode*
+type_node_fundamental_new (GType ftype,
+ const gchar *name,
+ GTypeFlags type_flags)
+{
+ GTypeFundamentalInfo *finfo;
+ TypeNode *node;
+ guint i, flast = G_TYPE_FUNDAMENTAL_LAST;
+
+ g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
+
+ type_flags &= G_TYPE_FLAG_MASK;
+
+ _g_type_fundamental_last = MAX (_g_type_fundamental_last, ftype + 1);
+ if (G_TYPE_FUNDAMENTAL_LAST > flast)
+ {
+ g_type_nodes = g_renew (TypeNode**, g_type_nodes, G_TYPE_FUNDAMENTAL_LAST);
+ g_branch_seqnos = g_renew (GType, g_branch_seqnos, G_TYPE_FUNDAMENTAL_LAST);
+ for (i = flast; i < G_TYPE_FUNDAMENTAL_LAST; i++)
+ {
+ g_type_nodes[i] = NULL;
+ g_branch_seqnos[i] = 0;
+ }
+ }
+ g_assert (g_branch_seqnos[ftype] == 0);
+
+ node = type_node_any_new (NULL, ftype, name, NULL, type_flags);
+ finfo = type_node_fundamental_info (node);
+ finfo->type_flags = type_flags;
+
+ return node;
+}
+
+static TypeNode*
+type_node_new (TypeNode *pnode,
+ const gchar *name,
+ GTypePlugin *plugin)
+
+{
+ g_assert (pnode);
+ g_assert (pnode->n_supers < MAX_N_SUPERS);
+ g_assert (pnode->n_children < MAX_N_CHILDREN);
+
+ return type_node_any_new (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
+}
+
+static inline IFaceEntry*
+type_lookup_iface_entry (TypeNode *node,
+ TypeNode *iface)
+{
+ if (iface->is_iface && node->n_ifaces)
+ {
+ IFaceEntry *ifaces = node->private.iface_entries - 1;
+ guint n_ifaces = node->n_ifaces;
+ GType iface_type = NODE_TYPE (iface);
+
+ do /* FIXME: should optimize iface lookups for <= 4 */
+ {
+ guint i;
+ IFaceEntry *check;
+
+ i = (n_ifaces + 1) / 2;
+ check = ifaces + i;
+ if (iface_type == check->iface_type)
+ return check;
+ else if (iface_type > check->iface_type)
+ {
+ n_ifaces -= i;
+ ifaces = check;
+ }
+ else /* if (iface_type < check->iface_type) */
+ n_ifaces = i - 1;
+ }
+ while (n_ifaces);
+ }
+
+ return NULL;
+}
+
+static inline gchar*
+type_descriptive_name (GType type)
+{
+ if (type)
+ {
+ gchar *name = g_type_name (type);
+
+ return name ? name : "<unknown>";
+ }
+ else
+ return "<invalid>";
+}
+
+
+/* --- type consistency checks --- */
+static gboolean
+check_plugin (GTypePlugin *plugin,
+ gboolean need_complete_type_info,
+ gboolean need_complete_interface_info,
+ const gchar *type_name)
+{
+ if (!plugin)
+ {
+ g_warning ("plugin handle for type `%s' is NULL",
+ type_name);
+ return FALSE;
+ }
+ if (!plugin->vtable)
+ {
+ g_warning ("plugin for type `%s' has no function table",
+ type_name);
+ return FALSE;
+ }
+ if (!plugin->vtable->plugin_ref)
+ {
+ g_warning ("plugin for type `%s' has no plugin_ref() implementation",
+ type_name);
+ return FALSE;
+ }
+ if (!plugin->vtable->plugin_unref)
+ {
+ g_warning ("plugin for type `%s' has no plugin_unref() implementation",
+ type_name);
+ return FALSE;
+ }
+ if (need_complete_type_info && !plugin->vtable->complete_type_info)
+ {
+ g_warning ("plugin for type `%s' has no complete_type_info() implementation",
+ type_name);
+ return FALSE;
+ }
+ if (need_complete_interface_info && !plugin->vtable->complete_interface_info)
+ {
+ g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
+ type_name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+check_type_name (const gchar *type_name)
+{
+ static const gchar *extra_chars = "-_+";
+ const gchar *p = type_name;
+ gboolean name_valid;
+
+ if (!type_name[0] || !type_name[1] || !type_name[2])
+ {
+ g_warning ("type name `%s' is too short", type_name);
+ return FALSE;
+ }
+ /* check the first letter */
+ name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
+ for (p = type_name + 1; *p; p++)
+ name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
+ (p[0] >= 'a' && p[0] <= 'z') ||
+ (p[0] >= '0' && p[0] <= '9') ||
+ strchr (extra_chars, p[0]));
+ if (!name_valid)
+ {
+ g_warning ("type name `%s' contains invalid characters", type_name);
+ return FALSE;
+ }
+ if (g_type_from_name (type_name))
+ {
+ g_warning ("cannot register existing type `%s'", type_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_derivation (GType parent_type,
+ const gchar *type_name)
+{
+ TypeNode *pnode = LOOKUP_TYPE_NODE (parent_type);
+ GTypeFundamentalInfo* finfo = type_node_fundamental_info (pnode);
+
+ if (!pnode)
+ {
+ g_warning ("cannot derive type `%s' from invalid parent type `%s'",
+ type_name,
+ type_descriptive_name (parent_type));
+ return FALSE;
+ }
+ /* ensure flat derivability */
+ if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
+ {
+ g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
+ type_name,
+ NODE_NAME (pnode));
+ return FALSE;
+ }
+ /* ensure deep derivability */
+ if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
+ !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
+ {
+ g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
+ type_name,
+ NODE_NAME (pnode));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_type_info (TypeNode *pnode,
+ GType ftype,
+ const gchar *type_name,
+ const GTypeInfo *info)
+{
+ GTypeFundamentalInfo *finfo = type_node_fundamental_info (LOOKUP_TYPE_NODE (ftype));
+ gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
+
+ /* check instance members */
+ if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
+ (info->instance_size || info->n_preallocs || info->instance_init))
+ {
+ if (pnode)
+ g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
+ type_name,
+ NODE_NAME (pnode));
+ else
+ g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
+ type_name);
+ return FALSE;
+ }
+ /* check class & interface members */
+ if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) &&
+ (info->class_init || info->class_finalize || info->class_data ||
+ (!is_interface && (info->class_size || info->base_init || info->base_finalize))))
+ {
+ if (pnode)
+ g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
+ type_name,
+ NODE_NAME (pnode));
+ else
+ g_warning ("cannot create class for `%s' as non-classed fundamental",
+ type_name);
+ return FALSE;
+ }
+ /* check interface size */
+ if (is_interface && info->class_size < sizeof (GTypeInterface))
+ {
+ g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
+ type_name);
+ return FALSE;
+ }
+ /* check class size */
+ if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
+ {
+ if (info->class_size < sizeof (GTypeClass))
+ {
+ g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
+ type_name);
+ return FALSE;
+ }
+ if (pnode && info->class_size < pnode->data->class.class_size)
+ {
+ g_warning ("specified class size for type `%s' is smaller "
+ "than the parent type's `%s' class size",
+ type_name,
+ NODE_NAME (pnode));
+ return FALSE;
+ }
+ }
+ /* check instance size */
+ if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
+ {
+ if (info->instance_size < sizeof (GTypeInstance))
+ {
+ g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
+ type_name);
+ return FALSE;
+ }
+ if (pnode && info->instance_size < pnode->data->instance.instance_size)
+ {
+ g_warning ("specified instance size for type `%s' is smaller "
+ "than the parent type's `%s' instance size",
+ type_name,
+ NODE_NAME (pnode));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static TypeNode*
+find_conforming_type (TypeNode *pnode,
+ TypeNode *iface)
+{
+ TypeNode *node = NULL;
+ guint i;
+
+ if (type_lookup_iface_entry (pnode, iface))
+ return pnode;
+
+ for (i = 0; i < pnode->n_children && !node; i++)
+ node = find_conforming_type (LOOKUP_TYPE_NODE (pnode->children[i]), iface);
+
+ return node;
+}
+
+static gboolean
+check_add_interface (GType instance_type,
+ GType iface_type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (instance_type);
+ TypeNode *iface = LOOKUP_TYPE_NODE (iface_type);
+ TypeNode *tnode;
+
+ if (!node || !node->is_instantiatable)
+ {
+ g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
+ type_descriptive_name (instance_type));
+ return FALSE;
+ }
+ if (!iface || !iface->is_iface)
+ {
+ g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
+ type_descriptive_name (iface_type),
+ NODE_NAME (node));
+ return FALSE;
+ }
+ tnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (iface));
+ if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry (node, tnode))
+ {
+ g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
+ NODE_NAME (iface),
+ NODE_NAME (node),
+ NODE_NAME (tnode));
+ return FALSE;
+ }
+ tnode = find_conforming_type (node, iface);
+ if (tnode)
+ {
+ g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
+ NODE_NAME (iface),
+ NODE_NAME (node),
+ NODE_NAME (tnode));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_interface_info (TypeNode *iface,
+ GType instance_type,
+ const GInterfaceInfo *info)
+{
+ if ((info->interface_finalize || info->interface_data) && !info->interface_init)
+ {
+ g_warning ("interface type `%s' for type `%s' comes without initializer",
+ NODE_NAME (iface),
+ type_descriptive_name (instance_type));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* --- type info (type node data) --- */
+static void
+type_data_make (TypeNode *node,
+ const GTypeInfo *info)
+{
+ TypeData *data = NULL;
+
+ g_assert (node->data == NULL && info != NULL);
+
+ if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
+ {
+ data = g_malloc0 (sizeof (InstanceData));
+ data->instance.class_size = info->class_size;
+ data->instance.class_init_base = info->base_init;
+ data->instance.class_finalize_base = info->base_finalize;
+ data->instance.class_init = info->class_init;
+ data->instance.class_finalize = info->class_finalize;
+ data->instance.class_data = info->class_data;
+ data->instance.class = NULL;
+ data->instance.instance_size = info->instance_size;
+ data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
+#ifdef FIXME_DISABLE_PREALLOCATIONS
+ data->instance.n_preallocs = 0;
+#endif
+ data->instance.instance_init = info->instance_init;
+ data->instance.mem_chunk = NULL;
+ }
+ else if (node->is_classed) /* only classed */
+ {
+ data = g_malloc0 (sizeof (ClassData));
+ data->class.class_size = info->class_size;
+ data->class.class_init_base = info->base_init;
+ data->class.class_finalize_base = info->base_finalize;
+ data->class.class_init = info->class_init;
+ data->class.class_finalize = info->class_finalize;
+ data->class.class_data = info->class_data;
+ data->class.class = NULL;
+ }
+ else if (node->is_iface)
+ {
+ data = g_malloc0 (sizeof (IFaceData));
+ data->iface.vtable_size = info->class_size;
+ data->iface.vtable_init_base = info->base_init;
+ data->iface.vtable_finalize_base = info->base_finalize;
+ }
+ else
+ data = g_malloc0 (sizeof (CommonData));
+
+ node->data = data;
+ node->data->common.ref_count = 1;
+}
+
+static inline void
+type_data_ref (TypeNode *node)
+{
+ if (!node->data)
+ {
+ TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
+ GTypeInfo tmpinfo;
+
+ g_assert (node->plugin != NULL);
+
+ if (pnode)
+ type_data_ref (pnode);
+
+ memset (&tmpinfo, 0, sizeof (tmpinfo));
+ g_type_plugin_ref (node->plugin);
+ g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmpinfo);
+ check_type_info (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmpinfo);
+ type_data_make (node, &tmpinfo);
+ }
+ else
+ {
+ g_assert (node->data->common.ref_count > 0);
+
+ node->data->common.ref_count += 1;
+ }
+}
+
+static inline void
+type_data_unref (TypeNode *node)
+{
+ g_assert (node->data && node->data->common.ref_count);
+
+ if (node->data->common.ref_count > 1)
+ node->data->common.ref_count -= 1;
+ else
+ {
+ if (!node->plugin)
+ {
+ g_warning ("static type `%s' unreferenced too often",
+ NODE_NAME (node));
+ return;
+ }
+
+ type_data_last_unref (NODE_TYPE (node));
+ }
+}
+
+static void
+type_node_add_iface_entry (TypeNode *node,
+ GType iface_type)
+{
+ IFaceEntry *entries;
+ guint i;
+
+ g_assert (node->is_instantiatable && node->n_ifaces < MAX_N_IFACES);
+
+ node->n_ifaces++;
+ node->private.iface_entries = g_renew (IFaceEntry, node->private.iface_entries, node->n_ifaces);
+ entries = node->private.iface_entries;
+ for (i = 0; i < node->n_ifaces - 1; i++)
+ if (entries[i].iface_type > iface_type)
+ break;
+ g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (node->n_ifaces - i - 1));
+ entries[i].iface_type = iface_type;
+ entries[i].vtable = NULL;
+
+ for (i = 0; i < node->n_children; i++)
+ type_node_add_iface_entry (LOOKUP_TYPE_NODE (node->children[i]), iface_type);
+}
+
+static void
+type_add_interface (TypeNode *node,
+ TypeNode *iface,
+ GInterfaceInfo *info,
+ GTypePlugin *plugin)
+{
+ IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
+
+ /* we must not call any functions of GInterfaceInfo from within here, since
+ * we got most probably called from _within_ a type registration function
+ */
+ g_assert (node->is_instantiatable && iface->is_iface && ((info && !plugin) || (!info && plugin)));
+
+ iholder->next = iface->private.iholders;
+ iface->private.iholders = iholder;
+ iholder->instance_type = NODE_TYPE (node);
+ iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
+ iholder->plugin = plugin;
+
+ type_node_add_iface_entry (node, NODE_TYPE (iface));
+}
+
+static IFaceHolder*
+type_iface_retrive_holder_info (TypeNode *iface,
+ GType instance_type)
+{
+ IFaceHolder *iholder = iface->private.iholders;
+
+ g_assert (iface->is_iface);
+
+ while (iholder->instance_type != instance_type)
+ iholder = iholder->next;
+
+ if (!iholder->info)
+ {
+ GInterfaceInfo tmpinfo;
+
+ g_assert (iholder->plugin != NULL);
+
+ type_data_ref (iface);
+
+ memset (&tmpinfo, 0, sizeof (tmpinfo));
+ g_type_plugin_ref (iholder->plugin);
+ g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmpinfo);
+ check_interface_info (iface, instance_type, &tmpinfo);
+ iholder->info = g_memdup (&tmpinfo, sizeof (tmpinfo));
+ }
+
+ return iholder;
+}
+
+static void
+type_iface_blow_holder_info (TypeNode *iface,
+ GType instance_type)
+{
+ IFaceHolder *iholder = iface->private.iholders;
+
+ g_assert (iface->is_iface);
+
+ while (iholder->instance_type != instance_type)
+ iholder = iholder->next;
+
+ if (iholder->info && iholder->plugin)
+ {
+ g_free (iholder->info);
+ iholder->info = NULL;
+ g_type_plugin_unref (iholder->plugin);
+
+ type_data_unref (iface);
+ }
+}
+
+
+/* --- type structure creation/destruction --- */
+GTypeInstance*
+g_type_create_instance (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+ GTypeInstance *instance;
+ GTypeClass *class;
+ guint i;
+
+ if (!node || !node->is_instantiatable)
+ {
+ g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
+ type_descriptive_name (type));
+ return NULL;
+ }
+
+ class = g_type_class_ref (type);
+
+ if (node->data->instance.n_preallocs)
+ {
+ if (!node->data->instance.mem_chunk)
+ node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
+ node->data->instance.instance_size,
+ (node->data->instance.instance_size *
+ node->data->instance.n_preallocs),
+ G_ALLOC_AND_FREE);
+ instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
+ }
+ else
+ instance = g_malloc0 (node->data->instance.instance_size);
+
+ for (i = node->n_supers; i > 0; i--)
+ {
+ TypeNode *pnode = LOOKUP_TYPE_NODE (node->supers[i]);
+
+ if (pnode->data->instance.instance_init)
+ {
+ instance->g_class = pnode->data->instance.class;
+ pnode->data->instance.instance_init (instance, class);
+ }
+ }
+ instance->g_class = class;
+ if (node->data->instance.instance_init)
+ node->data->instance.instance_init (instance, class);
+
+ return instance;
+}
+
+void
+g_type_free_instance (GTypeInstance *instance)
+{
+ TypeNode *node;
+ GTypeClass *class;
+
+ g_return_if_fail (instance != NULL && instance->g_class != NULL);
+
+ class = instance->g_class;
+ node = LOOKUP_TYPE_NODE (class->g_type);
+ if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
+ {
+ g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
+ type_descriptive_name (class->g_type));
+ return;
+ }
+
+ instance->g_class = NULL;
+ if (node->data->instance.n_preallocs)
+ g_chunk_free (instance, node->data->instance.mem_chunk);
+ else
+ g_free (instance);
+
+ g_type_class_unref (class);
+}
+
+static void
+type_propagate_iface_vtable (TypeNode *pnode,
+ TypeNode *iface,
+ GTypeInterface *vtable)
+{
+ IFaceEntry *entry = type_lookup_iface_entry (pnode, iface);
+ guint i;
+
+ entry->vtable = vtable;
+ for (i = 0; i < pnode->n_children; i++)
+ {
+ TypeNode *node = LOOKUP_TYPE_NODE (pnode->children[i]);
+
+ type_propagate_iface_vtable (node, iface, vtable);
+ }
+}
+
+static void
+type_iface_vtable_init (TypeNode *iface,
+ TypeNode *node)
+{
+ IFaceEntry *entry = type_lookup_iface_entry (node, iface);
+ IFaceHolder *iholder = type_iface_retrive_holder_info (iface, NODE_TYPE (node));
+ GTypeInterface *vtable;
+
+ g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
+
+ vtable = g_malloc0 (iface->data->iface.vtable_size);
+ type_propagate_iface_vtable (node, iface, vtable);
+ vtable->g_type = NODE_TYPE (iface);
+ vtable->g_instance_type = NODE_TYPE (node);
+
+ if (iface->data->iface.vtable_init_base)
+ iface->data->iface.vtable_init_base (vtable);
+ if (iholder->info->interface_init)
+ iholder->info->interface_init (vtable, iholder->info->interface_data);
+}
+
+static void
+type_iface_vtable_finalize (TypeNode *iface,
+ TypeNode *node,
+ GTypeInterface *vtable)
+{
+ IFaceEntry *entry = type_lookup_iface_entry (node, iface);
+ IFaceHolder *iholder = iface->private.iholders;
+
+ g_assert (entry && entry->vtable == vtable);
+
+ while (iholder->instance_type != NODE_TYPE (node))
+ iholder = iholder->next;
+ g_assert (iholder && iholder->info);
+
+ type_propagate_iface_vtable (node, iface, NULL);
+ if (iholder->info->interface_finalize)
+ iholder->info->interface_finalize (vtable, iholder->info->interface_data);
+ if (iface->data->iface.vtable_finalize_base)
+ iface->data->iface.vtable_finalize_base (vtable);
+
+ vtable->g_type = 0;
+ vtable->g_instance_type = 0;
+ g_free (vtable);
+
+ type_iface_blow_holder_info (iface, NODE_TYPE (node));
+}
+
+static void
+type_class_init (TypeNode *node,
+ GTypeClass *pclass)
+{
+ GSList *slist, *init_slist = NULL;
+ GTypeClass *class;
+ IFaceEntry *entry;
+ TypeNode *bnode;
+ guint i;
+
+ g_assert (node->is_classed && node->data &&
+ node->data->class.class_size &&
+ !node->data->class.class);
+
+ class = g_malloc0 (node->data->class.class_size);
+ node->data->class.class = class;
+
+ if (pclass)
+ {
+ TypeNode *pnode = LOOKUP_TYPE_NODE (pclass->g_type);
+
+ memcpy (class, pclass, pnode->data->class.class_size);
+ }
+
+ class->g_type = NODE_TYPE (node);
+
+ /* stack all base class initialization functions, so we
+ * call them in ascending order.
+ */
+ for (bnode = node; bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
+ if (bnode->data->class.class_init_base)
+ init_slist = g_slist_prepend (init_slist, bnode->data->class.class_init_base);
+ for (slist = init_slist; slist; slist = slist->next)
+ {
+ GBaseInitFunc class_init_base = slist->data;
+
+ class_init_base (class);
+ }
+ g_slist_free (init_slist);
+
+ if (node->data->class.class_init)
+ node->data->class.class_init (class, (gpointer) node->data->class.class_data);
+
+ /* ok, we got the class done, now initialize all interfaces */
+ for (entry = NULL, i = 0; i < node->n_ifaces; i++)
+ if (!node->private.iface_entries[i].vtable)
+ entry = node->private.iface_entries;
+ while (entry)
+ {
+ type_iface_vtable_init (LOOKUP_TYPE_NODE (entry->iface_type), node);
+
+ for (entry = NULL, i = 0; i < node->n_ifaces; i++)
+ if (!node->private.iface_entries[i].vtable)
+ entry = node->private.iface_entries;
+ }
+}
+
+static void
+type_data_finalize_class_ifaces (TypeNode *node)
+{
+ IFaceEntry *entry;
+ guint i;
+
+ g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
+
+ g_message ("finalizing interfaces for %sClass `%s'",
+ type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
+ type_descriptive_name (NODE_TYPE (node)));
+
+ for (entry = NULL, i = 0; i < node->n_ifaces; i++)
+ if (node->private.iface_entries[i].vtable &&
+ node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
+ entry = node->private.iface_entries;
+ while (entry)
+ {
+ type_iface_vtable_finalize (LOOKUP_TYPE_NODE (entry->iface_type), node, entry->vtable);
+
+ for (entry = NULL, i = 0; i < node->n_ifaces; i++)
+ if (node->private.iface_entries[i].vtable &&
+ node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
+ entry = node->private.iface_entries;
+ }
+}
+
+static void
+type_data_finalize_class (TypeNode *node,
+ ClassData *cdata)
+{
+ GTypeClass *class = cdata->class;
+ TypeNode *bnode;
+
+ g_assert (cdata->class && cdata->common.ref_count == 0);
+
+ g_message ("finalizing %sClass `%s'",
+ type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
+ type_descriptive_name (NODE_TYPE (node)));
+
+ if (cdata->class_finalize)
+ cdata->class_finalize (class, (gpointer) cdata->class_data);
+
+ /* call all base class destruction functions in descending order
+ */
+ if (cdata->class_finalize_base)
+ cdata->class_finalize_base (class);
+ for (bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node)); bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
+ if (bnode->data->class.class_finalize_base)
+ bnode->data->class.class_finalize_base (class);
+
+ class->g_type = 0;
+ g_free (cdata->class);
+}
+
+static void
+type_data_last_unref (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ g_return_if_fail (node != NULL && node->plugin != NULL);
+
+ if (!node->data || node->data->common.ref_count == 0)
+ {
+ g_warning ("cannot drop last reference to unreferenced type `%s'",
+ type_descriptive_name (type));
+ return;
+ }
+
+ if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
+ node->data->common.ref_count -= 1;
+ else
+ {
+ GType ptype = NODE_PARENT_TYPE (node);
+
+ node->data->common.ref_count = 0;
+
+ if (node->is_instantiatable && node->data->instance.mem_chunk)
+ {
+ g_mem_chunk_destroy (node->data->instance.mem_chunk);
+ node->data->instance.mem_chunk = NULL;
+ }
+
+ if (node->is_classed && node->data->class.class)
+ {
+ ClassData *cdata = &node->data->class;
+
+ if (node->n_ifaces)
+ type_data_finalize_class_ifaces (node);
+ node->data = NULL;
+ type_data_finalize_class (node, cdata);
+ g_free (cdata);
+ }
+ else
+ {
+ g_free (node->data);
+ node->data = NULL;
+ }
+
+ if (ptype)
+ type_data_unref (LOOKUP_TYPE_NODE (ptype));
+ g_type_plugin_unref (node->plugin);
+ }
+}
+
+
+/* --- type registration --- */
+GType
+g_type_register_fundamental (GType type_id,
+ const gchar *type_name,
+ const GTypeFundamentalInfo *finfo,
+ const GTypeInfo *info)
+{
+ GTypeFundamentalInfo *node_finfo;
+ TypeNode *node;
+
+ g_return_val_if_fail (type_id > 0, 0);
+ g_return_val_if_fail (type_name != NULL, 0);
+ g_return_val_if_fail (finfo != NULL, 0);
+ g_return_val_if_fail (info != NULL, 0);
+
+ if (!check_type_name (type_name))
+ return 0;
+ if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
+ {
+ g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
+ type_name,
+ type_id);
+ return 0;
+ }
+ if (LOOKUP_TYPE_NODE (type_id))
+ {
+ g_warning ("cannot register existing fundamental type `%s' (as `%s')",
+ type_descriptive_name (type_id),
+ type_name);
+ return 0;
+ }
+ if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
+ !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
+ {
+ g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
+ type_name);
+ return 0;
+ }
+
+ node = type_node_fundamental_new (type_id, type_name, finfo->type_flags);
+ node_finfo = type_node_fundamental_info (node);
+ node_finfo->n_collect_bytes = finfo->n_collect_bytes; // FIXME: check max bytes
+ node_finfo->param_collector = finfo->param_collector;
+
+ if (!check_type_info (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
+ return NODE_TYPE (node);
+ type_data_make (node, info);
+
+ return NODE_TYPE (node);
+}
+
+GType
+g_type_register_static (GType parent_type,
+ const gchar *type_name,
+ const GTypeInfo *info)
+{
+ TypeNode *pnode, *node;
+ GType type;
+
+ g_return_val_if_fail (parent_type > 0, 0);
+ g_return_val_if_fail (type_name != NULL, 0);
+ g_return_val_if_fail (info != NULL, 0);
+
+ if (!check_type_name (type_name))
+ return 0;
+ if (!check_derivation (parent_type, type_name))
+ return 0;
+
+ pnode = LOOKUP_TYPE_NODE (parent_type);
+ type_data_ref (pnode);
+
+ if (!check_type_info (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
+ return 0;
+ if (info->class_finalize)
+ {
+ g_warning ("class destructor specified for static type `%s'",
+ type_name);
+ return 0;
+ }
+
+ node = type_node_new (pnode, type_name, NULL);
+ type = NODE_TYPE (node);
+ type_data_make (node, info);
+
+ return type;
+}
+
+GType
+g_type_register_dynamic (GType parent_type,
+ const gchar *type_name,
+ GTypePlugin *plugin)
+{
+ TypeNode *pnode, *node;
+ GType type;
+
+ g_return_val_if_fail (parent_type > 0, 0);
+ g_return_val_if_fail (type_name != NULL, 0);
+ g_return_val_if_fail (plugin != NULL, 0);
+
+ if (!check_type_name (type_name))
+ return 0;
+ if (!check_derivation (parent_type, type_name))
+ return 0;
+ if (!check_plugin (plugin, TRUE, FALSE, type_name))
+ return 0;
+ pnode = LOOKUP_TYPE_NODE (parent_type);
+
+ node = type_node_new (pnode, type_name, plugin);
+ type = NODE_TYPE (node);
+
+ return type;
+}
+
+void
+g_type_add_interface_static (GType instance_type,
+ GType interface_type,
+ GInterfaceInfo *info)
+{
+ TypeNode *node;
+ TypeNode *iface;
+
+ g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
+ g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
+
+ if (!check_add_interface (instance_type, interface_type))
+ return;
+ node = LOOKUP_TYPE_NODE (instance_type);
+ iface = LOOKUP_TYPE_NODE (interface_type);
+ if (!check_interface_info (iface, NODE_TYPE (node), info))
+ return;
+ type_add_interface (node, iface, info, NULL);
+}
+
+void
+g_type_add_interface_dynamic (GType instance_type,
+ GType interface_type,
+ GTypePlugin *plugin)
+{
+ TypeNode *node;
+ TypeNode *iface;
+
+ g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
+ g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
+
+ if (!check_add_interface (instance_type, interface_type))
+ return;
+ node = LOOKUP_TYPE_NODE (instance_type);
+ iface = LOOKUP_TYPE_NODE (interface_type);
+ if (!check_plugin (plugin, FALSE, TRUE, NODE_NAME (node)))
+ return;
+ type_add_interface (node, iface, NULL, plugin);
+}
+
+
+/* --- public API functions --- */
+gpointer
+g_type_class_ref (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ /* optimize for common code path
+ */
+ if (node && node->is_classed && node->data &&
+ node->data->class.class && node->data->common.ref_count > 0)
+ {
+ type_data_ref (node);
+
+ return node->data->class.class;
+ }
+
+ if (!node || !node->is_classed ||
+ (node->data && node->data->common.ref_count < 1))
+ {
+ g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
+ type_descriptive_name (type));
+ return NULL;
+ }
+
+ type_data_ref (node);
+
+ if (!node->data->class.class)
+ {
+ GType ptype = NODE_PARENT_TYPE (node);
+ GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
+
+ type_class_init (node, pclass);
+ }
+
+ return node->data->class.class;
+}
+
+void
+g_type_class_unref (gpointer g_class)
+{
+ TypeNode *node;
+ GTypeClass *class = g_class;
+
+ g_return_if_fail (g_class != NULL);
+
+ node = LOOKUP_TYPE_NODE (class->g_type);
+ if (node && node->is_classed && node->data &&
+ node->data->class.class == class && node->data->common.ref_count > 0)
+ type_data_unref (node);
+ else
+ g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
+ type_descriptive_name (class->g_type));
+}
+
+gpointer
+g_type_class_peek (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
+ return node->data->class.class;
+ else
+ return NULL;
+}
+
+gpointer
+g_type_class_peek_parent (gpointer g_class)
+{
+ TypeNode *node;
+
+ g_return_val_if_fail (g_class != NULL, NULL);
+
+ node = LOOKUP_TYPE_NODE (G_TYPE_FROM_CLASS (g_class));
+ if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
+ {
+ node = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
+
+ return node->data->class.class;
+ }
+
+ return NULL;
+}
+
+gpointer
+g_type_interface_peek (gpointer instance_class,
+ GType iface_type)
+{
+ TypeNode *node;
+ TypeNode *iface;
+ GTypeClass *class = instance_class;
+
+ g_return_val_if_fail (instance_class != NULL, NULL);
+
+ node = LOOKUP_TYPE_NODE (class->g_type);
+ iface = LOOKUP_TYPE_NODE (iface_type);
+ if (node && node->is_instantiatable && iface)
+ {
+ IFaceEntry *entry = type_lookup_iface_entry (node, iface);
+
+ if (entry && entry->vtable)
+ return entry->vtable;
+ }
+
+ return NULL;
+}
+
+gchar*
+g_type_name (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ return node ? NODE_NAME (node) : NULL;
+}
+
+GQuark
+g_type_qname (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ return node ? node->qname : 0;
+}
+
+GType
+g_type_from_name (const gchar *name)
+{
+ GQuark quark;
+
+ g_return_val_if_fail (name != NULL, 0);
+
+ quark = g_quark_try_string (name);
+ if (quark)
+ {
+ GType type = GPOINTER_TO_UINT (g_hash_table_lookup (g_type_nodes_ht, GUINT_TO_POINTER (quark)));
+
+ if (type)
+ return type;
+ }
+
+ return 0;
+}
+
+GType
+g_type_parent (GType type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ return node ? NODE_PARENT_TYPE (node) : 0;
+}
+
+GType
+g_type_next_base (GType type,
+ GType base_type)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ if (node)
+ {
+ TypeNode *base_node = LOOKUP_TYPE_NODE (base_type);
+
+ if (base_node && base_node->n_supers < node->n_supers)
+ {
+ guint n = node->n_supers - base_node->n_supers;
+
+ if (node->supers[n] == base_type)
+ return node->supers[n - 1];
+ }
+ }
+
+ return 0;
+}
+
+gboolean
+g_type_is_a (GType type,
+ GType is_a_type)
+{
+ if (type != is_a_type)
+ {
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ if (node)
+ {
+ TypeNode *a_node = LOOKUP_TYPE_NODE (is_a_type);
+
+ if (a_node && a_node->n_supers <= node->n_supers)
+ return node->supers[node->n_supers - a_node->n_supers] == is_a_type;
+ }
+ }
+ else
+ return LOOKUP_TYPE_NODE (type) != NULL;
+
+ return FALSE;
+}
+
+gboolean
+g_type_conforms_to (GType type,
+ GType iface_type)
+{
+ if (type != iface_type)
+ {
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ if (node)
+ {
+ TypeNode *iface_node = LOOKUP_TYPE_NODE (iface_type);
+
+ if (iface_node)
+ {
+ if (iface_node->is_iface && node->is_instantiatable)
+ return type_lookup_iface_entry (node, iface_node) != NULL;
+ else if (iface_node->n_supers <= node->n_supers)
+ return node->supers[node->n_supers - iface_node->n_supers] == iface_type;
+ }
+ }
+ }
+ else
+ {
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ return node && (node->is_iface || node->is_instantiatable);
+ }
+
+ return FALSE;
+}
+
+guint
+g_type_fundamental_branch_last (GType type)
+{
+ GType ftype = G_TYPE_FUNDAMENTAL (type);
+
+ return ftype < G_TYPE_FUNDAMENTAL_LAST ? g_branch_seqnos[ftype] : 0;
+}
+
+GType* /* free result */
+g_type_children (GType type,
+ guint *n_children)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ if (node)
+ {
+ GType *children = g_new (GType, node->n_children + 1);
+
+ memcpy (children, node->children, sizeof (GType) * node->n_children);
+ children[node->n_children] = 0;
+
+ if (n_children)
+ *n_children = node->n_children;
+
+ return children;
+ }
+ else
+ {
+ if (n_children)
+ *n_children = 0;
+
+ return NULL;
+ }
+}
+
+GType* /* free result */
+g_type_interfaces (GType type,
+ guint *n_interfaces)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ if (node && node->is_instantiatable)
+ {
+ GType *ifaces = g_new (GType, node->n_ifaces + 1);
+ guint i;
+
+ for (i = 0; i < node->n_ifaces; i++)
+ ifaces[i] = node->private.iface_entries[i].iface_type;
+ ifaces[i] = 0;
+
+ if (n_interfaces)
+ *n_interfaces = node->n_ifaces;
+
+ return ifaces;
+ }
+ else
+ {
+ if (n_interfaces)
+ *n_interfaces = 0;
+
+ return NULL;
+ }
+}
+
+typedef struct _QData QData;
+struct _GData
+{
+ guint n_qdatas;
+ QData *qdatas;
+};
+struct _QData
+{
+ GQuark quark;
+ gpointer data;
+};
+
+gpointer
+g_type_get_qdata (GType type,
+ GQuark quark)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+ GData *gdata;
+
+ g_return_val_if_fail (node != NULL, NULL);
+
+ gdata = node->static_gdata;
+ if (quark && gdata && gdata->n_qdatas)
+ {
+ QData *qdatas = gdata->qdatas - 1;
+ guint n_qdatas = gdata->n_qdatas;
+
+ do /* FIXME: should optimize qdata lookups for <= 4 */
+ {
+ guint i;
+ QData *check;
+
+ i = (n_qdatas + 1) / 2;
+ check = qdatas + i;
+ if (quark == check->quark)
+ return check->data;
+ else if (quark > check->quark)
+ {
+ n_qdatas -= i;
+ qdatas = check;
+ }
+ else /* if (quark < check->quark) */
+ n_qdatas = i - 1;
+ }
+ while (n_qdatas);
+ }
+
+ return NULL;
+}
+
+void
+g_type_set_qdata (GType type,
+ GQuark quark,
+ gpointer data)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+ GData *gdata;
+ QData *qdata;
+ guint i;
+
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (quark != 0);
+
+ /* setup qdata list if necessary */
+ if (!node->static_gdata)
+ node->static_gdata = g_new0 (GData, 1);
+ gdata = node->static_gdata;
+
+ /* try resetting old data */
+ qdata = gdata->qdatas;
+ for (i = 0; i < gdata->n_qdatas; i++)
+ if (qdata[i].quark == quark)
+ {
+ qdata[i].data = data;
+ return;
+ }
+
+ /* add new entry */
+ gdata->n_qdatas++;
+ gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
+ qdata = gdata->qdatas;
+ for (i = 0; i < gdata->n_qdatas - 1; i++)
+ if (qdata[i].quark > quark)
+ break;
+ g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
+ qdata[i].quark = quark;
+ qdata[i].data = data;
+}
+
+
+/* --- implementation details --- */
+gboolean
+g_type_check_flags (GType type,
+ GTypeFlags flags)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ flags &= G_TYPE_FLAG_MASK;
+ if (node)
+ {
+ GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
+
+ return (finfo->type_flags & flags) != 0;
+ }
+
+ return FALSE;
+}
+
+gboolean
+g_type_is_dynamic (GType type,
+ GTypeFlags flags)
+{
+ TypeNode *node = LOOKUP_TYPE_NODE (type);
+
+ return node && node->plugin;
+}
+
+gboolean
+g_type_instance_conforms_to (GTypeInstance *type_instance,
+ GType iface_type)
+{
+ return (type_instance && type_instance->g_class &&
+ g_type_conforms_to (type_instance->g_class->g_type, iface_type));
+}
+
+gboolean
+g_type_class_is_a (GTypeClass *type_class,
+ GType is_a_type)
+{
+ return (type_class && g_type_is_a (type_class->g_type, is_a_type));
+}
+
+GTypeInstance*
+g_type_check_instance_cast (GTypeInstance *type_instance,
+ GType iface_type)
+{
+ if (!type_instance)
+ {
+ g_warning ("invalid cast from (NULL) pointer to `%s'",
+ type_descriptive_name (iface_type));
+ return type_instance;
+ }
+ if (!type_instance->g_class)
+ {
+ g_warning ("invalid unclassed pointer in cast to `%s'",
+ type_descriptive_name (iface_type));
+ return type_instance;
+ }
+ if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
+ {
+ g_warning ("invalid unclassed type `%s' in cast to `%s'",
+ type_descriptive_name (type_instance->g_class->g_type),
+ type_descriptive_name (iface_type));
+ return type_instance;
+ }
+ if (!g_type_conforms_to (type_instance->g_class->g_type, iface_type))
+ {
+ g_warning ("invalid cast from `%s' to `%s'",
+ type_descriptive_name (type_instance->g_class->g_type),
+ type_descriptive_name (iface_type));
+ return type_instance;
+ }
+
+ return type_instance;
+}
+
+GTypeClass*
+g_type_check_class_cast (GTypeClass *type_class,
+ GType is_a_type)
+{
+ if (!type_class)
+ {
+ g_warning ("invalid class cast from (NULL) pointer to `%s'",
+ type_descriptive_name (is_a_type));
+ return type_class;
+ }
+ if (!G_TYPE_IS_CLASSED (type_class->g_type))
+ {
+ g_warning ("invalid unclassed type `%s' in class cast to `%s'",
+ type_descriptive_name (type_class->g_type),
+ type_descriptive_name (is_a_type));
+ return type_class;
+ }
+ if (!g_type_is_a (type_class->g_type, is_a_type))
+ {
+ g_warning ("invalid class cast from `%s' to `%s'",
+ type_descriptive_name (type_class->g_type),
+ type_descriptive_name (is_a_type));
+ return type_class;
+ }
+
+ return type_class;
+}
+
+
+/* --- foreign prototypes --- */
+extern void g_param_types_init (void); /* sync with glib-gparam.c */
+extern void g_enum_types_init (void); /* sync with glib-genums.c */
+extern void g_object_type_init (void); /* sync with glib-gobject.c */
+
+
+/* --- initialization --- */
+void
+g_type_init (void)
+{
+ static TypeNode *type0_node = NULL;
+ GTypeInfo info;
+ TypeNode *node;
+ GType type;
+
+ if (G_TYPE_FUNDAMENTAL_LAST)
+ return;
+
+ /* type qname hash table */
+ g_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ /* invalid type G_TYPE_INVALID (0)
+ */
+ _g_type_fundamental_last = 1;
+ g_type_nodes = g_renew (TypeNode**, g_type_nodes, G_TYPE_FUNDAMENTAL_LAST);
+ g_type_nodes[0] = &type0_node;
+ g_branch_seqnos = g_renew (GType, g_branch_seqnos, G_TYPE_FUNDAMENTAL_LAST);
+ g_branch_seqnos[0] = 1;
+
+ /* void type G_TYPE_NONE
+ */
+ node = type_node_fundamental_new (G_TYPE_NONE, "void", 0);
+ type = NODE_TYPE (node);
+ g_assert (type == G_TYPE_NONE);
+
+ /* interface fundamental type G_TYPE_INTERFACE (!classed)
+ */
+ memset (&info, 0, sizeof (info));
+ node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
+ type = NODE_TYPE (node);
+ type_data_make (node, &info);
+ g_assert (type == G_TYPE_INTERFACE);
+
+ /* G_TYPE_ENUM & G_TYPE_FLAGS
+ */
+ g_enum_types_init ();
+
+ /* G_TYPE_PARAM
+ */
+ g_param_types_init ();
+
+ /* G_TYPE_OBJECT
+ */
+ g_object_type_init ();
+}
diff --git a/gobject/gtype.h b/gobject/gtype.h
new file mode 100644
index 000000000..5ddf4e945
--- /dev/null
+++ b/gobject/gtype.h
@@ -0,0 +1,304 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ */
+#ifndef __G_TYPE_H__
+#define __G_TYPE_H__
+
+extern const char *g_log_domain_gobject;
+#include <glib.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Basic Type Macros
+ */
+#define G_TYPE_FUNDAMENTAL(type) ((type) & 0xff)
+#define G_TYPE_FUNDAMENTAL_MAX (0xff)
+#define G_TYPE_DERIVE_ID(ptype, branch_seqno) (G_TYPE_FUNDAMENTAL (ptype) | ((branch_seqno) << 8))
+#define G_TYPE_BRANCH_SEQNO(type) ((type) >> 8)
+#define G_TYPE_FUNDAMENTAL_LAST ((GType) _g_type_fundamental_last)
+
+
+/* predefined fundamental and derived types
+ */
+typedef enum /*< skip >*/
+{
+ /* standard types, introduced by g_type_init() */
+ G_TYPE_INVALID,
+ G_TYPE_NONE,
+ G_TYPE_INTERFACE,
+
+ /* GLib type ids */
+ G_TYPE_ENUM,
+ G_TYPE_FLAGS,
+ G_TYPE_PARAM,
+ G_TYPE_OBJECT,
+
+ /* reserved type ids, mail gtk-devel-list@redhat.com for reservations */
+ G_TYPE_BSE_PROCEDURE,
+ G_TYPE_GLE_GOBJECT,
+
+ /* the following reserved ids should vanish soon */
+ G_TYPE_GTK_CHAR,
+ G_TYPE_GTK_UCHAR,
+ G_TYPE_GTK_BOOL,
+ G_TYPE_GTK_INT,
+ G_TYPE_GTK_UINT,
+ G_TYPE_GTK_LONG,
+ G_TYPE_GTK_ULONG,
+ G_TYPE_GTK_FLOAT,
+ G_TYPE_GTK_DOUBLE,
+ G_TYPE_GTK_STRING,
+ G_TYPE_GTK_BOXED,
+ G_TYPE_GTK_POINTER,
+ G_TYPE_GTK_SIGNAL,
+
+ G_TYPE_LAST_RESERVED_FUNDAMENTAL,
+
+ /* derived type ids */
+ G_TYPE_PARAM_CHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 1),
+ G_TYPE_PARAM_UCHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 2),
+ G_TYPE_PARAM_BOOL = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 3),
+ G_TYPE_PARAM_INT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 4),
+ G_TYPE_PARAM_UINT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 5),
+ G_TYPE_PARAM_LONG = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 6),
+ G_TYPE_PARAM_ULONG = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 7),
+ G_TYPE_PARAM_ENUM = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 8),
+ G_TYPE_PARAM_FLAGS = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 9),
+ G_TYPE_PARAM_FLOAT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 10),
+ G_TYPE_PARAM_DOUBLE = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 11),
+ G_TYPE_PARAM_STRING = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 12),
+ G_TYPE_PARAM_OBJECT = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 13)
+} GTypeFundamentals;
+
+
+/* Type Checking Macros
+ */
+#define G_TYPE_IS_INTERFACE(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_INTERFACE)
+#define G_TYPE_IS_CLASSED(type) (g_type_check_flags ((type), G_TYPE_FLAG_CLASSED))
+#define G_TYPE_IS_INSTANTIATABLE(type) (g_type_check_flags ((type), G_TYPE_FLAG_INSTANTIATABLE))
+#define G_TYPE_IS_DERIVABLE(type) (g_type_check_flags ((type), G_TYPE_FLAG_DERIVABLE))
+#define G_TYPE_IS_DEEP_DERIVABLE(type) (g_type_check_flags ((type), G_TYPE_FLAG_DEEP_DERIVABLE))
+#define G_TYPE_IS_PARAM(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_PARAM)
+
+
+/* Typedefs
+ */
+typedef guint32 GType;
+typedef struct _GParam GParam;
+typedef struct _GTypePlugin GTypePlugin;
+typedef struct _GTypePluginVTable GTypePluginVTable;
+typedef struct _GTypeClass GTypeClass;
+typedef struct _GTypeInterface GTypeInterface;
+typedef struct _GTypeInstance GTypeInstance;
+typedef struct _GTypeInfo GTypeInfo;
+typedef struct _GTypeFundamentalInfo GTypeFundamentalInfo;
+typedef struct _GInterfaceInfo GInterfaceInfo;
+
+
+/* Basic Type Structures
+ */
+struct _GTypeClass
+{
+ GType g_type;
+};
+struct _GTypeInstance
+{
+ GTypeClass *g_class;
+};
+struct _GTypeInterface
+{
+ GType g_type; /* iface type */
+ GType g_instance_type;
+};
+
+
+/* Casts, Checks And Convenience Macros For Structured Types
+ */
+#define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type))
+#define G_TYPE_CHECK_CLASS_CAST(g_class, g_type, c_type) (_G_TYPE_CCC ((g_class), (g_type), c_type))
+#define G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type) (_G_TYPE_CIT ((instance), (g_type)))
+#define G_TYPE_CHECK_CLASS_TYPE(g_class, g_type) (_G_TYPE_CCT ((g_class), (g_type)))
+#define G_TYPE_INSTANCE_GET_CLASS(instance, g_type, c_type) (_G_TYPE_IGC ((instance), c_type))
+#define G_TYPE_FROM_INSTANCE(instance) (G_TYPE_FROM_CLASS (((GTypeInstance*) (instance))->g_class))
+#define G_TYPE_FROM_CLASS(g_class) (((GTypeClass*) (g_class))->g_type)
+
+
+/* --- prototypes --- */
+void g_type_init (void);
+gchar* g_type_name (GType type);
+GQuark g_type_qname (GType type);
+GType g_type_from_name (const gchar *name);
+GType g_type_parent (GType type);
+GType g_type_next_base (GType type,
+ GType base_type);
+gboolean g_type_is_a (GType type,
+ GType is_a_type);
+gboolean g_type_conforms_to (GType type,
+ GType iface_type);
+guint g_type_fundamental_branch_last (GType type);
+gpointer g_type_class_ref (GType type);
+gpointer g_type_class_peek (GType type);
+void g_type_class_unref (gpointer g_class);
+gpointer g_type_class_peek_parent (gpointer g_class);
+gpointer g_type_interface_peek (gpointer instance_class,
+ GType iface_type);
+/* g_free() the returned arrays */
+GType* g_type_children (GType type,
+ guint *n_children);
+GType* g_type_interfaces (GType type,
+ guint *n_interfaces);
+/* per-type *static* data */
+void g_type_set_qdata (GType type,
+ GQuark quark,
+ gpointer data);
+gpointer g_type_get_qdata (GType type,
+ GQuark quark);
+
+
+/* --- type registration --- */
+typedef void (*GBaseInitFunc) (gpointer g_class);
+typedef void (*GBaseFinalizeFunc) (gpointer g_class);
+typedef void (*GClassInitFunc) (gpointer g_class,
+ gpointer class_data);
+typedef void (*GClassFinalizeFunc) (gpointer g_class,
+ gpointer class_data);
+typedef void (*GInstanceInitFunc) (GTypeInstance *instance,
+ gpointer g_class);
+typedef void (*GInterfaceInitFunc) (gpointer g_iface,
+ gpointer iface_data);
+typedef void (*GInterfaceFinalizeFunc) (gpointer g_iface,
+ gpointer iface_data);
+typedef gchar* (*GTypeParamCollector) (GParam *param,
+ guint n_bytes,
+ guint8 *bytes);
+typedef void (*GTypePluginRef) (GTypePlugin *plugin);
+typedef void (*GTypePluginUnRef) (GTypePlugin *plugin);
+typedef void (*GTypePluginFillTypeInfo) (GTypePlugin *plugin,
+ GType g_type,
+ GTypeInfo *info);
+typedef void (*GTypePluginFillInterfaceInfo) (GTypePlugin *plugin,
+ GType interface_type,
+ GType instance_type,
+ GInterfaceInfo *info);
+struct _GTypePlugin
+{
+ GTypePluginVTable *vtable;
+};
+struct _GTypePluginVTable
+{
+ GTypePluginRef plugin_ref;
+ GTypePluginUnRef plugin_unref;
+ GTypePluginFillTypeInfo complete_type_info;
+ GTypePluginFillInterfaceInfo complete_interface_info;
+};
+typedef enum /*< skip >*/
+{
+ G_TYPE_FLAG_CLASSED = (1 << 0),
+ G_TYPE_FLAG_INSTANTIATABLE = (1 << 1),
+ G_TYPE_FLAG_DERIVABLE = (1 << 2),
+ G_TYPE_FLAG_DEEP_DERIVABLE = (1 << 3)
+} GTypeFlags;
+struct _GTypeInfo
+{
+ /* interface types, classed types, instantiated types */
+ guint16 class_size;
+
+ GBaseInitFunc base_init;
+ GBaseFinalizeFunc base_finalize;
+
+ /* classed types, instantiated types */
+ GClassInitFunc class_init;
+ GClassFinalizeFunc class_finalize;
+ gconstpointer class_data;
+
+ /* instantiated types */
+ guint16 instance_size;
+ guint16 n_preallocs;
+ GInstanceInitFunc instance_init;
+};
+struct _GTypeFundamentalInfo
+{
+ GTypeFlags type_flags;
+ guint n_collect_bytes;
+ GTypeParamCollector param_collector;
+};
+struct _GInterfaceInfo
+{
+ GInterfaceInitFunc interface_init;
+ GInterfaceFinalizeFunc interface_finalize;
+ gpointer interface_data;
+};
+GType g_type_register_static (GType parent_type,
+ const gchar *type_name,
+ const GTypeInfo *info);
+GType g_type_register_dynamic (GType parent_type,
+ const gchar *type_name,
+ GTypePlugin *plugin);
+GType g_type_register_fundamental (GType type_id,
+ const gchar *type_name,
+ const GTypeFundamentalInfo *finfo,
+ const GTypeInfo *info);
+void g_type_add_interface_static (GType instance_type,
+ GType interface_type,
+ GInterfaceInfo *info);
+void g_type_add_interface_dynamic (GType instance_type,
+ GType interface_type,
+ GTypePlugin *plugin);
+
+
+/* --- implementation details --- */
+gboolean g_type_class_is_a (GTypeClass *g_class,
+ GType is_a_type);
+GTypeClass* g_type_check_class_cast (GTypeClass *g_class,
+ GType is_a_type);
+GTypeInstance* g_type_check_instance_cast (GTypeInstance *instance,
+ GType iface_type);
+gboolean g_type_instance_conforms_to (GTypeInstance *instance,
+ GType iface_type);
+gboolean g_type_check_flags (GType type,
+ GTypeFlags flags);
+gboolean g_type_is_dynamic (GType type,
+ GTypeFlags flags);
+GTypeInstance* g_type_create_instance (GType type);
+void g_type_free_instance (GTypeInstance *instance);
+
+#ifndef G_DISABLE_CAST_CHECKS
+# define _G_TYPE_CIC(ip, gt, ct) \
+ ((ct*) g_type_check_instance_cast ((GTypeInstance*) ip, gt))
+# define _G_TYPE_CCC(cp, gt, ct) \
+ ((ct*) g_type_check_class_cast ((GTypeClass*) cp, gt))
+#else /* G_DISABLE_CAST_CHECKS */
+# define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
+# define _G_TYPE_CCC(cp, gt, ct) ((ct*) cp)
+#endif /* G_DISABLE_CAST_CHECKS */
+#define _G_TYPE_IGC(ip, ct) ((ct*) (((GTypeInstance*) ip)->g_class))
+#define _G_TYPE_CIT(ip, gt) (g_type_instance_conforms_to ((GTypeInstance*) ip, gt))
+#define _G_TYPE_CCT(cp, gt) (g_type_class_is_a ((GTypeClass*) cp, gt))
+extern GType _g_type_fundamental_last;
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_TYPE_H__ */
diff --git a/gobject/gvalue.c b/gobject/gvalue.c
new file mode 100644
index 000000000..d85a9f793
--- /dev/null
+++ b/gobject/gvalue.c
@@ -0,0 +1,374 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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 "gvalue.h"
+
+
+/* --- defines --- */
+#define G_PARAM_SPEC_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
+
+
+/* --- typedefs & structures --- */
+typedef struct
+{
+ GType value_type1;
+ GType value_type2;
+ GValueExchange func;
+ GType first_type;
+} ExchangeEntry;
+
+
+/* --- variables --- */
+static GHashTable *param_exchange_ht = NULL;
+
+
+/* --- functions --- */
+void
+g_value_init (GValue *value,
+ GType g_type)
+{
+ GParamSpecClass *pclass;
+
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (G_VALUE_TYPE (value) == 0);
+ g_type = g_type_next_base (g_type, G_TYPE_PARAM);
+ g_return_if_fail (G_TYPE_IS_VALUE (g_type));
+
+ memset (value, 0, sizeof (*value));
+ value->g_type = g_type;
+
+ pclass = g_type_class_ref (G_VALUE_TYPE (value));
+ pclass->param_init (value, NULL);
+ g_type_class_unref (pclass);
+}
+
+void
+g_value_init_default (GValue *value,
+ GParamSpec *pspec)
+{
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (G_VALUE_TYPE (value) == 0);
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+
+ memset (value, 0, sizeof (*value));
+ value->g_type = g_type_next_base (G_PARAM_SPEC_TYPE (pspec), G_TYPE_PARAM);
+
+ G_PARAM_SPEC_GET_CLASS (pspec)->param_init (value, pspec);
+}
+
+gboolean
+g_value_validate (GValue *value,
+ GParamSpec *pspec)
+{
+ g_return_val_if_fail (G_IS_VALUE (value), FALSE);
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
+ g_return_val_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value)), FALSE);
+
+ if (G_PARAM_SPEC_GET_CLASS (pspec)->param_validate)
+ {
+ GValue oval = *value;
+
+ if (G_PARAM_SPEC_GET_CLASS (pspec)->param_validate (value, pspec) ||
+ memcmp (&oval.data, &value->data, sizeof (oval.data)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean
+g_value_defaults (const GValue *value,
+ GParamSpec *pspec)
+{
+ GValue dflt_value = { 0, };
+ gboolean defaults;
+
+ g_return_val_if_fail (G_IS_VALUE (value), FALSE);
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
+ g_return_val_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value)), FALSE);
+
+ dflt_value.g_type = g_type_next_base (G_PARAM_SPEC_TYPE (pspec), G_TYPE_PARAM);
+ G_PARAM_SPEC_GET_CLASS (pspec)->param_init (&dflt_value, pspec);
+ defaults = g_values_cmp (value, &dflt_value, pspec) == 0;
+ g_value_unset (&dflt_value);
+
+ return defaults;
+}
+
+void
+g_value_set_default (GValue *value,
+ GParamSpec *pspec)
+{
+ GValue tmp_value = { 0, };
+
+ g_return_if_fail (G_IS_VALUE (value));
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value)));
+
+ /* retrive default value */
+ tmp_value.g_type = g_type_next_base (G_PARAM_SPEC_TYPE (pspec), G_TYPE_PARAM);
+ G_PARAM_SPEC_GET_CLASS (pspec)->param_init (&tmp_value, pspec);
+
+ /* set default value */
+ g_values_exchange (&tmp_value, value);
+
+ g_value_unset (&tmp_value);
+}
+
+gint
+g_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec)
+{
+ GParamSpecClass *pclass;
+ gint cmp;
+
+ /* param_values_cmp() effectively does: value1 - value2
+ * so the return values are:
+ * -1) value1 < value2
+ * 0) value1 == value2
+ * 1) value1 > value2
+ */
+ g_return_val_if_fail (G_IS_VALUE (value1), 0);
+ g_return_val_if_fail (G_IS_VALUE (value2), 0);
+ g_return_val_if_fail (G_VALUE_TYPE (value1) == G_VALUE_TYPE (value2), 0);
+ if (pspec)
+ {
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
+ g_return_val_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (pspec), G_VALUE_TYPE (value1)), FALSE);
+ }
+
+ pclass = g_type_class_ref (G_VALUE_TYPE (value1));
+ cmp = pclass->param_values_cmp (value1, value2, pspec);
+ g_type_class_unref (pclass);
+
+ return CLAMP (cmp, -1, 1);
+}
+
+void
+g_value_copy (const GValue *src_value,
+ GValue *dest_value)
+{
+ g_return_if_fail (G_IS_VALUE (src_value));
+ g_return_if_fail (G_IS_VALUE (dest_value));
+ g_return_if_fail (G_VALUE_TYPE (src_value) == G_VALUE_TYPE (dest_value));
+
+ if (src_value != dest_value)
+ {
+ GParamSpecClass *pclass = g_type_class_ref (G_VALUE_TYPE (src_value));
+
+ /* make sure dest_value's value is free()d and zero initialized */
+ g_value_reset (dest_value);
+
+ if (pclass->param_copy_value)
+ pclass->param_copy_value (src_value, dest_value);
+ else
+ memcpy (&dest_value->data, &src_value->data, sizeof (src_value->data));
+ g_type_class_unref (pclass);
+ }
+}
+
+void
+g_value_unset (GValue *value)
+{
+ GParamSpecClass *pclass;
+
+ g_return_if_fail (G_IS_VALUE (value));
+
+ pclass = g_type_class_ref (G_VALUE_TYPE (value));
+ if (pclass->param_free_value)
+ pclass->param_free_value (value);
+ memset (value, 0, sizeof (*value));
+ g_type_class_unref (pclass);
+}
+
+void
+g_value_reset (GValue *value)
+{
+ GParamSpecClass *pclass;
+ GType g_type;
+
+ g_return_if_fail (G_IS_VALUE (value));
+
+ g_type = G_VALUE_TYPE (value);
+ pclass = g_type_class_ref (g_type);
+
+ if (pclass->param_free_value)
+ pclass->param_free_value (value);
+ memset (value, 0, sizeof (*value));
+
+ value->g_type = g_type;
+ pclass->param_init (value, NULL);
+
+ g_type_class_unref (pclass);
+}
+
+static gint
+exchange_entries_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const ExchangeEntry *entry1 = v1;
+ const ExchangeEntry *entry2 = v2;
+
+ return (entry1->value_type1 == entry2->value_type1 &&
+ entry1->value_type2 == entry2->value_type2);
+}
+
+static guint
+exchange_entry_hash (gconstpointer key)
+{
+ const ExchangeEntry *entry = key;
+
+ return entry->value_type1 ^ entry->value_type2;
+}
+
+static void
+value_exchange_memcpy (GValue *value1,
+ GValue *value2)
+{
+ GValue tmp_value;
+
+ memcpy (&tmp_value.data, &value1->data, sizeof (value1->data));
+ memcpy (&value1->data, &value2->data, sizeof (value1->data));
+ memcpy (&value2->data, &tmp_value.data, sizeof (value2->data));
+}
+
+static inline GValueExchange
+exchange_func_lookup (GType value_type1,
+ GType value_type2,
+ gboolean *need_swap)
+{
+ if (value_type1 == value_type2)
+ return value_exchange_memcpy;
+ else
+ {
+ ExchangeEntry entry, *ret;
+
+ entry.value_type1 = MIN (value_type1, value_type2);
+ entry.value_type2 = MAX (value_type1, value_type2);
+
+ ret = g_hash_table_lookup (param_exchange_ht, &entry);
+ if (ret)
+ {
+ if (need_swap)
+ *need_swap = ret->first_type == value_type1;
+
+ return ret->func;
+ }
+ }
+ return NULL;
+}
+
+void
+g_value_register_exchange_func (GType value_type1,
+ GType value_type2,
+ GValueExchange func)
+{
+ GType type1, type2;
+
+ g_return_if_fail (G_TYPE_IS_VALUE (value_type1));
+ g_return_if_fail (G_TYPE_IS_VALUE (value_type2));
+ g_return_if_fail (func != NULL);
+
+ type1 = g_type_next_base (value_type1, G_TYPE_PARAM);
+ type2 = g_type_next_base (value_type2, G_TYPE_PARAM);
+
+ if (param_exchange_ht && exchange_func_lookup (type1, type2, NULL))
+ g_warning (G_STRLOC ": cannot re-register param value exchange function "
+ "for `%s' and `%s'",
+ g_type_name (type1),
+ g_type_name (type2));
+ else
+ {
+ ExchangeEntry *entry = g_new (ExchangeEntry, 1);
+
+ if (!param_exchange_ht)
+ param_exchange_ht = g_hash_table_new (exchange_entry_hash, exchange_entries_equal);
+ entry->value_type1 = MIN (type1, type2);
+ entry->value_type2 = MAX (type1, type2);
+ entry->func = func;
+ entry->first_type = type1;
+ g_hash_table_insert (param_exchange_ht, entry, entry);
+ }
+}
+
+gboolean
+g_value_types_exchangable (GType value_type1,
+ GType value_type2)
+{
+ GType type1, type2;
+
+ g_return_val_if_fail (G_TYPE_IS_VALUE (value_type1), FALSE);
+ g_return_val_if_fail (G_TYPE_IS_VALUE (value_type2), FALSE);
+
+ type1 = g_type_next_base (value_type1, G_TYPE_PARAM);
+ type2 = g_type_next_base (value_type2, G_TYPE_PARAM);
+
+ return exchange_func_lookup (type1, type2, NULL) != NULL;
+}
+
+gboolean
+g_values_exchange (GValue *value1,
+ GValue *value2)
+{
+ g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
+ g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
+
+ if (value1 != value2)
+ {
+ GType type1 = g_type_next_base (G_VALUE_TYPE (value1), G_TYPE_PARAM);
+ GType type2 = g_type_next_base (G_VALUE_TYPE (value2), G_TYPE_PARAM);
+ gboolean need_swap;
+ GValueExchange value_exchange = exchange_func_lookup (type1,
+ type2,
+ &need_swap);
+ if (value_exchange)
+ {
+ if (need_swap)
+ value_exchange (value2, value1);
+ else
+ value_exchange (value1, value2);
+ }
+
+ return value_exchange != NULL;
+ }
+
+ return TRUE;
+}
+
+gboolean
+g_value_convert (const GValue *src_value,
+ GValue *dest_value)
+{
+ gboolean success = TRUE;
+
+ g_return_val_if_fail (G_IS_VALUE (src_value), FALSE);
+ g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE);
+
+ if (src_value != dest_value)
+ {
+ GValue tmp_value = { 0, };
+
+ g_value_init (&tmp_value, G_VALUE_TYPE (src_value));
+ g_value_copy (src_value, &tmp_value);
+
+ success = g_values_exchange (&tmp_value, dest_value);
+ g_value_unset (&tmp_value);
+ }
+
+ return success;
+}
diff --git a/gobject/gvalue.h b/gobject/gvalue.h
new file mode 100644
index 000000000..697e1dfe6
--- /dev/null
+++ b/gobject/gvalue.h
@@ -0,0 +1,92 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ *
+ * gvalue.h: generic GValue functions
+ */
+#ifndef __G_VALUE_H__
+#define __G_VALUE_H__
+
+
+#include <gobject/gparam.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- type macros --- */
+#define G_TYPE_IS_VALUE(type) (G_TYPE_FUNDAMENTAL (type) == G_TYPE_PARAM)
+#define G_IS_VALUE(value) (G_TYPE_CHECK_CLASS_TYPE ((value), G_TYPE_PARAM))
+#define G_VALUE_TYPE(value) (G_TYPE_FROM_CLASS (value))
+#define G_VALUE_TYPE_NAME(value) (g_type_name (G_VALUE_TYPE (value)))
+
+
+/* --- typedefs & structures --- */
+/* typedef struct _GValue GValue; */
+struct _GValue
+{
+ GType g_type; /* param value type */
+
+ union {
+ gint v_int;
+ guint v_uint;
+ glong v_long;
+ gulong v_ulong;
+ gfloat v_float;
+ gdouble v_double;
+ gpointer v_pointer;
+ } data[4];
+};
+
+
+/* --- prototypes --- */
+void g_value_init (GValue *value,
+ GType g_type);
+void g_value_init_default (GValue *value,
+ GParamSpec *pspec);
+gboolean g_value_validate (GValue *value,
+ GParamSpec *pspec);
+gboolean g_value_defaults (const GValue *value,
+ GParamSpec *pspec);
+void g_value_set_default (GValue *value,
+ GParamSpec *pspec);
+gint g_values_cmp (const GValue *value1,
+ const GValue *value2,
+ GParamSpec *pspec);
+void g_value_copy (const GValue *src_value,
+ GValue *dest_value);
+gboolean g_value_convert (const GValue *src_value,
+ GValue *dest_value);
+gboolean g_values_exchange (GValue *value1,
+ GValue *value2);
+void g_value_reset (GValue *value);
+void g_value_unset (GValue *value);
+
+
+/* --- implementation bits --- */
+gboolean g_value_types_exchangable (GType value_type1,
+ GType value_type2);
+void g_value_register_exchange_func (GType value_type1,
+ GType value_type2,
+ GValueExchange func);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_VALUE_H__ */
diff --git a/gobject/gvaluecollector.h b/gobject/gvaluecollector.h
new file mode 100644
index 000000000..b62c26277
--- /dev/null
+++ b/gobject/gvaluecollector.h
@@ -0,0 +1,174 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * 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.
+ *
+ * gvaluecollector.h: GValue varargs stubs
+ */
+#ifndef __G_VALUE_COLLECTOR_H__
+#define __G_VALUE_COLLECTOR_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* we may want to add aggregate types here some day, if requested
+ * by users. the basic C types are covered already, everything
+ * smaller than an int is promoted to an integer and floats are
+ * always promoted to doubles for varargs call constructions.
+ */
+enum /*< skip >*/
+{
+ G_VALUE_COLLECT_NONE,
+ G_VALUE_COLLECT_INT,
+ G_VALUE_COLLECT_LONG,
+ G_VALUE_COLLECT_DOUBLE,
+ G_VALUE_COLLECT_POINTER
+};
+
+union _GParamCValue
+{
+ gint v_int;
+ glong v_long;
+ gdouble v_double;
+ gpointer v_pointer;
+};
+
+
+/* G_PARAM_COLLECT_VALUE() collects a parameter's variable arguments
+ * from a va_list. we have to implement the varargs collection as a
+ * macro, because on some systems va_list variables cannot be passed
+ * by reference.
+ * param_value is supposed to be initialized according to the param
+ * type to be collected.
+ * the param_spec argument is optional, but probably needed by most
+ * param class' param_collect_value() implementations.
+ * var_args is the va_list variable and may be evaluated multiple times.
+ * __error is a gchar** variable that will be modified to hold a g_new()
+ * allocated error messages if something fails.
+ */
+#define G_PARAM_COLLECT_VALUE(param_value, param_spec, var_args, __error) \
+G_STMT_START { \
+ GValue *_value = (param_value); \
+ GParamSpecClass *_pclass = g_type_class_ref (_value->g_type); \
+ GParamSpec *_pspec = (param_spec); \
+ gchar *_error_msg = NULL; \
+ guint _collect_type = _pclass->collect_type; \
+ guint _nth_value = 0; \
+ \
+ if (_pspec) \
+ g_param_spec_ref (_pspec); \
+ g_value_reset (_value); \
+ while (_collect_type && !_error_msg) \
+ { \
+ GParamCValue _cvalue; \
+ \
+ memset (&_cvalue, 0, sizeof (_cvalue)); \
+ switch (_collect_type) \
+ { \
+ case G_VALUE_COLLECT_INT: \
+ _cvalue.v_int = va_arg ((var_args), gint); \
+ break; \
+ case G_VALUE_COLLECT_LONG: \
+ _cvalue.v_long = va_arg ((var_args), glong); \
+ break; \
+ case G_VALUE_COLLECT_DOUBLE: \
+ _cvalue.v_double = va_arg ((var_args), gdouble); \
+ break; \
+ case G_VALUE_COLLECT_POINTER: \
+ _cvalue.v_pointer = va_arg ((var_args), gpointer); \
+ break; \
+ default: \
+ _error_msg = g_strdup_printf ("%s: invalid collect type (%d) used for %s", \
+ G_STRLOC, \
+ _collect_type, \
+ "G_PARAM_COLLECT_VALUE()"); \
+ continue; \
+ } \
+ _error_msg = _pclass->param_collect_value (_value, \
+ _pspec, \
+ _nth_value++, \
+ &_collect_type, \
+ &_cvalue); \
+ } \
+ *(__error) = _error_msg; \
+ if (_pspec) \
+ g_param_spec_unref (_pspec); \
+ g_type_class_unref (_pclass); \
+} G_STMT_END
+
+
+/* G_PARAM_LCOPY_VALUE() collects a parameter's variable argument
+ * locations from a va_list. usage is analogous to G_PARAM_COLLECT_VALUE().
+ */
+#define G_PARAM_LCOPY_VALUE(param_value, param_spec, var_args, __error) \
+G_STMT_START { \
+ GValue *_value = (param_value); \
+ GParamSpecClass *_pclass = g_type_class_ref (_value->g_type); \
+ GParamSpec *_pspec = (param_spec); \
+ gchar *_error_msg = NULL; \
+ guint _lcopy_type = _pclass->lcopy_type; \
+ guint _nth_value = 0; \
+ \
+ if (_pspec) \
+ g_param_spec_ref (_pspec); \
+ while (_lcopy_type && !_error_msg) \
+ { \
+ GParamCValue _cvalue; \
+ \
+ memset (&_cvalue, 0, sizeof (_cvalue)); \
+ switch (_lcopy_type) \
+ { \
+ case G_VALUE_COLLECT_INT: \
+ _cvalue.v_int = va_arg ((var_args), gint); \
+ break; \
+ case G_VALUE_COLLECT_LONG: \
+ _cvalue.v_long = va_arg ((var_args), glong); \
+ break; \
+ case G_VALUE_COLLECT_DOUBLE: \
+ _cvalue.v_double = va_arg ((var_args), gdouble); \
+ break; \
+ case G_VALUE_COLLECT_POINTER: \
+ _cvalue.v_pointer = va_arg ((var_args), gpointer); \
+ break; \
+ default: \
+ _error_msg = g_strdup_printf ("%s: invalid collect type (%d) used for %s", \
+ G_STRLOC, \
+ _lcopy_type, \
+ "G_PARAM_LCOPY_VALUE()"); \
+ continue; \
+ } \
+ _error_msg = _pclass->param_lcopy_value (_value, \
+ _pspec, \
+ _nth_value++, \
+ &_lcopy_type, \
+ &_cvalue); \
+ } \
+ *(__error) = _error_msg; \
+ if (_pspec) \
+ g_param_spec_unref (_pspec); \
+ g_type_class_unref (_pclass); \
+} G_STMT_END
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_VALUE_COLLECTOR_H__ */