fixed dealing with collection/lcopy of NULL values.
authorTim Janik <timj@gtk.org>
Tue, 12 Dec 2000 07:32:00 +0000 (07:32 +0000)
committerTim Janik <timj@src.gnome.org>
Tue, 12 Dec 2000 07:32:00 +0000 (07:32 +0000)
Mon Dec 11 04:44:11 2000  Tim Janik  <timj@gtk.org>

* gboxed.c: fixed dealing with collection/lcopy of NULL values.

* gclosure.h: removed insane ramblings, added G_CALLBACK() a casting
convenience macro.

* Makefile.am: cleanups, marshaller generation rules.

* gmarshal.[hc]: new files with GRuntime standard marshallers.

* glib-genmarshal.c: fix log domain, support gruntime standard
marshallers, suport G_TYPE_PARAM, come with extern "C" and
#include gmarshal.h.

* glib-genmarshal.1: reflect glib-genmarshal.c updates.

* gobject.[hc]: implement object constructor. rework parameter
changed notification queueing, we support queue freezes now and
don't dispatch from an idle handler anymore.
parameter->property rename hassle.
implemented ::properties_changed and ::notify::* signals for
property change notification (the later supports property names
as details). added signal connection and named data properties.
(g_signal_connect_object): new function to setup while_alive
connections.
(g_object_class_install_property): sink properties now, since they
are initially floating.
(g_object_steal_data):
(g_object_set_data_full):
(g_object_set_data):
(g_object_get_data): set/get data by using g_datalist_*() functions
directly.
(g_object_queue_param_changed): nuked.
(g_object_freeze_notify): start queueing of property changes (freeze/
thaw calls stack).
(g_object_notify): announce changes of a certain property directly.
(g_object_thaw_notify): process queue of property changes, therefore
emitting GObject::notify::detail with detail being the changed
properties names.
(G_OBJECT_WARN_INVALID_PROPERTY_ID): saner macro variant of former
G_WARN_INVALID_PARAM_ID().

* gparam.[hc]: param specs are now initially floating and need to be
sunken with g_param_spec_sink(), support G_TYPE_PARAM values.
added G_PARAM_CONSTRUCT and G_PARAM_CONSTRUCT_ONLY parameter flags,
required by GObjectClass.constructor().

* gparamspecs.[hc]: added GParamSpecParam, GParamSpecPointer and
GParamSpecCCallback, param specs for G_TYPE_PARAM, G_TYPE_POINTER
and G_TYPE_CCALLBACK respectively.

* gsignal.[hc]: cleanups.
(signal_id_lookup): after walking the anchestry, try interfaces as well.
(g_signal_new): new function to create signals from varargs type list.
(g_signal_connect_closure): closure connection variant that works from
signal name+detail.
(g_signal_connect_data): c handler connection variant that works from
signal name+detail.
(g_signal_emit_valist): emit signal for an instance with paraneters
collected from a va_list.
(g_signal_emit): emit signal, taking parameters from varargs list.
(g_signal_emit_by_name): same as g_signal_emit, working from
signal name+detail.
(signal_emit_R): return whether return_value needs to be altered.

* gtype.[hc]: set log-domain to GRuntime, i'm slowly getting to all
the points that need to reflect the upcoming rename.
melt g_type_conforms_to() functionality into g_type_is_a(), as that
is what we really want (liskov substitution principle).
assorted changes to other files due to conforms_to->is_a.

* gvalue.[hc]: implemented g_value_set_instance() that sets a value
from an instantiatable type via the value_table's collect_value()
function (based on an idea from James Henstridge <james@daa.com.au>).
cleanups/fixes.

* gvaluetypes.[hc]: implement G_TYPE_CCALLBACK and G_TYPE_PARAM.

44 files changed:
configure.in
docs/reference/glib/tmpl/arrays.sgml
docs/reference/glib/tmpl/arrays_byte.sgml
docs/reference/glib/tmpl/arrays_pointer.sgml
docs/reference/glib/tmpl/caches.sgml
docs/reference/glib/tmpl/completion.sgml
docs/reference/glib/tmpl/conversions.sgml
docs/reference/glib/tmpl/fileutils.sgml
docs/reference/glib/tmpl/glib-unused.sgml
docs/reference/glib/tmpl/hash_tables.sgml
docs/reference/glib/tmpl/iochannels.sgml
docs/reference/glib/tmpl/linked_lists_double.sgml
docs/reference/glib/tmpl/linked_lists_single.sgml
docs/reference/glib/tmpl/main.sgml
docs/reference/glib/tmpl/markup.sgml
docs/reference/glib/tmpl/relations.sgml
docs/reference/glib/tmpl/shell.sgml
docs/reference/glib/tmpl/strings.sgml
docs/reference/glib/tmpl/trees-binary.sgml
gobject/ChangeLog
gobject/Makefile.am
gobject/gboxed.c
gobject/gclosure.c
gobject/gclosure.h
gobject/glib-genmarshal.1
gobject/glib-genmarshal.c
gobject/gobject.c
gobject/gobject.h
gobject/gparam.c
gobject/gparam.h
gobject/gparamspecs.c
gobject/gparamspecs.h
gobject/gsignal.c
gobject/gsignal.h
gobject/gtype.c
gobject/gtype.h
gobject/gtypemodule.c
gobject/gvalue.c
gobject/gvalue.h
gobject/gvaluecollector.h
gobject/gvaluetypes.c
gobject/gvaluetypes.h
gobject/makefile.mingw.in
gobject/makefile.msc.in

index 6fd14ac..4ec48f9 100644 (file)
@@ -109,6 +109,7 @@ AC_ARG_ENABLE(ansi, [  --enable-ansi           turn on strict ansi [default=no]]
                    , enable_ansi=no)
 AC_ARG_ENABLE(threads, [  --enable-threads        turn on basic thread support [default=yes]
                           ([=no] will override --with-threads)],,enable_threads=yes)
+AC_ARG_ENABLE(rebuilds, [  --disable-rebuilds      disable all source autogeneration rules],,enable_rebuilds=yes)
 
 if test "x$enable_threads" != "xyes"; then
   enable_threads=no
@@ -163,6 +164,21 @@ AC_PROG_CC
 AM_PROG_CC_STDC
 AC_PROG_INSTALL
 
+# define a MAINT-like variable REBUILD which is set if Perl
+# and awk are found, so autogenerated sources can be rebuilt
+AC_PROG_AWK
+AC_CHECK_PROGS(PERL, perl5 perl)
+# We would like indent, but don't require it.
+AC_CHECK_PROG(INDENT, indent, indent)
+REBUILD=\#
+if test "x$enable_rebuilds" = "xyes" && \
+     test -n "$PERL" && \
+     $PERL -e 'exit !($] >= 5.002)' > /dev/null 2>&1 && \
+     test -n "$AWK" ; then
+  REBUILD=
+fi
+AC_SUBST(REBUILD)
+
 dnl Initialize libtool
 AM_PROG_LIBTOOL
 
index f4eea22..bf1f0d1 100644 (file)
@@ -209,25 +209,6 @@ g_array_remove_index().
 @Returns: the #GArray.
 
 
-<!-- ##### FUNCTION g_array_sort ##### -->
-<para>
-
-</para>
-
-@array: 
-@compare_func: 
-
-
-<!-- ##### FUNCTION g_array_sort_with_data ##### -->
-<para>
-
-</para>
-
-@array: 
-@compare_func: 
-@user_data: 
-
-
 <!-- ##### MACRO g_array_index ##### -->
 <para>
 Returns the element of a #GArray at the given index.
index 9d2fb83..0a454e6 100644 (file)
@@ -123,25 +123,6 @@ g_byte_array_remove_index().
 @Returns: the #GByteArray.
 
 
-<!-- ##### FUNCTION g_byte_array_sort ##### -->
-<para>
-
-</para>
-
-@array: 
-@compare_func: 
-
-
-<!-- ##### FUNCTION g_byte_array_sort_with_data ##### -->
-<para>
-
-</para>
-
-@array: 
-@compare_func: 
-@user_data: 
-
-
 <!-- ##### FUNCTION g_byte_array_set_size ##### -->
 <para>
 Sets the size of the #GByteArray, expanding it if necessary.
index f44d90f..fa6659a 100644 (file)
@@ -156,25 +156,6 @@ g_ptr_array_remove_index().
 @Returns: the pointer which was removed.
 
 
-<!-- ##### FUNCTION g_ptr_array_sort ##### -->
-<para>
-
-</para>
-
-@array: 
-@compare_func: 
-
-
-<!-- ##### FUNCTION g_ptr_array_sort_with_data ##### -->
-<para>
-
-</para>
-
-@array: 
-@compare_func: 
-@user_data: 
-
-
 <!-- ##### FUNCTION g_ptr_array_set_size ##### -->
 <para>
 Sets the size of the array, expanding it if necessary.
index 33752e5..119b732 100644 (file)
@@ -51,11 +51,11 @@ called by g_cache_remove() when the object is no longer needed (i.e. its
 reference count drops to 0).
 @hash_key_func: a function to create a hash value from a key.
 @hash_value_func: a function to create a hash value from a value.
-@key_equal_func: a function to compare two keys. It should return TRUE if
-the two keys are equivalent.
+@key_compare_func: 
 @Returns: a new #GCache.
 <!-- # Unused Parameters # -->
-@key_compare_func: 
+@key_equal_func: a function to compare two keys. It should return TRUE if
+the two keys are equivalent.
 
 
 <!-- ##### FUNCTION g_cache_insert ##### -->
index 80500e2..6bb7681 100644 (file)
@@ -47,7 +47,6 @@ g_completion_complete().
 @func: 
 @prefix: 
 @cache: 
-@strncmp_func: 
 
 <!-- ##### FUNCTION g_completion_new ##### -->
 <para>
@@ -71,16 +70,6 @@ This is used when you use data structures as #GCompletion items.
 @Returns: the string corresponding to the item.
 
 
-<!-- ##### USER_FUNCTION GCompletionStrcmpFunc ##### -->
-<para>
-
-</para>
-
-@s1: 
-@s2: 
-@Returns: 
-
-
 <!-- ##### FUNCTION g_completion_add_items ##### -->
 <para>
 Adds items to the #GCompletion.
index 5ce9133..1253402 100644 (file)
@@ -52,56 +52,15 @@ Character Set Conversion
 
 
 
-<!-- ##### FUNCTION g_iconv_open ##### -->
-<para>
-
-</para>
-
-@to_codeset: 
-@from_codeset: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_iconv ##### -->
-<para>
-
-</para>
-
-@converter: 
-@inbuf: 
-@inbytes_left: 
-@outbuf: 
-@outbytes_left: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_iconv_close ##### -->
-<para>
-
-</para>
-
-@converter: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_locale_to_utf8 ##### -->
-<para>
-
-</para>
-
-@opsysstring: 
-@error: 
-@Returns: 
-
-
 <!-- ##### FUNCTION g_filename_to_utf8 ##### -->
 <para>
 
 </para>
 
 @opsysstring: 
-@error: 
 @Returns: 
+<!-- # Unused Parameters # -->
+@error: 
 
 
 <!-- ##### FUNCTION g_filename_from_utf8 ##### -->
@@ -110,18 +69,9 @@ Character Set Conversion
 </para>
 
 @utf8string: 
-@error: 
 @Returns: 
-
-
-<!-- ##### FUNCTION g_locale_from_utf8 ##### -->
-<para>
-
-</para>
-
-@utf8string: 
+<!-- # Unused Parameters # -->
 @error: 
-@Returns: 
 
 
 <!-- ##### ENUM GConvertError ##### -->
@@ -132,5 +82,4 @@ Character Set Conversion
 @G_CONVERT_ERROR_NO_CONVERSION: 
 @G_CONVERT_ERROR_ILLEGAL_SEQUENCE: 
 @G_CONVERT_ERROR_FAILED: 
-@G_CONVERT_ERROR_PARTIAL_INPUT: 
 
index a5e9037..40b2c39 100644 (file)
@@ -93,23 +93,3 @@ File Utilities
 @Returns: 
 
 
-<!-- ##### FUNCTION g_mkstemp ##### -->
-<para>
-
-</para>
-
-@tmpl: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_file_open_tmp ##### -->
-<para>
-
-</para>
-
-@tmpl: 
-@name_used: 
-@error: 
-@Returns: 
-
-
index debc85f..f22b1e7 100644 (file)
@@ -1,24 +1,61 @@
-<!-- ##### FUNCTION g_main_remove_poll ##### -->
+<!-- ##### FUNCTION g_markup_parse_context_parse ##### -->
 <para>
-Removes a file descriptor from the list being polled.
+
 </para>
 
-@fd: the #GPollFD to remove.
+@context: 
+@text: 
+@text_len: 
+@error: 
+@Returns: 
 
-<!-- ##### MACRO lseek ##### -->
+<!-- ##### STRUCT GSource ##### -->
 <para>
 
 </para>
 
 
-<!-- ##### FUNCTION g_convert_error_quark ##### -->
+<!-- ##### FUNCTION g_source_connect_indirect ##### -->
 <para>
 
 </para>
 
+@source: 
+@callback_data: 
+@callback_funcs: 
+
+<!-- ##### FUNCTION g_locale_to_utf8 ##### -->
+<para>
+
+</para>
+
+@opsysstring: 
+@error: 
 @Returns: 
 
-<!-- ##### MACRO write ##### -->
+<!-- ##### FUNCTION g_iconv_close ##### -->
+<para>
+
+</para>
+
+@converter: 
+@Returns: 
+
+<!-- ##### MACRO popen ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION g_source_set_can_recurse ##### -->
+<para>
+
+</para>
+
+@source: 
+@can_recurse: 
+
+<!-- ##### MACRO pclose ##### -->
 <para>
 
 </para>
@@ -40,26 +77,122 @@ the results may be needed.
 See #G_PRIORITY_DEFAULT, #G_PRIORITY_DEFAULT_IDLE, #G_PRIORITY_HIGH,
 #G_PRIORITY_HIGH_IDLE, and #G_PRIORITY_LOW.
 
-<!-- ##### MACRO pclose ##### -->
+<!-- ##### ENUM GMarkupError ##### -->
 <para>
 
 </para>
 
+@G_MARKUP_ERROR_BAD_UTF8: text being parsed was not valid UTF-8
+@G_MARKUP_ERROR_EMPTY: document contained nothing, or only whitespace
+@G_MARKUP_ERROR_PARSE: document was ill-formed
+@G_MARKUP_ERROR_UNKNOWN_ELEMENT: error should be set by #GMarkupParser functions; element wasn't known
+@G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE: error should be set by #GMarkupParser functions; attribute wasn't known
+@G_MARKUP_ERROR_INVALID_CONTENT: error should be set by #GMarkupParser functions; something was wrong with contents of the document, e.g. invalid attribute value
 
-<!-- ##### MACRO g_string ##### -->
+<!-- ##### FUNCTION g_main_context_add_poll ##### -->
 <para>
-Turns the argument into a string literal by using the '#' stringizing operator.
+
 </para>
 
-@x: text to convert to a literal string.
+@context: 
+@fd: 
+@priority: 
 
-<!-- ##### MACRO popen ##### -->
+<!-- ##### MACRO lseek ##### -->
 <para>
 
 </para>
 
 
-<!-- ##### MACRO access ##### -->
+<!-- ##### FUNCTION g_string_new_len ##### -->
+<para>
+
+</para>
+
+@init: 
+@len: 
+@Returns: 
+
+<!-- ##### STRUCT GSourceCallbackFuncs ##### -->
+<para>
+
+</para>
+
+@ref: 
+@unref: 
+@get: 
+
+<!-- ##### FUNCTION g_array_sort ##### -->
+<para>
+
+</para>
+
+@array: 
+@compare_func: 
+
+<!-- ##### FUNCTION g_main_context_find_source_by_funcs_user_data ##### -->
+<para>
+
+</para>
+
+@context: 
+@funcs: 
+@user_data: 
+@Returns: 
+@source_data: 
+
+<!-- ##### FUNCTION g_markup_parse_context_free ##### -->
+<para>
+
+</para>
+
+@context: 
+
+<!-- ##### STRUCT GMarkupParseContext ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION g_ptr_array_sort ##### -->
+<para>
+
+</para>
+
+@array: 
+@compare_func: 
+
+<!-- ##### FUNCTION g_main_context_query ##### -->
+<para>
+
+</para>
+
+@context: 
+@max_priority: 
+@timeout: 
+@fds: 
+@n_fds: 
+@Returns: 
+
+<!-- ##### FUNCTION g_iconv_open ##### -->
+<para>
+
+</para>
+
+@to_codeset: 
+@from_codeset: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_new ##### -->
+<para>
+
+</para>
+
+@source_funcs: 
+@struct_size: 
+@Returns: 
+
+<!-- ##### MACRO getpid ##### -->
 <para>
 
 </para>
@@ -78,17 +211,43 @@ priority are stored in the order in which they were added.
 type of source.
 @Returns: TRUE if an event source was found and removed.
 
-<!-- ##### MACRO open ##### -->
+<!-- ##### MACRO close ##### -->
 <para>
 
 </para>
 
 
-<!-- ##### MACRO getpid ##### -->
+<!-- ##### FUNCTION g_source_get_id ##### -->
 <para>
 
 </para>
 
+@source: 
+@Returns: 
+
+<!-- ##### FUNCTION g_mkstemp ##### -->
+<para>
+
+</para>
+
+@tmpl: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_get_poll_func ##### -->
+<para>
+
+</para>
+
+@context: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_add_poll ##### -->
+<para>
+
+</para>
+
+@source: 
+@fd: 
 
 <!-- ##### MACRO fdopen ##### -->
 <para>
@@ -96,11 +255,240 @@ type of source.
 </para>
 
 
-<!-- ##### MACRO close ##### -->
+<!-- ##### FUNCTION g_source_get_current_time ##### -->
 <para>
 
 </para>
 
+@source: 
+@timeval: 
+
+<!-- ##### USER_FUNCTION GCompletionStrcmpFunc ##### -->
+<para>
+
+</para>
+
+@s1: 
+@s2: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_loop_new ##### -->
+<para>
+
+</para>
+
+@context: 
+@is_running: 
+@Returns: 
+
+<!-- ##### FUNCTION g_iconv ##### -->
+<para>
+
+</para>
+
+@converter: 
+@inbuf: 
+@inbytes_left: 
+@outbuf: 
+@outbytes_left: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_ref ##### -->
+<para>
+
+</para>
+
+@source: 
+@Returns: 
+
+<!-- ##### FUNCTION g_byte_array_sort ##### -->
+<para>
+
+</para>
+
+@array: 
+@compare_func: 
+
+<!-- ##### FUNCTION g_markup_parse_context_get_position ##### -->
+<para>
+
+</para>
+
+@context: 
+@line_number: 
+@char_number: 
+
+<!-- ##### FUNCTION g_locale_from_utf8 ##### -->
+<para>
+
+</para>
+
+@utf8string: 
+@error: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_loop_is_running ##### -->
+<para>
+
+</para>
+
+@loop: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_remove_poll ##### -->
+<para>
+
+</para>
+
+@context: 
+@fd: 
+
+<!-- ##### FUNCTION g_byte_array_sort_with_data ##### -->
+<para>
+
+</para>
+
+@array: 
+@compare_func: 
+@user_data: 
+
+<!-- ##### FUNCTION g_markup_parse_context_new ##### -->
+<para>
+
+</para>
+
+@parser: 
+@flags: 
+@user_data: 
+@user_data_dnotify: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_get_can_recurse ##### -->
+<para>
+
+</para>
+
+@source: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_get ##### -->
+<para>
+
+</para>
+
+@thread: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_remove_poll ##### -->
+<para>
+
+</para>
+
+@source: 
+@fd: 
+
+<!-- ##### FUNCTION g_tree_new_with_data ##### -->
+<para>
+
+</para>
+
+@key_compare_func: 
+@user_data: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_get_priority ##### -->
+<para>
+
+</para>
+
+@source: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_connect ##### -->
+<para>
+
+</para>
+
+@source: 
+@func: 
+@data: 
+@notify: 
+
+<!-- ##### FUNCTION g_main_context_iteration ##### -->
+<para>
+
+</para>
+
+@context: 
+@may_block: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_dispatch ##### -->
+<para>
+
+</para>
+
+@context: 
+
+<!-- ##### FUNCTION g_main_loop_quit ##### -->
+<para>
+
+</para>
+
+@loop: 
+
+<!-- ##### FUNCTION g_main_context_prepare ##### -->
+<para>
+
+</para>
+
+@context: 
+@priority: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_set_priority ##### -->
+<para>
+
+</para>
+
+@source: 
+@priority: 
+
+<!-- ##### FUNCTION g_ptr_array_sort_with_data ##### -->
+<para>
+
+</para>
+
+@array: 
+@compare_func: 
+@user_data: 
+
+<!-- ##### FUNCTION g_list_sort_with_data ##### -->
+<para>
+
+</para>
+
+@list: 
+@compare_func: 
+@user_data: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_find_source_by_user_data ##### -->
+<para>
+
+</para>
+
+@context: 
+@user_data: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_set_poll_func ##### -->
+<para>
+
+</para>
+
+@context: 
+@func: 
 
 <!-- ##### MACRO getcwd ##### -->
 <para>
@@ -108,11 +496,71 @@ type of source.
 </para>
 
 
-<!-- ##### MACRO read ##### -->
+<!-- ##### FUNCTION g_io_create_watch ##### -->
 <para>
 
 </para>
 
+@channel: 
+@condition: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_unref ##### -->
+<para>
+
+</para>
+
+@source: 
+
+<!-- ##### MACRO write ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION g_main_context_find_source_by_id ##### -->
+<para>
+
+</para>
+
+@context: 
+@id: 
+@Returns: 
+
+<!-- ##### FUNCTION g_main_remove_poll ##### -->
+<para>
+Removes a file descriptor from the list being polled.
+</para>
+
+@fd: the #GPollFD to remove.
+
+<!-- ##### MACRO access ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO g_string ##### -->
+<para>
+Turns the argument into a string literal by using the '#' stringizing operator.
+</para>
+
+@x: text to convert to a literal string.
+
+<!-- ##### FUNCTION g_idle_source_new ##### -->
+<para>
+
+</para>
+
+@Returns: 
+
+<!-- ##### FUNCTION g_main_context_pending ##### -->
+<para>
+
+</para>
+
+@context: 
+@Returns: 
 
 <!-- ##### FUNCTION g_main_win32_get_poll_func ##### -->
 <para>
@@ -121,3 +569,175 @@ type of source.
 
 @Returns: 
 
