[kdbus] KDBUS_ITEM_PAYLOAD_OFF items are (once again) relative to msg header
[platform/upstream/glib.git] / gobject / gparamspecs.c
index 628d134..c48ae0c 100644 (file)
@@ -1,5 +1,6 @@
 /* GObject - GLib Type, Object, Parameter and Signal Library
- * Copyright (C) 1997, 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
+ * Copyright (C) 1997-1999, 2000-2001 Tim Janik and Red Hat, Inc.
+ * Copyright (C) 2010 Christian Persch
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * 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.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
-#include       "gparamspecs.h"
 
-#include       "gvaluecollector.h"
-#include       <string.h>
-#include       "../config.h"   /* for SIZEOF_LONG */
+/*
+ * MT safe
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
+#include "gparamspecs.h"
+#include "gtype-private.h"
+#include "gvaluecollector.h"
+
+#include "gvaluearray.h"
 
-#define        G_FLOAT_EPSILON         (1e-30)
-#define        G_DOUBLE_EPSILON        (1e-90)
+
+/**
+ * SECTION:param_value_types
+ * @short_description: Standard Parameter and Value Types
+ * @see_also: #GParamSpec, #GValue, g_object_class_install_property().
+ * @title: Parameters and Values
+ *
+ * #GValue provides an abstract container structure which can be
+ * copied, transformed and compared while holding a value of any
+ * (derived) type, which is registered as a #GType with a
+ * #GTypeValueTable in its #GTypeInfo structure.  Parameter
+ * specifications for most value types can be created as #GParamSpec
+ * derived instances, to implement e.g. #GObject properties which
+ * operate on #GValue containers.
+ *
+ * Parameter names need to start with a letter (a-z or A-Z). Subsequent
+ * characters can be letters, numbers or a '-'.
+ * All other characters are replaced by a '-' during construction.
+ */
 
 
-/* --- prototypes --- */
-extern void    g_param_spec_types_init (void);
+#define        G_FLOAT_EPSILON         (1e-30)
+#define        G_DOUBLE_EPSILON        (1e-90)
 
 
 /* --- param spec functions --- */
 static void
-param_spec_char_init (GParamSpec *pspec)
+param_char_init (GParamSpec *pspec)
 {
   GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
   
@@ -42,16 +69,15 @@ param_spec_char_init (GParamSpec *pspec)
 }
 
 static void
-param_char_init (GValue            *value,
-                GParamSpec *pspec)
+param_char_set_default (GParamSpec *pspec,
+                       GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
+  value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
 }
 
 static gboolean
