, 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
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
@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.
@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.
@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.
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 ##### -->
@func:
@prefix:
@cache:
-@strncmp_func:
<!-- ##### FUNCTION g_completion_new ##### -->
<para>
@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.
-<!-- ##### 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 ##### -->
</para>
@utf8string:
-@error:
@Returns:
-
-
-<!-- ##### FUNCTION g_locale_from_utf8 ##### -->
-<para>
-
-</para>
-
-@utf8string:
+<!-- # Unused Parameters # -->
@error:
-@Returns:
<!-- ##### ENUM GConvertError ##### -->
@G_CONVERT_ERROR_NO_CONVERSION:
@G_CONVERT_ERROR_ILLEGAL_SEQUENCE:
@G_CONVERT_ERROR_FAILED:
-@G_CONVERT_ERROR_PARTIAL_INPUT:
@Returns:
-<!-- ##### FUNCTION g_mkstemp ##### -->
-<para>
-
-</para>
-
-@tmpl:
-@Returns:
-
-
-<!-- ##### FUNCTION g_file_open_tmp ##### -->
-<para>
-
-</para>
-
-@tmpl:
-@name_used:
-@error:
-@Returns:
-
-
-<!-- ##### 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>
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>
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>
</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>
</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>
@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>
+
+
#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 ##### -->
@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.
@channel: a #GIOChannel.
-<!-- ##### FUNCTION g_io_create_watch ##### -->
-<para>
-
-</para>
-
-@channel:
-@condition:
-@Returns:
-
-
<!-- ##### FUNCTION g_io_add_watch ##### -->
<para>
Adds the #GIOChannel into the
@io_write:
@io_seek:
@io_close:
-@io_create_watch:
+@io_add_watch:
@io_free:
@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
@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.
<graphic fileref="mainloop-states.gif" format="gif"></graphic>
</figure>
</refsect2>
+
<!-- ##### SECTION See_Also ##### -->
<para>
</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().
@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().
@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>
@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().
@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().
-<!-- ##### 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().
@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
@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().
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
@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:
@priority:
@function:
@data:
-@notify:
+@destroy:
@Returns:
<!-- # Unused Parameters # -->
-@destroy:
+@notify:
<!-- ##### FUNCTION g_idle_remove_by_data ##### -->
@events:
@revents:
-<!-- ##### STRUCT GSource ##### -->
-<para>
-
-</para>
-
-
<!-- ##### STRUCT GSourceFuncs ##### -->
<para>
The #GSourceFuncs struct contains a table of functions used to handle
@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 ##### -->
@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>
</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:
-
-
@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 ##### -->
</para>
@command_line:
-@argcp:
-@argvp:
+@argc:
+@argv:
@error:
@Returns:
<!-- # Unused Parameters # -->
-@argc:
-@argv:
+@argcp:
+@argvp:
<!-- ##### FUNCTION g_shell_quote ##### -->
@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.
@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.
+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
-# 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
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
for f in $$files; do \
if test -f $$f; then d=.; else d=$(srcdir); fi; \
cp $$d/$$f $(distdir) || exit 1; done
-
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;
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;
}
GClosure*
-g_signal_type_closure_new (GType itype,
- guint struct_offset)
+g_signal_type_cclosure_new (GType itype,
+ guint struct_offset)
{
GClosure *closure;
/* --- 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 --- */
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);
/* 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
*/
\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
\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
*/
#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>
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 --- */
{ "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]);
{
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;
}
{
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);
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");
static void
process_signature (Signature *sig)
{
- gchar *pname, *sname;
+ gchar *pname, *sname, *tmp;
GList *node;
/* lookup and complete info on arguments */
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);
main (int argc,
char *argv[])
{
+ const gchar *gruntime_marshallers[] = {
+#include "gmarshal.strings"
+ };
GScanner *scanner;
GSList *slist, *files = NULL;
gint i;
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)
{
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);
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))
{
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");
}
}
* 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,
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 --- */
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 = {
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
_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)
{
}
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);
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.
}
static void
-g_object_do_finalize (GObject *object)
+g_object_finalize (GObject *object)
{
g_signal_handlers_destroy (object);
g_datalist_clear (&object->qdata);
#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;
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;
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;
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);
}
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));
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;
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);
}
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));
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)
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, };
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); */
}
g_object_unref (object);
}
-void
-g_object_queue_param_changed (GObject *object,
- const gchar *param_name)
-{
- GParamSpec *pspec;
-
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (param_name != NULL);
-
- pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
- param_name,
- G_OBJECT_TYPE (object),
- TRUE, NULL);
- if (!pspec)
- g_warning ("%s: object class `%s' has no parameter named `%s'",
- G_STRLOC,
- G_OBJECT_TYPE_NAME (object),
- param_name);
- else
- G_OBJECT_GET_CLASS (object)->queue_param_changed (object, pspec);
-}
-
GObject*
g_object_ref (GObject *object)
{
g_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
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
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
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*
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;
*
* 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
/* --- 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
#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 --- */
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 --- */
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),
0, /* n_preallocs */
(GInstanceInitFunc) g_param_spec_init,
- NULL, /* value_table */
+ ¶m_value_table,
};
GType type;
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;
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
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,
{
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);
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);
{
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)
{
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)
{
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;
+}
#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;
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,
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 --- */
}
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);
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
*/
{
}
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,
/* --- 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;
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;
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,
#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)
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,
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;
}
{
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)
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);
}
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,
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);
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)
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);
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,
{
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);
}
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));
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,
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)
{
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;
instance_and_params,
&ihint);
G_LOCK (g_signal_mutex);
+ return_value_altered = TRUE;
if (emission_state == EMISSION_STOP)
goto EMIT_CLEANUP;
instance_and_params,
&ihint);
G_LOCK (g_signal_mutex);
+ return_value_altered = TRUE;
tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
}
instance_and_params,
&ihint);
G_LOCK (g_signal_mutex);
+ return_value_altered = TRUE;
if (emission_state == EMISSION_STOP)
goto EMIT_CLEANUP;
instance_and_params,
&ihint);
G_LOCK (g_signal_mutex);
+ return_value_altered = TRUE;
tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
}
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"
#include <gobject/gclosure.h>
#include <gobject/gvalue.h>
#include <gobject/gparam.h>
+#include <gobject/gmarshal.h>
#ifdef __cplusplus
/* --- 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,
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);
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,
#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
/* --- externs --- */
-const char *g_log_domain_gobject = "GLib-Object";
+const char *g_log_domain_gruntime = "GRuntime";
/* --- type nodes --- */
*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
}
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
return 0;
}
+#if 0
gboolean
g_type_is_a (GType type,
GType is_a_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)
{
QData *qdatas = gdata->qdatas - 1;
guint n_qdatas = gdata->n_qdatas;
- do /* FIXME: should optimize qdata lookups for <= 4 */
+ do
{
guint i;
QData *check;
}
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
}
gboolean
-g_type_value_conforms_to (GValue *value,
- GType type)
+g_type_value_is_a (GValue *value,
+ GType type)
{
TypeNode *node;
#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;
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*
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),
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
#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>
G_TYPE_PARAM,
G_TYPE_BOXED,
G_TYPE_POINTER,
+ G_TYPE_CCALLBACK,
G_TYPE_OBJECT,
/* the following reserved ids should vanish soon */
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),
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;
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);
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);
# 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))
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);
#include <string.h>
#include "gvalue.h"
+#include "gvaluecollector.h"
/* --- typedefs & structures --- */
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);
}
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));
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)
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 --- */
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: \
\
while (_lcopy_type && !_error_msg) \
{ \
- GTypeCValue _cvalue; \
+ GTypeCValue _cvalue = { 0, }; \
\
- memset (&_cvalue, 0, sizeof (_cvalue)); \
switch (_lcopy_type) \
{ \
case G_VALUE_COLLECT_INT: \
static void
value_pointer_init (GValue *value)
{
- value->data[0].v_pointer = 0;
+ value->data[0].v_pointer = NULL;
}
static void
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
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);
+ }
}
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;
+}
#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 --- */
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);
# 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
# 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 \