+ class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
+ object_queue_property (object, pspec, nqueue);
+}
+
+gpointer
+g_object_new (GType object_type,
+ const gchar *first_property_name,
+ ...)
+{
+ GObject *object;
+ va_list var_args;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+
+ va_start (var_args, first_property_name);
+ object = g_object_new_valist (object_type, first_property_name, var_args);
+ va_end (var_args);
+
+ return object;
+}
+
+gpointer
+g_object_new_valist (GType object_type,
+ const gchar *first_property_name,
+ va_list var_args)
+{
+ NotifyQueue *nqueue;
+ GObject *object;
+ GObjectClass *class;
+ const gchar *name;
+ GObjectConstructParam *cparams = NULL, *nparams = NULL;
+ guint n_cparams = 0, n_nparams = 0;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+
+ /* collect parameters, sort into construction and normal ones */
+ name = first_property_name;
+ while (name)
+ {
+ const gchar *trailer = NULL;
+ GValue *value;
+ GParamSpec *pspec;
+ gchar *error = NULL;
+
+ pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
+ name,
+ object_type,
+ TRUE,
+ &trailer);
+ if (!pspec)
+ {
+ g_warning ("%s: object class `%s' has no property named `%s'",
+ G_STRLOC,
+ g_type_name (object_type),
+ name);
+ break;
+ }
+ if (!(pspec->flags & G_PARAM_WRITABLE))
+ {
+ g_warning ("%s: property `%s' of object class `%s' is not writable",
+ G_STRLOC,
+ pspec->name,
+ g_type_name (object_type));
+ break;
+ }
+
+ value = g_new (GValue, 1);
+ value->g_type = 0;
+ g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ G_VALUE_COLLECT (value, var_args, &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occoured
+ */
+ break;
+ }
+ if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+ {
+ if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
+ cparams = g_renew (GObjectConstructParam, cparams, n_cparams + 1);
+ cparams[n_cparams].pspec = pspec;
+ cparams[n_cparams].value = value;
+ cparams[n_cparams].trailer = trailer;
+ n_cparams++;
+ }
+ else
+ {
+ if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
+ nparams = g_renew (GObjectConstructParam, nparams, n_nparams + 1);
+ nparams[n_nparams].pspec = pspec;
+ nparams[n_nparams].value = value;
+ nparams[n_nparams].trailer = trailer;
+ n_nparams++;
+ }
+
+ name = va_arg (var_args, gchar*);
+ }
+
+ /* construct object from construction parameters */
+ class = g_type_class_ref (object_type);
+ object = class->constructor (object_type, n_cparams, cparams);
+ g_type_class_unref (class);
+
+ /* free construction values */
+ while (n_cparams--)
+ {
+ g_value_unset (cparams[n_cparams].value);
+ g_free (cparams[n_cparams].value);
+ }
+ g_free (cparams);
+
+ /* release g_object_init() notification queue freeze_count */
+ nqueue = object_freeze_notifies (object);
+ nqueue->freeze_count--;
+
+ /* set remaining properties */
+ while (n_nparams--)
+ {
+ GValue *value = nparams[n_nparams].value;
+ GParamSpec *pspec = nparams[n_nparams].pspec;
+ const gchar *trailer = nparams[n_nparams].trailer;
+
+ /* convert if necessary */
+ if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
+ {
+ GValue tmp_value = { 0, };
+
+ g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ if (!g_value_convert (value, &tmp_value) ||
+ g_param_value_validate (pspec, &tmp_value))
+ g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
+ G_STRLOC,
+ G_VALUE_TYPE_NAME (value),
+ pspec->name,
+ g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+ else
+ object_set_property (object, &tmp_value, pspec, trailer, nqueue);
+ g_value_unset (&tmp_value);
+ }
+ else
+ object_set_property (object, value, pspec, trailer, nqueue);
+
+ g_value_unset (value);
+ g_free (value);
+ }
+ g_free (nparams);
+
+ /* release our own freeze count and handle notifications */
+ object_thaw_notifies (object, nqueue);