-param_char_validate (GValue    *value,
-                    GParamSpec *pspec)
+param_char_validate (GParamSpec *pspec,
+                    GValue     *value)
 {
   GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
   gint oval = value->data[0].v_int;
@@ -61,27 +87,8 @@ param_char_validate (GValue  *value,
   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)
+param_uchar_init (GParamSpec *pspec)
 {
   GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
   
@@ -91,16 +98,15 @@ param_spec_uchar_init (GParamSpec *pspec)
 }
 
 static void
-param_uchar_init (GValue     *value,
-                 GParamSpec *pspec)
+param_uchar_set_default (GParamSpec *pspec,
+                        GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
+  value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
 }
 
 static gboolean
-param_uchar_validate (GValue    *value,
-                     GParamSpec *pspec)
+param_uchar_validate (GParamSpec *pspec,
+                     GValue     *value)
 {
   GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
   guint oval = value->data[0].v_uint;
@@ -111,16 +117,15 @@ param_uchar_validate (GValue       *value,
 }
 
 static void
-param_bool_init (GValue            *value,
-                GParamSpec *pspec)
+param_boolean_set_default (GParamSpec *pspec,
+                          GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_int = G_PARAM_SPEC_BOOL (pspec)->default_value;
+  value->data[0].v_int = G_PARAM_SPEC_BOOLEAN (pspec)->default_value;
 }
 
 static gboolean
-param_bool_validate (GValue    *value,
-                    GParamSpec *pspec)
+param_boolean_validate (GParamSpec *pspec,
+                       GValue     *value)
 {
   gint oval = value->data[0].v_int;
   
@@ -129,27 +134,8 @@ param_bool_validate (GValue        *value,
   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)
+param_int_init (GParamSpec *pspec)
 {
   GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
   
@@ -159,16 +145,15 @@ param_spec_int_init (GParamSpec *pspec)
 }
 
 static void
-param_int_init (GValue    *value,
-               GParamSpec *pspec)
+param_int_set_default (GParamSpec *pspec,
+                      GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
+  value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
 }
 
 static gboolean
-param_int_validate (GValue     *value,
-                   GParamSpec *pspec)
+param_int_validate (GParamSpec *pspec,
+                   GValue     *value)
 {
   GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
   gint oval = value->data[0].v_int;
@@ -179,50 +164,18 @@ param_int_validate (GValue     *value,
 }
 
 static gint
-param_int_values_cmp (const GValue *value1,
-                     const GValue *value2,
-                     GParamSpec   *pspec)
+param_int_values_cmp (GParamSpec   *pspec,
+                     const GValue *value1,
+                     const GValue *value2)
 {
   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;
+    return value1->data[0].v_int > value2->data[0].v_int;
 }
 
 static void
-param_spec_uint_init (GParamSpec *pspec)
+param_uint_init (GParamSpec *pspec)
 {
   GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
   
@@ -232,16 +185,15 @@ param_spec_uint_init (GParamSpec *pspec)
 }
 
 static void
-param_uint_init (GValue            *value,
-                GParamSpec *pspec)
+param_uint_set_default (GParamSpec *pspec,
+                       GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
+  value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
 }
 
 static gboolean
-param_uint_validate (GValue    *value,
-                    GParamSpec *pspec)
+param_uint_validate (GParamSpec *pspec,
+                    GValue     *value)
 {
   GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
   guint oval = value->data[0].v_uint;
@@ -252,18 +204,18 @@ param_uint_validate (GValue       *value,
 }
 
 static gint
-param_uint_values_cmp (const GValue *value1,
-                      const GValue *value2,
-                      GParamSpec   *pspec)
+param_uint_values_cmp (GParamSpec   *pspec,
+                      const GValue *value1,
+                      const GValue *value2)
 {
   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;
+    return value1->data[0].v_uint > value2->data[0].v_uint;
 }
 
 static void
-param_spec_long_init (GParamSpec *pspec)
+param_long_init (GParamSpec *pspec)
 {
   GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
   
@@ -278,16 +230,15 @@ param_spec_long_init (GParamSpec *pspec)
 }
 
 static void
-param_long_init (GValue            *value,
-                GParamSpec *pspec)
+param_long_set_default (GParamSpec *pspec,
+                       GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
+  value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
 }
 
 static gboolean
-param_long_validate (GValue    *value,
-                    GParamSpec *pspec)
+param_long_validate (GParamSpec *pspec,
+                    GValue     *value)
 {
   GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
   glong oval = value->data[0].v_long;
@@ -298,50 +249,18 @@ param_long_validate (GValue       *value,
 }
 
 static gint
-param_long_values_cmp (const GValue *value1,
-                      const GValue *value2,
-                      GParamSpec   *pspec)
+param_long_values_cmp (GParamSpec   *pspec,
+                      const GValue *value1,
+                      const GValue *value2)
 {
   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;
+    return value1->data[0].v_long > value2->data[0].v_long;
 }
 
 static void
-param_spec_ulong_init (GParamSpec *pspec)
+param_ulong_init (GParamSpec *pspec)
 {
   GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
   
@@ -355,16 +274,15 @@ param_spec_ulong_init (GParamSpec *pspec)
 }
 
 static void
-param_ulong_init (GValue     *value,
-                 GParamSpec *pspec)
+param_ulong_set_default (GParamSpec *pspec,
+                        GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
+  value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
 }
 
 static gboolean
-param_ulong_validate (GValue    *value,
-                     GParamSpec *pspec)
+param_ulong_validate (GParamSpec *pspec,
+                     GValue     *value)
 {
   GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
   gulong oval = value->data[0].v_ulong;
@@ -375,18 +293,140 @@ param_ulong_validate (GValue      *value,
 }
 
 static gint
-param_ulong_values_cmp (const GValue *value1,
-                       const GValue *value2,
-                       GParamSpec   *pspec)
+param_ulong_values_cmp (GParamSpec   *pspec,
+                       const GValue *value1,
+                       const GValue *value2)
 {
   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;
+    return value1->data[0].v_ulong > value2->data[0].v_ulong;
+}
+
+static void
+param_int64_init (GParamSpec *pspec)
+{
+  GParamSpecInt64 *lspec = G_PARAM_SPEC_INT64 (pspec);
+  
+  lspec->minimum = G_MININT64;
+  lspec->maximum = G_MAXINT64;
+  lspec->default_value = 0;
+}
+
+static void
+param_int64_set_default (GParamSpec *pspec,
+                       GValue     *value)
+{
+  value->data[0].v_int64 = G_PARAM_SPEC_INT64 (pspec)->default_value;
+}
+
+static gboolean
+param_int64_validate (GParamSpec *pspec,
+                    GValue     *value)
+{
+  GParamSpecInt64 *lspec = G_PARAM_SPEC_INT64 (pspec);
+  gint64 oval = value->data[0].v_int64;
+  
+  value->data[0].v_int64 = CLAMP (value->data[0].v_int64, lspec->minimum, lspec->maximum);
+  
+  return value->data[0].v_int64 != oval;
+}
+
+static gint
+param_int64_values_cmp (GParamSpec   *pspec,
+                      const GValue *value1,
+                      const GValue *value2)
+{
+  if (value1->data[0].v_int64 < value2->data[0].v_int64)
+    return -1;
+  else
+    return value1->data[0].v_int64 > value2->data[0].v_int64;
+}
+
+static void
+param_uint64_init (GParamSpec *pspec)
+{
+  GParamSpecUInt64 *uspec = G_PARAM_SPEC_UINT64 (pspec);
+  
+  uspec->minimum = 0;
+  uspec->maximum = G_MAXUINT64;
+  uspec->default_value = 0;
+}
+
+static void
+param_uint64_set_default (GParamSpec *pspec,
+                        GValue     *value)
+{
+  value->data[0].v_uint64 = G_PARAM_SPEC_UINT64 (pspec)->default_value;
+}
+
+static gboolean
+param_uint64_validate (GParamSpec *pspec,
+                     GValue     *value)
+{
+  GParamSpecUInt64 *uspec = G_PARAM_SPEC_UINT64 (pspec);
+  guint64 oval = value->data[0].v_uint64;
+  
+  value->data[0].v_uint64 = CLAMP (value->data[0].v_uint64, uspec->minimum, uspec->maximum);
+  
+  return value->data[0].v_uint64 != oval;
+}
+
+static gint
+param_uint64_values_cmp (GParamSpec   *pspec,
+                       const GValue *value1,
+                       const GValue *value2)
+{
+  if (value1->data[0].v_uint64 < value2->data[0].v_uint64)
+    return -1;
+  else
+    return value1->data[0].v_uint64 > value2->data[0].v_uint64;
+}
+
+static void
+param_unichar_init (GParamSpec *pspec)
+{
+  GParamSpecUnichar *uspec = G_PARAM_SPEC_UNICHAR (pspec);
+  
+  uspec->default_value = 0;
+}
+
+static void
+param_unichar_set_default (GParamSpec *pspec,
+                        GValue     *value)
+{
+  value->data[0].v_uint = G_PARAM_SPEC_UNICHAR (pspec)->default_value;
+}
+
+static gboolean
+param_unichar_validate (GParamSpec *pspec,
+                       GValue     *value)
+{
+  gunichar oval = value->data[0].v_uint;
+  gboolean changed = FALSE;
+
+  if (!g_unichar_validate (oval))
+    {
+      value->data[0].v_uint = 0;
+      changed = TRUE;
+    }
+
+  return changed;
+}
+
+static gint
+param_unichar_values_cmp (GParamSpec   *pspec,
+                       const GValue *value1,
+                       const GValue *value2)
+{
+  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_enum_init (GParamSpec *pspec)
+param_enum_init (GParamSpec *pspec)
 {
   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
   
@@ -395,7 +435,7 @@ param_spec_enum_init (GParamSpec *pspec)
 }
 
 static void
-param_spec_enum_finalize (GParamSpec *pspec)
+param_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));
@@ -410,16 +450,15 @@ param_spec_enum_finalize (GParamSpec *pspec)
 }
 
 static void
-param_enum_init (GValue            *value,
-                GParamSpec *pspec)
+param_enum_set_default (GParamSpec *pspec,
+                       GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
+  value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
 }
 
 static gboolean
-param_enum_validate (GValue    *value,
-                    GParamSpec *pspec)
+param_enum_validate (GParamSpec *pspec,
+                    GValue     *value)
 {
   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
   glong oval = value->data[0].v_long;
@@ -431,40 +470,8 @@ param_enum_validate (GValue        *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)
+param_flags_init (GParamSpec *pspec)
 {
   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
   
@@ -473,7 +480,7 @@ param_spec_flags_init (GParamSpec *pspec)
 }
 
 static void
-param_spec_flags_finalize (GParamSpec *pspec)
+param_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));
@@ -488,16 +495,15 @@ param_spec_flags_finalize (GParamSpec *pspec)
 }
 
 static void
-param_flags_init (GValue     *value,
-                 GParamSpec *pspec)
+param_flags_set_default (GParamSpec *pspec,
+                        GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
+  value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
 }
 
 static gboolean
-param_flags_validate (GValue    *value,
-                     GParamSpec *pspec)
+param_flags_validate (GParamSpec *pspec,
+                     GValue     *value)
 {
   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
   gulong oval = value->data[0].v_ulong;
@@ -511,27 +517,26 @@ param_flags_validate (GValue       *value,
 }
 
 static void
-param_spec_float_init (GParamSpec *pspec)
+param_float_init (GParamSpec *pspec)
 {
   GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
   
-  fspec->minimum = G_MINFLOAT;
+  fspec->minimum = -G_MAXFLOAT;
   fspec->maximum = G_MAXFLOAT;
   fspec->default_value = 0;
   fspec->epsilon = G_FLOAT_EPSILON;
 }
 
 static void
-param_float_init (GValue     *value,
-                 GParamSpec *pspec)
+param_float_set_default (GParamSpec *pspec,
+                        GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
+  value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
 }
 
 static gboolean
-param_float_validate (GValue    *value,
-                     GParamSpec *pspec)
+param_float_validate (GParamSpec *pspec,
+                     GValue     *value)
 {
   GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
   gfloat oval = value->data[0].v_float;
@@ -542,11 +547,11 @@ param_float_validate (GValue       *value,
 }
 
 static gint
-param_float_values_cmp (const GValue *value1,
-                       const GValue *value2,
-                       GParamSpec   *pspec)
+param_float_values_cmp (GParamSpec   *pspec,
+                       const GValue *value1,
+                       const GValue *value2)
 {
-  gfloat epsilon = pspec ? G_PARAM_SPEC_FLOAT (pspec)->epsilon : G_FLOAT_EPSILON;
+  gfloat epsilon = G_PARAM_SPEC_FLOAT (pspec)->epsilon;
   
   if (value1->data[0].v_float < value2->data[0].v_float)
     return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
@@ -554,60 +559,27 @@ param_float_values_cmp (const GValue *value1,
     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)
+param_double_init (GParamSpec *pspec)
 {
   GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
   
-  dspec->minimum = G_MINDOUBLE;
+  dspec->minimum = -G_MAXDOUBLE;
   dspec->maximum = G_MAXDOUBLE;
   dspec->default_value = 0;
   dspec->epsilon = G_DOUBLE_EPSILON;
 }
 
 static void
-param_double_init (GValue     *value,
-                  GParamSpec *pspec)
+param_double_set_default (GParamSpec *pspec,
+                         GValue     *value)
 {
-  if (pspec)
-    value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
+  value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
 }
 
 static gboolean
-param_double_validate (GValue    *value,
-                      GParamSpec *pspec)
+param_double_validate (GParamSpec *pspec,
+                      GValue     *value)
 {
   GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
   gdouble oval = value->data[0].v_double;
@@ -618,11 +590,11 @@ param_double_validate (GValue       *value,
 }
 
 static gint
-param_double_values_cmp (const GValue *value1,
-                        const GValue *value2,
-                        GParamSpec   *pspec)
+param_double_values_cmp (GParamSpec   *pspec,
+                        const GValue *value1,
+                        const GValue *value2)
 {
-  gdouble epsilon = pspec ? G_PARAM_SPEC_DOUBLE (pspec)->epsilon : G_DOUBLE_EPSILON;
+  gdouble epsilon = G_PARAM_SPEC_DOUBLE (pspec)->epsilon;
   
   if (value1->data[0].v_double < value2->data[0].v_double)
     return - (value2->data[0].v_double - value1->data[0].v_double > epsilon);
@@ -630,40 +602,8 @@ param_double_values_cmp (const GValue *value1,
     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)
+param_string_init (GParamSpec *pspec)
 {
   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
   
@@ -676,7 +616,7 @@ param_spec_string_init (GParamSpec *pspec)
 }
 
 static void
-param_spec_string_finalize (GParamSpec *pspec)
+param_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));
@@ -692,22 +632,15 @@ param_spec_string_finalize (GParamSpec *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)
+param_string_set_default (GParamSpec *pspec,
+                         GValue     *value)
 {
-  g_free (value->data[0].v_pointer);
+  value->data[0].v_pointer = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
 }
 
 static gboolean
-param_string_validate (GValue    *value,
-                      GParamSpec *pspec)
+param_string_validate (GParamSpec *pspec,
+                      GValue     *value)
 {
   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
   gchar *string = value->data[0].v_pointer;
@@ -719,6 +652,12 @@ param_string_validate (GValue        *value,
       
       if (sspec->cset_first && !strchr (sspec->cset_first, string[0]))
        {
+          if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
+            {
+              value->data[0].v_pointer = g_strdup (string);
+              string = value->data[0].v_pointer;
+              value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
+            }
          string[0] = sspec->substitutor;
          changed++;
        }
@@ -726,31 +665,42 @@ param_string_validate (GValue       *value,
        for (s = string + 1; *s; s++)
          if (!strchr (sspec->cset_nth, *s))
            {
+              if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
+                {
+                  value->data[0].v_pointer = g_strdup (string);
+                  s = (gchar*) value->data[0].v_pointer + (s - string);
+                  string = value->data[0].v_pointer;
+                  value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
+                }
              *s = sspec->substitutor;
              changed++;
            }
     }
   if (sspec->null_fold_if_empty && string && string[0] == 0)
     {
-      g_free (value->data[0].v_pointer);
+      if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
+        g_free (value->data[0].v_pointer);
+      else
+        value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
       value->data[0].v_pointer = NULL;
       changed++;
       string = value->data[0].v_pointer;
     }
   if (sspec->ensure_non_null && !string)
     {
+      value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
       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)
+param_string_values_cmp (GParamSpec   *pspec,
+                        const GValue *value1,
+                        const GValue *value2)
 {
   if (!value1->data[0].v_pointer)
     return value2->data[0].v_pointer != NULL ? -1 : 0;
@@ -761,77 +711,29 @@ param_string_values_cmp (const GValue *value1,
 }
 
 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)
+param_param_init (GParamSpec *pspec)
 {
-  GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
-  
-  ospec->object_type = G_TYPE_OBJECT;
+  /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
 }
 
 static void
-param_object_init (GValue     *value,
-                  GParamSpec *pspec)
+param_param_set_default (GParamSpec *pspec,
+                        GValue     *value)
 {
   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)
+param_param_validate (GParamSpec *pspec,
+                     GValue     *value)
 {
-  GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
-  GObject *object = value->data[0].v_pointer;
+  /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
+  GParamSpec *param = value->data[0].v_pointer;
   guint changed = 0;
   
-  if (object && !g_type_is_a (G_OBJECT_TYPE (object), ospec->object_type))
+  if (param && !g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_PARAM_SPEC_VALUE_TYPE (pspec)))
     {
-      g_object_unref (object);
+      g_param_spec_unref (param);
       value->data[0].v_pointer = NULL;
       changed++;
     }
@@ -839,864 +741,871 @@ param_object_validate (GValue     *value,
   return changed;
 }
 
-static gint
-param_object_values_cmp (const GValue *value1,
-                        const GValue *value2,
-                        GParamSpec   *pspec)
+static void
+param_boxed_init (GParamSpec *pspec)
 {
-  return value1->data[0].v_pointer != value2->data[0].v_pointer;
+  /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
 }
 
 static void
-param_object_copy_value (const GValue *src_value,
-                        GValue       *dest_value)
+param_boxed_set_default (GParamSpec *pspec,
+                        GValue     *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;
+  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)
+static gboolean
+param_boxed_validate (GParamSpec *pspec,
+                     GValue     *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;
+  /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
+  guint changed = 0;
+
+  /* can't do a whole lot here since we haven't even G_BOXED_TYPE() */
   
-  *collect_type = 0;
-  return NULL;
+  return changed;
 }
 
-static gchar*
-param_object_lcopy_value (const GValue *value,
-                         GParamSpec   *pspec,
-                         guint         nth_value,
-                         GType        *collect_type,
-                         GParamCValue *collect_value)
+static gint
+param_boxed_values_cmp (GParamSpec    *pspec,
+                        const GValue *value1,
+                        const GValue *value2)
 {
-  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;
+  guint8 *p1 = value1->data[0].v_pointer;
+  guint8 *p2 = value2->data[0].v_pointer;
+
+  /* not much to compare here, try to at least provide stable lesser/greater result */
+
+  return p1 < p2 ? -1 : p1 > p2;
 }
 
 static void
-value_exch_memcpy (GValue *value1,
-                  GValue *value2)
+param_pointer_init (GParamSpec *pspec)
 {
-  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));
+  /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
 }
 
 static void
-value_exch_long_int (GValue *value1,
-                    GValue *value2)
+param_pointer_set_default (GParamSpec *pspec,
+                          GValue     *value)
 {
-  glong tmp = value1->data[0].v_long;
-  value1->data[0].v_long = value2->data[0].v_int;
-  value2->data[0].v_int = tmp;
+  value->data[0].v_pointer = NULL;
 }
 
-static void
-value_exch_long_uint (GValue *value1,
-                     GValue *value2)
+static gboolean
+param_pointer_validate (GParamSpec *pspec,
+                       GValue     *value)
 {
-  glong tmp = value1->data[0].v_long;
-  value1->data[0].v_long = value2->data[0].v_uint;
-  value2->data[0].v_uint = tmp;
+  /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
+  guint changed = 0;
+  
+  return changed;
 }
 
-static void
-value_exch_ulong_int (GValue *value1,
-                     GValue *value2)
+static gint
+param_pointer_values_cmp (GParamSpec   *pspec,
+                         const GValue *value1,
+                         const 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;
+  guint8 *p1 = value1->data[0].v_pointer;
+  guint8 *p2 = value2->data[0].v_pointer;
+
+  /* not much to compare here, try to at least provide stable lesser/greater result */
+
+  return p1 < p2 ? -1 : p1 > p2;
 }
 
 static void
-value_exch_ulong_uint (GValue *value1,
-                      GValue *value2)
+param_value_array_init (GParamSpec *pspec)
 {
-  gulong tmp = value1->data[0].v_ulong;
-  value1->data[0].v_ulong = value2->data[0].v_uint;
-  value2->data[0].v_uint = tmp;
+  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
+
+  aspec->element_spec = NULL;
+  aspec->fixed_n_elements = 0; /* disable */
 }
 
-static void
-value_exch_float_int (GValue *value1,
-                     GValue *value2)
+static inline guint
+value_array_ensure_size (GValueArray *value_array,
+                        guint        fixed_n_elements)
 {
-  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;
+  guint changed = 0;
+
+  if (fixed_n_elements)
+    {
+      while (value_array->n_values < fixed_n_elements)
+       {
+         g_value_array_append (value_array, NULL);
+         changed++;
+       }
+      while (value_array->n_values > fixed_n_elements)
+       {
+         g_value_array_remove (value_array, value_array->n_values - 1);
+         changed++;
+       }
+    }
+  return changed;
 }
 
 static void
-value_exch_float_uint (GValue *value1,
-                      GValue *value2)
+param_value_array_finalize (GParamSpec *pspec)
 {
-  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;
+  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
+  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VALUE_ARRAY));
+
+  if (aspec->element_spec)
+    {
+      g_param_spec_unref (aspec->element_spec);
+      aspec->element_spec = NULL;
+    }
+
+  parent_class->finalize (pspec);
 }
 
 static void
-value_exch_float_long (GValue *value1,
-                      GValue *value2)
+param_value_array_set_default (GParamSpec *pspec,
+                              GValue     *value)
 {
-  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;
+  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
+
+  if (!value->data[0].v_pointer && aspec->fixed_n_elements)
+    value->data[0].v_pointer = g_value_array_new (aspec->fixed_n_elements);
+
+  if (value->data[0].v_pointer)
+    {
+      /* g_value_reset (value);  already done */
+      value_array_ensure_size (value->data[0].v_pointer, aspec->fixed_n_elements);
+    }
 }
 
-static void
-value_exch_float_ulong (GValue *value1,
-                       GValue *value2)
+static gboolean
+param_value_array_validate (GParamSpec *pspec,
+                           GValue     *value)
 {
-  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;
+  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
+  GValueArray *value_array = value->data[0].v_pointer;
+  guint changed = 0;
+
+  if (!value->data[0].v_pointer && aspec->fixed_n_elements)
+    value->data[0].v_pointer = g_value_array_new (aspec->fixed_n_elements);
+
+  if (value->data[0].v_pointer)
+    {
+      /* ensure array size validity */
+      changed += value_array_ensure_size (value_array, aspec->fixed_n_elements);
+      
+      /* ensure array values validity against a present element spec */
+      if (aspec->element_spec)
+       {
+         GParamSpec *element_spec = aspec->element_spec;
+         guint i;
+         
+         for (i = 0; i < value_array->n_values; i++)
+           {
+             GValue *element = value_array->values + i;
+             
+             /* need to fixup value type, or ensure that the array value is initialized at all */
+             if (!g_value_type_compatible (G_VALUE_TYPE (element), G_PARAM_SPEC_VALUE_TYPE (element_spec)))
+               {
+                 if (G_VALUE_TYPE (element) != 0)
+                   g_value_unset (element);
+                 g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
+                 g_param_value_set_default (element_spec, element);
+                 changed++;
+               }
+             /* validate array value against element_spec */
+             changed += g_param_value_validate (element_spec, element);
+           }
+       }
+    }
+
+  return changed;
 }
 
-static void
-value_exch_double_int (GValue *value1,
-                      GValue *value2)
+static gint
+param_value_array_values_cmp (GParamSpec   *pspec,
+                             const GValue *value1,
+                             const 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;
+  GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
+  GValueArray *value_array1 = value1->data[0].v_pointer;
+  GValueArray *value_array2 = value2->data[0].v_pointer;
+
+  if (!value_array1 || !value_array2)
+    return value_array2 ? -1 : value_array1 != value_array2;
+
+  if (value_array1->n_values != value_array2->n_values)
+    return value_array1->n_values < value_array2->n_values ? -1 : 1;
+  else if (!aspec->element_spec)
+    {
+      /* we need an element specification for comparisons, so there's not much
+       * to compare here, try to at least provide stable lesser/greater result
+       */
+      return value_array1->n_values < value_array2->n_values ? -1 : value_array1->n_values > value_array2->n_values;
+    }
+  else /* value_array1->n_values == value_array2->n_values */
+    {
+      guint i;
+
+      for (i = 0; i < value_array1->n_values; i++)
+       {
+         GValue *element1 = value_array1->values + i;
+         GValue *element2 = value_array2->values + i;
+         gint cmp;
+
+         /* need corresponding element types, provide stable result otherwise */
+         if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
+           return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
+         cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
+         if (cmp)
+           return cmp;
+       }
+      return 0;
+    }
 }
 
 static void
-value_exch_double_uint (GValue *value1,
-                       GValue *value2)
+param_object_init (GParamSpec *pspec)
 {
-  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;
+  /* GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec); */
 }
 
 static void
-value_exch_double_long (GValue *value1,
-                       GValue *value2)
+param_object_set_default (GParamSpec *pspec,
+                         GValue     *value)
 {
-  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;
+  value->data[0].v_pointer = NULL;
 }
 
-static void
-value_exch_double_ulong (GValue *value1,
-                        GValue *value2)
+static gboolean
+param_object_validate (GParamSpec *pspec,
+                      GValue     *value)
+{
+  GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
+  GObject *object = value->data[0].v_pointer;
+  guint changed = 0;
+  
+  if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
+    {
+      g_object_unref (object);
+      value->data[0].v_pointer = NULL;
+      changed++;
+    }
+  
+  return changed;
+}
+
+static gint
+param_object_values_cmp (GParamSpec   *pspec,
+                        const GValue *value1,
+                        const 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;
+  guint8 *p1 = value1->data[0].v_pointer;
+  guint8 *p2 = value2->data[0].v_pointer;
+
+  /* not much to compare here, try to at least provide stable lesser/greater result */
+
+  return p1 < p2 ? -1 : p1 > p2;
 }
 
 static void
-value_exch_double_float (GValue *value1,
-                        GValue *value2)
+param_override_init (GParamSpec *pspec)
 {
-  gdouble tmp = value1->data[0].v_double;
-  value1->data[0].v_double = value2->data[0].v_float;
-  value2->data[0].v_float = tmp;
+  /* GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec); */
 }
 
+static void
+param_override_finalize (GParamSpec *pspec)
+{
+  GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
+  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_OVERRIDE));
+  
+  if (ospec->overridden)
+    {
+      g_param_spec_unref (ospec->overridden);
+      ospec->overridden = NULL;
+    }
+  
+  parent_class->finalize (pspec);
+}
 
-/* --- 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_override_set_default (GParamSpec *pspec,
+                           GValue     *value)
+{
+  GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
+
+  g_param_value_set_default (ospec->overridden, value);
+}
+
+static gboolean
+param_override_validate (GParamSpec *pspec,
+                        GValue     *value)
+{
+  GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
+  
+  return g_param_value_validate (ospec->overridden, value);
+}
+
+static gint
+param_override_values_cmp (GParamSpec   *pspec,
+                          const GValue *value1,
+                          const GValue *value2)
+{
+  GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
+
+  return g_param_values_cmp (ospec->overridden, value1, value2);
+}
+
+static void
+param_gtype_init (GParamSpec *pspec)
+{
+}
+
+static void
+param_gtype_set_default (GParamSpec *pspec,
+                        GValue     *value)
+{
+  GParamSpecGType *tspec = G_PARAM_SPEC_GTYPE (pspec);
+
+  value->data[0].v_long = tspec->is_a_type;
+}
+
+static gboolean
+param_gtype_validate (GParamSpec *pspec,
+                     GValue     *value)
+{
+  GParamSpecGType *tspec = G_PARAM_SPEC_GTYPE (pspec);
+  GType gtype = value->data[0].v_long;
+  guint changed = 0;
+  
+  if (tspec->is_a_type != G_TYPE_NONE && !g_type_is_a (gtype, tspec->is_a_type))
+    {
+      value->data[0].v_long = tspec->is_a_type;
+      changed++;
+    }
+  
+  return changed;
+}
+
+static gint
+param_gtype_values_cmp (GParamSpec   *pspec,
+                       const GValue *value1,
+                       const GValue *value2)
+{
+  GType p1 = value1->data[0].v_long;
+  GType p2 = value2->data[0].v_long;
+
+  /* not much to compare here, try to at least provide stable lesser/greater result */
+
+  return p1 < p2 ? -1 : p1 > p2;
+}
+
+static void
+param_variant_init (GParamSpec *pspec)
+{
+  GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
+
+  vspec->type = NULL;
+  vspec->default_value = NULL;
+}
+
+static void
+param_variant_finalize (GParamSpec *pspec)
+{
+  GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
+  GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VARIANT));
+
+  if (vspec->default_value)
+    g_variant_unref (vspec->default_value);
+  g_variant_type_free (vspec->type);
+
+  parent_class->finalize (pspec);
+}
 
 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;