+<!-- ##### FUNCTION g_main_loop_run ##### -->
+<para>
+
+</para>
+
+@loop: 
+
+<!-- ##### MACRO read ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION g_array_sort_with_data ##### -->
+<para>
+
+</para>
+
+@array: 
+@compare_func: 
+@user_data: 
+
+<!-- ##### MACRO G_MARKUP_ERROR ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION g_main_context_default ##### -->
+<para>
+
+</para>
+
+@Returns: 
+
+<!-- ##### ENUM GMarkupParseFlags ##### -->
+<para>
+There are no flags right now
+</para>
+
+@G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG: 
+
+<!-- ##### FUNCTION g_slist_sort_with_data ##### -->
+<para>
+
+</para>
+
+@list: 
+@compare_func: 
+@user_data: 
+@Returns: 
+
+<!-- ##### FUNCTION g_markup_parse_context_end_parse ##### -->
+<para>
+
+</para>
+
+@context: 
+@error: 
+@Returns: 
+
+<!-- ##### FUNCTION g_source_get_context ##### -->
+<para>
+
+</para>
+
+@source: 
+@Returns: 
+
+<!-- ##### FUNCTION g_timeout_source_new ##### -->
+<para>
+
+</para>
+
+@interval: 
+@Returns: 
+
+<!-- ##### STRUCT GMarkupParser ##### -->
+<para>
+Any of the fields in #GMarkupParser can be %NULL, in which case they
+will be ignored. Except for the @error function, any of these
+callbacks can set an error; in particular the
+%G_MARKUP_ERROR_UNKNOWN_ELEMENT, %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
+and %G_MARKUP_ERROR_INVALID_CONTENT errors are intended to be set 
+from these callbacks. If you set an error from a callback,
+g_markup_parse_context_parse() will report that error back to its caller.
+</para>
+
+@start_element: Callback to invoke when the opening tag of an element
+is seen.
+@end_element: Callback to invoke when the closing tag of an element is seen
+@text: Callback to invoke when some text is seen (text is always
+inside an element)
+@passthrough: Callback to invoke for comments and processing
+instructions; if you're re-writing the parsed document, write the
+passthrough text back out in the same position
+@error: Callback to invoke when an error occurs
+
+<!-- ##### USER_FUNCTION GEqualFunc ##### -->
+<para>
+Specifies the type of a function used to test two values for
+equality. The function should return TRUE if both values are equal and
+FALSE otherwise.
+</para>
+
+@a: a value.
+@b: a value to compare with.
+@Returns: TRUE if @a = @b; FALSE otherwise.
+
+<!-- ##### FUNCTION g_main_loop_destroy ##### -->
+<para>
+
+</para>
+
+@loop: 
+
+<!-- ##### FUNCTION g_file_open_tmp ##### -->
+<para>
+
+</para>
+
+@tmpl: 
+@name_used: 
+@error: 
+@Returns: 
+
+<!-- ##### STRUCT GMainContext ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### FUNCTION g_main_context_check ##### -->
+<para>
+
+</para>
+
+@context: 
+@max_priority: 
+@fds: 
+@n_fds: 
+@Returns: 
+
+<!-- ##### FUNCTION g_convert_error_quark ##### -->
+<para>
+
+</para>
+
+@Returns: 
+
+<!-- ##### FUNCTION g_source_destroy ##### -->
+<para>
+
+</para>
+
+@source: 
+
+<!-- ##### FUNCTION g_markup_escape_text ##### -->
+<para>
+
+</para>
+
+@text: 
+@length: 
+@Returns: 
+
+<!-- ##### MACRO open ##### -->
+<para>
+
+</para>
+
+
index c638038..edbab18 100644 (file)
@@ -69,15 +69,15 @@ Hash values are used to determine where keys are stored within the
 #GHashTable data structure.
 The g_direct_hash(), g_int_hash() and g_str_hash() functions are provided for
 some common types of keys. If hash_func is NULL, g_direct_hash() is used.
+@key_compare_func: 
+@Returns: a new #GHashTable.
+<!-- # Unused Parameters # -->
 @key_equal_func: a function to check two keys for equality.  This is
 used when looking up keys in the #GHashTable.  The g_direct_equal(),
 g_int_equal() and g_str_equal() functions are provided for the most
 common types of keys. If @key_equal_func is NULL, keys are compared
 directly in a similar fashion to g_direct_equal(), but without the
 overhead of a function call.
-@Returns: a new #GHashTable.
-<!-- # Unused Parameters # -->
-@key_compare_func: 
 
 
 <!-- ##### USER_FUNCTION GHashFunc ##### -->
@@ -104,18 +104,6 @@ lookup.
 @Returns: the hash value corresponding to the key.
 
 
-<!-- ##### USER_FUNCTION GEqualFunc ##### -->
-<para>
-Specifies the type of a function used to test two values for
-equality. The function should return TRUE if both values are equal and
-FALSE otherwise.
-</para>
-
-@a: a value.
-@b: a value to compare with.
-@Returns: TRUE if @a = @b; FALSE otherwise.
-
-
 <!-- ##### FUNCTION g_hash_table_insert ##### -->
 <para>
 Inserts a new key and value into a #GHashTable.
index ebfdd05..1c44eb2 100644 (file)
@@ -209,16 +209,6 @@ Decrements the reference count of a #GIOChannel.
 @channel: a #GIOChannel.
 
 
-<!-- ##### FUNCTION g_io_create_watch ##### -->
-<para>
-
-</para>
-
-@channel: 
-@condition: 
-@Returns: 
-
-
 <!-- ##### FUNCTION g_io_add_watch ##### -->
 <para>
 Adds the #GIOChannel into the
@@ -324,6 +314,6 @@ generic way.
 @io_write: 
 @io_seek: 
 @io_close: 
-@io_create_watch: 
+@io_add_watch: 
 @io_free: 
 
index 8812d8a..ab995f0 100644 (file)
@@ -268,17 +268,6 @@ value if the first element comes after the second.
 @Returns: the start of the sorted #GList.
 
 
-<!-- ##### FUNCTION g_list_sort_with_data ##### -->
-<para>
-
-</para>
-
-@list: 
-@compare_func: 
-@user_data: 
-@Returns: 
-
-
 <!-- ##### USER_FUNCTION GCompareFunc ##### -->
 <para>
 Specifies the type of a comparison function used to compare two
index 780240f..3bb1a4e 100644 (file)
@@ -271,17 +271,6 @@ value if the first element comes after the second.
 @Returns: the start of the sorted #GList.
 
 
-<!-- ##### FUNCTION g_slist_sort_with_data ##### -->
-<para>
-
-</para>
-
-@list: 
-@compare_func: 
-@user_data: 
-@Returns: 
-
-
 <!-- ##### FUNCTION g_slist_concat ##### -->
 <para>
 Adds the second #GSList onto the end of the first #GSList.
index 4957d02..d3feaec 100644 (file)
@@ -96,6 +96,7 @@ manages all available sources of events.
       <graphic fileref="mainloop-states.gif" format="gif"></graphic>
     </figure>
   </refsect2>
+
 <!-- ##### SECTION See_Also ##### -->
 <para>
 
@@ -108,50 +109,7 @@ of a GLib or GTK+ application.
 </para>
 
 
-<!-- ##### FUNCTION g_main_loop_new ##### -->
-<para>
-
-</para>
-
-@context: 
-@is_running: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_loop_destroy ##### -->
-<para>
-
-</para>
-
-@loop: 
-
-
-<!-- ##### FUNCTION g_main_loop_run ##### -->
-<para>
-
-</para>
-
-@loop: 
-
-
-<!-- ##### FUNCTION g_main_loop_quit ##### -->
-<para>
-
-</para>
-
-@loop: 
-
-
-<!-- ##### FUNCTION g_main_loop_is_running ##### -->
-<para>
-
-</para>
-
-@loop: 
-@Returns: 
-
-
-<!-- ##### MACRO g_main_new ##### -->
+<!-- ##### FUNCTION g_main_new ##### -->
 <para>
 Creates a new #GMainLoop for the default main loop. A compatibility
 macro, see g_main_loop_new().
@@ -162,7 +120,7 @@ very important since calling g_main_run() will set this to TRUE anyway.
 @Returns: a new #GMainLoop.
 
 
-<!-- ##### MACRO g_main_destroy ##### -->
+<!-- ##### FUNCTION g_main_destroy ##### -->
 <para>
 Frees the memory allocated for the #GMainLoop. A compatibility macro, see
 g_main_loop_destroy().
@@ -171,7 +129,7 @@ g_main_loop_destroy().
 @loop: a #GMainLoop.
 
 
-<!-- ##### MACRO g_main_run ##### -->
+<!-- ##### FUNCTION g_main_run ##### -->
 <para>
 Runs a main loop until it stops running. A compatibility macro, see g_main_loop_run().
 </para>
@@ -179,7 +137,7 @@ Runs a main loop until it stops running. A compatibility macro, see g_main_loop_
 @loop: a #GMainLoop.
 
 
-<!-- ##### MACRO g_main_quit ##### -->
+<!-- ##### FUNCTION g_main_quit ##### -->
 <para>
 Stops the #GMainLoop. If g_main_run() was called to run the #GMainLoop,
 it will now return. A compatibility macro, see g_main_loop_quit().
@@ -188,7 +146,7 @@ it will now return. A compatibility macro, see g_main_loop_quit().
 @loop: a #GMainLoop.
 
 
-<!-- ##### MACRO g_main_is_running ##### -->
+<!-- ##### FUNCTION g_main_is_running ##### -->
 <para>
 Checks if the main loop is running. A compatibility macro, see
 g_main_loop_is_running().    
@@ -243,40 +201,7 @@ It is not used within GLib or GTK+.
 
 
 
-<!-- ##### STRUCT GMainContext ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### FUNCTION g_main_context_get ##### -->
-<para>
-
-</para>
-
-@thread: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_default ##### -->
-<para>
-
-</para>
-
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_iteration ##### -->
-<para>
-
-</para>
-
-@context: 
-@may_block: 
-@Returns: 
-
-
-<!-- ##### MACRO g_main_iteration ##### -->
+<!-- ##### FUNCTION g_main_iteration ##### -->
 <para>
 Runs a single iteration for the default #GMainContext.
 A compatibility macro, see g_main_context_iteration().
@@ -289,16 +214,7 @@ processed.
 @Returns: TRUE if more events are pending.
 
 
-<!-- ##### FUNCTION g_main_context_pending ##### -->
-<para>
-
-</para>
-
-@context: 
-@Returns: 
-
-
-<!-- ##### MACRO g_main_pending ##### -->
+<!-- ##### FUNCTION g_main_pending ##### -->
 <para>
 Checks if any events are pending for the default #GMainContext
 (i.e. ready to be processed).  A compatibility macro, see
@@ -308,100 +224,6 @@ g_main_context_pending().
 @Returns: %TRUE if any events are pending.
 
 
-<!-- ##### FUNCTION g_main_context_find_source_by_id ##### -->
-<para>
-
-</para>
-
-@context: 
-@id: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_find_source_by_user_data ##### -->
-<para>
-
-</para>
-
-@context: 
-@user_data: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_find_source_by_funcs_user_data ##### -->
-<para>
-
-</para>
-
-@context: 
-@funcs: 
-@user_data: 
-@Returns: 
-<!-- # Unused Parameters # -->
-@source_data: 
-
-
-<!-- ##### FUNCTION g_main_context_prepare ##### -->
-<para>
-
-</para>
-
-@context: 
-@priority: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_query ##### -->
-<para>
-
-</para>
-
-@context: 
-@max_priority: 
-@timeout: 
-@fds: 
-@n_fds: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_check ##### -->
-<para>
-
-</para>
-
-@context: 
-@max_priority: 
-@fds: 
-@n_fds: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_main_context_dispatch ##### -->
-<para>
-
-</para>
-
-@context: 
-
-
-<!-- ##### FUNCTION g_main_context_set_poll_func ##### -->
-<para>
-
-</para>
-
-@context: 
-@func: 
-
-
-<!-- ##### FUNCTION g_main_context_get_poll_func ##### -->
-<para>
-
-</para>
-
-@context: 
-@Returns: 
-
-
 <!-- ##### USER_FUNCTION GPollFunc ##### -->
 <para>
 Specifies the type of function passed to g_main_set_poll_func().
@@ -417,26 +239,7 @@ The semantics of the function should match those of the
 or -1 if an error occurred.
 
 
-<!-- ##### FUNCTION g_main_context_add_poll ##### -->
-<para>
-
-</para>
-
-@context: 
-@fd: 
-@priority: 
-
-
-<!-- ##### FUNCTION g_main_context_remove_poll ##### -->
-<para>
-
-</para>
-
-@context: 
-@fd: 
-
-
-<!-- ##### MACRO g_main_set_poll_func ##### -->
+<!-- ##### FUNCTION g_main_set_poll_func ##### -->
 <para>
 Sets the function to use for the handle polling of file descriptors
 for the default main context. This is a compatability macro, see
@@ -446,42 +249,25 @@ g_main_context_set_poll_func() for full details.
 @func: the function to call to poll all file descriptors.
 
 
-<!-- ##### FUNCTION g_timeout_source_new ##### -->
+<!-- ##### FUNCTION g_timeout_add ##### -->
 <para>
-
 </para>
 
 @interval: 
+@function: 
+@data: 
 @Returns: 
 
 
-<!-- ##### FUNCTION g_timeout_add ##### -->
-<para>
-</para>
-  
-@interval:
-@function:
-@data:
-@Returns:
-
-
 <!-- ##### FUNCTION g_timeout_add_full ##### -->
 <para>
 </para>
 
-@priority:
+@priority: 
 @interval: 
-@function:
-@data:
-@notify:
-@Returns: 
-
-
-<!-- ##### FUNCTION g_idle_source_new ##### -->
-<para>
-
-</para>
-
+@function: 
+@data: 
+@notify: 
 @Returns: 
 
 
@@ -501,10 +287,10 @@ g_main_context_set_poll_func() for full details.
 @priority: 
 @function: 
 @data: 
-@notify: 
+@destroy: 
 @Returns: 
 <!-- # Unused Parameters # -->
-@destroy: 
+@notify: 
 
 
 <!-- ##### FUNCTION g_idle_remove_by_data ##### -->
@@ -550,12 +336,6 @@ poll() function to indicate which events occurred.
 @events: 
 @revents: 
 
-<!-- ##### STRUCT GSource ##### -->
-<para>
-
-</para>
-
-
 <!-- ##### STRUCT GSourceFuncs ##### -->
 <para>
 The #GSourceFuncs struct contains a table of functions used to handle
@@ -636,122 +416,20 @@ the required condition has been met, and returns TRUE if so.
 @dispatch: 
 @destroy: 
 
-<!-- ##### STRUCT GSourceCallbackFuncs ##### -->
-<para>
-
-</para>
-
-@ref: 
-@unref: 
-@get: 
-
-<!-- ##### FUNCTION g_source_new ##### -->
-<para>
-
-</para>
-
-@source_funcs: 
-@struct_size: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_source_ref ##### -->
-<para>
-
-</para>
-
-@source: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_source_unref ##### -->
-<para>
-
-</para>
-
-@source: 
-
-
 <!-- ##### FUNCTION g_source_add ##### -->
 <para>
 </para>
 
-@source: 
-@context: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_source_destroy ##### -->
-<para>
-
-</para>
-
-@source: 
-
-
-<!-- ##### FUNCTION g_source_set_priority ##### -->
-<para>
-
-</para>
-
-@source: 
 @priority: 
-
-
-<!-- ##### FUNCTION g_source_get_priority ##### -->
-<para>
-
-</para>
-
-@source: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_source_set_can_recurse ##### -->
-<para>
-
-</para>
-
-@source: 
 @can_recurse: 
-
-
-<!-- ##### FUNCTION g_source_get_can_recurse ##### -->
-<para>
-
-</para>
-
-@source: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_source_get_id ##### -->
-<para>
-
-</para>
-
-@source: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_source_get_context ##### -->
-<para>
-
-</para>
-
-@source: 
+@funcs: 
+@source_data: 
+@user_data: 
+@notify: 
 @Returns: 
-
-
-<!-- ##### FUNCTION g_source_connect ##### -->
-<para>
-
-</para>
-
+<!-- # Unused Parameters # -->
 @source: 
-@func: 
-@data: 
-@notify: 
+@context: 
 
 
 <!-- ##### USER_FUNCTION GSourceFunc ##### -->
@@ -765,43 +443,6 @@ of the above functions.
 @Returns: it should return FALSE if the source should be removed.
 
 
-<!-- ##### FUNCTION g_source_connect_indirect ##### -->
-<para>
-
-</para>
-
-@source: 
-@callback_data: 
-@callback_funcs: 
-
-
-<!-- ##### FUNCTION g_source_add_poll ##### -->
-<para>
-
-</para>
-
-@source: 
-@fd: 
-
-
-<!-- ##### FUNCTION g_source_remove_poll ##### -->
-<para>
-
-</para>
-
-@source: 
-@fd: 
-
-
-<!-- ##### FUNCTION g_source_get_current_time ##### -->
-<para>
-
-</para>
-
-@source: 
-@timeval: 
-
-
 <!-- ##### FUNCTION g_source_remove ##### -->
 <para>
 </para>
index 69680e3..9c064e3 100644 (file)
@@ -87,118 +87,3 @@ Character references
 
 </para>
 
-<!-- ##### ENUM GMarkupError ##### -->
-<para>
-
-</para>
-
-@G_MARKUP_ERROR_BAD_UTF8: text being parsed was not valid UTF-8
-@G_MARKUP_ERROR_EMPTY: document contained nothing, or only whitespace
-@G_MARKUP_ERROR_PARSE: document was ill-formed
-@G_MARKUP_ERROR_UNKNOWN_ELEMENT: error should be set by #GMarkupParser functions; element wasn't known
-@G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE: error should be set by #GMarkupParser functions; attribute wasn't known
-@G_MARKUP_ERROR_INVALID_CONTENT: error should be set by #GMarkupParser functions; something was wrong with contents of the document, e.g. invalid attribute value
-
-<!-- ##### MACRO G_MARKUP_ERROR ##### -->
-<para>
-
-</para>
-
-
-
-<!-- ##### ENUM GMarkupParseFlags ##### -->
-<para>
-There are no flags right now
-</para>
-
-@G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG: 
-
-<!-- ##### STRUCT GMarkupParseContext ##### -->
-<para>
-
-</para>
-
-
-<!-- ##### STRUCT GMarkupParser ##### -->
-<para>
-Any of the fields in #GMarkupParser can be %NULL, in which case they
-will be ignored. Except for the @error function, any of these
-callbacks can set an error; in particular the
-%G_MARKUP_ERROR_UNKNOWN_ELEMENT, %G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
-and %G_MARKUP_ERROR_INVALID_CONTENT errors are intended to be set 
-from these callbacks. If you set an error from a callback,
-g_markup_parse_context_parse() will report that error back to its caller.
-</para>
-
-@start_element: Callback to invoke when the opening tag of an element
-is seen.
-@end_element: Callback to invoke when the closing tag of an element is seen
-@text: Callback to invoke when some text is seen (text is always
-inside an element)
-@passthrough: Callback to invoke for comments and processing
-instructions; if you're re-writing the parsed document, write the
-passthrough text back out in the same position
-@error: Callback to invoke when an error occurs
-
-<!-- ##### FUNCTION g_markup_escape_text ##### -->
-<para>
-
-</para>
-
-@text: 
-@length: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_markup_parse_context_end_parse ##### -->
-<para>
-
-</para>
-
-@context: 
-@error: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_markup_parse_context_free ##### -->
-<para>
-
-</para>
-
-@context: 
-
-
-<!-- ##### FUNCTION g_markup_parse_context_get_position ##### -->
-<para>
-
-</para>
-
-@context: 
-@line_number: 
-@char_number: 
-
-
-<!-- ##### FUNCTION g_markup_parse_context_new ##### -->
-<para>
-
-</para>
-
-@parser: 
-@flags: 
-@user_data: 
-@user_data_dnotify: 
-@Returns: 
-
-
-<!-- ##### FUNCTION g_markup_parse_context_parse ##### -->
-<para>
-
-</para>
-
-@context: 
-@text: 
-@text_len: 
-@error: 
-@Returns: 
-
-
index 5e83181..d6bc525 100644 (file)
@@ -83,9 +83,9 @@ Note that this must be called before any records are added to the #GRelation.
 @relation: a #GRelation.
 @field: the field to index, counting from 0.
 @hash_func: a function to produce a hash value from the field data.
-@key_equal_func: a function to compare two values of the given field.
-<!-- # Unused Parameters # -->
 @key_compare_func: 
+<!-- # Unused Parameters # -->
+@key_equal_func: a function to compare two values of the given field.
 
 
 <!-- ##### FUNCTION g_relation_insert ##### -->
index 9e8dcdd..4774574 100644 (file)
@@ -36,13 +36,13 @@ Shell-related Utilities
 </para>
 
 @command_line: 
-@argcp
-@argvp
+@argc: 
+@argv: 
 @error: 
 @Returns: 
 <!-- # Unused Parameters # -->
-@argc: 
-@argv: 
+@argcp
+@argvp
 
 
 <!-- ##### FUNCTION g_shell_quote ##### -->
index 23bfc3b..fd4408b 100644 (file)
@@ -45,16 +45,6 @@ Creates a new #GString, initialized with the given string.
 @Returns: the new #GString.
 
 
-<!-- ##### FUNCTION g_string_new_len ##### -->
-<para>
-
-</para>
-
-@init: 
-@len: 
-@Returns: 
-
-
 <!-- ##### FUNCTION g_string_sized_new ##### -->
 <para>
 Creates a new GString, with enough space for @dfl_size characters.
index 11ab995..104c66a 100644 (file)
@@ -61,16 +61,6 @@ second.
 @Returns: a new #GTree.
 
 
-<!-- ##### FUNCTION g_tree_new_with_data ##### -->
-<para>
-
-</para>
-
-@key_compare_func: 
-@user_data: 
-@Returns: 
-
-
 <!-- ##### FUNCTION g_tree_insert ##### -->
 <para>
 Inserts a key/value pair into a #GTree.