+param_variant_set_default (GParamSpec *pspec,
+                           GValue     *value)
+{
+  value->data[0].v_pointer = G_PARAM_SPEC_VARIANT (pspec)->default_value;
+  value->data[1].v_uint |= G_VALUE_NOCOPY_CONTENTS;
+}
+
+static gboolean
+param_variant_validate (GParamSpec *pspec,
+                        GValue     *value)
+{
+  GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
+  GVariant *variant = value->data[0].v_pointer;
+
+  if ((variant == NULL && vspec->default_value != NULL) ||
+      (variant != NULL && !g_variant_is_of_type (variant, vspec->type)))
+    {
+      g_param_value_set_default (pspec, value);
+      return TRUE;
+    }
+
+  return FALSE;
 }
 
+static gint
+param_variant_values_cmp (GParamSpec   *pspec,
+                          const GValue *value1,
+                          const GValue *value2)
+{
+  GVariant *v1 = value1->data[0].v_pointer;
+  GVariant *v2 = value2->data[0].v_pointer;
+
+  return v1 < v2 ? -1 : v2 > v1;
+}
+
+/* --- type initialization --- */
+GType *g_param_spec_types = NULL;
+
 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_param_spec_types_init (void)        
+{
+  const guint n_types = 23;
+  GType type, *spec_types, *spec_types_bound;
+
+  g_param_spec_types = g_new0 (GType, n_types);
+  spec_types = g_param_spec_types;
+  spec_types_bound = g_param_spec_types + n_types;
   
   /* G_TYPE_PARAM_CHAR
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecChar), /* instance_size */
+      16,                      /* n_preallocs */
+      param_char_init,         /* instance_init */
+      G_TYPE_CHAR,             /* value_type */
       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 */
+      param_char_set_default,  /* value_set_default */
+      param_char_validate,     /* value_validate */
+      param_int_values_cmp,    /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamChar"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_CHAR);
   }
   
   /* G_TYPE_PARAM_UCHAR
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecUChar), /* instance_size */
+      16,                       /* n_preallocs */
+      param_uchar_init,         /* instance_init */
+      G_TYPE_UCHAR,            /* value_type */
       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 */
+      param_uchar_set_default, /* value_set_default */
+      param_uchar_validate,    /* value_validate */
+      param_uint_values_cmp,   /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamUChar"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_UCHAR);
   }
   
-  /* G_TYPE_PARAM_BOOL
+  /* G_TYPE_PARAM_BOOLEAN
    */
   {
-    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 */
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecBoolean), /* instance_size */
+      16,                         /* n_preallocs */
+      NULL,                      /* instance_init */
+      G_TYPE_BOOLEAN,             /* value_type */
+      NULL,                       /* finalize */
+      param_boolean_set_default,  /* value_set_default */
+      param_boolean_validate,     /* value_validate */
+      param_int_values_cmp,       /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamBoolean"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_BOOLEAN);
   }
   
   /* G_TYPE_PARAM_INT
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecInt),   /* instance_size */
+      16,                       /* n_preallocs */
+      param_int_init,           /* instance_init */
+      G_TYPE_INT,              /* value_type */
       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 */
+      param_int_set_default,   /* value_set_default */
+      param_int_validate,      /* value_validate */
+      param_int_values_cmp,    /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamInt"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_INT);
   }
   
   /* G_TYPE_PARAM_UINT
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecUInt),  /* instance_size */
+      16,                       /* n_preallocs */
+      param_uint_init,          /* instance_init */
+      G_TYPE_UINT,             /* value_type */
       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 */