index fde2b44..45ec974 100644 (file)
@@ -1,3 +1,82 @@
+Mon Dec 11 04:44:11 2000  Tim Janik  <timj@gtk.org>
+
+       * gboxed.c: fixed dealing with collection/lcopy of NULL values.
+       
+       * gclosure.h: removed insane ramblings, added G_CALLBACK() a casting
+       convenience macro.
+       
+       * Makefile.am: cleanups, marshaller generation rules.
+       
+       * gmarshal.[hc]: new files with GRuntime standard marshallers.
+       
+       * glib-genmarshal.c: fix log domain, support gruntime standard 
+       marshallers, suport G_TYPE_PARAM, come with extern "C" and
+       #include gmarshal.h.
+       
+       * glib-genmarshal.1: reflect glib-genmarshal.c updates.
+       
+       * gobject.[hc]: implement object constructor. rework parameter
+       changed notification queueing, we support queue freezes now and
+       don't dispatch from an idle handler anymore.
+       parameter->property rename hassle.
+       implemented ::properties_changed and ::notify::* signals for
+       property change notification (the later supports property names
+       as details). added signal connection and named data properties.
+       (g_signal_connect_object): new function to setup while_alive
+       connections.
+       (g_object_class_install_property): sink properties now, since they
+       are initially floating.
+       (g_object_steal_data):
+       (g_object_set_data_full):
+       (g_object_set_data):
+       (g_object_get_data): set/get data by using g_datalist_*() functions
+       directly.
+       (g_object_queue_param_changed): nuked.
+       (g_object_freeze_notify): start queueing of property changes (freeze/
+       thaw calls stack).
+       (g_object_notify): announce changes of a certain property directly.
+       (g_object_thaw_notify): process queue of property changes, therefore
+       emitting GObject::notify::detail with detail being the changed
+       properties names.
+       (G_OBJECT_WARN_INVALID_PROPERTY_ID): saner macro variant of former
+       G_WARN_INVALID_PARAM_ID().
+       
+       * gparam.[hc]: param specs are now initially floating and need to be
+       sunken with g_param_spec_sink(), support G_TYPE_PARAM values.
+       added G_PARAM_CONSTRUCT and G_PARAM_CONSTRUCT_ONLY parameter flags,
+       required by GObjectClass.constructor().
+       
+       * gparamspecs.[hc]: added GParamSpecParam, GParamSpecPointer and
+       GParamSpecCCallback, param specs for G_TYPE_PARAM, G_TYPE_POINTER
+       and G_TYPE_CCALLBACK respectively.
+       
+       * gsignal.[hc]: cleanups.
+       (signal_id_lookup): after walking the anchestry, try interfaces as well.
+       (g_signal_new): new function to create signals from varargs type list.
+       (g_signal_connect_closure): closure connection variant that works from
+       signal name+detail.
+       (g_signal_connect_data): c handler connection variant that works from
+       signal name+detail.
+       (g_signal_emit_valist): emit signal for an instance with paraneters
+       collected from a va_list.
+       (g_signal_emit): emit signal, taking parameters from varargs list.
+       (g_signal_emit_by_name): same as g_signal_emit, working from
+       signal name+detail.
+       (signal_emit_R): return whether return_value needs to be altered.
+       
+       * gtype.[hc]: set log-domain to GRuntime, i'm slowly getting to all
+       the points that need to reflect the upcoming rename.
+       melt g_type_conforms_to() functionality into g_type_is_a(), as that
+       is what we really want (liskov substitution principle).
+       assorted changes to other files due to conforms_to->is_a.
+
+       * gvalue.[hc]: implemented g_value_set_instance() that sets a value
+       from an instantiatable type via the value_table's collect_value()
+       function (based on an idea from James Henstridge <james@daa.com.au>).
+       cleanups/fixes.
+       
+       * gvaluetypes.[hc]: implement G_TYPE_CCALLBACK and G_TYPE_PARAM.
+
 Wed Nov 29 13:30:05 2000  Tim Janik  <timj@gtk.org>
 
        * gsignal.c (handlers_find): fix elliots "logic fix" that dereferences
index 6296bce..0c37fdf 100644 (file)
-# GObject - GLib Type, Object, Parameter and Signal Library
+# GRuntime - GLib Type, Object, Parameter and Signal Library
 # Copyright (C) 1997,98,99,2000 Tim Janik and Red Hat, Inc.
 #
 ## Process this file with automake to produce Makefile.in
 
-INCLUDES = -I$(top_srcdir) -I$(top_builddir) @GLIB_DEBUG_FLAGS@
+INCLUDES = @STRIP_BEGIN@ \
+       -DG_LOG_DOMAIN=g_log_domain_gruntime    \
+       -I$(top_srcdir)                         \
+       -I$(top_builddir)                       \
+       @GLIB_DEBUG_FLAGS@                      \
+@STRIP_END@
 
 # libraries to compile and install
 lib_LTLIBRARIES = libgobject-1.3.la
 
-# provide g_logv() domain
-AM_CFLAGS = -DG_LOG_DOMAIN=g_log_domain_gobject
-
 # libtool stuff: set version and export symbols for resolving
 libgobjectincludedir = $(includedir)/glib-2.0/gobject
-libgobject_1_3_la_LDFLAGS = \
-       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
-       -export-dynamic
+libgobject_1_3_la_LDFLAGS = @STRIP_BEGIN@ \
+       -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)    \
+       -export-dynamic                                         \
+@STRIP_END@
 libgobject_1_3_la_LIBADD = # $(libglib)
 
 #
 # setup source file variables
 #
-# GObject header files for public installation (non-generated)
-gobject_public_h_sources = @STRIP_BEGIN@ \
-       gboxed.h \
-       gbsearcharray.h \
-       gclosure.h \
-       genums.h \
-       gobject.h \
-       gparam.h \
-       gparamspecs.h \
-       gsignal.h \
-       gtype.h \
-       gtypemodule.h \
-       gtypeplugin.h \
-       gvalue.h \
-       gvaluecollector.h \
-       gvaluetypes.h \
+# GRuntime header files for public installation (non-generated)
+gruntime_public_h_sources = @STRIP_BEGIN@ \
+       gboxed.h                \
+       gbsearcharray.h         \
+       gclosure.h              \
+       genums.h                \
+       gobject.h               \
+       gparam.h                \
+       gparamspecs.h           \
+       gsignal.h               \
+       gtype.h                 \
+       gtypemodule.h           \
+       gtypeplugin.h           \
+       gvalue.h                \
+       gvaluecollector.h       \
+       gvaluetypes.h           \
 @STRIP_END@
-
-# private GObject header files
-gobject_private_h_sources = 
-
-# GObject C sources to build the library from
-gobject_c_sources = @STRIP_BEGIN@ \
-       gboxed.c \
-       gbsearcharray.c \
-       gclosure.c \
-       genums.c \
-       gobject.c \
-       gparam.c \
-       gparamspecs.c \
-       gsignal.c \
-       gtype.c \
-       gtypemodule.c \
-       gtypeplugin.c \
-       gvalue.c \
-       gvaluetypes.c \
+# GRuntime header files that don't get installed
+gruntime_private_h_sources = 
+# GRuntime C sources to build the library from
+gruntime_c_sources = @STRIP_BEGIN@ \
+       gboxed.c                \
+       gbsearcharray.c         \
+       gclosure.c              \
+       genums.c                \
+       gobject.c               \
+       gparam.c                \
+       gparamspecs.c           \
+       gsignal.c               \
+       gtype.c                 \
+       gtypemodule.c           \
+       gtypeplugin.c           \
+       gvalue.c                \
+       gvaluetypes.c           \
 @STRIP_END@
 
+# we use our own built_sources variable rules to avoid automake's
+# BUILT_SOURCES oddities
+# we generate frequently rebuild files piggyback on a stamp file, so sources
+# depending on them only get rebuild when the built source actually changed
+# content
+
+# built sources that get installed with the header files
+gruntime_built_public_sources = @STRIP_BEGIN@ \
+       gmarshal.h      \
+@STRIP_END@
+# built sources that don't get installed
+gruntime_built_sources = @STRIP_BEGIN@ \
+       stamp-gmarshal.h                 \
+       gmarshal.c                       \
+       ${gruntime_built_public_sources} \
+@STRIP_END@
 # non-header sources (headers should be specified in the above variables)
 # that don't serve as direct make target sources, i.e. they don't have
 # their own .lo rules and don't get publically installed
-gobject_extra_sources = 
+gruntime_extra_sources = @STRIP_BEGIN@ \
+       gmarshal.list           \
+       gmarshal.strings        \
+@STRIP_END@
+
 
 #
-# setup GObject sources and their dependancies
+# setup GRuntime sources and their dependancies
 #
-gobject_h_sources = $(gobject_private_h_sources) $(gobject_public_h_sources) # $(gobject_built_public_sources)
-libgobjectinclude_HEADERS = $(gobject_public_h_sources) # $(gobject_built_public_sources)
-libgobject_1_3_la_SOURCES = $(gobject_c_sources)
-MAINTAINERCLEANFILES += 
-# $(gobject_built_public_sources) $(gobject_built_sources)
+gruntime_target_headers = $(gruntime_public_h_sources) $(gruntime_built_public_sources)
+gruntime_target_sources = $(gruntime_c_sources)
+MAINTAINERCLEANFILES += $(gruntime_built_sources)
 EXTRA_HEADERS +=
-EXTRA_DIST += $(gobject_private_h_sources)
-EXTRA_DIST += $(gobject_extra_sources) 
-# $(gobject_built_sources) $(gobject_built_public_sources)
+EXTRA_DIST += $(gruntime_private_h_sources) $(gruntime_extra_sources)
+EXTRA_DIST += $(gruntime_built_sources)
+
+#
+# rules to generate built sources
+#
+# setup autogeneration dependancies
+gen_sources = xgen-gmh xgen-gmc xgen-gms
+CLEANFILES += $(gen_sources)
+Makefile: oldest-source-stamp  # oh boy, does automake SUCK!
+oldest-source-stamp: $(gruntime_built_sources)
+$(OBJECTS): oldest-source-stamp  ${gruntime_built_public_sources} # this is our oldest file, used for implicit auto-generation deps
+# initial creation of the real stamp-* files
+gmarshal.h:    # never add deps here
+       test -f "$(srcdir)/$@" || touch $(srcdir)/$@
+# normal autogeneration rules
+# all autogenerated files need to be generated in the srcdir,
+# so old versions get remade and are not confused with newer
+# versions in the build dir. thus a development setup requires
+# srcdir to be writable, passing --disable-rebuilds to
+# ../configure will supress all autogeneration rules.
+$(srcdir)/stamp-gmarshal.h: @REBUILD@ gmarshal.list gmarshal.h glib-genmarshal
+       cd $(srcdir) \
+       && echo "#ifndef __G_MARSHAL_H__" > xgen-gmh \
+       && echo "#define __G_MARSHAL_H__" >> xgen-gmh \
+       && ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal gmarshal.list --header >> xgen-gmh \
+       && echo "#endif /* __G_MARSHAL_H__ */" >> xgen-gmh \
+       && (cmp -s xgen-gmh gmarshal.h || cp xgen-gmh gmarshal.h) \
+       && rm -f xgen-gmh xgen-gmh~ \
+       && echo timestamp > $(@F)
+$(srcdir)/gmarshal.c: @REBUILD@ $(srcdir)/stamp-gmarshal.h
+       cd $(srcdir) \
+       && ./glib-genmarshal --nostdinc --prefix=g_cclosure_marshal gmarshal.list --body >> xgen-gmc \
+       && cp xgen-gmc gmarshal.c \
+       && rm -f xgen-gmc xgen-gmc~
+$(srcdir)/gmarshal.strings: @REBUILD@ $(srcdir)/gmarshal.list
+       cd $(srcdir) \
+       && grep '^[A-Z]' $(srcdir)/gmarshal.list \
+       | sed -e 's/^/"g_cclosure_marshal_/' -e 's/:/__/' -e 's/,/_/g' -e 's/$$/",/' > xgen-gms \
+       && cp xgen-gms gmarshal.strings \
+       && rm -f xgen-gms xgen-gms~
+glib-genmarshal.o: gmarshal.strings
+
+
+# target platform:
+libgobjectinclude_HEADERS = $(gruntime_target_headers)
+libgobject_1_3_la_SOURCES = $(gruntime_target_sources)
 
 #
 # programs to compile and install
@@ -86,8 +149,8 @@ gobject_query_SOURCES = gobject-query.c
 glib_genmarshal_SOURCES = glib-genmarshal.c
 # link programs against libgobject
 progs_LDADD = ../libglib-1.3.la libgobject-1.3.la
+glib_genmarshal_LDADD = ../libglib-1.3.la # can't have libgobject here
 gobject_query_LDADD = $(progs_LDADD)
-glib_genmarshal_LDADD = $(progs_LDADD)
 
 #
 # manual pages to install
@@ -123,4 +186,3 @@ dist-hook: $(BUILT_EXTRA_DIST)
        for f in $$files; do \
          if test -f $$f; then d=.; else d=$(srcdir); fi; \
          cp $$d/$$f $(distdir) || exit 1; done