+      param_uint_set_default,  /* value_set_default */
+      param_uint_validate,     /* value_validate */
+      param_uint_values_cmp,   /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamUInt"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_UINT);
   }
   
   /* G_TYPE_PARAM_LONG
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecLong),  /* instance_size */
+      16,                       /* n_preallocs */
+      param_long_init,          /* instance_init */
+      G_TYPE_LONG,             /* value_type */
       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 */
+      param_long_set_default,  /* value_set_default */
+      param_long_validate,     /* value_validate */
+      param_long_values_cmp,   /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamLong"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_LONG);
   }
   
   /* G_TYPE_PARAM_ULONG
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecULong), /* instance_size */
+      16,                       /* n_preallocs */
+      param_ulong_init,         /* instance_init */
+      G_TYPE_ULONG,            /* value_type */
       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 */
+      param_ulong_set_default, /* value_set_default */
+      param_ulong_validate,    /* value_validate */
+      param_ulong_values_cmp,  /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamULong"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_ULONG);
   }
+
+  /* G_TYPE_PARAM_INT64
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecInt64),  /* instance_size */
+      16,                       /* n_preallocs */
+      param_int64_init,         /* instance_init */
+      G_TYPE_INT64,            /* value_type */
+      NULL,                    /* finalize */
+      param_int64_set_default, /* value_set_default */
+      param_int64_validate,    /* value_validate */
+      param_int64_values_cmp,  /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamInt64"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_INT64);
+  }
   
-  /* G_TYPE_PARAM_ENUM
+  /* G_TYPE_PARAM_UINT64
    */
   {
-    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 */
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecUInt64), /* instance_size */
+      16,                       /* n_preallocs */
+      param_uint64_init,        /* instance_init */
+      G_TYPE_UINT64,           /* value_type */
+      NULL,                    /* finalize */
+      param_uint64_set_default,        /* value_set_default */
+      param_uint64_validate,   /* value_validate */
+      param_uint64_values_cmp, /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamUInt64"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_UINT64);
+  }
+
+  /* G_TYPE_PARAM_UNICHAR
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecUnichar), /* instance_size */
+      16,                        /* n_preallocs */
+      param_unichar_init,       /* instance_init */
+      G_TYPE_UINT,              /* value_type */
+      NULL,                     /* finalize */
+      param_unichar_set_default, /* value_set_default */
+      param_unichar_validate,   /* value_validate */
+      param_unichar_values_cmp,         /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamUnichar"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_UNICHAR);
+  }
+
+ /* G_TYPE_PARAM_ENUM
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecEnum),  /* instance_size */
+      16,                       /* n_preallocs */
+      param_enum_init,          /* instance_init */
+      G_TYPE_ENUM,             /* value_type */
+      param_enum_finalize,     /* finalize */
+      param_enum_set_default,  /* value_set_default */
+      param_enum_validate,     /* value_validate */
+      param_long_values_cmp,   /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamEnum"), &pspec_info);
+    *spec_types++ = type;
     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 */
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecFlags),        /* instance_size */
+      16,                      /* n_preallocs */
+      param_flags_init,                /* instance_init */
+      G_TYPE_FLAGS,            /* value_type */
+      param_flags_finalize,    /* finalize */
+      param_flags_set_default, /* value_set_default */
+      param_flags_validate,    /* value_validate */
+      param_ulong_values_cmp,  /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamFlags"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_FLAGS);
   }
   
   /* G_TYPE_PARAM_FLOAT
    */
   {
-    static const ParamSpecClassInfo class_info = {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecFloat), /* instance_size */
+      16,                       /* n_preallocs */
+      param_float_init,         /* instance_init */
+      G_TYPE_FLOAT,            /* value_type */
       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 */
+      param_float_set_default, /* value_set_default */
+      param_float_validate,    /* value_validate */
+      param_float_values_cmp,  /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamFloat"), &pspec_info);
+    *spec_types++ = type;
     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 */
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecDouble),       /* instance_size */
+      16,                              /* n_preallocs */
+      param_double_init,               /* instance_init */
+      G_TYPE_DOUBLE,                   /* value_type */
+      NULL,                            /* finalize */
+      param_double_set_default,                /* value_set_default */
+      param_double_validate,           /* value_validate */
+      param_double_values_cmp,         /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamDouble"), &pspec_info);
+    *spec_types++ = type;
     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 */
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecString),       /* instance_size */
+      16,                              /* n_preallocs */
+      param_string_init,               /* instance_init */
+      G_TYPE_STRING,                   /* value_type */
+      param_string_finalize,           /* finalize */
+      param_string_set_default,                /* value_set_default */
+      param_string_validate,           /* value_validate */
+      param_string_values_cmp,         /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamString"), &pspec_info);
+    *spec_types++ = type;
     g_assert (type == G_TYPE_PARAM_STRING);
   }
   
-  /* G_TYPE_PARAM_OBJECT
+  /* G_TYPE_PARAM_PARAM
    */
   {
-    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 */
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecParam),        /* instance_size */
+      16,                      /* n_preallocs */
+      param_param_init,                /* instance_init */
+      G_TYPE_PARAM,            /* value_type */
+      NULL,                    /* finalize */
+      param_param_set_default, /* value_set_default */
+      param_param_validate,    /* value_validate */
+      param_pointer_values_cmp,        /* values_cmp */
     };
-    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);
+    type = g_param_type_register_static (g_intern_static_string ("GParamParam"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_PARAM);
   }
   
-  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;
-}
+  /* G_TYPE_PARAM_BOXED
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecBoxed),        /* instance_size */
+      4,                       /* n_preallocs */
+      param_boxed_init,                /* instance_init */
+      G_TYPE_BOXED,            /* value_type */
+      NULL,                    /* finalize */
+      param_boxed_set_default, /* value_set_default */
+      param_boxed_validate,    /* value_validate */
+      param_boxed_values_cmp,  /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamBoxed"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_BOXED);
+  }
 
-void
-g_value_set_string (GValue     *value,
-                   const gchar *v_string)
-{
-  g_return_if_fail (G_IS_VALUE_STRING (value));
+  /* G_TYPE_PARAM_POINTER
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecPointer),  /* instance_size */
+      0,                           /* n_preallocs */
+      param_pointer_init,         /* instance_init */
+      G_TYPE_POINTER,                     /* value_type */
+      NULL,                       /* finalize */
+      param_pointer_set_default,   /* value_set_default */
+      param_pointer_validate,     /* value_validate */
+      param_pointer_values_cmp,           /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamPointer"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_POINTER);
+  }
   
-  g_free (value->data[0].v_pointer);
-  value->data[0].v_pointer = g_strdup (v_string);
-}
+  /* G_TYPE_PARAM_VALUE_ARRAY
+   */
+  {
+    static /* const */ GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecValueArray),   /* instance_size */
+      0,                               /* n_preallocs */
+      param_value_array_init,          /* instance_init */
+      0xdeadbeef,                      /* value_type, assigned further down */
+      param_value_array_finalize,      /* finalize */
+      param_value_array_set_default,   /* value_set_default */
+      param_value_array_validate,      /* value_validate */
+      param_value_array_values_cmp,    /* values_cmp */
+    };
+    pspec_info.value_type = G_TYPE_VALUE_ARRAY;
+    type = g_param_type_register_static (g_intern_static_string ("GParamValueArray"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_VALUE_ARRAY);
+  }
 
-gchar*
-g_value_get_string (GValue *value)
-{
-  g_return_val_if_fail (G_IS_VALUE_STRING (value), NULL);
-  
-  return value->data[0].v_pointer;
-}
+  /* G_TYPE_PARAM_OBJECT
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecObject), /* instance_size */
+      16,                        /* n_preallocs */
+      param_object_init,        /* instance_init */
+      G_TYPE_OBJECT,            /* value_type */
+      NULL,                     /* finalize */
+      param_object_set_default,         /* value_set_default */
+      param_object_validate,    /* value_validate */
+      param_object_values_cmp,  /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamObject"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_OBJECT);
+  }
 
-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);
-}
+  /* G_TYPE_PARAM_OVERRIDE
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecOverride), /* instance_size */
+      16,                        /* n_preallocs */
+      param_override_init,      /* instance_init */
+      G_TYPE_NONE,              /* value_type */
+      param_override_finalize,  /* finalize */
+      param_override_set_default, /* value_set_default */
+      param_override_validate,   /* value_validate */
+      param_override_values_cmp,  /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamOverride"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_OVERRIDE);
+  }
 
-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);
-}
+  /* G_TYPE_PARAM_GTYPE
+   */
+  {
+    GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecGType),        /* instance_size */
+      0,                       /* n_preallocs */
+      param_gtype_init,                /* instance_init */
+      0xdeadbeef,              /* value_type, assigned further down */
+      NULL,                    /* finalize */
+      param_gtype_set_default, /* value_set_default */
+      param_gtype_validate,    /* value_validate */
+      param_gtype_values_cmp,  /* values_cmp */
+    };
+    pspec_info.value_type = G_TYPE_GTYPE;
+    type = g_param_type_register_static (g_intern_static_string ("GParamGType"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_GTYPE);
+  }
 
-GObject*
-g_value_get_object (GValue *value)
-{
-  g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
-  
-  return value->data[0].v_pointer;
-}
+  /* G_TYPE_PARAM_VARIANT
+   */
+  {
+    const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecVariant), /* instance_size */
+      0,                          /* n_preallocs */
+      param_variant_init,         /* instance_init */
+      G_TYPE_VARIANT,             /* value_type */
+      param_variant_finalize,     /* finalize */
+      param_variant_set_default,  /* value_set_default */
+      param_variant_validate,     /* value_validate */
+      param_variant_values_cmp,   /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamVariant"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_VARIANT);
+  }
 
-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;
+  g_assert (spec_types == spec_types_bound);
 }
 
-
 /* --- GParamSpec initialization --- */