-
index d9d00af..c3d90de 100644 (file)
@@ -127,7 +127,7 @@ boxed_proxy_collect_value (GValue      *value,
 
   key.type = value->g_type;
   node = g_bsearch_array_lookup (&boxed_bsa, &key);
-  value->data[0].v_pointer = node->copy (collect_value->v_pointer);
+  value->data[0].v_pointer = collect_value->v_pointer ? node->copy (collect_value->v_pointer) : NULL;
 
   *collect_type = 0;
   return NULL;
@@ -147,7 +147,7 @@ boxed_proxy_lcopy_value (const GValue *value,
 
   key.type = value->g_type;
   node = g_bsearch_array_lookup (&boxed_bsa, &key);
-  *boxed_p = node->copy (value->data[0].v_pointer);
+  *boxed_p = value->data[0].v_pointer ? node->copy (value->data[0].v_pointer) : NULL;
 
   *collect_type = 0;
   return NULL;
index d1844f7..258861d 100644 (file)
@@ -524,8 +524,8 @@ g_type_iface_meta_marshal (GClosure       *closure,
 }
 
 GClosure*
-g_signal_type_closure_new (GType    itype,
-                          guint    struct_offset)
+g_signal_type_cclosure_new (GType    itype,
+                           guint    struct_offset)
 {
   GClosure *closure;
   
index 4720fda..c3ff793 100644 (file)
@@ -32,6 +32,7 @@ extern "C" {
 /* --- defines --- */
 #define        G_CLOSURE_NEEDS_MARSHAL(closure) (((GClosure*) (closure))->marshal == NULL)
 #define        G_CCLOSURE_SWAP_DATA(cclosure)   (((GClosure*) (closure))->derivative_flag)
+#define        G_CALLBACK(f)                    ((GCallback) (f))
 
 
 /* -- typedefs --- */
@@ -105,7 +106,7 @@ GClosure*   g_cclosure_new                  (GCallback      callback_func,
 GClosure*      g_cclosure_new_swap             (GCallback      callback_func,
                                                 gpointer       user_data,
                                                 GClosureNotify destroy_data);
-GClosure*      g_signal_type_closure_new       (GType          itype,
+GClosure*      g_signal_type_cclosure_new      (GType          itype,
                                                 guint          struct_offset);
 
 
@@ -146,35 +147,14 @@ void              g_closure_invoke                (GClosure       *closure,
 
 
 /* FIXME:
-  data_object::destroy         -> closure_invalidate();
-  closure_invalidate()         -> disconnect(closure);
-  disconnect(closure)          -> (unlink) closure_unref();
-  closure_finalize()           -> g_free (data_string);
-  
-  1) need GObject and GType in glib
-  2) need GParam
-  3) need to resolve dtor cycles
-  4) need GSignal move
-  5) destroy on last caller ref or last data ref?
-  
-  
-  random remarks:
-  - don't mandate signals for GObject
-  - OTOH, don't mandate GObject for GSignal
-  - need marshaller repo with decent aliasing to base types
-  - provide marshaller collection, virtually covering anything out there
-  - at that point, still need GSignalCMarhsaller to g_signal_new() ?
-  - can we combine varargs collect mechanisms with marshaller stubs?
-  for out values (i.e. returntypes), that might get rid of the following
-  point...
-  - char* return signals with connections ala:
-  connect({ return "static data that can't work"; }),
-  connect({ return g_strdup ("properly duplicated string"); })
-  won't work anymore. CRASH
-
-  problems:
-  - accumulator needs gboolean to indicate EMISSION_STOP
-  - accumulator needs data
+   OK:  data_object::destroy           -> closure_invalidate();
+   MIS:        closure_invalidate()            -> disconnect(closure);
+   MIS:        disconnect(closure)             -> (unlink) closure_unref();
+   OK: closure_finalize()              -> g_free (data_string);
+
+   random remarks:
+   - need marshaller repo with decent aliasing to base types
+   - provide marshaller collection, virtually covering anything out there
 */
 
 
index d68ff6b..687b020 100644 (file)
@@ -35,6 +35,10 @@ Specify marshaller prefix. The default prefix is `\fIg_cclosure_marshal\fP'.
 \fI--skip-source
 Skip source location remarks in generated comments.
 .TP
+\fI--nostdinc
+Do not use the standard GRuntime marshallers, and skip gmarshal.h include
+directive in generated header files.
+.TP
 \fI--g-fatal-warnings
 Make warnings fatal, that is, exit immediately once a warning occours.
 .TP
@@ -118,6 +122,8 @@ for string types (gchar*)
 \fIBOXED
 for boxed (anonymous but reference counted) types (GBoxed*)
 .TP 12
+\fIPARAM
+for GParamSpec or derived types (GParamSpec*)
 \fIPOINTER
 for anonymous pointer types (gpointer)
 .TP 12
index 0c3214a..f1b4c3b 100644 (file)
  */
 #include       "config.h"
 
-#include       <glib-object.h>
+
+/* ok, this is a bit hackish, have to provide gruntime log domain as
+ * we don't link against -lgruntime
+ */
+char *g_log_domain_gruntime = "GLib-Genmarshal";
+
+#include       <glib.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
@@ -108,11 +114,13 @@ static GScannerConfig scanner_config_template =
   FALSE                 /* symbol_2_token */,
   FALSE                 /* scope_0_fallback */,
 };
-static gchar           *marshaller_prefix = "g_cclosure_marshal";
+static gchar           *std_marshaller_prefix = "g_cclosure_marshal";
+static gchar           *marshaller_prefix = "g_cclosure_user_marshal";
 static GHashTable      *marshallers = NULL;
 static gboolean                 gen_cheader = FALSE;
 static gboolean                 gen_cbody = FALSE;
 static gboolean                 skip_ploc = FALSE;
+static gboolean                 std_includes = TRUE;
 
 
 /* --- functions --- */
@@ -142,12 +150,14 @@ complete_arg (Argument *arg,
     { "STRING",                "POINTER",      "as_pointer",           "gpointer",     },
     { "BOXED",         "POINTER",      "as_pointer",           "gpointer",     },
     { "POINTER",       "POINTER",      "as_pointer",           "gpointer",     },
+    { "PARAM",         "POINTER",      "as_pointer",           "gpointer",     },
     { "OBJECT",                "POINTER",      "as_pointer",           "gpointer",     },
   };
   static const Argument out_arguments[] = {
     { "STRING",                "STRING",       "string",               "gchar*",       },
     { "BOXED",         "BOXED",        "boxed",                "gpointer",     },
     { "POINTER",       "POINTER",      "pointer",              "gpointer",     },
+    { "PARAM",         "PARAM",        "param",                "GParamSpec*",  },
     { "OBJECT",                "OBJECT",       "object",               "GObject*",     },
   };
   const guint n_inout_arguments = sizeof (inout_arguments) / sizeof (inout_arguments[0]);
@@ -201,7 +211,7 @@ pad (const gchar *string)
     {
       g_free (buffer);
       buffer = g_strdup_printf ("%s ", string);
-      g_warning ("overfull string (%lu bytes) for padspace", strlen (string));
+      g_warning ("overfull string (%u bytes) for padspace", (guint) strlen (string));
 
       return buffer;
     }
@@ -241,17 +251,39 @@ generate_marshal (const gchar *signame,
 {
   guint ind, a;
   GList *node;
+  gchar *tmp = g_strconcat (marshaller_prefix, "_", signame, NULL);
+  gboolean have_std_marshaller = FALSE;
 
-  if (g_hash_table_lookup (marshallers, signame))
-    return;
+  /* here we have to make sure a marshaller named <marshaller_prefix>_<signame>
+   * exists. we might have put it out already, can revert to a standard marshaller
+   * provided by glib, or need to generate one.
+   */
+
+  if (g_hash_table_lookup (marshallers, tmp))
+    {
+      /* done, marshaller already generated */
+      g_free (tmp);
+      return;
+    }
   else
     {
-      gchar *tmp = g_strdup (signame);
-
+      /* need to alias/generate marshaller, register name */
       g_hash_table_insert (marshallers, tmp, tmp);
     }
-  
-  if (gen_cheader)
+
+  /* can we revert to a standard marshaller? */
+  if (std_includes)
+    {
+      tmp = g_strconcat (std_marshaller_prefix, "_", signame, NULL);
+      have_std_marshaller = g_hash_table_lookup (marshallers, tmp) != NULL;
+      g_free (tmp);
+    }
+
+  if (gen_cheader && have_std_marshaller)
+    {
+      fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, signame, std_marshaller_prefix, signame);
+    }
+  if (gen_cheader && !have_std_marshaller)
     {
       ind = fprintf (fout, "extern void ");
       ind += fprintf (fout, "%s_%s (", marshaller_prefix, signame);
@@ -262,7 +294,7 @@ generate_marshal (const gchar *signame,
       fprintf (fout, "%sgpointer      invocation_hint,\n", indent (ind));
       fprintf (fout, "%sgpointer      marshal_data);\n", indent (ind));
     }
-  if (gen_cbody)
+  if (gen_cbody && !have_std_marshaller)
     {
       /* cfile marhsal header */
       fprintf (fout, "void\n");
@@ -352,7 +384,7 @@ generate_marshal (const gchar *signame,
 static void
 process_signature (Signature *sig)
 {
-  gchar *pname, *sname;
+  gchar *pname, *sname, *tmp;
   GList *node;
 
   /* lookup and complete info on arguments */
@@ -400,18 +432,19 @@ process_signature (Signature *sig)
     fprintf (fout, " (%s)", sig->ploc);
   fprintf (fout, " */\n");
 
-  /* generate signature marshaller */
+  /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
   generate_marshal (sname, sig);
 
-  /* put out marshaler alias if required */
-  if (gen_cheader && !g_hash_table_lookup (marshallers, pname))
+  /* put out marshaller alias for requested name if required (<marshaller_prefix>_<pname>) */
+  tmp = g_strconcat (marshaller_prefix, "_", pname, NULL);
+  if (gen_cheader && !g_hash_table_lookup (marshallers, tmp))
     {
-      gchar *tmp = g_strdup (pname);
-
       fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, pname, marshaller_prefix, sname);
 
       g_hash_table_insert (marshallers, tmp, tmp);
     }
+  else
+    g_free (tmp);
 
   g_free (pname);
   g_free (sname);
@@ -482,6 +515,9 @@ int
 main (int   argc,
       char *argv[])
 {
+  const gchar *gruntime_marshallers[] = {
+#include       "gmarshal.strings"
+  };
   GScanner *scanner;
   GSList *slist, *files = NULL;
   gint i;
@@ -502,6 +538,24 @@ main (int   argc,
   fout = stdout;
   marshallers = g_hash_table_new (g_str_hash, g_str_equal);
 
+  /* add GRuntime standard marshallers */
+  if (std_includes)
+    for (i = 0; i < sizeof (gruntime_marshallers) / sizeof (gruntime_marshallers[0]); i++)
+      {
+       gchar *tmp = g_strdup (gruntime_marshallers[i]);
+       
+       g_hash_table_insert (marshallers, tmp, tmp);
+      }
+
+  /* put out initial heading */
+  fprintf (fout, "\n");
+  if (gen_cheader)
+    {
+      if (std_includes)
+       fprintf (fout, "#include\t<gobject/gmarshal.h>\n\n");
+      fprintf (fout, "#ifdef __cplusplus\nextern \"C\" {\n#endif /* __cplusplus */\n");
+    }
+
   /* process input files */
   for (slist = files; slist; slist = slist->next)
     {
@@ -579,6 +633,13 @@ main (int   argc,
       close (fd);
     }
 
+  /* put out trailer */
+  if (gen_cheader)
+    {
+      fprintf (fout, "\n#ifdef __cplusplus\n}\n#endif /* __cplusplus */\n");
+    }
+  fprintf (fout, "\n");
+
   /* clean up */
   g_slist_free (files);
   g_scanner_destroy (scanner);
@@ -613,6 +674,16 @@ parse_args (gint    *argc_p,
          skip_ploc = TRUE;
          argv[i] = NULL;
        }
+      else if (strcmp ("--nostdinc", argv[i]) == 0)
+       {
+         std_includes = FALSE;
+         argv[i] = NULL;
+       }
+      else if (strcmp ("--stdinc", argv[i]) == 0)
+       {
+         std_includes = TRUE;
+         argv[i] = NULL;
+       }
       else if ((strcmp ("--prefix", argv[i]) == 0) ||
               (strncmp ("--prefix=", argv[i], 9) == 0))
        {
@@ -690,12 +761,13 @@ print_blurb (FILE    *bout,
   else
     {
       fprintf (bout, "Usage: %s [options] [files...]\n", PRG_NAME);
-      fprintf (bout, "  --header                        generate C headers\n");
-      fprintf (bout, "  --body                          generate C code\n");
-      fprintf (bout, "  --prefix=string                 specify marshaller prefix\n");
-      fprintf (bout, "  --skip-source                   skip source location comments\n");
-      fprintf (bout, "  -h, --help                      show this help message\n");
-      fprintf (bout, "  -v, --version                   print version informations\n");
-      fprintf (bout, "  --g-fatal-warnings              make warnings fatal (abort)\n");
+      fprintf (bout, "  --header                   generate C headers\n");
+      fprintf (bout, "  --body                     generate C code\n");
+      fprintf (bout, "  --prefix=string            specify marshaller prefix\n");
+      fprintf (bout, "  --skip-source              skip source location comments\n");
+      fprintf (bout, "  --stdinc, --nostdinc       include/use GRuntime standard marshallers\n");
+      fprintf (bout, "  -h, --help                 show this help message\n");
+      fprintf (bout, "  -v, --version              print version informations\n");
+      fprintf (bout, "  --g-fatal-warnings         make warnings fatal (abort)\n");
     }
 }
index 8f94c18..f1be160 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-#include "gobject.h"
+#include       "gobject.h"
 
 
-#include "gvaluecollector.h"
-#include "gsignal.h"
-#include <string.h>
+#include       "gvaluecollector.h"
+#include       "gsignal.h"
+#include       "gparamspecs.h"
+#include       "gvaluetypes.h"
+#include       <string.h>
 
 
+#define        PREALLOC_CPARAMS        (8)
 #define        DEBUG_OBJECTS
 
 
 /* --- macros --- */
-#define PARAM_SPEC_PARAM_ID(pspec)     (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_param_id)))
+#define PARAM_SPEC_PARAM_ID(pspec)     (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_property_id)))
+
+
+/* --- signals --- */
+enum {
+  PROPERTIES_CHANGED,
+  NOTIFY,
+  LAST_SIGNAL
+};
+
+
+/* --- properties --- */
+enum {
+  PROP_NONE,
+  PROP_DATA,
+  PROP_SIGNAL,
+  PROP_SWAPPED_SIGNAL,
+  PROP_SIGNAL_AFTER,
+  PROP_SWAPPED_SIGNAL_AFTER
+};
+
+
+/* --- typedefs --- */
+typedef struct _NotifyQueue NotifyQueue;
 
 
 /* --- prototypes --- */
 static void    g_object_base_class_init                (GObjectClass   *class);
 static void    g_object_base_class_finalize            (GObjectClass   *class);
 static void    g_object_do_class_init                  (GObjectClass   *class);
-static void    g_object_do_init                        (GObject        *object);
-static void    g_object_do_queue_param_changed         (GObject        *object,
-                                                        GParamSpec     *pspec);
-static void    g_object_do_dispatch_param_changed      (GObject        *object,
-                                                        GParamSpec     *pspec);
+static void    g_object_init                           (GObject        *object);
+static GObject*        g_object_constructor                    (GType                  type,
+                                                        guint                  n_construct_properties,
+                                                        GObjectConstructParam *construct_params);
 static void    g_object_last_unref                     (GObject        *object);
-static void    g_object_do_shutdown                    (GObject        *object);
-static void    g_object_do_finalize                    (GObject        *object);
+static void    g_object_shutdown                       (GObject        *object);
+static void    g_object_finalize                       (GObject        *object);
+static void    g_object_do_set_property                (GObject        *object,
+                                                        guint           property_id,
+                                                        const GValue   *value,
+                                                        GParamSpec     *pspec,
+                                                        const gchar    *trailer);
+static void    g_object_do_get_property                (GObject        *object,
+                                                        guint           property_id,
+                                                        GValue         *value,
+                                                        GParamSpec     *pspec,
+                                                        const gchar    *trailer);
 static void    g_value_object_init                     (GValue         *value);
 static void    g_value_object_free_value               (GValue         *value);
 static void    g_value_object_copy_value               (const GValue   *src_value,
@@ -56,13 +91,46 @@ static gchar*       g_value_object_lcopy_value              (const GValue   *value,
                                                         guint           nth_value,
                                                         GType          *collect_type,
                                                         GTypeCValue    *collect_value);
+static void    g_object_dispatch_properties_changed    (GObject        *object,
+                                                        guint           n_pspecs,
+                                                        GParamSpec    **pspecs);
+static void    g_object_properties_changed             (GObject        *object,
+                                                        guint           n_pspecs,
+                                                        GParamSpec    **pspecs);
+static void    g_object_notify_property_changed        (GObject        *object,
+                                                        GParamSpec     *pspec);
+static inline NotifyQueue* object_freeze_notifies      (GObject        *object);
+static inline void        object_queue_property        (GObject        *object,
+                                                        GParamSpec     *pspec,
+                                                        NotifyQueue    *nqueue);
+static inline void        object_thaw_notifies         (GObject        *object,
+                                                        NotifyQueue    *nqueue);
+static inline void         object_get_property         (GObject        *object,
+                                                        GValue         *value,
+                                                        GParamSpec     *pspec,
+                                                        const gchar    *trailer);
+static inline void        object_set_property          (GObject        *object,
+                                                        GValue         *value,
+                                                        GParamSpec     *pspec,
+                                                        const gchar    *trailer,
+                                                        NotifyQueue    *nqueue);
+
+
+/* --- structures --- */
+struct _NotifyQueue
+{
+  GSList *pspecs;
+  guint   n_pspecs;
+  guint   freeze_count;
+};
 
 
 /* --- variables --- */
-static GQuark           quark_param_id = 0;
-static GQuark           quark_param_changed_queue = 0;
+static GQuark           quark_notify_queue = 0;
+static GQuark           quark_property_id = 0;
 static GQuark           quark_closure_array = 0;
-static GHashTable      *param_spec_hash_table = NULL;
+static GHashTable      *pspec_hash_table = NULL;
+static gulong           gobject_signals[LAST_SIGNAL] = { 0, };
 
 
 /* --- functions --- */
@@ -118,7 +186,7 @@ g_object_type_init (void)   /* sync with gtype.c */
     NULL       /* class_data */,
     sizeof (GObject),
     0          /* n_preallocs */,
-    (GInstanceInitFunc) g_object_do_init,
+    (GInstanceInitFunc) g_object_init,
     NULL,      /* value_table */
   };
   static const GTypeValueTable value_table = {
@@ -151,10 +219,10 @@ static void
 g_object_base_class_init (GObjectClass *class)
 {
   /* reset instance specific fields and methods that don't get inherited */
-  class->n_param_specs = 0;
-  class->param_specs = NULL;
-  class->get_param = NULL;
-  class->set_param = NULL;
+  class->n_property_specs = 0;
+  class->property_specs = NULL;
+  class->get_property = NULL;
+  class->set_property = NULL;
 }
 
 static void
@@ -166,95 +234,193 @@ g_object_base_class_finalize (GObjectClass *class)
 
   _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
   
-  for (i = 0; i < class->n_param_specs; i++)
+  for (i = 0; i < class->n_property_specs; i++)
     {
-      GParamSpec *pspec = class->param_specs[i];
+      GParamSpec *pspec = class->property_specs[i];
       
-      g_param_spec_hash_table_remove (param_spec_hash_table, pspec);
-      g_param_spec_set_qdata (pspec, quark_param_id, NULL);
+      g_param_spec_hash_table_remove (pspec_hash_table, pspec);
+      g_param_spec_set_qdata (pspec, quark_property_id, NULL);
       g_param_spec_unref (pspec);
     }
-  class->n_param_specs = 0;
-  g_free (class->param_specs);
-  class->param_specs = NULL;
+  class->n_property_specs = 0;
+  g_free (class->property_specs);
+  class->property_specs = NULL;
 }
 
 static void
 g_object_do_class_init (GObjectClass *class)
 {
-  quark_param_id = g_quark_from_static_string ("glib-object-param-id");
-  quark_param_changed_queue = g_quark_from_static_string ("glib-object-param-changed-queue");
+  quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
+  quark_property_id = g_quark_from_static_string ("GObject-property-id");
   quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
-  param_spec_hash_table = g_param_spec_hash_table_new ();
-  
-  class->queue_param_changed = g_object_do_queue_param_changed;
-  class->dispatch_param_changed = g_object_do_dispatch_param_changed;
-  class->shutdown = g_object_do_shutdown;
-  class->finalize = g_object_do_finalize;
+  pspec_hash_table = g_param_spec_hash_table_new ();
+  
+  class->constructor = g_object_constructor;
+  class->set_property = g_object_do_set_property;
+  class->get_property = g_object_do_get_property;
+  class->shutdown = g_object_shutdown;
+  class->finalize = g_object_finalize;
+  class->dispatch_properties_changed = g_object_dispatch_properties_changed;
+  class->properties_changed = g_object_properties_changed;
+  class->notify = g_object_notify_property_changed;
+
+  g_object_class_install_property (class,
+                                  PROP_DATA,
+                                  g_param_spec_pointer ("data", "Named Data",
+                                                        "Named anonymous pointers",
+                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
+  g_object_class_install_property (class,
+                                  PROP_SIGNAL,
+                                  g_param_spec_ccallback ("signal", "Signal Connection",
+                                                          "Signal connection consisting of a callback function "
+                                                          "and a data pointer",
+                                                          G_PARAM_WRITABLE));
+  g_object_class_install_property (class,
+                                  PROP_SWAPPED_SIGNAL,
+                                  g_param_spec_ccallback ("swapped_signal", "Swapped Signal Connection",
+                                                          "Signal connection consisting of a callback function "
+                                                          "and a data pointer",
+                                                          G_PARAM_WRITABLE));
+  g_object_class_install_property (class,
+                                  PROP_SIGNAL_AFTER,
+                                  g_param_spec_ccallback ("signal_after", "Signal After Connection",
+                                                          "Signal connection consisting of a callback function "
+                                                          "and a data pointer",
+                                                          G_PARAM_WRITABLE));
+  g_object_class_install_property (class,
+                                  PROP_SWAPPED_SIGNAL_AFTER,
+                                  g_param_spec_ccallback ("swapped_signal_after", "Swapped Signal After Connection",
+                                                          "Signal connection consisting of a callback function "
+                                                          "and a data pointer",
+                                                          G_PARAM_WRITABLE));
+  gobject_signals[PROPERTIES_CHANGED] =
+    g_signal_new ("properties_changed",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
+                 g_signal_type_cclosure_new (G_TYPE_FROM_CLASS (class),
+                                             G_STRUCT_OFFSET (GObjectClass, properties_changed)),
+                 NULL, /* accumulator */
+                 g_cclosure_marshal_VOID__UINT_POINTER,
+                 G_TYPE_NONE,
+                 2, G_TYPE_UINT, G_TYPE_POINTER);
+  gobject_signals[NOTIFY] =
+    g_signal_new ("notify",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
+                 g_signal_type_cclosure_new (G_TYPE_FROM_CLASS (class),
+                                             G_STRUCT_OFFSET (GObjectClass, notify)),
+                 NULL, /* accumulator */
+                 g_cclosure_marshal_VOID__PARAM,
+                 G_TYPE_NONE,
+                 1, G_TYPE_PARAM);
 }
 
 void
-g_object_class_install_param (GObjectClass *class,
-                             guint         param_id,
-                             GParamSpec   *pspec /* 1 ref_count taken over */)
+g_object_class_install_property (GObjectClass *class,
+                                guint         property_id,
+                                GParamSpec   *pspec)
 {
   guint i;
   
   g_return_if_fail (G_IS_OBJECT_CLASS (class));
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
   if (pspec->flags & G_PARAM_WRITABLE)
-    g_return_if_fail (class->set_param != NULL);
+    g_return_if_fail (class->set_property != NULL);
   if (pspec->flags & G_PARAM_READABLE)
-    g_return_if_fail (class->get_param != NULL);
-  g_return_if_fail (param_id > 0);
+    g_return_if_fail (class->get_property != NULL);
+  g_return_if_fail (property_id > 0);
   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
-  
+  if (pspec->flags & G_PARAM_CONSTRUCT)
+    g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
+  if (pspec->flags & (G_PARAM_CONSTRUCT || G_PARAM_CONSTRUCT_ONLY))
+    g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
+
   /* expensive paranoia checks ;( */
-  for (i = 0; i < class->n_param_specs; i++)
-    if (PARAM_SPEC_PARAM_ID (class->param_specs[i]) == param_id)
+  for (i = 0; i < class->n_property_specs; i++)
+    if (PARAM_SPEC_PARAM_ID (class->property_specs[i]) == property_id)
       {
-       g_warning (G_STRLOC ": class `%s' already contains a parameter `%s' with id %u, "
-                  "cannot install parameter `%s'",
+       g_warning (G_STRLOC ": class `%s' already contains a property `%s' with id %u, "
+                  "cannot install property `%s'",
                   G_OBJECT_CLASS_NAME (class),
-                  class->param_specs[i]->name,
-                  param_id,
+                  class->property_specs[i]->name,
+                  property_id,
                   pspec->name);
        return;
       }
-  if (g_object_class_find_param_spec (class, pspec->name))
+  if (g_object_class_find_property (class, pspec->name))
     {
-      g_warning (G_STRLOC ": class `%s' already contains a parameter named `%s'",
+      g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
                 G_OBJECT_CLASS_NAME (class),
                 pspec->name);
       return;
     }
-  
-  g_param_spec_set_qdata (pspec, quark_param_id, GUINT_TO_POINTER (param_id));
-  g_param_spec_hash_table_insert (param_spec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
-  i = class->n_param_specs++;
-  class->param_specs = g_renew (GParamSpec*, class->param_specs, class->n_param_specs);
-  class->param_specs[i] = pspec;
+
+  g_param_spec_ref (pspec);
+  g_param_spec_sink (pspec);
+  g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
+  g_param_spec_hash_table_insert (pspec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
+  i = class->n_property_specs++;
+  class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
+  class->property_specs[i] = pspec;
 }
 
 GParamSpec*
-g_object_class_find_param_spec (GObjectClass *class,
-                               const gchar  *param_name)
+g_object_class_find_property (GObjectClass *class,
+                             const gchar  *property_name)
 {
   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
-  g_return_val_if_fail (param_name != NULL, NULL);
+  g_return_val_if_fail (property_name != NULL, NULL);
   
-  return g_param_spec_hash_table_lookup (param_spec_hash_table,
-                                        param_name,
+  return g_param_spec_hash_table_lookup (pspec_hash_table,
+                                        property_name,
                                         G_OBJECT_CLASS_TYPE (class),
                                         TRUE, NULL);
 }
 
 static void
-g_object_do_init (GObject *object)
+free_notify_queue (gpointer data)
+{
+  NotifyQueue *nqueue = data;
+  
+  g_slist_free (nqueue->pspecs);
+  g_free (nqueue);
+}
+
+static inline NotifyQueue*
+object_freeze_notifies (GObject *object)
+{
+  NotifyQueue *nqueue;
+
+  nqueue = g_object_get_qdata (object, quark_notify_queue);
+  if (!nqueue)
+    {
+      nqueue = g_new0 (NotifyQueue, 1);
+      g_object_set_qdata_full (object, quark_notify_queue, nqueue, free_notify_queue);
+    }
+  nqueue->freeze_count++;
+
+  return nqueue;
+}
+
+static inline void
+object_queue_property (GObject     *object,
+                      GParamSpec  *pspec,
+                      NotifyQueue *nqueue)
+{
+  /* we will dedup later */
+  nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
+  nqueue->n_pspecs++;
+}
+
+static void
+g_object_init (GObject *object)
 {
   object->ref_count = 1;
   object->qdata = NULL;
   
+  /* freeze object's notification queue, g_object_new_valist() takes care of that */
+  object_freeze_notifies (object);
+
 #ifdef DEBUG_OBJECTS
   if (glib_debug_objects)
     {
@@ -267,6 +433,66 @@ g_object_do_init (GObject *object)
 }
 
 static void
+g_object_do_set_property (GObject      *object,
+                         guint         property_id,
+                         const GValue *value,
+                         GParamSpec   *pspec,
+                         const gchar  *trailer)
+{
+  guint i = 0;
+  
+  switch (property_id)
+    {
+      gboolean swapped, after;
+      gpointer callback, data;
+    case PROP_DATA:
+      g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+
+      g_object_set_data (object, trailer + 2, g_value_get_pointer (value));
+      break;
+    case PROP_SWAPPED_SIGNAL_AFTER:
+      i++;
+    case PROP_SIGNAL_AFTER:
+      i++;
+    case PROP_SWAPPED_SIGNAL:
+      i++;
+    case PROP_SIGNAL:
+      after = i > 2;
+      swapped = i & 1;
+      g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+
+      g_value_get_ccallback (value, &callback, &data);
+      g_signal_connect_data (object, trailer + 2,
+                            callback, data, NULL,
+                            swapped, after);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+g_object_do_get_property (GObject     *object,
+                         guint        property_id,
+                         GValue      *value,
+                         GParamSpec  *pspec,
+                         const gchar *trailer)
+{
+  switch (property_id)
+    {
+    case PROP_DATA:
+      g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+
+      g_value_set_pointer (value, g_object_get_data (object, trailer + 2));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
 g_object_last_unref (GObject *object)
 {
   g_return_if_fail (object->ref_count > 0);
@@ -279,12 +505,16 @@ g_object_last_unref (GObject *object)
   if (object->ref_count == 0)  /* may have been re-referenced meanwhile */
     {
       G_OBJECT_GET_CLASS (object)->finalize (object);
+#ifdef  DEBUG_OBJECTS
+      if (glib_debug_objects && debug_objects_ht)
+       g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
+#endif /* DEBUG_OBJECTS */
       g_type_free_instance ((GTypeInstance*) object);
     }
 }
 
 static void
-g_object_do_shutdown (GObject *object)
+g_object_shutdown (GObject *object)
 {
   /* this function needs to be always present for unconditional
    * chaining, we also might add some code here later.
@@ -293,7 +523,7 @@ g_object_do_shutdown (GObject *object)
 }
 
 static void
-g_object_do_finalize (GObject *object)
+g_object_finalize (GObject *object)
 {
   g_signal_handlers_destroy (object);
   g_datalist_clear (&object->qdata);
@@ -309,116 +539,137 @@ g_object_do_finalize (GObject *object)
 #endif /* DEBUG_OBJECTS */
 }
 
-gpointer
-g_object_new (GType       object_type,
-             const gchar *first_param_name,
-             ...)
+static inline void
+object_thaw_notifies (GObject     *object,
+                     NotifyQueue *nqueue)
 {
-  GObject *object;
-  va_list var_args;
+  GParamSpec **pspecs;
+  GSList *slist;
+  guint n_pspecs = 0;
   
-  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+  nqueue->freeze_count--;
+  if (nqueue->freeze_count)
+    return;
+  g_return_if_fail (object->ref_count > 0);
   
-  va_start (var_args, first_param_name);
-  object = g_object_new_valist (object_type, first_param_name, var_args);
-  va_end (var_args);
+  pspecs = g_new (GParamSpec*, nqueue->n_pspecs);
+  for (slist = nqueue->pspecs; slist; slist = slist->next)
+    {
+      GParamSpec *pspec = slist->data;
+      gint i = 0;
+      
+      /* dedup, make pspecs in the list unique */
+    redo_dedup_check:
+      if (pspecs[i] == pspec)
+       continue;
+      if (++i < n_pspecs)
+       goto redo_dedup_check;
+      
+      pspecs[n_pspecs++] = pspec;
+    }
+  g_object_set_qdata (object, quark_notify_queue, NULL);
   
-  return object;
+  if (n_pspecs)
+    G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
+  
+  g_free (pspecs);
 }
 
-gpointer
-g_object_new_valist (GType       object_type,
-                    const gchar *first_param_name,
-                    va_list      var_args)
+static void
+g_object_dispatch_properties_changed (GObject     *object,
+                                     guint        n_pspecs,
+                                     GParamSpec **pspecs)
 {
-  GObject *object;
-  
-  g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
-  
-  object = (GObject*) g_type_create_instance (object_type);
-  if (first_param_name)
-    g_object_set_valist (object, first_param_name, var_args);
-  
-  return object;
+  g_signal_emit (object, gobject_signals[PROPERTIES_CHANGED], 0, n_pspecs, pspecs);
 }
 
 static void
-g_object_do_dispatch_param_changed (GObject    *object,
-                                   GParamSpec *pspec)
+g_object_properties_changed (GObject     *object,
+                            guint        n_pspecs,
+                            GParamSpec **pspecs)
 {
-/*  g_message ("NOTIFICATION: parameter `%s' changed on object `%s'",
+  guint i;
+
+  for (i = 0; i < n_pspecs; i++)
+    g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
+}
+
+static void
+g_object_notify_property_changed (GObject    *object,
+                                 GParamSpec *pspec)
+{
+  g_message ("NOTIFICATION: %s property changed on object `%s'",
             pspec->name,
-            G_OBJECT_TYPE_NAME (object));*/
+            G_OBJECT_TYPE_NAME (object));
 }
 
-static gboolean
-notify_param_changed_handler (gpointer data)
+void
+g_object_freeze_notify (GObject *object)
 {
-  GObject *object;
-  GObjectClass *class;
-  GSList *slist;
-  
-  /* FIXME: need GDK_THREADS lock */
-  
-  object = G_OBJECT (data);
-  class = G_OBJECT_GET_CLASS (object);
-  slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
-  
-  /* a reference count is still being held */
-  
-  for (; slist; slist = slist->next)
-    if (slist->data)
-      {
-       GParamSpec *pspec = slist->data;
-       
-       slist->data = NULL;
-       class->dispatch_param_changed (object, pspec);
-      }
-  
-  g_datalist_id_set_data (&object->qdata, quark_param_changed_queue, NULL);
-  
-  return FALSE;
+  g_return_if_fail (G_IS_OBJECT (object));
+  if (!object->ref_count)
+    return;
+
+  g_object_ref (object);
+  object_freeze_notifies (object);
+  g_object_unref (object);
 }
 
-static void
-g_object_do_queue_param_changed (GObject    *object,
-                                GParamSpec *pspec)
+void
+g_object_notify (GObject     *object,
+                const gchar *property_name)
 {
-  GSList *slist, *last = NULL;
-  
-  /* if this is a recursive call on this object (i.e. pspecs are queued
-   * for notification, while param_changed notification is currently in
-   * progress), we simply add them to the queue that is currently being
-   * dispatched. otherwise, we later dispatch parameter changed notification
-   * asyncronously from an idle handler untill the queue is completely empty.
-   */
+  GParamSpec *pspec;
   
-  slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
-  for (; slist; last = slist, slist = last->next)
-    if (slist->data == pspec)
-      return;
+  g_return_if_fail (G_IS_OBJECT (object));
+  g_return_if_fail (property_name != NULL);
+  if (!object->ref_count)
+    return;
   
-  if (!last)
+  g_object_ref (object);
+  pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
+                                         property_name,
+                                         G_OBJECT_TYPE (object),
+                                         TRUE, NULL);
+  if (!pspec)
+    g_warning ("%s: object class `%s' has no property named `%s'",
+              G_STRLOC,
+              G_OBJECT_TYPE_NAME (object),
+              property_name);
+  else
     {
-      g_object_ref (object);
-      g_idle_add_full (G_NOTIFY_PRIORITY,
-                      notify_param_changed_handler,
-                      object,
-                      (GDestroyNotify) g_object_unref);
-      g_object_set_qdata_full (object,
-                              quark_param_changed_queue,
-                              g_slist_prepend (NULL, pspec),
-                              (GDestroyNotify) g_slist_free);
+      NotifyQueue *nqueue = object_freeze_notifies (object);
+
+      object_queue_property (object, pspec, nqueue);
+      object_thaw_notifies (object, nqueue);
     }
+  g_object_unref (object);
+}
+
+void
+g_object_thaw_notify (GObject *object)
+{
+  NotifyQueue *nqueue;
+  
+  g_return_if_fail (G_IS_OBJECT (object));
+  if (!object->ref_count)
+    return;
+  
+  g_object_ref (object);
+  nqueue = g_object_get_qdata (object, quark_notify_queue);
+  if (!nqueue || !nqueue->freeze_count)
+    g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen",
+              G_OBJECT_TYPE_NAME (object), object);
   else
-    last->next = g_slist_prepend (NULL, pspec);
+    object_thaw_notifies (object, nqueue);
+  g_object_unref (object);
 }
 
 static inline void
-object_get_param (GObject     *object,
-                 GValue      *value,
-                 GParamSpec  *pspec,
-                 const gchar *trailer)
+object_get_property (GObject     *object,
+                    GValue      *value,
+                    GParamSpec  *pspec,
+                    const gchar *trailer)
 {
   GObjectClass *class;
   
@@ -426,14 +677,15 @@ object_get_param (GObject     *object,
   
   class = g_type_class_peek (pspec->owner_type);
   
-  class->get_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
+  class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
 }
 
 static inline void
-object_set_param (GObject     *object,
-                 GValue      *value,
-                 GParamSpec  *pspec,
-                 const gchar *trailer)
+object_set_property (GObject     *object,
+                    GValue      *value,
+                    GParamSpec  *pspec,
+                    const gchar *trailer,
+                    NotifyQueue *nqueue)
 {
   GObjectClass *class;
   
@@ -441,24 +693,229 @@ object_set_param (GObject     *object,
   
   class = g_type_class_peek (pspec->owner_type);
   
-  class->set_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
+  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);
   
-  class->queue_param_changed (object, pspec);
+  return object;
+}
+
+static GObject*
+g_object_constructor (GType                  type,
+                     guint                  n_construct_properties,
+                     GObjectConstructParam *construct_params)
+{
+  GObject *object;
+
+  /* create object */
+  object = (GObject*) g_type_create_instance (type);
+
+  /* set construction parameters */
+  if (n_construct_properties)
+    {
+      NotifyQueue *nqueue = object_freeze_notifies (object);
+      
+      /* set construct properties */
+      while (n_construct_properties--)
+       {
+         GValue *value = construct_params[n_construct_properties].value;
+         GParamSpec *pspec = construct_params[n_construct_properties].pspec;
+         const gchar *trailer = construct_params[n_construct_properties].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);
+       }
+      nqueue->freeze_count--;
+      /* the notification queue is still frozen from g_object_init(), so
+       * we don't need to handle it here, g_object_new_valist() takes
+       * care of that
+       */
+    }
+
+  return object;
 }
 
 void
 g_object_set_valist (GObject    *object,
-                    const gchar *first_param_name,
+                    const gchar *first_property_name,
                     va_list      var_args)
 {
+  NotifyQueue *nqueue;
   const gchar *name;
   
   g_return_if_fail (G_IS_OBJECT (object));
   
   g_object_ref (object);
+  nqueue = object_freeze_notifies (object);
   
-  name = first_param_name;
-  
+  name = first_property_name;
   while (name)
     {
       const gchar *trailer = NULL;
@@ -466,14 +923,14 @@ g_object_set_valist (GObject       *object,
       GParamSpec *pspec;
       gchar *error = NULL;
       
-      pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+      pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
                                              name,
                                              G_OBJECT_TYPE (object),
                                              TRUE,
                                              &trailer);
       if (!pspec)
        {
-         g_warning ("%s: object class `%s' has no parameter named `%s'",
+         g_warning ("%s: object class `%s' has no property named `%s'",
                     G_STRLOC,
                     G_OBJECT_TYPE_NAME (object),
                     name);
@@ -481,7 +938,7 @@ g_object_set_valist (GObject         *object,
        }
       if (!(pspec->flags & G_PARAM_WRITABLE))
        {
-         g_warning ("%s: parameter `%s' of object class `%s' is not writable",
+         g_warning ("%s: property `%s' of object class `%s' is not writable",
                     G_STRLOC,
                     pspec->name,
                     G_OBJECT_TYPE_NAME (object));
@@ -502,19 +959,20 @@ g_object_set_valist (GObject       *object,
          break;
        }
       
-      object_set_param (object, &value, pspec, trailer);
+      object_set_property (object, &value, pspec, trailer, nqueue);
       
       g_value_unset (&value);
       
       name = va_arg (var_args, gchar*);
     }
-  
+
+  object_thaw_notifies (object, nqueue);
   g_object_unref (object);
 }
 
 void
 g_object_get_valist (GObject    *object,
-                    const gchar *first_param_name,
+                    const gchar *first_property_name,
                     va_list      var_args)
 {
   const gchar *name;
@@ -523,23 +981,23 @@ g_object_get_valist (GObject       *object,
   
   g_object_ref (object);
   
-  name = first_param_name;
+  name = first_property_name;
   
   while (name)
     {
       const gchar *trailer = NULL;
       GValue value = { 0, };
       GParamSpec *pspec;
-      gchar *error = NULL;
+      gchar *error;
       
-      pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
+      pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
                                              name,
                                              G_OBJECT_TYPE (object),
                                              TRUE,
                                              &trailer);
       if (!pspec)
        {
-         g_warning ("%s: object class `%s' has no parameter named `%s'",
+         g_warning ("%s: object class `%s' has no property named `%s'",
                     G_STRLOC,
                     G_OBJECT_TYPE_NAME (object),
                     name);
@@ -547,7 +1005,7 @@ g_object_get_valist (GObject        *object,
        }
       if (!(pspec->flags & G_PARAM_READABLE))
        {
-         g_warning ("%s: parameter `%s' of object class `%s' is not readable",
+         g_warning ("%s: property `%s' of object class `%s' is not readable",
                     G_STRLOC,
                     pspec->name,
                     G_OBJECT_TYPE_NAME (object));
@@ -556,7 +1014,7 @@ g_object_get_valist (GObject        *object,
       
       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
       
-      object_get_param (object, &value, pspec, trailer);
+      object_get_property (object, &value, pspec, trailer);
       
       G_VALUE_LCOPY (&value, var_args, &error);
       if (error)
@@ -580,56 +1038,58 @@ g_object_get_valist (GObject      *object,
 
 void
 g_object_set (GObject    *object,
-             const gchar *first_param_name,
+             const gchar *first_property_name,
              ...)
 {
   va_list var_args;
   
   g_return_if_fail (G_IS_OBJECT (object));
   
-  va_start (var_args, first_param_name);
-  g_object_set_valist (object, first_param_name, var_args);
+  va_start (var_args, first_property_name);
+  g_object_set_valist (object, first_property_name, var_args);
   va_end (var_args);
 }
 
 void
 g_object_get (GObject    *object,
-             const gchar *first_param_name,
+             const gchar *first_property_name,
              ...)
 {
   va_list var_args;
   
   g_return_if_fail (G_IS_OBJECT (object));
   
-  va_start (var_args, first_param_name);
-  g_object_get_valist (object, first_param_name, var_args);
+  va_start (var_args, first_property_name);
+  g_object_get_valist (object, first_property_name, var_args);
   va_end (var_args);
 }
 
 void
-g_object_set_param (GObject     *object,
-                   const gchar  *param_name,
-                   const GValue *value)
+g_object_set_property (GObject     *object,
+                      const gchar  *property_name,
+                      const GValue *value)
 {
+  NotifyQueue *nqueue;
   GParamSpec *pspec;
   const gchar *trailer;
   
   g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (param_name != NULL);
+  g_return_if_fail (property_name != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   
   g_object_ref (object);
+  nqueue = object_freeze_notifies (object);
   
-  pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
-                                         param_name,
+  pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
+                                         property_name,
                                          G_OBJECT_TYPE (object),
                                          TRUE,
                                          &trailer);
   if (!pspec)
-    g_warning ("%s: object class `%s' has no parameter named `%s'",
+    g_warning ("%s: object class `%s' has no property named `%s'",
               G_STRLOC,
               G_OBJECT_TYPE_NAME (object),
-              param_name);
+              property_name);
   else
     {
       GValue tmp_value = { 0, };
@@ -639,65 +1099,66 @@ g_object_set_param (GObject       *object,
       
       if (!g_value_convert (value, &tmp_value) ||
          g_param_value_validate (pspec, &tmp_value))
-       g_warning ("%s: cannot convert `%s' value to parameter `%s' value of type `%s'",
+       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_param (object, &tmp_value, pspec, trailer);
+       object_set_property (object, &tmp_value, pspec, trailer, nqueue);
       
       g_value_unset (&tmp_value);
     }
   
+  object_thaw_notifies (object, nqueue);
   g_object_unref (object);
 }
 
 void
-g_object_get_param (GObject    *object,
-                   const gchar *param_name,
-                   GValue      *value)
+g_object_get_property (GObject    *object,
+                      const gchar *property_name,
+                      GValue      *value)
 {
   GParamSpec *pspec;
   const gchar *trailer;
   
   g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (param_name != NULL);
+  g_return_if_fail (property_name != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   
   g_object_ref (object);
   
-  pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
-                                         param_name,
+  pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
+                                         property_name,
                                          G_OBJECT_TYPE (object),
                                          TRUE,
                                          &trailer);
   if (!pspec)
-    g_warning ("%s: object class `%s' has no parameter named `%s'",
+    g_warning ("%s: object class `%s' has no property named `%s'",
               G_STRLOC,
               G_OBJECT_TYPE_NAME (object),
-              param_name);
+              property_name);
   else
     {
       GValue tmp_value = { 0, };
       
       /* provide a copy to work from and later convert if necessary, so
-       * _get_param() implementations need *not* care about freeing values
-       * that might be already set in the parameter to get.
+       * _get_property() implementations need *not* care about freeing values
+       * that might be already set in the property to get.
        * (though, at this point, GValue should exclusively be modified
        * through the accessor functions anyways)
        */
       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
       
       if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
-       g_warning ("%s: can't retrive parameter `%s' value of type `%s' as value of type `%s'",
+       g_warning ("%s: can't retrive property `%s' value of type `%s' as value of type `%s'",
                   G_STRLOC,
                   pspec->name,
                   g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
                   G_VALUE_TYPE_NAME (value));
       else
        {
-         object_get_param (object, &tmp_value, pspec, trailer);
+         object_get_property (object, &tmp_value, pspec, trailer);
          g_value_convert (&tmp_value, value);
          /* g_value_validate (value, pspec); */
        }
@@ -708,28 +1169,6 @@ g_object_get_param (GObject       *object,
   g_object_unref (object);
 }
 
-void
-g_object_queue_param_changed (GObject    *object,
-                             const gchar *param_name)
-{
-  GParamSpec *pspec;
-  
-  g_return_if_fail (G_IS_OBJECT (object));
-  g_return_if_fail (param_name != NULL);
-  
-  pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
-                                         param_name,
-                                         G_OBJECT_TYPE (object),
-                                         TRUE, NULL);
-  if (!pspec)
-    g_warning ("%s: object class `%s' has no parameter named `%s'",
-              G_STRLOC,
-              G_OBJECT_TYPE_NAME (object),
-              param_name);
-  else
-    G_OBJECT_GET_CLASS (object)->queue_param_changed (object, pspec);
-}
-
 GObject*
 g_object_ref (GObject *object)
 {
@@ -799,11 +1238,14 @@ gpointer
 g_object_get_data (GObject     *object,
                    const gchar *key)
 {
+  GQuark quark;
+
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
   g_return_val_if_fail (key != NULL, NULL);
-  
-  return g_object_get_qdata (object,
-                             g_quark_try_string (key));
+
+  quark = g_quark_try_string (key);
+
+  return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
 }
 
 void
@@ -814,9 +1256,7 @@ g_object_set_data (GObject     *object,
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (key != NULL);
 
-  g_object_set_qdata (object,
-                      g_quark_from_string (key),
-                      data);
+  g_datalist_id_set_data (&object->qdata, g_quark_from_string (key), data);
 }
 
 void
@@ -828,21 +1268,21 @@ g_object_set_data_full (GObject       *object,
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (key != NULL);
 
-  g_object_set_qdata_full (object,
-                           g_quark_from_string (key),
-                           data,
-                           destroy);
+  g_datalist_id_set_data_full (&object->qdata, g_quark_from_string (key), data, data ? destroy : NULL);
 }
 
 gpointer
 g_object_steal_data (GObject     *object,
                      const gchar *key)
 {
+  GQuark quark;
+
   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
   g_return_val_if_fail (key != NULL, NULL);
 
-  return g_object_steal_qdata (object,
-                               g_quark_try_string (key));
+  quark = g_quark_try_string (key);
+
+  return quark ? g_datalist_id_remove_no_notify (&object->qdata, quark) : NULL;
 }
 
 static void
@@ -927,14 +1367,21 @@ 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_object_unref (value->data[0].v_pointer);
+      value->data[0].v_pointer = NULL;
+    }
+
+  if (v_object)
+    {
+      g_return_if_fail (G_IS_OBJECT (v_object));
+      g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
+
+      value->data[0].v_pointer = v_object;
+      g_object_ref (value->data[0].v_pointer);
+    }
 }
 
 GObject*
@@ -953,6 +1400,32 @@ g_value_dup_object (const GValue *value)
   return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
 }
 
+guint
+g_signal_connect_object (gpointer     instance,
+                        const gchar *detailed_signal,
+                        GCallback    c_handler,
+                        gpointer     gobject,
+                        gboolean     swapped,
+                        gboolean     after)
+{
+  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
+  g_return_val_if_fail (detailed_signal != NULL, 0);
+  g_return_val_if_fail (c_handler != NULL, 0);
+
+  if (gobject)
+    {
+      GClosure *closure;
+
+      g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
+
+      closure = (swapped ? g_cclosure_new_object_swap : g_cclosure_new_object) (c_handler, gobject);
+
+      return g_signal_connect_closure (instance, detailed_signal, closure, after);
+    }
+  else
+    return g_signal_connect_data (instance, detailed_signal, c_handler, NULL, NULL, swapped, after);
+}
+
 typedef struct {
   GObject  *object;
   guint     n_closures;
index 7c31d6a..4625830 100644 (file)
@@ -8,7 +8,7 @@
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General
 #ifndef __G_OBJECT_H__
 #define __G_OBJECT_H__
 
-#include       <gobject/gtype.h>
-#include       <gobject/gvalue.h>
-#include       <gobject/gparam.h>
-#include       <gobject/gclosure.h>
+#include        <gobject/gtype.h>
+#include        <gobject/gvalue.h>
+#include        <gobject/gparam.h>
+#include        <gobject/gclosure.h>
 
 
 #ifdef __cplusplus
@@ -31,161 +31,177 @@ extern "C" {
 
 
 /* --- type macros --- */
-#define G_TYPE_IS_OBJECT(type)    (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT)
-#define G_OBJECT(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
-#define G_OBJECT_CLASS(class)     (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_OBJECT, GObjectClass))
-#define G_IS_OBJECT(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_OBJECT))
+#define G_TYPE_IS_OBJECT(type)     (G_TYPE_FUNDAMENTAL (type) == G_TYPE_OBJECT)
+#define G_OBJECT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
+#define G_OBJECT_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_OBJECT, GObjectClass))
+#define G_IS_OBJECT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_OBJECT))
 #define G_IS_OBJECT_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_OBJECT))
 #define G_OBJECT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), G_TYPE_OBJECT, GObjectClass))
-#define G_OBJECT_TYPE(object)     (G_TYPE_FROM_INSTANCE (object))
+#define G_OBJECT_TYPE(object)      (G_TYPE_FROM_INSTANCE (object))
 #define G_OBJECT_TYPE_NAME(object) (g_type_name (G_OBJECT_TYPE (object)))
 #define G_OBJECT_CLASS_TYPE(class) (G_TYPE_FROM_CLASS (class))
 #define G_OBJECT_CLASS_NAME(class) (g_type_name (G_OBJECT_CLASS_TYPE (class)))
 #define G_IS_VALUE_OBJECT(value)   (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_OBJECT))
 
-#define        G_NOTIFY_PRIORITY          (G_PRIORITY_HIGH_IDLE + 20)
-
 
 /* --- typedefs & structures --- */
-typedef struct _GObject                      GObject;
-typedef struct _GObjectClass          GObjectClass;
-typedef struct _GObjectConstructParam GObjectConstructParam;
-typedef void (*GObjectGetParamFunc)    (GObject      *object,
-                                        guint         param_id,
-                                        GValue       *value,
-                                        GParamSpec   *pspec,
-                                        const gchar  *trailer);
-typedef void (*GObjectSetParamFunc)    (GObject      *object,
-                                        guint         param_id,
-                                        const GValue *value,
-                                        GParamSpec   *pspec,
-                                        const gchar  *trailer);
-typedef void (*GObjectFinalizeFunc)    (GObject      *object);
-struct _GObject
+typedef struct _GObject                  GObject;
+typedef struct _GObjectClass             GObjectClass;
+typedef struct _GObjectConstructParam    GObjectConstructParam;
+typedef void (*GObjectGetPropertyFunc)  (GObject      *object,
+                                         guint         property_id,
+                                         GValue       *value,
+                                         GParamSpec   *pspec,
+                                         const gchar  *trailer);
+typedef void (*GObjectSetPropertyFunc)  (GObject      *object,
+                                         guint         property_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec,
+                                         const gchar  *trailer);
+typedef void (*GObjectFinalizeFunc)     (GObject      *object);
+struct  _GObject
 {
   GTypeInstance g_type_instance;
   
   /*< private >*/
-  guint                ref_count;
-  GData               *qdata;
+  guint         ref_count;
+  GData        *qdata;
 };
-struct _GObjectClass
+struct  _GObjectClass
 {
   GTypeClass   g_type_class;
 
-  guint               n_param_specs;
-  GParamSpec **param_specs;
-
-  GObject*   (*constructor)    (GType                  type, // FIXME!!!
-                                guint                  n_construct_params,
-                                GObjectConstructParam *construct_params);
-  void      (*get_param)               (GObject        *object,
-                                        guint           param_id,
-                                        GValue         *value,
-                                        GParamSpec     *pspec,
-                                        const gchar    *trailer);
-  void      (*set_param)               (GObject        *object,
-                                        guint           param_id,
-                                        const GValue   *value,
-                                        GParamSpec     *pspec,
-                                        const gchar    *trailer);
-  void      (*queue_param_changed)     (GObject        *object,
-                                        GParamSpec     *pspec);
-  void      (*dispatch_param_changed)  (GObject        *object,
+  /* private, these fields might vanish */
+  guint        n_property_specs;
+  GParamSpec **property_specs;
+
+  /* public overridable methods */
+  GObject*   (*constructor)     (GType                  type,
+                                 guint                  n_construct_properties,
+                                 GObjectConstructParam *construct_params);
+  void       (*get_property)            (GObject        *object,
+                                         guint           property_id,
+                                         GValue         *value,
+                                         GParamSpec     *pspec,
+                                         const gchar    *trailer);
+  void       (*set_property)            (GObject        *object,
+                                         guint           property_id,
+                                         const GValue   *value,
+                                         GParamSpec     *pspec,
+                                         const gchar    *trailer);
+  void       (*shutdown)                (GObject        *object);
+  void       (*finalize)                (GObject        *object);
+
+  /*< private >*/
+  void       (*dispatch_properties_changed) (GObject      *object,
+                                            guint         n_pspecs,
+                                            GParamSpec  **pspecs);
+
+  /* signals */
+  void      (*properties_changed)      (GObject        *object,
+                                        guint           n_pspecs,
+                                        GParamSpec    **pspecs);
+  void      (*notify)                  (GObject        *object,
                                         GParamSpec     *pspec);
-  void      (*shutdown)                (GObject        *object);
-  void      (*finalize)                (GObject        *object);
 };
 struct _GObjectConstructParam
 {
-  GParamSpec *pspec;
-  GValue     *value;
-  gchar      *trailer;
+  GParamSpec  *pspec;
+  GValue      *value;
+  const gchar *trailer;
 };
 
 
 /* --- prototypes --- */
-void       g_object_class_install_param   (GObjectClass   *oclass,
-                                           guint           param_id,
-                                           GParamSpec     *pspec /* +1 ref */);
-GParamSpec* g_object_class_find_param_spec (GObjectClass   *oclass,
-                                           const gchar    *param_name);
-gpointer    g_object_new                  (GType           object_type,
-                                           const gchar    *first_param_name,
-                                           ...);
-gpointer    g_object_new_valist                   (GType           object_type,
-                                           const gchar    *first_param_name,
-                                           va_list         var_args);
-void       g_object_set                   (GObject        *object,
-                                           const gchar    *first_param_name,
-                                           ...);
-void       g_object_get                   (GObject        *object,
-                                           const gchar    *first_param_name,
-                                           ...);
-void       g_object_set_valist            (GObject        *object,
-                                           const gchar    *first_param_name,
-                                           va_list         var_args);
-void       g_object_get_valist            (GObject        *object,
-                                           const gchar    *first_param_name,
-                                           va_list         var_args);
-void       g_object_set_param             (GObject        *object,
-                                           const gchar    *param_name,
-                                           const GValue   *value);
-void       g_object_get_param             (GObject        *object,
-                                           const gchar    *param_name,
-                                           GValue         *value);
-void       g_object_queue_param_changed   (GObject        *object,
-                                           const gchar    *param_name);
-GObject*    g_object_ref                  (GObject        *object);
-void       g_object_unref                 (GObject        *object);
-gpointer    g_object_get_qdata            (GObject        *object,
-                                           GQuark          quark);
-void       g_object_set_qdata             (GObject        *object,
-                                           GQuark          quark,
-                                           gpointer        data);
-void       g_object_set_qdata_full        (GObject        *object,
-                                           GQuark          quark,
-                                           gpointer        data,
-                                           GDestroyNotify  destroy);
-gpointer    g_object_steal_qdata          (GObject        *object,
-                                           GQuark          quark);
-gpointer    g_object_get_data             (GObject        *object,
-                                            const gchar    *key);
-void       g_object_set_data              (GObject        *object,
-                                            const gchar    *key,
-                                           gpointer        data);
-void       g_object_set_data_full         (GObject        *object,
-                                            const gchar    *key,
-                                           gpointer        data,
-                                           GDestroyNotify  destroy);
-gpointer    g_object_steal_data            (GObject       *object,
-                                            const gchar    *key);
-void       g_object_watch_closure         (GObject        *object,
-                                           GClosure       *closure);
-GClosure*   g_cclosure_new_object         (GCallback       callback_func,
-                                           gpointer        object);
-GClosure*   g_cclosure_new_object_swap    (GCallback       callback_func,
-                                           gpointer        object);
-GClosure*   g_closure_new_object          (guint           sizeof_closure,
-                                           GObject        *object);
-void        g_value_set_object            (GValue         *value,
-                                           GObject        *v_object);
-GObject*    g_value_get_object            (const GValue   *value);
-GObject*    g_value_dup_object            (const GValue   *value);
+void        g_object_class_install_property   (GObjectClass   *oclass,
+                                              guint           property_id,
+                                              GParamSpec     *pspec);
+GParamSpec* g_object_class_find_property      (GObjectClass   *oclass,
+                                              const gchar    *property_name);
+gpointer    g_object_new                      (GType           object_type,
+                                              const gchar    *first_property_name,
+                                              ...);
+gpointer    g_object_new_valist               (GType           object_type,
+                                              const gchar    *first_property_name,
+                                              va_list         var_args);
+void        g_object_set                      (GObject        *object,
+                                              const gchar    *first_property_name,
+                                              ...);
+void        g_object_get                      (GObject        *object,
+                                              const gchar    *first_property_name,
+                                              ...);
+void        g_object_set_valist               (GObject        *object,
+                                              const gchar    *first_property_name,
+                                              va_list         var_args);
+void        g_object_get_valist               (GObject        *object,
+                                              const gchar    *first_property_name,
+                                              va_list         var_args);
+void        g_object_set_property             (GObject        *object,
+                                              const gchar    *property_name,
+                                              const GValue   *value);
+void        g_object_get_property             (GObject        *object,
+                                              const gchar    *property_name,
+                                              GValue         *value);
+void        g_object_freeze_notify            (GObject        *object);
+void        g_object_notify                   (GObject        *object,
+                                              const gchar    *property_name);
+void        g_object_thaw_notify              (GObject        *object);
+GObject*    g_object_ref                      (GObject        *object);
+void        g_object_unref                    (GObject        *object);
+gpointer    g_object_get_qdata                (GObject        *object,
+                                              GQuark          quark);
+void        g_object_set_qdata                (GObject        *object,
+                                              GQuark          quark,
+                                              gpointer        data);
+void        g_object_set_qdata_full           (GObject        *object,
+                                              GQuark          quark,
+                                              gpointer        data,
+                                              GDestroyNotify  destroy);
+gpointer    g_object_steal_qdata              (GObject        *object,
+                                              GQuark          quark);
+gpointer    g_object_get_data                 (GObject        *object,
+                                              const gchar    *key);
+void        g_object_set_data                 (GObject        *object,
+                                              const gchar    *key,
+                                              gpointer        data);
+void        g_object_set_data_full            (GObject        *object,
+                                              const gchar    *key,
+                                              gpointer        data,
+                                              GDestroyNotify  destroy);
+gpointer    g_object_steal_data               (GObject        *object,
+                                              const gchar    *key);
+void        g_object_watch_closure            (GObject        *object,
+                                              GClosure       *closure);
+GClosure*   g_cclosure_new_object             (GCallback       callback_func,
+                                              gpointer        object);
+GClosure*   g_cclosure_new_object_swap        (GCallback       callback_func,
+                                              gpointer        object);
+GClosure*   g_closure_new_object              (guint           sizeof_closure,
+                                              GObject        *object);
+void        g_value_set_object                (GValue         *value,
+                                              GObject        *v_object);
+GObject*    g_value_get_object                (const GValue   *value);
+GObject*    g_value_dup_object                (const GValue   *value);
+guint      g_signal_connect_object           (gpointer        instance,
+                                              const gchar    *detailed_signal,
+                                              GCallback       c_handler,
+                                              gpointer        gobject,
+                                              gboolean        swapped,
+                                              gboolean        after);
 
 
 /* --- implementation macros --- */
-#define G_WARN_INVALID_PARAM_ID(object, param_id, pspec) \
+#define G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec) \
 G_STMT_START { \
   GObject *_object = (GObject*) (object); \
   GParamSpec *_pspec = (GParamSpec*) (pspec); \
-  guint _param_id = (param_id); \
-  g_warning ("%s: invalid parameter id %u for \"%s\" of type `%s' in `%s'", \
-            G_STRLOC, \
-            _param_id, \
-            _pspec->name, \
-            g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \
-            G_OBJECT_TYPE_NAME (_object)); \
+  guint _property_id = (property_id); \
+  g_warning ("%s: invalid property id %u for \"%s\" of type `%s' in `%s'", \
+             G_STRLOC, \
+             _property_id, \
+             _pspec->name, \
+             g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \
+             G_OBJECT_TYPE_NAME (_object)); \
 } G_STMT_END
 
 
index fd93698..fdb1508 100644 (file)
 #include       "gparam.h"
 
 
+#include       "gvaluecollector.h"
 #include       <string.h>
 
 
 
 /* --- defines --- */
 #define G_PARAM_SPEC_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
+#define PSPEC_APPLIES_TO_VALUE(pspec, value)  (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
 
 
 /* --- prototypes --- */
@@ -34,6 +36,23 @@ static void  g_param_spec_class_init          (GParamSpecClass       *class,
                                                  gpointer               class_data);
 static void    g_param_spec_init                (GParamSpec            *pspec);
 static void    g_param_spec_finalize            (GParamSpec            *pspec);
+static void    value_param_init                (GValue         *value);
+static void    value_param_free_value          (GValue         *value);
+static void    value_param_copy_value          (const GValue   *src_value,
+                                                GValue         *dest_value);
+static gpointer        value_param_peek_pointer        (const GValue   *value);
+static gchar*  value_param_collect_value       (GValue         *value,
+                                                guint           nth_value,
+                                                GType          *collect_type,
+                                                GTypeCValue    *collect_value);
+static gchar*  value_param_lcopy_value         (const GValue   *value,
+                                                guint           nth_value,
+                                                GType          *collect_type,
+                                                GTypeCValue    *collect_value);
+
+
+/* --- variables --- */
+static GQuark quark_floating = 0;
 
 
 /* --- functions --- */
@@ -46,6 +65,16 @@ g_param_type_init (void)     /* sync with gtype.c */
      G_TYPE_FLAG_DERIVABLE |
      G_TYPE_FLAG_DEEP_DERIVABLE),
   };
+  static const GTypeValueTable param_value_table = {
+    value_param_init,           /* value_init */
+    value_param_free_value,     /* value_free */
+    value_param_copy_value,     /* value_copy */
+    value_param_peek_pointer,   /* value_peek_pointer */
+    G_VALUE_COLLECT_POINTER,    /* collect_type */
+    value_param_collect_value,  /* collect_value */
+    G_VALUE_COLLECT_POINTER,    /* lcopy_type */
+    value_param_lcopy_value,    /* lcopy_value */
+  };
   static const GTypeInfo param_spec_info = {
     sizeof (GParamSpecClass),
 
@@ -59,7 +88,7 @@ g_param_type_init (void)      /* sync with gtype.c */
     0,         /* n_preallocs */
     (GInstanceInitFunc) g_param_spec_init,
 
-    NULL,      /* value_table */
+    &param_value_table,
   };
   GType type;
 
@@ -81,6 +110,8 @@ static void
 g_param_spec_class_init (GParamSpecClass *class,
                         gpointer         class_data)
 {
+  quark_floating = g_quark_from_static_string ("GParamSpec-floating");
+
   class->value_type = G_TYPE_NONE;
   class->finalize = g_param_spec_finalize;
   class->value_set_default = NULL;
@@ -98,6 +129,7 @@ g_param_spec_init (GParamSpec *pspec)
   pspec->owner_type = 0;
   pspec->qdata = NULL;
   pspec->ref_count = 1;
+  g_datalist_id_set_data (&pspec->qdata, quark_floating, GUINT_TO_POINTER (TRUE));
 }
 
 static void
@@ -129,11 +161,28 @@ g_param_spec_unref (GParamSpec *pspec)
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
   g_return_if_fail (pspec->ref_count > 0);
 
+  /* sync with _sink */
   pspec->ref_count -= 1;
   if (pspec->ref_count == 0)
     G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
 }
 
+void
+g_param_spec_sink (GParamSpec *pspec)
+{
+  g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+  g_return_if_fail (pspec->ref_count > 0);
+
+  if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
+    {
+      /* sync with _unref */
+      if (pspec->ref_count > 1)
+       pspec->ref_count -= 1;
+      else
+       g_param_spec_unref (pspec);
+    }
+}
+
 gpointer
 g_param_spec_internal (GType        param_type,
                       const gchar *name,
@@ -204,7 +253,7 @@ g_param_value_set_default (GParamSpec *pspec,
 {
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
   g_return_if_fail (G_IS_VALUE (value));
-  g_return_if_fail (G_IS_PARAM_VALUE (pspec, value));
+  g_return_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value));
 
   g_value_reset (value);
   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, value);
@@ -219,7 +268,7 @@ g_param_value_defaults (GParamSpec *pspec,
 
   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
-  g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value), FALSE);
+  g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
 
   g_value_init (&dflt_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
   G_PARAM_SPEC_GET_CLASS (pspec)->value_set_default (pspec, &dflt_value);
@@ -235,7 +284,7 @@ g_param_value_validate (GParamSpec *pspec,
 {
   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
-  g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value), FALSE);
+  g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value), FALSE);
 
   if (G_PARAM_SPEC_GET_CLASS (pspec)->value_validate)
     {
@@ -265,14 +314,90 @@ g_param_values_cmp (GParamSpec   *pspec,
   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), 0);
   g_return_val_if_fail (G_IS_VALUE (value1), 0);
   g_return_val_if_fail (G_IS_VALUE (value2), 0);
-  g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value1), 0);
-  g_return_val_if_fail (G_IS_PARAM_VALUE (pspec, value2), 0);
+  g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value1), 0);
+  g_return_val_if_fail (PSPEC_APPLIES_TO_VALUE (pspec, value2), 0);
 
   cmp = G_PARAM_SPEC_GET_CLASS (pspec)->values_cmp (pspec, value1, value2);
 
   return CLAMP (cmp, -1, 1);
 }
 
+static void
+value_param_init (GValue *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static void
+value_param_free_value (GValue *value)
+{
+  if (value->data[0].v_pointer)
+    g_param_spec_unref (value->data[0].v_pointer);
+}
+
+static void
+value_param_copy_value (const GValue *src_value,
+                       GValue       *dest_value)
+{
+  dest_value->data[0].v_pointer = (src_value->data[0].v_pointer
+                                  ? g_param_spec_ref (src_value->data[0].v_pointer)
+                                  : NULL);
+}
+
+static gpointer
+value_param_peek_pointer (const GValue *value)
+{
+  return value->data[0].v_pointer;
+}
+
+static gchar*
+value_param_collect_value (GValue      *value,
+                          guint        nth_value,
+                          GType       *collect_type,
+                          GTypeCValue *collect_value)
+{
+  if (collect_value->v_pointer)
+    {
+      GParamSpec *param = collect_value->v_pointer;
+
+      if (param->g_type_instance.g_class == NULL)
+       return g_strconcat ("invalid unclassed param spec pointer for value type `",
+                           G_VALUE_TYPE_NAME (value),
+                           "'",
+                           NULL);
+      else if (!g_type_is_a (G_PARAM_SPEC_TYPE (param), G_VALUE_TYPE (value)))
+       return g_strconcat ("invalid param spec type `",
+                           G_PARAM_SPEC_TYPE_NAME (param),
+                           "' for value type `",
+                           G_VALUE_TYPE_NAME (value),
+                           "'",
+                           NULL);
+      value->data[0].v_pointer = g_param_spec_ref (param);
+    }
+  else
+    value->data[0].v_pointer = NULL;
+
+  *collect_type = 0;
+  return NULL;
+}
+
+static gchar*
+value_param_lcopy_value (const GValue *value,
+                        guint         nth_value,
+                        GType        *collect_type,
+                        GTypeCValue  *collect_value)
+{
+  GParamSpec **param_p = collect_value->v_pointer;
+
+  if (!param_p)
+    return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+
+  *param_p = value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
+
+  *collect_type = 0;
+  return NULL;
+}
+
 static guint
 param_spec_hash (gconstpointer key_spec)
 {
@@ -468,3 +593,34 @@ g_param_type_register_static (const gchar              *name,
 
   return g_type_register_static (G_TYPE_PARAM, name, &info, 0);
 }
+
+void
+g_value_set_param (GValue     *value,
+                  GParamSpec *param)
+{
+  g_return_if_fail (G_IS_VALUE_PARAM (value));
+  if (param)
+    g_return_if_fail (G_IS_PARAM_SPEC (param));
+
+  if (value->data[0].v_pointer)
+    g_param_spec_unref (value->data[0].v_pointer);
+  value->data[0].v_pointer = param;
+  if (value->data[0].v_pointer)
+    g_param_spec_ref (value->data[0].v_pointer);
+}
+
+GParamSpec*
+g_value_get_param (const GValue *value)
+{
+  g_return_val_if_fail (G_IS_VALUE_PARAM (value), NULL);
+
+  return value->data[0].v_pointer;
+}
+
+GParamSpec*
+g_value_dup_param (const GValue *value)
+{
+  g_return_val_if_fail (G_IS_VALUE_PARAM (value), NULL);
+
+  return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
+}
index 8b1f3f1..ec33fbc 100644 (file)
@@ -37,24 +37,40 @@ extern "C" {
 #define G_PARAM_SPEC(pspec)            (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM, GParamSpec))
 #define G_IS_PARAM_SPEC(pspec)         (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM))
 #define G_PARAM_SPEC_GET_CLASS(pspec)  (G_TYPE_INSTANCE_GET_CLASS ((pspec), G_TYPE_PARAM, GParamSpecClass))
-#define        G_IS_PARAM_VALUE(pspec, value)  (g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec))) /* FIXME */
 #define        G_PARAM_SPEC_VALUE_TYPE(pspec)  (G_PARAM_SPEC_GET_CLASS (pspec)->value_type)
-
+#define G_IS_VALUE_PARAM(value)                (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_PARAM))
+       
 
 /* --- flags --- */
 typedef enum
 {
   G_PARAM_READABLE            = 1 << 0,
   G_PARAM_WRITABLE            = 1 << 1,
-  G_PARAM_MASK                = 0x000f,
+  G_PARAM_CONSTRUCT          = 1 << 2,
+  G_PARAM_CONSTRUCT_ONLY      = 1 << 3,
+#define        G_PARAM_MASK            (0x000f)
   /* bits in the range 0xfff0 are reserved for 3rd party usage */
-  G_PARAM_USER_MASK           = 0xfff0
+#define        G_PARAM_USER_MASK       (0xfff0)
 } GParamFlags;
 
 
 /* --- typedefs & structures --- */
-typedef struct _GParamSpecClass GParamSpecClass;
 typedef struct _GParamSpec      GParamSpec;
+typedef struct _GParamSpecClass GParamSpecClass;
+struct _GParamSpec
+{
+  GTypeInstance  g_type_instance;
+
+  gchar         *name;
+  gchar         *nick;
+  gchar         *blurb;
+  GParamFlags    flags;
+
+  /*< private >*/
+  GType                 owner_type;
+  GData                *qdata;
+  guint          ref_count;
+};
 struct _GParamSpecClass
 {
   GTypeClass      g_type_class;
@@ -72,25 +88,12 @@ struct _GParamSpecClass
                                         const GValue *value1,
                                         const GValue *value2);
 };
-struct _GParamSpec
-{
-  GTypeInstance  g_instance;
-
-  gchar         *name;
-  gchar         *nick;
-  gchar         *blurb;
-  GParamFlags    flags;
-
-  /*< private >*/
-  GType                 owner_type;
-  GData                *qdata;
-  guint          ref_count;
-};
 
 
 /* --- prototypes --- */
 GParamSpec*    g_param_spec_ref                (GParamSpec    *pspec);
 void           g_param_spec_unref              (GParamSpec    *pspec);
+void           g_param_spec_sink               (GParamSpec    *pspec);
 gpointer        g_param_spec_get_qdata         (GParamSpec    *pspec,
                                                 GQuark         quark);
 void            g_param_spec_set_qdata         (GParamSpec    *pspec,
@@ -111,6 +114,10 @@ gboolean   g_param_value_validate          (GParamSpec    *pspec,
 gint           g_param_values_cmp              (GParamSpec    *pspec,
                                                 const GValue  *value1,
                                                 const GValue  *value2);
+void            g_value_set_param               (GValue               *value,
+                                                GParamSpec    *param);
+GParamSpec*     g_value_get_param               (const GValue  *value);
+GParamSpec*     g_value_dup_param               (const GValue  *value);
 
 
 /* --- convenience functions --- */
index 10b8ab3..64b63f0 100644 (file)
@@ -541,6 +541,103 @@ param_string_values_cmp (GParamSpec   *pspec,
 }
 
 static void
+param_spec_param_init (GParamSpec *pspec)
+{
+  GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec);
+  
+  spec->param_type = G_TYPE_PARAM;
+}
+
+static void
+param_param_set_default (GParamSpec *pspec,
+                        GValue     *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static gboolean
+param_param_validate (GParamSpec *pspec,
+                     GValue     *value)
+{
+  GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec);
+  GParamSpec *param = value->data[0].v_pointer;
+  guint changed = 0;
+  
+  if (param && !g_type_is_a (G_PARAM_SPEC_TYPE (param), spec->param_type))
+    {
+      g_param_spec_unref (param);
+      value->data[0].v_pointer = NULL;
+      changed++;
+    }
+  
+  return changed;
+}
+
+static void
+param_spec_pointer_init (GParamSpec *pspec)
+{
+  /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
+}
+
+static void
+param_pointer_set_default (GParamSpec *pspec,
+                          GValue     *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static gboolean
+param_pointer_validate (GParamSpec *pspec,
+                       GValue     *value)
+{
+  /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
+  guint changed = 0;
+  
+  return changed;
+}
+
+static gint
+param_pointer_values_cmp (GParamSpec   *pspec,
+                         const GValue *value1,
+                         const GValue *value2)
+{
+  return value1->data[0].v_pointer != value2->data[0].v_pointer;
+}
+
+static void
+param_spec_ccallback_init (GParamSpec *pspec)
+{
+  /* GParamSpecCCallback *spec = G_PARAM_SPEC_CCALLBACK (pspec); */
+}
+
+static void
+param_ccallback_set_default (GParamSpec *pspec,
+                            GValue     *value)
+{
+  value->data[0].v_pointer = NULL;
+  value->data[1].v_pointer = NULL;
+}
+
+static gboolean
+param_ccallback_validate (GParamSpec *pspec,
+                         GValue     *value)
+{
+  /* GParamSpecCCallback *spec = G_PARAM_SPEC_CCALLBACK (pspec); */
+  guint changed = 0;
+  
+  return changed;
+}
+
+static gint
+param_ccallback_values_cmp (GParamSpec   *pspec,
+                           const GValue *value1,
+                           const GValue *value2)
+{
+  return (value1->data[0].v_pointer != value2->data[0].v_pointer ||
+         value1->data[1].v_pointer != value2->data[1].v_pointer);
+}
+
+static void
 param_spec_object_init (GParamSpec *pspec)
 {
   GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
@@ -919,6 +1016,57 @@ g_param_spec_types_init (void)    /* sync with gtype.c */
     g_assert (type == G_TYPE_PARAM_STRING);
   }
   
+  /* G_TYPE_PARAM_PARAM
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecParam),  /* instance_size */
+      16,                        /* n_preallocs */
+      param_spec_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 */
+    };
+    type = g_param_type_register_static ("GParamParam", &pspec_info);
+    g_assert (type == G_TYPE_PARAM_PARAM);
+  }
+  
+  /* G_TYPE_PARAM_POINTER
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecPointer),  /* instance_size */
+      0,                           /* n_preallocs */
+      param_spec_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 ("GParamPointer", &pspec_info);
+    g_assert (type == G_TYPE_PARAM_POINTER);
+  }
+  
+  /* G_TYPE_PARAM_CCALLBACK
+   */
+  {
+    static const GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecCCallback), /* instance_size */
+      0,                            /* n_preallocs */
+      param_spec_ccallback_init,    /* instance_init */
+      G_TYPE_CCALLBACK,                    /* value_type */
+      NULL,                        /* finalize */
+      param_ccallback_set_default,  /* value_set_default */
+      param_ccallback_validate,            /* value_validate */
+      param_ccallback_values_cmp,   /* values_cmp */
+    };
+    type = g_param_type_register_static ("GParamCCallback", &pspec_info);
+    g_assert (type == G_TYPE_PARAM_CCALLBACK);
+  }
+  
   /* G_TYPE_PARAM_OBJECT
    */
   {
@@ -1281,6 +1429,59 @@ g_param_spec_string_c (const gchar *name,
 }
 
 GParamSpec*
+g_param_spec_param (const gchar *name,
+                   const gchar *nick,
+                   const gchar *blurb,
+                   GType        param_type,
+                   GParamFlags  flags)
+{
+  GParamSpecParam *pspec;
+  
+  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);
+  pspec->param_type = param_type;
+  
+  return G_PARAM_SPEC (pspec);
+}
+
+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);
+  return G_PARAM_SPEC (pspec);
+}
+
+GParamSpec*
+g_param_spec_ccallback (const gchar *name,
+                       const gchar *nick,
+                       const gchar *blurb,
+                       GParamFlags  flags)
+{
+  GParamSpecCCallback *cspec;
+  
+  cspec = g_param_spec_internal (G_TYPE_PARAM_CCALLBACK,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+  return G_PARAM_SPEC (cspec);
+}
+
+GParamSpec*
 g_param_spec_object (const gchar *name,
                     const gchar *nick,
                     const gchar *blurb,
index 01219d0..5fb0b00 100644 (file)
@@ -33,48 +33,57 @@ extern "C" {
 
 
 /* --- type macros --- */
-#define G_IS_PARAM_SPEC_CHAR(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CHAR))
-#define G_PARAM_SPEC_CHAR(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CHAR, GParamSpecChar))
-#define G_IS_PARAM_SPEC_UCHAR(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UCHAR))
-#define G_PARAM_SPEC_UCHAR(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UCHAR, GParamSpecUChar))
-#define G_IS_PARAM_SPEC_BOOLEAN(pspec)  (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_BOOLEAN))
-#define G_PARAM_SPEC_BOOLEAN(pspec)     (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_BOOLEAN, GParamSpecBoolean))
-#define G_IS_PARAM_SPEC_INT(pspec)      (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_INT))
-#define G_PARAM_SPEC_INT(pspec)         (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_INT, GParamSpecInt))
-#define G_IS_PARAM_SPEC_UINT(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UINT))
-#define G_PARAM_SPEC_UINT(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UINT, GParamSpecUInt))
-#define G_IS_PARAM_SPEC_LONG(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_LONG))
-#define G_PARAM_SPEC_LONG(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_LONG, GParamSpecLong))
-#define G_IS_PARAM_SPEC_ULONG(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ULONG))
-#define G_PARAM_SPEC_ULONG(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ULONG, GParamSpecULong))
-#define G_IS_PARAM_SPEC_ENUM(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ENUM))
-#define G_PARAM_SPEC_ENUM(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ENUM, GParamSpecEnum))
-#define G_IS_PARAM_SPEC_FLAGS(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLAGS))
-#define G_PARAM_SPEC_FLAGS(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLAGS, GParamSpecFlags))
-#define G_IS_PARAM_SPEC_FLOAT(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLOAT))
-#define G_PARAM_SPEC_FLOAT(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLOAT, GParamSpecFloat))
-#define G_IS_PARAM_SPEC_DOUBLE(pspec)   (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_DOUBLE))
-#define G_PARAM_SPEC_DOUBLE(pspec)      (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_DOUBLE, GParamSpecDouble))
-#define G_IS_PARAM_SPEC_STRING(pspec)   (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_STRING))
-#define G_PARAM_SPEC_STRING(pspec)      (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_STRING, GParamSpecString))
-#define G_IS_PARAM_SPEC_OBJECT(pspec)   (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT))
-#define G_PARAM_SPEC_OBJECT(pspec)      (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject))
+#define G_IS_PARAM_SPEC_CHAR(pspec)      (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CHAR))
+#define G_PARAM_SPEC_CHAR(pspec)         (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CHAR, GParamSpecChar))
+#define G_IS_PARAM_SPEC_UCHAR(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UCHAR))
+#define G_PARAM_SPEC_UCHAR(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UCHAR, GParamSpecUChar))
+#define G_IS_PARAM_SPEC_BOOLEAN(pspec)   (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_BOOLEAN))
+#define G_PARAM_SPEC_BOOLEAN(pspec)      (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_BOOLEAN, GParamSpecBoolean))
+#define G_IS_PARAM_SPEC_INT(pspec)       (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_INT))
+#define G_PARAM_SPEC_INT(pspec)          (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_INT, GParamSpecInt))
+#define G_IS_PARAM_SPEC_UINT(pspec)      (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_UINT))
+#define G_PARAM_SPEC_UINT(pspec)         (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_UINT, GParamSpecUInt))
+#define G_IS_PARAM_SPEC_LONG(pspec)      (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_LONG))
+#define G_PARAM_SPEC_LONG(pspec)         (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_LONG, GParamSpecLong))
+#define G_IS_PARAM_SPEC_ULONG(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ULONG))
+#define G_PARAM_SPEC_ULONG(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ULONG, GParamSpecULong))
+#define G_IS_PARAM_SPEC_ENUM(pspec)      (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_ENUM))
+#define G_PARAM_SPEC_ENUM(pspec)         (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_ENUM, GParamSpecEnum))
+#define G_IS_PARAM_SPEC_FLAGS(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLAGS))
+#define G_PARAM_SPEC_FLAGS(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLAGS, GParamSpecFlags))
+#define G_IS_PARAM_SPEC_FLOAT(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_FLOAT))
+#define G_PARAM_SPEC_FLOAT(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_FLOAT, GParamSpecFloat))
+#define G_IS_PARAM_SPEC_DOUBLE(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_DOUBLE))
+#define G_PARAM_SPEC_DOUBLE(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_DOUBLE, GParamSpecDouble))
+#define G_IS_PARAM_SPEC_STRING(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_STRING))
+#define G_PARAM_SPEC_STRING(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_STRING, GParamSpecString))
+#define G_IS_PARAM_SPEC_PARAM(pspec)     (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_PARAM))
+#define G_PARAM_SPEC_PARAM(pspec)        (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_PARAM, GParamSpecParam))
+#define G_IS_PARAM_SPEC_POINTER(pspec)   (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_POINTER))
+#define G_PARAM_SPEC_POINTER(pspec)      (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_POINTER, GParamSpecPointer))
+#define G_IS_PARAM_SPEC_CCALLBACK(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_CCALLBACK))
+#define G_PARAM_SPEC_CCALLBACK(pspec)    (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_CCALLBACK, GParamSpecCCallback))
+#define G_IS_PARAM_SPEC_OBJECT(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT))
+#define G_PARAM_SPEC_OBJECT(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject))
 
 
 /* --- typedefs & structures --- */
-typedef struct _GParamSpecChar    GParamSpecChar;
-typedef struct _GParamSpecUChar   GParamSpecUChar;
-typedef struct _GParamSpecBoolean GParamSpecBoolean;
-typedef struct _GParamSpecInt     GParamSpecInt;
-typedef struct _GParamSpecUInt    GParamSpecUInt;
-typedef struct _GParamSpecLong    GParamSpecLong;
-typedef struct _GParamSpecULong   GParamSpecULong;
-typedef struct _GParamSpecEnum    GParamSpecEnum;
-typedef struct _GParamSpecFlags   GParamSpecFlags;
-typedef struct _GParamSpecFloat   GParamSpecFloat;
-typedef struct _GParamSpecDouble  GParamSpecDouble;
-typedef struct _GParamSpecString  GParamSpecString;
-typedef struct _GParamSpecObject  GParamSpecObject;
+typedef struct _GParamSpecChar      GParamSpecChar;
+typedef struct _GParamSpecUChar     GParamSpecUChar;
+typedef struct _GParamSpecBoolean   GParamSpecBoolean;
+typedef struct _GParamSpecInt       GParamSpecInt;
+typedef struct _GParamSpecUInt      GParamSpecUInt;
+typedef struct _GParamSpecLong      GParamSpecLong;
+typedef struct _GParamSpecULong     GParamSpecULong;
+typedef struct _GParamSpecEnum      GParamSpecEnum;
+typedef struct _GParamSpecFlags     GParamSpecFlags;
+typedef struct _GParamSpecFloat     GParamSpecFloat;
+typedef struct _GParamSpecDouble    GParamSpecDouble;
+typedef struct _GParamSpecString    GParamSpecString;
+typedef struct _GParamSpecParam     GParamSpecParam;
+typedef struct _GParamSpecPointer   GParamSpecPointer;
+typedef struct _GParamSpecCCallback GParamSpecCCallback;
+typedef struct _GParamSpecObject    GParamSpecObject;
 struct _GParamSpecChar
 {
   GParamSpec    parent_instance;
@@ -172,6 +181,20 @@ struct _GParamSpecString
   guint         null_fold_if_empty : 1;
   guint         ensure_non_null : 1;
 };
+struct _GParamSpecParam
+{
+  GParamSpec    parent_instance;
+  
+  GType         param_type;
+};
+struct _GParamSpecPointer
+{
+  GParamSpec    parent_instance;
+};
+struct _GParamSpecCCallback
+{
+  GParamSpec    parent_instance;
+};
 struct _GParamSpecObject
 {
   GParamSpec    parent_instance;
@@ -264,6 +287,19 @@ GParamSpec*     g_param_spec_string_c   (const gchar    *name,
                                          const gchar    *blurb,
                                          const gchar    *default_value,
                                          GParamFlags     flags);
+GParamSpec*     g_param_spec_param      (const gchar    *name,
+                                         const gchar    *nick,
+                                         const gchar    *blurb,
+                                         GType           param_type,
+                                         GParamFlags     flags);
+GParamSpec*     g_param_spec_pointer    (const gchar    *name,
+                                         const gchar    *nick,
+                                         const gchar    *blurb,
+                                         GParamFlags     flags);
+GParamSpec*     g_param_spec_ccallback  (const gchar    *name,
+                                         const gchar    *nick,
+                                         const gchar    *blurb,
+                                         GParamFlags     flags);
 GParamSpec*     g_param_spec_object     (const gchar    *name,
                                          const gchar    *nick,
                                          const gchar    *blurb,
index b5ce638..dc93b5a 100644 (file)
 #include <string.h> 
 
 #include        "gsignal.h"
-
 #include        "gbsearcharray.h"
+#include        "gvaluecollector.h"
 
 
 /* pre allocation configurations
  */
+#define        MAX_STACK_VALUES        (16)
 #define BSA_PRE_ALLOC           (20)
 #define HANDLER_PRE_ALLOC       (48)
 #define EMISSION_PRE_ALLOC      (16)
@@ -131,7 +132,7 @@ static inline Emission*             emission_find           (Emission        *emission_list,
                                                         guint            signal_id,
                                                         GQuark           detail,
                                                         gpointer         instance);
-static       void              signal_emit_R           (SignalNode      *node,
+static       gboolean          signal_emit_R           (SignalNode      *node,
                                                         GQuark           detail,
                                                         gpointer         instance,
                                                         GValue          *return_value,
@@ -233,21 +234,43 @@ static inline guint
 signal_id_lookup (GQuark quark,
                  GType  itype)
 {
+  GType *ifaces, type = itype;
+  SignalKey key;
+  guint n_ifaces;
+
+  key.quark = quark;
+
+  /* try looking up signals for this type and its anchestors */
   do
     {
-      SignalKey key, *signal_key;
-      
-      key.itype = itype;
-      key.quark = quark;
+      SignalKey *signal_key;
       
+      key.itype = type;
       signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
       
       if (signal_key)
        return signal_key->signal_id;
       
-      itype = g_type_parent (itype);
+      type = g_type_parent (type);
     }
-  while (itype);
+  while (type);
+
+  /* no luck, try interfaces it exports */
+  ifaces = g_type_interfaces (itype, &n_ifaces);
+  while (n_ifaces--)
+    {
+      SignalKey *signal_key;
+
+      key.itype = ifaces[n_ifaces];
+      signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
+
+      if (signal_key)
+       {
+         g_free (ifaces);
+         return signal_key->signal_id;
+       }
+    }
+  g_free (ifaces);
   
   return 0;
 }
@@ -515,7 +538,7 @@ handler_insert (guint    signal_id,
 {
   HandlerList *hlist;
   
-  g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
+  g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
   
   hlist = handler_list_ensure (signal_id, instance);
   if (!hlist->handlers)
@@ -671,7 +694,7 @@ g_signal_stop_emission (gpointer instance,
       G_UNLOCK (g_signal_mutex);
       return;
     }
-  if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
+  if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
     {
       Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
       Emission *emission = emission_find (emission_list, signal_id, detail, instance);
@@ -860,6 +883,44 @@ g_signal_list_ids (GType  itype,
 }
 
 guint
+g_signal_new (const gchar       *signal_name,
+             GType              itype,
+             GSignalFlags       signal_flags,
+             GClosure          *class_closure,
+             GSignalAccumulator accumulator,
+             GSignalCMarshaller c_marshaller,
+             GType              return_type,
+             guint              n_params,
+             ...)
+{
+  GType *param_types;
+  guint i;
+  va_list args;
+  guint signal_id;
+
+  if (n_params > 0)
+    {
+      param_types = g_new (GType, n_params);
+
+      va_start (args, n_params);
+
+      for (i = 0; i < n_params; i++)
+       param_types[i] = va_arg (args, GType);
+
+      va_end (args);
+    }
+  else
+    param_types = NULL;
+
+  signal_id = g_signal_newv (signal_name, itype, signal_flags,
+                            class_closure, accumulator, c_marshaller,
+                            return_type, n_params, param_types);
+  g_free (param_types);
+
+  return signal_id;
+}
+
+guint
 g_signal_newv (const gchar       *signal_name,
                GType              itype,
                GSignalFlags       signal_flags,
@@ -1023,22 +1084,23 @@ g_signal_connect_closure_by_id (gpointer  instance,
   
   G_LOCK (g_signal_mutex);
   node = LOOKUP_SIGNAL_NODE (signal_id);
-  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
+  if (node)
     {
-      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
-      G_UNLOCK (g_signal_mutex);
-      return 0;
-    }
-  if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
-    {
-      Handler *handler = handler_new (after);
-      
-      handler_id = handler->id;
-      handler->detail = detail;
-      handler->closure = g_closure_ref (closure);
-      handler_insert (signal_id, instance, handler);
-      if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
-       g_closure_set_marshal (closure, node->c_marshaller);
+      if (detail && !(node->flags & G_SIGNAL_DETAILED))
+       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
+      else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
+       g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
+      else
+       {
+         Handler *handler = handler_new (after);
+         
+         handler_id = handler->id;
+         handler->detail = detail;
+         handler->closure = g_closure_ref (closure);
+         handler_insert (signal_id, instance, handler);
+         if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
+           g_closure_set_marshal (closure, node->c_marshaller);
+       }
     }
   else
     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
@@ -1047,6 +1109,97 @@ g_signal_connect_closure_by_id (gpointer  instance,
   return handler_id;
 }
 
+guint
+g_signal_connect_closure (gpointer     instance,
+                         const gchar *detailed_signal,
+                         GClosure    *closure,
+                         gboolean     after)
+{
+  guint signal_id, handler_id = 0;
+  GQuark detail = 0;
+  GType itype;
+
+  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
+  g_return_val_if_fail (detailed_signal != NULL, 0);
+  g_return_val_if_fail (closure != NULL, 0);
+
+  G_LOCK (g_signal_mutex);
+  itype = G_TYPE_FROM_INSTANCE (instance);
+  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
+  if (signal_id)
+    {
+      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
+
+      if (detail && !(node->flags & G_SIGNAL_DETAILED))
+       g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
+      else if (!g_type_is_a (itype, node->itype))
+       g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
+      else
+       {
+         Handler *handler = handler_new (after);
+
+         handler_id = handler->id;
+         handler->detail = detail;
+         handler->closure = g_closure_ref (closure);
+         handler_insert (signal_id, instance, handler);
+         if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
+           g_closure_set_marshal (handler->closure, node->c_marshaller);
+       }
+    }
+  else
+    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
+  G_UNLOCK (g_signal_mutex);
+
+  return handler_id;
+}
+
+guint
+g_signal_connect_data (gpointer       instance,
+                      const gchar   *detailed_signal,
+                      GCallback      c_handler,
+                      gpointer       data,
+                      GClosureNotify destroy_data,
+                      gboolean       swapped,
+                      gboolean       after)
+{
+  guint signal_id, handler_id = 0;
+  GQuark detail = 0;
+  GType itype;
+
+  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
+  g_return_val_if_fail (detailed_signal != NULL, 0);
+  g_return_val_if_fail (c_handler != NULL, 0);
+
+  G_LOCK (g_signal_mutex);
+  itype = G_TYPE_FROM_INSTANCE (instance);
+  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
+  if (signal_id)
+    {
+      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
+
+      if (detail && !(node->flags & G_SIGNAL_DETAILED))
+       g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
+      else if (!g_type_is_a (itype, node->itype))
+       g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
+      else
+       {
+         Handler *handler = handler_new (after);
+
+         handler_id = handler->id;
+         handler->detail = detail;
+         handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
+         handler_insert (signal_id, instance, handler);
+         if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
+           g_closure_set_marshal (handler->closure, node->c_marshaller);
+       }
+    }
+  else
+    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
+  G_UNLOCK (g_signal_mutex);
+
+  return handler_id;
+}
+
 void
 g_signal_handler_block (gpointer instance,
                         guint    handler_id)
@@ -1342,27 +1495,27 @@ g_signal_emitv (const GValue *instance_and_params,
                GQuark        detail,
                GValue       *return_value)
 {
-  SignalNode *node;
-  gpointer instance;
   const GValue *param_values;
+  gpointer instance;
+  SignalNode *node;
   guint i;
   
   g_return_if_fail (instance_and_params != NULL);
   instance = g_value_get_as_pointer (instance_and_params);
   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
   g_return_if_fail (signal_id > 0);
-  
+
   param_values = instance_and_params + 1;
   
   G_LOCK (g_signal_mutex);
   node = LOOKUP_SIGNAL_NODE (signal_id);
-#ifndef G_DISABLE_CHECKS
-  if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
+  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
     {
       g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
       G_UNLOCK (g_signal_mutex);
       return;
     }
+#ifndef G_DISABLE_CHECKS
   if (detail && !(node->flags & G_SIGNAL_DETAILED))
     {
       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
@@ -1372,7 +1525,8 @@ g_signal_emitv (const GValue *instance_and_params,
   for (i = 0; i < node->n_params; i++)
     if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
       {
-       g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
+       g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
+                   G_STRLOC,
                    g_type_name (node->param_types[i]),
                    i,
                    node->name,
@@ -1384,7 +1538,8 @@ g_signal_emitv (const GValue *instance_and_params,
     {
       if (!return_value)
        {
-         g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
+         g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
+                     G_STRLOC,
                      g_type_name (node->return_type),
                      node->name);
          G_UNLOCK (g_signal_mutex);
@@ -1392,7 +1547,8 @@ g_signal_emitv (const GValue *instance_and_params,
        }
       else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
        {
-         g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
+         g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
+                     G_STRLOC,
                      g_type_name (node->return_type),
                      node->name,
                      G_VALUE_TYPE_NAME (return_value));
@@ -1403,13 +1559,147 @@ g_signal_emitv (const GValue *instance_and_params,
   else
     return_value = NULL;
 #endif /* !G_DISABLE_CHECKS */
-  
+
   signal_emit_R (node, detail, instance, return_value, instance_and_params);
-  
   G_UNLOCK (g_signal_mutex);
 }
 
-static void
+void
+g_signal_emit_valist (gpointer instance,
+                     guint    signal_id,
+                     GQuark   detail,
+                     va_list  var_args)
+{
+  GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
+  GValue *param_values;
+  SignalNode *node;
+  guint i;
+
+  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
+  g_return_if_fail (signal_id > 0);
+
+  G_LOCK (g_signal_mutex);
+  node = LOOKUP_SIGNAL_NODE (signal_id);
+  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
+    {
+      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
+      G_UNLOCK (g_signal_mutex);
+      return;
+    }
+#ifndef G_DISABLE_CHECKS
+  if (detail && !(node->flags & G_SIGNAL_DETAILED))
+    {
+      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
+      G_UNLOCK (g_signal_mutex);
+      return;
+    }
+#endif  /* !G_DISABLE_CHECKS */
+
+  if (node->n_params < MAX_STACK_VALUES)
+    instance_and_params = stack_values;
+  else
+    {
+      free_me = g_new (GValue, node->n_params + 1);
+      instance_and_params = free_me;
+    }
+  param_values = instance_and_params + 1;
+  for (i = 0; i < node->n_params; i++)
+    {
+      gchar *error;
+
+      param_values[i].g_type = 0;
+      g_value_init (param_values + i, node->param_types[i]);
+      G_VALUE_COLLECT (param_values + i, 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
+          */
+         while (i--)
+           g_value_unset (param_values + i);
+
+         G_UNLOCK (g_signal_mutex);
+         g_free (free_me);
+         return;
+       }
+    }
+  instance_and_params->g_type = 0;
+  g_value_init (instance_and_params, node->itype);
+  g_value_set_instance (instance_and_params, instance);
+  if (node->return_type == G_TYPE_NONE)
+    signal_emit_R (node, detail, instance, NULL, instance_and_params);
+  else
+    {
+      GValue return_value = { 0, };
+      gchar *error = NULL;
+
+      g_value_init (&return_value, node->return_type);
+      if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
+       G_VALUE_LCOPY (&return_value, var_args, &error);
+      if (!error)
+       g_value_unset (&return_value);
+      else
+       {
+         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
+          */
+       }
+    }
+  for (i = 0; i < node->n_params; i++)
+    g_value_unset (param_values + i);
+  g_value_unset (instance_and_params);
+  if (free_me)
+    g_free (free_me);
+  G_UNLOCK (g_signal_mutex);
+}
+
+void
+g_signal_emit (gpointer instance,
+              guint    signal_id,
+              GQuark   detail,
+              ...)
+{
+  va_list var_args;
+
+  va_start (var_args, detail);
+  g_signal_emit_valist (instance, signal_id, detail, var_args);
+  va_end (var_args);
+}
+
+void
+g_signal_emit_by_name (gpointer     instance,
+                      const gchar *detailed_signal,
+                      ...)
+{
+  GQuark detail = 0;
+  guint signal_id;
+
+  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
+  g_return_if_fail (detailed_signal != NULL);
+
+  G_LOCK (g_signal_mutex);
+  signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
+  G_UNLOCK (g_signal_mutex);
+
+  if (signal_id)
+    {
+      va_list var_args;
+
+      va_start (var_args, detailed_signal);
+      g_signal_emit_valist (instance, signal_id, detail, var_args);
+      va_end (var_args);
+    }
+  else
+    g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
+}
+
+static gboolean
 signal_emit_R (SignalNode   *node,
               GQuark        detail,
               gpointer      instance,
@@ -1422,9 +1712,10 @@ signal_emit_R (SignalNode   *node,
   GClosure *class_closure;
   HandlerList *hlist;
   Handler *handler_list = NULL;
-  GValue accu;
+  GValue accu = { 0, };
   gboolean accu_used = FALSE;
   guint signal_id = node->signal_id;
+  gboolean return_value_altered = FALSE;
   
   if (node->flags & G_SIGNAL_NO_RECURSE)
     {
@@ -1433,18 +1724,14 @@ signal_emit_R (SignalNode   *node,
       if (emission)
        {
          *emission->state_p = EMISSION_RESTART;
-         return;
+         return return_value_altered;
        }
     }
   ihint.signal_id = node->signal_id;
   ihint.detail = detail;
   accumulator = node->accumulator;
   if (accumulator)
-    {
-      G_UNLOCK (g_signal_mutex);
-      g_value_init (&accu, node->return_type);
-      G_LOCK (g_signal_mutex);
-    }
+    g_value_init (&accu, node->return_type);
   emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
                 signal_id, detail, instance, &emission_state);
   class_closure = node->class_closure;
@@ -1486,6 +1773,7 @@ signal_emit_R (SignalNode   *node,
                          instance_and_params,
                          &ihint);
       G_LOCK (g_signal_mutex);
+      return_value_altered = TRUE;
       
       if (emission_state == EMISSION_STOP)
        goto EMIT_CLEANUP;
@@ -1545,6 +1833,7 @@ signal_emit_R (SignalNode   *node,
                                  instance_and_params,
                                  &ihint);
              G_LOCK (g_signal_mutex);
+             return_value_altered = TRUE;
              
              tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
            }
@@ -1593,6 +1882,7 @@ signal_emit_R (SignalNode   *node,
                          instance_and_params,
                          &ihint);
       G_LOCK (g_signal_mutex);
+      return_value_altered = TRUE;
       
       if (emission_state == EMISSION_STOP)
        goto EMIT_CLEANUP;
@@ -1634,6 +1924,7 @@ signal_emit_R (SignalNode   *node,
                                  instance_and_params,
                                  &ihint);
              G_LOCK (g_signal_mutex);
+             return_value_altered = TRUE;
              
              tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
            }
@@ -1692,9 +1983,12 @@ signal_emit_R (SignalNode   *node,
   
   emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
   if (accumulator)
-    {
-      G_UNLOCK (g_signal_mutex);
-      g_value_unset (&accu);
-      G_LOCK (g_signal_mutex);
-    }
+    g_value_unset (&accu);
+
+  return return_value_altered;
 }
+
+
+/* compile standard marshallers */
+#include       "gvaluetypes.h"
+#include        "gmarshal.c"
index 9d2c5ca..d054595 100644 (file)
@@ -23,6 +23,7 @@
 #include       <gobject/gclosure.h>
 #include       <gobject/gvalue.h>
 #include       <gobject/gparam.h>
+#include       <gobject/gmarshal.h>
 
 
 #ifdef __cplusplus
@@ -86,9 +87,18 @@ struct _GSignalQuery
 
 
 /* --- signals --- */
+guint  g_signal_new                          (const gchar       *signal_name,
+                                              GType              itype,
+                                              GSignalFlags       signal_flags,
+                                              GClosure          *class_closure,
+                                              GSignalAccumulator accumulator,
+                                              GSignalCMarshaller c_marshaller,
+                                              GType              return_type,
+                                              guint              n_params,
+                                              ...);
 guint  g_signal_newv                         (const gchar       *signal_name,
                                               GType              itype,
-                                              GSignalFlags        signal_flags,
+                                              GSignalFlags       signal_flags,
                                               GClosure          *class_closure,
                                               GSignalAccumulator accumulator,
                                               GSignalCMarshaller c_marshaller,
@@ -99,6 +109,17 @@ void        g_signal_emitv                        (const GValue      *instance_and_params,
                                               guint              signal_id,
                                               GQuark             detail,
                                               GValue            *return_value);
+void   g_signal_emit_valist                  (gpointer           instance,
+                                              guint              signal_id,
+                                              GQuark             detail,
+                                              va_list            var_args);
+void   g_signal_emit                         (gpointer           instance,
+                                              guint              signal_id,
+                                              GQuark             detail,
+                                              ...);
+void   g_signal_emit_by_name                 (gpointer           instance,
+                                              const gchar       *detailed_signal,
+                                              ...);
 guint  g_signal_lookup                       (const gchar       *name,
                                               GType              itype);
 gchar* g_signal_name                         (guint              signal_id);
@@ -127,6 +148,17 @@ guint       g_signal_connect_closure_by_id       (gpointer           instance,
                                               GQuark             detail,
                                               GClosure          *closure,
                                               gboolean           after);
+guint   g_signal_connect_closure             (gpointer           instance,
+                                              const gchar       *detailed_signal,
+                                              GClosure          *closure,
+                                              gboolean           after);
+guint   g_signal_connect_data                (gpointer           instance,
+                                              const gchar       *detailed_signal,
+                                              GCallback          c_handler,
+                                              gpointer           data,
+                                              GClosureNotify     destroy_data,
+                                              gboolean           swapped,
+                                              gboolean           after);
 void    g_signal_handler_block               (gpointer           instance,
                                               guint              handler_id);
 void    g_signal_handler_unblock             (gpointer           instance,
index 7924d87..42842dd 100644 (file)
@@ -21,7 +21,7 @@
 #include       "gtypeplugin.h"
 #include       <string.h>
 
-#define FIXME_DISABLE_PREALLOCATIONS
+#undef FIXME_DISABLE_PREALLOCATIONS
 
 /* NOTE: some functions (some internal variants and exported ones)
  * invalidate data portions of the TypeNodes. if external functions/callbacks
@@ -173,7 +173,7 @@ static GQuark          quark_type_flags = 0;
 
 
 /* --- externs --- */
-const char  *g_log_domain_gobject = "GLib-Object";
+const char  *g_log_domain_gruntime = "GRuntime";
 
 
 /* --- type nodes --- */
@@ -796,7 +796,7 @@ type_data_make (TypeNode              *node,
     *vtable = *value_table;
   node->data->common.value_table = vtable;
 
-  g_assert (node->data->common.value_table != NULL); /* FIXME: paranoid */
+  g_assert (node->data->common.value_table != NULL); /* paranoid */
 }
 
 static inline void
@@ -1024,7 +1024,7 @@ g_type_free_instance (GTypeInstance *instance)
     }
 
   instance->g_class = NULL;
-  memset (instance, 0xaa, node->data->instance.instance_size); // FIXME
+  memset (instance, 0xaa, node->data->instance.instance_size); // FIXME: debugging hack
   if (node->data->instance.n_preallocs)
     g_chunk_free (instance, node->data->instance.mem_chunk);
   else
@@ -1667,6 +1667,7 @@ g_type_next_base (GType type,
   return 0;
 }
 
+#if 0
 gboolean
 g_type_is_a (GType type,
             GType is_a_type)
@@ -1688,10 +1689,11 @@ g_type_is_a (GType type,
 
   return FALSE;
 }
+#endif
 
 gboolean
-g_type_conforms_to (GType type,
-                   GType iface_type)
+g_type_is_a (GType type,
+            GType iface_type)
 {
   if (type != iface_type)
     {
@@ -1807,7 +1809,7 @@ g_type_get_qdata (GType  type,
       QData *qdatas = gdata->qdatas - 1;
       guint n_qdatas = gdata->n_qdatas;
 
-      do                /* FIXME: should optimize qdata lookups for <= 4 */
+      do
        {
          guint i;
          QData *check;
@@ -1943,12 +1945,12 @@ g_type_fundamental_last (void)
 }
 
 gboolean
-g_type_instance_conforms_to (GTypeInstance *type_instance,
-                            GType          iface_type)
+g_type_instance_is_a (GTypeInstance *type_instance,
+                     GType          iface_type)
 {
   return (type_instance && type_instance->g_class &&
          G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type) &&
-         g_type_conforms_to (type_instance->g_class->g_type, iface_type));
+         g_type_is_a (type_instance->g_class->g_type, iface_type));
 }
 
 gboolean
@@ -1960,8 +1962,8 @@ g_type_class_is_a (GTypeClass *type_class,
 }
 
 gboolean
-g_type_value_conforms_to (GValue *value,
-                         GType   type)
+g_type_value_is_a (GValue *value,
+                  GType   type)
 {
   TypeNode *node;
   
@@ -1974,7 +1976,7 @@ g_type_value_conforms_to (GValue *value,
 #endif
   if (!node || !node->data || node->data->common.ref_count < 1 ||
       !node->data->common.value_table->value_init ||
-      !g_type_conforms_to (value->g_type, type))
+      !g_type_is_a (value->g_type, type))
     return FALSE;
   
   return TRUE;
@@ -1983,7 +1985,7 @@ g_type_value_conforms_to (GValue *value,
 gboolean
 g_type_check_value (GValue *value)
 {
-  return value && g_type_value_conforms_to (value, value->g_type);
+  return value && g_type_value_is_a (value, value->g_type);
 }
 
 GTypeInstance*
@@ -2009,7 +2011,7 @@ g_type_check_instance_cast (GTypeInstance *type_instance,
                 type_descriptive_name (iface_type));
       return type_instance;
     }
-  if (!g_type_conforms_to (type_instance->g_class->g_type, iface_type))
+  if (!g_type_is_a (type_instance->g_class->g_type, iface_type))
     {
       g_warning ("invalid cast from `%s' to `%s'",
                 type_descriptive_name (type_instance->g_class->g_type),
@@ -2125,7 +2127,7 @@ g_type_init (void)
   memset (&info, 0, sizeof (info));
   node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
   type = NODE_TYPE (node);
-  type_data_make (node, &info, NULL); /* FIXME */
+  type_data_make (node, &info, NULL);
   g_assert (type == G_TYPE_INTERFACE);
 
   /* G_TYPE_TYPE_PLUGIN
index 89ecd96..bbbf36b 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef __G_TYPE_H__
 #define __G_TYPE_H__
 
-extern const char *g_log_domain_gobject;
+extern const char *g_log_domain_gruntime;
 #include        <glib.h>
 
 
@@ -62,6 +62,7 @@ typedef enum    /*< skip >*/
   G_TYPE_PARAM,
   G_TYPE_BOXED,
   G_TYPE_POINTER,
+  G_TYPE_CCALLBACK,
   G_TYPE_OBJECT,
 
   /* the following reserved ids should vanish soon */
@@ -79,7 +80,6 @@ typedef enum    /*< skip >*/
   G_TYPE_LAST_RESERVED_FUNDAMENTAL,
 
   /* derived type ids */
-  /* FIXME: G_TYPE_PARAM_INTERFACE */
   G_TYPE_PARAM_CHAR             = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 1),
   G_TYPE_PARAM_UCHAR            = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 2),
   G_TYPE_PARAM_BOOLEAN          = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 3),
@@ -92,8 +92,10 @@ typedef enum    /*< skip >*/
   G_TYPE_PARAM_FLOAT            = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 10),
   G_TYPE_PARAM_DOUBLE           = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 11),
   G_TYPE_PARAM_STRING           = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 12),
-  /* FIXME: G_TYPE_PARAM_PARAM */
-  G_TYPE_PARAM_OBJECT           = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 13)
+  G_TYPE_PARAM_PARAM            = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 13),
+  G_TYPE_PARAM_POINTER          = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 14),
+  G_TYPE_PARAM_CCALLBACK        = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 15),
+  G_TYPE_PARAM_OBJECT           = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 16)
 } GTypeFundamentals;
 
 
@@ -174,8 +176,6 @@ GType    g_type_next_base               (GType                   type,
                                          GType                   base_type);
 gboolean g_type_is_a                    (GType                   type,
                                          GType                   is_a_type);
-gboolean g_type_conforms_to             (GType                   type,
-                                         GType                   iface_type);
 guint    g_type_fundamental_branch_last (GType                   type);
 gpointer g_type_class_ref               (GType                   type);
 gpointer g_type_class_peek              (GType                   type);
@@ -317,10 +317,10 @@ gboolean         g_type_class_is_a              (GTypeClass         *g_class,
                                                 GType               is_a_type);
 GTypeInstance*   g_type_check_instance_cast     (GTypeInstance      *instance,
                                                 GType               iface_type);
-gboolean         g_type_instance_conforms_to    (GTypeInstance      *instance,
+gboolean         g_type_instance_is_a          (GTypeInstance      *instance,
                                                 GType               iface_type);
 gboolean        g_type_check_value             (GValue             *value);
-gboolean        g_type_value_conforms_to       (GValue             *value,
+gboolean        g_type_value_is_a              (GValue             *value,
                                                 GType               type);
 gboolean        g_type_check_instance          (GTypeInstance      *instance);
 GTypeValueTable* g_type_value_table_peek        (GType              type);
@@ -336,9 +336,9 @@ GTypeValueTable* g_type_value_table_peek        (GType                   type);
 #  define _G_TYPE_CCC(cp, gt, ct)       ((ct*) cp)
 #endif /* G_DISABLE_CAST_CHECKS */
 #define _G_TYPE_CHI(ip)                        (g_type_check_instance ((GTypeInstance*) ip))
-#define _G_TYPE_CIT(ip, gt)             (g_type_instance_conforms_to ((GTypeInstance*) ip, gt))
+#define _G_TYPE_CIT(ip, gt)             (g_type_instance_is_a ((GTypeInstance*) ip, gt))
 #define _G_TYPE_CCT(cp, gt)             (g_type_class_is_a ((GTypeClass*) cp, gt))
-#define _G_TYPE_CVT(vl, gt)             (g_type_value_conforms_to ((GValue*) vl, gt))
+#define _G_TYPE_CVT(vl, gt)             (g_type_value_is_a ((GValue*) vl, gt))
 #define _G_TYPE_CHV(vl)                        (g_type_check_value ((GValue*) vl))
 #define _G_TYPE_IGC(ip, gt, ct)         ((ct*) (((GTypeInstance*) ip)->g_class))
 #define _G_TYPE_IGI(ip, gt, ct)         ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))
index cef7499..858af80 100644 (file)
@@ -406,7 +406,7 @@ g_type_module_add_interface (GTypeModule    *module,
   g_return_if_fail (module != NULL);
   g_return_if_fail (interface_info != NULL);
 
-  if (g_type_conforms_to (instance_type, interface_type))
+  if (g_type_is_a (instance_type, interface_type))
     {
       GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
                                                             interface_type);
index e6a2dbd..466c13d 100644 (file)
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include "gvalue.h"
+#include "gvaluecollector.h"
 
 
 /* --- typedefs & structures --- */
@@ -66,7 +67,7 @@ g_value_copy (const GValue *src_value,
   g_return_if_fail (G_IS_VALUE (src_value));
   g_return_if_fail (G_IS_VALUE (dest_value));
   g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)));
-
+  
   value_table = g_type_value_table_peek (G_VALUE_TYPE (dest_value));
   if (!value_table)
     g_return_if_fail (g_type_value_table_peek (G_VALUE_TYPE (dest_value)) != NULL);
@@ -111,6 +112,54 @@ g_value_get_as_pointer (const GValue *value)
 }
 
 void
+g_value_set_instance (GValue  *value,
+                     gpointer instance)
+{
+  g_return_if_fail (G_IS_VALUE (value));
+  
+  g_value_reset (value);
+  if (instance)
+    {
+      GType g_type = G_VALUE_TYPE (value);
+      GTypeValueTable *value_table = g_type_value_table_peek (g_type);
+      GTypeCValue cvalue = { 0, };
+      guint nth_value = 0;
+      guint collect_type = value_table->collect_type;
+      gchar *error_msg;
+      
+      g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
+      g_return_if_fail (g_type_is_a (G_TYPE_FROM_INSTANCE (instance), G_VALUE_TYPE (value)));
+      g_return_if_fail (value_table->collect_type == G_VALUE_COLLECT_POINTER);
+      
+      cvalue.v_pointer = instance;
+      error_msg = value_table->collect_value (value, nth_value++, &collect_type, &cvalue);
+      
+      /* this shouldn't be triggered, instance types should collect just one pointer,
+       * but since we have to follow the calling conventions for collect_value(),
+       * we can attempt to feed them with 0s if they insist on extra args.
+       */
+      while (collect_type && !error_msg)
+       {
+         memset (&cvalue, 0, sizeof (cvalue));
+         error_msg = value_table->collect_value (value, nth_value++, &collect_type, &cvalue);
+       }
+      
+      if (error_msg)
+       {
+         g_warning ("%s: %s", G_STRLOC, error_msg);
+         g_free (error_msg);
+         
+         /* we purposely leak the value here, it might not be
+          * in a sane state if an error condition occoured
+          */
+         memset (value, 0, sizeof (*value));
+         value->g_type = g_type;
+         value_table->value_init (value);
+       }
+    }
+}
+
+void
 g_value_unset (GValue *value)
 {
   GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
@@ -127,11 +176,12 @@ g_value_unset (GValue *value)
 void
 g_value_reset (GValue *value)
 {
-  GTypeValueTable *value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
+  GTypeValueTable *value_table;
   GType g_type;
   
   g_return_if_fail (G_IS_VALUE (value));
   
+  value_table = g_type_value_table_peek (G_VALUE_TYPE (value));
   g_type = G_VALUE_TYPE (value);
   
   if (value_table->value_free)
index be68eba..364e88a 100644 (file)
@@ -69,6 +69,8 @@ void            g_value_reset         (GValue       *value);
 void            g_value_unset          (GValue       *value);
 gboolean       g_value_fits_pointer    (const GValue *value);
 gpointer       g_value_get_as_pointer  (const GValue *value);
+void           g_value_set_instance    (GValue       *value,
+                                        gpointer      instance);
 
 
 /* --- implementation details --- */
index 7bbdfc0..d85e8d6 100644 (file)
@@ -71,9 +71,8 @@ G_STMT_START {                                                                                \
   g_value_reset (_value);                                                              \
   while (_collect_type && !_error_msg)                                                 \
     {                                                                                  \
-      GTypeCValue _cvalue;                                                             \
+      GTypeCValue _cvalue = { 0, };                                                    \
                                                                                         \
-      memset (&_cvalue, 0, sizeof (_cvalue));                                          \
       switch (_collect_type)                                                           \
        {                                                                               \
        case G_VALUE_COLLECT_INT:                                                       \
@@ -117,9 +116,8 @@ G_STMT_START {                                                                              \
                                                                                         \
   while (_lcopy_type && !_error_msg)                                                   \
     {                                                                                  \
-      GTypeCValue _cvalue;                                                             \
+      GTypeCValue _cvalue = { 0, };                                                    \
                                                                                         \
-      memset (&_cvalue, 0, sizeof (_cvalue));                                          \
       switch (_lcopy_type)                                                             \
        {                                                                               \
        case G_VALUE_COLLECT_INT:                                                       \
index e3406aa..8ead3a5 100644 (file)
@@ -264,7 +264,7 @@ value_string_lcopy_value (const GValue *value,
 static void
 value_pointer_init (GValue *value)
 {
-  value->data[0].v_pointer = 0;
+  value->data[0].v_pointer = NULL;
 }
 
 static void
@@ -309,6 +309,76 @@ value_pointer_lcopy_value (const GValue *value,
   return NULL;
 }
 
+static void
+value_ccallback_init (GValue *value)
+{
+  value->data[0].v_pointer = NULL;
+  value->data[1].v_pointer = NULL;
+}
+
+static void
+value_ccallback_copy (const GValue *src_value,
+                     GValue       *dest_value)
+{
+  dest_value->data[0].v_pointer = src_value->data[0].v_pointer;
+  dest_value->data[1].v_pointer = src_value->data[1].v_pointer;
+}
+
+static gchar*
+value_ccallback_collect_value (GValue      *value,
+                              guint        nth_value,
+                              GType       *collect_type,
+                              GTypeCValue *collect_value)
+{
+  gchar *error = NULL;
+
+  switch (nth_value)
+    {
+    case 0:
+      value->data[0].v_pointer = collect_value->v_pointer;
+      *collect_type = G_VALUE_COLLECT_POINTER;
+      if (!value->data[0].v_pointer)
+       error = g_strconcat ("invalid (NULL) pointer callback function for value type `",
+                            G_VALUE_TYPE_NAME (value),
+                            "'",
+                            NULL);
+      break;
+    case 1:
+      value->data[1].v_pointer = collect_value->v_pointer;
+      *collect_type = 0;
+      break;
+    }
+
+  return error;
+}
+
+static gchar*
+value_ccallback_lcopy_value (const GValue *value,
+                            guint         nth_value,
+                            GType        *collect_type,
+                            GTypeCValue  *collect_value)
+{
+  gpointer *pointer_p = collect_value->v_pointer;
+
+  if (!pointer_p)
+    return g_strdup_printf ("%s location for `%s' passed as NULL",
+                           nth_value ? "data" : "callback",
+                           G_VALUE_TYPE_NAME (value));
+  switch (nth_value)
+    {
+    case 0:
+      *pointer_p = value->data[0].v_pointer;
+      *collect_type = G_VALUE_COLLECT_POINTER;
+      break;
+    case 1:
+      *pointer_p = value->data[1].v_pointer;
+      *collect_type = 0;
+      break;
+    }
+
+  return NULL;
+}
+
 
 /* --- type initialization --- */
 void
@@ -478,6 +548,24 @@ g_value_types_init (void)  /* sync with gtype.c */
     type = g_type_register_fundamental (G_TYPE_POINTER, "gpointer", &info, &finfo, 0);
     g_assert (type == G_TYPE_POINTER);
   }
+
+  /* G_TYPE_CCALLBACK
+   */
+  {
+    static const GTypeValueTable value_table = {
+      value_ccallback_init,          /* value_init */
+      NULL,                          /* value_free */
+      value_ccallback_copy,          /* value_copy */
+      NULL,                          /* value_peek_pointer */
+      G_VALUE_COLLECT_POINTER,       /* collect_type */
+      value_ccallback_collect_value, /* collect_value */
+      G_VALUE_COLLECT_POINTER,       /* lcopy_type */
+      value_ccallback_lcopy_value,   /* lcopy_value */
+    };
+    info.value_table = &value_table;
+    type = g_type_register_fundamental (G_TYPE_CCALLBACK, "GCCallback", &info, &finfo, 0);
+    g_assert (type == G_TYPE_CCALLBACK);
+  }
 }
 
 
@@ -692,3 +780,27 @@ g_value_get_pointer (const GValue *value)
 
   return value->data[0].v_pointer;
 }
+
+void
+g_value_set_ccallback (GValue  *value,
+                      gpointer callback_func,
+                      gpointer callback_data)
+{
+  g_return_if_fail (G_IS_VALUE_CCALLBACK (value));
+  
+  value->data[0].v_pointer = callback_func;
+  value->data[1].v_pointer = callback_data;
+}
+
+void
+g_value_get_ccallback (const GValue *value,
+                      gpointer     *callback_func,
+                      gpointer     *callback_data)
+{
+  g_return_if_fail (G_IS_VALUE_CCALLBACK (value));
+
+  if (callback_func)
+    *callback_func = value->data[0].v_pointer;
+  if (callback_data)
+    *callback_data = value->data[1].v_pointer;
+}
index 9f0b143..a7405cc 100644 (file)
@@ -42,6 +42,7 @@ extern "C" {
 #define G_IS_VALUE_DOUBLE(value)       (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_DOUBLE))
 #define G_IS_VALUE_STRING(value)       (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_STRING))
 #define G_IS_VALUE_POINTER(value)      (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_POINTER))
+#define G_IS_VALUE_CCALLBACK(value)    (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_CCALLBACK))
 
 
 /* --- prototypes --- */
@@ -81,7 +82,12 @@ gchar*               g_value_dup_string              (const GValue   *value);
 void            g_value_set_pointer            (GValue         *value,
                                                 gpointer        v_pointer);
 gpointer        g_value_get_pointer            (const GValue   *value);
-
+void            g_value_set_ccallback          (GValue         *value,
+                                                gpointer        callback_func,
+                                                gpointer        callback_data);
+void            g_value_get_ccallback          (const GValue   *value,
+                                                gpointer       *callback_func,
+                                                gpointer       *callback_data);
 
 
 
index a0f0669..5608e14 100644 (file)
@@ -16,7 +16,7 @@ GLIB_VER = @GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@
 # Nothing much configurable below
 
 INCLUDES = -I .. -I .
-DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gobject
+DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gruntime
 
 BUILD_DLL = ../build-dll
 
index ce8ce8e..b804ace 100644 (file)
@@ -13,7 +13,7 @@ GLIB_VER = @GLIB_MAJOR_VERSION@.@GLIB_MINOR_VERSION@
 # Nothing much configurable below
 
 INCLUDES = -I .. -I .
-DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gobject
+DEFINES = -DHAVE_CONFIG_H -DGOBJECT_COMPILATION -DG_LOG_DOMAIN=g_log_domain_gruntime
 
 all :                          \
        gobject-$(GLIB_VER).dll \