+
+/**
+ * g_param_spec_char:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecChar instance specifying a %G_TYPE_CHAR property.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_char (const gchar *name,
                   const gchar *nick,
@@ -1706,11 +1615,17 @@ g_param_spec_char (const gchar *name,
                   gint8        default_value,
                   GParamFlags  flags)
 {
-  GParamSpecChar *cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
-                                                name,
-                                                nick,
-                                                blurb,
-                                                flags);
+  GParamSpecChar *cspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (cspec == NULL)
+    return NULL;
   
   cspec->minimum = minimum;
   cspec->maximum = maximum;
@@ -1719,6 +1634,20 @@ g_param_spec_char (const gchar *name,
   return G_PARAM_SPEC (cspec);
 }
 
+/**
+ * g_param_spec_uchar:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecUChar instance specifying a %G_TYPE_UCHAR property.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_uchar (const gchar *name,
                    const gchar *nick,
@@ -1728,11 +1657,17 @@ g_param_spec_uchar (const gchar *name,
                    guint8       default_value,
                    GParamFlags  flags)
 {
-  GParamSpecUChar *uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
-                                                 name,
-                                                 nick,
-                                                 blurb,
-                                                 flags);
+  GParamSpecUChar *uspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (uspec == NULL)
+    return NULL;
   
   uspec->minimum = minimum;
   uspec->maximum = maximum;
@@ -1741,24 +1676,61 @@ g_param_spec_uchar (const gchar *name,
   return G_PARAM_SPEC (uspec);
 }
 
+/**
+ * g_param_spec_boolean:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecBoolean instance specifying a %G_TYPE_BOOLEAN
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
-g_param_spec_bool (const gchar *name,
-                  const gchar *nick,
-                  const gchar *blurb,
-                  gboolean     default_value,
-                  GParamFlags  flags)
+g_param_spec_boolean (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);
+  GParamSpecBoolean *bspec;
+
+  g_return_val_if_fail (default_value == TRUE || default_value == FALSE, NULL);
+
+  bspec = g_param_spec_internal (G_TYPE_PARAM_BOOLEAN,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (bspec == NULL)
+    return NULL;
   
   bspec->default_value = default_value;
   
   return G_PARAM_SPEC (bspec);
 }
 
+/**
+ * g_param_spec_int:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecInt instance specifying a %G_TYPE_INT property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_int (const gchar *name,
                  const gchar *nick,
@@ -1768,11 +1740,17 @@ g_param_spec_int (const gchar *name,
                  gint         default_value,
                  GParamFlags  flags)
 {
-  GParamSpecInt *ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
-                                               name,
-                                               nick,
-                                               blurb,
-                                               flags);
+  GParamSpecInt *ispec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (ispec == NULL)
+    return NULL;
   
   ispec->minimum = minimum;
   ispec->maximum = maximum;
@@ -1781,6 +1759,22 @@ g_param_spec_int (const gchar *name,
   return G_PARAM_SPEC (ispec);
 }
 
+/**
+ * g_param_spec_uint:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecUInt instance specifying a %G_TYPE_UINT property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_uint (const gchar *name,
                   const gchar *nick,
@@ -1790,11 +1784,17 @@ g_param_spec_uint (const gchar *name,
                   guint        default_value,
                   GParamFlags  flags)
 {
-  GParamSpecUInt *uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
-                                                name,
-                                                nick,
-                                                blurb,
-                                                flags);
+  GParamSpecUInt *uspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (uspec == NULL)
+    return NULL;
   
   uspec->minimum = minimum;
   uspec->maximum = maximum;
@@ -1803,6 +1803,22 @@ g_param_spec_uint (const gchar *name,
   return G_PARAM_SPEC (uspec);
 }
 
+/**
+ * g_param_spec_long:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecLong instance specifying a %G_TYPE_LONG property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_long (const gchar *name,
                   const gchar *nick,
@@ -1812,11 +1828,17 @@ g_param_spec_long (const gchar *name,
                   glong        default_value,
                   GParamFlags  flags)
 {
-  GParamSpecLong *lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
-                                                name,
-                                                nick,
-                                                blurb,
-                                                flags);
+  GParamSpecLong *lspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (lspec == NULL)
+    return NULL;
   
   lspec->minimum = minimum;
   lspec->maximum = maximum;
@@ -1825,6 +1847,23 @@ g_param_spec_long (const gchar *name,
   return G_PARAM_SPEC (lspec);
 }
 
+/**
+ * g_param_spec_ulong:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecULong instance specifying a %G_TYPE_ULONG
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_ulong (const gchar *name,
                    const gchar *nick,
@@ -1834,11 +1873,106 @@ g_param_spec_ulong (const gchar *name,
                    gulong       default_value,
                    GParamFlags  flags)
 {
-  GParamSpecULong *uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
-                                                 name,
-                                                 nick,
-                                                 blurb,
-                                                 flags);
+  GParamSpecULong *uspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (uspec == NULL)
+    return NULL;
+  
+  uspec->minimum = minimum;
+  uspec->maximum = maximum;
+  uspec->default_value = default_value;
+  
+  return G_PARAM_SPEC (uspec);
+}
+
+/**
+ * g_param_spec_int64:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecInt64 instance specifying a %G_TYPE_INT64 property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_int64 (const gchar *name,
+                   const gchar *nick,
+                   const gchar *blurb,
+                   gint64       minimum,
+                   gint64       maximum,
+                   gint64       default_value,
+                   GParamFlags  flags)
+{
+  GParamSpecInt64 *lspec;
+  
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  lspec = g_param_spec_internal (G_TYPE_PARAM_INT64,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (lspec == NULL)
+    return NULL;
+  
+  lspec->minimum = minimum;
+  lspec->maximum = maximum;
+  lspec->default_value = default_value;
+  
+  return G_PARAM_SPEC (lspec);
+}
+
+/**
+ * g_param_spec_uint64:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecUInt64 instance specifying a %G_TYPE_UINT64
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_uint64 (const gchar *name,
+                    const gchar *nick,
+                    const gchar *blurb,
+                    guint64      minimum,
+                    guint64      maximum,
+                    guint64      default_value,
+                    GParamFlags  flags)
+{
+  GParamSpecUInt64 *uspec;
+  
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+  
+  uspec = g_param_spec_internal (G_TYPE_PARAM_UINT64,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (uspec == NULL)
+    return NULL;
   
   uspec->minimum = minimum;
   uspec->maximum = maximum;
@@ -1847,6 +1981,60 @@ g_param_spec_ulong (const gchar *name,
   return G_PARAM_SPEC (uspec);
 }
 
+/**
+ * g_param_spec_unichar:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecUnichar instance specifying a %G_TYPE_UINT
+ * property. #GValue structures for this property can be accessed with
+ * g_value_set_uint() and g_value_get_uint().
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_unichar (const gchar *name,
+                     const gchar *nick,
+                     const gchar *blurb,
+                     gunichar     default_value,
+                     GParamFlags  flags)
+{
+  GParamSpecUnichar *uspec;
+
+  uspec = g_param_spec_internal (G_TYPE_PARAM_UNICHAR,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (uspec == NULL)
+    return NULL;
+  
+  uspec->default_value = default_value;
+  
+  return G_PARAM_SPEC (uspec);
+}
+
+/**
+ * g_param_spec_enum:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @enum_type: a #GType derived from %G_TYPE_ENUM
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecEnum instance specifying a %G_TYPE_ENUM
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_enum (const gchar *name,
                   const gchar *nick,
@@ -1856,21 +2044,45 @@ g_param_spec_enum (const gchar *name,
                   GParamFlags  flags)
 {
   GParamSpecEnum *espec;
+  GEnumClass *enum_class;
   
   g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
+
+  enum_class = g_type_class_ref (enum_type);
+
+  g_return_val_if_fail (g_enum_get_value (enum_class, default_value) != NULL, NULL);
   
   espec = g_param_spec_internal (G_TYPE_PARAM_ENUM,
                                 name,
                                 nick,
                                 blurb,
                                 flags);
+  if (espec == NULL)
+    return NULL;
   
-  espec->enum_class = g_type_class_ref (enum_type);
+  espec->enum_class = enum_class;
   espec->default_value = default_value;
+  G_PARAM_SPEC (espec)->value_type = enum_type;
   
   return G_PARAM_SPEC (espec);
 }
 
+/**
+ * g_param_spec_flags:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @flags_type: a #GType derived from %G_TYPE_FLAGS
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecFlags instance specifying a %G_TYPE_FLAGS
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_flags (const gchar *name,
                    const gchar *nick,
@@ -1880,21 +2092,45 @@ g_param_spec_flags (const gchar *name,
                    GParamFlags  flags)
 {
   GParamSpecFlags *fspec;
+  GFlagsClass *flags_class;
   
   g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
+
+  flags_class = g_type_class_ref (flags_type);
+
+  g_return_val_if_fail ((default_value & flags_class->mask) == default_value, NULL);
   
   fspec = g_param_spec_internal (G_TYPE_PARAM_FLAGS,
                                 name,
                                 nick,
                                 blurb,
                                 flags);
+  if (fspec == NULL)
+    return NULL;
   
-  fspec->flags_class = g_type_class_ref (flags_type);
+  fspec->flags_class = flags_class;
   fspec->default_value = default_value;
+  G_PARAM_SPEC (fspec)->value_type = flags_type;
   
   return G_PARAM_SPEC (fspec);
 }
 
+/**
+ * g_param_spec_float:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecFloat instance specifying a %G_TYPE_FLOAT property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_float (const gchar *name,
                    const gchar *nick,
@@ -1904,11 +2140,17 @@ g_param_spec_float (const gchar *name,
                    gfloat       default_value,
                    GParamFlags  flags)
 {
-  GParamSpecFloat *fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
-                                                 name,
-                                                 nick,
-                                                 blurb,
-                                                 flags);
+  GParamSpecFloat *fspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (fspec == NULL)
+    return NULL;
   
   fspec->minimum = minimum;
   fspec->maximum = maximum;
@@ -1917,6 +2159,23 @@ g_param_spec_float (const gchar *name,
   return G_PARAM_SPEC (fspec);
 }
 
+/**
+ * g_param_spec_double:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @minimum: minimum value for the property specified
+ * @maximum: maximum value for the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecDouble instance specifying a %G_TYPE_DOUBLE
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_double (const gchar *name,
                     const gchar *nick,
@@ -1926,11 +2185,17 @@ g_param_spec_double (const gchar *name,
                     gdouble      default_value,
                     GParamFlags  flags)
 {
-  GParamSpecDouble *dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
-                                                  name,
-                                                  nick,
-                                                  blurb,
-                                                  flags);
+  GParamSpecDouble *dspec;
+
+  g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
+
+  dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (dspec == NULL)
+    return NULL;
   
   dspec->minimum = minimum;
   dspec->maximum = maximum;
@@ -1939,6 +2204,20 @@ g_param_spec_double (const gchar *name,
   return G_PARAM_SPEC (dspec);
 }
 
+/**
+ * g_param_spec_string:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @default_value: default value for the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecString instance.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_string (const gchar *name,
                     const gchar *nick,
@@ -1951,37 +2230,228 @@ g_param_spec_string (const gchar *name,
                                                   nick,
                                                   blurb,
                                                   flags);
+  if (sspec == NULL)
+    return NULL;
+
   g_free (sspec->default_value);
   sspec->default_value = g_strdup (default_value);
   
   return G_PARAM_SPEC (sspec);
 }
 
+/**
+ * g_param_spec_param:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @param_type: a #GType derived from %G_TYPE_PARAM
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecParam instance specifying a %G_TYPE_PARAM
+ * property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
-g_param_spec_string_c (const gchar *name,
-                      const gchar *nick,
-                      const gchar *blurb,
-                      const gchar *default_value,
-                      GParamFlags  flags)
+g_param_spec_param (const gchar *name,
+                   const gchar *nick,
+                   const gchar *blurb,
+                   GType        param_type,
+                   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);
+  GParamSpecParam *pspec;
   
-  return G_PARAM_SPEC (sspec);
+  g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
+  
+  pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (pspec == NULL)
+    return NULL;
+
+  G_PARAM_SPEC (pspec)->value_type = param_type;
+  
+  return G_PARAM_SPEC (pspec);
+}
+
+/**
+ * g_param_spec_boxed:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @boxed_type: %G_TYPE_BOXED derived type of this property
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecBoxed instance specifying a %G_TYPE_BOXED
+ * derived property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_boxed (const gchar *name,
+                   const gchar *nick,
+                   const gchar *blurb,
+                   GType        boxed_type,
+                   GParamFlags  flags)
+{
+  GParamSpecBoxed *bspec;
+  
+  g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
+  g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type), NULL);
+  
+  bspec = g_param_spec_internal (G_TYPE_PARAM_BOXED,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (bspec == NULL)
+    return NULL;
+
+  G_PARAM_SPEC (bspec)->value_type = boxed_type;
+  
+  return G_PARAM_SPEC (bspec);
+}
+
+/**
+ * g_param_spec_pointer:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecPointer instance specifying a pointer property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_pointer (const gchar *name,
+                     const gchar *nick,
+                     const gchar *blurb,
+                     GParamFlags  flags)
+{
+  GParamSpecPointer *pspec;
+  
+  pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (pspec == NULL)
+    return NULL;
+
+  return G_PARAM_SPEC (pspec);
+}
+
+/**
+ * g_param_spec_gtype:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @is_a_type: a #GType whose subtypes are allowed as values
+ *  of the property (use %G_TYPE_NONE for any type)
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecGType instance specifying a
+ * %G_TYPE_GTYPE property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Since: 2.10
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_gtype (const gchar *name,
+                   const gchar *nick,
+                   const gchar *blurb,
+                   GType        is_a_type,
+                   GParamFlags  flags)
+{
+  GParamSpecGType *tspec;
+  
+  tspec = g_param_spec_internal (G_TYPE_PARAM_GTYPE,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (tspec == NULL)
+    return NULL;
+
+  tspec->is_a_type = is_a_type;
+
+  return G_PARAM_SPEC (tspec);
+}
+
+/**
+ * g_param_spec_value_array: (skip)
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @element_spec: a #GParamSpec describing the elements contained in
+ *  arrays of this property, may be %NULL
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecValueArray instance specifying a
+ * %G_TYPE_VALUE_ARRAY property. %G_TYPE_VALUE_ARRAY is a
+ * %G_TYPE_BOXED type, as such, #GValue structures for this property
+ * can be accessed with g_value_set_boxed() and g_value_get_boxed().
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: a newly created parameter specification
+ */
+GParamSpec*
+g_param_spec_value_array (const gchar *name,
+                         const gchar *nick,
+                         const gchar *blurb,
+                         GParamSpec  *element_spec,
+                         GParamFlags  flags)
+{
+  GParamSpecValueArray *aspec;
+  
+  if (element_spec)
+    g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
+  
+  aspec = g_param_spec_internal (G_TYPE_PARAM_VALUE_ARRAY,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  if (aspec == NULL)
+    return NULL;
+
+  if (element_spec)
+    {
+      aspec->element_spec = g_param_spec_ref (element_spec);
+      g_param_spec_sink (element_spec);
+    }
+
+  return G_PARAM_SPEC (aspec);
 }
 
+/**
+ * g_param_spec_object:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @object_type: %G_TYPE_OBJECT derived type of this property
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecBoxed instance specifying a %G_TYPE_OBJECT
+ * derived property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): a newly created parameter specification
+ */
 GParamSpec*
 g_param_spec_object (const gchar *name,
                     const gchar *nick,
@@ -1991,14 +2461,112 @@ g_param_spec_object (const gchar *name,
 {
   GParamSpecObject *ospec;
   
-  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+  g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
   
   ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
                                 name,
                                 nick,
                                 blurb,
                                 flags);
-  ospec->object_type = object_type;
+  if (ospec == NULL)
+    return NULL;
+
+  G_PARAM_SPEC (ospec)->value_type = object_type;
   
   return G_PARAM_SPEC (ospec);
 }
+
+/**
+ * g_param_spec_override: (skip)
+ * @name: the name of the property.
+ * @overridden: The property that is being overridden
+ *
+ * Creates a new property of type #GParamSpecOverride. This is used
+ * to direct operations to another paramspec, and will not be directly
+ * useful unless you are implementing a new base type similar to GObject.
+ *
+ * Since: 2.4
+ *
+ * Returns: the newly created #GParamSpec
+ */
+GParamSpec*
+g_param_spec_override (const gchar *name,
+                      GParamSpec  *overridden)
+{
+  GParamSpec *pspec;
+  
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (G_IS_PARAM_SPEC (overridden), NULL);
+  
+  /* Dereference further redirections for property that was passed in
+   */
+  while (TRUE)
+    {
+      GParamSpec *indirect = g_param_spec_get_redirect_target (overridden);
+      if (indirect)
+       overridden = indirect;
+      else
+       break;
+    }
+
+  pspec = g_param_spec_internal (G_TYPE_PARAM_OVERRIDE,
+                                name, NULL, NULL,
+                                overridden->flags);
+  if (pspec == NULL)
+    return NULL;
+  
+  pspec->value_type = G_PARAM_SPEC_VALUE_TYPE (overridden);
+  G_PARAM_SPEC_OVERRIDE (pspec)->overridden = g_param_spec_ref (overridden);
+
+  return pspec;
+}
+
+/**
+ * g_param_spec_variant:
+ * @name: canonical name of the property specified
+ * @nick: nick name for the property specified
+ * @blurb: description of the property specified
+ * @type: a #GVariantType
+ * @default_value: (allow-none) (transfer full): a #GVariant of type @type to
+ *                 use as the default value, or %NULL
+ * @flags: flags for the property specified
+ *
+ * Creates a new #GParamSpecVariant instance specifying a #GVariant
+ * property.
+ *
+ * If @default_value is floating, it is consumed.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): the newly created #GParamSpec
+ *
+ * Since: 2.26
+ */
+GParamSpec*
+g_param_spec_variant (const gchar        *name,
+                      const gchar        *nick,
+                      const gchar        *blurb,
+                      const GVariantType *type,
+                      GVariant           *default_value,
+                      GParamFlags         flags)
+{
+  GParamSpecVariant *vspec;
+
+  g_return_val_if_fail (type != NULL, NULL);
+  g_return_val_if_fail (default_value == NULL ||
+                        g_variant_is_of_type (default_value, type), NULL);
+
+  vspec = g_param_spec_internal (G_TYPE_PARAM_VARIANT,
+                                 name,
+                                 nick,
+                                 blurb,
+                                 flags);
+  if (vspec == NULL)
+    return NULL;
+
+  vspec->type = g_variant_type_copy (type);
+  if (default_value)
+    vspec->default_value = g_variant_ref_sink (default_value);
+
+  return G_PARAM_SPEC (vspec);
+}