summaryrefslogtreecommitdiff
path: root/glib
diff options
context:
space:
mode:
Diffstat (limited to 'glib')
-rw-r--r--glib/.cvsignore6
-rw-r--r--glib/Makefile.am13
-rw-r--r--glib/README1
-rw-r--r--glib/glibmm-2.4.pc.in11
-rw-r--r--glib/glibmm.h69
-rw-r--r--glib/glibmm/.cvsignore31
-rw-r--r--glib/glibmm/Makefile.am100
-rw-r--r--glib/glibmm/arrayhandle.h522
-rw-r--r--glib/glibmm/class.cc116
-rw-r--r--glib/glibmm/class.h76
-rw-r--r--glib/glibmm/containerhandle_shared.h286
-rw-r--r--glib/glibmm/containers.cc33
-rw-r--r--glib/glibmm/containers.h358
-rw-r--r--glib/glibmm/debug.cc21
-rw-r--r--glib/glibmm/debug.h85
-rw-r--r--glib/glibmm/dispatcher.cc325
-rw-r--r--glib/glibmm/dispatcher.h102
-rw-r--r--glib/glibmm/error.cc187
-rw-r--r--glib/glibmm/error.h77
-rw-r--r--glib/glibmm/exception.cc40
-rw-r--r--glib/glibmm/exception.h42
-rw-r--r--glib/glibmm/exceptionhandler.cc193
-rw-r--r--glib/glibmm/exceptionhandler.h45
-rw-r--r--glib/glibmm/helperlist.h165
-rw-r--r--glib/glibmm/interface.cc91
-rw-r--r--glib/glibmm/interface.h72
-rw-r--r--glib/glibmm/listhandle.h404
-rw-r--r--glib/glibmm/main.cc979
-rw-r--r--glib/glibmm/main.h549
-rw-r--r--glib/glibmm/miscutils.cc216
-rw-r--r--glib/glibmm/miscutils.h209
-rw-r--r--glib/glibmm/object.cc287
-rw-r--r--glib/glibmm/object.h188
-rw-r--r--glib/glibmm/objectbase.cc257
-rw-r--r--glib/glibmm/objectbase.h124
-rw-r--r--glib/glibmm/pattern.cc66
-rw-r--r--glib/glibmm/pattern.h69
-rw-r--r--glib/glibmm/private/.cvsignore13
-rw-r--r--glib/glibmm/private/Makefile.am20
-rw-r--r--glib/glibmm/private/interface_p.h24
-rw-r--r--glib/glibmm/private/object_p.h28
-rw-r--r--glib/glibmm/property.cc198
-rw-r--r--glib/glibmm/property.h161
-rw-r--r--glib/glibmm/propertyproxy.cc24
-rw-r--r--glib/glibmm/propertyproxy.h129
-rw-r--r--glib/glibmm/propertyproxy_base.cc159
-rw-r--r--glib/glibmm/propertyproxy_base.h84
-rw-r--r--glib/glibmm/quark.cc66
-rw-r--r--glib/glibmm/quark.h88
-rw-r--r--glib/glibmm/random.cc76
-rw-r--r--glib/glibmm/random.h73
-rw-r--r--glib/glibmm/refptr.h349
-rw-r--r--glib/glibmm/sarray.cc85
-rw-r--r--glib/glibmm/sarray.h108
-rw-r--r--glib/glibmm/signalproxy.cc111
-rw-r--r--glib/glibmm/signalproxy_connectionnode.cc84
-rw-r--r--glib/glibmm/signalproxy_connectionnode.h60
-rw-r--r--glib/glibmm/slisthandle.h403
-rw-r--r--glib/glibmm/streamiochannel.cc188
-rw-r--r--glib/glibmm/streamiochannel.h67
-rw-r--r--glib/glibmm/stringutils.cc117
-rw-r--r--glib/glibmm/stringutils.h184
-rw-r--r--glib/glibmm/threadpool.cc249
-rw-r--r--glib/glibmm/threadpool.h183
-rw-r--r--glib/glibmm/timer.cc72
-rw-r--r--glib/glibmm/timer.h79
-rw-r--r--glib/glibmm/timeval.cc120
-rw-r--r--glib/glibmm/timeval.h233
-rw-r--r--glib/glibmm/ustring.cc1180
-rw-r--r--glib/glibmm/ustring.h907
-rw-r--r--glib/glibmm/utility.cc40
-rw-r--r--glib/glibmm/utility.h119
-rw-r--r--glib/glibmm/value.cc242
-rw-r--r--glib/glibmm/value.h312
-rw-r--r--glib/glibmm/value_custom.cc144
-rw-r--r--glib/glibmm/value_custom.h286
-rw-r--r--glib/glibmm/wrap.cc161
-rw-r--r--glib/glibmm/wrap.h118
-rw-r--r--glib/glibmm/wrap_init.h38
-rw-r--r--glib/glibmmconfig.h.in71
-rw-r--r--glib/src/.cvsignore4
-rw-r--r--glib/src/Makefile.am21
-rw-r--r--glib/src/Makefile_list_of_hg.am_fragment8
-rw-r--r--glib/src/convert.ccg276
-rw-r--r--glib/src/convert.hg236
-rw-r--r--glib/src/date.ccg325
-rw-r--r--glib/src/date.hg151
-rw-r--r--glib/src/fileutils.ccg185
-rw-r--r--glib/src/fileutils.hg400
-rw-r--r--glib/src/glib.defs5
-rw-r--r--glib/src/glib_enums.defs489
-rw-r--r--glib/src/glib_functions.defs6328
-rw-r--r--glib/src/gmodule_enums.defs11
-rw-r--r--glib/src/gmodule_functions.defs79
-rw-r--r--glib/src/gobject.defs3
-rw-r--r--glib/src/gobject_enums.defs80
-rw-r--r--glib/src/gobject_functions.defs2608
-rw-r--r--glib/src/iochannel.ccg540
-rw-r--r--glib/src/iochannel.hg452
-rw-r--r--glib/src/markup.ccg318
-rw-r--r--glib/src/markup.hg346
-rw-r--r--glib/src/module.ccg39
-rw-r--r--glib/src/module.hg68
-rw-r--r--glib/src/shell.ccg61
-rw-r--r--glib/src/shell.hg96
-rw-r--r--glib/src/signalproxy.h.m4158
-rw-r--r--glib/src/spawn.ccg264
-rw-r--r--glib/src/spawn.hg105
-rw-r--r--glib/src/template.macros.m4229
-rw-r--r--glib/src/thread.ccg377
-rw-r--r--glib/src/thread.hg968
-rw-r--r--glib/src/unicode.ccg22
-rw-r--r--glib/src/unicode.hg141
-rw-r--r--glib/src/value_basictypes.cc.m484
-rw-r--r--glib/src/value_basictypes.h.m483
115 files changed, 29428 insertions, 0 deletions
diff --git a/glib/.cvsignore b/glib/.cvsignore
new file mode 100644
index 00000000..e375c56c
--- /dev/null
+++ b/glib/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+stamp*
+
+glibmm-2.0.pc
+glibmmconfig.h
diff --git a/glib/Makefile.am b/glib/Makefile.am
new file mode 100644
index 00000000..04fa877b
--- /dev/null
+++ b/glib/Makefile.am
@@ -0,0 +1,13 @@
+SUBDIRS = src glibmm
+
+EXTRA_DIST = README glibmmconfig.h.in glibmm-2.0.pc.in
+
+glibmm_includedir = $(includedir)/gtkmm-2.0
+glibmm_include_HEADERS = glibmm.h
+
+glibmm_configdir = $(libdir)/gtkmm-2.0/include
+glibmm_config_DATA = glibmmconfig.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = glibmm-2.0.pc
+
diff --git a/glib/README b/glib/README
new file mode 100644
index 00000000..289d17a7
--- /dev/null
+++ b/glib/README
@@ -0,0 +1 @@
+glib base dir.
diff --git a/glib/glibmm-2.4.pc.in b/glib/glibmm-2.4.pc.in
new file mode 100644
index 00000000..66f05e73
--- /dev/null
+++ b/glib/glibmm-2.4.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: GLibmm
+Description: C++ wrapper for GLib
+Requires: gobject-2.0 sigc++-1.2
+Version: @VERSION@
+Libs: -L${libdir} -lglibmm-2.0
+Cflags: -I${includedir}/gtkmm-2.0 -I${libdir}/gtkmm-2.0/include
diff --git a/glib/glibmm.h b/glib/glibmm.h
new file mode 100644
index 00000000..7f44fea7
--- /dev/null
+++ b/glib/glibmm.h
@@ -0,0 +1,69 @@
+/* $Id$ */
+
+/* glibmm - a C++ wrapper for the GLib toolkit
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GLIBMM_H
+#define _GLIBMM_H
+
+#include <glibmmconfig.h>
+#include <glibmm/arrayhandle.h>
+#include <glibmm/class.h>
+#include <glibmm/containerhandle_shared.h>
+#include <glibmm/convert.h>
+#include <glibmm/date.h>
+#include <glibmm/dispatcher.h>
+#include <glibmm/error.h>
+#include <glibmm/exception.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/fileutils.h>
+#include <glibmm/helperlist.h>
+#include <glibmm/interface.h>
+#include <glibmm/iochannel.h>
+#include <glibmm/streamiochannel.h>
+#include <glibmm/listhandle.h>
+#include <glibmm/main.h>
+#include <glibmm/markup.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/module.h>
+#include <glibmm/objectbase.h>
+#include <glibmm/object.h>
+#include <glibmm/pattern.h>
+#include <glibmm/property.h>
+#include <glibmm/propertyproxy_base.h>
+#include <glibmm/propertyproxy.h>
+#include <glibmm/quark.h>
+#include <glibmm/random.h>
+#include <glibmm/refptr.h>
+#include <glibmm/shell.h>
+#include <glibmm/signalproxy_connectionnode.h>
+#include <glibmm/signalproxy.h>
+#include <glibmm/slisthandle.h>
+#include <glibmm/spawn.h>
+#include <glibmm/stringutils.h>
+#include <glibmm/thread.h>
+#include <glibmm/threadpool.h>
+#include <glibmm/timer.h>
+#include <glibmm/timeval.h>
+#include <glibmm/ustring.h>
+#include <glibmm/value.h>
+#include <glibmm/wrap.h>
+
+#endif /* _GLIBMM_H */
+
diff --git a/glib/glibmm/.cvsignore b/glib/glibmm/.cvsignore
new file mode 100644
index 00000000..24c89ef7
--- /dev/null
+++ b/glib/glibmm/.cvsignore
@@ -0,0 +1,31 @@
+.deps
+.libs
+*.la
+*.lo
+Makefile
+Makefile.in
+
+convert.cc
+date.cc
+fileutils.cc
+iochannel.cc
+markup.cc
+module.cc
+shell.cc
+spawn.cc
+thread.cc
+unicode.cc
+wrap_init.cc
+value_basictypes.cc
+convert.h
+date.h
+fileutils.h
+iochannel.h
+markup.h
+module.h
+shell.h
+spawn.h
+thread.h
+unicode.h
+signalproxy.h
+value_basictypes.h
diff --git a/glib/glibmm/Makefile.am b/glib/glibmm/Makefile.am
new file mode 100644
index 00000000..b831829e
--- /dev/null
+++ b/glib/glibmm/Makefile.am
@@ -0,0 +1,100 @@
+## Copyright (c) 2001
+## The gtkmm development team.
+
+SUBDIRS = private
+
+sublib_name = glibmm
+sublib_namespace = Gtk
+sublib_cflags = $(GLIBMM_CFLAGS)
+
+sublib_files_extra_posix_cc =
+sublib_files_extra_win32_cc =
+
+sublib_files_extra_general_cc = \
+ class.cc \
+ containers.cc \
+ debug.cc \
+ dispatcher.cc \
+ error.cc \
+ exception.cc \
+ exceptionhandler.cc \
+ interface.cc \
+ main.cc \
+ miscutils.cc \
+ object.cc \
+ objectbase.cc \
+ pattern.cc \
+ property.cc \
+ propertyproxy.cc \
+ propertyproxy_base.cc \
+ quark.cc \
+ random.cc \
+ signalproxy.cc \
+ signalproxy_connectionnode.cc \
+ streamiochannel.cc \
+ stringutils.cc \
+ threadpool.cc \
+ timer.cc \
+ timeval.cc \
+ ustring.cc \
+ utility.cc \
+ value.cc \
+ value_custom.cc \
+ wrap.cc
+
+sublib_files_extra_posix_h =
+sublib_files_extra_win32_h =
+
+sublib_files_extra_general_h = \
+ arrayhandle.h \
+ class.h \
+ containerhandle_shared.h \
+ containers.h \
+ debug.h \
+ dispatcher.h \
+ error.h \
+ exception.h \
+ exceptionhandler.h \
+ helperlist.h \
+ interface.h \
+ iochannel.h \
+ listhandle.h \
+ main.h \
+ miscutils.h \
+ object.h \
+ objectbase.h \
+ pattern.h \
+ property.h \
+ propertyproxy.h \
+ propertyproxy_base.h \
+ quark.h \
+ random.h \
+ refptr.h \
+ sarray.h \
+ signalproxy_connectionnode.h \
+ slisthandle.h \
+ streamiochannel.h \
+ stringutils.h \
+ threadpool.h \
+ timer.h \
+ timeval.h \
+ ustring.h \
+ utility.h \
+ value.h \
+ value_custom.h \
+ wrap.h
+
+include $(top_srcdir)/build_shared/Makefile_build_gensrc.am_fragment
+
+files_built_general_cc += value_basictypes.cc
+files_built_general_h += signalproxy.h value_basictypes.h
+
+lib_LTLIBRARIES = libglibmm-2.0.la
+if OS_WIN32
+libglibmm_2_0_la_SOURCES = $(files_all_general_cc) $(files_all_win32_cc)
+else
+libglibmm_2_0_la_SOURCES = $(files_all_general_cc) $(files_all_posix_cc)
+endif
+libglibmm_2_0_la_LDFLAGS = $(common_ldflags)
+libglibmm_2_0_la_LIBADD = $(GLIBMM_LIBS)
+
diff --git a/glib/glibmm/arrayhandle.h b/glib/glibmm/arrayhandle.h
new file mode 100644
index 00000000..db018b78
--- /dev/null
+++ b/glib/glibmm/arrayhandle.h
@@ -0,0 +1,522 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_ARRAYHANDLE_H
+#define _GLIBMM_ARRAYHANDLE_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/containerhandle_shared.h>
+
+
+namespace Glib
+{
+
+namespace Container_Helpers
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* Count the number of elements in a 0-terminated sequence.
+ */
+template <class T> inline
+size_t compute_array_size(const T* array)
+{
+ const T* pend = array;
+
+ while(*pend)
+ ++pend;
+
+ return (pend - array);
+}
+
+/* Allocate and fill a 0-terminated array. The size argument
+ * specifies the number of elements in the input sequence.
+ */
+template <class For, class Tr>
+typename Tr::CType* create_array(For pbegin, size_t size, Tr)
+{
+ typedef typename Tr::CType CType;
+
+ CType *const array = static_cast<CType*>(g_malloc((size + 1) * sizeof(CType)));
+ CType *const array_end = array + size;
+
+ for(CType* pdest = array; pdest != array_end; ++pdest)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ *pdest = Tr::to_c_type(*&*pbegin);
+ ++pbegin;
+ }
+
+ *array_end = CType();
+ return array;
+}
+
+
+/* Convert from any container that supports forward
+ * iterators and has a size() method.
+ */
+template <class Tr, class Cont>
+struct ArraySourceTraits
+{
+ typedef typename Tr::CType CType;
+
+ static size_t get_size(const Cont& cont)
+ { return cont.size(); }
+
+ static const CType* get_data(const Cont& cont, size_t size)
+ { return Glib::Container_Helpers::create_array(cont.begin(), size, Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+/* Convert from a 0-terminated array. The Cont argument must be a pointer
+ * to the first element. Note that only arrays of the C type are supported.
+ */
+template <class Tr, class Cont>
+struct ArraySourceTraits<Tr,Cont*>
+{
+ typedef typename Tr::CType CType;
+
+ static size_t get_size(const CType* array)
+ { return (array) ? Glib::Container_Helpers::compute_array_size(array) : 0; }
+
+ static const CType* get_data(const CType* array, size_t)
+ { return array; }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_NONE;
+};
+
+template <class Tr, class Cont>
+struct ArraySourceTraits<Tr,const Cont*> : ArraySourceTraits<Tr,Cont*>
+{};
+
+/* Convert from a 0-terminated array. The Cont argument must be a pointer
+ * to the first element. Note that only arrays of the C type are supported.
+ * For consistency, the array must be 0-terminated, even though the array
+ * size is known at compile time.
+ */
+template <class Tr, class Cont, size_t N>
+struct ArraySourceTraits<Tr,Cont[N]>
+{
+ typedef typename Tr::CType CType;
+
+ static size_t get_size(const CType*)
+ { return (N - 1); }
+
+ static const CType* get_data(const CType* array, size_t)
+ { return array; }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_NONE;
+};
+
+template <class Tr, class Cont, size_t N>
+struct ArraySourceTraits<Tr,const Cont[N]> : ArraySourceTraits<Tr,Cont[N]>
+{};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/**
+ * @ingroup ContHelpers
+ */
+template <class Tr>
+class ArrayHandleIterator
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef CppType value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type reference;
+ typedef void pointer;
+
+ explicit inline ArrayHandleIterator(const CType* pos);
+
+ inline value_type operator*() const;
+ inline value_type operator[](difference_type offset) const;
+
+ inline ArrayHandleIterator<Tr> & operator++();
+ inline const ArrayHandleIterator<Tr> operator++(int);
+
+ // All this random access stuff is only there because STL algorithms
+ // usually have optimized specializations for random access iterators,
+ // and we don't want to give away efficiency for nothing.
+ //
+ inline ArrayHandleIterator<Tr> & operator+=(difference_type rhs);
+ inline ArrayHandleIterator<Tr> & operator-=(difference_type rhs);
+ inline const ArrayHandleIterator<Tr> operator+ (difference_type rhs) const;
+ inline const ArrayHandleIterator<Tr> operator- (difference_type rhs) const;
+ inline difference_type operator-(const ArrayHandleIterator<Tr>& rhs) const;
+
+ inline bool operator==(const ArrayHandleIterator<Tr>& rhs) const;
+ inline bool operator!=(const ArrayHandleIterator<Tr>& rhs) const;
+ inline bool operator< (const ArrayHandleIterator<Tr>& rhs) const;
+ inline bool operator> (const ArrayHandleIterator<Tr>& rhs) const;
+ inline bool operator<=(const ArrayHandleIterator<Tr>& rhs) const;
+ inline bool operator>=(const ArrayHandleIterator<Tr>& rhs) const;
+
+private:
+ const CType* pos_;
+};
+
+} // namespace Container_Helpers
+
+
+/** If a method takes this as an argument then you can use a standard
+ * container such as std::list or std::vector.
+ * @ingroup ContHandles
+ */
+template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
+class ArrayHandle
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef CppType value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef Glib::Container_Helpers::ArrayHandleIterator<Tr> const_iterator;
+ typedef Glib::Container_Helpers::ArrayHandleIterator<Tr> iterator;
+
+ template <class Cont> inline
+ ArrayHandle(const Cont& container);
+
+ // Take over ownership of an array created by GTK+ functions.
+ inline ArrayHandle(const CType* array, size_t array_size, Glib::OwnershipType ownership);
+ inline ArrayHandle(const CType* array, Glib::OwnershipType ownership);
+
+ // Copying clears the ownership flag of the source handle.
+ inline ArrayHandle(const ArrayHandle<T,Tr>& other);
+
+ ~ArrayHandle();
+
+ inline const_iterator begin() const;
+ inline const_iterator end() const;
+
+ template <class U> inline operator std::vector<U>() const;
+ template <class U> inline operator std::deque<U>() const;
+ template <class U> inline operator std::list<U>() const;
+
+ template <class Cont> inline
+ void assign_to(Cont& container) const;
+
+ template <class Out> inline
+ void copy(Out pdest) const;
+
+ inline const CType* data() const;
+ inline size_t size() const;
+ inline bool empty() const;
+
+private:
+ size_t size_;
+ const CType * parray_;
+ mutable Glib::OwnershipType ownership_;
+
+ // No copy assignment.
+ ArrayHandle<T,Tr>& operator=(const ArrayHandle<T,Tr>&);
+};
+
+/** If a method takes this as an argument then you can use a standard
+ * container such as std::list<Glib::ustring> or std::vector<Glib::ustring>.
+ * @ingroup ContHandles
+ */
+typedef ArrayHandle<Glib::ustring> StringArrayHandle;
+
+
+/***************************************************************************/
+/* Inline implementation */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace Container_Helpers
+{
+
+/**** Glib::Container_Helpers::ArrayHandleIterator<> ***********************/
+
+template <class Tr> inline
+ArrayHandleIterator<Tr>::ArrayHandleIterator(const CType* pos)
+:
+ pos_ (pos)
+{}
+
+template <class Tr> inline
+typename ArrayHandleIterator<Tr>::value_type ArrayHandleIterator<Tr>::operator*() const
+{
+ return Tr::to_cpp_type(*pos_);
+}
+
+template <class Tr> inline
+typename ArrayHandleIterator<Tr>::value_type
+ArrayHandleIterator<Tr>::operator[](difference_type offset) const
+{
+ return Tr::to_cpp_type(pos_[offset]);
+}
+
+template <class Tr> inline
+ArrayHandleIterator<Tr>& ArrayHandleIterator<Tr>::operator++()
+{
+ ++pos_;
+ return *this;
+}
+
+template <class Tr> inline
+const ArrayHandleIterator<Tr> ArrayHandleIterator<Tr>::operator++(int)
+{
+ return ArrayHandleIterator<Tr>(pos_++);
+}
+
+template <class Tr> inline
+ArrayHandleIterator<Tr>&
+ArrayHandleIterator<Tr>::operator+=(typename ArrayHandleIterator<Tr>::difference_type rhs)
+{
+ pos_ += rhs;
+ return *this;
+}
+
+template <class Tr> inline
+ArrayHandleIterator<Tr>&
+ArrayHandleIterator<Tr>::operator-=(typename ArrayHandleIterator<Tr>::difference_type rhs)
+{
+ pos_ -= rhs;
+ return *this;
+}
+
+template <class Tr> inline
+const ArrayHandleIterator<Tr>
+ArrayHandleIterator<Tr>::operator+(typename ArrayHandleIterator<Tr>::difference_type rhs) const
+{
+ return ArrayHandleIterator<Tr>(pos_ + rhs);
+}
+
+template <class Tr> inline
+const ArrayHandleIterator<Tr>
+ArrayHandleIterator<Tr>::operator-(typename ArrayHandleIterator<Tr>::difference_type rhs) const
+{
+ return ArrayHandleIterator<Tr>(pos_ - rhs);
+}
+
+template <class Tr> inline
+typename ArrayHandleIterator<Tr>::difference_type
+ArrayHandleIterator<Tr>::operator-(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ - rhs.pos_);
+}
+
+template <class Tr> inline
+bool ArrayHandleIterator<Tr>::operator==(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ == rhs.pos_);
+}
+
+template <class Tr> inline
+bool ArrayHandleIterator<Tr>::operator!=(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ != rhs.pos_);
+}
+
+template <class Tr> inline
+bool ArrayHandleIterator<Tr>::operator<(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ < rhs.pos_);
+}
+
+template <class Tr> inline
+bool ArrayHandleIterator<Tr>::operator>(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ > rhs.pos_);
+}
+
+template <class Tr> inline
+bool ArrayHandleIterator<Tr>::operator<=(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ <= rhs.pos_);
+}
+
+template <class Tr> inline
+bool ArrayHandleIterator<Tr>::operator>=(const ArrayHandleIterator<Tr>& rhs) const
+{
+ return (pos_ >= rhs.pos_);
+}
+
+} // namespace Container_Helpers
+
+
+/**** Glib::ArrayHandle<> **************************************************/
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+ArrayHandle<T,Tr>::ArrayHandle(const Cont& container)
+:
+ size_ (Glib::Container_Helpers::ArraySourceTraits<Tr,Cont>::get_size(container)),
+ parray_ (Glib::Container_Helpers::ArraySourceTraits<Tr,Cont>::get_data(container, size_)),
+ ownership_ (Glib::Container_Helpers::ArraySourceTraits<Tr,Cont>::initial_ownership)
+{}
+
+template <class T, class Tr> inline
+ArrayHandle<T,Tr>::ArrayHandle(const typename ArrayHandle<T,Tr>::CType* array, size_t array_size,
+ Glib::OwnershipType ownership)
+:
+ size_ (array_size),
+ parray_ (array),
+ ownership_ (ownership)
+{}
+
+template <class T, class Tr> inline
+ArrayHandle<T,Tr>::ArrayHandle(const typename ArrayHandle<T,Tr>::CType* array,
+ Glib::OwnershipType ownership)
+:
+ size_ ((array) ? Glib::Container_Helpers::compute_array_size(array) : 0),
+ parray_ (array),
+ ownership_ (ownership)
+{}
+
+template <class T, class Tr> inline
+ArrayHandle<T,Tr>::ArrayHandle(const ArrayHandle<T,Tr>& other)
+:
+ size_ (other.size_),
+ parray_ (other.parray_),
+ ownership_ (other.ownership_)
+{
+ other.ownership_ = Glib::OWNERSHIP_NONE;
+}
+
+template <class T, class Tr>
+ArrayHandle<T,Tr>::~ArrayHandle()
+{
+ if(ownership_ != Glib::OWNERSHIP_NONE)
+ {
+ if(ownership_ != Glib::OWNERSHIP_SHALLOW)
+ {
+ // Deep ownership: release each container element.
+ const CType *const pend = parray_ + size_;
+ for(const CType* p = parray_; p != pend; ++p)
+ Tr::release_c_type(*p);
+ }
+ g_free(const_cast<CType*>(parray_));
+ }
+}
+
+template <class T, class Tr> inline
+typename ArrayHandle<T,Tr>::const_iterator ArrayHandle<T,Tr>::begin() const
+{
+ return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_);
+}
+
+template <class T, class Tr> inline
+typename ArrayHandle<T,Tr>::const_iterator ArrayHandle<T,Tr>::end() const
+{
+ return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_ + size_);
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+ArrayHandle<T,Tr>::operator std::vector<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::vector<U>(this->begin(), this->end());
+#else
+ std::vector<U> temp;
+ temp.reserve(this->size());
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+ArrayHandle<T,Tr>::operator std::deque<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::deque<U>(this->begin(), this->end());
+#else
+ std::deque<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+ArrayHandle<T,Tr>::operator std::list<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::list<U>(this->begin(), this->end());
+#else
+ std::list<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+void ArrayHandle<T,Tr>::assign_to(Cont& container) const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ container.assign(this->begin(), this->end());
+#else
+ Cont temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ container.swap(temp);
+#endif
+}
+
+template <class T, class Tr>
+ template <class Out>
+inline
+void ArrayHandle<T,Tr>::copy(Out pdest) const
+{
+ std::copy(this->begin(), this->end(), pdest);
+}
+
+template <class T, class Tr> inline
+const typename ArrayHandle<T,Tr>::CType* ArrayHandle<T,Tr>::data() const
+{
+ return parray_;
+}
+
+template <class T, class Tr> inline
+size_t ArrayHandle<T,Tr>::size() const
+{
+ return size_;
+}
+
+template <class T, class Tr> inline
+bool ArrayHandle<T,Tr>::empty() const
+{
+ return (size_ == 0);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_ARRAYHANDLE_H */
+
diff --git a/glib/glibmm/class.cc b/glib/glibmm/class.cc
new file mode 100644
index 00000000..ff4a671d
--- /dev/null
+++ b/glib/glibmm/class.cc
@@ -0,0 +1,116 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/class.h>
+#include <glibmm/property.h>
+#include <glibmm/ustring.h>
+#include <glibmm/utility.h>
+
+
+namespace Glib
+{
+
+void Class::register_derived_type(GType base_type)
+{
+ if(gtype_)
+ return; // already initialized
+
+ GTypeQuery base_query = { 0, 0, 0, 0, };
+ g_type_query(base_type, &base_query);
+
+ const GTypeInfo derived_info =
+ {
+ base_query.class_size,
+ 0, // base_init
+ 0, // base_finalize
+ class_init_func_,
+ 0, // class_finalize
+ 0, // class_data
+ base_query.instance_size,
+ 0, // n_preallocs
+ 0, // instance_init
+ 0, // value_table
+ };
+
+ Glib::ustring derived_name = "gtkmm__";
+ derived_name += base_query.type_name;
+
+ gtype_ = g_type_register_static(base_type, derived_name.c_str(), &derived_info, GTypeFlags(0));
+}
+
+GType Class::clone_custom_type(const char* custom_type_name) const
+{
+ std::string full_name ("gtkmm__CustomObject_");
+ Glib::append_canonical_typename(full_name, custom_type_name);
+
+ GType custom_type = g_type_from_name(full_name.c_str());
+
+ if(!custom_type)
+ {
+ g_return_val_if_fail(gtype_ != 0, 0);
+
+ // Cloned custom types derive from the wrapper's parent type,
+ // so that g_type_class_peek_parent() works correctly.
+ const GType base_type = g_type_parent(gtype_);
+
+ GTypeQuery base_query = { 0, 0, 0, 0, };
+ g_type_query(base_type, &base_query);
+
+ const GTypeInfo derived_info =
+ {
+ base_query.class_size,
+ 0, // base_init
+ 0, // base_finalize
+ &Class::custom_class_init_function,
+ 0, // class_finalize
+ this, // class_data
+ base_query.instance_size,
+ 0, // n_preallocs
+ 0, // instance_init
+ 0, // value_table
+ };
+
+ custom_type = g_type_register_static(
+ base_type, full_name.c_str(), &derived_info, GTypeFlags(0));
+ }
+
+ return custom_type;
+}
+
+// static
+void Class::custom_class_init_function(void* g_class, void* class_data)
+{
+ // The class_data pointer is set to 'this' by clone_custom_type().
+ const Class *const self = static_cast<Class*>(class_data);
+
+ g_return_if_fail(self->class_init_func_ != 0);
+
+ // Call the wrapper's class_init_function() to redirect
+ // the vfunc and default signal handler callbacks.
+ (*self->class_init_func_)(g_class, 0);
+
+ GObjectClass *const gobject_class = static_cast<GObjectClass*>(g_class);
+
+ gobject_class->get_property = &Glib::custom_get_property_callback;
+ gobject_class->set_property = &Glib::custom_set_property_callback;
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/class.h b/glib/glibmm/class.h
new file mode 100644
index 00000000..c7b5a96f
--- /dev/null
+++ b/glib/glibmm/class.h
@@ -0,0 +1,76 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_CLASS_H
+#define _GLIBMM_CLASS_H
+
+/* $Id$ */
+
+/* Copyright 2001 Free Software Foundation
+ * Copyright (C) 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib-object.h>
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace Glib
+{
+
+class Class
+{
+public:
+ /* No constructor/destructor:
+ * Glib::Class objects are used only as static data, which would cause
+ * lots of ugly global constructor invocations. These are avoidable,
+ * because the C/C++ standard explicitly specifies that all _static_ data
+ * is zero-initialized at program start.
+ */
+ //Class();
+ //~Class();
+
+ //static void class_init_function(BaseClassType *p);
+ //static void object_init_function(BaseObjectType *o);
+ //GType get_type() = 0; //Creates the GType when this is first called.
+
+ // Hook for translating API
+ //static Glib::Object* wrap_new(GObject*);
+
+ inline GType get_type() const;
+ GType clone_custom_type(const char* custom_type_name) const;
+
+protected:
+ GType gtype_;
+ GClassInitFunc class_init_func_;
+
+ void register_derived_type(GType base_type);
+
+private:
+ static void custom_class_init_function(void* g_class, void* class_data);
+};
+
+inline
+GType Class::get_type() const
+{
+ return gtype_;
+}
+
+} // namespace Glib
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* _GLIBMM_CLASS_H */
+
diff --git a/glib/glibmm/containerhandle_shared.h b/glib/glibmm/containerhandle_shared.h
new file mode 100644
index 00000000..8796bf96
--- /dev/null
+++ b/glib/glibmm/containerhandle_shared.h
@@ -0,0 +1,286 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_CONTAINERHANDLE_SHARED_H
+#define _GLIBMM_CONTAINERHANDLE_SHARED_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <cstddef>
+#include <algorithm>
+#include <iterator>
+#include <vector>
+#include <deque>
+#include <list>
+
+#include <glib-object.h>
+#include <glib/gmem.h>
+#include <glibmm/refptr.h>
+#include <glibmm/ustring.h>
+#include <glibmm/wrap.h>
+#include <glibmm/debug.h>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(forward_iterator_tag)
+GTKMM_USING_STD(random_access_iterator_tag)
+GTKMM_USING_STD(distance)
+GTKMM_USING_STD(copy)
+GTKMM_USING_STD(vector)
+GTKMM_USING_STD(deque)
+GTKMM_USING_STD(list)
+
+
+namespace Glib
+{
+
+/** @defgroup ContHandles Generic container converters
+ */
+
+/**
+ * @ingroup ContHandles
+ */
+enum OwnershipType
+{
+ OWNERSHIP_NONE = 0,
+ OWNERSHIP_SHALLOW,
+ OWNERSHIP_DEEP
+};
+
+
+/** Utility class holding an iterator sequence.
+ * @ingroup ContHandles
+ * This can be used to initialize a Glib container handle (such as
+ * Glib::ArrayHandle) with an iterator sequence. Use the helper
+ * function Glib::sequence() to create a Sequence<> object.
+ */
+template <class Iterator>
+class Sequence
+{
+private:
+ Iterator pbegin_;
+ Iterator pend_;
+
+public:
+ Sequence(Iterator pbegin, Iterator pend)
+ : pbegin_(pbegin), pend_(pend) {}
+
+ Iterator begin() const { return pbegin_; }
+ Iterator end() const { return pend_; }
+ size_t size() const { return std::distance(pbegin_, pend_); }
+};
+
+/** Helper function to create a Glib::Sequence<> object, which
+ * in turn can be used to initialize a container handle.
+ * @ingroup ContHandles
+ *
+ * @par Usage example:
+ * @code
+ * combo.set_popdown_strings(Glib::sequence(foo_begin, foo_end));
+ * @endcode
+ */
+template <class Iterator> inline
+Sequence<Iterator> sequence(Iterator pbegin, Iterator pend)
+{
+ return Sequence<Iterator>(pbegin, pend);
+}
+
+
+namespace Container_Helpers
+{
+
+/** @defgroup ContHelpers Helper classes
+ * @ingroup ContHandles
+ */
+
+/** Generic TypeTraits implementation.
+ * @ingroup ContHelpers
+ * This can be used if the C++ type is the same as the C type, or if implicit
+ * conversions between the types are available. Also, the types are required
+ * to implement copy-by-value semantics. (Ownership is just ignored.)
+ */
+template <class T>
+struct TypeTraits
+{
+ typedef T CppType;
+ typedef T CType;
+ typedef T CTypeNonConst;
+
+ static CType to_c_type (const CppType& item) { return item; }
+ static CppType to_cpp_type (const CType& item) { return item; }
+ static void release_c_type (const CType&) {}
+};
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS /* hide the specializations */
+
+/** Partial specialization for pointers to GtkObject instances.
+ * @ingroup ContHelpers
+ */
+template <class T>
+struct TypeTraits<T*>
+{
+ typedef T * CppType;
+ typedef typename T::BaseObjectType * CType;
+ typedef typename T::BaseObjectType * CTypeNonConst;
+
+ static CType to_c_type (CppType ptr) { return Glib::unwrap(ptr); }
+ static CType to_c_type (CType ptr) { return ptr; }
+ static CppType to_cpp_type (CType ptr) { return Glib::wrap(ptr, false); }
+ static void release_c_type (CType ptr)
+ {
+ GTKMM_DEBUG_UNREFERENCE(0, ptr);
+ g_object_unref(ptr);
+ }
+};
+
+/** Partial specialization for pointers to const GtkObject instances.
+ * @ingroup ContHelpers
+ */
+template <class T>
+struct TypeTraits<const T*>
+{
+ typedef const T * CppType;
+ typedef const typename T::BaseObjectType * CType;
+ typedef typename T::BaseObjectType * CTypeNonConst;
+
+ static CType to_c_type (CppType ptr) { return Glib::unwrap(ptr); }
+ static CType to_c_type (CType ptr) { return ptr; }
+ static CppType to_cpp_type (CType ptr) { return Glib::wrap(ptr, false); }
+ static void release_c_type (CType ptr)
+ {
+ GTKMM_DEBUG_UNREFERENCE(0, ptr);
+ g_object_unref(const_cast<CTypeNonConst>(ptr));
+ }
+};
+
+/** Partial specialization for pointers to GObject instances.
+ * @ingroup ContHelpers
+ * The C++ type is always a Glib::RefPtr<>.
+ */
+template <class T>
+struct TypeTraits< Glib::RefPtr<T> >
+{
+ typedef Glib::RefPtr<T> CppType;
+ typedef typename T::BaseObjectType * CType;
+ typedef typename T::BaseObjectType * CTypeNonConst;
+
+ static CType to_c_type (const CppType& ptr) { return Glib::unwrap(ptr); }
+ static CType to_c_type (CType ptr) { return ptr; }
+ static CppType to_cpp_type (CType ptr) { return Glib::wrap(ptr, true); }
+ static void release_c_type (CType ptr)
+ {
+ GTKMM_DEBUG_UNREFERENCE(0, ptr);
+ g_object_unref(ptr);
+ }
+};
+
+/** Partial specialization for pointers to const GObject instances.
+ * @ingroup ContHelpers
+ * The C++ type is always a Glib::RefPtr<>.
+ */
+template <class T>
+struct TypeTraits< Glib::RefPtr<const T> >
+{
+ typedef Glib::RefPtr<const T> CppType;
+ typedef const typename T::BaseObjectType * CType;
+ typedef typename T::BaseObjectType * CTypeNonConst;
+
+ static CType to_c_type (const CppType& ptr) { return Glib::unwrap(ptr); }
+ static CType to_c_type (CType ptr) { return ptr; }
+ static CppType to_cpp_type (CType ptr) { return Glib::wrap(ptr, true); }
+ static void release_c_type (CType ptr)
+ {
+ GTKMM_DEBUG_UNREFERENCE(0, ptr);
+ g_object_unref(const_cast<CTypeNonConst>(ptr));
+ }
+};
+
+/** Specialization for UTF-8 strings.
+ * @ingroup ContHelpers
+ * When converting from C++ to C, Glib::ustring will be accepted as well as
+ * std::string and 'const char*'. However, when converting to the C++ side,
+ * the output type cannot be 'const char*'.
+ */
+template <>
+struct TypeTraits<Glib::ustring>
+{
+ typedef Glib::ustring CppType;
+ typedef const char * CType;
+ typedef char * CTypeNonConst;
+
+ static CType to_c_type (const Glib::ustring& str) { return str.c_str(); }
+ static CType to_c_type (const std::string& str) { return str.c_str(); }
+ static CType to_c_type (CType str) { return str; }
+
+ static CppType to_cpp_type(CType str)
+ { return (str) ? Glib::ustring(str) : Glib::ustring(); }
+
+ static void release_c_type(CType str)
+ { g_free(const_cast<CTypeNonConst>(str)); }
+};
+
+/** Specialization for std::string.
+ * @ingroup ContHelpers
+ * When converting from C++ to C, std::string will be accepted as well as
+ * 'const char*'. However, when converting to the C++ side, the output type
+ * cannot be 'const char*'.
+ */
+template <>
+struct TypeTraits<std::string>
+{
+ typedef std::string CppType;
+ typedef const char * CType;
+ typedef char * CTypeNonConst;
+
+ static CType to_c_type (const std::string& str) { return str.c_str(); }
+ static CType to_c_type (const Glib::ustring& str) { return str.c_str(); }
+ static CType to_c_type (CType str) { return str; }
+
+ static CppType to_cpp_type(CType str)
+ { return (str) ? std::string(str) : std::string(); }
+
+ static void release_c_type(CType str)
+ { g_free(const_cast<CTypeNonConst>(str)); }
+};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#ifndef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+
+/* The STL containers in Sun's libCstd don't support templated sequence
+ * constructors, for "backward compatibility" reasons. This helper function
+ * is used in the ContainerHandle -> STL-container conversion workarounds.
+ */
+template <class Cont, class In>
+void fill_container(Cont& container, In pbegin, In pend)
+{
+ for(; pbegin != pend; ++pbegin)
+ container.push_back(*pbegin);
+}
+
+#endif /* GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS */
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Container_Helpers
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_CONTAINERHANDLE_SHARED_H */
+
diff --git a/glib/glibmm/containers.cc b/glib/glibmm/containers.cc
new file mode 100644
index 00000000..49803e11
--- /dev/null
+++ b/glib/glibmm/containers.cc
@@ -0,0 +1,33 @@
+// -*- c++ -*-
+
+/* $Id$ */
+
+/* containers.h
+ *
+ * Copyright (C) 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/containers.h>
+
+namespace Glib
+{
+
+gpointer glibmm_null_pointer=0;
+
+
+} //namespace Glib
+
diff --git a/glib/glibmm/containers.h b/glib/glibmm/containers.h
new file mode 100644
index 00000000..068d58fd
--- /dev/null
+++ b/glib/glibmm/containers.h
@@ -0,0 +1,358 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_CONTAINERS_H
+#define _GLIBMM_CONTAINERS_H
+
+/* $Id$ */
+
+/* containers.h
+ *
+ * Copyright (C) 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/glist.h>
+#include <glib/gslist.h>
+#include <glibmm/sarray.h> /* for backward compatibility */
+
+#include <iterator>
+#include <glibmmconfig.h>
+
+GTKMM_USING_STD(bidirectional_iterator_tag)
+GTKMM_USING_STD(forward_iterator_tag)
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace Glib
+{
+
+template <class T> class List_Iterator;
+template <class T> class List_ConstIterator;
+template <class T> class List_ReverseIterator;
+
+// Most of these methods in the non-template classes needs to be moved
+// to implementation.
+
+//Daniel Elstner has ideas about generating these per-widget with m4. murrayc.
+
+
+extern GLIBMM_API gpointer glibmm_null_pointer;
+
+template <class T>
+class List_Iterator_Base
+{
+public:
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+} ;
+
+///For instance, List_Iterator< Gtk::Widget >
+template <class T>
+class List_Iterator : public List_Iterator_Base<T>
+{
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef typename List_Iterator_Base<T>::pointer pointer;
+ typedef typename List_Iterator_Base<T>::reference reference;
+
+ GList* const* head_;
+ GList* node_;
+
+ typedef List_Iterator<T> Self;
+
+ List_Iterator(GList* const& head, GList* node)
+ : head_(&head), node_(node)
+ {}
+
+ List_Iterator()
+ : head_(0), node_(0)
+ {}
+
+ List_Iterator(const Self& src)
+ : head_(src.head_), node_(src.node_)
+ {}
+
+ bool operator==(const Self& src) const { return node_ == src.node_; }
+ bool operator!=(const Self& src) const { return node_ != src.node_; }
+
+ Self& operator++()
+ {
+ if (!node_)
+ node_ = g_list_first(*head_);
+ else
+ node_ = (GList*)g_list_next(node_);
+ return *this;
+ }
+
+ Self operator++(int)
+ {
+ Self tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ Self& operator--()
+ {
+ if (!node_)
+ node_ = g_list_last(*head_);
+ else
+ node_ = (GList*)g_list_previous(node_);
+
+ return *this;
+ }
+
+ Self operator--(int)
+ {
+ Self tmp = *this;
+ --*this;
+ return tmp;
+ }
+
+ reference operator*() const
+ {
+ return *(pointer)( node_ ? node_->data : glibmm_null_pointer );
+ }
+
+ pointer operator -> () const { return &operator*(); }
+};
+
+///For instance, SList_Iterator< Gtk::Widget >
+template <class T>
+class SList_Iterator : public List_Iterator_Base<T>
+{
+public:
+ typedef std::forward_iterator_tag iterator_category;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef typename List_Iterator_Base<T>::pointer pointer;
+ typedef typename List_Iterator_Base<T>::reference reference;
+
+ GSList* node_;
+ typedef SList_Iterator<T> Self;
+
+ SList_Iterator(GSList* node)
+ : node_(node)
+ {}
+
+ SList_Iterator()
+ : node_(0)
+ {}
+
+ SList_Iterator(const Self& src)
+ : node_(src.node_)
+ {}
+
+ bool operator==(const Self& src) const { return node_ == src.node_; }
+ bool operator!=(const Self& src) const { return node_ != src.node_; }
+
+ Self& operator++()
+ {
+ node_ = g_slist_next(node_);
+ return *this;
+ }
+
+ Self operator++(int)
+ {
+ Self tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ reference operator*() const
+ {
+ g_assert(node_);
+ return reinterpret_cast<T&>( node_ ? node_->data : glibmm_null_pointer );
+ }
+
+ pointer operator -> () const { return &operator*(); }
+};
+
+
+// This iterator variation returns T_IFace (wrapped from T_Impl)
+// For instance, List_Cpp_Iterator<GtkWidget, Gtk::Widget> is a little like std::list<Gtk::Widget>::iterator
+template<class T_Impl, class T_IFace>
+class List_Cpp_Iterator : public List_Iterator_Base<T_IFace>
+{
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef typename List_Iterator_Base<T_IFace>::pointer pointer;
+ typedef typename List_Iterator_Base<T_IFace>::reference reference;
+
+ typedef List_Cpp_Iterator<T_Impl, T_IFace> Self;
+
+ GList** head_;
+ GList* node_;
+
+ bool operator==(const Self& src) const { return node_ == src.node_; }
+ bool operator!=(const Self& src) const { return node_ != src.node_; }
+
+ List_Cpp_Iterator(GList*& head, GList* node )
+ : head_(&head), node_(node )
+ {}
+
+ List_Cpp_Iterator()
+ : head_(0), node_(0)
+ {}
+
+ List_Cpp_Iterator(const Self& src)
+ : head_(src.head_), node_(src.node_)
+ {}
+
+ reference operator*() const
+ {
+ if (node_ && node_->data)
+ return *Glib::wrap(static_cast<T_Impl*>((*node_).data));
+
+ return *(pointer)glibmm_null_pointer;
+ }
+
+ pointer operator->() const { return &operator*(); }
+
+ Self& operator++()
+ {
+ if (!node_)
+ node_ = g_list_first(*head_);
+ else
+ node_ = (GList *)g_list_next(node_);
+
+ return *this;
+ }
+
+ Self operator++(int)
+ {
+ Self tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ Self& operator--()
+ {
+ if (!node_)
+ node_ = g_list_last(*head_);
+ else
+ node_ = (GList *)g_list_previous(node_);
+
+ return *this;
+ }
+
+ Self operator--(int)
+ {
+ Self tmp = *this;
+ --*this;
+ return tmp;
+ }
+
+};
+
+template <class T_Base>
+class List_ReverseIterator: private T_Base
+{
+public:
+ typedef typename T_Base::iterator_category iterator_category;
+ typedef typename T_Base::size_type size_type;
+ typedef typename T_Base::difference_type difference_type;
+
+ typedef typename T_Base::value_type value_type;
+ typedef typename T_Base::pointer pointer;
+ typedef typename T_Base::reference reference;
+
+ typedef List_ReverseIterator<T_Base> Self;
+
+ bool operator==(const Self& src) const { return T_Base::operator==(src); }
+ bool operator!=(const Self& src) const { return T_Base::operator!=(src); }
+
+ List_ReverseIterator(GList* const& head, GList* node)
+ : T_Base(head, node)
+ {}
+
+ List_ReverseIterator()
+ : T_Base()
+ {}
+
+ List_ReverseIterator(const Self& src)
+ : T_Base(src)
+ {}
+
+ List_ReverseIterator(const T_Base& src)
+ : T_Base(src)
+ { ++(*this); }
+
+
+ Self& operator++() {T_Base::operator--(); return *this;}
+ Self& operator--() {T_Base::operator++(); return *this;}
+ Self operator++(int) {Self src = *this; T_Base::operator--(); return src;}
+ Self operator--(int) {Self src = *this; T_Base::operator++(); return src;}
+
+ reference operator*() const { return T_Base::operator*(); }
+ pointer operator->() const { return T_Base::operator->(); }
+};
+
+template <class T_Base>
+class List_ConstIterator: public T_Base
+{
+public:
+ typedef typename T_Base::iterator_category iterator_category;
+ typedef typename T_Base::size_type size_type;
+ typedef typename T_Base::difference_type difference_type;
+
+ typedef const typename T_Base::value_type value_type;
+ typedef const typename T_Base::pointer pointer;
+ typedef const typename T_Base::reference reference;
+
+ typedef List_ConstIterator<T_Base> Self;
+
+ bool operator==(const Self& src) const { return T_Base::operator==(src); }
+ bool operator!=(const Self& src) const { return T_Base::operator!=(src); }
+
+ List_ConstIterator(GList* const& head, GList* node)
+ : T_Base(head, node)
+ {}
+
+ List_ConstIterator()
+ : T_Base()
+ {}
+
+ List_ConstIterator(const Self& src)
+ : T_Base(src)
+ {}
+
+ List_ConstIterator(const T_Base& src)
+ : T_Base(src)
+ {}
+
+ Self& operator++() {T_Base::operator++(); return *this;}
+ Self& operator--() {T_Base::operator--(); return *this;}
+ Self operator++(int) {Self src = *this; T_Base::operator++(); return src;}
+ Self operator--(int) {Self src = *this; T_Base::operator--(); return src;}
+
+ reference operator*() const { return T_Base::operator*(); }
+ pointer operator->() const { return T_Base::operator->(); }
+};
+
+} // namespace Glib
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* _GLIBMM_CONTAINERS_H */
+
diff --git a/glib/glibmm/debug.cc b/glib/glibmm/debug.cc
new file mode 100644
index 00000000..de181ebf
--- /dev/null
+++ b/glib/glibmm/debug.cc
@@ -0,0 +1,21 @@
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/debug.h>
+
diff --git a/glib/glibmm/debug.h b/glib/glibmm/debug.h
new file mode 100644
index 00000000..0ece7f55
--- /dev/null
+++ b/glib/glibmm/debug.h
@@ -0,0 +1,85 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_DEBUG_H
+#define _GLIBMM_DEBUG_H
+
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gmacros.h>
+#include <glibmmconfig.h>
+
+// Some stuff that's useful when debugging gtkmm internals:
+
+#ifdef GTKMM_DEBUG_REFCOUNTING
+
+#include <glib/gmessages.h>
+
+/* We can't use G_GNUC_PRETTY_FUNCTION because it's always disabled in C++,
+ * even though __PRETTY_FUNCTION__ works fine in C++ as well if you use it
+ * right (i.e. concatenation with string literals isn't allowed).
+ */
+#ifdef __GNUC__
+#define GTKMM_GNUC_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else
+#define GTKMM_GNUC_PRETTY_FUNCTION ""
+#endif
+
+#define GTKMM_DEBUG_REFERENCE(cppInstance, cInstance) \
+ G_STMT_START{ \
+ void *const cppInstance__ = (void*) (cppInstance); \
+ void *const cInstance__ = (void*) (cInstance); \
+ g_log(G_LOG_DOMAIN, \
+ G_LOG_LEVEL_DEBUG, \
+ "file %s: line %d (%s):\n" \
+ "ref: C++ instance: %p; C instance: %p, ref_count = %u, type = %s\n", \
+ __FILE__, \
+ __LINE__, \
+ GTKMM_GNUC_PRETTY_FUNCTION, \
+ cppInstance__, \
+ cInstance__, \
+ G_OBJECT(cInstance__)->ref_count, \
+ G_OBJECT_TYPE_NAME(cInstance__)); \
+ }G_STMT_END
+
+#define GTKMM_DEBUG_UNREFERENCE(cppInstance, cInstance) \
+ G_STMT_START{ \
+ void *const cppInstance__ = (void*) (cppInstance); \
+ void *const cInstance__ = (void*) (cInstance); \
+ g_log(G_LOG_DOMAIN, \
+ G_LOG_LEVEL_DEBUG, \
+ "file %s: line %d (%s):\n" \
+ "unref: C++ instance: %p; C instance: %p, ref_count = %u, type = %s\n", \
+ __FILE__, \
+ __LINE__, \
+ GTKMM_GNUC_PRETTY_FUNCTION, \
+ cppInstance__, \
+ cInstance__, \
+ G_OBJECT(cInstance__)->ref_count, \
+ G_OBJECT_TYPE_NAME(cInstance__)); \
+ }G_STMT_END
+
+#else
+
+#define GTKMM_DEBUG_REFERENCE(cppInstance,cInstance) G_STMT_START{ (void)0; }G_STMT_END
+#define GTKMM_DEBUG_UNREFERENCE(cppInstance,cInstance) G_STMT_START{ (void)0; }G_STMT_END
+
+#endif /* GTKMM_DEBUG_REFCOUNTING */
+
+#endif /* _GLIBMM_DEBUG_H */
+
diff --git a/glib/glibmm/dispatcher.cc b/glib/glibmm/dispatcher.cc
new file mode 100644
index 00000000..7dfce6c0
--- /dev/null
+++ b/glib/glibmm/dispatcher.cc
@@ -0,0 +1,325 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/dispatcher.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/fileutils.h>
+#include <glibmm/main.h>
+#include <glibmm/thread.h>
+#include <sigc++/class_slot.h>
+
+#include <cerrno>
+#include <glib.h>
+
+#ifndef G_OS_WIN32
+#include <fcntl.h>
+#include <unistd.h>
+#else
+#include <windows.h>
+#include <fcntl.h>
+#include <direct.h>
+#endif /* G_OS_WIN32 */
+
+
+namespace
+{
+
+struct DispatchNotifyData
+{
+ unsigned long tag;
+ Glib::Dispatcher* dispatcher;
+ Glib::DispatchNotifier* notifier;
+};
+
+void warn_failed_pipe_io(const char* what, int err_no)
+{
+ g_critical("Error in inter-thread communication: %s() failed: %s", what, g_strerror(err_no));
+}
+
+#ifndef G_OS_WIN32
+
+/* Try to set the close-on-exec flag of the file descriptor,
+ * so that it won't be leaked if a new process is spawned.
+ */
+void fd_set_close_on_exec(int fd)
+{
+ const int flags = fcntl(fd, F_GETFD, 0);
+ g_return_if_fail(flags >= 0);
+
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+}
+
+#endif /* G_OS_WIN32 */
+
+/* One word: paranoia.
+ */
+void fd_close_and_invalidate(int& fd)
+{
+ if(fd >= 0)
+ {
+ int result;
+
+ do { result = close(fd); }
+ while(result < 0 && errno == EINTR);
+
+ if(result < 0)
+ warn_failed_pipe_io("close", errno);
+
+ fd = -1;
+ }
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+class DispatchNotifier
+{
+public:
+ ~DispatchNotifier();
+
+ static DispatchNotifier* reference_instance(const Glib::RefPtr<MainContext>& context);
+ static void unreference_instance(DispatchNotifier* notifier);
+
+ void send_notification(Dispatcher* dispatcher);
+
+protected:
+ // Only used by reference_instance(). Should be private, but that triggers
+ // a silly gcc warning even though DispatchNotifier has static methods.
+ explicit DispatchNotifier(const Glib::RefPtr<MainContext>& context);
+
+private:
+ static Glib::StaticPrivate<DispatchNotifier> thread_specific_instance_;
+
+ Glib::RefPtr<MainContext> context_;
+ int ref_count_;
+ int fd_receiver_;
+ int fd_sender_;
+ SigC::Connection conn_io_handler_;
+
+ void create_pipe();
+ bool pipe_io_handler(Glib::IOCondition condition);
+
+ // noncopyable
+ DispatchNotifier(const DispatchNotifier&);
+ DispatchNotifier& operator=(const DispatchNotifier&);
+};
+
+
+/**** Glib::DispatchNotifier ***********************************************/
+
+Glib::StaticPrivate<DispatchNotifier>
+DispatchNotifier::thread_specific_instance_ = GLIBMM_STATIC_PRIVATE_INIT;
+
+DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context)
+:
+ context_ (context),
+ ref_count_ (0),
+ fd_receiver_ (-1),
+ fd_sender_ (-1)
+{
+ create_pipe();
+
+ try
+ {
+ conn_io_handler_ = context_->signal_io().connect(
+ SigC::slot_class(*this, &DispatchNotifier::pipe_io_handler),
+ fd_receiver_, Glib::IO_IN);
+ }
+ catch(...)
+ {
+ fd_close_and_invalidate(fd_sender_);
+ fd_close_and_invalidate(fd_receiver_);
+
+ throw;
+ }
+}
+
+DispatchNotifier::~DispatchNotifier()
+{
+ // Disconnect manually because we're using SigC::slot_class().
+ conn_io_handler_.disconnect();
+
+ fd_close_and_invalidate(fd_sender_);
+ fd_close_and_invalidate(fd_receiver_);
+}
+
+void DispatchNotifier::create_pipe()
+{
+ int filedes[2] = { -1, -1 };
+
+ if(pipe(filedes) < 0)
+ {
+ GError *const error = g_error_new(
+ G_FILE_ERROR, g_file_error_from_errno(errno),
+ "Failed to create pipe for inter-thread communication: %s", g_strerror(errno));
+
+ throw Glib::FileError(error);
+ }
+
+#ifndef G_OS_WIN32
+ fd_set_close_on_exec(filedes[0]);
+ fd_set_close_on_exec(filedes[1]);
+#endif
+
+ fd_receiver_ = filedes[0];
+ fd_sender_ = filedes[1];
+}
+
+// static
+DispatchNotifier* DispatchNotifier::reference_instance(const Glib::RefPtr<MainContext>& context)
+{
+ DispatchNotifier* instance = thread_specific_instance_.get();
+
+ if(!instance)
+ {
+ instance = new DispatchNotifier(context);
+ thread_specific_instance_.set(instance);
+ }
+ else
+ {
+ // Prevent massive mess-up.
+ g_return_val_if_fail(instance->context_ == context, 0);
+ }
+
+ ++instance->ref_count_; // initially 0
+
+ return instance;
+}
+
+// static
+void DispatchNotifier::unreference_instance(DispatchNotifier* notifier)
+{
+ DispatchNotifier *const instance = thread_specific_instance_.get();
+
+ // Yes, the notifier argument is only used to check for sanity.
+ g_return_if_fail(instance == notifier);
+
+ if(--instance->ref_count_ <= 0)
+ {
+ g_return_if_fail(instance->ref_count_ == 0); // could be < 0 if messed up
+
+ // This will cause deletion of the notifier object.
+ thread_specific_instance_.set(0);
+ }
+}
+
+void DispatchNotifier::send_notification(Dispatcher* dispatcher)
+{
+ DispatchNotifyData data = { 0xdeadbeef, dispatcher, this };
+ gssize n_written;
+
+ do { n_written = write(fd_sender_, &data, sizeof(data)); }
+ while(n_written < 0 && errno == EINTR);
+
+ if(n_written < 0)
+ {
+ warn_failed_pipe_io("write", errno);
+ return;
+ }
+
+ // All data must be written in a single call to write(), otherwise we can't
+ // guarantee reentrancy since another thread might be scheduled between two
+ // write() calls. The manpage is a bit unclear about this -- but I hope
+ // it's safe to assume immediate success for the tiny amount of data we're
+ // writing.
+ g_return_if_fail(n_written == sizeof(data));
+}
+
+bool DispatchNotifier::pipe_io_handler(Glib::IOCondition)
+{
+ DispatchNotifyData data = { 0, 0, 0 };
+ gsize n_read = 0;
+
+ do
+ {
+ void * const buffer = reinterpret_cast<guint8*>(&data) + n_read;
+ const gssize result = read(fd_receiver_, buffer, sizeof(data) - n_read);
+
+ if(result < 0)
+ {
+ if(errno == EINTR)
+ continue;
+
+ warn_failed_pipe_io("read", errno);
+ return true;
+ }
+
+ n_read += result;
+ }
+ while(n_read < sizeof(data));
+
+ g_return_val_if_fail(data.tag == 0xdeadbeef, true);
+ g_return_val_if_fail(data.notifier == this, true);
+
+ // Actually, we wouldn't need the try/catch block because the Glib::Source
+ // C callback already does it for us. However, we do it anyway because the
+ // default return value is 'false', which is not what we want.
+ try
+ {
+ data.dispatcher->signal_(); // emit
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return true;
+}
+
+
+/**** Glib::Dispatcher *****************************************************/
+
+Dispatcher::Dispatcher()
+:
+ signal_ (),
+ notifier_ (DispatchNotifier::reference_instance(MainContext::get_default()))
+{}
+
+Dispatcher::Dispatcher(const Glib::RefPtr<MainContext>& context)
+:
+ signal_ (),
+ notifier_ (DispatchNotifier::reference_instance(context))
+{}
+
+Dispatcher::~Dispatcher()
+{
+ DispatchNotifier::unreference_instance(notifier_);
+}
+
+void Dispatcher::emit()
+{
+ notifier_->send_notification(this);
+}
+
+void Dispatcher::operator()()
+{
+ emit();
+}
+
+SigC::Connection Dispatcher::connect(const SigC::Slot0<void>& slot)
+{
+ return signal_.connect(slot);
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/dispatcher.h b/glib/glibmm/dispatcher.h
new file mode 100644
index 00000000..7e086883
--- /dev/null
+++ b/glib/glibmm/dispatcher.h
@@ -0,0 +1,102 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_DISPATCHER_H
+#define _GLIBMM_DISPATCHER_H
+
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sigc++/sigc++.h>
+#include <glibmm/main.h>
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class DispatchNotifier;
+#endif
+
+/** Signal class for inter-thread communication.
+ * @ingroup Threads
+ * Glib::Dispatcher works similar to SigC::Signal0<void>. But unlike normal
+ * signals, the notification happens asynchronously through a pipe. This is
+ * a simple and efficient way of communicating between threads, and especially
+ * useful in a thread model with a single GUI thread.
+ *
+ * No mutex locking is involved, apart from the operating system's internal
+ * I/O locking. That implies some usage rules:
+ *
+ * @li Only one thread may connect to the signal and receive notification, but
+ * multiple senders are allowed even without locking.
+ * @li The GLib main loop must run in the receiving thread (this will be the
+ * GUI thread usually).
+ * @li The Dispatcher object must be instantiated by the receiver thread.
+ * @li The Dispatcher object should be instantiated before creating any of the
+ * sender threads, if you want to avoid extra locking.
+ *
+ * Notes about performance:
+ *
+ * @li After instantiation, Glib::Dispatcher will never lock any mutexes on its
+ * own. The interaction with the GLib main loop might involve locking on the
+ * @em receiver side. The @em sender side, however, is guaranteed not to lock,
+ * except for internal locking in the <tt>%write()</tt> system call.
+ * @li All Dispatcher instances of a receiver thread share the same pipe. That
+ * is, if you use Glib::Dispatcher only to notify the GUI thread, only one pipe
+ * is created no matter how many Dispatcher objects you have.
+ */
+class Dispatcher
+{
+public:
+ /** Create new Dispatcher instance using the default main context.
+ * @throw Glib::FileError
+ */
+ Dispatcher();
+ /** Create new Dispatcher instance using an arbitrary main context.
+ * @throw Glib::FileError
+ */
+ explicit Dispatcher(const Glib::RefPtr<MainContext>& context);
+ ~Dispatcher();
+
+ void emit();
+ void operator()();
+
+ SigC::Connection connect(const SigC::Slot0<void>& slot);
+
+private:
+ SigC::Signal0<void> signal_;
+ DispatchNotifier* notifier_;
+
+ // noncopyable
+ Dispatcher(const Dispatcher&);
+ Dispatcher& operator=(const Dispatcher&);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ friend class Glib::DispatchNotifier;
+#endif
+};
+
+/*! A Glib::Dispatcher example.
+ * @example thread/dispatcher.cc
+ */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_DISPATCHER_H */
+
diff --git a/glib/glibmm/error.cc b/glib/glibmm/error.cc
new file mode 100644
index 00000000..3f1e0ca1
--- /dev/null
+++ b/glib/glibmm/error.cc
@@ -0,0 +1,187 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* error.cc
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gerror.h>
+#include <glib/gmessages.h>
+
+#include <map>
+#include <glibmmconfig.h>
+#include <glibmm/error.h>
+#include <glibmm/wrap_init.h>
+
+GTKMM_USING_STD(map)
+
+
+namespace
+{
+
+typedef std::map<GQuark,Glib::Error::ThrowFunc> ThrowFuncTable;
+
+ThrowFuncTable* throw_func_table = 0;
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+Error::Error()
+:
+ gobject_ (0)
+{}
+
+Error::Error(GQuark domain, int code, const Glib::ustring& message)
+:
+ gobject_ (g_error_new_literal(domain, code, message.c_str()))
+{}
+
+Error::Error(GError* gobject, bool take_copy)
+:
+ gobject_ ((take_copy && gobject) ? g_error_copy(gobject) : gobject)
+{}
+
+Error::Error(const Error& other)
+:
+ Exception(other),
+ gobject_ ((other.gobject_) ? g_error_copy(other.gobject_) : 0)
+{}
+
+Error& Error::operator=(const Error& other)
+{
+ if(gobject_ != other.gobject_)
+ {
+ if(gobject_)
+ {
+ g_error_free(gobject_);
+ gobject_ = 0;
+ }
+ if(other.gobject_)
+ {
+ gobject_ = g_error_copy(other.gobject_);
+ }
+ }
+ return *this;
+}
+
+Error::~Error() throw()
+{
+ if(gobject_)
+ g_error_free(gobject_);
+}
+
+GQuark Error::domain() const
+{
+ g_return_val_if_fail(gobject_ != 0, 0);
+
+ return gobject_->domain;
+}
+
+int Error::code() const
+{
+ g_return_val_if_fail(gobject_ != 0, -1);
+
+ return gobject_->code;
+}
+
+Glib::ustring Error::what() const
+{
+ g_return_val_if_fail(gobject_ != 0, "");
+ g_return_val_if_fail(gobject_->message != 0, "");
+
+ return gobject_->message;
+}
+
+bool Error::matches(GQuark domain, int code) const
+{
+ return g_error_matches(gobject_, domain, code);
+}
+
+GError* Error::gobj()
+{
+ return gobject_;
+}
+
+const GError* Error::gobj() const
+{
+ return gobject_;
+}
+
+void Error::propagate(GError** dest)
+{
+ g_propagate_error(dest, gobject_);
+ gobject_ = 0;
+}
+
+
+// static
+void Error::register_init()
+{
+ if(!throw_func_table)
+ {
+ throw_func_table = new ThrowFuncTable();
+ Glib::wrap_init(); // make sure that at least the Glib exceptions are registered
+ }
+}
+
+// static
+void Error::register_cleanup()
+{
+ if(throw_func_table)
+ {
+ delete throw_func_table;
+ throw_func_table = 0;
+ }
+}
+
+// static
+void Error::register_domain(GQuark domain, Error::ThrowFunc throw_func)
+{
+ g_assert(throw_func_table != 0);
+
+ (*throw_func_table)[domain] = throw_func;
+}
+
+// static, noreturn
+void Error::throw_exception(GError* gobject)
+{
+ g_assert(gobject != 0);
+
+ // Just in case Gtk::Main hasn't been instantiated yet.
+ if(!throw_func_table)
+ register_init();
+
+ if(const ThrowFunc throw_func = (*throw_func_table)[gobject->domain])
+ {
+ (*throw_func)(gobject);
+ g_assert_not_reached();
+ }
+
+ g_warning("Glib::Error::throw_exception():\n "
+ "unknown error domain '%s': throwing generic Glib::Error exception\n",
+ (gobject->domain) ? g_quark_to_string(gobject->domain) : "(null)");
+
+ // Doesn't copy, because error-returning functions return a newly allocated GError for us.
+ throw Glib::Error(gobject);
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/error.h b/glib/glibmm/error.h
new file mode 100644
index 00000000..d4c39e6d
--- /dev/null
+++ b/glib/glibmm/error.h
@@ -0,0 +1,77 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_ERROR_H
+#define _GLIBMM_ERROR_H
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GError GError; }
+#endif
+
+#include <glib/gquark.h>
+#include <glibmm/exception.h>
+
+
+namespace Glib
+{
+
+class Error : public Glib::Exception
+{
+public:
+ Error();
+ Error(GQuark domain, int code, const Glib::ustring& message);
+ explicit Error(GError* gobject, bool take_copy = false);
+
+ Error(const Error& other);
+ Error& operator=(const Error& other);
+
+ virtual ~Error() throw();
+
+ GQuark domain() const;
+ int code() const;
+ virtual Glib::ustring what() const;
+
+ bool matches(GQuark domain, int code) const;
+
+ GError* gobj();
+ const GError* gobj() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ void propagate(GError** dest);
+
+ typedef void (* ThrowFunc) (GError*);
+
+ static void register_init();
+ static void register_cleanup();
+ static void register_domain(GQuark domain, ThrowFunc throw_func);
+
+ static void throw_exception(GError* gobject) G_GNUC_NORETURN;
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+protected:
+ GError* gobject_;
+};
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_ERROR_H */
+
diff --git a/glib/glibmm/exception.cc b/glib/glibmm/exception.cc
new file mode 100644
index 00000000..22345b28
--- /dev/null
+++ b/glib/glibmm/exception.cc
@@ -0,0 +1,40 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* exception.cc
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gmessages.h>
+#include <glibmm/exception.h>
+
+
+namespace Glib
+{
+
+Exception::~Exception() throw()
+{}
+
+Glib::ustring Exception::what() const
+{
+ g_assert_not_reached();
+ return Glib::ustring();
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/exception.h b/glib/glibmm/exception.h
new file mode 100644
index 00000000..7f0dd43c
--- /dev/null
+++ b/glib/glibmm/exception.h
@@ -0,0 +1,42 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_EXCEPTION_H
+#define _GLIBMM_EXCEPTION_H
+/* $Id$ */
+
+/* exception.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/ustring.h>
+
+
+namespace Glib
+{
+
+class Exception
+{
+public:
+ virtual ~Exception() throw() = 0;
+ virtual Glib::ustring what() const = 0;
+};
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_EXCEPTION_H */
+
diff --git a/glib/glibmm/exceptionhandler.cc b/glib/glibmm/exceptionhandler.cc
new file mode 100644
index 00000000..52408b91
--- /dev/null
+++ b/glib/glibmm/exceptionhandler.cc
@@ -0,0 +1,193 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* exceptionhandler.cc
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib.h>
+#include <exception>
+#include <list>
+
+#include <glibmmconfig.h>
+#include <glibmm/error.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/thread.h>
+
+GTKMM_USING_STD(exception)
+GTKMM_USING_STD(list)
+
+
+namespace
+{
+
+typedef std::list< SigC::Slot0<void> > HandlerList;
+
+// Each thread has its own list of exception handlers
+// to avoid thread synchronization problems.
+Glib::StaticPrivate<HandlerList> thread_specific_handler_list = GLIBMM_STATIC_PRIVATE_INIT;
+
+
+class HandlerConnectionNode : public SigC::ConnectionNode
+{
+public:
+ explicit HandlerConnectionNode(const SigC::Slot0<void>& slot)
+ : SigC::ConnectionNode(static_cast<SigC::SlotNode*>(slot.impl())) {}
+
+ virtual void notify(bool from_child);
+};
+
+void HandlerConnectionNode::notify(bool from_child)
+{
+ if(HandlerList *const handler_list = thread_specific_handler_list.get())
+ {
+ // We can't use remove_if() because it's possible to insert the same
+ // slot multiple times, although unlikely. std::list<>::remove_if()
+ // would remove only the first matching element.
+
+ HandlerList::iterator pslot = handler_list->begin();
+
+ while(pslot != handler_list->end())
+ {
+ if(pslot->impl() == slot().impl())
+ pslot = handler_list->erase(pslot);
+ else
+ ++pslot;
+ }
+ }
+
+ SigC::ConnectionNode::notify(from_child);
+}
+
+
+void glibmm_exception_warning(const GError* error)
+{
+ g_assert(error != 0);
+
+ g_critical("\n"
+ "unhandled exception (type Glib::Error) in signal handler:\n"
+ "domain: %s\n"
+ "code : %d\n"
+ "what : %s\n",
+ g_quark_to_string(error->domain), error->code,
+ (error->message) ? error->message : "(null)");
+}
+
+void glibmm_unexpected_exception()
+{
+ try
+ {
+ throw; // re-throw current exception
+ }
+ catch(const Glib::Error& error)
+ {
+ // Access the GError directly, to avoid possible exceptions from C++ code.
+ glibmm_exception_warning(error.gobj());
+
+ // For most failures that cause a Glib::Error exception, aborting the
+ // program seems too harsh. Instead, give control back to the main loop.
+ return;
+ }
+ catch(const std::exception& except)
+ {
+ g_error("\n"
+ "unhandled exception (type std::exception) in signal handler:\n"
+ "what: %s\n", except.what());
+ }
+ catch(...)
+ {
+ g_error("\nunhandled exception (type unknown) in signal handler\n");
+ }
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+SigC::Connection add_exception_handler(const SigC::Slot0<void>& slot)
+{
+ HandlerList* handler_list = thread_specific_handler_list.get();
+
+ if(!handler_list)
+ {
+ handler_list = new HandlerList();
+ thread_specific_handler_list.set(handler_list);
+ }
+
+ const SigC::Connection connection (new HandlerConnectionNode(slot));
+ handler_list->push_front(slot);
+
+ return connection;
+}
+
+// internal
+void exception_handlers_invoke() throw()
+{
+ // This function will be called from our GLib signal handler proxies
+ // if an exception has been caught. It's not possible to throw C++
+ // exceptions through C signal handlers. To handle this situation, the
+ // programmer can install slots to global Reusable Exception Handlers.
+ //
+ // A handler has to re-throw the current exception in a try block, and then
+ // catch the exceptions it knows about. Any unknown exceptions should just
+ // fall through, i.e. the handler must not do catch(...).
+ //
+ // We now invoke each of the installed slots until the exception has been
+ // handled. If there are no more handlers in the list and the exception
+ // is still unhandled, call glibmm_unexpected_exception().
+
+ if(HandlerList *const handler_list = thread_specific_handler_list.get())
+ {
+ HandlerList::iterator pslot = handler_list->begin();
+
+ while(pslot != handler_list->end())
+ {
+ // Calling an empty slot would mean ignoring the exception,
+ // thus we have to check for dead slots explicitly.
+ if(pslot->empty())
+ {
+ pslot = handler_list->erase(pslot);
+ continue;
+ }
+
+ // Call the Reusable Exception Handler, which should re-throw
+ // the exception that's currently on the stack.
+ try
+ {
+ (*pslot)();
+ }
+ catch(...) // unhandled, try next slot
+ {
+ ++pslot;
+ continue;
+ }
+
+ // The exception has either been handled or ignored.
+ // Give control back to the GLib main loop.
+ return;
+ }
+ }
+
+ // Critical: The exception is still unhandled.
+ glibmm_unexpected_exception();
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/exceptionhandler.h b/glib/glibmm/exceptionhandler.h
new file mode 100644
index 00000000..ccbc239f
--- /dev/null
+++ b/glib/glibmm/exceptionhandler.h
@@ -0,0 +1,45 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_EXCEPTIONHANDLER_H
+#define _GLIBMM_EXCEPTIONHANDLER_H
+
+/* $Id$ */
+
+/* exceptionhandler.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sigc++/sigc++.h>
+
+
+namespace Glib
+{
+
+/** Specify a slot to be called when an exception is thrown by a signal handler.
+ */
+SigC::Connection add_exception_handler(const SigC::Slot0<void>& slot);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+// internal
+void exception_handlers_invoke() throw();
+#endif
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_EXCEPTIONHANDLER_H */
+
diff --git a/glib/glibmm/helperlist.h b/glib/glibmm/helperlist.h
new file mode 100644
index 00000000..50685e80
--- /dev/null
+++ b/glib/glibmm/helperlist.h
@@ -0,0 +1,165 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_HELPERLIST_H
+#define _GLIBMM_HELPERLIST_H
+/* $Id$ */
+
+/* helperlist.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/containers.h>
+
+namespace Glib
+{
+
+// This class has some pure virtual methods which need to be implemented by derived classes.
+template< typename T_Child, typename T_CppElement, typename T_Iterator >
+class HelperList
+{
+public:
+ HelperList()
+ : gparent_(0)
+ {}
+
+ HelperList(GObject* gparent)
+ : gparent_(gparent)
+ {}
+
+ virtual ~HelperList()
+ {}
+
+ typedef T_Child value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+
+ typedef T_Iterator iterator;
+ typedef List_ConstIterator<iterator> const_iterator;
+ typedef List_ReverseIterator<iterator> reverse_iterator;
+ typedef List_ConstIterator<reverse_iterator> const_reverse_iterator;
+
+ typedef T_CppElement element_type;
+
+ typedef size_t difference_type;
+ typedef size_t size_type;
+
+ //These are implemented differently for each Helper List.
+ virtual iterator erase(iterator) = 0;
+
+ virtual void erase(iterator start, iterator stop)
+ {
+ while(start != stop)
+ start = erase(start); //Implemented in derived class.
+ }
+
+ virtual void remove(const_reference) = 0;
+
+ size_type size() const
+ {
+ return g_list_length(glist());
+ }
+
+ inline size_type max_size() { return size_type(-1); }
+ inline bool empty() { return glist() == 0; }
+
+ inline iterator begin()
+ {return begin_();}
+ inline iterator end()
+ {return end_();}
+
+ inline const_iterator begin() const
+ { return const_iterator(begin_()); }
+ inline const_iterator end() const
+ { return const_iterator(end_()); }
+
+ inline reverse_iterator rbegin()
+ { return reverse_iterator(end_()); }
+ inline reverse_iterator rend()
+ { return reverse_iterator(begin_()); }
+
+ inline const_reverse_iterator rbegin() const
+ { return const_reverse_iterator(reverse_iterator(end_())); }
+ inline const_reverse_iterator rend() const
+ { return const_reverse_iterator(reverse_iterator(begin_())); }
+
+ reference front() const
+ {
+ return *begin();
+ }
+
+ reference back() const
+ {
+ return *(--end());
+ }
+
+ reference operator[](size_type l) const
+ {
+ size_type j = 0;
+ iterator i;
+ for(i = begin(), j = 0; i != end(), j < l; ++i, ++j);
+ return (*i);
+ }
+
+// iterator find(const_reference w)
+// {
+// iterator i = begin();
+// for(i = begin(); i != end() && (*i != w); i++);
+// return i;
+// }
+//
+// iterator find(Widget& w)
+// {
+// iterator i;
+// for (i = begin(); i != end() && ((*i)->$1() != &w); i++);
+// return i;
+// }
+
+ //Derived classes might choose to reimplement these as public:
+ inline void pop_front()
+ { erase(begin()); }
+ inline void pop_back()
+ { erase(--end()); }
+
+ void clear()
+ { erase(begin(), end()); }
+
+ GObject* gparent()
+ { return gparent_; };
+ const GObject* gparent() const
+ { return gparent_; };
+
+protected:
+ virtual GList*& glist() const = 0; // front of list
+
+ iterator begin_() const
+ {
+ return iterator(glist(), glist());
+ }
+
+ iterator end_() const
+ {
+ return iterator(glist(), (GList*)0);
+ }
+
+ GObject* gparent_;
+};
+
+
+} /* namespace Glib */
+
+#endif /* _GLIBMM_HELPERLIST_H */
+
diff --git a/glib/glibmm/interface.cc b/glib/glibmm/interface.cc
new file mode 100644
index 00000000..1c7ed550
--- /dev/null
+++ b/glib/glibmm/interface.cc
@@ -0,0 +1,91 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/interface.h>
+#include <glibmm/private/interface_p.h>
+
+
+namespace Glib
+{
+
+/**** Glib::Interface_Class ************************************************/
+
+void Interface_Class::add_interface(GType instance_type) const
+{
+ const GInterfaceInfo interface_info =
+ {
+ class_init_func_,
+ 0, // interface_finalize
+ 0, // interface_data
+ };
+
+ g_type_add_interface_static(instance_type, gtype_, &interface_info);
+}
+
+
+/**** Interface Glib::Interface ********************************************/
+
+Interface::Interface(const Interface_Class& interface_class)
+{
+ //gobject_ will be set in the Object constructor.
+ //Any instantiable class that derives from Interface should also inherit from Object.
+
+ // If I understand it correctly, gobject_ shouldn't be 0 now. daniel.
+ // TODO: Make this a g_assert() if the assumption above is correct.
+
+ g_return_if_fail(gobject_ != 0);
+
+ if(custom_type_name_ && !is_anonymous_custom_())
+ {
+ void *const instance_class = G_OBJECT_GET_CLASS(gobject_);
+
+ if(!g_type_interface_peek(instance_class, interface_class.get_type()))
+ {
+ interface_class.add_interface(G_OBJECT_CLASS_TYPE(instance_class));
+ }
+ }
+}
+
+Interface::Interface(GObject* castitem)
+{
+ // Connect GObject and wrapper instances.
+ ObjectBase::initialize(castitem);
+}
+
+Interface::~Interface()
+{}
+
+GType Interface::get_type()
+{
+ return G_TYPE_INTERFACE;
+}
+
+GType Interface::get_base_type()
+{
+ return G_TYPE_INTERFACE;
+}
+
+RefPtr<ObjectBase> wrap_interface(GObject* object, bool take_copy)
+{
+ return Glib::RefPtr<ObjectBase>( wrap_auto(object, take_copy) );
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/interface.h b/glib/glibmm/interface.h
new file mode 100644
index 00000000..ce9bf509
--- /dev/null
+++ b/glib/glibmm/interface.h
@@ -0,0 +1,72 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_INTERFACE_H
+#define _GLIBMM_INTERFACE_H
+
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/object.h>
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class Interface_Class;
+#endif
+
+// There is no base GInterface struct in Glib, though there is G_TYPE_INTERFACE enum value.
+class Interface : virtual public Glib::ObjectBase
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ typedef Interface CppObjectType;
+ typedef Interface_Class CppClassType;
+ typedef GTypeInterface BaseClassType;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+ explicit Interface(const Glib::Interface_Class& interface_class);
+ explicit Interface(GObject* castitem);
+ virtual ~Interface();
+
+ //void add_interface(GType gtype_implementer);
+
+ // Hook for translating API
+ //static Glib::Interface* wrap_new(GTypeInterface*);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ static GType get_type() G_GNUC_CONST;
+ static GType get_base_type() G_GNUC_CONST;
+#endif
+
+ inline GObject* gobj() { return gobject_; }
+ inline const GObject* gobj() const { return gobject_; }
+
+private:
+ // noncopyable
+ Interface(const Interface&);
+ Interface& operator=(const Interface&);
+};
+
+RefPtr<ObjectBase> wrap_interface(GObject* object, bool take_copy = false);
+
+} // namespace Glib
+
+#endif /* _GLIBMM_INTERFACE_H */
+
diff --git a/glib/glibmm/listhandle.h b/glib/glibmm/listhandle.h
new file mode 100644
index 00000000..1508149d
--- /dev/null
+++ b/glib/glibmm/listhandle.h
@@ -0,0 +1,404 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_LISTHANDLE_H
+#define _GLIBMM_LISTHANDLE_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/glist.h>
+#include <glibmm/containerhandle_shared.h>
+
+
+namespace Glib
+{
+
+namespace Container_Helpers
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* Create and fill a GList as efficient as possible.
+ * This requires bidirectional iterators.
+ */
+template <class Bi, class Tr>
+GList* create_list(Bi pbegin, Bi pend, Tr)
+{
+ GList* head = 0;
+
+ while(pend != pbegin)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ const void *const item = Tr::to_c_type(*&*--pend);
+ head = g_list_prepend(head, const_cast<void*>(item));
+ }
+
+ return head;
+}
+
+/* Create a GList from a 0-terminated input sequence.
+ * Build it in reverse order and reverse the whole list afterwards,
+ * because appending to the list would be horribly inefficient.
+ */
+template <class For, class Tr>
+GList* create_list(For pbegin, Tr)
+{
+ GList* head = 0;
+
+ while(*pbegin)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ const void *const item = Tr::to_c_type(*&*pbegin);
+ head = g_list_prepend(head, const_cast<void*>(item));
+ ++pbegin;
+ }
+
+ return g_list_reverse(head);
+}
+
+
+/* Convert from any container that supports bidirectional iterators.
+ */
+template <class Tr, class Cont>
+struct ListSourceTraits
+{
+ static GList* get_data(const Cont& cont)
+ { return Glib::Container_Helpers::create_list(cont.begin(), cont.end(), Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+/* Convert from a 0-terminated array. The Cont
+ * argument must be a pointer to the first element.
+ */
+template <class Tr, class Cont>
+struct ListSourceTraits<Tr,Cont*>
+{
+ static GList* get_data(const Cont* array)
+ { return (array) ? Glib::Container_Helpers::create_list(array, Tr()) : 0; }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+template <class Tr, class Cont>
+struct ListSourceTraits<Tr,const Cont*> : ListSourceTraits<Tr,Cont*>
+{};
+
+/* Convert from a 0-terminated array. The Cont argument must be a pointer
+ * to the first element. For consistency, the array must be 0-terminated,
+ * even though the array size is known at compile time.
+ */
+template <class Tr, class Cont, size_t N>
+struct ListSourceTraits<Tr,Cont[N]>
+{
+ static GList* get_data(const Cont* array)
+ { return Glib::Container_Helpers::create_list(array, array + (N - 1), Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+template <class Tr, class Cont, size_t N>
+struct ListSourceTraits<Tr,const Cont[N]> : ListSourceTraits<Tr,Cont[N]>
+{};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/**
+ * @ingroup ContHelpers
+ */
+template <class Tr>
+class ListHandleIterator
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef std::forward_iterator_tag iterator_category;
+ typedef CppType value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type reference;
+ typedef void pointer;
+
+ explicit inline ListHandleIterator(const GList* node);
+
+ inline value_type operator*() const;
+ inline ListHandleIterator<Tr> & operator++();
+ inline const ListHandleIterator<Tr> operator++(int);
+
+ inline bool operator==(const ListHandleIterator<Tr>& rhs) const;
+ inline bool operator!=(const ListHandleIterator<Tr>& rhs) const;
+
+private:
+ const GList* node_;
+};
+
+} // namespace Container_Helpers
+
+
+/**
+ * @ingroup ContHandles
+ */
+template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
+class ListHandle
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef CppType value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef Glib::Container_Helpers::ListHandleIterator<Tr> const_iterator;
+ typedef Glib::Container_Helpers::ListHandleIterator<Tr> iterator;
+
+ template <class Cont> inline
+ ListHandle(const Cont& container);
+
+ // Take over ownership of an array created by GTK+ functions.
+ inline ListHandle(GList* glist, Glib::OwnershipType ownership);
+
+ // Copying clears the ownership flag of the source handle.
+ inline ListHandle(const ListHandle<T,Tr>& other);
+
+ ~ListHandle();
+
+ inline const_iterator begin() const;
+ inline const_iterator end() const;
+
+ template <class U> inline operator std::vector<U>() const;
+ template <class U> inline operator std::deque<U>() const;
+ template <class U> inline operator std::list<U>() const;
+
+ template <class Cont> inline
+ void assign_to(Cont& container) const;
+
+ template <class Out> inline
+ void copy(Out pdest) const;
+
+ inline GList* data() const;
+ inline size_t size() const;
+ inline bool empty() const;
+
+private:
+ GList * plist_;
+ mutable Glib::OwnershipType ownership_;
+
+ // No copy assignment.
+ ListHandle<T,Tr>& operator=(const ListHandle<T,Tr>&);
+};
+
+
+/***************************************************************************/
+/* Inline implementation */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace Container_Helpers
+{
+
+/**** Glib::Container_Helpers::ListHandleIterator<> ************************/
+
+template <class Tr> inline
+ListHandleIterator<Tr>::ListHandleIterator(const GList* node)
+:
+ node_ (node)
+{}
+
+template <class Tr> inline
+typename ListHandleIterator<Tr>::value_type ListHandleIterator<Tr>::operator*() const
+{
+ return Tr::to_cpp_type(static_cast<typename Tr::CTypeNonConst>(node_->data));
+}
+
+template <class Tr> inline
+ListHandleIterator<Tr>& ListHandleIterator<Tr>::operator++()
+{
+ node_ = node_->next;
+ return *this;
+}
+
+template <class Tr> inline
+const ListHandleIterator<Tr> ListHandleIterator<Tr>::operator++(int)
+{
+ const ListHandleIterator<Tr> tmp (*this);
+ node_ = node_->next;
+ return tmp;
+}
+
+template <class Tr> inline
+bool ListHandleIterator<Tr>::operator==(const ListHandleIterator<Tr>& rhs) const
+{
+ return (node_ == rhs.node_);
+}
+
+template <class Tr> inline
+bool ListHandleIterator<Tr>::operator!=(const ListHandleIterator<Tr>& rhs) const
+{
+ return (node_ != rhs.node_);
+}
+
+} // namespace Container_Helpers
+
+
+/**** Glib::ListHandle<> ***************************************************/
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+ListHandle<T,Tr>::ListHandle(const Cont& container)
+:
+ plist_ (Glib::Container_Helpers::ListSourceTraits<Tr,Cont>::get_data(container)),
+ ownership_ (Glib::Container_Helpers::ListSourceTraits<Tr,Cont>::initial_ownership)
+{}
+
+template <class T, class Tr> inline
+ListHandle<T,Tr>::ListHandle(GList* glist, Glib::OwnershipType ownership)
+:
+ plist_ (glist),
+ ownership_ (ownership)
+{}
+
+template <class T, class Tr> inline
+ListHandle<T,Tr>::ListHandle(const ListHandle<T,Tr>& other)
+:
+ plist_ (other.plist_),
+ ownership_ (other.ownership_)
+{
+ other.ownership_ = Glib::OWNERSHIP_NONE;
+}
+
+template <class T, class Tr>
+ListHandle<T,Tr>::~ListHandle()
+{
+ if(ownership_ != Glib::OWNERSHIP_NONE)
+ {
+ if(ownership_ != Glib::OWNERSHIP_SHALLOW)
+ {
+ // Deep ownership: release each container element.
+ for(GList* node = plist_; node != 0; node = node->next)
+ Tr::release_c_type(static_cast<typename Tr::CTypeNonConst>(node->data));
+ }
+ g_list_free(plist_);
+ }
+}
+
+template <class T, class Tr> inline
+typename ListHandle<T,Tr>::const_iterator ListHandle<T,Tr>::begin() const
+{
+ return Glib::Container_Helpers::ListHandleIterator<Tr>(plist_);
+}
+
+template <class T, class Tr> inline
+typename ListHandle<T,Tr>::const_iterator ListHandle<T,Tr>::end() const
+{
+ return Glib::Container_Helpers::ListHandleIterator<Tr>(0);
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+ListHandle<T,Tr>::operator std::vector<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::vector<U>(this->begin(), this->end());
+#else
+ std::vector<U> temp;
+ temp.reserve(this->size());
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+ListHandle<T,Tr>::operator std::deque<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::deque<U>(this->begin(), this->end());
+#else
+ std::deque<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+ListHandle<T,Tr>::operator std::list<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::list<U>(this->begin(), this->end());
+#else
+ std::list<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+void ListHandle<T,Tr>::assign_to(Cont& container) const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ container.assign(this->begin(), this->end());
+#else
+ Cont temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ container.swap(temp);
+#endif
+}
+
+template <class T, class Tr>
+ template <class Out>
+inline
+void ListHandle<T,Tr>::copy(Out pdest) const
+{
+ std::copy(this->begin(), this->end(), pdest);
+}
+
+template <class T, class Tr> inline
+GList* ListHandle<T,Tr>::data() const
+{
+ return plist_;
+}
+
+template <class T, class Tr> inline
+size_t ListHandle<T,Tr>::size() const
+{
+ return g_list_length(plist_);
+}
+
+template <class T, class Tr> inline
+bool ListHandle<T,Tr>::empty() const
+{
+ return (plist_ == 0);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_LISTHANDLE_H */
+
diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc
new file mode 100644
index 00000000..2078b611
--- /dev/null
+++ b/glib/glibmm/main.cc
@@ -0,0 +1,979 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/main.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/thread.h>
+#include <glibmm/wrap.h>
+#include <glibmm/iochannel.h>
+
+#include <glib/gmessages.h>
+#include <algorithm>
+
+GTKMM_USING_STD(min)
+
+
+namespace
+{
+
+class SourceConnectionNode : public SigC::ConnectionNode
+{
+public:
+ explicit inline SourceConnectionNode(const SigC::SlotBase& slot);
+
+ virtual void notify(bool from_child);
+ static void destroy_notify_callback(void* data);
+
+ inline void install(GSource* source);
+ inline SigC::SlotNode* get_slot_node();
+
+private:
+ GSource* source_;
+};
+
+inline
+SourceConnectionNode::SourceConnectionNode(const SigC::SlotBase& slot)
+:
+ SigC::ConnectionNode (static_cast<SigC::SlotNode*>(slot.impl())),
+ source_ (0)
+{}
+
+void SourceConnectionNode::notify(bool from_child)
+{
+ SigC::ConnectionNode::notify(from_child);
+
+ if(source_)
+ {
+ g_source_destroy(source_);
+ source_ = 0;
+ }
+}
+
+// static
+void SourceConnectionNode::destroy_notify_callback(void* data)
+{
+ try
+ {
+ SourceConnectionNode *const self = static_cast<SourceConnectionNode*>(data);
+
+ // The GLib side is disconnected now, thus the GSource* is no longer valid.
+ self->source_ = 0;
+
+ if(!self->notified_)
+ self->notify(false);
+
+ // Undo the reference made by install().
+ self->unreference();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+inline
+void SourceConnectionNode::install(GSource* source)
+{
+ source_ = source;
+ reference();
+}
+
+inline
+SigC::SlotNode* SourceConnectionNode::get_slot_node()
+{
+ return static_cast<SigC::SlotNode*>(slot().impl());
+}
+
+
+/* We use the callback data member of GSource to store both a pointer to our
+ * wrapper and a pointer to the connection node that is currently being used.
+ * The one and only SourceCallbackData object of a Glib::Source is constructed
+ * in the ctor of Glib::Source and destroyed after the GSource object when the
+ * reference counter of the GSource object reaches zero!
+ */
+struct SourceCallbackData
+{
+ explicit inline SourceCallbackData(Glib::Source* wrapper_);
+
+ void set_node(SourceConnectionNode* node_);
+
+ static void destroy_notify_callback(void* data);
+
+ Glib::Source* wrapper;
+ SourceConnectionNode* node;
+};
+
+inline
+SourceCallbackData::SourceCallbackData(Glib::Source* wrapper_)
+:
+ wrapper (wrapper_),
+ node (0)
+{}
+
+void SourceCallbackData::set_node(SourceConnectionNode* node_)
+{
+ if(node)
+ SourceConnectionNode::destroy_notify_callback(node);
+
+ node = node_;
+}
+
+// static
+void SourceCallbackData::destroy_notify_callback(void* data)
+{
+ SourceCallbackData *const self = static_cast<SourceCallbackData*>(data);
+
+ if(self->node)
+ SourceConnectionNode::destroy_notify_callback(self->node);
+
+ if(self->wrapper)
+ Glib::Source::destroy_notify_callback(self->wrapper);
+
+ delete self;
+}
+
+
+/* Retrieve the callback data from a wrapped GSource object.
+ */
+SourceCallbackData* glibmm_source_get_callback_data(GSource* source)
+{
+ g_return_val_if_fail(source->callback_funcs->get != 0, 0);
+
+ GSourceFunc func;
+ void* user_data = 0;
+
+ // Retrieve the callback function and data.
+ (*source->callback_funcs->get)(source->callback_data, source, &func, &user_data);
+
+ return static_cast<SourceCallbackData*>(user_data);
+}
+
+/* Glib::Source doesn't use the callback function installed with
+ * g_source_set_callback(). Instead, it invokes the sigc++ slot
+ * directly from dispatch_vfunc(), which is both simpler and more
+ * efficient.
+ * For correctness, provide a pointer to this dummy callback rather
+ * than some random pointer. That also allows for sanity checks
+ * here as well as in Source::dispatch_vfunc().
+ */
+gboolean glibmm_dummy_source_callback(void*)
+{
+ g_assert_not_reached();
+ return 0;
+}
+
+/* Only used by SignalTimeout::connect() and SignalIdle::connect().
+ * These don't use Glib::Source, to avoid the unnecessary overhead
+ * of a completely unused wrapper object.
+ */
+gboolean glibmm_source_callback(void* data)
+{
+ try
+ {
+ // Recreate the specific slot from the generic slot node.
+ SigC::Slot0<bool> slot (static_cast<SourceConnectionNode*>(data)->get_slot_node());
+ return slot();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ return 0;
+}
+
+gboolean glibmm_iosource_callback(GIOChannel*, GIOCondition condition, void* data)
+{
+ SourceCallbackData *const callback_data = static_cast<SourceCallbackData*>(data);
+ g_return_val_if_fail(callback_data->node != 0, 0);
+
+ try
+ {
+ // Recreate the specific slot from the generic slot node.
+ SigC::Slot1<bool,Glib::IOCondition> slot (callback_data->node->get_slot_node());
+ return slot((Glib::IOCondition) condition);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ return 0;
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+/**** Glib::PollFD *********************************************************/
+
+PollFD::PollFD()
+{
+ gobject_.fd = 0;
+ gobject_.events = 0;
+ gobject_.revents = 0;
+}
+
+PollFD::PollFD(int fd)
+{
+ gobject_.fd = fd;
+ gobject_.events = 0;
+ gobject_.revents = 0;
+}
+
+PollFD::PollFD(int fd, IOCondition events)
+{
+ gobject_.fd = fd;
+ gobject_.events = events;
+ gobject_.revents = 0;
+}
+
+
+/**** Glib::SignalTimeout **************************************************/
+
+inline
+SignalTimeout::SignalTimeout(GMainContext* context)
+:
+ context_ (context)
+{}
+
+SigC::Connection SignalTimeout::connect(const SigC::Slot0<bool>& slot,
+ unsigned int interval, int priority)
+{
+ SourceConnectionNode *const conn_node = new SourceConnectionNode(slot);
+ const SigC::Connection connection (conn_node);
+
+ GSource *const source = g_timeout_source_new(interval);
+
+ if(priority != G_PRIORITY_DEFAULT)
+ g_source_set_priority(source, priority);
+
+ g_source_set_callback(
+ source, &glibmm_source_callback, conn_node,
+ &SourceConnectionNode::destroy_notify_callback);
+
+ g_source_attach(source, context_);
+ g_source_unref(source); // GMainContext holds a reference
+
+ conn_node->install(source);
+ return connection;
+}
+
+SignalTimeout signal_timeout()
+{
+ return SignalTimeout(0); // 0 means default context
+}
+
+
+/**** Glib::SignalIdle *****************************************************/
+
+inline
+SignalIdle::SignalIdle(GMainContext* context)
+:
+ context_ (context)
+{}
+
+SigC::Connection SignalIdle::connect(const SigC::Slot0<bool>& slot, int priority)
+{
+ SourceConnectionNode *const conn_node = new SourceConnectionNode(slot);
+ const SigC::Connection connection (conn_node);
+
+ GSource *const source = g_idle_source_new();
+
+ if(priority != G_PRIORITY_DEFAULT)
+ g_source_set_priority(source, priority);
+
+ g_source_set_callback(
+ source, &glibmm_source_callback, conn_node,
+ &SourceConnectionNode::destroy_notify_callback);
+
+ g_source_attach(source, context_);
+ g_source_unref(source); // GMainContext holds a reference
+
+ conn_node->install(source);
+ return connection;
+}
+
+SignalIdle signal_idle()
+{
+ return SignalIdle(0); // 0 means default context
+}
+
+
+/**** Glib::SignalIO *******************************************************/
+
+inline
+SignalIO::SignalIO(GMainContext* context)
+:
+ context_ (context)
+{}
+
+SigC::Connection SignalIO::connect(const SigC::Slot1<bool,IOCondition>& slot,
+ int fd, IOCondition condition, int priority)
+{
+ const Glib::RefPtr<IOSource> source = IOSource::create(fd, condition);
+
+ if(priority != G_PRIORITY_DEFAULT)
+ source->set_priority(priority);
+
+ const SigC::Connection connection = source->connect(slot);
+
+ g_source_attach(source->gobj(), context_);
+
+ return connection;
+}
+
+SigC::Connection SignalIO::connect(const SigC::Slot1<bool,IOCondition>& slot,
+ const Glib::RefPtr<IOChannel>& channel,
+ IOCondition condition, int priority)
+{
+ const Glib::RefPtr<IOSource> source = IOSource::create(channel, condition);
+
+ if(priority != G_PRIORITY_DEFAULT)
+ source->set_priority(priority);
+
+ const SigC::Connection connection = source->connect(slot);
+
+ g_source_attach(source->gobj(), context_);
+
+ return connection;
+}
+
+SignalIO signal_io()
+{
+ return SignalIO(0); // 0 means default context
+}
+
+
+/**** Glib::MainContext ****************************************************/
+
+// static
+Glib::RefPtr<MainContext> MainContext::create()
+{
+ return Glib::RefPtr<MainContext>(reinterpret_cast<MainContext*>(g_main_context_new()));
+}
+
+// static
+Glib::RefPtr<MainContext> MainContext::get_default()
+{
+ return Glib::wrap(g_main_context_default(), true);
+}
+
+bool MainContext::iteration(bool may_block)
+{
+ return g_main_context_iteration(gobj(), may_block);
+}
+
+bool MainContext::pending()
+{
+ return g_main_context_pending(gobj());
+}
+
+void MainContext::wakeup()
+{
+ g_main_context_wakeup(gobj());
+}
+
+bool MainContext::acquire()
+{
+ return g_main_context_acquire(gobj());
+}
+
+bool MainContext::wait(Glib::Cond& cond, Glib::Mutex& mutex)
+{
+ return g_main_context_wait(gobj(), cond.gobj(), mutex.gobj());
+}
+
+void MainContext::release()
+{
+ g_main_context_release(gobj());
+}
+
+bool MainContext::prepare(int& priority)
+{
+ return g_main_context_prepare(gobj(), &priority);
+}
+
+bool MainContext::prepare()
+{
+ return g_main_context_prepare(gobj(), 0);
+}
+
+void MainContext::query(int max_priority, int& timeout, std::vector<PollFD>& fds)
+{
+ if(fds.empty())
+ fds.resize(8); // rather bogus number, but better than 0
+
+ for(;;)
+ {
+ const int size_before = fds.size();
+ const int size_needed = g_main_context_query(
+ gobj(), max_priority, &timeout, reinterpret_cast<GPollFD*>(&fds.front()), size_before);
+
+ fds.resize(size_needed);
+
+ if(size_needed <= size_before)
+ break;
+ }
+}
+
+bool MainContext::check(int max_priority, std::vector<PollFD>& fds)
+{
+ if(!fds.empty())
+ return g_main_context_check(gobj(), max_priority, reinterpret_cast<GPollFD*>(&fds.front()), fds.size());
+ else
+ return false;
+}
+
+void MainContext::dispatch()
+{
+ g_main_context_dispatch(gobj());
+}
+
+void MainContext::set_poll_func(GPollFunc poll_func)
+{
+ g_main_context_set_poll_func(gobj(), poll_func);
+}
+
+GPollFunc MainContext::get_poll_func()
+{
+ return g_main_context_get_poll_func(gobj());
+}
+
+void MainContext::add_poll(PollFD& fd, int priority)
+{
+ g_main_context_add_poll(gobj(), fd.gobj(), priority);
+}
+
+void MainContext::remove_poll(PollFD& fd)
+{
+ g_main_context_remove_poll(gobj(), fd.gobj());
+}
+
+SignalTimeout MainContext::signal_timeout()
+{
+ return SignalTimeout(gobj());
+}
+
+SignalIdle MainContext::signal_idle()
+{
+ return SignalIdle(gobj());
+}
+
+SignalIO MainContext::signal_io()
+{
+ return SignalIO(gobj());
+}
+
+void MainContext::reference() const
+{
+ g_main_context_ref(reinterpret_cast<GMainContext*>(const_cast<MainContext*>(this)));
+}
+
+void MainContext::unreference() const
+{
+ g_main_context_unref(reinterpret_cast<GMainContext*>(const_cast<MainContext*>(this)));
+}
+
+GMainContext* MainContext::gobj()
+{
+ return reinterpret_cast<GMainContext*>(this);
+}
+
+const GMainContext* MainContext::gobj() const
+{
+ return reinterpret_cast<const GMainContext*>(this);
+}
+
+GMainContext* MainContext::gobj_copy() const
+{
+ reference();
+ return const_cast<GMainContext*>(gobj());
+}
+
+Glib::RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy)
+{
+ if(take_copy && gobject)
+ g_main_context_ref(gobject);
+
+ return Glib::RefPtr<MainContext>(reinterpret_cast<MainContext*>(gobject));
+}
+
+
+/**** Glib::MainLoop *******************************************************/
+
+Glib::RefPtr<MainLoop> MainLoop::create(bool is_running)
+{
+ return Glib::RefPtr<MainLoop>(
+ reinterpret_cast<MainLoop*>(g_main_loop_new(0, is_running)));
+}
+
+Glib::RefPtr<MainLoop> MainLoop::create(const Glib::RefPtr<MainContext>& context, bool is_running)
+{
+ return Glib::RefPtr<MainLoop>(
+ reinterpret_cast<MainLoop*>(g_main_loop_new(Glib::unwrap(context), is_running)));
+}
+
+void MainLoop::run()
+{
+ g_main_loop_run(gobj());
+}
+
+void MainLoop::quit()
+{
+ g_main_loop_quit(gobj());
+}
+
+bool MainLoop::is_running()
+{
+ return g_main_loop_is_running(gobj());
+}
+
+Glib::RefPtr<MainContext> MainLoop::get_context()
+{
+ return Glib::wrap(g_main_loop_get_context(gobj()), true);
+}
+
+void MainLoop::reference() const
+{
+ g_main_loop_ref(reinterpret_cast<GMainLoop*>(const_cast<MainLoop*>(this)));
+}
+
+void MainLoop::unreference() const
+{
+ g_main_loop_unref(reinterpret_cast<GMainLoop*>(const_cast<MainLoop*>(this)));
+}
+
+GMainLoop* MainLoop::gobj()
+{
+ return reinterpret_cast<GMainLoop*>(this);
+}
+
+const GMainLoop* MainLoop::gobj() const
+{
+ return reinterpret_cast<const GMainLoop*>(this);
+}
+
+GMainLoop* MainLoop::gobj_copy() const
+{
+ reference();
+ return const_cast<GMainLoop*>(gobj());
+}
+
+Glib::RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy)
+{
+ if(take_copy && gobject)
+ g_main_loop_ref(gobject);
+
+ return Glib::RefPtr<MainLoop>(reinterpret_cast<MainLoop*>(gobject));
+}
+
+
+/**** Glib::Source *********************************************************/
+
+// static
+const GSourceFuncs Source::vfunc_table_ =
+{
+ &Source::prepare_vfunc,
+ &Source::check_vfunc,
+ &Source::dispatch_vfunc,
+ 0, // finalize_vfunc // We can't use finalize_vfunc because there is no way
+ // to store a pointer to our wrapper anywhere in GSource so
+ // that it persists until finalize_vfunc would be called from here.
+ 0, // closure_callback
+ 0, // closure_marshal
+};
+
+unsigned int Source::attach(const Glib::RefPtr<MainContext>& context)
+{
+ return g_source_attach(gobject_, Glib::unwrap(context));
+}
+
+unsigned int Source::attach()
+{
+ return g_source_attach(gobject_, 0);
+}
+
+void Source::destroy()
+{
+ g_source_destroy(gobject_);
+}
+
+void Source::set_priority(int priority)
+{
+ g_source_set_priority(gobject_, priority);
+}
+
+int Source::get_priority() const
+{
+ return g_source_get_priority(gobject_);
+}
+
+void Source::set_can_recurse(bool can_recurse)
+{
+ g_source_set_can_recurse(gobject_, can_recurse);
+}
+
+bool Source::get_can_recurse() const
+{
+ return g_source_get_can_recurse(gobject_);
+}
+
+unsigned int Source::get_id() const
+{
+ return g_source_get_id(gobject_);
+}
+
+Glib::RefPtr<MainContext> Source::get_context()
+{
+ return Glib::wrap(g_source_get_context(gobject_), true);
+}
+
+GSource* Source::gobj_copy() const
+{
+ return g_source_ref(gobject_);
+}
+
+void Source::reference() const
+{
+ g_source_ref(gobject_);
+}
+
+void Source::unreference() const
+{
+ g_source_unref(gobject_);
+}
+
+Source::Source()
+:
+ gobject_ (g_source_new(const_cast<GSourceFuncs*>(&vfunc_table_), sizeof(GSource)))
+{
+ g_source_set_callback(
+ gobject_, &glibmm_dummy_source_callback,
+ new SourceCallbackData(this), // our persistant callback data object
+ &SourceCallbackData::destroy_notify_callback);
+}
+
+Source::Source(GSource* cast_item, GSourceFunc callback_func)
+:
+ gobject_ (cast_item)
+{
+ g_source_set_callback(
+ gobject_, callback_func,
+ new SourceCallbackData(this), // our persistant callback data object
+ &SourceCallbackData::destroy_notify_callback);
+}
+
+Source::~Source()
+{
+ // The dtor should be invoked by destroy_notify_callback() only, which clears
+ // gobject_ before deleting. However, we might also get to this point if
+ // a derived ctor threw an exception, and then we need to unref manually.
+
+ if(gobject_)
+ {
+ SourceCallbackData *const data = glibmm_source_get_callback_data(gobject_);
+ data->wrapper = 0;
+
+ GSource *const tmp_gobject = gobject_;
+ gobject_ = 0;
+
+ g_source_unref(tmp_gobject);
+ }
+}
+
+SigC::Connection Source::connect_generic(const SigC::SlotBase& slot)
+{
+ SourceConnectionNode *const conn_node = new SourceConnectionNode(slot);
+ const SigC::Connection connection (conn_node);
+
+ // Don't override the callback data. Reuse the existing one
+ // calling SourceCallbackData::set_node() to register conn_node.
+ SourceCallbackData *const data = glibmm_source_get_callback_data(gobject_);
+ data->set_node(conn_node);
+
+ conn_node->install(gobject_);
+ return connection;
+}
+
+void Source::add_poll(Glib::PollFD& poll_fd)
+{
+ g_source_add_poll(gobject_, poll_fd.gobj());
+}
+
+void Source::remove_poll(Glib::PollFD& poll_fd)
+{
+ g_source_remove_poll(gobject_, poll_fd.gobj());
+}
+
+void Source::get_current_time(Glib::TimeVal& current_time)
+{
+ g_source_get_current_time(gobject_, &current_time);
+}
+
+inline // static
+Source* Source::get_wrapper(GSource* source)
+{
+ SourceCallbackData *const data = glibmm_source_get_callback_data(source);
+ return data->wrapper;
+}
+
+// static
+gboolean Source::prepare_vfunc(GSource* source, int* timeout)
+{
+ try
+ {
+ Source *const self = get_wrapper(source);
+ return self->prepare(*timeout);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ return 0;
+}
+
+// static
+gboolean Source::check_vfunc(GSource* source)
+{
+ try
+ {
+ Source *const self = get_wrapper(source);
+ return self->check();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ return 0;
+}
+
+// static
+gboolean Source::dispatch_vfunc(GSource*, GSourceFunc callback, void* user_data)
+{
+ SourceCallbackData *const callback_data = static_cast<SourceCallbackData*>(user_data);
+
+ g_return_val_if_fail(callback == &glibmm_dummy_source_callback, 0);
+ g_return_val_if_fail(callback_data != 0 && callback_data->node != 0, 0);
+
+ try
+ {
+ Source *const self = callback_data->wrapper;
+ return self->dispatch(callback_data->node->get_slot_node());
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ return 0;
+}
+
+// static
+void Source::destroy_notify_callback(void* data)
+{
+ if(data)
+ {
+ Source *const self = static_cast<Source*>(data);
+
+ // gobject_ is already invalid at this point.
+ self->gobject_ = 0;
+
+ // No exception checking: if the dtor throws, you're out of luck anyway.
+ delete self;
+ }
+}
+
+
+/**** Glib::TimeoutSource **************************************************/
+
+// static
+Glib::RefPtr<TimeoutSource> TimeoutSource::create(unsigned int interval)
+{
+ return Glib::RefPtr<TimeoutSource>(new TimeoutSource(interval));
+}
+
+SigC::Connection TimeoutSource::connect(const SigC::Slot0<bool>& slot)
+{
+ return connect_generic(slot);
+}
+
+TimeoutSource::TimeoutSource(unsigned int interval)
+:
+ interval_ (interval)
+{
+ expiration_.assign_current_time();
+ expiration_.add_milliseconds(std::min<unsigned long>(G_MAXLONG, interval_));
+}
+
+TimeoutSource::~TimeoutSource()
+{}
+
+bool TimeoutSource::prepare(int& timeout)
+{
+ Glib::TimeVal current_time;
+ get_current_time(current_time);
+
+ Glib::TimeVal remaining = expiration_;
+ remaining.subtract(current_time);
+
+ if(remaining.negative())
+ {
+ // Already expired.
+ timeout = 0;
+ }
+ else
+ {
+ const unsigned long milliseconds =
+ static_cast<unsigned long>(remaining.tv_sec) * 1000U +
+ static_cast<unsigned long>(remaining.tv_usec) / 1000U;
+
+ // Set remaining milliseconds.
+ timeout = std::min<unsigned long>(G_MAXINT, milliseconds);
+
+ // Check if the system time has been set backwards. (remaining > interval)
+ remaining.add_milliseconds(- std::min<unsigned long>(G_MAXLONG, interval_) - 1);
+ if(!remaining.negative())
+ {
+ // Oh well. Reset the expiration time to now + interval;
+ // this at least avoids hanging for long periods of time.
+ expiration_ = current_time;
+ expiration_.add_milliseconds(interval_);
+ timeout = std::min<unsigned int>(G_MAXINT, interval_);
+ }
+ }
+
+ return (timeout == 0);
+}
+
+bool TimeoutSource::check()
+{
+ Glib::TimeVal current_time;
+ get_current_time(current_time);
+
+ return (expiration_ <= current_time);
+}
+
+bool TimeoutSource::dispatch(SigC::SlotNode* slot_data)
+{
+ SigC::Slot0<bool> slot (slot_data);
+ const bool again = slot();
+
+ if(again)
+ {
+ get_current_time(expiration_);
+ expiration_.add_milliseconds(std::min<unsigned long>(G_MAXLONG, interval_));
+ }
+
+ return again;
+}
+
+
+/**** Glib::IdleSource *****************************************************/
+
+// static
+Glib::RefPtr<IdleSource> IdleSource::create()
+{
+ return Glib::RefPtr<IdleSource>(new IdleSource());
+}
+
+SigC::Connection IdleSource::connect(const SigC::Slot0<bool>& slot)
+{
+ return connect_generic(slot);
+}
+
+IdleSource::IdleSource()
+{
+ set_priority(PRIORITY_DEFAULT_IDLE);
+}
+
+IdleSource::~IdleSource()
+{}
+
+bool IdleSource::prepare(int& timeout)
+{
+ timeout = 0;
+ return true;
+}
+
+bool IdleSource::check()
+{
+ return true;
+}
+
+bool IdleSource::dispatch(SigC::SlotNode* slot_data)
+{
+ SigC::Slot0<bool> slot (slot_data);
+ return slot();
+}
+
+
+/**** Glib::IOSource *******************************************************/
+
+// static
+Glib::RefPtr<IOSource> IOSource::create(int fd, IOCondition condition)
+{
+ return Glib::RefPtr<IOSource>(new IOSource(fd, condition));
+}
+
+Glib::RefPtr<IOSource> IOSource::create(const Glib::RefPtr<IOChannel>& channel, IOCondition condition)
+{
+ return Glib::RefPtr<IOSource>(new IOSource(channel, condition));
+}
+
+SigC::Connection IOSource::connect(const SigC::Slot1<bool,IOCondition>& slot)
+{
+ return connect_generic(slot);
+}
+
+IOSource::IOSource(int fd, IOCondition condition)
+:
+ poll_fd_ (fd, condition)
+{
+ add_poll(poll_fd_);
+}
+
+IOSource::IOSource(const Glib::RefPtr<IOChannel>& channel, IOCondition condition)
+:
+ Source(g_io_create_watch(channel->gobj(), (GIOCondition) condition),
+ (GSourceFunc) &glibmm_iosource_callback)
+{}
+
+IOSource::~IOSource()
+{}
+
+bool IOSource::prepare(int& timeout)
+{
+ timeout = -1;
+ return false;
+}
+
+bool IOSource::check()
+{
+ return ((poll_fd_.get_revents() & poll_fd_.get_events()) != 0);
+}
+
+bool IOSource::dispatch(SigC::SlotNode* slot_data)
+{
+ SigC::Slot1<bool,IOCondition> slot (slot_data);
+ return slot(poll_fd_.get_revents());
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h
new file mode 100644
index 00000000..078d9d9e
--- /dev/null
+++ b/glib/glibmm/main.h
@@ -0,0 +1,549 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_MAIN_H
+#define _GLIBMM_MAIN_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/giochannel.h>
+#include <glib/gmain.h>
+
+#include <vector>
+#include <sigc++/sigc++.h>
+
+#include <glibmmconfig.h>
+#include <glibmm/refptr.h>
+#include <glibmm/timeval.h>
+
+GTKMM_USING_STD(vector)
+
+
+namespace Glib
+{
+
+class Cond;
+class Mutex;
+class IOChannel;
+
+
+/** @defgroup MainLoop The Main Event Loop
+ * Manages all available sources of events.
+ * @{
+ */
+
+enum
+{
+ /*! Use this for high priority event sources. It is not used within
+ * GLib or GTK+.<br><br>
+ */
+ PRIORITY_HIGH = -100,
+
+ /*! Use this for default priority event sources. In glibmm this
+ * priority is used by default when installing timeout handlers with
+ * SignalTimeout::connect(). In GDK this priority is used for events
+ * from the X server.<br><br>
+ */
+ PRIORITY_DEFAULT = 0,
+
+ /*! Use this for high priority idle functions. GTK+ uses
+ * <tt>PRIORITY_HIGH_IDLE&nbsp;+&nbsp;10</tt> for resizing operations, and
+ * <tt>PRIORITY_HIGH_IDLE&nbsp;+&nbsp;20</tt> for redrawing operations.
+ * (This is done to ensure that any pending resizes are processed before
+ * any pending redraws, so that widgets are not redrawn twice unnecessarily.)
+ * <br><br>
+ */
+ PRIORITY_HIGH_IDLE = 100,
+
+ /*! Use this for default priority idle functions. In glibmm this priority is
+ * used by default when installing idle handlers with SignalIdle::connect().
+ * <br><br>
+ */
+ PRIORITY_DEFAULT_IDLE = 200,
+
+ /*! Use this for very low priority background tasks. It is not used within
+ * GLib or GTK+.
+ */
+ PRIORITY_LOW = 300
+};
+
+
+/** A bitwise combination representing an I/O condition to watch for on an
+ * event source.
+ * The flags correspond to those used by the <tt>%poll()</tt> system call
+ * on UNIX (see <tt>man 2 poll</tt>). To test for individual flags, do
+ * something like this:
+ * @code
+ * if((condition & Glib::IO_OUT) != 0)
+ * do_some_output();
+ * @endcode
+ * @par Bitwise operators:
+ * <tt>IOCondition operator|(IOCondition, IOCondition)</tt><br>
+ * <tt>IOCondition operator&(IOCondition, IOCondition)</tt><br>
+ * <tt>IOCondition operator^(IOCondition, IOCondition)</tt><br>
+ * <tt>IOCondition operator~(IOCondition)</tt><br>
+ * <tt>IOCondition& operator|=(IOCondition&, IOCondition)</tt><br>
+ * <tt>IOCondition& operator&=(IOCondition&, IOCondition)</tt><br>
+ * <tt>IOCondition& operator^=(IOCondition&, IOCondition)</tt><br>
+ */
+enum IOCondition
+{
+ IO_IN = G_IO_IN, /*!< @hideinitializer There is data to read. */
+ IO_OUT = G_IO_OUT, /*!< @hideinitializer Data can be written (without blocking). */
+ IO_PRI = G_IO_PRI, /*!< @hideinitializer There is urgent data to read. */
+ IO_ERR = G_IO_ERR, /*!< @hideinitializer %Error condition. */
+ IO_HUP = G_IO_HUP, /*!< @hideinitializer Hung up (the connection has been broken,
+ usually for pipes and sockets). */
+ IO_NVAL = G_IO_NVAL /*!< @hideinitializer Invalid request. The file descriptor is not open. */
+};
+
+inline IOCondition operator|(IOCondition lhs, IOCondition rhs)
+ { return static_cast<IOCondition>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }
+
+inline IOCondition operator&(IOCondition lhs, IOCondition rhs)
+ { return static_cast<IOCondition>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); }
+
+inline IOCondition operator^(IOCondition lhs, IOCondition rhs)
+ { return static_cast<IOCondition>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)); }
+
+inline IOCondition operator~(IOCondition flags)
+ { return static_cast<IOCondition>(~static_cast<unsigned>(flags)); }
+
+inline IOCondition& operator|=(IOCondition& lhs, IOCondition rhs)
+ { return (lhs = static_cast<IOCondition>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs))); }
+
+inline IOCondition& operator&=(IOCondition& lhs, IOCondition rhs)
+ { return (lhs = static_cast<IOCondition>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs))); }
+
+inline IOCondition& operator^=(IOCondition& lhs, IOCondition rhs)
+ { return (lhs = static_cast<IOCondition>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs))); }
+
+
+class PollFD
+{
+public:
+ PollFD();
+ explicit PollFD(int fd);
+ PollFD(int fd, IOCondition events);
+
+ void set_fd(int fd) { gobject_.fd = fd; }
+ int get_fd() const { return gobject_.fd; }
+
+ void set_events(IOCondition events) { gobject_.events = events; }
+ IOCondition get_events() const { return static_cast<IOCondition>(gobject_.events); }
+
+ void set_revents(IOCondition revents) { gobject_.revents = revents; }
+ IOCondition get_revents() const { return static_cast<IOCondition>(gobject_.revents); }
+
+ GPollFD* gobj() { return &gobject_; }
+ const GPollFD* gobj() const { return &gobject_; }
+
+private:
+ GPollFD gobject_;
+};
+
+
+class SignalTimeout
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ explicit inline SignalTimeout(GMainContext* context);
+#endif
+
+ /** Connects a timeout handler.
+ * @code
+ * Glib::signal_timeout().connect(SigC::slot(&timeout_handler), 1000);
+ * @endcode
+ * is equivalent to:
+ * @code
+ * const Glib::RefPtr<Glib::TimeoutSource> timeout_source = Glib::TimeoutSource::create(1000);
+ * timeout_source->connect(SigC::slot(&timeout_handler));
+ * timeout_source->attach(Glib::MainContext::get_default());
+ * @endcode
+ * @param slot A slot to call when @a interval elapsed.
+ * @param interval The timeout in milliseconds.
+ * @param priority The priority of the new event source.
+ * @return A connection handle, which can be used to disconnect the handler.
+ */
+ SigC::Connection connect(const SigC::Slot0<bool>& slot, unsigned int interval,
+ int priority = PRIORITY_DEFAULT);
+private:
+ GMainContext* context_;
+
+ // no copy assignment
+ SignalTimeout& operator=(const SignalTimeout&);
+};
+
+
+class SignalIdle
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ explicit inline SignalIdle(GMainContext* context);
+#endif
+
+ /** Connects an idle handler.
+ * @code
+ * Glib::signal_idle().connect(SigC::slot(&idle_handler));
+ * @endcode
+ * is equivalent to:
+ * @code
+ * const Glib::RefPtr<Glib::IdleSource> idle_source = Glib::IdleSource::create();
+ * idle_source->connect(SigC::slot(&idle_handler));
+ * idle_source->attach(Glib::MainContext::get_default());
+ * @endcode
+ * @param slot A slot to call when the main loop is idle.
+ * @param priority The priority of the new event source.
+ * @return A connection handle, which can be used to disconnect the handler.
+ */
+ SigC::Connection connect(const SigC::Slot0<bool>& slot, int priority = PRIORITY_DEFAULT_IDLE);
+
+private:
+ GMainContext* context_;
+
+ // no copy assignment
+ SignalIdle& operator=(const SignalIdle&);
+};
+
+
+class SignalIO
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ explicit inline SignalIO(GMainContext* context);
+#endif
+
+ /** Connects an I/O handler.
+ * @code
+ * Glib::signal_io().connect(SigC::slot(&io_handler), fd, Glib::IO_IN | Glib::IO_HUP);
+ * @endcode
+ * is equivalent to:
+ * @code
+ * const Glib::RefPtr<Glib::IOSource> io_source = Glib::IOSource::create(fd, Glib::IO_IN | Glib::IO_HUP);
+ * io_source->connect(SigC::slot(&io_handler));
+ * io_source->attach(Glib::MainContext::get_default());
+ * @endcode
+ * @param slot A slot to call when polling @a fd results in an event that matches @a condition.
+ * The event will be passed as a parameter to @a slot.
+ * If @a io_handler returns <tt>false</tt> the signal is disconnected.
+ * @param fd The file descriptor (or a @c HANDLE on Win32 systems) to watch.
+ * @param condition The conditions to watch for.
+ * @param priority The priority of the new event source.
+ * @return A connection handle, which can be used to disconnect the handler.
+ */
+ SigC::Connection connect(const SigC::Slot1<bool,IOCondition>& slot, int fd,
+ IOCondition condition, int priority = PRIORITY_DEFAULT);
+
+ /** Connects an I/O channel.
+ * @code
+ * Glib::signal_io().connect(SigC::slot(&io_handler), channel, Glib::IO_IN | Glib::IO_HUP);
+ * @endcode
+ * is equivalent to:
+ * @code
+ * const Glib::RefPtr<Glib::IOSource> io_source = Glib::IOSource::create(channel, Glib::IO_IN | Glib::IO_HUP);
+ * io_source->connect(SigC::slot(&io_handler));
+ * io_source->attach(Glib::MainContext::get_default());
+ * @endcode
+ * @param slot A slot to call when polling @a fd results in an event that matches @a condition.
+ * The event will be passed as a parameter to @a slot.
+ * If @a io_handler returns <tt>false</tt> the signal is disconnected.
+ * @param channel The IOChannel object to watch.
+ * @param condition The conditions to watch for.
+ * @param priority The priority of the new event source.
+ * @return A connection handle, which can be used to disconnect the handler.
+ */
+ SigC::Connection connect(const SigC::Slot1<bool,IOCondition>& slot, const Glib::RefPtr<IOChannel>& channel,
+ IOCondition condition, int priority = PRIORITY_DEFAULT);
+
+private:
+ GMainContext* context_;
+
+ // no copy assignment
+ SignalIO& operator=(const SignalIO&);
+};
+
+
+/** Convenience timeout signal.
+ * @return A signal proxy; you want to use SignalTimeout::connect().
+ */
+SignalTimeout signal_timeout();
+
+/** Convenience idle signal.
+ * @return A signal proxy; you want to use SignalIdle::connect().
+ */
+SignalIdle signal_idle();
+
+/** Convenience I/O signal.
+ * @return A signal proxy; you want to use SignalIO::connect().
+ */
+SignalIO signal_io();
+
+
+/** Main context.
+ */
+class MainContext
+{
+public:
+ typedef Glib::MainContext CppObjectType;
+ typedef GMainContext BaseObjectType;
+
+ static Glib::RefPtr<MainContext> create();
+ static Glib::RefPtr<MainContext> get_default();
+
+ bool iteration(bool may_block);
+ bool pending();
+ void wakeup();
+
+ bool acquire();
+ bool wait(Glib::Cond& cond, Glib::Mutex& mutex);
+ void release();
+
+ bool prepare(int& priority);
+ bool prepare();
+
+ void query(int max_priority, int& timeout, std::vector<PollFD>& fds);
+ bool check(int max_priority, std::vector<PollFD>& fds);
+ void dispatch();
+
+ void set_poll_func(GPollFunc poll_func);
+ GPollFunc get_poll_func();
+
+ void add_poll(PollFD& fd, int priority);
+ void remove_poll(PollFD& fd);
+
+ /** Timeout signal, attached to this MainContext.
+ * @return A signal proxy; you want to use SignalTimeout::connect().
+ */
+ SignalTimeout signal_timeout();
+
+ /** Idle signal, attached to this MainContext.
+ * @return A signal proxy; you want to use SignalIdle::connect().
+ */
+ SignalIdle signal_idle();
+
+ /** I/O signal, attached to this MainContext.
+ * @return A signal proxy; you want to use SignalIO::connect().
+ */
+ SignalIO signal_io();
+
+ void reference() const;
+ void unreference() const;
+
+ GMainContext* gobj();
+ const GMainContext* gobj() const;
+ GMainContext* gobj_copy() const;
+
+private:
+ // Glib::MainContext can neither be constructed nor deleted.
+ MainContext();
+ void operator delete(void*, size_t);
+
+ // noncopyable
+ MainContext(const MainContext& other);
+ MainContext& operator=(const MainContext& other);
+
+};
+
+/** @relates Glib::MainContext */
+Glib::RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy = false);
+
+
+class MainLoop
+{
+public:
+ typedef Glib::MainLoop CppObjectType;
+ typedef GMainLoop BaseObjectType;
+
+ static Glib::RefPtr<MainLoop> create(bool is_running = false);
+ static Glib::RefPtr<MainLoop> create(const Glib::RefPtr<MainContext>& context,
+ bool is_running = false);
+
+ void run();
+ void quit();
+ bool is_running();
+
+ Glib::RefPtr<MainContext> get_context();
+
+ void reference() const;
+ void unreference() const;
+
+ GMainLoop* gobj();
+ const GMainLoop* gobj() const;
+ GMainLoop* gobj_copy() const;
+
+private:
+ // Glib::MainLoop can neither be constructed nor deleted.
+ MainLoop();
+ void operator delete(void*, size_t);
+
+ MainLoop(const MainLoop&);
+ MainLoop& operator=(const MainLoop&);
+};
+
+/** @relates Glib::MainLoop */
+Glib::RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy = false);
+
+
+class Source
+{
+public:
+ typedef Glib::Source CppObjectType;
+ typedef GSource BaseObjectType;
+
+ static Glib::RefPtr<Source> create() /* = 0 */;
+
+ unsigned int attach(const Glib::RefPtr<MainContext>& context);
+ unsigned int attach();
+ void destroy();
+
+ void set_priority(int priority);
+ int get_priority() const;
+
+ void set_can_recurse(bool can_recurse);
+ bool get_can_recurse() const;
+
+ unsigned int get_id() const;
+ Glib::RefPtr<MainContext> get_context();
+
+ GSource* gobj() { return gobject_; }
+ const GSource* gobj() const { return gobject_; }
+ GSource* gobj_copy() const;
+
+ void reference() const;
+ void unreference() const;
+
+protected:
+ /** Construct an object that uses the virtual functions prepare(), check() and dispatch().
+ */
+ Source();
+
+ /** Wrap an existing GSource object and install the given callback function.
+ * The constructed object doesn't use the virtual functions prepare(), check() and dispatch().
+ * This ctor is for use by derived types that need to wrap a GSource object.
+ * The callback function can be a static member function. But beware!
+ * Depending on the actual implementation of the GSource's virtual functions
+ * the expected type of the callback function can differ from GSourceFunc.
+ */
+ Source(GSource* cast_item, GSourceFunc callback_func);
+
+ virtual ~Source();
+
+ SigC::Connection connect_generic(const SigC::SlotBase& slot);
+
+ void add_poll (PollFD& poll_fd);
+ void remove_poll(PollFD& poll_fd);
+
+ void get_current_time(Glib::TimeVal& current_time);
+
+ virtual bool prepare(int& timeout) = 0;
+ virtual bool check() = 0;
+ virtual bool dispatch(SigC::SlotNode* slot_data) = 0;
+
+private:
+ GSource* gobject_;
+
+#ifndef DOXGEN_SHOULD_SKIP_THIS
+
+ static inline Source* get_wrapper(GSource* source);
+
+ static const GSourceFuncs vfunc_table_;
+
+ static gboolean prepare_vfunc(GSource* source, int* timeout);
+ static gboolean check_vfunc(GSource* source);
+ static gboolean dispatch_vfunc(GSource* source, GSourceFunc callback, void* user_data);
+public:
+ static void destroy_notify_callback(void* data);
+private:
+
+#endif /* DOXGEN_SHOULD_SKIP_THIS */
+
+ // noncopyable
+ Source(const Source&);
+ Source& operator=(const Source&);
+};
+
+
+class TimeoutSource : public Glib::Source
+{
+public:
+ typedef Glib::TimeoutSource CppObjectType;
+
+ static Glib::RefPtr<TimeoutSource> create(unsigned int interval);
+ SigC::Connection connect(const SigC::Slot0<bool>& slot);
+
+protected:
+ explicit TimeoutSource(unsigned int interval);
+ virtual ~TimeoutSource();
+
+ virtual bool prepare(int& timeout);
+ virtual bool check();
+ virtual bool dispatch(SigC::SlotNode* slot_data);
+
+private:
+ Glib::TimeVal expiration_;
+ unsigned int interval_;
+};
+
+
+class IdleSource : public Glib::Source
+{
+public:
+ typedef Glib::IdleSource CppObjectType;
+
+ static Glib::RefPtr<IdleSource> create();
+ SigC::Connection connect(const SigC::Slot0<bool>& slot);
+
+protected:
+ IdleSource();
+ virtual ~IdleSource();
+
+ virtual bool prepare(int& timeout);
+ virtual bool check();
+ virtual bool dispatch(SigC::SlotNode* slot_data);
+};
+
+
+class IOSource : public Glib::Source
+{
+public:
+ typedef Glib::IOSource CppObjectType;
+
+ static Glib::RefPtr<IOSource> create(int fd, IOCondition condition);
+ static Glib::RefPtr<IOSource> create(const Glib::RefPtr<IOChannel>& channel, IOCondition condition);
+ SigC::Connection connect(const SigC::Slot1<bool,IOCondition>& slot);
+
+protected:
+ IOSource(int fd, IOCondition condition);
+ IOSource(const Glib::RefPtr<IOChannel>& channel, IOCondition condition);
+ virtual ~IOSource();
+
+ virtual bool prepare(int& timeout);
+ virtual bool check();
+ virtual bool dispatch(SigC::SlotNode* slot_data);
+
+private:
+ PollFD poll_fd_;
+};
+
+/** @} group MainLoop */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_MAIN_H */
+
diff --git a/glib/glibmm/miscutils.cc b/glib/glibmm/miscutils.cc
new file mode 100644
index 00000000..d1969fa4
--- /dev/null
+++ b/glib/glibmm/miscutils.cc
@@ -0,0 +1,216 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <cstddef>
+#include <cstring>
+
+#include <glibmm/miscutils.h>
+#include <glibmm/utility.h>
+#include <glib.h>
+
+
+namespace Glib
+{
+
+Glib::ustring get_application_name()
+{
+ if(const char *const application_name = g_get_application_name())
+ {
+ // Lets be a bit more strict than the original GLib function and ensure
+ // we always return valid UTF-8. gtkmm coders surely won't expect invalid
+ // UTF-8 in a Glib::ustring returned by a glibmm function.
+
+ if(g_utf8_validate(application_name, -1, 0))
+ return Glib::ustring(application_name);
+
+ char *const appname_utf8 = g_filename_to_utf8(application_name, -1, 0, 0, 0);
+ g_return_val_if_fail(appname_utf8 != 0, "");
+
+ return Glib::ustring(ScopedPtr<char>(appname_utf8).get());
+ }
+
+ return Glib::ustring();
+}
+
+void set_application_name(const Glib::ustring& application_name)
+{
+ g_set_application_name(application_name.c_str());
+}
+
+std::string get_prgname()
+{
+ const char *const prgname = g_get_prgname();
+ return (prgname) ? std::string(prgname) : std::string();
+}
+
+void set_prgname(const std::string& prgname)
+{
+ g_set_prgname(prgname.c_str());
+}
+
+std::string getenv(const std::string& variable, bool& found)
+{
+ const char *const value = g_getenv(variable.c_str());
+ found = (value != 0);
+ return (value) ? std::string(value) : std::string();
+}
+
+std::string getenv(const std::string& variable)
+{
+ const char *const value = g_getenv(variable.c_str());
+ return (value) ? std::string(value) : std::string();
+}
+
+std::string get_user_name()
+{
+ return std::string(g_get_user_name());
+}
+
+std::string get_real_name()
+{
+ return std::string(g_get_real_name());
+}
+
+std::string get_home_dir()
+{
+ return std::string(g_get_home_dir());
+}
+
+std::string get_tmp_dir()
+{
+ return std::string(g_get_tmp_dir());
+}
+
+std::string get_current_dir()
+{
+ const ScopedPtr<char> buf (g_get_current_dir());
+ return std::string(buf.get());
+}
+
+bool path_is_absolute(const std::string& filename)
+{
+ return g_path_is_absolute(filename.c_str());
+}
+
+std::string path_skip_root(const std::string& filename)
+{
+ // g_path_skip_root() returns a pointer _into_ the argument string,
+ // or NULL if there was no root component.
+
+ if(const char *const ptr = g_path_skip_root(filename.c_str()))
+ return std::string(ptr);
+ else
+ return std::string();
+}
+
+std::string path_get_basename(const std::string& filename)
+{
+ const ScopedPtr<char> buf (g_path_get_basename(filename.c_str()));
+ return std::string(buf.get());
+}
+
+std::string path_get_dirname(const std::string& filename)
+{
+ const ScopedPtr<char> buf (g_path_get_dirname(filename.c_str()));
+ return std::string(buf.get());
+}
+
+std::string build_filename(const Glib::ArrayHandle<std::string>& elements)
+{
+ return build_path(G_DIR_SEPARATOR_S, elements);
+}
+
+std::string build_filename(const std::string& elem1, const std::string& elem2)
+{
+ std::string result;
+ result.reserve(elem1.size() + elem2.size() + 1);
+
+ // Skip trailing '/'.
+ std::string::size_type idx = elem1.find_last_not_of(G_DIR_SEPARATOR);
+
+ if(idx != std::string::npos)
+ result.append(elem1, 0, idx + 1);
+
+ result += G_DIR_SEPARATOR;
+
+ // Skip leading '/'.
+ idx = elem2.find_first_not_of(G_DIR_SEPARATOR);
+
+ if(idx != std::string::npos)
+ result.append(elem2, idx, std::string::npos);
+
+ return result;
+}
+
+/* Yes, this reimplements the functionality of g_build_path() -- because
+ * it takes a varargs list, and calling it several times would it result
+ * in different behaviour.
+ */
+std::string build_path(const std::string& separator,
+ const Glib::ArrayHandle<std::string>& elements)
+{
+ std::string result;
+
+ const char *const sep = separator.c_str();
+ const size_t seplen = separator.length();
+
+ const char *const *const elements_begin = elements.data();
+ const char *const *const elements_end = elements_begin + elements.size();
+
+ for(const char *const * pelement = elements_begin; pelement != elements_end; ++pelement)
+ {
+ const char* start = *pelement;
+
+ if((pelement != elements_begin) && (seplen != 0))
+ {
+ while(strncmp(start, sep, seplen) == 0)
+ start += seplen;
+ }
+
+ size_t len = strlen(start);
+
+ if((pelement != elements_end - 1) && (seplen != 0))
+ {
+ while((len >= seplen) && (strncmp(start + len - seplen, sep, seplen) == 0))
+ len -= seplen;
+ }
+
+ if(len != 0)
+ {
+ if(!result.empty())
+ result.append(sep, seplen);
+
+ result.append(start, len);
+ }
+ }
+
+ return result;
+}
+
+std::string find_program_in_path(const std::string& program)
+{
+ if(char *const buf = g_find_program_in_path(program.c_str()))
+ return std::string(ScopedPtr<char>(buf).get());
+ else
+ return std::string();
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/miscutils.h b/glib/glibmm/miscutils.h
new file mode 100644
index 00000000..4c06e561
--- /dev/null
+++ b/glib/glibmm/miscutils.h
@@ -0,0 +1,209 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_MISCUTILS_H
+#define _GLIBMM_MISCUTILS_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/arrayhandle.h>
+#include <glibmm/ustring.h>
+
+
+namespace Glib
+{
+
+/** @defgroup MiscUtils Miscellaneous Utility Functions
+ * Miscellaneous Utility Functions -- a selection of portable utility functions.
+ * @{
+ */
+
+/** Gets a human-readable name for the application,
+ * as set by Glib::set_application_name().
+ * This name should be localized if possible, and is intended for display to
+ * the user. Contrast with Glib::get_prgname(), which gets a non-localized
+ * name. If Glib::set_application_name() has not been called, returns the
+ * result of Glib::get_prgname() (which may be empty if Glib::set_prgname()
+ * has also not been called).
+ *
+ * @return Human-readable application name. May return <tt>""</tt>.
+ */
+Glib::ustring get_application_name();
+
+/** Sets a human-readable name for the application.
+ * This name should be localized if possible, and is intended for display to
+ * the user. Contrast with Glib::set_prgname(), which sets a non-localized
+ * name. Glib::set_prgname() will be called automatically by
+ * <tt>gtk_init()</tt>, but Glib::set_application_name() will not.
+ *
+ * Note that for thread safety reasons, this function can only be called once.
+ *
+ * The application name will be used in contexts such as error messages,
+ * or when displaying an application's name in the task list.
+ *
+ * @param application_name Localized name of the application.
+ */
+void set_application_name(const Glib::ustring& application_name);
+
+/** Gets the name of the program.
+ * If you are using GDK or GTK+ the program name is set in <tt>gdk_init()</tt>,
+ * which is called by <tt>gtk_init()</tt>. The program name is found by taking
+ * the last component of <tt>argv[0]</tt>.
+ * @return The name of the program.
+ */
+std::string get_prgname();
+
+/** Sets the name of the program.
+ * @param prgname The name of the program.
+ */
+void set_prgname(const std::string& prgname);
+
+/** Returns an environment variable.
+ * @param variable The environment variable to get.
+ * @retval found <tt>true</tt> if the environment variable has been found.
+ * @return The value of the environment variable, or <tt>""</tt> if not found.
+ */
+std::string getenv(const std::string& variable, bool& found);
+
+/** Returns an environment variable.
+ * @param variable The environment variable to get.
+ * @return The value of the environment variable, or <tt>""</tt> if not found.
+ */
+std::string getenv(const std::string& variable);
+
+/** Gets the user name of the current user.
+ * @return The name of the current user.
+ */
+std::string get_user_name();
+
+/** Gets the real name of the user.
+ * This usually comes from the user's entry in the <tt>passwd</tt> file.
+ * @return The user's real name.
+ */
+std::string get_real_name();
+
+/** Gets the current user's home directory.
+ * @return The current user's home directory.
+ */
+std::string get_home_dir();
+
+/** Gets the directory to use for temporary files.
+ * This is found from inspecting the environment variables <tt>TMPDIR</tt>,
+ * <tt>TMP</tt>, and <tt>TEMP</tt> in that order. If none of those are defined
+ * <tt>"/tmp"</tt> is returned on UNIX and <tt>"C:\\"</tt> on Windows.
+ * @return The directory to use for temporary files.
+ */
+std::string get_tmp_dir();
+
+/** Gets the current directory.
+ * @return The current directory.
+ */
+std::string get_current_dir();
+
+/** Returns @c true if the given @a filename is an absolute file name, i.e.\ it
+ * contains a full path from the root directory such as <tt>"/usr/local"</tt>
+ * on UNIX or <tt>"C:\\windows"</tt> on Windows systems.
+ * @param filename A file name.
+ * @return Whether @a filename is an absolute path.
+ */
+bool path_is_absolute(const std::string& filename);
+
+/** Returns the remaining part of @a filename after the root component,
+ * i.e.\ after the <tt>"/"</tt> on UNIX or <tt>"C:\\"</tt> on Windows.
+ * If @a filename is not an absolute path, <tt>""</tt> will be returned.
+ * @param filename A file name.
+ * @return The file name without the root component, or <tt>""</tt>.
+ */
+std::string path_skip_root(const std::string& filename);
+
+/** Gets the name of the file without any leading directory components.
+ * @param filename The name of the file.
+ * @return The name of the file without any leading directory components.
+ */
+std::string path_get_basename(const std::string& filename);
+
+/** Gets the directory components of a file name.
+ * If the file name has no directory components <tt>"."</tt> is returned.
+ * @param filename The name of the file.
+ * @return The directory components of the file.
+ */
+std::string path_get_dirname(const std::string& filename);
+
+/** Creates a filename from a series of elements using the correct
+ * separator for filenames.
+ * This function behaves identically to Glib::build_path(G_DIR_SEPARATOR_S,
+ * elements). No attempt is made to force the resulting filename to be an
+ * absolute path. If the first element is a relative path, the result will
+ * be a relative path.
+ * @param elements A container holding the elements of the path to build.
+ * Any STL compatible container type is accepted.
+ * @return The resulting path.
+ */
+std::string build_filename(const Glib::ArrayHandle<std::string>& elements);
+
+/** Creates a filename from two elements using the correct separator for filenames.
+ * No attempt is made to force the resulting filename to be an absolute path.
+ * If the first element is a relative path, the result will be a relative path.
+ * @param elem1 First path element.
+ * @param elem2 Second path element.
+ * @return The resulting path.
+ */
+std::string build_filename(const std::string& elem1, const std::string& elem2);
+
+/** Creates a path from a series of elements using @a separator as the
+ * separator between elements. At the boundary between two elements, any
+ * trailing occurrences of @a separator in the first element, or leading
+ * occurrences of @a separator in the second element are removed and exactly
+ * one copy of the separator is inserted.
+ * @param separator A string used to separate the elements of the path.
+ * @param elements A container holding the elements of the path to build.
+ * Any STL compatible container type is accepted.
+ * @return The resulting path.
+ */
+std::string build_path(const std::string& separator,
+ const Glib::ArrayHandle<std::string>& elements);
+
+/** Locates the first executable named @a program in the user's path, in the
+ * same way that <tt>execvp()</tt> would locate it.
+ * Returns a string with the absolute path name, or <tt>""</tt> if the program
+ * is not found in the path. If @a program is already an absolute path,
+ * returns a copy of @a program if @a program exists and is executable, and
+ * <tt>""</tt> otherwise.
+ *
+ * On Windows, if @a program does not have a file type suffix, tries to append
+ * the suffixes in the <tt>PATHEXT</tt> environment variable (if that doesn't
+ * exist, the suffixes .com, .exe, and .bat) in turn, and then look for the
+ * resulting file name in the same way as CreateProcess() would. This means
+ * first in the directory where the program was loaded from, then in the
+ * current directory, then in the Windows 32-bit system directory, then in the
+ * Windows directory, and finally in the directories in the <tt>PATH</tt>
+ * environment variable. If the program is found, the return value contains
+ * the full name including the type suffix.
+ *
+ * @param program A program name.
+ * @return An absolute path, or <tt>""</tt>.
+ */
+std::string find_program_in_path(const std::string& program);
+
+/** @} group MiscUtils */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_FILEUTILS_H */
+
diff --git a/glib/glibmm/object.cc b/glib/glibmm/object.cc
new file mode 100644
index 00000000..4e94b428
--- /dev/null
+++ b/glib/glibmm/object.cc
@@ -0,0 +1,287 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/object.h>
+#include <glibmm/private/object_p.h>
+#include <glibmm/property.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+
+#include <cstdarg>
+
+#include <cstring>
+
+//Weak references:
+//I'm not sure what the point of these are apart from being a hacky way out of circular references,
+//but maybe we could make it easier to use them by making a Java Reference Object -style class like so:
+// Glib::WeakRef<SomeDerivedObject> weakrefSomeObject(object1);
+// ...
+// if(weakrefSomeObject->isStillAlive())
+// {
+// weakrefSomeObject->some_method();
+// }
+// else
+// {
+// //Deal with it, maybe recreating the object.
+// }
+//
+// Without this, the coder has to define his own signal handler which sets his own isStillAlive boolean.
+// weakrefSomeObject<> could still have its own signal_destroyed signal so that coders can choose to deal
+// with the destruction as soon as it happens instead of just checking later before they try to use it.
+
+
+namespace Glib
+{
+
+ConstructParams::ConstructParams(const Glib::Class& glibmm_class_)
+:
+ glibmm_class (glibmm_class_),
+ n_parameters (0),
+ parameters (0)
+{}
+
+/* The implementation is mostly copied from gobject.c, with some minor tweaks.
+ * Basically, it looks up each property name to get its GType, and then uses
+ * G_VALUE_COLLECT() to store the varargs argument in a GValue of the correct
+ * type.
+ */
+ConstructParams::ConstructParams(const Glib::Class& glibmm_class_,
+ const char* first_property_name, ...)
+:
+ glibmm_class (glibmm_class_),
+ n_parameters (0),
+ parameters (0)
+{
+ va_list var_args;
+ va_start(var_args, first_property_name);
+
+ GObjectClass *const g_class =
+ static_cast<GObjectClass*>(g_type_class_ref(glibmm_class.get_type()));
+
+ unsigned int n_alloced_params = 8;
+ parameters = g_new(GParameter, n_alloced_params);
+
+ char* collect_error = 0; // output arg of G_VALUE_COLLECT()
+
+ for(const char* name = first_property_name;
+ name != 0;
+ name = va_arg(var_args, char*))
+ {
+ GParamSpec *const pspec = g_object_class_find_property(g_class, name);
+
+ if(!pspec)
+ {
+ g_warning("Glib::ConstructParams::ConstructParams(): "
+ "object class `%s' has no property named `%s'",
+ g_type_name(glibmm_class.get_type()), name);
+ break;
+ }
+
+ if(n_parameters >= n_alloced_params)
+ {
+ n_alloced_params += 8;
+ parameters = g_renew(GParameter, parameters, n_alloced_params);
+ }
+
+ GParameter& param = parameters[n_parameters];
+
+ param.name = name;
+ param.value.g_type = 0;
+
+ // Fill the GValue with the current vararg, and move on to the next one.
+ g_value_init(&param.value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+ G_VALUE_COLLECT(&param.value, var_args, 0, &collect_error);
+
+ if(collect_error)
+ {
+ g_warning("Glib::ConstructParams::ConstructParams(): %s", collect_error);
+ g_free(collect_error);
+
+ // We purposely leak the value here, it might not be
+ // in a sane state if an error condition occurred.
+ break;
+ }
+
+ ++n_parameters;
+ }
+
+ g_type_class_unref(g_class);
+
+ va_end(var_args);
+}
+
+ConstructParams::~ConstructParams()
+{
+ while(n_parameters > 0)
+ g_value_unset(&parameters[--n_parameters].value);
+
+ g_free(parameters);
+}
+
+
+/**** Glib::Object_Class ***************************************************/
+
+const Glib::Class& Object_Class::init()
+{
+ if(!gtype_)
+ {
+ class_init_func_ = &Object_Class::class_init_function;
+ register_derived_type(G_TYPE_OBJECT);
+ }
+
+ return *this;
+}
+
+void Object_Class::class_init_function(void*, void*)
+{}
+
+Object* Object_Class::wrap_new(GObject* object)
+{
+ return new Object(object);
+}
+
+
+/**** Glib::Object *********************************************************/
+
+// static data
+Object::CppClassType Object::object_class_;
+
+Object::Object()
+{
+ // This constructor is ONLY for derived classes that are NOT wrappers of
+ // derived C objects. For instance, Gtk::Object should NOT use this
+ // constructor. TODO: Remove the g_warning()
+ g_warning("Object::Object(): Did you really mean to call this?");
+
+ ObjectBase::initialize(static_cast<GObject*>(g_object_newv(G_TYPE_OBJECT, 0, 0)));
+}
+
+Object::Object(const Glib::ConstructParams& construct_params)
+{
+ GType object_type = construct_params.glibmm_class.get_type();
+
+ // If Glib::ObjectBase has been constructed with a custom typeid, we derive
+ // a new GType on the fly. This works because ObjectBase is a virtual base
+ // class, therefore its constructor is always executed first.
+
+ if(custom_type_name_ && !is_anonymous_custom_())
+ object_type = construct_params.glibmm_class.clone_custom_type(custom_type_name_);
+
+ // Create a new GObject with the specified array of construct properties.
+ // This works with custom types too, since those inherit the properties of
+ // their base class.
+
+ void *const new_object = g_object_newv(
+ object_type, construct_params.n_parameters, construct_params.parameters);
+
+ // Connect the GObject and Glib::Object instances.
+ ObjectBase::initialize(static_cast<GObject*>(new_object));
+}
+
+Object::Object(GObject* castitem)
+{
+ //I disabled this check because libglademm really does need to do this.
+ //(actually it tells libglade to instantiate "gtkmm_" types.
+ //The 2nd instance bug will be caught elsewhere anyway.
+/*
+ static const char gtkmm_prefix[] = "gtkmm__";
+ const char *const type_name = G_OBJECT_TYPE_NAME(castitem);
+
+ if(strncmp(type_name, gtkmm_prefix, sizeof(gtkmm_prefix) - 1) == 0)
+ {
+ g_warning("Glib::Object::Object(GObject*): "
+ "An object of type '%s' was created directly via g_object_new(). "
+ "The Object::Object(const Glib::ConstructParams&) constructor "
+ "should be used instead.\n"
+ "This could happen if the C instance lived longer than the C++ instance, so that "
+ "a second C++ instance was created automatically to wrap it. That would be a gtkmm bug that you should report.",
+ type_name);
+ }
+*/
+
+ // Connect the GObject and Glib::Object instances.
+ ObjectBase::initialize(castitem);
+}
+
+Object::~Object()
+{
+ cpp_destruction_in_progress_ = true;
+}
+
+/*
+RefPtr<Object> Object::create()
+{
+ // Derived classes will actually return RefPtr<>s that contain useful instances.
+ return RefPtr<Object>();
+}
+*/
+
+GType Object::get_type()
+{
+ return object_class_.init().get_type();
+}
+
+GType Object::get_base_type()
+{
+ return G_TYPE_OBJECT;
+}
+
+// Data services
+void* Object::get_data(const QueryQuark& id)
+{
+ return g_object_get_qdata(gobj(),id);
+}
+
+void Object::set_data(const Quark& id, void* data)
+{
+ g_object_set_qdata(gobj(),id,data);
+}
+
+void Object::set_data(const Quark& id, void* data, DestroyNotify destroy)
+{
+ g_object_set_qdata_full(gobj(), id, data, destroy);
+}
+
+void Object::remove_data(const QueryQuark& id)
+{
+ // missing in glib??
+ g_return_if_fail(id.id() > 0);
+ g_datalist_id_remove_data(&gobj()->qdata, id);
+}
+
+void* Object::steal_data(const QueryQuark& id)
+{
+ return g_object_steal_qdata(gobj(), id);
+}
+
+void Object::set_property_value(const Glib::ustring& property_name, const Glib::ValueBase& value)
+{
+ g_object_set_property(gobj(), property_name.c_str(), value.gobj());
+}
+
+void Object::get_property_value(const Glib::ustring& property_name, Glib::ValueBase& value) const
+{
+ g_object_get_property(const_cast<GObject*>(gobj()), property_name.c_str(), value.gobj());
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/object.h b/glib/glibmm/object.h
new file mode 100644
index 00000000..9cd42412
--- /dev/null
+++ b/glib/glibmm/object.h
@@ -0,0 +1,188 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_OBJECT_H
+#define _GLIBMM_OBJECT_H
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/objectbase.h>
+#include <glibmm/wrap.h>
+#include <glibmm/quark.h>
+#include <glibmm/signalproxy.h>
+#include <glibmm/propertyproxy.h>
+#include <glibmm/refptr.h>
+#include <glibmm/utility.h> /* Could be private, but that would be tedious. */
+#include <glibmm/value.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C"
+{
+typedef struct _GObject GObject;
+typedef struct _GObjectClass GObjectClass;
+}
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+class Class;
+class Object_Class;
+class GSigConnectionNode;
+
+/* ConstructParams::ConstructParams() takes a varargs list of properties
+ * and values, like g_object_new() does. This list will then be converted
+ * to a GParameter array, for use with g_object_newv(). No overhead is
+ * involved, since g_object_new() is just a wrapper around g_object_newv()
+ * as well.
+ *
+ * The advantage of an auxilary ConstructParams object over g_object_new()
+ * is that the actual construction is always done in the Glib::Object ctor.
+ * This allows for neat tricks like easy creation of derived custom types,
+ * without adding special support to each ctor of every class.
+ *
+ * The comments in object.cc and objectbase.cc should explain in detail
+ * how this works.
+ */
+struct ConstructParams
+{
+ const Glib::Class& glibmm_class;
+ unsigned int n_parameters;
+ GParameter* parameters;
+
+ explicit ConstructParams(const Glib::Class& glibmm_class_);
+ ConstructParams(const Glib::Class& glibmm_class_, const char* first_property_name, ...);
+ ~ConstructParams();
+
+private:
+ // noncopyable
+ ConstructParams(const ConstructParams&);
+ ConstructParams& operator=(const ConstructParams&);
+};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+class Object : virtual public ObjectBase
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ typedef Object CppObjectType;
+ typedef Object_Class CppClassType;
+ typedef GObject BaseObjectType;
+ typedef GObjectClass BaseClassType;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+protected:
+ Object(); //For use by C++-only sub-types.
+ explicit Object(const Glib::ConstructParams& construct_params);
+ explicit Object(GObject* castitem);
+ virtual ~Object(); //It should only be deleted by the callback.
+
+public:
+ //static RefPtr<Object> create(); //You must reimplement this in each derived class.
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ static GType get_type() G_GNUC_CONST;
+ static GType get_base_type() G_GNUC_CONST;
+#endif
+
+ //GObject* gobj_copy(); //Give a ref-ed copy to someone. Use for direct struct access.
+
+ // Glib::Objects contain a list<Quark, pair<void*, DestroyNotify> >
+ // to store run time data added to the object at run time.
+ //TODO: Use slots instead:
+ void* get_data(const QueryQuark &key);
+ void set_data(const Quark &key, void* data);
+ typedef void (*DestroyNotify) (gpointer data);
+ void set_data(const Quark &key, void* data, DestroyNotify notify);
+ void remove_data(const QueryQuark& quark);
+ // same as remove without notifying
+ void* steal_data(const QueryQuark& quark);
+
+ // convenience functions
+ //template <class T>
+ //void set_data_typed(const Quark& quark, const T& data)
+ // { set_data(quark, new T(data), delete_typed<T>); }
+
+ //template <class T>
+ //T& get_data_typed(const QueryQuark& quark)
+ // { return *static_cast<T*>(get_data(quark)); }
+
+ /// You probably want to use a specific property_*() accessor method instead.
+ void set_property_value(const Glib::ustring& property_name, const Glib::ValueBase& value);
+
+ /// You probably want to use a specific property_*() accessor method instead.
+ void get_property_value(const Glib::ustring& property_name, Glib::ValueBase& value) const;
+
+ /// You probably want to use a specific property_*() accessor method instead.
+ template <class PropertyType>
+ void set_property(const Glib::ustring& property_name, const PropertyType& value);
+
+ /// You probably want to use a specific property_*() accessor method instead.
+ template <class PropertyType>
+ void get_property(const Glib::ustring& property_name, PropertyType& value) const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+private:
+ friend class Glib::Object_Class;
+ static CppClassType object_class_;
+
+ // noncopyable
+ Object(const Object&);
+ Object& operator=(const Object&);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+ // Glib::Object can not be dynamic because it lacks a float state.
+ //virtual void set_manage();
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <class PropertyType>
+void Object::set_property(const Glib::ustring& property_name, const PropertyType& value)
+{
+ Glib::Value<PropertyType> property_value;
+ property_value.init(Glib::Value<PropertyType>::value_type());
+
+ property_value.set(value);
+ this->set_property_value(property_name, property_value);
+}
+
+template <class PropertyType>
+void Object::get_property(const Glib::ustring& property_name, PropertyType& value) const
+{
+ Glib::Value<PropertyType> property_value;
+ property_value.init(Glib::Value<PropertyType>::value_type());
+
+ this->get_property_value(property_name, property_value);
+
+ value = property_value.get();
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+#endif /* _GLIBMM_OBJECT_H */
+
diff --git a/glib/glibmm/objectbase.cc b/glib/glibmm/objectbase.cc
new file mode 100644
index 00000000..7fa2b4c9
--- /dev/null
+++ b/glib/glibmm/objectbase.cc
@@ -0,0 +1,257 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib-object.h>
+
+#include <glibmm/quark.h>
+#include <glibmm/objectbase.h>
+
+
+namespace
+{
+
+// Used by the Glib::ObjectBase default ctor. Using an explicitly defined
+// char array rather than a string literal allows for fast pointer comparison,
+// which is otherwise not guaranteed to work.
+
+const char anonymous_custom_type_name[] = "gtkmm__anonymous_custom_type";
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+/**** Glib::ObjectBase *****************************************************/
+
+ObjectBase::ObjectBase()
+:
+ gobject_ (0),
+ custom_type_name_ (anonymous_custom_type_name),
+ cpp_destruction_in_progress_ (false)
+{}
+
+ObjectBase::ObjectBase(const char* custom_type_name)
+:
+ gobject_ (0),
+ custom_type_name_ (custom_type_name),
+ cpp_destruction_in_progress_ (false)
+{}
+
+ObjectBase::ObjectBase(const std::type_info& custom_type_info)
+:
+ gobject_ (0),
+ custom_type_name_ (custom_type_info.name()),
+ cpp_destruction_in_progress_ (false)
+{}
+
+// initialize() actually initializes the wrapper. Glib::ObjectBase is used
+// as virtual base class, which means the most-derived class' ctor invokes
+// the Glib::ObjectBase ctor -- thus it's useless for Glib::Object.
+//
+void ObjectBase::initialize(GObject* castitem)
+{
+ if(gobject_)
+ {
+ // initialize() might be called twice when used with MI, e.g. by the ctors
+ // of Glib::Object and Glib::Interface. However, they must both refer to
+ // the same underlying GObject instance.
+ //
+ g_assert(gobject_ == castitem);
+
+ // TODO: Think about it. Will this really be called twice?
+ g_printerr("ObjectBase::initialize() called twice for the same GObject\n");
+
+ return; // Don't initialize the wrapper twice.
+ }
+
+ //g_print("%s : %s\n", G_GNUC_PRETTY_FUNCTION, G_OBJECT_TYPE_NAME(castitem));
+
+ gobject_ = castitem;
+ _set_current_wrapper(castitem);
+}
+
+ObjectBase::~ObjectBase()
+{
+ // Normally, gobject_ should always be 0 at this point, because:
+ //
+ // a) Gtk::Object handles memory management on its own and always resets
+ // the gobject_ pointer in its destructor.
+ //
+ // b) Glib::Object instances that aren't Gtk::Objects will always be
+ // deleted by the destroy_notify_() virtual method. Calling delete
+ // on a Glib::Object is a programming error.
+ //
+ // The *only* situation where gobject_ is validly not 0 at this point
+ // happens if a derived class's ctor throws an exception. In that case
+ // we have to call g_object_unref() on our own.
+ //
+ if(GObject *const gobject = gobject_)
+ {
+#ifdef GTKMM_DEBUG_REFCOUNTING
+ g_warning("(Glib::ObjectBase::~ObjectBase): gobject_ = %p", (void*) gobject_);
+#endif
+
+ gobject_ = 0;
+
+#ifdef GTKMM_DEBUG_REFCOUNTING
+ g_warning("(Glib::ObjectBase::~ObjectBase): before g_object_steal_qdata()");
+#endif
+
+ // Remove the pointer to the wrapper from the underlying instance.
+ // This does _not_ cause invocation of the destroy_notify callback.
+ g_object_steal_qdata(gobject, quark_);
+
+#ifdef GTKMM_DEBUG_REFCOUNTING
+ g_warning("(Glib::ObjectBase::~ObjectBase): calling g_object_unref()");
+#endif
+
+ g_object_unref(gobject);
+ }
+}
+
+void ObjectBase::reference() const
+{
+ // Completely replace the SigC::Object refcounting.
+ GTKMM_DEBUG_REFERENCE(this, gobject_);
+ g_object_ref(gobject_);
+}
+
+void ObjectBase::unreference() const
+{
+ // Completely replace the SigC::Object refcounting.
+ GTKMM_DEBUG_UNREFERENCE(this, gobject_);
+ g_object_unref(gobject_);
+}
+
+GObject* ObjectBase::gobj_copy() const
+{
+ reference();
+ return gobject_;
+}
+
+void ObjectBase::_set_current_wrapper(GObject* object)
+{
+ // Store a pointer to this wrapper in the underlying instance, so that we
+ // never create a second wrapper for the same underlying instance. Also,
+ // specify a callback that will tell us when it's time to delete this C++
+ // wrapper instance:
+
+ if(object)
+ {
+ if(!g_object_get_qdata(object, Glib::quark_))
+ {
+ g_object_set_qdata_full(object, Glib::quark_, this, &destroy_notify_callback_);
+ }
+ else
+ {
+ g_warning("This object, of type %s, already has a wrapper.\n"
+ "You should use wrap() instead of a constructor.",
+ G_OBJECT_TYPE_NAME(object));
+ }
+ }
+}
+
+// static
+ObjectBase* ObjectBase::_get_current_wrapper(GObject* object)
+{
+ if(object)
+ return static_cast<ObjectBase*>(g_object_get_qdata(object, Glib::quark_));
+ else
+ return 0;
+}
+
+// static
+void ObjectBase::destroy_notify_callback_(void* data)
+{
+ //GTKMM_LIFECYCLE
+
+ // This method is called (indirectly) from g_object_run_dispose().
+ // Get the C++ instance associated with the C instance:
+ ObjectBase* cppObject = static_cast<ObjectBase*>(data); //Previously set with g_object_set_qdata_full().
+
+#ifdef GTKMM_DEBUG_REFCOUNTING
+ g_warning("ObjectBase::destroy_notify_callback_: cppObject=%10X, gobject_=%10X\n", cppObject, cppObject->gobject_);
+ g_warning(" gtypename=%s\n", cppObject->gobject_);
+#endif
+
+ if(cppObject) //This will be 0 if the C++ destructor has already run.
+ {
+ cppObject->destroy_notify_(); //Virtual - it does different things for GObject and GtkObject.
+ }
+}
+
+void ObjectBase::destroy_notify_()
+{
+ // The C instance is about to be disposed, making it unusable. Now is a
+ // good time to delete the C++ wrapper of the C instance. There is no way
+ // to force the disposal of the GObject (though GtkObject has
+ // gtk_object_destroy()), So this is the *only* place where we delete the
+ // C++ wrapper.
+ //
+ // This will only happen after the last unreference(), which will be done by
+ // the RefPtr<> destructor. There should be no way to access the wrapper or
+ // the undobjecterlying instance after that, so it's OK to delete this.
+
+#ifdef GTKMM_DEBUG_REFCOUNTING
+ g_warning("Glib::ObjectBase::destroy_notify_: gobject_=%10X\n", gobject_);
+#endif
+
+ gobject_ = 0; // Make sure we don't unref it again in the dtor.
+
+ delete this;
+}
+
+bool ObjectBase::is_anonymous_custom_() const
+{
+ // Doing high-speed pointer comparison is OK here.
+ return (custom_type_name_ == anonymous_custom_type_name);
+}
+
+bool ObjectBase::is_derived_() const
+{
+ // gtkmmproc-generated classes initialize this to 0 by default.
+ return (custom_type_name_ != 0);
+}
+
+void ObjectBase::set_manage()
+{
+ // This is a private method and SigC::manage() is a template function.
+ // Thus this will probably never run, unless you do something like:
+ //
+ // manage(static_cast<SigC::Object*>(refptr.operator->()));
+
+ g_error("Glib::ObjectBase::set_manage(): "
+ "only Gtk::Object instances can be managed");
+}
+
+bool _gobject_cppinstance_already_deleted(GObject* gobject)
+{
+ //This function is used to prevent calling wrap() on a GTK+ instance whose gtkmm instance has been deleted.
+
+ if(gobject)
+ return (bool)g_object_get_qdata(gobject, Glib::quark_cpp_wrapper_deleted_); //true means that something is odd.
+ else
+ return false; //Nothing is particularly wrong.
+}
+
+
+} // namespace Glib
+
diff --git a/glib/glibmm/objectbase.h b/glib/glibmm/objectbase.h
new file mode 100644
index 00000000..edeb40c1
--- /dev/null
+++ b/glib/glibmm/objectbase.h
@@ -0,0 +1,124 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_OBJECTBASE_H
+#define _GLIBMM_OBJECTBASE_H
+
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sigc++/object.h>
+#include <typeinfo>
+#include <glibmmconfig.h>
+#include <glibmm/debug.h>
+
+GTKMM_USING_STD(type_info)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GObject GObject; }
+#endif
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class GSigConnectionNode;
+#endif
+
+class ObjectBase : public SigC::Object
+{
+protected:
+ // Glib::ObjectBase is used as virtual base class. This means the ObjectBase
+ // ctor runs before all others -- either implicitly or explicitly. Each of
+ // the available ctors initializes custom_type_name_ in a different way:
+ //
+ // 1) default: custom_type_name_ = "gtkmm__anonymous_custom_type"
+ // 2) const char*: custom_type_name_ = custom_type_name
+ // 3) type_info: custom_type_name_ = custom_type_info.name()
+ //
+ // All classes generated by gtkmmproc use ctor 2) with custom_type_name = 0,
+ // which essentially means it's not a custom type. This is used to optimize
+ // vfunc and signal handler callbacks -- since the C++ virtual methods are
+ // not overridden, invocation can be skipped.
+ //
+ // The default ctor 1) is called implicitly from the ctor of user-derived
+ // classes -- yes, even if e.g. Gtk::Button calls ctor 2), a derived ctor
+ // always overrides this choice. The language itself ensures that the ctor
+ // is only invoked once.
+ //
+ // Ctor 3) is a special feature to allow creation of derived types on the
+ // fly, without having to use g_object_new() manually. This feature is
+ // sometimes necessary, e.g. to implement a custom Gtk::CellRenderer. The
+ // neat trick with the virtual base class ctor makes it possible to reuse
+ // the same direct base class' ctor as with non-custom types.
+
+ ObjectBase();
+ explicit ObjectBase(const char* custom_type_name);
+ explicit ObjectBase(const std::type_info& custom_type_info);
+
+ virtual ~ObjectBase() = 0;
+
+ // Called by Glib::Object and Glib::Interface constructors. See comments there.
+ void initialize(GObject* castitem);
+
+public:
+ virtual void reference() const; // overrides SigC::ObjectBase::reference()
+ virtual void unreference() const; // overrides SigC::ObjectBase::unreference()
+
+ inline GObject* gobj() { return gobject_; }
+ inline const GObject* gobj() const { return gobject_; }
+
+ // Give a ref-ed copy to someone. Use for direct struct access.
+ GObject* gobj_copy() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ static ObjectBase* _get_current_wrapper(GObject* object);
+#endif
+
+protected:
+ GObject* gobject_; // the GLib/GDK/GTK+ object instance
+ const char* custom_type_name_;
+ bool cpp_destruction_in_progress_;
+
+ bool is_anonymous_custom_() const;
+ bool is_derived_() const;
+
+ static void destroy_notify_callback_(void* data);
+ virtual void destroy_notify_();
+
+ void _set_current_wrapper(GObject* object);
+
+private:
+ // noncopyable
+ ObjectBase(const ObjectBase&);
+ ObjectBase& operator=(const ObjectBase&);
+
+ virtual void set_manage(); // calls g_error()
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ friend class Glib::GSigConnectionNode; // for GSigConnectionNode::notify()
+#endif
+};
+
+bool _gobject_cppinstance_already_deleted(GObject* gobject);
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_OBJECTBASE_H */
+
diff --git a/glib/glibmm/pattern.cc b/glib/glibmm/pattern.cc
new file mode 100644
index 00000000..a6552595
--- /dev/null
+++ b/glib/glibmm/pattern.cc
@@ -0,0 +1,66 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* pattern.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gpattern.h>
+#include <glibmm/pattern.h>
+
+
+namespace Glib
+{
+
+PatternSpec::PatternSpec(const Glib::ustring& pattern)
+:
+ gobject_ (g_pattern_spec_new(pattern.c_str()))
+{}
+
+PatternSpec::PatternSpec(GPatternSpec* gobject)
+:
+ gobject_ (gobject)
+{}
+
+PatternSpec::~PatternSpec()
+{
+ g_pattern_spec_free(gobject_);
+}
+
+bool PatternSpec::match(const Glib::ustring& str) const
+{
+ return g_pattern_match(gobject_, str.bytes(), str.c_str(), 0);
+}
+
+bool PatternSpec::match(const Glib::ustring& str, const Glib::ustring& str_reversed) const
+{
+ return g_pattern_match(gobject_, str.bytes(), str.c_str(), str_reversed.c_str());
+}
+
+bool PatternSpec::operator==(const PatternSpec& rhs) const
+{
+ return g_pattern_spec_equal(gobject_, rhs.gobject_);
+}
+
+bool PatternSpec::operator!=(const PatternSpec& rhs) const
+{
+ return !g_pattern_spec_equal(gobject_, rhs.gobject_);
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/pattern.h b/glib/glibmm/pattern.h
new file mode 100644
index 00000000..bf09a3a1
--- /dev/null
+++ b/glib/glibmm/pattern.h
@@ -0,0 +1,69 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_PATTERN_H
+#define _GLIBMM_PATTERN_H
+
+/* $Id$ */
+
+/* pattern.h
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+extern "C" { typedef struct _GPatternSpec GPatternSpec; }
+
+#include <glibmm/ustring.h>
+
+
+namespace Glib
+{
+
+/** @defgroup PatternMatching Glob-style Pattern Matching
+ * Match strings against patterns containing '*' (wildcard) and '?' (joker).
+ * @{
+ */
+
+class PatternSpec
+{
+public:
+ explicit PatternSpec(const Glib::ustring& pattern);
+ explicit PatternSpec(GPatternSpec* gobject);
+ ~PatternSpec();
+
+ bool match(const Glib::ustring& str) const;
+ bool match(const Glib::ustring& str, const Glib::ustring& str_reversed) const;
+
+ bool operator==(const PatternSpec& rhs) const;
+ bool operator!=(const PatternSpec& rhs) const;
+
+ GPatternSpec* gobj() { return gobject_; }
+ const GPatternSpec* gobj() const { return gobject_; }
+
+private:
+ GPatternSpec* gobject_;
+
+ // noncopyable
+ PatternSpec(const PatternSpec&);
+ PatternSpec& operator=(const PatternSpec&);
+};
+
+/** @} group PatternMatching */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_PATTERN_H */
+
diff --git a/glib/glibmm/private/.cvsignore b/glib/glibmm/private/.cvsignore
new file mode 100644
index 00000000..c2ad697c
--- /dev/null
+++ b/glib/glibmm/private/.cvsignore
@@ -0,0 +1,13 @@
+Makefile
+Makefile.in
+
+convert_p.h
+date_p.h
+fileutils_p.h
+iochannel_p.h
+markup_p.h
+module_p.h
+shell_p.h
+spawn_p.h
+thread_p.h
+unicode_p.h
diff --git a/glib/glibmm/private/Makefile.am b/glib/glibmm/private/Makefile.am
new file mode 100644
index 00000000..21fc8beb
--- /dev/null
+++ b/glib/glibmm/private/Makefile.am
@@ -0,0 +1,20 @@
+## Copyright (c) 2001
+## The gtkmm development team.
+
+include $(srcdir)/../../src/Makefile_list_of_hg.am_fragment
+include $(top_srcdir)/build_shared/Makefile_gensrc_platform.am_fragment
+
+files_built_h = $(files_hg:.hg=_p.h)
+files_built_all_h = $(files_all_hg:.hg=_p.h)
+files_extra_h = interface_p.h object_p.h
+files_extra_all_h = interface_p.h object_p.h
+
+dist_sources = $(files_built_all_h) $(files_extra_all_h)
+DISTFILES = $(DIST_COMMON) $(dist_sources)
+
+private_includedir = $(includedir)/gtkmm-2.0/glibmm/private
+private_include_HEADERS = $(files_built_h) $(files_extra_h)
+
+maintainer-clean-local:
+ (cd $(srcdir) && rm -f $(files_built_h))
+
diff --git a/glib/glibmm/private/interface_p.h b/glib/glibmm/private/interface_p.h
new file mode 100644
index 00000000..805d8db3
--- /dev/null
+++ b/glib/glibmm/private/interface_p.h
@@ -0,0 +1,24 @@
+// -*- c++ -*-
+
+#ifndef _GLIBMM_INTERFACE_P_H
+#define _GLIBMM_INTERFACE_P_H
+
+#include <glibmm/class.h>
+
+
+namespace Glib
+{
+
+class Interface_Class : public Glib::Class
+{
+public:
+ typedef Interface CppObjectType;
+ typedef GTypeInterface BaseClassType;
+
+ void add_interface(GType instance_type) const;
+};
+
+} // namespace Glib
+
+#endif /* _GLIBMM_INTERFACE_P_H */
+
diff --git a/glib/glibmm/private/object_p.h b/glib/glibmm/private/object_p.h
new file mode 100644
index 00000000..20a71189
--- /dev/null
+++ b/glib/glibmm/private/object_p.h
@@ -0,0 +1,28 @@
+// -*- c++ -*-
+
+#ifndef _GLIBMM_OBJECT_P_H
+#define _GLIBMM_OBJECT_P_H
+
+#include <glibmm/class.h>
+
+namespace Glib
+{
+
+class Object_Class : public Glib::Class
+{
+public:
+ typedef Object CppObjectType;
+ typedef GObject BaseObjectType;
+ typedef GObjectClass BaseClassType;
+
+ static void class_init_function(void* g_class, void* class_data);
+
+ const Glib::Class& init();
+
+ static Glib::Object* wrap_new(GObject*);
+};
+
+} // namespace Glib
+
+#endif /* _GLIBMM_OBJECT_P_H */
+
diff --git a/glib/glibmm/property.cc b/glib/glibmm/property.cc
new file mode 100644
index 00000000..e801e0c1
--- /dev/null
+++ b/glib/glibmm/property.cc
@@ -0,0 +1,198 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/property.h>
+#include <glibmm/object.h>
+#include <cstddef>
+
+// Temporary hack till GLib gets fixed.
+#undef G_STRLOC
+#define G_STRLOC __FILE__ ":" G_STRINGIFY(__LINE__)
+
+
+namespace
+{
+
+// OK guys, please don't kill me for that. Let me explain what happens here.
+//
+// The task:
+// ---------
+// a) Autogenerate a property ID number for each custom property. This is an
+// unsigned integer, which doesn't have to be assigned continuously. I.e.,
+// it can be everything but 0.
+// b) If more than one object of the same class is instantiated, then of course
+// the already installed properties must be used. That means, a property ID
+// must not be associated with a single Glib::Property<> instance. Rather,
+// the ID has to be associated with the class somehow.
+// c) With only a GObject pointer and a property ID (and perhaps GParamSpec*
+// if necessary), it must be possible to acquire a reference to the property
+// wrapper instance.
+//
+// The current solution:
+// ---------------------
+// a) Assign an ID to a Glib::PropertyBase by calculating its offset in bytes
+// relative to the beginning of the object's memory. dynamic_cast<void*>
+// is used to retrieve a pointer to the very beginning of an instance.
+// b) Recalculate a specific PropertyBase pointer by adding the property ID
+// (i.e. the byte offset) to the object start pointer. The result is then
+// just casted to PropertyBase*.
+//
+// Drawbacks:
+// ----------
+// a) It's a low-level hack. Should be portable, yes, but we can only do very
+// limited error checking.
+// b) All Glib::Property<> instances are absolutely required to be direct data
+// members of the class that implements the property. That seems a natural
+// thing to do, but it's questionable whether it should be a requirement.
+//
+// Advantages:
+// -----------
+// a) Although low-level, it's extremely easy to implement. The nasty code is
+// concentrated in only two non-exposed utility functions, and it works
+// just fine.
+// b) It's efficient, and the memory footprint is very small too.
+// c) I actually tried other ways, too, but ran into dead-ends everywhere.
+// It's probably possible to implement this without calculating offsets,
+// but it'll be very complicated, and involve a lot of qdata pointers to
+// property tables andwhatnot.
+//
+// We can reimplement this later if necessary.
+
+unsigned int property_to_id(Glib::ObjectBase& object, Glib::PropertyBase& property)
+{
+ void *const base_ptr = dynamic_cast<void*>(&object);
+ void *const prop_ptr = &property;
+
+ const ptrdiff_t offset = static_cast<guint8*>(prop_ptr) - static_cast<guint8*>(base_ptr);
+
+ g_return_val_if_fail(offset > 0 && offset < G_MAXINT, 0);
+
+ return static_cast<unsigned int>(offset);
+}
+
+Glib::PropertyBase& property_from_id(Glib::ObjectBase& object, unsigned int property_id)
+{
+ void *const base_ptr = dynamic_cast<void*>(&object);
+ void *const prop_ptr = static_cast<guint8*>(base_ptr) + property_id;
+
+ return *static_cast<Glib::PropertyBase*>(prop_ptr);
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+void custom_get_property_callback(GObject* object, unsigned int property_id,
+ GValue* value, GParamSpec* param_spec)
+{
+ if(Glib::ObjectBase *const wrapper = Glib::ObjectBase::_get_current_wrapper(object))
+ {
+ PropertyBase& property = property_from_id(*wrapper, property_id);
+
+ if((property.object_ == wrapper) && (property.param_spec_ == param_spec))
+ g_value_copy(property.value_.gobj(), value);
+ else
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, param_spec);
+ }
+}
+
+void custom_set_property_callback(GObject* object, unsigned int property_id,
+ const GValue* value, GParamSpec* param_spec)
+{
+ if(Glib::ObjectBase *const wrapper = Glib::ObjectBase::_get_current_wrapper(object))
+ {
+ PropertyBase& property = property_from_id(*wrapper, property_id);
+
+ if((property.object_ == wrapper) && (property.param_spec_ == param_spec))
+ {
+ g_value_copy(value, property.value_.gobj());
+ g_object_notify(object, g_param_spec_get_name(param_spec));
+ }
+ else
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, param_spec);
+ }
+}
+
+
+/**** Glib::PropertyBase ***************************************************/
+
+PropertyBase::PropertyBase(Glib::Object& object, GType value_type)
+:
+ object_ (&object),
+ value_ (),
+ param_spec_ (0)
+{
+ value_.init(value_type);
+}
+
+PropertyBase::~PropertyBase()
+{
+ if(param_spec_)
+ g_param_spec_unref(param_spec_);
+}
+
+bool PropertyBase::lookup_property(const Glib::ustring& name)
+{
+ g_assert(param_spec_ == 0);
+
+ param_spec_ = g_object_class_find_property(G_OBJECT_GET_CLASS(object_->gobj()), name.c_str());
+
+ if(param_spec_)
+ {
+ g_assert(G_PARAM_SPEC_VALUE_TYPE(param_spec_) == G_VALUE_TYPE(value_.gobj()));
+ g_param_spec_ref(param_spec_);
+ }
+
+ return (param_spec_ != 0);
+}
+
+void PropertyBase::install_property(GParamSpec* param_spec)
+{
+ g_return_if_fail(param_spec != 0);
+
+ const unsigned int property_id = property_to_id(*object_, *this);
+
+ g_object_class_install_property(G_OBJECT_GET_CLASS(object_->gobj()), property_id, param_spec);
+
+ param_spec_ = param_spec;
+ g_param_spec_ref(param_spec_);
+}
+
+const char* PropertyBase::get_name_internal() const
+{
+ const char *const name = g_param_spec_get_name(param_spec_);
+ g_return_val_if_fail(name != 0, "");
+ return name;
+}
+
+Glib::ustring PropertyBase::get_name() const
+{
+ return Glib::ustring(get_name_internal());
+}
+
+void PropertyBase::notify()
+{
+ g_object_notify(object_->gobj(), g_param_spec_get_name(param_spec_));
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/property.h b/glib/glibmm/property.h
new file mode 100644
index 00000000..288c17d2
--- /dev/null
+++ b/glib/glibmm/property.h
@@ -0,0 +1,161 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_PROPERTY_H
+#define _GLIBMM_PROPERTY_H
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/propertyproxy.h>
+#include <glibmm/value.h>
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+void custom_get_property_callback(GObject* object, unsigned int property_id,
+ GValue* value, GParamSpec* param_spec);
+
+void custom_set_property_callback(GObject* object, unsigned int property_id,
+ const GValue* value, GParamSpec* param_spec);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+class PropertyBase
+{
+public:
+ Glib::ustring get_name() const;
+ void notify();
+
+protected:
+ Glib::Object* object_;
+ Glib::ValueBase value_;
+ GParamSpec* param_spec_;
+
+ PropertyBase(Glib::Object& object, GType value_type);
+ ~PropertyBase();
+
+ bool lookup_property(const Glib::ustring& name);
+ void install_property(GParamSpec* param_spec);
+
+ const char* get_name_internal() const;
+
+private:
+ // noncopyable
+ PropertyBase(const PropertyBase&);
+ PropertyBase& operator=(const PropertyBase&);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+ friend void Glib::custom_get_property_callback(GObject* object, unsigned int property_id,
+ GValue* value, GParamSpec* param_spec);
+
+ friend void Glib::custom_set_property_callback(GObject* object, unsigned int property_id,
+ const GValue* value, GParamSpec* param_spec);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+};
+
+
+template <class T>
+class Property : public PropertyBase
+{
+public:
+ typedef T PropertyType;
+ typedef Glib::Value<T> ValueType;
+
+ Property(Glib::Object& object, const Glib::ustring& name);
+ Property(Glib::Object& object, const Glib::ustring& name, const PropertyType& default_value);
+
+ inline void set_value(const PropertyType& data);
+ inline PropertyType get_value() const;
+
+ inline Property<T>& operator=(const PropertyType& data);
+ inline operator PropertyType() const;
+
+ inline Glib::PropertyProxy<T> get_proxy();
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/**** Glib::Property<T> ****************************************************/
+
+template <class T>
+Property<T>::Property(Glib::Object& object, const Glib::ustring& name)
+:
+ PropertyBase(object, ValueType::value_type())
+{
+ if(!lookup_property(name))
+ install_property(static_cast<ValueType&>(value_).create_param_spec(name));
+}
+
+template <class T>
+Property<T>::Property(Glib::Object& object, const Glib::ustring& name,
+ const typename Property<T>::PropertyType& default_value)
+:
+ PropertyBase(object, ValueType::value_type())
+{
+ static_cast<ValueType&>(value_).set(default_value);
+
+ if(!lookup_property(name))
+ install_property(static_cast<ValueType&>(value_).create_param_spec(name));
+}
+
+template <class T> inline
+void Property<T>::set_value(const typename Property<T>::PropertyType& data)
+{
+ static_cast<ValueType&>(value_).set(data);
+ this->notify();
+}
+
+template <class T> inline
+typename Property<T>::PropertyType Property<T>::get_value() const
+{
+ return static_cast<const ValueType&>(value_).get();
+}
+
+template <class T> inline
+Property<T>& Property<T>::operator=(const typename Property<T>::PropertyType& data)
+{
+ static_cast<ValueType&>(value_).set(data);
+ this->notify();
+ return *this;
+}
+
+template <class T> inline
+Property<T>::operator T() const
+{
+ return static_cast<const ValueType&>(value_).get();
+}
+
+template <class T> inline
+Glib::PropertyProxy<T> Property<T>::get_proxy()
+{
+ return Glib::PropertyProxy<T>(object_, get_name_internal());
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_PROPERTY_H */
+
diff --git a/glib/glibmm/propertyproxy.cc b/glib/glibmm/propertyproxy.cc
new file mode 100644
index 00000000..c20f36bc
--- /dev/null
+++ b/glib/glibmm/propertyproxy.cc
@@ -0,0 +1,24 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* propertyproxy.cc
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/propertyproxy.h>
+
diff --git a/glib/glibmm/propertyproxy.h b/glib/glibmm/propertyproxy.h
new file mode 100644
index 00000000..a0da2764
--- /dev/null
+++ b/glib/glibmm/propertyproxy.h
@@ -0,0 +1,129 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_PROPERTYPROXY_H
+#define _GLIBMM_PROPERTYPROXY_H
+/* $Id$ */
+
+/* propertyproxy.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/propertyproxy_base.h>
+
+
+namespace Glib
+{
+
+template <class T>
+class PropertyProxy : public PropertyProxy_Base
+{
+public:
+ typedef T PropertyType;
+
+ PropertyProxy(Object* obj, const char* name)
+ : PropertyProxy_Base(obj, name) {}
+
+ void set_value(const PropertyType& data);
+ PropertyType get_value() const;
+
+ void reset_value()
+ { reset_property_(); }
+
+ PropertyProxy<T>& operator=(const PropertyType& data)
+ { this->set_value(data); return *this; }
+
+ operator PropertyType() const
+ { return this->get_value(); }
+};
+
+
+template <class T>
+class PropertyProxy_WriteOnly : public PropertyProxy_Base
+{
+public:
+ typedef T PropertyType;
+
+ PropertyProxy_WriteOnly(Object* obj, const char* name)
+ : PropertyProxy_Base(obj, name) {}
+
+ void set_value(const PropertyType& data)
+ {
+ PropertyProxy_Base& base = *this;
+ // The downcast to PropertyProxy<T> is safe, and avoids code duplication.
+ static_cast<PropertyProxy<T>&>(base).set_value(data);
+ }
+
+ void reset_value()
+ { reset_property_(); }
+
+ PropertyProxy_WriteOnly<T>& operator=(const PropertyType& data)
+ { this->set_value(data); return *this; }
+};
+
+
+template <class T>
+class PropertyProxy_ReadOnly : public PropertyProxy_Base
+{
+public:
+ typedef T PropertyType;
+
+ PropertyProxy_ReadOnly(Object* obj, const char* name)
+ : PropertyProxy_Base(obj, name) {}
+
+ PropertyType get_value() const
+ {
+ const PropertyProxy_Base& base = *this;
+ // The downcast to PropertyProxy<T> is safe, and avoids code duplication.
+ return static_cast<const PropertyProxy<T>&>(base).get_value();
+ }
+
+ operator PropertyType() const
+ { return this->get_value(); }
+};
+
+
+/**** Template Implementation **********************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <class T>
+void PropertyProxy<T>::set_value(const T& data)
+{
+ Glib::Value<T> value;
+ value.init(Glib::Value<T>::value_type());
+
+ value.set(data);
+ set_property_(value);
+}
+
+template <class T>
+T PropertyProxy<T>::get_value() const
+{
+ Glib::Value<T> value;
+ value.init(Glib::Value<T>::value_type());
+
+ get_property_(value);
+ return value.get();
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_PROPERTYPROXY_H */
+
diff --git a/glib/glibmm/propertyproxy_base.cc b/glib/glibmm/propertyproxy_base.cc
new file mode 100644
index 00000000..177ab6e8
--- /dev/null
+++ b/glib/glibmm/propertyproxy_base.cc
@@ -0,0 +1,159 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* propertyproxy_base.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/propertyproxy_base.h>
+#include <glibmm/signalproxy_connectionnode.h>
+#include <glibmm/object.h>
+#include <glibmm/private/object_p.h>
+
+namespace Glib
+{
+
+/** PropertyProxyConnectionNode is a SigC::ConnectionNode for use with SignalProxyProperty.
+ * It's like ProxyConnectionNode, but it contains the property name too.
+ */
+class PropertyProxyConnectionNode : public SignalProxyConnectionNode
+{
+public:
+ friend class SignalProxyProperty;
+
+ PropertyProxyConnectionNode(SigC::SlotNode* slot_data, GObject* gobject, const gchar* property_name);
+ virtual ~PropertyProxyConnectionNode();
+
+protected:
+ //This will be examined in the callback.
+ //Should be a static string literal.
+ const gchar* property_name_;
+};
+
+PropertyProxyConnectionNode::PropertyProxyConnectionNode(SigC::SlotNode* slot_data, GObject* gobject, const gchar* property_name)
+: SignalProxyConnectionNode(slot_data, gobject),
+ property_name_(property_name)
+{
+}
+
+PropertyProxyConnectionNode::~PropertyProxyConnectionNode()
+{
+}
+
+//SignalProxyProperty implementation:
+
+SignalProxyProperty::SignalProxyProperty(Glib::ObjectBase* obj, const gchar* property_name)
+: SignalProxyBase(obj),
+ property_name_(property_name)
+{
+}
+
+SignalProxyProperty::~SignalProxyProperty()
+{
+}
+
+SigC::Connection SignalProxyProperty::connect(const SlotType& sl)
+{
+ // create a proxy to hold our connection info
+ PropertyProxyConnectionNode* pConnectionNode = new PropertyProxyConnectionNode( (SigC::SlotNode*)(sl.impl()), obj_->gobj(), property_name_ );
+
+ // gtk+ will hold a reference to this object
+ pConnectionNode->reference();
+
+ // connect it to gtk+
+ // pConnectionNode will be passed as the data argument to the callback.
+ // The callback will then call the virtual Object::property_change_notify() method,
+ // which will contain a switch/case statement which will examine the property name.
+ pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(),
+ "notify", (GCallback)(&callback), pConnectionNode,
+ &PropertyProxyConnectionNode::destroy_notify_handler,
+ G_CONNECT_AFTER);
+
+ return SigC::Connection(pConnectionNode);
+}
+
+void SignalProxyProperty::callback(GObject*, GParamSpec* pspec, gpointer data) //static
+{
+ if(pspec && data)
+ {
+ //Get the name of the property that has changed:
+ const char* property_name_changed = pspec->name;
+
+ //Get the name of the property that we are waiting for:
+ PropertyProxyConnectionNode* conn = static_cast<PropertyProxyConnectionNode*>(data);
+ const char* property_name_monitored = conn->property_name_;
+
+ //If it's the correct property, then call the signal handler:
+ if(strcmp(property_name_changed, property_name_monitored) == 0)
+ {
+ if(SigC::SlotNode *const slot = data_to_slot(data))
+ (*(SlotType::Proxy)(slot->proxy_))(slot);
+ }
+ }
+}
+
+
+//PropertyProxy_Base implementation:
+
+PropertyProxy_Base::PropertyProxy_Base(Object* obj, const char* property_name)
+:
+ obj_ (obj),
+ property_name_ (property_name)
+{}
+
+PropertyProxy_Base::PropertyProxy_Base(const PropertyProxy_Base& other)
+:
+ obj_ (other.obj_),
+ property_name_ (other.property_name_)
+{}
+
+SignalProxyProperty PropertyProxy_Base::signal_changed()
+{
+ return SignalProxyProperty(obj_, property_name_);
+}
+
+void PropertyProxy_Base::set_property_(const Glib::ValueBase& value)
+{
+ g_object_set_property(obj_->gobj(), property_name_, value.gobj());
+}
+
+void PropertyProxy_Base::get_property_(Glib::ValueBase& value) const
+{
+ g_object_get_property(obj_->gobj(), property_name_, value.gobj());
+}
+
+void PropertyProxy_Base::reset_property_()
+{
+ // Get information about the parameter:
+ const GParamSpec *const pParamSpec =
+ g_object_class_find_property(G_OBJECT_GET_CLASS(obj_->gobj()), property_name_);
+
+ g_return_if_fail(pParamSpec != 0);
+
+ Glib::ValueBase value;
+ value.init(G_PARAM_SPEC_VALUE_TYPE(pParamSpec));
+
+ // An explicit reset is not needed, because ValueBase:init()
+ // has already initialized it to the default value for this type.
+ // value.reset();
+
+ g_object_set_property(obj_->gobj(), property_name_, value.gobj());
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/propertyproxy_base.h b/glib/glibmm/propertyproxy_base.h
new file mode 100644
index 00000000..5eb6d159
--- /dev/null
+++ b/glib/glibmm/propertyproxy_base.h
@@ -0,0 +1,84 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_PROPERTYPROXY_BASE_H
+#define _GLIBMM_PROPERTYPROXY_BASE_H
+/* $Id$ */
+
+/* propertyproxy_base.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/value.h>
+#include <glibmm/signalproxy.h>
+
+
+namespace Glib
+{
+
+class Object;
+
+/// Use the connect() method, with SigC::slot() to connect signals to signal handlers.
+class SignalProxyProperty : public SignalProxyBase
+{
+public:
+ friend class PropertyProxy_Base;
+
+ SignalProxyProperty(Glib::ObjectBase* obj, const gchar* property_name);
+ ~SignalProxyProperty();
+
+ typedef SigC::Slot0<void> SlotType;
+ SigC::Connection connect(const SlotType& sl);
+
+protected:
+ static void callback(GObject* object, GParamSpec* pspec, gpointer data);
+
+ const char* property_name_; //Should be a static string literal.
+
+private:
+ SignalProxyProperty& operator=(const SignalProxyProperty&); // not implemented
+};
+
+
+class PropertyProxy_Base
+{
+public:
+ PropertyProxy_Base(Object* obj, const char* property_name);
+ PropertyProxy_Base(const PropertyProxy_Base& other);
+
+ ///This signal will be emitted when the property changes.
+ SignalProxyProperty signal_changed();
+
+ Object* get_object() const { return obj_; }
+ const char* get_name() const { return property_name_; }
+
+protected:
+ void set_property_(const Glib::ValueBase& value);
+ void get_property_(Glib::ValueBase& value) const;
+ void reset_property_();
+
+ Object* obj_; //The C++ wrapper instance of which this PropertyProxy is a member.
+ const char* property_name_; //Should be a static string literal.
+
+private:
+ // not implemented (for now) -- Why "for now"? I don't think it'll ever be needed. daniel.
+ PropertyProxy_Base& operator=(const PropertyProxy_Base&);
+};
+
+} // namespace Glib
+
+#endif /* _GLIBMM_PROPERTYPROXY_BASE_H */
+
diff --git a/glib/glibmm/quark.cc b/glib/glibmm/quark.cc
new file mode 100644
index 00000000..ea01f470
--- /dev/null
+++ b/glib/glibmm/quark.cc
@@ -0,0 +1,66 @@
+/* $Id$ */
+
+/* quark.cc
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gquark.h>
+#include <glibmm/quark.h>
+
+namespace Glib
+{
+
+QueryQuark::QueryQuark(const GQuark& q)
+ : quark_(q)
+{}
+
+QueryQuark::QueryQuark(const ustring& s)
+: quark_(g_quark_try_string(s.c_str()))
+{}
+
+QueryQuark::QueryQuark(const char* s)
+: quark_(g_quark_try_string(s))
+{}
+
+QueryQuark& QueryQuark::operator=(const QueryQuark& q)
+{ quark_=q.quark_;
+ return *this;
+}
+
+QueryQuark::operator ustring() const
+{
+ return ustring(g_quark_to_string(quark_));
+}
+
+
+Quark::Quark(const ustring& s)
+: QueryQuark(g_quark_from_string(s.c_str()))
+{}
+
+Quark::Quark(const char* s)
+: QueryQuark(g_quark_from_string(s))
+{}
+
+Quark::~Quark()
+{}
+
+
+GQuark quark_ = 0;
+GQuark quark_cpp_wrapper_deleted_ = 0;
+
+} /* namespace Glib */
diff --git a/glib/glibmm/quark.h b/glib/glibmm/quark.h
new file mode 100644
index 00000000..d2f450fe
--- /dev/null
+++ b/glib/glibmm/quark.h
@@ -0,0 +1,88 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_QUARK_H
+#define _GLIBMM_QUARK_H
+/* $Id$ */
+
+/* quark.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gquark.h>
+#include <glibmm/ustring.h>
+
+
+namespace Glib
+{
+
+/** Quarks are unique IDs in Glib for strings for use in
+ * hash table lookups. Each Quark is unique but may change
+ * between runs.
+ *
+ * QueryQuark is a converter class for looking up but not
+ * allocating an ID. An id means the quark lookup failed.
+ *
+ * Quark is used for actions for which the id should live on
+ * While QueryQuark should be used for queries.
+ * ie.
+ * void set_data (const Quark&, void * data);
+ * void* get_data (const QueryQuark&);
+ */
+class QueryQuark
+{
+ public:
+ QueryQuark(const GQuark& q);
+ QueryQuark(const ustring& s);
+ QueryQuark(const char*s);
+ ~QueryQuark() {}
+ QueryQuark& operator=(const QueryQuark& q);
+ operator ustring() const;
+
+ operator GQuark() const {return quark_;}
+ GQuark id() const {return quark_;}
+
+ private:
+ GQuark quark_;
+};
+
+class Quark: public QueryQuark
+{
+ public:
+ Quark(const ustring& s);
+ Quark(const char* s);
+ ~Quark();
+};
+
+/** @relates Glib::QueryQuark */
+inline bool operator==(const QueryQuark& a, const QueryQuark& b)
+ { return a.id() == b.id(); }
+
+/** @relates Glib::QueryQuark */
+inline bool operator!=(const QueryQuark& a, const QueryQuark& b)
+ { return a.id() != b.id(); }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+// TODO: Put this somewhere else.
+// (internal) The quark for C++ wrappers.
+extern GLIBMM_API GQuark quark_;
+extern GLIBMM_API GQuark quark_cpp_wrapper_deleted_;
+#endif
+
+} /* namespace Glib */
+
+#endif /* _GLIBMM_QUARK_H */
+
diff --git a/glib/glibmm/random.cc b/glib/glibmm/random.cc
new file mode 100644
index 00000000..d4475616
--- /dev/null
+++ b/glib/glibmm/random.cc
@@ -0,0 +1,76 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* random.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/random.h>
+#include <glib/grand.h>
+
+
+namespace Glib
+{
+
+Rand::Rand()
+:
+ gobject_ (g_rand_new())
+{}
+
+Rand::Rand(guint32 seed)
+:
+ gobject_ (g_rand_new_with_seed(seed))
+{}
+
+Rand::~Rand()
+{
+ g_rand_free(gobject_);
+}
+
+void Rand::set_seed(guint32 seed)
+{
+ g_rand_set_seed(gobject_, seed);
+}
+
+bool Rand::get_bool()
+{
+ return g_rand_boolean(gobject_);
+}
+
+guint32 Rand::get_int()
+{
+ return g_rand_int(gobject_);
+}
+
+gint32 Rand::get_int_range(gint32 begin, gint32 end)
+{
+ return g_rand_int_range(gobject_, begin, end);
+}
+
+double Rand::get_double()
+{
+ return g_rand_double(gobject_);
+}
+
+double Rand::get_double_range(double begin, double end)
+{
+ return g_rand_double_range(gobject_, begin, end);
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/random.h b/glib/glibmm/random.h
new file mode 100644
index 00000000..4a4ce844
--- /dev/null
+++ b/glib/glibmm/random.h
@@ -0,0 +1,73 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_RANDOM_H
+#define _GLIBMM_RANDOM_H
+
+/* $Id$ */
+
+/* random.h
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gtypes.h>
+
+extern "C" { typedef struct _GRand GRand; }
+
+
+namespace Glib
+{
+
+/** @defgroup Random Random Numbers
+ * Pseudo random number generator.
+ * @{
+ */
+
+class Rand
+{
+public:
+ Rand();
+ explicit Rand(guint32 seed);
+ ~Rand();
+
+ void set_seed(guint32 seed);
+
+ bool get_bool();
+
+ guint32 get_int();
+ gint32 get_int_range(gint32 begin, gint32 end);
+
+ double get_double();
+ double get_double_range(double begin, double end);
+
+ GRand* gobj() { return gobject_; }
+ const GRand* gobj() const { return gobject_; }
+
+private:
+ GRand* gobject_;
+
+ // noncopyable
+ Rand(const Rand&);
+ Rand& operator=(const Rand&);
+};
+
+/** @} group Random */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_RANDOM_H */
+
diff --git a/glib/glibmm/refptr.h b/glib/glibmm/refptr.h
new file mode 100644
index 00000000..638a71b9
--- /dev/null
+++ b/glib/glibmm/refptr.h
@@ -0,0 +1,349 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_REFPTR_H
+#define _GLIBMM_REFPTR_H
+
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+namespace Glib
+{
+
+/** RefPtr<> is a reference-counting shared smartpointer.
+ *
+ * Some objects in gtkmm are obtained from a shared
+ * store. Consequently you cannot instantiate them yourself. Instead they
+ * return a RefPtr which behaves much like an ordinary pointer in that members
+ * can be reached with the usual <code>object_ptr->member</code> notation.
+ * Unlike most other smart pointers, RefPtr doesn't support dereferencing
+ * through <code>*object_ptr</code>.
+ *
+ * Reference counting means that a shared reference count is incremented each
+ * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
+ * for instance when it leaves its scope. When the reference count reaches
+ * zero, the contained object is deleted, meaning you don't need to remember
+ * to delete the object.
+ *
+ * RefPtr<> can store any class that has reference() and unreference() methods.
+ * In gtkmm, that is anything derived from Glib::ObjectBase, such as
+ * Gdk::Pixmap.
+ *
+ * See the "Memory Management" section in the "Programming with gtkmm"
+ * book for further information.
+ */
+template <class T_CppObject>
+class RefPtr
+{
+public:
+ /** Default constructor
+ *
+ * Afterwards is_null() will return true and use of -> will cause a segmentation fault.
+ */
+ inline RefPtr();
+
+ /// Destructor - decrements reference count.
+ inline ~RefPtr();
+
+ /// For use only by the ::create() methods.
+ explicit inline RefPtr(T_CppObject* pCppObject);
+
+ /** Copy constructor
+ *
+ * This increments the shared reference count.
+ */
+ inline RefPtr(const RefPtr<T_CppObject>& src);
+
+ /** Copy constructor (from different, but castable type).
+ *
+ * Increments the reference count.
+ */
+ template <class T_CastFrom>
+ inline RefPtr(const RefPtr<T_CastFrom>& src);
+
+ /** Swap the contents of two RefPtr<>.
+ * This method swaps the internal pointers to T_CppObject. This can be
+ * done safely without involving a reference/unreference cycle and is
+ * therefore highly efficient.
+ */
+ inline void swap(RefPtr<T_CppObject>& other);
+
+ /// Copy from another RefPtr:
+ inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
+
+ // TODO: Get rid of this evilness.
+ /// For use only by the ::create() methods.
+ inline RefPtr<T_CppObject>& operator=(T_CppObject* pCppObject);
+
+ /** Copy from different, but castable type).
+ *
+ * Increments the reference count.
+ */
+ template <class T_CastFrom>
+ inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
+
+ /// Tests whether the RefPtr<> point to the same underlying instance.
+ inline bool operator==(const RefPtr<T_CppObject>& src) const;
+
+ /// See operator==().
+ inline bool operator!=(const RefPtr<T_CppObject>& src) const;
+
+ /** Dereferencing.
+ *
+ * Use the methods of the underlying instance like so:
+ * <code>refptr->memberfun()</code>.
+ */
+ inline T_CppObject* operator->() const;
+
+ /** Test whether the RefPtr<> points to any underlying instance.
+ *
+ * Mimics usage of ordinary pointers:
+ * @code
+ * if (ptr)
+ * do_something();
+ * @endcode
+ */
+ inline operator bool() const;
+
+ /// Test whether the RefPtr<> points to any underlying instance.
+ inline bool is_null() const; // whether there is no underlying instance
+
+
+ /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
+ inline void clear();
+
+ /** Dynamic cast to derived class.
+ *
+ * The RefPtr can't be cast with the usual notation so instead you can use
+ * @code
+ * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
+ * @endcode
+ */
+ template <class T_CastFrom>
+ static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
+
+ /** Static cast to derived class.
+ *
+ * Like the dynamic cast; the notation is
+ * @code
+ * ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
+ * @endcode
+ */
+ template <class T_CastFrom>
+ static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
+
+private:
+ T_CppObject* pCppObject_;
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+// RefPtr<>::operator->() comes first here since it's used by other methods.
+// If it would come after them it wouldn't be inlined.
+
+template <class T_CppObject> inline
+T_CppObject* RefPtr<T_CppObject>::operator->() const
+{
+ return pCppObject_;
+}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>::RefPtr()
+:
+ pCppObject_ (0)
+{}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>::~RefPtr()
+{
+ if(pCppObject_)
+ pCppObject_->unreference(); // This could cause pCppObject to be deleted.
+}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
+:
+ pCppObject_ (pCppObject)
+{}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
+:
+ pCppObject_ (src.pCppObject_)
+{
+ if(pCppObject_)
+ pCppObject_->reference();
+}
+
+// The templated ctor allows copy construction from any object that's
+// castable. Thus, it does downcasts:
+// base_ref = derived_ref
+template <class T_CppObject>
+ template <class T_CastFrom>
+inline
+RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
+:
+ // A different RefPtr<> will not allow us access to pCppObject_. We need
+ // to add a get_underlying() for this, but that would encourage incorrect
+ // use, so we use the less well-known operator->() accessor:
+ pCppObject_ (src.operator->())
+{
+ if(pCppObject_)
+ pCppObject_->reference();
+}
+
+template <class T_CppObject> inline
+void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
+{
+ T_CppObject *const temp = pCppObject_;
+ pCppObject_ = other.pCppObject_;
+ other.pCppObject_ = temp;
+}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
+{
+ // In case you haven't seen the swap() technique to implement copy
+ // assignment before, here's what it does:
+ //
+ // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
+ // increasing the reference count of the source object.
+ //
+ // 2) Swap the internal object pointers of *this and the temporary
+ // RefPtr<>. After this step, *this already contains the new pointer,
+ // and the old pointer is now managed by temp.
+ //
+ // 3) The destructor of temp is executed, thereby unreferencing the
+ // old object pointer.
+ //
+ // This technique is described in Herb Sutter's "Exceptional C++", and
+ // has a number of advantages over conventional approaches:
+ //
+ // - Code reuse by calling the copy ctor.
+ // - Strong exception safety for free.
+ // - Self assignment is handled implicitely.
+ // - Simplicity.
+ // - It just works and is hard to get wrong; i.e. you can use it without
+ // even thinking about it to implement copy assignment whereever the
+ // object data is managed indirectly via a pointer, which is very common.
+
+ RefPtr<T_CppObject> temp (src);
+ this->swap(temp);
+ return *this;
+}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(T_CppObject* pCppObject)
+{
+ RefPtr<T_CppObject> temp (pCppObject);
+
+ // This extra reference is necessary because operator=(T_CppObject*) used
+ // to behave differently than the ctor RefPtr(T_CppObject*), i.e. it takes
+ // a reference. Unfortunately we can't fix it at this point.
+ //
+ // TODO: This assignment operator should be removed entirely at the next API break.
+
+ if(pCppObject)
+ pCppObject->reference();
+
+ this->swap(temp);
+ return *this;
+}
+
+template <class T_CppObject>
+ template <class T_CastFrom>
+inline
+RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
+{
+ RefPtr<T_CppObject> temp (src);
+ this->swap(temp);
+ return *this;
+}
+
+template <class T_CppObject> inline
+bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
+{
+ return (pCppObject_ == src.pCppObject_);
+}
+
+template <class T_CppObject> inline
+bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
+{
+ return (pCppObject_ != src.pCppObject_);
+}
+
+template <class T_CppObject> inline
+RefPtr<T_CppObject>::operator bool() const
+{
+ return (pCppObject_ != 0);
+}
+
+template <class T_CppObject> inline
+bool RefPtr<T_CppObject>::is_null() const
+{
+ return (pCppObject_ == 0);
+}
+
+template <class T_CppObject> inline
+void RefPtr<T_CppObject>::clear()
+{
+ RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
+ this->swap(temp);
+}
+
+template <class T_CppObject>
+ template <class T_CastFrom>
+inline
+RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
+{
+ T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
+
+ if(pCppObject)
+ pCppObject->reference();
+
+ return RefPtr<T_CppObject>(pCppObject);
+}
+
+template <class T_CppObject>
+ template <class T_CastFrom>
+inline
+RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
+{
+ T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
+
+ if(pCppObject)
+ pCppObject->reference();
+
+ return RefPtr<T_CppObject>(pCppObject);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/** @relates Glib::RefPtr */
+template <class T_CppObject> inline
+void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
+{
+ lhs.swap(rhs);
+}
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_REFPTR_H */
+
diff --git a/glib/glibmm/sarray.cc b/glib/glibmm/sarray.cc
new file mode 100644
index 00000000..55e1d0dc
--- /dev/null
+++ b/glib/glibmm/sarray.cc
@@ -0,0 +1,85 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* sarray.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/sarray.h>
+/*
+namespace Glib
+{
+
+SArray::SArray(const SArray& src)
+: type_base(src)
+{
+}
+
+SArray::SArray(const T_c* pValues, size_type size)
+: type_base(pValues, size)
+{
+}
+
+SArray::operator std::vector<nstring>() const
+{
+ return std::vector<nstring>(begin(), end());
+}
+
+SArray::operator std::vector<ustring>() const
+{
+ return std::vector<ustring>(begin(), end());
+}
+
+SArray::operator std::vector<std::string>() const
+{
+ return std::vector<std::string>(begin(), end());
+}
+
+
+SArray::operator std::deque<nstring>() const
+{
+ return std::deque<nstring>(begin(), end());
+}
+
+SArray::operator std::deque<ustring>() const
+{
+ return std::deque<ustring>(begin(), end());
+}
+
+SArray::operator std::deque<std::string>() const
+{
+ return std::deque<std::string>(begin(), end());
+}
+
+SArray::operator std::list<nstring>() const
+{
+ return std::list<nstring>(begin(), end());
+}
+
+SArray::operator std::list<ustring>() const
+{
+ return std::list<ustring>(begin(), end());
+}
+
+SArray::operator std::list<std::string>() const
+{
+ return std::list<std::string>(begin(), end());
+}
+
+}; // namespace Glib
+*/
diff --git a/glib/glibmm/sarray.h b/glib/glibmm/sarray.h
new file mode 100644
index 00000000..01d7ee20
--- /dev/null
+++ b/glib/glibmm/sarray.h
@@ -0,0 +1,108 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_SARRAY_H
+#define _GLIBMM_SARRAY_H
+
+/* $Id$ */
+
+/* array.h
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <glibmm/arrayhandle.h>
+#include <glibmm/ustring.h>
+
+namespace Glib { typedef Glib::ArrayHandle<Glib::ustring> SArray; }
+
+#if 0
+
+namespace Glib
+{
+
+template <>
+inline void cpp_type_to_c_type(const ustring& cpp_value, type_constpch& ref_c_value)
+{
+ ref_c_value = cpp_value.c_str();
+}
+
+template <>
+inline void cpp_type_to_c_type(const std::string& cpp_value, type_constpch& ref_c_value)
+{
+ ref_c_value = cpp_value.c_str();
+}
+
+typedef Array<Glib::ustring, const char*> SArray;
+
+/*
+class SArray: public Array<nstring, const char*>
+{
+public:
+ typedef const char* T_c;
+ typedef Array<nstring, const char*> type_base;
+
+ SArray(const SArray& src);
+
+ // copy other containers
+ template <typename T_container>
+ SArray(const T_container& t)
+ {
+ owned_ = Array_Helpers::Traits<T_container, pointer>::get_owned();
+ size_ = Array_Helpers::Traits<T_container, pointer>::get_size(t);
+ pData_ = Array_Helpers::Traits<T_container, pointer>::get_data(t);
+ }
+
+ SArray(const T_c* pValues, size_type size);
+
+ // copy a sequence
+ template <typename Iterator>
+ SArray(Iterator b, Iterator e);
+
+ operator std::vector<nstring>() const;
+ operator std::vector<ustring>() const;
+ operator std::vector<std::string>() const;
+
+ operator std::deque<nstring>() const;
+ operator std::deque<ustring>() const;
+ operator std::deque<std::string>() const;
+
+ operator std::list<nstring>() const;
+ operator std::list<ustring>() const;
+ operator std::list<std::string>() const;
+};
+
+
+//template <typename T_container>
+//SArray::SArray(const T_container& t)
+//: type_base(t)
+//{
+//}
+
+
+template <typename Iterator>
+SArray::SArray(Iterator b, Iterator e)
+: type_base(b, e)
+{
+}
+*/
+
+} // namespace Glib
+
+#endif /* #if 0 */
+
+#endif // _GLIBMM_SARRAY_H
+
diff --git a/glib/glibmm/signalproxy.cc b/glib/glibmm/signalproxy.cc
new file mode 100644
index 00000000..f95450b4
--- /dev/null
+++ b/glib/glibmm/signalproxy.cc
@@ -0,0 +1,111 @@
+// -*- c++ -*-
+
+/* $Id$ */
+
+/* signalproxy.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib-object.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/object.h>
+#include <glibmm/signalproxy.h>
+#include <glibmm/signalproxy_connectionnode.h>
+
+
+namespace Glib
+{
+
+// SignalProxyBase implementation:
+
+SignalProxyBase::SignalProxyBase(Glib::ObjectBase* obj)
+:
+ obj_ (obj)
+{}
+
+
+// SignalProxyNormal implementation:
+
+SignalProxyNormal::SignalProxyNormal(Glib::ObjectBase* obj, const SignalProxyInfo* info)
+:
+ SignalProxyBase (obj),
+ info_ (info)
+{}
+
+SignalProxyNormal::~SignalProxyNormal()
+{}
+
+SigC::ConnectionNode*
+SignalProxyNormal::connect_(const SigC::SlotBase& slot_base, bool after)
+{
+ return connect_impl_(info_->callback, slot_base, after);
+}
+
+SigC::ConnectionNode*
+SignalProxyNormal::connect_notify_(const SigC::SlotBase& slot_base, bool after)
+{
+ return connect_impl_(info_->notify_callback, slot_base, after);
+}
+
+SigC::ConnectionNode*
+SignalProxyNormal::connect_impl_(GCallback callback, const SigC::SlotBase& slot_base, bool after)
+{
+ // create a proxy to hold our connection info
+ SignalProxyConnectionNode *const pConnectionNode =
+ new SignalProxyConnectionNode(static_cast<SigC::SlotNode*>(slot_base.impl()), obj_->gobj());
+
+ // glib will hold a reference to this object
+ pConnectionNode->reference();
+
+ // connect it to glib
+ // pConnectionNode will be passed in the data argument to the callback.
+ pConnectionNode->connection_id_ = g_signal_connect_data(
+ obj_->gobj(), info_->signal_name, callback, pConnectionNode,
+ &SignalProxyConnectionNode::destroy_notify_handler,
+ static_cast<GConnectFlags>((after) ? G_CONNECT_AFTER : 0));
+
+ return pConnectionNode;
+}
+
+void SignalProxyNormal::emission_stop()
+{
+ g_signal_stop_emission_by_name(obj_->gobj(), info_->signal_name);
+}
+
+// static
+void SignalProxyNormal::slot0_void_callback(GObject* self, void* data)
+{
+ typedef SigC::Slot0<void> SlotType;
+
+ // Do not try to call a signal on a disassociated wrapper.
+ if(Glib::ObjectBase::_get_current_wrapper(self))
+ {
+ try
+ {
+ if(SigC::SlotNode *const slot = data_to_slot(data))
+ (*(SlotType::Proxy)(slot->proxy_))(slot);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ }
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/signalproxy_connectionnode.cc b/glib/glibmm/signalproxy_connectionnode.cc
new file mode 100644
index 00000000..b9d5bbbc
--- /dev/null
+++ b/glib/glibmm/signalproxy_connectionnode.cc
@@ -0,0 +1,84 @@
+// -*- c++ -*-
+
+/* $Id$ */
+
+/* signalproxy_connectionnode.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/signalproxy_connectionnode.h>
+#include <glibmm/object.h>
+
+
+namespace Glib
+{
+
+SignalProxyConnectionNode::SignalProxyConnectionNode(SigC::SlotNode* slot_data, GObject* gobject)
+:
+ SigC::ConnectionNode(slot_data),
+ connection_id_ (0),
+ gsignal_disconnection_in_process_ (false),
+ object_ (gobject)
+{}
+
+SignalProxyConnectionNode::~SignalProxyConnectionNode()
+{
+ object_ = 0;
+}
+
+// notify is a message coming up from the slot to be passed back to Gtk+
+// disconnect is a message coming up from the Gtk+ to be passed down to SigC++
+void SignalProxyConnectionNode::notify(bool from_child)
+{
+ if (object_)
+ {
+ GObject* o = object_;
+ object_ = 0;
+
+ gsignal_disconnection_in_process_ = true; //Prevent destroy_notify_handler() from calling notify() too.
+ if(g_signal_handler_is_connected(o, connection_id_)) //During destruction, GTK+ sometimes seems to disconnect them for us, before we expect it to. See bug #87912
+ g_signal_handler_disconnect(o, connection_id_);
+ }
+
+ connection_id_ = 0;
+ SigC::ConnectionNode::notify(from_child);
+}
+
+void SignalProxyConnectionNode::destroy_notify_handler(gpointer data, GClosure*)
+{
+ // notification from gtk+.
+ SignalProxyConnectionNode* conn = static_cast<SignalProxyConnectionNode*>(data);
+
+ // if there is no object, this call was reduntant.
+ // (except for unreferencing the connection node. daniel.)
+ if (conn->object_)
+ {
+ // the object has already lost track of this object.
+ conn->object_ = 0;
+
+ // inform sigc++ that the slot is of no further use.
+ if(!conn->gsignal_disconnection_in_process_) //Prevent us from calling notify() twice. If it's in process then SignalProxyConnectionNode::notify() will do this.
+ conn->notify(false); //TODO: What does false mean here?
+ }
+
+ if(!conn->gsignal_disconnection_in_process_)
+ conn->unreference(); // remove the notice
+}
+
+} /* namespace Glib */
+
diff --git a/glib/glibmm/signalproxy_connectionnode.h b/glib/glibmm/signalproxy_connectionnode.h
new file mode 100644
index 00000000..deccd35e
--- /dev/null
+++ b/glib/glibmm/signalproxy_connectionnode.h
@@ -0,0 +1,60 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_SIGNALPROXY_CONNECTIONNODE_H
+#define _GLIBMM_SIGNALPROXY_CONNECTIONNODE_H
+
+/* $Id$ */
+
+/* signalproxy_connectionnode.h
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sigc++/sigc++.h>
+#include <glibmm/wrap.h>
+
+typedef struct _GObject GObject;
+
+namespace Glib
+{
+
+/** SignalProxyConnectionNode is a SigC::ConnectionNode for use with SignalProxy.
+ * It lives between the layer of Gtk+ and SigC++.
+ * It is very much an internal class.
+ */
+class SignalProxyConnectionNode : public SigC::ConnectionNode
+{
+public:
+ SignalProxyConnectionNode(SigC::SlotNode* slot_data, GObject* gobject);
+ virtual ~SignalProxyConnectionNode();
+
+ virtual void notify(bool from_child); //overridden.
+
+ static void destroy_notify_handler(gpointer data, GClosure *closure);
+
+ gulong connection_id_;
+ bool gsignal_disconnection_in_process_;
+
+protected:
+ GObject* object_;
+
+};
+
+} /* namespace Glib */
+
+
+#endif /* _GLIBMM_SIGNALPROXY_CONNECTIONNODE_H */
+
diff --git a/glib/glibmm/slisthandle.h b/glib/glibmm/slisthandle.h
new file mode 100644
index 00000000..a8b35ea4
--- /dev/null
+++ b/glib/glibmm/slisthandle.h
@@ -0,0 +1,403 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_SLISTHANDLE_H
+#define _GLIBMM_SLISTHANDLE_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gslist.h>
+#include <glibmm/containerhandle_shared.h>
+
+
+namespace Glib
+{
+
+namespace Container_Helpers
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* Create and fill a GSList as efficient as possible.
+ * This requires bidirectional iterators.
+ */
+template <class Bi, class Tr>
+GSList* create_slist(Bi pbegin, Bi pend, Tr)
+{
+ GSList* head = 0;
+
+ while(pend != pbegin)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ const void *const item = Tr::to_c_type(*&*--pend);
+ head = g_slist_prepend(head, const_cast<void*>(item));
+ }
+
+ return head;
+}
+
+/* Create a GSList from a 0-terminated input sequence.
+ * Build it in reverse order and reverse the whole list afterwards,
+ * because appending to the list would be horribly inefficient.
+ */
+template <class For, class Tr>
+GSList* create_slist(For pbegin, Tr)
+{
+ GSList* head = 0;
+
+ while(*pbegin)
+ {
+ // Use & to force a warning if the iterator returns a temporary object.
+ const void *const item = Tr::to_c_type(*&*pbegin);
+ head = g_slist_prepend(head, const_cast<void*>(item));
+ ++pbegin;
+ }
+
+ return g_slist_reverse(head);
+}
+
+
+/* Convert from any container that supports bidirectional iterators.
+ */
+template <class Tr, class Cont>
+struct SListSourceTraits
+{
+ static GSList* get_data(const Cont& cont)
+ { return Glib::Container_Helpers::create_slist(cont.begin(), cont.end(), Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+/* Convert from a 0-terminated array. The Cont
+ * argument must be a pointer to the first element.
+ */
+template <class Tr, class Cont>
+struct SListSourceTraits<Tr,Cont*>
+{
+ static GSList* get_data(const Cont* array)
+ { return (array) ? Glib::Container_Helpers::create_slist(array, Tr()) : 0; }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+template <class Tr, class Cont>
+struct SListSourceTraits<Tr,const Cont*> : SListSourceTraits<Tr,Cont*>
+{};
+
+/* Convert from a 0-terminated array. The Cont argument must be a pointer
+ * to the first element. For consistency, the array must be 0-terminated,
+ * even though the array size is known at compile time.
+ */
+template <class Tr, class Cont, size_t N>
+struct SListSourceTraits<Tr,Cont[N]>
+{
+ static GSList* get_data(const Cont* array)
+ { return Glib::Container_Helpers::create_slist(array, array + (N - 1), Tr()); }
+
+ static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
+};
+
+template <class Tr, class Cont, size_t N>
+struct SListSourceTraits<Tr,const Cont[N]> : SListSourceTraits<Tr,Cont[N]>
+{};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/**
+ * @ingroup ContHelpers
+ */
+template <class Tr>
+class SListHandleIterator
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef std::forward_iterator_tag iterator_category;
+ typedef CppType value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type reference;
+ typedef void pointer;
+
+ explicit inline SListHandleIterator(const GSList* node);
+
+ inline value_type operator*() const;
+ inline SListHandleIterator<Tr> & operator++();
+ inline const SListHandleIterator<Tr> operator++(int);
+
+ inline bool operator==(const SListHandleIterator<Tr>& rhs) const;
+ inline bool operator!=(const SListHandleIterator<Tr>& rhs) const;
+
+private:
+ const GSList* node_;
+};
+
+} // namespace Container_Helpers
+
+
+/**
+ * @ingroup ContHandles
+ */
+template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
+class SListHandle
+{
+public:
+ typedef typename Tr::CppType CppType;
+ typedef typename Tr::CType CType;
+
+ typedef CppType value_type;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ typedef Glib::Container_Helpers::SListHandleIterator<Tr> const_iterator;
+ typedef Glib::Container_Helpers::SListHandleIterator<Tr> iterator;
+
+ template <class Cont> inline
+ SListHandle(const Cont& container);
+
+ // Take over ownership of a GSList created by GTK+ functions.
+ inline SListHandle(GSList* glist, Glib::OwnershipType ownership);
+
+ // Copying clears the ownership flag of the source handle.
+ inline SListHandle(const SListHandle<T,Tr>& other);
+
+ ~SListHandle();
+
+ inline const_iterator begin() const;
+ inline const_iterator end() const;
+
+ template <class U> inline operator std::vector<U>() const;
+ template <class U> inline operator std::deque<U>() const;
+ template <class U> inline operator std::list<U>() const;
+
+ template <class Cont> inline
+ void assign_to(Cont& container) const;
+ template <class Out> inline
+ void copy(Out pdest) const;
+
+ inline GSList* data() const;
+ inline size_t size() const;
+ inline bool empty() const;
+
+private:
+ GSList * pslist_;
+ mutable Glib::OwnershipType ownership_;
+
+ // No copy assignment.
+ SListHandle<T,Tr>& operator=(const SListHandle<T,Tr>&);
+};
+
+
+/***************************************************************************/
+/* Inline implementation */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+namespace Container_Helpers
+{
+
+/**** Glib::Container_Helpers::SListHandleIterator<> ***********************/
+
+template <class Tr> inline
+SListHandleIterator<Tr>::SListHandleIterator(const GSList* node)
+:
+ node_ (node)
+{}
+
+template <class Tr> inline
+typename SListHandleIterator<Tr>::value_type SListHandleIterator<Tr>::operator*() const
+{
+ return Tr::to_cpp_type(static_cast<typename Tr::CTypeNonConst>(node_->data));
+}
+
+template <class Tr> inline
+SListHandleIterator<Tr>& SListHandleIterator<Tr>::operator++()
+{
+ node_ = node_->next;
+ return *this;
+}
+
+template <class Tr> inline
+const SListHandleIterator<Tr> SListHandleIterator<Tr>::operator++(int)
+{
+ const SListHandleIterator<Tr> tmp (*this);
+ node_ = node_->next;
+ return tmp;
+}
+
+template <class Tr> inline
+bool SListHandleIterator<Tr>::operator==(const SListHandleIterator<Tr>& rhs) const
+{
+ return (node_ == rhs.node_);
+}
+
+template <class Tr> inline
+bool SListHandleIterator<Tr>::operator!=(const SListHandleIterator<Tr>& rhs) const
+{
+ return (node_ != rhs.node_);
+}
+
+} // namespace Container_Helpers
+
+
+/**** Glib::SListHandle<> **************************************************/
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+SListHandle<T,Tr>::SListHandle(const Cont& container)
+:
+ pslist_ (Glib::Container_Helpers::SListSourceTraits<Tr,Cont>::get_data(container)),
+ ownership_ (Glib::Container_Helpers::SListSourceTraits<Tr,Cont>::initial_ownership)
+{}
+
+template <class T, class Tr> inline
+SListHandle<T,Tr>::SListHandle(GSList* gslist, Glib::OwnershipType ownership)
+:
+ pslist_ (gslist),
+ ownership_ (ownership)
+{}
+
+template <class T, class Tr> inline
+SListHandle<T,Tr>::SListHandle(const SListHandle<T,Tr>& other)
+:
+ pslist_ (other.pslist_),
+ ownership_ (other.ownership_)
+{
+ other.ownership_ = Glib::OWNERSHIP_NONE;
+}
+
+template <class T, class Tr>
+SListHandle<T,Tr>::~SListHandle()
+{
+ if(ownership_ != Glib::OWNERSHIP_NONE)
+ {
+ if(ownership_ != Glib::OWNERSHIP_SHALLOW)
+ {
+ // Deep ownership: release each container element.
+ for(GSList* node = pslist_; node != 0; node = node->next)
+ Tr::release_c_type(static_cast<typename Tr::CTypeNonConst>(node->data));
+ }
+ g_slist_free(pslist_);
+ }
+}
+
+template <class T, class Tr> inline
+typename SListHandle<T,Tr>::const_iterator SListHandle<T,Tr>::begin() const
+{
+ return Glib::Container_Helpers::SListHandleIterator<Tr>(pslist_);
+}
+
+template <class T, class Tr> inline
+typename SListHandle<T,Tr>::const_iterator SListHandle<T,Tr>::end() const
+{
+ return Glib::Container_Helpers::SListHandleIterator<Tr>(0);
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+SListHandle<T,Tr>::operator std::vector<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::vector<U>(this->begin(), this->end());
+#else
+ std::vector<U> temp;
+ temp.reserve(this->size());
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+SListHandle<T,Tr>::operator std::deque<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::deque<U>(this->begin(), this->end());
+#else
+ std::deque<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class U>
+inline
+SListHandle<T,Tr>::operator std::list<U>() const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ return std::list<U>(this->begin(), this->end());
+#else
+ std::list<U> temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ return temp;
+#endif
+}
+
+template <class T, class Tr>
+ template <class Cont>
+inline
+void SListHandle<T,Tr>::assign_to(Cont& container) const
+{
+#ifdef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+ container.assign(this->begin(), this->end());
+#else
+ Cont temp;
+ Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
+ container.swap(temp);
+#endif
+}
+
+template <class T, class Tr>
+ template <class Out>
+inline
+void SListHandle<T,Tr>::copy(Out pdest) const
+{
+ std::copy(this->begin(), this->end(), pdest);
+}
+
+template <class T, class Tr> inline
+GSList* SListHandle<T,Tr>::data() const
+{
+ return pslist_;
+}
+
+template <class T, class Tr> inline
+size_t SListHandle<T,Tr>::size() const
+{
+ return g_slist_length(pslist_);
+}
+
+template <class T, class Tr> inline
+bool SListHandle<T,Tr>::empty() const
+{
+ return (pslist_ == 0);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_SLISTHANDLE_H */
+
diff --git a/glib/glibmm/streamiochannel.cc b/glib/glibmm/streamiochannel.cc
new file mode 100644
index 00000000..b25a7cec
--- /dev/null
+++ b/glib/glibmm/streamiochannel.cc
@@ -0,0 +1,188 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/streamiochannel.h>
+#include <glib.h>
+#include <fstream>
+#include <iostream>
+
+GTKMM_USING_STD(ios)
+
+
+namespace Glib
+{
+
+// static
+Glib::RefPtr<StreamIOChannel> StreamIOChannel::create(std::istream& stream)
+{
+ return Glib::RefPtr<StreamIOChannel>(new StreamIOChannel(&stream, 0));
+}
+
+// static
+Glib::RefPtr<StreamIOChannel> StreamIOChannel::create(std::ostream& stream)
+{
+ return Glib::RefPtr<StreamIOChannel>(new StreamIOChannel(0, &stream));
+}
+
+// static
+Glib::RefPtr<StreamIOChannel> StreamIOChannel::create(std::iostream& stream)
+{
+ return Glib::RefPtr<StreamIOChannel>(new StreamIOChannel(&stream, &stream));
+}
+
+StreamIOChannel::StreamIOChannel(std::istream* stream_in, std::ostream* stream_out)
+:
+ stream_in_ (stream_in),
+ stream_out_ (stream_out)
+{
+ get_flags_vfunc(); // initialize GIOChannel flag bits
+}
+
+StreamIOChannel::~StreamIOChannel()
+{}
+
+IOStatus StreamIOChannel::read_vfunc(char* buf, gsize count, gsize& bytes_read)
+{
+ g_return_val_if_fail(stream_in_ != 0, IO_STATUS_ERROR);
+
+ stream_in_->clear();
+ stream_in_->read(buf, count);
+ bytes_read = stream_in_->gcount();
+
+ if(stream_in_->eof())
+ return IO_STATUS_EOF;
+
+ if(stream_in_->fail())
+ throw Glib::Error(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, "Reading from stream failed");
+
+ return IO_STATUS_NORMAL;
+}
+
+IOStatus StreamIOChannel::write_vfunc(const char* buf, gsize count, gsize& bytes_written)
+{
+ g_return_val_if_fail(stream_out_ != 0, IO_STATUS_ERROR);
+
+ bytes_written = 0;
+
+ stream_out_->clear();
+ stream_out_->write(buf, count);
+
+ if(stream_out_->fail())
+ throw Glib::Error(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, "Writing to stream failed");
+
+ bytes_written = count; // all or nothing ;)
+
+ return IO_STATUS_NORMAL;
+}
+
+IOStatus StreamIOChannel::seek_vfunc(gint64 offset, SeekType type)
+{
+ std::ios::seekdir direction = std::ios::beg;
+
+ switch(type)
+ {
+ case SEEK_TYPE_SET: direction = std::ios::beg; break;
+ case SEEK_TYPE_CUR: direction = std::ios::cur; break;
+ case SEEK_TYPE_END: direction = std::ios::end; break;
+ }
+
+ bool failed = false;
+
+ if(stream_in_)
+ {
+ stream_in_->clear();
+ stream_in_->seekg(offset, direction);
+ failed = stream_in_->fail();
+ }
+ if(stream_out_)
+ {
+ stream_out_->clear();
+ stream_out_->seekp(offset, direction);
+ failed = (failed || stream_out_->fail());
+ }
+
+ if(failed)
+ throw Glib::Error(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, "Seeking into stream failed");
+
+ return Glib::IO_STATUS_NORMAL;
+}
+
+IOStatus StreamIOChannel::close_vfunc()
+{
+ bool failed = false;
+
+ if(std::fstream *const stream = dynamic_cast<std::fstream*>(stream_in_))
+ {
+ stream->clear();
+ stream->close();
+ failed = stream->fail();
+ }
+ else if(std::ifstream *const stream = dynamic_cast<std::ifstream*>(stream_in_))
+ {
+ stream->clear();
+ stream->close();
+ failed = stream->fail();
+ }
+ else if(std::ofstream *const stream = dynamic_cast<std::ofstream*>(stream_out_))
+ {
+ stream->clear();
+ stream->close();
+ failed = stream->fail();
+ }
+ else
+ {
+ throw Glib::Error(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED,
+ "Attempt to close non-file stream");
+ }
+
+ if(failed)
+ throw Glib::Error(G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, "Failed to close stream");
+
+ return IO_STATUS_NORMAL;
+}
+
+IOStatus StreamIOChannel::set_flags_vfunc(IOFlags)
+{
+ return IO_STATUS_NORMAL;
+}
+
+IOFlags StreamIOChannel::get_flags_vfunc()
+{
+ gobj()->is_seekable = 1;
+ gobj()->is_readable = (stream_in_ != 0);
+ gobj()->is_writeable = (stream_out_ != 0);
+
+ IOFlags flags = IO_FLAG_IS_SEEKABLE;
+
+ if(stream_in_)
+ flags |= IO_FLAG_IS_READABLE;
+ if(stream_out_)
+ flags |= IO_FLAG_IS_WRITEABLE;
+
+ return flags;
+}
+
+Glib::RefPtr<Glib::Source> StreamIOChannel::create_watch_vfunc(IOCondition)
+{
+ g_warning("Glib::StreamIOChannel::create_watch_vfunc() not implemented");
+ return Glib::RefPtr<Glib::Source>();
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/streamiochannel.h b/glib/glibmm/streamiochannel.h
new file mode 100644
index 00000000..35edb7db
--- /dev/null
+++ b/glib/glibmm/streamiochannel.h
@@ -0,0 +1,67 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GLIBMM_STREAMIOCHANNEL_H
+#define _GLIBMM_STREAMIOCHANNEL_H
+
+#include <glibmm/iochannel.h>
+#include <glibmmconfig.h>
+#include <iosfwd>
+
+GTKMM_USING_STD(istream)
+GTKMM_USING_STD(ostream)
+GTKMM_USING_STD(iostream)
+
+
+namespace Glib
+{
+
+/** This whole class is deprecated in glibmm&nbsp;2.2.
+ * See the Glib::IOChannel documentation for an explanation.
+ */
+class StreamIOChannel : public Glib::IOChannel
+{
+public:
+ virtual ~StreamIOChannel();
+
+ static Glib::RefPtr<StreamIOChannel> create(std::istream& stream);
+ static Glib::RefPtr<StreamIOChannel> create(std::ostream& stream);
+ static Glib::RefPtr<StreamIOChannel> create(std::iostream& stream);
+
+protected:
+ std::istream* stream_in_;
+ std::ostream* stream_out_;
+
+ StreamIOChannel(std::istream* stream_in, std::ostream* stream_out);
+
+ virtual IOStatus read_vfunc(char* buf, gsize count, gsize& bytes_read);
+ virtual IOStatus write_vfunc(const char* buf, gsize count, gsize& bytes_written);
+ virtual IOStatus seek_vfunc(gint64 offset, SeekType type);
+ virtual IOStatus close_vfunc();
+ virtual IOStatus set_flags_vfunc(IOFlags flags);
+ virtual IOFlags get_flags_vfunc();
+ virtual Glib::RefPtr<Glib::Source> create_watch_vfunc(IOCondition cond);
+};
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_STREAMIOCHANNEL_H */
+
diff --git a/glib/glibmm/stringutils.cc b/glib/glibmm/stringutils.cc
new file mode 100644
index 00000000..1f3a3411
--- /dev/null
+++ b/glib/glibmm/stringutils.cc
@@ -0,0 +1,117 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/stringutils.h>
+#include <glibmm/utility.h>
+#include <glib.h>
+#include <cerrno>
+#include <stdexcept>
+#include <glibmmconfig.h>
+
+GTKMM_USING_STD(out_of_range)
+GTKMM_USING_STD(overflow_error)
+GTKMM_USING_STD(underflow_error)
+
+
+bool Glib::str_has_prefix(const std::string& str, const std::string& prefix)
+{
+ return g_str_has_prefix(str.c_str(), prefix.c_str());
+}
+
+bool Glib::str_has_suffix(const std::string& str, const std::string& suffix)
+{
+ return g_str_has_suffix(str.c_str(), suffix.c_str());
+}
+
+double Glib::Ascii::strtod(const std::string& str)
+{
+ std::string::size_type dummy;
+ return Glib::Ascii::strtod(str, dummy, 0);
+}
+
+double Glib::Ascii::strtod(const std::string& str,
+ std::string::size_type& end_index,
+ std::string::size_type start_index)
+{
+ if(start_index > str.size())
+ throw std::out_of_range("out of range (strtod): start_index > str.size()");
+
+ const char *const bufptr = str.c_str();
+ char* endptr = 0;
+
+ const double result = g_ascii_strtod(bufptr + start_index, &endptr);
+ const int err_no = errno;
+
+ if(err_no != 0)
+ {
+ g_return_val_if_fail(err_no == ERANGE, result);
+
+ if(result > 0.0)
+ throw std::overflow_error("overflow (strtod): positive number too large");
+
+ if(result < 0.0)
+ throw std::overflow_error("overflow (strtod): negative number too large");
+
+ throw std::underflow_error("underflow (strtod): number too small");
+ }
+
+ if(endptr)
+ end_index = endptr - bufptr;
+ else
+ end_index = str.size();
+
+ return result;
+}
+
+std::string Glib::Ascii::dtostr(double d)
+{
+ char buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+ return g_ascii_dtostr(buf, sizeof(buf), d);
+}
+
+std::string Glib::strescape(const std::string& source)
+{
+ const Glib::ScopedPtr<char> buf (g_strescape(source.c_str(), 0));
+ return buf.get();
+}
+
+std::string Glib::strescape(const std::string& source, const std::string& exceptions)
+{
+ const Glib::ScopedPtr<char> buf (g_strescape(source.c_str(), exceptions.c_str()));
+ return buf.get();
+}
+
+std::string Glib::strcompress(const std::string& source)
+{
+ const Glib::ScopedPtr<char> buf (g_strcompress(source.c_str()));
+ return buf.get();
+}
+
+Glib::ustring Glib::strerror(int errnum)
+{
+ return g_strerror(errnum);
+}
+
+Glib::ustring Glib::strsignal(int signum)
+{
+ return g_strsignal(signum);
+}
+
diff --git a/glib/glibmm/stringutils.h b/glib/glibmm/stringutils.h
new file mode 100644
index 00000000..564a1f72
--- /dev/null
+++ b/glib/glibmm/stringutils.h
@@ -0,0 +1,184 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_STRINGUTILS_H
+#define _GLIBMM_STRINGUTILS_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/ustring.h>
+
+
+namespace Glib
+{
+
+/** @defgroup StringUtils String Utility Functions
+ *
+ * This section describes a number of utility functions for creating
+ * and manipulating strings, as well as other string-related stuff.
+ */
+
+/** Looks whether the string @a str begins with @a prefix.
+ * @ingroup StringUtils
+ * @param str A string.
+ * @param prefix The prefix to look for.
+ * @return <tt>true</tt> if @a str begins with @a prefix, <tt>false</tt> otherwise.
+ */
+bool str_has_prefix(const std::string& str, const std::string& prefix);
+
+/** Looks whether the string @a str ends with @a suffix.
+ * @ingroup StringUtils
+ * @param str A string.
+ * @param suffix The suffix to look for.
+ * @return <tt>true</tt> if @a str ends with @a suffix, <tt>false</tt> otherwise.
+ */
+bool str_has_suffix(const std::string& str, const std::string& suffix);
+
+
+namespace Ascii
+{
+
+/** Converts a string to a <tt>double</tt> value.
+ * @ingroup StringUtils
+ * This function behaves like the standard <tt>%strtod()</tt> function does in
+ * the C&nbsp;locale. It does this without actually changing the current
+ * locale, since that would not be thread-safe.
+ *
+ * This function is typically used when reading configuration files or other
+ * non-user input that should be locale independent. To handle input from the
+ * user you should normally use locale-sensitive C++ streams.
+ *
+ * To convert from a string to <tt>double</tt> in a locale-insensitive way, use
+ * Glib::Ascii::dtostr().
+ *
+ * @param str The string to convert to a numeric value.
+ * @return The <tt>double</tt> value.
+ * @throw std::overflow_error Thrown if the correct value would cause overflow.
+ * @throw std::underflow_error Thrown if the correct value would cause underflow.
+ */
+double strtod(const std::string& str);
+
+/** Converts a string to a <tt>double</tt> value.
+ * @ingroup StringUtils
+ * This function behaves like the standard <tt>%strtod()</tt> function does in
+ * the C&nbsp;locale. It does this without actually changing the current
+ * locale, since that would not be thread-safe.
+ *
+ * This function is typically used when reading configuration files or other
+ * non-user input that should be locale independent. To handle input from the
+ * user you should normally use locale-sensitive C++ streams.
+ *
+ * To convert from a string to <tt>double</tt> in a locale-insensitive way, use
+ * Glib::Ascii::dtostr().
+ *
+ * @param str The string to convert to a numeric value.
+ * @param start_index The index of the first character that should be used in the conversion.
+ * @retval end_index The index of the character after the last character used in the conversion.
+ * @return The <tt>double</tt> value.
+ * @throw std::out_of_range Thrown if @a start_index is out of range.
+ * @throw std::overflow_error Thrown if the correct value would cause overflow.
+ * @throw std::underflow_error Thrown if the correct value would cause underflow.
+ */
+double strtod(const std::string& str,
+ std::string::size_type& end_index,
+ std::string::size_type start_index = 0);
+
+/** Converts a <tt>double</tt> to a string, using the <tt>'.'</tt> as decimal point.
+ * @ingroup StringUtils
+ * This functions generates enough precision that converting the string back
+ * using Glib::Ascii::strtod() gives the same machine-number (on machines with
+ * IEEE compatible 64bit doubles).
+ *
+ * @param d The <tt>double</tt> value to convert.
+ * @return The converted string.
+ */
+std::string dtostr(double d);
+
+} // namespace Ascii
+
+
+/** Escapes all special characters in the string.
+ * @ingroup StringUtils
+ * Escapes the special characters <tt>'\\b'</tt>, <tt>'\\f'</tt>, <tt>'\\n'</tt>,
+ * <tt>'\\r'</tt>, <tt>'\\t'</tt>, <tt>'\\'</tt> and <tt>'"'</tt> in the string
+ * @a source by inserting a <tt>'\\'</tt> before them. Additionally all characters
+ * in the range <tt>0x01</tt>&nbsp;-&nbsp;<tt>0x1F</tt> (everything below <tt>SPACE</tt>)
+ * and in the range <tt>0x80</tt>&nbsp;-&nbsp;<tt>0xFF</tt> (all non-ASCII chars)
+ * are replaced with a <tt>'\\'</tt> followed by their octal representation.
+ *
+ * Glib::strcompress() does the reverse conversion.
+ *
+ * @param source A string to escape.
+ * @return A copy of @a source with certain characters escaped. See above.
+ */
+std::string strescape(const std::string& source);
+
+/** Escapes all special characters in the string.
+ * @ingroup StringUtils
+ * Escapes the special characters <tt>'\\b'</tt>, <tt>'\\f'</tt>, <tt>'\\n'</tt>,
+ * <tt>'\\r'</tt>, <tt>'\\t'</tt>, <tt>'\\'</tt> and <tt>'"'</tt> in the string
+ * @a source by inserting a <tt>'\\'</tt> before them. Additionally all characters
+ * in the range <tt>0x01</tt>&nbsp;-&nbsp;<tt>0x1F</tt> (everything below <tt>SPACE</tt>)
+ * and in the range <tt>0x80</tt>&nbsp;-&nbsp;<tt>0xFF</tt> (all non-ASCII chars)
+ * are replaced with a <tt>'\\'</tt> followed by their octal representation.
+ * Characters supplied in @a exceptions are not escaped.
+ *
+ * Glib::strcompress() does the reverse conversion.
+ *
+ * @param source A string to escape.
+ * @param exceptions A string of characters not to escape in @a source.
+ * @return A copy of @a source with certain characters escaped. See above.
+ */
+std::string strescape(const std::string& source, const std::string& exceptions);
+
+/** Replaces all escaped characters with their one byte equivalent.
+ * @ingroup StringUtils
+ * This function does the reverse conversion of Glib::strescape().
+ *
+ * @param source A string to compress.
+ * @return A copy of @a source with all escaped characters compressed.
+ */
+std::string strcompress(const std::string& source);
+
+/** Returns a string corresponding to the given error code, e.g.\ <tt>"no such process"</tt>.
+ * @ingroup StringUtils
+ * This function is included since not all platforms support the
+ * <tt>%strerror()</tt> function.
+ *
+ * @param errnum The system error number. See the standard C <tt>errno</tt> documentation.
+ * @return A string describing the error code. If the error code is unknown,
+ * <tt>"unknown error (<em>\<errnum\></em>)"</tt> is returned.
+ */
+Glib::ustring strerror(int errnum);
+
+/** Returns a string describing the given signal, e.g.\ <tt>"Segmentation fault"</tt>.
+ * @ingroup StringUtils
+ * This function is included since not all platforms support the
+ * <tt>%strsignal()</tt> function.
+ *
+ * @param signum The signal number. See the <tt>signal()</tt> documentation.
+ * @return A string describing the signal. If the signal is unknown,
+ * <tt>"unknown signal (<em>\<signum\></em>)"</tt> is returned.
+ */
+Glib::ustring strsignal(int signum);
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_STRINGUTILS_H */
+
diff --git a/glib/glibmm/threadpool.cc b/glib/glibmm/threadpool.cc
new file mode 100644
index 00000000..0699302d
--- /dev/null
+++ b/glib/glibmm/threadpool.cc
@@ -0,0 +1,249 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/threadpool.h>
+#include <glibmm/exceptionhandler.h>
+#include <glib.h>
+#include <list>
+#include <glibmmconfig.h>
+
+GTKMM_USING_STD(list)
+
+
+namespace Glib
+{
+
+// internal
+class ThreadPool::SlotList
+{
+public:
+ SlotList();
+ ~SlotList();
+
+ SigC::Slot0<void>* push(const SigC::Slot0<void>& slot);
+ SigC::Slot0<void> pop(SigC::Slot0<void>* slot_ptr);
+
+ void lock_and_unlock();
+
+private:
+ Glib::Mutex mutex_;
+ std::list< SigC::Slot0<void> > list_;
+
+ // noncopyable
+ SlotList(const ThreadPool::SlotList&);
+ ThreadPool::SlotList& operator=(const ThreadPool::SlotList&);
+};
+
+ThreadPool::SlotList::SlotList()
+{}
+
+ThreadPool::SlotList::~SlotList()
+{}
+
+SigC::Slot0<void>* ThreadPool::SlotList::push(const SigC::Slot0<void>& slot)
+{
+ Mutex::Lock lock (mutex_);
+
+ list_.push_back(slot);
+ return &list_.back();
+}
+
+SigC::Slot0<void> ThreadPool::SlotList::pop(SigC::Slot0<void>* slot_ptr)
+{
+ SigC::Slot0<void> slot;
+
+ {
+ Mutex::Lock lock (mutex_);
+
+ std::list< SigC::Slot0<void> >::iterator pslot = list_.begin();
+ while(pslot != list_.end() && slot_ptr != &*pslot)
+ ++pslot;
+
+ if(pslot != list_.end())
+ {
+ slot = *pslot;
+ list_.erase(pslot);
+ }
+ }
+
+ return slot;
+}
+
+void ThreadPool::SlotList::lock_and_unlock()
+{
+ mutex_.lock();
+ mutex_.unlock();
+}
+
+} // namespace Glib
+
+
+namespace
+{
+
+void call_thread_entry_slot(void* data, void* user_data)
+{
+ try
+ {
+ Glib::ThreadPool::SlotList *const slot_list =
+ static_cast<Glib::ThreadPool::SlotList*>(user_data);
+
+ SigC::Slot0<void> slot (slot_list->pop(static_cast<SigC::Slot0<void>*>(data)));
+
+ slot();
+ }
+ catch(Glib::Thread::Exit&)
+ {
+ // Just exit from the thread. The Thread::Exit exception
+ // is our sane C++ replacement of g_thread_exit().
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+ThreadPool::ThreadPool(int max_threads, bool exclusive)
+:
+ gobject_ (0),
+ slot_list_ (new SlotList())
+{
+ GError* error = 0;
+
+ gobject_ = g_thread_pool_new(
+ &call_thread_entry_slot, slot_list_, max_threads, exclusive, &error);
+
+ if(error)
+ {
+ delete slot_list_;
+ slot_list_ = 0;
+ Glib::Error::throw_exception(error);
+ }
+}
+
+ThreadPool::~ThreadPool()
+{
+ if(gobject_)
+ g_thread_pool_free(gobject_, 1, 1);
+
+ if(slot_list_)
+ {
+ slot_list_->lock_and_unlock();
+ delete slot_list_;
+ }
+}
+
+void ThreadPool::push(const SigC::Slot0<void>& slot)
+{
+ SigC::Slot0<void> *const slot_ptr = slot_list_->push(slot);
+
+ GError* error = 0;
+ g_thread_pool_push(gobject_, slot_ptr, &error);
+
+ if(error)
+ {
+ slot_list_->pop(slot_ptr);
+ Glib::Error::throw_exception(error);
+ }
+}
+
+void ThreadPool::set_max_threads(int max_threads)
+{
+ GError* error = 0;
+ g_thread_pool_set_max_threads(gobject_, max_threads, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+int ThreadPool::get_max_threads() const
+{
+ return g_thread_pool_get_max_threads(gobject_);
+}
+
+unsigned int ThreadPool::get_num_threads() const
+{
+ return g_thread_pool_get_num_threads(gobject_);
+}
+
+unsigned int ThreadPool::unprocessed() const
+{
+ return g_thread_pool_unprocessed(gobject_);
+}
+
+bool ThreadPool::get_exclusive() const
+{
+ g_return_val_if_fail(gobject_ != 0, false);
+
+ return gobject_->exclusive;
+}
+
+void ThreadPool::shutdown(bool immediately)
+{
+ if(gobject_)
+ {
+ g_thread_pool_free(gobject_, immediately, 1);
+ gobject_ = 0;
+ }
+
+ if(slot_list_)
+ {
+ slot_list_->lock_and_unlock();
+ delete slot_list_;
+ slot_list_ = 0;
+ }
+}
+
+// static
+void ThreadPool::set_max_unused_threads(int max_threads)
+{
+ g_thread_pool_set_max_unused_threads(max_threads);
+}
+
+// static
+int ThreadPool::get_max_unused_threads()
+{
+ return g_thread_pool_get_max_unused_threads();
+}
+
+#ifndef GTKMM_WIN32
+
+// static
+unsigned int ThreadPool::get_num_unused_threads()
+{
+ return g_thread_pool_get_num_unused_threads();
+}
+
+// static
+void ThreadPool::stop_unused_threads()
+{
+ g_thread_pool_stop_unused_threads();
+}
+
+#endif /* GTKMM_WIN32 */
+
+} // namespace Glib
+
diff --git a/glib/glibmm/threadpool.h b/glib/glibmm/threadpool.h
new file mode 100644
index 00000000..af999d52
--- /dev/null
+++ b/glib/glibmm/threadpool.h
@@ -0,0 +1,183 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_THREADPOOL_H
+#define _GLIBMM_THREADPOOL_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/thread.h>
+
+extern "C" { typedef struct _GThreadPool GThreadPool; }
+
+
+namespace Glib
+{
+
+/** @defgroup ThreadPools Thread Pools
+ * Pools of threads to execute work concurrently.
+ * @{
+ */
+
+/** A pool of threads to execute work concurrently.
+ */
+class ThreadPool
+{
+public:
+ /** Constructs a new thread pool.
+ * Whenever you call ThreadPool::push(), either a new thread is created or an
+ * unused one is reused. At most @a max_threads threads are running
+ * concurrently for this thread pool. @a max_threads&nbsp;=&nbsp;-1 allows
+ * unlimited threads to be created for this thread pool.
+ *
+ * The parameter @a exclusive determines, whether the thread pool owns all
+ * threads exclusive or whether the threads are shared globally. If @a
+ * exclusive is <tt>true</tt>, @a max_threads threads are started immediately
+ * and they will run exclusively for this thread pool until it is destroyed
+ * by ~ThreadPool(). If @a exclusive is <tt>false</tt>, threads are created
+ * when needed and shared between all non-exclusive thread pools. This
+ * implies that @a max_threads may not be -1 for exclusive thread pools.
+ *
+ * @param max_threads The maximal number of threads to execute concurrently
+ * in the new thread pool, -1 means no limit.
+ * @param exclusive Should this thread pool be exclusive?
+ * @throw Glib::ThreadError An error can only occur when @a exclusive is
+ * set to <tt>true</tt> and not all @a max_threads threads could be created.
+ */
+ explicit ThreadPool(int max_threads = -1, bool exclusive = false);
+ virtual ~ThreadPool();
+
+ /** Inserts @a slot into the list of tasks to be executed by the pool.
+ * When the number of currently running threads is lower than the maximal
+ * allowed number of threads, a new thread is started (or reused). Otherwise
+ * @a slot stays in the queue until a thread in this pool finishes its
+ * previous task and processes @a slot.
+ * @param slot A new task for the thread pool.
+ * @throw Glib::ThreadError An error can only occur when a new thread
+ * couldn't be created. In that case @a slot is simply appended to the
+ * queue of work to do.
+ */
+ void push(const SigC::Slot0<void>& slot);
+
+ /** Sets the maximal allowed number of threads for the pool.
+ * A value of -1 means that the maximal number of threads is unlimited.
+ * Setting @a max_threads to 0 means stopping all work for pool. It is
+ * effectively frozen until @a max_threads is set to a non-zero value again.
+ *
+ * A thread is never terminated while it is still running. Instead the
+ * maximal number of threads only has effect for the allocation of new
+ * threads in ThreadPool::push(). A new thread is allocated whenever the
+ * number of currently running threads in the pool is smaller than the
+ * maximal number.
+ *
+ * @param max_threads A new maximal number of threads for the pool.
+ * @throw Glib::ThreadError An error can only occur when a new thread
+ * couldn't be created.
+ */
+ void set_max_threads(int max_threads);
+
+ /** Returns the maximal number of threads for the pool.
+ * @return The maximal number of threads.
+ */
+ int get_max_threads() const;
+
+ /** Returns the number of threads currently running in the pool.
+ * @return The number of threads currently running.
+ */
+ unsigned int get_num_threads() const;
+
+ /** Returns the number of tasks still unprocessed in the pool.
+ * @return The number of unprocessed tasks.
+ */
+ unsigned int unprocessed() const;
+
+ /** Returns whether all threads are exclusive to this pool.
+ * @return Whether all threads are exclusive to this pool.
+ */
+ bool get_exclusive() const;
+
+ /** Frees all resources allocated for the pool.
+ * If @a immediately is <tt>true</tt>, no new task is processed. Otherwise the
+ * pool is not freed before the last task is processed. Note however, that no
+ * thread of this pool is interrupted while processing a task. Instead at least
+ * all still running threads can finish their tasks before the pool is freed.
+ *
+ * This method does not return before all tasks to be processed (dependent on
+ * @a immediately, whether all or only the currently running) are ready.
+ * After calling shutdown() the pool must not be used anymore.
+ *
+ * @param immediately Should the pool shut down immediately?
+ */
+ void shutdown(bool immediately = false);
+
+ /** Sets the maximal number of unused threads to @a max_threads.
+ * If @a max_threads is -1, no limit is imposed on the number of unused threads.
+ * @param max_threads Maximal number of unused threads.
+ */
+ static void set_max_unused_threads(int max_threads);
+
+ /** Returns the maximal allowed number of unused threads.
+ * @return The maximal number of unused threads.
+ */
+ static int get_max_unused_threads();
+
+ /** Returns the number of currently unused threads.
+ * @return The number of currently unused threads.
+ */
+ static unsigned int get_num_unused_threads();
+
+ /** Stops all currently unused threads.
+ * This does not change the maximal number of unused threads. This function can
+ * be used to regularly stop all unused threads e.g. from Glib::signal_timeout().
+ */
+ static void stop_unused_threads();
+
+ GThreadPool* gobj() { return gobject_; }
+ const GThreadPool* gobj() const { return gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ class SlotList;
+#endif
+
+private:
+ GThreadPool* gobject_;
+ SlotList* slot_list_;
+
+ ThreadPool(const ThreadPool&);
+ ThreadPool& operator=(const ThreadPool&);
+};
+
+/** @} group ThreadPools */
+
+
+/***************************************************************************/
+/* inline implementation */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/**** Glib::Private ********************************************************/
+
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_THREADPOOL_H */
+
diff --git a/glib/glibmm/timer.cc b/glib/glibmm/timer.cc
new file mode 100644
index 00000000..40a7fd35
--- /dev/null
+++ b/glib/glibmm/timer.cc
@@ -0,0 +1,72 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* timer.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gtimer.h>
+#include <glibmm/timer.h>
+
+
+namespace Glib
+{
+
+Timer::Timer()
+:
+ gobject_ (g_timer_new())
+{}
+
+Timer::~Timer()
+{
+ g_timer_destroy(gobject_);
+}
+
+void Timer::start()
+{
+ g_timer_start(gobject_);
+}
+
+void Timer::stop()
+{
+ g_timer_stop(gobject_);
+}
+
+void Timer::reset()
+{
+ g_timer_reset(gobject_);
+}
+
+double Timer::elapsed() const
+{
+ return g_timer_elapsed(gobject_, 0);
+}
+
+double Timer::elapsed(unsigned long& microseconds) const
+{
+ return g_timer_elapsed(gobject_, &microseconds);
+}
+
+
+void usleep(unsigned long microseconds)
+{
+ g_usleep(microseconds);
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/timer.h b/glib/glibmm/timer.h
new file mode 100644
index 00000000..a9ac479f
--- /dev/null
+++ b/glib/glibmm/timer.h
@@ -0,0 +1,79 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_TIMER_H
+#define _GLIBMM_TIMER_H
+
+/* $Id$ */
+
+/* timer.h
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+extern "C" { typedef struct _GTimer GTimer; }
+
+
+namespace Glib
+{
+
+/** Portable stop watch interface.
+ * This resembles a convient and portable timer with microseconds resolution.
+ */
+class Timer
+{
+public:
+ /** Create a new timer.
+ * Also starts timing by calling start() implicitly.
+ */
+ Timer();
+ ~Timer();
+
+ void start();
+ void stop();
+ void reset();
+
+ /** Get the elapsed time.
+ * @return The value in seconds.
+ */
+ double elapsed() const;
+
+ /** Get the elapsed time.
+ * @return The value in seconds. Also fills @p microseconds
+ * with the corresponding @htmlonly&micro;s@endhtmlonly value.
+ */
+ double elapsed(unsigned long& microseconds) const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GTimer* gobj() { return gobject_; }
+ const GTimer* gobj() const { return gobject_; }
+#endif
+
+private:
+ GTimer* gobject_;
+
+ // not copyable
+ Timer(const Timer&);
+ Timer& operator=(const Timer&);
+};
+
+
+void usleep(unsigned long microseconds);
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_TIMER_H */
+
diff --git a/glib/glibmm/timeval.cc b/glib/glibmm/timeval.cc
new file mode 100644
index 00000000..6494d0f4
--- /dev/null
+++ b/glib/glibmm/timeval.cc
@@ -0,0 +1,120 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* timeval.cc
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gmain.h>
+#include <glib/gmessages.h>
+#include <glib/gtimer.h>
+
+#include <glibmm/timeval.h>
+
+
+namespace Glib
+{
+
+void TimeVal::assign_current_time()
+{
+ g_get_current_time(this);
+}
+
+void TimeVal::add(const TimeVal& rhs)
+{
+ g_return_if_fail(tv_usec >= 0 && tv_usec < G_USEC_PER_SEC);
+ g_return_if_fail(rhs.tv_usec >= 0 && rhs.tv_usec < G_USEC_PER_SEC);
+
+ tv_usec += rhs.tv_usec;
+
+ if(tv_usec >= G_USEC_PER_SEC)
+ {
+ tv_usec -= G_USEC_PER_SEC;
+ ++tv_sec;
+ }
+
+ tv_sec += rhs.tv_sec;
+}
+
+void TimeVal::subtract(const TimeVal& rhs)
+{
+ g_return_if_fail(tv_usec >= 0 && tv_usec < G_USEC_PER_SEC);
+ g_return_if_fail(rhs.tv_usec >= 0 && rhs.tv_usec < G_USEC_PER_SEC);
+
+ tv_usec -= rhs.tv_usec;
+
+ if(tv_usec < 0)
+ {
+ tv_usec += G_USEC_PER_SEC;
+ --tv_sec;
+ }
+
+ tv_sec -= rhs.tv_sec;
+}
+
+void TimeVal::add_seconds(long seconds)
+{
+ g_return_if_fail(tv_usec >= 0 && tv_usec < G_USEC_PER_SEC);
+
+ tv_sec += seconds;
+}
+
+void TimeVal::subtract_seconds(long seconds)
+{
+ g_return_if_fail(tv_usec >= 0 && tv_usec < G_USEC_PER_SEC);
+
+ tv_sec -= seconds;
+}
+
+void TimeVal::add_milliseconds(long milliseconds)
+{
+ g_return_if_fail(tv_usec >= 0 && tv_usec < G_USEC_PER_SEC);
+
+ tv_usec += (milliseconds % 1000) * 1000;
+
+ if(tv_usec < 0)
+ {
+ tv_usec += G_USEC_PER_SEC;
+ --tv_sec;
+ }
+ else if(tv_usec >= G_USEC_PER_SEC)
+ {
+ tv_usec -= G_USEC_PER_SEC;
+ ++tv_sec;
+ }
+
+ tv_sec += milliseconds / 1000;
+}
+
+void TimeVal::subtract_milliseconds(long milliseconds)
+{
+ add_milliseconds(-1 * milliseconds);
+}
+
+void TimeVal::add_microseconds(long microseconds)
+{
+ g_time_val_add(this, microseconds);
+}
+
+void TimeVal::subtract_microseconds(long microseconds)
+{
+ g_time_val_add(this, -1 * microseconds);
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/timeval.h b/glib/glibmm/timeval.h
new file mode 100644
index 00000000..f27952c2
--- /dev/null
+++ b/glib/glibmm/timeval.h
@@ -0,0 +1,233 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_TIMEVAL_H
+#define _GLIBMM_TIMEVAL_H
+
+/* $Id$ */
+
+/* timeval.h
+ *
+ * Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gtypes.h>
+#include <glib/gtimer.h>
+
+namespace Glib
+{
+
+/** Glib::TimeVal is a wrapper around the glib structure GTimeVal.
+ * The glib structure GTimeVal itself is equivalent to struct timeval,
+ * which is returned by the gettimeofday() UNIX call. Additionally
+ * this wrapper provides an assortment of time manipulation functions.
+ */
+struct TimeVal : public GTimeVal
+{
+ inline TimeVal();
+ inline TimeVal(long seconds, long microseconds);
+
+ inline TimeVal(const GTimeVal& gtimeval);
+ inline TimeVal& operator=(const GTimeVal& gtimeval);
+
+ /** Assigns the current time to the TimeVal instance.
+ * Equivalent to the UNIX gettimeofday() function, but is portable and
+ * works also on Win32.
+ */
+ void assign_current_time();
+
+ void add(const TimeVal& rhs);
+ void subtract(const TimeVal& rhs);
+ void add_seconds(long seconds);
+ void subtract_seconds(long seconds);
+ void add_milliseconds(long milliseconds);
+ void subtract_milliseconds(long milliseconds);
+ void add_microseconds(long microseconds);
+ void subtract_microseconds(long microseconds);
+
+ inline TimeVal& operator+=(const TimeVal& gtimeval);
+ inline TimeVal& operator-=(const TimeVal& gtimeval);
+ inline TimeVal& operator+=(long seconds);
+ inline TimeVal& operator-=(long seconds);
+
+ /** Returns a double representation of the time interval.
+ * This member function converts the time interval, that is
+ * internally stored as two long values for seconds and microseconds,
+ * to a double representation, whose unit is seconds.
+ */
+ inline double as_double() const;
+
+ inline bool negative() const;
+
+ /** Checks whether the stored time interval is positive.
+ * Returns true if the stored time / time interval is positive.
+ */
+ inline bool valid() const;
+};
+
+inline
+TimeVal::TimeVal()
+{
+ tv_sec = 0;
+ tv_usec = 0;
+}
+
+inline
+TimeVal::TimeVal(long seconds, long microseconds)
+{
+ tv_sec = seconds;
+ tv_usec = microseconds;
+}
+
+inline
+TimeVal::TimeVal(const GTimeVal& gtimeval)
+{
+ tv_sec = gtimeval.tv_sec;
+ tv_usec = gtimeval.tv_usec;
+}
+
+inline
+TimeVal& TimeVal::operator=(const GTimeVal& gtimeval)
+{
+ tv_sec = gtimeval.tv_sec;
+ tv_usec = gtimeval.tv_usec;
+ return *this;
+}
+
+inline
+TimeVal& TimeVal::operator+=(const TimeVal& gtimeval)
+{
+ add(gtimeval);
+
+ return *this;
+}
+
+inline
+TimeVal& TimeVal::operator-=(const TimeVal& gtimeval)
+{
+ subtract(gtimeval);
+
+ return *this;
+}
+
+inline
+TimeVal& TimeVal::operator+=(long seconds)
+{
+ add_seconds(seconds);
+
+ return *this;
+}
+
+inline
+TimeVal& TimeVal::operator-=(long seconds)
+{
+ subtract_seconds(seconds);
+
+ return *this;
+}
+
+inline
+double TimeVal::as_double() const
+{
+ return tv_sec + ((double) tv_usec / (double) G_USEC_PER_SEC);
+}
+
+inline
+bool TimeVal::negative() const
+{
+ return (tv_sec < 0);
+}
+
+inline
+bool TimeVal::valid() const
+{
+ return (tv_usec >= 0 && tv_usec < G_USEC_PER_SEC);
+}
+
+/** @relates Glib::TimeVal */
+inline
+TimeVal operator+(const TimeVal& lhs, const TimeVal& rhs)
+{ return TimeVal(lhs) += rhs; }
+
+/** @relates Glib::TimeVal */
+inline
+TimeVal operator+(const TimeVal& lhs, long seconds)
+{ return TimeVal(lhs) += seconds; }
+
+/** @relates Glib::TimeVal */
+inline
+TimeVal operator-(const TimeVal& lhs, const TimeVal& rhs)
+{ return TimeVal(lhs) -= rhs; }
+
+/** @relates Glib::TimeVal */
+inline
+TimeVal operator-(const TimeVal& lhs, long seconds)
+{ return TimeVal(lhs) -= seconds; }
+
+
+/** @relates Glib::TimeVal */
+inline
+bool operator==(const TimeVal& lhs, const TimeVal& rhs)
+{
+ return (lhs.tv_sec == rhs.tv_sec && lhs.tv_usec == rhs.tv_usec);
+}
+
+/** @relates Glib::TimeVal */
+inline
+bool operator!=(const TimeVal& lhs, const TimeVal& rhs)
+{
+ return (lhs.tv_sec != rhs.tv_sec || lhs.tv_usec != rhs.tv_usec);
+}
+
+/** @relates Glib::TimeVal */
+inline
+bool operator<(const TimeVal& lhs, const TimeVal& rhs)
+{
+ return ((lhs.tv_sec < rhs.tv_sec) ||
+ (lhs.tv_sec == rhs.tv_sec && lhs.tv_usec < rhs.tv_usec));
+}
+
+/** @relates Glib::TimeVal */
+inline
+bool operator>(const TimeVal& lhs, const TimeVal& rhs)
+{
+ return ((lhs.tv_sec > rhs.tv_sec) ||
+ (lhs.tv_sec == rhs.tv_sec && lhs.tv_usec > rhs.tv_usec));
+}
+
+/** @relates Glib::TimeVal */
+inline
+bool operator<=(const TimeVal& lhs, const TimeVal& rhs)
+{
+ return ((lhs.tv_sec < rhs.tv_sec) ||
+ (lhs.tv_sec == rhs.tv_sec && lhs.tv_usec <= rhs.tv_usec));
+}
+
+/** @relates Glib::TimeVal */
+inline
+bool operator>=(const TimeVal& lhs, const TimeVal& rhs)
+{
+ return ((lhs.tv_sec > rhs.tv_sec) ||
+ (lhs.tv_sec == rhs.tv_sec && lhs.tv_usec >= rhs.tv_usec));
+}
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_TIMEVAL_H */
+
+
+
+
diff --git a/glib/glibmm/ustring.cc b/glib/glibmm/ustring.cc
new file mode 100644
index 00000000..d33b6104
--- /dev/null
+++ b/glib/glibmm/ustring.cc
@@ -0,0 +1,1180 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/ustring.h>
+#include <glibmm/convert.h>
+#include <glibmm/error.h>
+#include <glibmm/utility.h>
+
+#include <algorithm>
+#include <iostream>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(find)
+
+
+namespace
+{
+
+using Glib::ustring;
+
+
+// Little helper to make the conversion from gunichar to UTF-8 a one-liner.
+//
+struct UnicharToUtf8
+{
+ char buf[6];
+ ustring::size_type len;
+
+ explicit UnicharToUtf8(gunichar uc)
+ : len (g_unichar_to_utf8(uc, buf)) {}
+};
+
+
+// All utf8_*_offset() functions return npos if offset is out of range.
+// The caller should decide if npos is a valid argument and just marks
+// the whole string, or if it is not allowed (e.g. for start positions).
+// In the latter case std::out_of_range should be thrown, but usually
+// std::string will do that for us.
+
+// First overload: stop on '\0' character.
+//
+ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset)
+{
+ if(offset == ustring::npos)
+ return ustring::npos;
+
+ const char* p = str;
+
+ for(; offset != 0; --offset)
+ {
+ if(*p == '\0')
+ return ustring::npos;
+
+ p = g_utf8_next_char(p);
+ }
+
+ return (p - str);
+}
+
+// Second overload: stop when reaching maxlen.
+//
+ustring::size_type utf8_byte_offset(
+ const char* str, ustring::size_type offset, ustring::size_type maxlen)
+{
+ if(offset == ustring::npos)
+ return ustring::npos;
+
+ const char *const pend = str + maxlen;
+ const char* p = str;
+
+ for(; offset != 0; --offset)
+ {
+ if(p >= pend)
+ return ustring::npos;
+
+ p = g_utf8_next_char(p);
+ }
+
+ return (p - str);
+}
+
+// Third overload: stop when reaching str.size().
+//
+inline
+ustring::size_type utf8_byte_offset(const std::string& str, ustring::size_type offset)
+{
+ return utf8_byte_offset(str.data(), offset, str.size());
+}
+
+// Takes UTF-8 character offset and count in ci and cn.
+// Returns the byte offset and count in i and n.
+//
+struct Utf8SubstrBounds
+{
+ ustring::size_type i;
+ ustring::size_type n;
+
+ Utf8SubstrBounds(const std::string& str, ustring::size_type ci, ustring::size_type cn)
+ :
+ i (utf8_byte_offset(str, ci)),
+ n (ustring::npos)
+ {
+ if(i != ustring::npos)
+ n = utf8_byte_offset(str.data() + i, cn, str.size() - i);
+ }
+};
+
+// Converts byte offset to UTF-8 character offset.
+inline
+ustring::size_type utf8_char_offset(const std::string& str, ustring::size_type offset)
+{
+ if(offset == ustring::npos)
+ return ustring::npos;
+
+ const char *const pdata = str.data();
+ return g_utf8_pointer_to_offset(pdata, pdata + offset);
+}
+
+
+// Helper to implement ustring::find_first_of() and find_first_not_of().
+// Returns the UTF-8 character offset, or ustring::npos if not found.
+//
+ustring::size_type utf8_find_first_of(
+ const std::string& str, ustring::size_type offset,
+ const char* utf8_match, long utf8_match_size,
+ bool find_not_of)
+{
+ const ustring::size_type byte_offset = utf8_byte_offset(str, offset);
+ if(byte_offset == ustring::npos)
+ return ustring::npos;
+
+ long ucs4_match_size = 0;
+ const Glib::ScopedPtr<gunichar> ucs4_match
+ (g_utf8_to_ucs4_fast(utf8_match, utf8_match_size, &ucs4_match_size));
+
+ const gunichar *const match_begin = ucs4_match.get();
+ const gunichar *const match_end = match_begin + ucs4_match_size;
+
+ const char *const str_begin = str.data();
+ const char *const str_end = str_begin + str.size();
+
+ for(const char* pstr = str_begin + byte_offset;
+ pstr < str_end;
+ pstr = g_utf8_next_char(pstr))
+ {
+ const gunichar *const pfound =
+ std::find(match_begin, match_end, g_utf8_get_char(pstr));
+
+ if((pfound != match_end) != find_not_of)
+ return offset;
+
+ ++offset;
+ }
+
+ return ustring::npos;
+}
+
+// Helper to implement ustring::find_last_of() and find_last_not_of().
+// Returns the UTF-8 character offset, or ustring::npos if not found.
+//
+ustring::size_type utf8_find_last_of(
+ const std::string& str, ustring::size_type offset,
+ const char* utf8_match, long utf8_match_size,
+ bool find_not_of)
+{
+ long ucs4_match_size = 0;
+ const Glib::ScopedPtr<gunichar> ucs4_match
+ (g_utf8_to_ucs4_fast(utf8_match, utf8_match_size, &ucs4_match_size));
+
+ const gunichar *const match_begin = ucs4_match.get();
+ const gunichar *const match_end = match_begin + ucs4_match_size;
+
+ const char *const str_begin = str.data();
+ const char* pstr = str_begin;
+
+ // Set pstr one byte beyond the actual start position.
+ const ustring::size_type byte_offset = utf8_byte_offset(str, offset);
+ pstr += (byte_offset < str.size()) ? byte_offset + 1 : str.size();
+
+ while(pstr > str_begin)
+ {
+ // Move to previous character.
+ do { --pstr; } while((*pstr & '\xC0') == '\x80');
+
+ const gunichar *const pfound =
+ std::find(match_begin, match_end, g_utf8_get_char(pstr));
+
+ if((pfound != match_end) != find_not_of)
+ return g_utf8_pointer_to_offset(str_begin, pstr);
+ }
+
+ return ustring::npos;
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+// We need our own version of g_utf8_get_char(), because the std::string
+// iterator is not necessarily a plain pointer (it's in fact not in GCC's
+// libstdc++-v3). Copying the UTF-8 data into a temporary buffer isn't
+// an option since this operation is quite time critical.
+//
+// Please excuse the lack of comments: In order to understand what the
+// code does, you just have to know how UCS-4 characters are encoded in
+// UTF-8 (see http://www.cl.cam.ac.uk/~mgk25/unicode.html). With that
+// knowledge, the code should be pretty easy to understand -- comments
+// would only reduce readability.
+//
+gunichar get_unichar_from_std_iterator(std::string::const_iterator pos)
+{
+ gunichar result = static_cast<unsigned char>(*pos);
+
+ if((result & 0x80) != 0)
+ {
+ unsigned char len = g_utf8_skip[result];
+ result &= 0x7F >> len;
+
+ while(--len != 0)
+ {
+ result <<= 6;
+ result |= static_cast<unsigned char>(*++pos) & 0x3F;
+ }
+ }
+
+ return result;
+}
+
+
+/**** Glib::ustring ********************************************************/
+
+ustring::ustring()
+:
+ string_ ()
+{}
+
+ustring::ustring(const ustring& other)
+:
+ string_ (other.string_)
+{}
+
+ustring::ustring(const ustring& src, ustring::size_type i, ustring::size_type n)
+:
+ string_ ()
+{
+ const Utf8SubstrBounds bounds (src.string_, i, n);
+ string_.assign(src.string_, bounds.i, bounds.n);
+}
+
+ustring::ustring(const char* src, ustring::size_type n)
+:
+ string_ (src, utf8_byte_offset(src, n))
+{}
+
+ustring::ustring(const char* src)
+:
+ string_ (src)
+{}
+
+ustring::ustring(ustring::size_type n, gunichar uc)
+:
+ string_ ()
+{
+ if(uc < 0x80)
+ {
+ // Optimize the probably most common case.
+ string_.assign(n, static_cast<char>(static_cast<unsigned char>(uc)));
+ }
+ else
+ {
+ const UnicharToUtf8 conv (uc);
+ string_.reserve(n * conv.len);
+
+ for(; n > 0; --n)
+ string_.append(conv.buf, conv.len);
+ }
+}
+
+ustring::ustring(ustring::size_type n, char c)
+:
+ string_ (n, c)
+{}
+
+ustring::ustring(const std::string& src)
+:
+ string_ (src)
+{}
+
+ustring::~ustring()
+{}
+
+void ustring::swap(ustring& other)
+{
+ string_.swap(other.string_);
+}
+
+
+/**** Glib::ustring::operator=() *******************************************/
+
+ustring& ustring::operator=(const ustring& other)
+{
+ string_ = other.string_;
+ return *this;
+}
+
+ustring& ustring::operator=(const std::string& src)
+{
+ string_ = src;
+ return *this;
+}
+
+ustring& ustring::operator=(const char* src)
+{
+ string_ = src;
+ return *this;
+}
+
+ustring& ustring::operator=(gunichar uc)
+{
+ const UnicharToUtf8 conv (uc);
+ string_.assign(conv.buf, conv.len);
+ return *this;
+}
+
+ustring& ustring::operator=(char c)
+{
+ string_ = c;
+ return *this;
+}
+
+
+/**** Glib::ustring::assign() **********************************************/
+
+ustring& ustring::assign(const ustring& src)
+{
+ string_ = src.string_;
+ return *this;
+}
+
+ustring& ustring::assign(const ustring& src, ustring::size_type i, ustring::size_type n)
+{
+ const Utf8SubstrBounds bounds (src.string_, i, n);
+ string_.assign(src.string_, bounds.i, bounds.n);
+ return *this;
+}
+
+ustring& ustring::assign(const char* src, ustring::size_type n)
+{
+ string_.assign(src, utf8_byte_offset(src, n));
+ return *this;
+}
+
+ustring& ustring::assign(const char* src)
+{
+ string_ = src;
+ return *this;
+}
+
+ustring& ustring::assign(ustring::size_type n, gunichar uc)
+{
+ ustring tmp (n, uc);
+ string_.swap(tmp.string_);
+ return *this;
+}
+
+ustring& ustring::assign(ustring::size_type n, char c)
+{
+ string_.assign(n, c);
+ return *this;
+}
+
+
+/**** Glib::ustring::operator+=() ******************************************/
+
+ustring& ustring::operator+=(const ustring& src)
+{
+ string_ += src.string_;
+ return *this;
+}
+
+ustring& ustring::operator+=(const char* src)
+{
+ string_ += src;
+ return *this;
+}
+
+ustring& ustring::operator+=(gunichar uc)
+{
+ const UnicharToUtf8 conv (uc);
+ string_.append(conv.buf, conv.len);
+ return *this;
+}
+
+ustring& ustring::operator+=(char c)
+{
+ string_ += c;
+ return *this;
+}
+
+
+/**** Glib::ustring::push_back() *******************************************/
+
+void ustring::push_back(gunichar uc)
+{
+ const UnicharToUtf8 conv (uc);
+ string_.append(conv.buf, conv.len);
+}
+
+void ustring::push_back(char c)
+{
+ string_ += c;
+}
+
+
+/**** Glib::ustring::append() **********************************************/
+
+ustring& ustring::append(const ustring& src)
+{
+ string_ += src.string_;
+ return *this;
+}
+
+ustring& ustring::append(const ustring& src, ustring::size_type i, ustring::size_type n)
+{
+ const Utf8SubstrBounds bounds (src.string_, i, n);
+ string_.append(src.string_, bounds.i, bounds.n);
+ return *this;
+}
+
+ustring& ustring::append(const char* src, ustring::size_type n)
+{
+ string_.append(src, utf8_byte_offset(src, n));
+ return *this;
+}
+
+ustring& ustring::append(const char* src)
+{
+ string_ += src;
+ return *this;
+}
+
+ustring& ustring::append(ustring::size_type n, gunichar uc)
+{
+ string_.append(ustring(n, uc).string_);
+ return *this;
+}
+
+ustring& ustring::append(ustring::size_type n, char c)
+{
+ string_.append(n, c);
+ return *this;
+}
+
+
+/**** Glib::ustring::insert() **********************************************/
+
+ustring& ustring::insert(ustring::size_type i, const ustring& src)
+{
+ string_.insert(utf8_byte_offset(string_, i), src.string_);
+ return *this;
+}
+
+ustring& ustring::insert(ustring::size_type i, const ustring& src,
+ ustring::size_type i2, ustring::size_type n)
+{
+ const Utf8SubstrBounds bounds2 (src.string_, i2, n);
+ string_.insert(utf8_byte_offset(string_, i), src.string_, bounds2.i, bounds2.n);
+ return *this;
+}
+
+ustring& ustring::insert(ustring::size_type i, const char* src, ustring::size_type n)
+{
+ string_.insert(utf8_byte_offset(string_, i), src, utf8_byte_offset(src, n));
+ return *this;
+}
+
+ustring& ustring::insert(ustring::size_type i, const char* src)
+{
+ string_.insert(utf8_byte_offset(string_, i), src);
+ return *this;
+}
+
+ustring& ustring::insert(ustring::size_type i, ustring::size_type n, gunichar uc)
+{
+ string_.insert(utf8_byte_offset(string_, i), ustring(n, uc).string_);
+ return *this;
+}
+
+ustring& ustring::insert(ustring::size_type i, ustring::size_type n, char c)
+{
+ string_.insert(utf8_byte_offset(string_, i), n, c);
+ return *this;
+}
+
+ustring::iterator ustring::insert(ustring::iterator p, gunichar uc)
+{
+ const size_type offset = p.base() - string_.begin();
+ const UnicharToUtf8 conv (uc);
+ string_.insert(offset, conv.buf, conv.len);
+ return iterator(string_.begin() + offset);
+}
+
+ustring::iterator ustring::insert(ustring::iterator p, char c)
+{
+ return iterator(string_.insert(p.base(), c));
+}
+
+void ustring::insert(ustring::iterator p, ustring::size_type n, gunichar uc)
+{
+ string_.insert(p.base() - string_.begin(), ustring(n, uc).string_);
+}
+
+void ustring::insert(ustring::iterator p, ustring::size_type n, char c)
+{
+ string_.insert(p.base(), n, c);
+}
+
+
+/**** Glib::ustring::replace() *********************************************/
+
+ustring& ustring::replace(ustring::size_type i, ustring::size_type n, const ustring& src)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ string_.replace(bounds.i, bounds.n, src.string_);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::size_type i, ustring::size_type n,
+ const ustring& src, ustring::size_type i2, ustring::size_type n2)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ const Utf8SubstrBounds bounds2 (src.string_, i2, n2);
+ string_.replace(bounds.i, bounds.n, src.string_, bounds2.i, bounds2.n);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::size_type i, ustring::size_type n,
+ const char* src, ustring::size_type n2)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ string_.replace(bounds.i, bounds.n, src, utf8_byte_offset(src, n2));
+ return *this;
+}
+
+ustring& ustring::replace(ustring::size_type i, ustring::size_type n, const char* src)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ string_.replace(bounds.i, bounds.n, src);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::size_type i, ustring::size_type n,
+ ustring::size_type n2, gunichar uc)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ string_.replace(bounds.i, bounds.n, ustring(n2, uc).string_);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::size_type i, ustring::size_type n,
+ ustring::size_type n2, char c)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ string_.replace(bounds.i, bounds.n, n2, c);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::iterator pbegin, ustring::iterator pend, const ustring& src)
+{
+ string_.replace(pbegin.base(), pend.base(), src.string_);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::iterator pbegin, ustring::iterator pend,
+ const char* src, ustring::size_type n)
+{
+ string_.replace(pbegin.base(), pend.base(), src, utf8_byte_offset(src, n));
+ return *this;
+}
+
+ustring& ustring::replace(ustring::iterator pbegin, ustring::iterator pend, const char* src)
+{
+ string_.replace(pbegin.base(), pend.base(), src);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::iterator pbegin, ustring::iterator pend,
+ ustring::size_type n, gunichar uc)
+{
+ string_.replace(pbegin.base(), pend.base(), ustring(n, uc).string_);
+ return *this;
+}
+
+ustring& ustring::replace(ustring::iterator pbegin, ustring::iterator pend,
+ ustring::size_type n, char c)
+{
+ string_.replace(pbegin.base(), pend.base(), n, c);
+ return *this;
+}
+
+
+/**** Glib::ustring::erase() ***********************************************/
+
+void ustring::clear()
+{
+ string_.erase();
+}
+
+ustring& ustring::erase(ustring::size_type i, ustring::size_type n)
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ string_.erase(bounds.i, bounds.n);
+ return *this;
+}
+
+ustring& ustring::erase()
+{
+ string_.erase();
+ return *this;
+}
+
+ustring::iterator ustring::erase(ustring::iterator p)
+{
+ return iterator(string_.erase(p.base()));
+}
+
+ustring::iterator ustring::erase(ustring::iterator pbegin, ustring::iterator pend)
+{
+ return iterator(string_.erase(pbegin.base(), pend.base()));
+}
+
+
+/**** Glib::ustring::compare() *********************************************/
+
+int ustring::compare(const ustring& rhs) const
+{
+ return g_utf8_collate(string_.c_str(), rhs.string_.c_str());
+}
+
+int ustring::compare(const char* rhs) const
+{
+ return g_utf8_collate(string_.c_str(), rhs);
+}
+
+int ustring::compare(ustring::size_type i, ustring::size_type n, const ustring& rhs) const
+{
+ return ustring(*this, i, n).compare(rhs);
+}
+
+int ustring::compare(ustring::size_type i, ustring::size_type n,
+ const ustring& rhs, ustring::size_type i2, ustring::size_type n2) const
+{
+ return ustring(*this, i, n).compare(ustring(rhs, i2, n2));
+}
+
+int ustring::compare(ustring::size_type i, ustring::size_type n,
+ const char* rhs, ustring::size_type n2) const
+{
+ return ustring(*this, i, n).compare(ustring(rhs, n2));
+}
+
+int ustring::compare(ustring::size_type i, ustring::size_type n, const char* rhs) const
+{
+ return ustring(*this, i, n).compare(rhs);
+}
+
+
+/**** Glib::ustring -- index access ****************************************/
+
+ustring::value_type ustring::operator[](ustring::size_type i) const
+{
+ return g_utf8_get_char(g_utf8_offset_to_pointer(string_.data(), i));
+}
+
+ustring::value_type ustring::at(ustring::size_type i) const
+{
+ const size_type byte_offset = utf8_byte_offset(string_, i);
+
+ // Throws std::out_of_range if the index is invalid.
+ return g_utf8_get_char(&string_.at(byte_offset));
+}
+
+
+/**** Glib::ustring -- iterator access *************************************/
+
+ustring::iterator ustring::begin()
+{
+ return iterator(string_.begin());
+}
+
+ustring::iterator ustring::end()
+{
+ return iterator(string_.end());
+}
+
+ustring::const_iterator ustring::begin() const
+{
+ return const_iterator(string_.begin());
+}
+
+ustring::const_iterator ustring::end() const
+{
+ return const_iterator(string_.end());
+}
+
+ustring::reverse_iterator ustring::rbegin()
+{
+ return reverse_iterator(iterator(string_.end()));
+}
+
+ustring::reverse_iterator ustring::rend()
+{
+ return reverse_iterator(iterator(string_.begin()));
+}
+
+ustring::const_reverse_iterator ustring::rbegin() const
+{
+ return const_reverse_iterator(const_iterator(string_.end()));
+}
+
+ustring::const_reverse_iterator ustring::rend() const
+{
+ return const_reverse_iterator(const_iterator(string_.begin()));
+}
+
+
+/**** Glib::ustring::find() ************************************************/
+
+ustring::size_type ustring::find(const ustring& str, ustring::size_type i) const
+{
+ return utf8_char_offset(string_,
+ string_.find(str.string_, utf8_byte_offset(string_, i)));
+}
+
+ustring::size_type ustring::find(const char* str, ustring::size_type i, ustring::size_type n) const
+{
+ return utf8_char_offset(string_, string_.find(
+ str, utf8_byte_offset(string_, i), utf8_byte_offset(str, n)));
+}
+
+ustring::size_type ustring::find(const char* str, ustring::size_type i) const
+{
+ return utf8_char_offset(string_,
+ string_.find(str, utf8_byte_offset(string_, i)));
+}
+
+ustring::size_type ustring::find(gunichar uc, ustring::size_type i) const
+{
+ const UnicharToUtf8 conv (uc);
+ return utf8_char_offset(string_,
+ string_.find(conv.buf, utf8_byte_offset(string_, i), conv.len));
+}
+
+ustring::size_type ustring::find(char c, ustring::size_type i) const
+{
+ return utf8_char_offset(string_,
+ string_.find(c, utf8_byte_offset(string_, i)));
+}
+
+
+/**** Glib::ustring::rfind() ***********************************************/
+
+ustring::size_type ustring::rfind(const ustring& str, ustring::size_type i) const
+{
+ return utf8_char_offset(string_,
+ string_.rfind(str.string_, utf8_byte_offset(string_, i)));
+}
+
+ustring::size_type ustring::rfind(const char* str, ustring::size_type i,
+ ustring::size_type n) const
+{
+ return utf8_char_offset(string_, string_.rfind(
+ str, utf8_byte_offset(string_, i), utf8_byte_offset(str, n)));
+}
+
+ustring::size_type ustring::rfind(const char* str, ustring::size_type i) const
+{
+ return utf8_char_offset(string_,
+ string_.rfind(str, utf8_byte_offset(string_, i)));
+}
+
+ustring::size_type ustring::rfind(gunichar uc, ustring::size_type i) const
+{
+ const UnicharToUtf8 conv (uc);
+ return utf8_char_offset(string_,
+ string_.rfind(conv.buf, utf8_byte_offset(string_, i), conv.len));
+}
+
+ustring::size_type ustring::rfind(char c, ustring::size_type i) const
+{
+ return utf8_char_offset(string_,
+ string_.rfind(c, utf8_byte_offset(string_, i)));
+}
+
+
+/**** Glib::ustring::find_first_of() ***************************************/
+
+ustring::size_type ustring::find_first_of(const ustring& match, ustring::size_type i) const
+{
+ return utf8_find_first_of(string_, i, match.string_.data(), match.string_.size(), false);
+}
+
+ustring::size_type ustring::find_first_of(const char* match,
+ ustring::size_type i, ustring::size_type n) const
+{
+ return utf8_find_first_of(string_, i, match, n, false);
+}
+
+ustring::size_type ustring::find_first_of(const char* match, ustring::size_type i) const
+{
+ return utf8_find_first_of(string_, i, match, -1, false);
+}
+
+ustring::size_type ustring::find_first_of(gunichar uc, ustring::size_type i) const
+{
+ return find(uc, i);
+}
+
+ustring::size_type ustring::find_first_of(char c, ustring::size_type i) const
+{
+ return find(c, i);
+}
+
+
+/**** Glib::ustring::find_last_of() ****************************************/
+
+ustring::size_type ustring::find_last_of(const ustring& match, ustring::size_type i) const
+{
+ return utf8_find_last_of(string_, i, match.string_.data(), match.string_.size(), false);
+}
+
+ustring::size_type ustring::find_last_of(const char* match,
+ ustring::size_type i, ustring::size_type n) const
+{
+ return utf8_find_last_of(string_, i, match, n, false);
+}
+
+ustring::size_type ustring::find_last_of(const char* match, ustring::size_type i) const
+{
+ return utf8_find_last_of(string_, i, match, -1, false);
+}
+
+ustring::size_type ustring::find_last_of(gunichar uc, ustring::size_type i) const
+{
+ return rfind(uc, i);
+}
+
+ustring::size_type ustring::find_last_of(char c, ustring::size_type i) const
+{
+ return rfind(c, i);
+}
+
+
+/**** Glib::ustring::find_first_not_of() ***********************************/
+
+ustring::size_type ustring::find_first_not_of(const ustring& match, ustring::size_type i) const
+{
+ return utf8_find_first_of(string_, i, match.string_.data(), match.string_.size(), true);
+}
+
+ustring::size_type ustring::find_first_not_of(const char* match,
+ ustring::size_type i, ustring::size_type n) const
+{
+ return utf8_find_first_of(string_, i, match, n, true);
+}
+
+ustring::size_type ustring::find_first_not_of(const char* match, ustring::size_type i) const
+{
+ return utf8_find_first_of(string_, i, match, -1, true);
+}
+
+// Unfortunately, all of the find_*_not_of() methods for single
+// characters need their own special implementation.
+//
+ustring::size_type ustring::find_first_not_of(gunichar uc, ustring::size_type i) const
+{
+ const size_type bi = utf8_byte_offset(string_, i);
+ if(bi != npos)
+ {
+ const char *const pbegin = string_.data();
+ const char *const pend = pbegin + string_.size();
+
+ for(const char* p = pbegin + bi;
+ p < pend;
+ p = g_utf8_next_char(p), ++i)
+ {
+ if(g_utf8_get_char(p) != uc)
+ return i;
+ }
+ }
+ return npos;
+}
+
+ustring::size_type ustring::find_first_not_of(char c, ustring::size_type i) const
+{
+ const size_type bi = utf8_byte_offset(string_, i);
+ if(bi != npos)
+ {
+ const char *const pbegin = string_.data();
+ const char *const pend = pbegin + string_.size();
+
+ for(const char* p = pbegin + bi;
+ p < pend;
+ p = g_utf8_next_char(p), ++i)
+ {
+ if(*p != c)
+ return i;
+ }
+ }
+ return npos;
+}
+
+
+/**** Glib::ustring::find_last_not_of() ************************************/
+
+ustring::size_type ustring::find_last_not_of(const ustring& match, ustring::size_type i) const
+{
+ return utf8_find_last_of(string_, i, match.string_.data(), match.string_.size(), true);
+}
+
+ustring::size_type ustring::find_last_not_of(const char* match,
+ ustring::size_type i, ustring::size_type n) const
+{
+ return utf8_find_last_of(string_, i, match, n, true);
+}
+
+ustring::size_type ustring::find_last_not_of(const char* match, ustring::size_type i) const
+{
+ return utf8_find_last_of(string_, i, match, -1, true);
+}
+
+// Unfortunately, all of the find_*_not_of() methods for single
+// characters need their own special implementation.
+//
+ustring::size_type ustring::find_last_not_of(gunichar uc, ustring::size_type i) const
+{
+ const char *const pbegin = string_.data();
+ const char *const pend = pbegin + string_.size();
+ size_type i_cur = 0;
+ size_type i_found = npos;
+
+ for(const char* p = pbegin;
+ p < pend && i_cur <= i;
+ p = g_utf8_next_char(p), ++i_cur)
+ {
+ if(g_utf8_get_char(p) != uc)
+ i_found = i_cur;
+ }
+ return i_found;
+}
+
+ustring::size_type ustring::find_last_not_of(char c, ustring::size_type i) const
+{
+ const char *const pbegin = string_.data();
+ const char *const pend = pbegin + string_.size();
+ size_type i_cur = 0;
+ size_type i_found = npos;
+
+ for(const char* p = pbegin;
+ p < pend && i_cur <= i;
+ p = g_utf8_next_char(p), ++i_cur)
+ {
+ if(*p != c)
+ i_found = i_cur;
+ }
+ return i_found;
+}
+
+
+/**** Glib::ustring -- get size and resize *********************************/
+
+bool ustring::empty() const
+{
+ return string_.empty();
+}
+
+ustring::size_type ustring::size() const
+{
+ const char *const pdata = string_.data();
+ return g_utf8_pointer_to_offset(pdata, pdata + string_.size());
+}
+
+ustring::size_type ustring::length() const
+{
+ const char *const pdata = string_.data();
+ return g_utf8_pointer_to_offset(pdata, pdata + string_.size());
+}
+
+ustring::size_type ustring::bytes() const
+{
+ return string_.size();
+}
+
+ustring::size_type ustring::capacity() const
+{
+ return string_.capacity();
+}
+
+ustring::size_type ustring::max_size() const
+{
+ return string_.max_size();
+}
+
+void ustring::resize(ustring::size_type n, gunichar uc)
+{
+ const size_type size_now = size();
+ if(n < size_now)
+ erase(n, npos);
+ else if(n > size_now)
+ append(n - size_now, uc);
+}
+
+void ustring::resize(ustring::size_type n, char c)
+{
+ const size_type size_now = size();
+ if(n < size_now)
+ erase(n, npos);
+ else if(n > size_now)
+ string_.append(n - size_now, c);
+}
+
+void ustring::reserve(ustring::size_type n)
+{
+ string_.reserve(n);
+}
+
+
+/**** Glib::ustring -- C string access *************************************/
+
+const char* ustring::data() const
+{
+ return string_.data();
+}
+
+const char* ustring::c_str() const
+{
+ return string_.c_str();
+}
+
+// Note that copy() requests UTF-8 character offsets as
+// parameters, but returns the number of copied bytes.
+//
+ustring::size_type ustring::copy(char* dest, ustring::size_type n, ustring::size_type i) const
+{
+ const Utf8SubstrBounds bounds (string_, i, n);
+ return string_.copy(dest, bounds.n, bounds.i);
+}
+
+
+/**** Glib::ustring -- UTF-8 utilities *************************************/
+
+bool ustring::validate() const
+{
+ return g_utf8_validate(string_.data(), string_.size(), 0);
+}
+
+bool ustring::validate(ustring::iterator& first_invalid)
+{
+ const char *const pdata = string_.data();
+ const char* valid_end = pdata;
+ const bool is_valid = g_utf8_validate(pdata, string_.size(), &valid_end);
+
+ first_invalid = iterator(string_.begin() + (valid_end - pdata));
+ return is_valid;
+}
+
+bool ustring::validate(ustring::const_iterator& first_invalid) const
+{
+ const char *const pdata = string_.data();
+ const char* valid_end = pdata;
+ const bool is_valid = g_utf8_validate(pdata, string_.size(), &valid_end);
+
+ first_invalid = const_iterator(string_.begin() + (valid_end - pdata));
+ return is_valid;
+}
+
+bool ustring::is_ascii() const
+{
+ const std::string::const_iterator string_end = string_.end();
+ for(std::string::const_iterator p = string_.begin(); p != string_end; ++p)
+ {
+ if((*p & '\x80') != 0)
+ return false;
+ }
+ return true;
+}
+
+ustring ustring::normalize(NormalizeMode mode) const
+{
+ const ScopedPtr<char> buf (g_utf8_normalize(
+ string_.data(), string_.size(), static_cast<GNormalizeMode>(int(mode))));
+
+ return ustring(buf.get());
+}
+
+ustring ustring::uppercase() const
+{
+ const ScopedPtr<char> buf (g_utf8_strup(string_.data(), string_.size()));
+ return ustring(buf.get());
+}
+
+ustring ustring::lowercase() const
+{
+ const ScopedPtr<char> buf (g_utf8_strdown(string_.data(), string_.size()));
+ return ustring(buf.get());
+}
+
+ustring ustring::casefold() const
+{
+ const ScopedPtr<char> buf (g_utf8_casefold(string_.data(), string_.size()));
+ return ustring(buf.get());
+}
+
+std::string ustring::collate_key() const
+{
+ const ScopedPtr<char> buf (g_utf8_collate_key(string_.data(), string_.size()));
+ return std::string(buf.get());
+}
+
+std::string ustring::casefold_collate_key() const
+{
+ char *const casefold_buf = g_utf8_casefold(string_.data(), string_.size());
+ char *const key_buf = g_utf8_collate_key(casefold_buf, -1);
+ g_free(casefold_buf);
+ return std::string(ScopedPtr<char>(key_buf).get());
+}
+
+
+/**** Glib::ustring::SequenceToString **************************************/
+
+ustring::SequenceToString<Glib::ustring::iterator,gunichar>
+ ::SequenceToString(Glib::ustring::iterator pbegin, Glib::ustring::iterator pend)
+:
+ std::string(pbegin.base(), pend.base())
+{}
+
+ustring::SequenceToString<Glib::ustring::const_iterator,gunichar>
+ ::SequenceToString(Glib::ustring::const_iterator pbegin, Glib::ustring::const_iterator pend)
+:
+ std::string(pbegin.base(), pend.base())
+{}
+
+
+/**** Glib::ustring -- stream I/O operators ********************************/
+
+std::istream& operator>>(std::istream& is, Glib::ustring& utf8_string)
+{
+ std::string locale_string;
+ is >> locale_string;
+ utf8_string = Glib::locale_to_utf8(locale_string);
+ return is;
+}
+
+std::ostream& operator<<(std::ostream& os, const Glib::ustring& utf8_string)
+{
+ os << Glib::locale_from_utf8(utf8_string);
+ return os;
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/ustring.h b/glib/glibmm/ustring.h
new file mode 100644
index 00000000..c4e75b04
--- /dev/null
+++ b/glib/glibmm/ustring.h
@@ -0,0 +1,907 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_USTRING_H
+#define _GLIBMM_USTRING_H
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gunicode.h>
+#include <glibmm/unicode.h>
+
+#include <iosfwd>
+#include <iterator>
+#include <string>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(bidirectional_iterator_tag)
+GTKMM_USING_STD(reverse_iterator)
+GTKMM_USING_STD(string)
+GTKMM_USING_STD(istream)
+GTKMM_USING_STD(ostream)
+
+#ifdef GTKMM_HAVE_STD_ITERATOR_TRAITS
+GTKMM_USING_STD(iterator_traits)
+#else
+#include <cstddef> /* for ptrdiff_t */
+GTKMM_USING_STD(random_access_iterator_tag)
+#endif
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#ifndef GTKMM_HAVE_STD_ITERATOR_TRAITS
+
+template <class T>
+struct IteratorTraits
+{
+ typedef typename T::iterator_category iterator_category;
+ typedef typename T::value_type value_type;
+ typedef typename T::difference_type difference_type;
+ typedef typename T::pointer pointer;
+ typedef typename T::reference reference;
+};
+
+template <class T>
+struct IteratorTraits<T*>
+{
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T& reference;
+};
+
+template <class T>
+struct IteratorTraits<const T*>
+{
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef ptrdiff_t difference_type;
+ typedef const T* pointer;
+ typedef const T& reference;
+};
+
+#endif /* GTKMM_HAVE_STD_ITERATOR_TRAITS */
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/** The iterator type of Glib::ustring.
+ * Note this is not a random access iterator but a bidirectional one,
+ * since all index operations need to iterate over the UTF-8 data. Use
+ * std::advance() to move to a certain position. However, all of the
+ * relational operators are available:
+ * <tt>==&nbsp;!=&nbsp;<&nbsp;>&nbsp;<=&nbsp;>=</tt>
+ *
+ * A writeable iterator isn't provided because: The number of bytes of
+ * the old UTF-8 character and the new one to write could be different.
+ * Therefore, any write operation would invalidate all other iterators
+ * pointing into the same string.
+ */
+template <class T>
+class ustring_Iterator
+{
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+ typedef gunichar value_type;
+ typedef std::string::difference_type difference_type;
+ typedef value_type reference;
+ typedef void pointer;
+
+ inline ustring_Iterator();
+ inline ustring_Iterator(const ustring_Iterator<std::string::iterator>& other);
+
+ inline value_type operator*() const;
+
+ inline ustring_Iterator<T> & operator++();
+ inline const ustring_Iterator<T> operator++(int);
+ inline ustring_Iterator<T> & operator--();
+ inline const ustring_Iterator<T> operator--(int);
+
+ explicit inline ustring_Iterator(T pos);
+ inline T base() const;
+
+private:
+ T pos_;
+};
+
+
+/** Extract a UCS-4 character from UTF-8 data.
+ * Convert a single UTF-8 (multibyte) character starting at @p pos to
+ * a UCS-4 wide character. This may read up to 6 bytes after the start
+ * position, depending on the UTF-8 character width. You have to make
+ * sure the source contains at least one valid UTF-8 character.
+ *
+ * This is mainly used by the implementation of Glib::ustring::iterator,
+ * but it might be useful as utility function if you prefer using
+ * std::string even for UTF-8 encoding.
+ */
+gunichar get_unichar_from_std_iterator(std::string::const_iterator pos);
+
+
+/** Glib::ustring has much the same interface as std::string, but contains
+ * %Unicode characters encoded as UTF-8.
+ *
+ * @par About UTF-8 and ASCII
+ * @par
+ * The standard character set ANSI_X3.4-1968&nbsp;-- more commonly known as
+ * ASCII&nbsp;-- is a subset of UTF-8. So, if you want to, you can use
+ * Glib::ustring without even thinking about UTF-8.
+ * @par
+ * Whenever ASCII is mentioned in this manual, we mean the @em real ASCII
+ * (i.e. as defined in ANSI_X3.4-1968), which contains only 7-bit characters.
+ * Glib::ustring can @em not be used with ASCII-compatible extended 8-bit
+ * charsets like ISO-8859-1. It's a good idea to avoid string literals
+ * containing non-ASCII characters (e.g. German umlauts) in source code,
+ * or at least you should use UTF-8 literals.
+ * @par
+ * You can find a detailed UTF-8 and %Unicode FAQ here:
+ * http://www.cl.cam.ac.uk/~mgk25/unicode.html
+ *
+ * @par Glib::ustring vs. std::string
+ * @par
+ * Glib::ustring has implicit type conversions to and from std::string.
+ * These conversions do @em not convert to/from the current locale (see
+ * Glib::locale_from_utf8() and Glib::locale_to_utf8() if you need that). You
+ * can always use std::string instead of Glib::ustring&nbsp;-- however, using
+ * std::string with multi-byte characters is quite hard. For instance,
+ * <tt>std::string::operator[]</tt> might return a byte in the middle of a
+ * character, and <tt>std::string::length()</tt> returns the number of bytes
+ * rather than characters. So don't do that without a good reason.
+ * @par
+ * In a perfect world the C++ Standard Library would contain a UTF-8 string
+ * class. Unfortunately, the C++ standard doesn't mention UTF-8 at all. Note
+ * that std::wstring is not a UTF-8 string class because it contains only
+ * fixed-width characters (where width could be 32, 16, or even 8 bits).
+ *
+ * @par Glib::ustring and stream input/output
+ * @par
+ * The stream I/O operators, that is operator<<() and operator>>(), perform
+ * implicit charset conversion to/from the current locale. If that's not
+ * what you intented (e.g. when writing to a configuration file that should
+ * always be UTF-8 encoded) use ustring::raw() to override this behaviour.
+ * @par
+ * If you're using std::ostringstream to build strings for display in the
+ * user interface, you must convert the result back to UTF-8 as shown below:
+ * @code
+ * std::ostringstream output;
+ * output.imbue(std::locale("")); // use the user's locale for this stream
+ * output << percentage << " % done";
+ * label->set_text(Glib::locale_to_utf8(output.str()));
+ * @endcode
+ *
+ * @par Implementation notes
+ * @par
+ * Glib::ustring does not inherit from std::string, because std::string was
+ * intended to be a final class. For instance, it does not have a virtual
+ * destructor. Also, a HAS-A relationship is more appropriate because
+ * ustring can't just enhance the std::string interface. Rather, it has to
+ * reimplement the interface so that all operations are based on characters
+ * instead of bytes.
+ */
+class ustring
+{
+public:
+ typedef std::string::size_type size_type;
+ typedef std::string::difference_type difference_type;
+
+ typedef gunichar value_type;
+ typedef gunichar & reference;
+ typedef const gunichar & const_reference;
+
+ typedef ustring_Iterator<std::string::iterator> iterator;
+ typedef ustring_Iterator<std::string::const_iterator> const_iterator;
+
+#ifndef GTKMM_HAVE_SUN_REVERSE_ITERATOR
+
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+#else
+
+ typedef std::reverse_iterator<iterator,
+ iterator::iterator_category,
+ iterator::value_type,
+ iterator::reference,
+ iterator::pointer,
+ iterator::difference_type> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator,
+ const_iterator::iterator_category,
+ const_iterator::value_type,
+ const_iterator::reference,
+ const_iterator::pointer,
+ const_iterator::difference_type> const_reverse_iterator;
+
+#endif /* GTKMM_HAVE_SUN_REVERSE_ITERATOR */
+
+ static const size_type npos = std::string::npos;
+
+ ustring();
+ ~ustring();
+
+ ustring(const ustring& other);
+ ustring& operator=(const ustring& other);
+
+ void swap(ustring& other);
+
+//! @name Create new strings.
+//! @{
+
+ ustring(const std::string& src);
+ ustring(const ustring& src, size_type i, size_type n=npos);
+ ustring(const char* src, size_type n);
+ ustring(const char* src);
+ ustring(size_type n, gunichar uc);
+ ustring(size_type n, char c);
+ template <class In> ustring(In pbegin, In pend);
+
+//! @}
+//! @name Assign new contents.
+//! @{
+
+ ustring& operator=(const std::string& src);
+ ustring& operator=(const char* src);
+ ustring& operator=(gunichar uc);
+ ustring& operator=(char c);
+
+ ustring& assign(const ustring& src);
+ ustring& assign(const ustring& src, size_type i, size_type n);
+ ustring& assign(const char* src, size_type n);
+ ustring& assign(const char* src);
+ ustring& assign(size_type n, gunichar uc);
+ ustring& assign(size_type n, char c);
+ template <class In> ustring& assign(In pbegin, In pend);
+
+//! @}
+//! @name Append to the string.
+//! @{
+
+ ustring& operator+=(const ustring& src);
+ ustring& operator+=(const char* src);
+ ustring& operator+=(gunichar uc);
+ ustring& operator+=(char c);
+ void push_back(gunichar uc);
+ void push_back(char c);
+
+ ustring& append(const ustring& src);
+ ustring& append(const ustring& src, size_type i, size_type n);
+ ustring& append(const char* src, size_type n);
+ ustring& append(const char* src);
+ ustring& append(size_type n, gunichar uc);
+ ustring& append(size_type n, char c);
+ template <class In> ustring& append(In pbegin, In pend);
+
+//! @}
+//! @name Insert into the string.
+//! @{
+
+ ustring& insert(size_type i, const ustring& src);
+ ustring& insert(size_type i, const ustring& src, size_type i2, size_type n);
+ ustring& insert(size_type i, const char* src, size_type n);
+ ustring& insert(size_type i, const char* src);
+ ustring& insert(size_type i, size_type n, gunichar uc);
+ ustring& insert(size_type i, size_type n, char c);
+
+ iterator insert(iterator p, gunichar uc);
+ iterator insert(iterator p, char c);
+ void insert(iterator p, size_type n, gunichar uc);
+ void insert(iterator p, size_type n, char c);
+ template <class In> void insert(iterator p, In pbegin, In pend);
+
+//! @}
+//! @name Replace sub-strings.
+//! @{
+
+ ustring& replace(size_type i, size_type n, const ustring& src);
+ ustring& replace(size_type i, size_type n, const ustring& src, size_type i2, size_type n2);
+ ustring& replace(size_type i, size_type n, const char* src, size_type n2);
+ ustring& replace(size_type i, size_type n, const char* src);
+ ustring& replace(size_type i, size_type n, size_type n2, gunichar uc);
+ ustring& replace(size_type i, size_type n, size_type n2, char c);
+
+ ustring& replace(iterator pbegin, iterator pend, const ustring& src);
+ ustring& replace(iterator pbegin, iterator pend, const char* src, size_type n);
+ ustring& replace(iterator pbegin, iterator pend, const char* src);
+ ustring& replace(iterator pbegin, iterator pend, size_type n, gunichar uc);
+ ustring& replace(iterator pbegin, iterator pend, size_type n, char c);
+ template <class In> ustring& replace(iterator pbegin, iterator pend, In pbegin2, In pend2);
+
+//! @}
+//! @name Erase sub-strings.
+//! @{
+
+ void clear();
+ ustring& erase(size_type i, size_type n=npos);
+ ustring& erase();
+ iterator erase(iterator p);
+ iterator erase(iterator pbegin, iterator pend);
+
+//! @}
+//! @name Compare and collate.
+//! @{
+
+ int compare(const ustring& rhs) const;
+ int compare(const char* rhs) const;
+ int compare(size_type i, size_type n, const ustring& rhs) const;
+ int compare(size_type i, size_type n, const ustring& rhs, size_type i2, size_type n2) const;
+ int compare(size_type i, size_type n, const char* rhs, size_type n2) const;
+ int compare(size_type i, size_type n, const char* rhs) const;
+
+ /*! Create a unique sorting key for the UTF-8 string. If you need to
+ * compare UTF-8 strings regularly, e.g. for sorted containers such as
+ * <tt>std::set<></tt>, you should consider creating a collate key first
+ * and compare this key instead of the actual string.
+ *
+ * The ustring::compare() methods as well as the relational operators
+ * <tt>==&nbsp;!=&nbsp;<&nbsp;>&nbsp;<=&nbsp;>=</tt> are quite costly
+ * because they have to deal with %Unicode and the collation rules defined by
+ * the current locale. Converting both operands to UCS-4 is just the first
+ * of several costly steps involved when comparing ustrings. So be careful.
+ */
+ std::string collate_key() const;
+
+ /*! Create a unique key for the UTF-8 string that can be used for caseless
+ * sorting. <tt>ustr.casefold_collate_key()</tt> results in the same string
+ * as <tt>ustr.casefold().collate_key()</tt>, but the former is likely more
+ * efficient.
+ */
+ std::string casefold_collate_key() const;
+
+//! @}
+//! @name Extract characters and sub-strings.
+//! @{
+
+ /*! No reference return; use replace() to write characters. */
+ value_type operator[](size_type i) const;
+
+ /*! No reference return; use replace() to write characters. @throw std::out_of_range */
+ value_type at(size_type i) const;
+
+ inline ustring substr(size_type i=0, size_type n=npos) const;
+
+//! @}
+//! @name Access a sequence of characters.
+//! @{
+
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+ reverse_iterator rbegin();
+ reverse_iterator rend();
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+
+//! @}
+//! @name Find sub-strings.
+//! @{
+
+ size_type find(const ustring& str, size_type i=0) const;
+ size_type find(const char* str, size_type i, size_type n) const;
+ size_type find(const char* str, size_type i=0) const;
+ size_type find(gunichar uc, size_type i=0) const;
+ size_type find(char c, size_type i=0) const;
+
+ size_type rfind(const ustring& str, size_type i=npos) const;
+ size_type rfind(const char* str, size_type i, size_type n) const;
+ size_type rfind(const char* str, size_type i=npos) const;
+ size_type rfind(gunichar uc, size_type i=npos) const;
+ size_type rfind(char c, size_type i=npos) const;
+
+//! @}
+//! @name Match against a set of characters.
+//! @{
+
+ size_type find_first_of(const ustring& match, size_type i=0) const;
+ size_type find_first_of(const char* match, size_type i, size_type n) const;
+ size_type find_first_of(const char* match, size_type i=0) const;
+ size_type find_first_of(gunichar uc, size_type i=0) const;
+ size_type find_first_of(char c, size_type i=0) const;
+
+ size_type find_last_of(const ustring& match, size_type i=npos) const;
+ size_type find_last_of(const char* match, size_type i, size_type n) const;
+ size_type find_last_of(const char* match, size_type i=npos) const;
+ size_type find_last_of(gunichar uc, size_type i=npos) const;
+ size_type find_last_of(char c, size_type i=npos) const;
+
+ size_type find_first_not_of(const ustring& match, size_type i=0) const;
+ size_type find_first_not_of(const char* match, size_type i, size_type n) const;
+ size_type find_first_not_of(const char* match, size_type i=0) const;
+ size_type find_first_not_of(gunichar uc, size_type i=0) const;
+ size_type find_first_not_of(char c, size_type i=0) const;
+
+ size_type find_last_not_of(const ustring& match, size_type i=npos) const;
+ size_type find_last_not_of(const char* match, size_type i, size_type n) const;
+ size_type find_last_not_of(const char* match, size_type i=npos) const;
+ size_type find_last_not_of(gunichar uc, size_type i=npos) const;
+ size_type find_last_not_of(char c, size_type i=npos) const;
+
+//! @}
+//! @name Retrieve the string's size.
+//! @{
+
+ bool empty() const;
+ size_type size() const;
+ size_type length() const;
+ size_type bytes() const;
+
+//! @}
+//! @name Change the string's size.
+//! @{
+
+ void resize(size_type n, gunichar uc);
+ void resize(size_type n, char c='\0');
+
+//! @}
+//! @name Control the allocated memory.
+//! @{
+
+ size_type capacity() const;
+ size_type max_size() const;
+ void reserve(size_type n=0);
+
+//! @}
+//! @name Get a per-byte representation of the string.
+//! @{
+
+ inline operator std::string() const; // e.g. std::string str = ustring();
+ inline const std::string& raw() const;
+
+ // Not necessarily an ASCII char*. Use g_utf8_*() where necessary.
+ const char* data() const;
+ const char* c_str() const;
+
+ /*! @return Number of copied @em bytes, not characters. */
+ size_type copy(char* dest, size_type n, size_type i=0) const;
+
+//! @}
+//! @name UTF-8 utilities.
+//! @{
+
+ /*! Check whether the string is valid UTF-8. */
+ bool validate() const;
+ bool validate(iterator& first_invalid);
+ bool validate(const_iterator& first_invalid) const;
+
+ /*! Check whether the string is plain 7-bit ASCII. @par
+ * Unlike any other ustring method, is_ascii() is safe to use on invalid
+ * UTF-8 strings. If the string isn't valid UTF-8, it cannot be valid
+ * ASCII either, therefore is_ascii() will just return @c false then.
+ * @return Whether the string contains only ASCII characters.
+ */
+ bool is_ascii() const;
+
+ /*! "Normalize" the %Unicode character representation of the string. */
+ ustring normalize(NormalizeMode mode = NORMALIZE_DEFAULT_COMPOSE) const;
+
+//! @}
+//! @name Character case conversion.
+//! @{
+
+ /*! Returns a new UTF-8 string with all characters characters converted to
+ * their uppercase equivalent, while honoring the current locale. The
+ * resulting string may change in the number of bytes as well as in the
+ * number of characters. For instance, the German sharp&nbsp;s
+ * <tt>"&szlig;"</tt> will be replaced by two characters <tt>"SS"</tt>
+ * because there is no capital <tt>"&szlig;"</tt>.
+ */
+ ustring uppercase() const;
+
+ /*! Returns a new UTF-8 string with all characters characters converted to
+ * their uppercase equivalent, while honoring the current locale. The
+ * resulting string may change in the number of bytes as well as in the
+ * number of characters.
+ */
+ ustring lowercase() const;
+
+ /*! Returns a caseless representation of the UTF-8 string. The resulting
+ * string doesn't correspond to any particular case, therefore the result
+ * is only useful to compare strings and should never be displayed to the
+ * user.
+ */
+ ustring casefold() const;
+
+//! @}
+
+private:
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#ifdef GTKMM_HAVE_STD_ITERATOR_TRAITS
+ template <class In, class ValueType = typename std::iterator_traits<In>::value_type>
+#else
+ template <class In, class ValueType = typename Glib::IteratorTraits<In>::value_type>
+#endif
+ struct SequenceToString;
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+ std::string string_;
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <class In, class ValueType>
+struct ustring::SequenceToString
+{};
+
+template <class In>
+struct ustring::SequenceToString<In,char> : public std::string
+{
+ SequenceToString(In pbegin, In pend);
+};
+
+template <class In>
+struct ustring::SequenceToString<In,gunichar> : public std::string
+{
+ SequenceToString(In pbegin, In pend);
+};
+
+template <>
+struct ustring::SequenceToString<Glib::ustring::iterator,gunichar> : public std::string
+{
+ SequenceToString(Glib::ustring::iterator pbegin, Glib::ustring::iterator pend);
+};
+
+template <>
+struct ustring::SequenceToString<Glib::ustring::const_iterator,gunichar> : public std::string
+{
+ SequenceToString(Glib::ustring::const_iterator pbegin, Glib::ustring::const_iterator pend);
+};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/** Stream input operator.
+ * @relates Glib::ustring
+ * @throw Glib::ConvertError
+ */
+std::istream& operator>>(std::istream& is, Glib::ustring& utf8_string);
+
+/** Stream output operator.
+ * @relates Glib::ustring
+ * @throw Glib::ConvertError
+ */
+std::ostream& operator<<(std::ostream& os, const Glib::ustring& utf8_string);
+
+
+/***************************************************************************/
+/* Inline implementation */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/**** Glib::ustring_Iterator<> *********************************************/
+
+template <class T> inline
+ustring_Iterator<T>::ustring_Iterator(T pos)
+:
+ pos_ (pos)
+{}
+
+template <class T> inline
+T ustring_Iterator<T>::base() const
+{
+ return pos_;
+}
+
+template <class T> inline
+ustring_Iterator<T>::ustring_Iterator()
+:
+ pos_ ()
+{}
+
+template <class T> inline
+ustring_Iterator<T>::ustring_Iterator(const ustring_Iterator<std::string::iterator>& other)
+:
+ pos_ (other.base())
+{}
+
+template <class T> inline
+typename ustring_Iterator<T>::value_type ustring_Iterator<T>::operator*() const
+{
+ return Glib::get_unichar_from_std_iterator(pos_);
+}
+
+template <class T> inline
+ustring_Iterator<T>& ustring_Iterator<T>::operator++()
+{
+ pos_ += g_utf8_skip[static_cast<unsigned char>(*pos_)];
+ return *this;
+}
+
+template <class T> inline
+const ustring_Iterator<T> ustring_Iterator<T>::operator++(int)
+{
+ const ustring_Iterator<T> tmp (*this);
+ this->operator++();
+ return tmp;
+}
+
+template <class T> inline
+ustring_Iterator<T>& ustring_Iterator<T>::operator--()
+{
+ do { --pos_; } while((*pos_ & '\xC0') == '\x80');
+ return *this;
+}
+
+template <class T> inline
+const ustring_Iterator<T> ustring_Iterator<T>::operator--(int)
+{
+ const ustring_Iterator<T> tmp (*this);
+ this->operator--();
+ return tmp;
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/** @relates Glib::ustring_Iterator */
+template <class T> inline
+bool operator==(const ustring_Iterator<T>& lhs, const ustring_Iterator<T>& rhs)
+{
+ return (lhs.base() == rhs.base());
+}
+
+/** @relates Glib::ustring_Iterator */
+template <class T> inline
+bool operator!=(const ustring_Iterator<T>& lhs, const ustring_Iterator<T>& rhs)
+{
+ return (lhs.base() != rhs.base());
+}
+
+/** @relates Glib::ustring_Iterator */
+template <class T> inline
+bool operator<(const ustring_Iterator<T>& lhs, const ustring_Iterator<T>& rhs)
+{
+ return (lhs.base() < rhs.base());
+}
+
+/** @relates Glib::ustring_Iterator */
+template <class T> inline
+bool operator>(const ustring_Iterator<T>& lhs, const ustring_Iterator<T>& rhs)
+{
+ return (lhs.base() > rhs.base());
+}
+
+/** @relates Glib::ustring_Iterator */
+template <class T> inline
+bool operator<=(const ustring_Iterator<T>& lhs, const ustring_Iterator<T>& rhs)
+{
+ return (lhs.base() <= rhs.base());
+}
+
+/** @relates Glib::ustring_Iterator */
+template <class T> inline
+bool operator>=(const ustring_Iterator<T>& lhs, const ustring_Iterator<T>& rhs)
+{
+ return (lhs.base() >= rhs.base());
+}
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/**** Glib::ustring::SequenceToString **************************************/
+
+template <class In>
+ustring::SequenceToString<In,char>::SequenceToString(In pbegin, In pend)
+:
+ std::string(pbegin, pend)
+{}
+
+template <class In>
+ustring::SequenceToString<In,gunichar>::SequenceToString(In pbegin, In pend)
+{
+ char utf8_buf[6]; // stores a single UTF-8 character
+
+ for(; pbegin != pend; ++pbegin)
+ {
+ const std::string::size_type utf8_len = g_unichar_to_utf8(*pbegin, utf8_buf);
+ this->append(utf8_buf, utf8_len);
+ }
+}
+
+
+/**** Glib::ustring ********************************************************/
+
+template <class In>
+ustring::ustring(In pbegin, In pend)
+:
+ string_ (Glib::ustring::SequenceToString<In>(pbegin, pend))
+{}
+
+template <class In>
+ustring& ustring::assign(In pbegin, In pend)
+{
+ Glib::ustring::SequenceToString<In> temp_string (pbegin, pend);
+ string_.swap(temp_string); // constant-time operation
+ return *this;
+}
+
+template <class In>
+ustring& ustring::append(In pbegin, In pend)
+{
+ string_.append(Glib::ustring::SequenceToString<In>(pbegin, pend));
+ return *this;
+}
+
+template <class In>
+void ustring::insert(ustring::iterator p, In pbegin, In pend)
+{
+ string_.insert(p.base(), Glib::ustring::SequenceToString<In>(pbegin, pend));
+}
+
+template <class In>
+ustring& ustring::replace(ustring::iterator pbegin, ustring::iterator pend, In pbegin2, In pend2)
+{
+ string_.replace(
+ pbegin.base(), pend.base(),
+ Glib::ustring::SequenceToString<In>(pbegin2, pend2));
+ return *this;
+}
+
+// The ustring methods substr() and operator std::string() are inline,
+// so that the compiler has a fair chance to optimize the copy ctor away.
+
+inline
+ustring ustring::substr(ustring::size_type i, ustring::size_type n) const
+{
+ return ustring(*this, i, n);
+}
+
+inline
+ustring::operator std::string() const
+{
+ return string_;
+}
+
+inline
+const std::string& ustring::raw() const
+{
+ return string_;
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/** @relates Glib::ustring */
+inline
+void swap(ustring& lhs, ustring& rhs)
+{
+ lhs.swap(rhs);
+}
+
+
+/**** Glib::ustring -- comparison operators ********************************/
+
+/** @relates Glib::ustring */
+inline bool operator==(const ustring& lhs, const ustring& rhs)
+ { return (lhs.compare(rhs) == 0); }
+
+/** @relates Glib::ustring */
+inline bool operator==(const ustring& lhs, const char* rhs)
+ { return (lhs.compare(rhs) == 0); }
+
+/** @relates Glib::ustring */
+inline bool operator==(const char* lhs, const ustring& rhs)
+ { return (rhs.compare(lhs) == 0); }
+
+
+/** @relates Glib::ustring */
+inline bool operator!=(const ustring& lhs, const ustring& rhs)
+ { return (lhs.compare(rhs) != 0); }
+
+/** @relates Glib::ustring */
+inline bool operator!=(const ustring& lhs, const char* rhs)
+ { return (lhs.compare(rhs) != 0); }
+
+/** @relates Glib::ustring */
+inline bool operator!=(const char* lhs, const ustring& rhs)
+ { return (rhs.compare(lhs) != 0); }
+
+
+/** @relates Glib::ustring */
+inline bool operator<(const ustring& lhs, const ustring& rhs)
+ { return (lhs.compare(rhs) < 0); }
+
+/** @relates Glib::ustring */
+inline bool operator<(const ustring& lhs, const char* rhs)
+ { return (lhs.compare(rhs) < 0); }
+
+/** @relates Glib::ustring */
+inline bool operator<(const char* lhs, const ustring& rhs)
+ { return (rhs.compare(lhs) > 0); }
+
+
+/** @relates Glib::ustring */
+inline bool operator>(const ustring& lhs, const ustring& rhs)
+ { return (lhs.compare(rhs) > 0); }
+
+/** @relates Glib::ustring */
+inline bool operator>(const ustring& lhs, const char* rhs)
+ { return (lhs.compare(rhs) > 0); }
+
+/** @relates Glib::ustring */
+inline bool operator>(const char* lhs, const ustring& rhs)
+ { return (rhs.compare(lhs) < 0); }
+
+
+/** @relates Glib::ustring */
+inline bool operator<=(const ustring& lhs, const ustring& rhs)
+ { return (lhs.compare(rhs) <= 0); }
+
+/** @relates Glib::ustring */
+inline bool operator<=(const ustring& lhs, const char* rhs)
+ { return (lhs.compare(rhs) <= 0); }
+
+/** @relates Glib::ustring */
+inline bool operator<=(const char* lhs, const ustring& rhs)
+ { return (rhs.compare(lhs) >= 0); }
+
+
+/** @relates Glib::ustring */
+inline bool operator>=(const ustring& lhs, const ustring& rhs)
+ { return (lhs.compare(rhs) >= 0); }
+
+/** @relates Glib::ustring */
+inline bool operator>=(const ustring& lhs, const char* rhs)
+ { return (lhs.compare(rhs) >= 0); }
+
+/** @relates Glib::ustring */
+inline bool operator>=(const char* lhs, const ustring& rhs)
+ { return (rhs.compare(lhs) <= 0); }
+
+
+/**** Glib::ustring -- concatenation operators *****************************/
+
+/** @relates Glib::ustring */
+inline ustring operator+(const ustring& lhs, const ustring& rhs)
+ { return ustring(lhs) += rhs; }
+
+/** @relates Glib::ustring */
+inline ustring operator+(const ustring& lhs, const char* rhs)
+ { return ustring(lhs) += rhs; }
+
+/** @relates Glib::ustring */
+inline ustring operator+(const char* lhs, const ustring& rhs)
+ { return ustring(lhs) += rhs; }
+
+/** @relates Glib::ustring */
+inline ustring operator+(const ustring& lhs, gunichar rhs)
+ { return ustring(lhs) += rhs; }
+
+/** @relates Glib::ustring */
+inline ustring operator+(gunichar lhs, const ustring& rhs)
+ { return ustring(1, lhs) += rhs; }
+
+/** @relates Glib::ustring */
+inline ustring operator+(const ustring& lhs, char rhs)
+ { return ustring(lhs) += rhs; }
+
+/** @relates Glib::ustring */
+inline ustring operator+(char lhs, const ustring& rhs)
+ { return ustring(1, lhs) += rhs; }
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_USTRING_H */
+
diff --git a/glib/glibmm/utility.cc b/glib/glibmm/utility.cc
new file mode 100644
index 00000000..f415bcb8
--- /dev/null
+++ b/glib/glibmm/utility.cc
@@ -0,0 +1,40 @@
+// -*- c++ -*-
+
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/utility.h>
+#include <glib/gstrfuncs.h>
+
+
+void Glib::append_canonical_typename(std::string& dest, const char* type_name)
+{
+ const std::string::size_type offset = dest.size();
+ dest += type_name;
+
+ std::string::iterator p = dest.begin() + offset;
+ const std::string::iterator pend = dest.end();
+
+ for(; p != pend; ++p)
+ {
+ if(!(g_ascii_isalnum(*p) || *p == '_' || *p == '-'))
+ *p = '+';
+ }
+}
+
diff --git a/glib/glibmm/utility.h b/glib/glibmm/utility.h
new file mode 100644
index 00000000..74a07a10
--- /dev/null
+++ b/glib/glibmm/utility.h
@@ -0,0 +1,119 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_UTILITY_H
+#define _GLIBMM_UTILITY_H
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gmacros.h>
+#include <glibmm/ustring.h>
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+extern "C" void g_free(void*);
+
+
+/* Occasionally, a struct variable has to be initialized after its definition,
+ * i.e. when using structs as class member data. For convenience, the macro
+ * GLIBMM_INITIALIZE_STRUCT(Var, Type) is provided. It even avoids creating
+ * a temporary if the compiler is GCC.
+ */
+#if ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__)
+
+#define GLIBMM_INITIALIZE_STRUCT(Var, Type) __builtin_bzero(&Var, sizeof(Type))
+
+#else
+
+#define GLIBMM_INITIALIZE_STRUCT(Var, Type) \
+ G_STMT_START{ \
+ Type const initializer = { 0, }; \
+ Var = initializer; \
+ }G_STMT_END
+
+#endif /* ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__) */
+
+
+namespace Glib
+{
+
+// These are used by gtkmmproc-generated type conversions:
+
+// Helper to deal with memory allocated
+// by GLib functions in an exception-safe manner.
+template <typename T>
+class ScopedPtr
+{
+private:
+ T* ptr_;
+ ScopedPtr(const ScopedPtr<T>&);
+ ScopedPtr<T>& operator=(const ScopedPtr<T>&);
+
+public:
+ ScopedPtr() : ptr_ (0) {}
+ explicit ScopedPtr(T* ptr) : ptr_ (ptr) {}
+ ~ScopedPtr() { g_free(ptr_); }
+ T* get() const { return ptr_; }
+ T** addr() { return &ptr_; }
+};
+
+// Removes the const nature of a ptr
+template <class T>
+inline T* unconst(const T* t)
+ { return const_cast<T*>(t); }
+
+// Convert const gchar* to ustring, while treating NULL as empty string.
+inline
+Glib::ustring convert_const_gchar_ptr_to_ustring(const char* str)
+{
+ return (str) ? Glib::ustring(str) : Glib::ustring();
+}
+
+// Convert const gchar* to std::string, while treating NULL as empty string.
+inline
+std::string convert_const_gchar_ptr_to_stdstring(const char* str)
+{
+ return (str) ? std::string(str) : std::string();
+}
+
+// Convert a non-const gchar* return value to ustring, freeing it too.
+inline
+Glib::ustring convert_return_gchar_ptr_to_ustring(char* str)
+{
+ return (str) ? Glib::ustring(Glib::ScopedPtr<char>(str).get())
+ : Glib::ustring();
+}
+
+// Convert a non-const gchar* return value to std::string, freeing it too.
+inline
+std::string convert_return_gchar_ptr_to_stdstring(char* str)
+{
+ return (str) ? std::string(Glib::ScopedPtr<char>(str).get())
+ : std::string();
+}
+
+// Append type_name to dest, while replacing special characters with '+'.
+void append_canonical_typename(std::string& dest, const char* type_name);
+
+} // namespace Glib
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+#endif /* _GLIBMM_UTILITY_H */
+
diff --git a/glib/glibmm/value.cc b/glib/glibmm/value.cc
new file mode 100644
index 00000000..adb3e902
--- /dev/null
+++ b/glib/glibmm/value.cc
@@ -0,0 +1,242 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/value.h>
+#include <glibmm/objectbase.h>
+#include <glibmm/utility.h>
+#include <glibmm/wrap.h>
+
+
+namespace Glib
+{
+
+/**** Glib::ValueBase ******************************************************/
+
+ValueBase::ValueBase()
+{
+ GLIBMM_INITIALIZE_STRUCT(gobject_, GValue);
+}
+
+void ValueBase::init(GType type)
+{
+ g_value_init(&gobject_, type);
+}
+
+ValueBase::ValueBase(const ValueBase& other)
+{
+ GLIBMM_INITIALIZE_STRUCT(gobject_, GValue);
+
+ g_value_init(&gobject_, G_VALUE_TYPE(&other.gobject_));
+ g_value_copy(&other.gobject_, &gobject_);
+}
+
+ValueBase& ValueBase::operator=(const ValueBase& other)
+{
+ // g_value_copy() prevents self-assignment and deletes the destination.
+ g_value_copy(&other.gobject_, &gobject_);
+ return *this;
+}
+
+ValueBase::~ValueBase()
+{
+ g_value_unset(&gobject_);
+}
+
+void ValueBase::reset()
+{
+ g_value_reset(&gobject_);
+}
+
+
+/**** Glib::ValueBase_Boxed ************************************************/
+
+// static
+GType ValueBase_Boxed::value_type()
+{
+ return G_TYPE_BOXED;
+}
+
+void ValueBase_Boxed::set_boxed(const void* data)
+{
+ g_value_set_boxed(&gobject_, data);
+}
+
+void* ValueBase_Boxed::get_boxed() const
+{
+ return g_value_get_boxed(&gobject_);
+}
+
+GParamSpec* ValueBase_Boxed::create_param_spec(const Glib::ustring& name) const
+{
+ return g_param_spec_boxed(
+ name.c_str(), 0, 0, G_VALUE_TYPE(&gobject_),
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+
+/**** Glib::ValueBase_Object ***********************************************/
+
+// static
+GType ValueBase_Object::value_type()
+{
+ return G_TYPE_OBJECT;
+}
+
+void ValueBase_Object::set_object(Glib::ObjectBase* data)
+{
+ g_value_set_object(&gobject_, (data) ? data->gobj() : 0);
+}
+
+Glib::ObjectBase* ValueBase_Object::get_object() const
+{
+ GObject *const data = static_cast<GObject*>(g_value_get_object(&gobject_));
+ return Glib::wrap_auto(data, false);
+}
+
+Glib::RefPtr<Glib::ObjectBase> ValueBase_Object::get_object_copy() const
+{
+ GObject *const data = static_cast<GObject*>(g_value_get_object(&gobject_));
+ return Glib::RefPtr<Glib::ObjectBase>(Glib::wrap_auto(data, true));
+}
+
+GParamSpec* ValueBase_Object::create_param_spec(const Glib::ustring& name) const
+{
+ // Glib::Value_Pointer<> derives from Glib::ValueBase_Object, because
+ // we don't know beforehand whether a certain type is derived from
+ // Glib::Object or not. To keep create_param_spec() out of the template
+ // struggle, we dispatch here at runtime.
+
+ if(G_VALUE_HOLDS_OBJECT(&gobject_))
+ {
+ return g_param_spec_object(
+ name.c_str(), 0, 0, G_VALUE_TYPE(&gobject_),
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+ }
+ else
+ {
+ g_return_val_if_fail(G_VALUE_HOLDS_POINTER(&gobject_), 0);
+
+ return g_param_spec_pointer(
+ name.c_str(), 0, 0,
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+ }
+}
+
+
+/**** Glib::ValueBase_Enum *************************************************/
+
+// static
+GType ValueBase_Enum::value_type()
+{
+ return G_TYPE_ENUM;
+}
+
+void ValueBase_Enum::set_enum(int data)
+{
+ g_value_set_enum(&gobject_, data);
+}
+
+int ValueBase_Enum::get_enum() const
+{
+ return g_value_get_enum(&gobject_);
+}
+
+GParamSpec* ValueBase_Enum::create_param_spec(const Glib::ustring& name) const
+{
+ return g_param_spec_enum(
+ name.c_str(), 0, 0,
+ G_VALUE_TYPE(&gobject_), g_value_get_enum(&gobject_),
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+
+/**** Glib::ValueBase_Flags ************************************************/
+
+// static
+GType ValueBase_Flags::value_type()
+{
+ return G_TYPE_FLAGS;
+}
+
+void ValueBase_Flags::set_flags(unsigned int data)
+{
+ g_value_set_flags(&gobject_, data);
+}
+
+unsigned int ValueBase_Flags::get_flags() const
+{
+ return g_value_get_flags(&gobject_);
+}
+
+GParamSpec* ValueBase_Flags::create_param_spec(const Glib::ustring& name) const
+{
+ return g_param_spec_flags(
+ name.c_str(), 0, 0,
+ G_VALUE_TYPE(&gobject_), g_value_get_flags(&gobject_),
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+
+/**** Glib::ValueBase_String ***********************************************/
+
+// static
+GType ValueBase_String::value_type()
+{
+ return G_TYPE_STRING;
+}
+
+void ValueBase_String::set_cstring(const char* data)
+{
+ g_value_set_string(&gobject_, data);
+}
+
+const char* ValueBase_String::get_cstring() const
+{
+ if(const char *const data = g_value_get_string(&gobject_))
+ return data;
+ else
+ return "";
+}
+
+GParamSpec* ValueBase_String::create_param_spec(const Glib::ustring& name) const
+{
+ return g_param_spec_string(
+ name.c_str(), 0, 0, get_cstring(),
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+
+
+/**** Glib::Value<std::string> *********************************************/
+
+void Value<std::string>::set(const std::string& data)
+{
+ g_value_set_string(&gobject_, data.c_str());
+}
+
+
+/**** Glib::Value<Glib::ustring> *******************************************/
+
+void Value<Glib::ustring>::set(const Glib::ustring& data)
+{
+ g_value_set_string(&gobject_, data.c_str());
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/value.h b/glib/glibmm/value.h
new file mode 100644
index 00000000..be2c2adb
--- /dev/null
+++ b/glib/glibmm/value.h
@@ -0,0 +1,312 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_VALUE_H
+#define _GLIBMM_VALUE_H
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib-object.h>
+#include <glibmm/refptr.h>
+#include <glibmm/ustring.h>
+
+
+namespace Glib
+{
+
+class ObjectBase;
+class Object;
+
+/** @defgroup glibmmValue Generic Values
+ *
+ * Glib::Value<> is specialized for almost any type used within
+ * the gtkmm libraries.
+ *
+ * - Basic types like <tt>int</tt>, <tt>char</tt>, <tt>bool</tt>, etc., also <tt>void*</tt>.
+ * - Glib::ustring and std::string.
+ * - Pointers to classes derived from Glib::Object.
+ * - Glib::RefPtr<> pointer types, which are assumed to be Glib::Object pointers.
+ * - All flags and enum types used within the gtkmm libraries.
+ *
+ * If a type doesn't fit into any of these categories, then a generic
+ * implementation for custom types will be used. The requirements imposed
+ * on custom types are described in the Glib::Value class documentation.
+ */
+
+/**
+ * @ingroup glibmmValue
+ */
+class ValueBase
+{
+public:
+ /** Initializes the GValue, but without a type. You have to
+ * call init() before using the set(), get(), or reset() methods.
+ */
+ ValueBase();
+
+ ValueBase(const ValueBase& other);
+ ValueBase& operator=(const ValueBase& other);
+
+ ~ValueBase();
+
+ /** Setup the GValue for storing the specified @a type.
+ * The contents will be initialized to the default value for this type.
+ * Note that init() should never be called twice.
+ *
+ * init() is not implemented as constructor, to avoid the necessity
+ * to implement a forward constructor in each derived class.
+ */
+ void init(GType type);
+
+ /** Reset contents to the default value of its type.
+ */
+ void reset();
+
+ GValue* gobj() { return &gobject_; }
+ const GValue* gobj() const { return &gobject_; }
+
+protected:
+ GValue gobject_;
+};
+
+
+/**
+ * @ingroup glibmmValue
+ */
+class ValueBase_Boxed : public ValueBase
+{
+public:
+ static GType value_type() G_GNUC_CONST;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GParamSpec* create_param_spec(const Glib::ustring& name) const;
+#endif
+
+protected:
+ void set_boxed(const void* data);
+ void* get_boxed() const; // doesn't copy
+};
+
+
+/**
+ * @ingroup glibmmValue
+ */
+class ValueBase_Object : public ValueBase
+{
+public:
+ static GType value_type() G_GNUC_CONST;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GParamSpec* create_param_spec(const Glib::ustring& name) const;
+#endif
+
+protected:
+ void set_object(Glib::ObjectBase* data);
+ Glib::ObjectBase* get_object() const;
+ Glib::RefPtr<Glib::ObjectBase> get_object_copy() const;
+};
+
+
+/**
+ * @ingroup glibmmValue
+ */
+class ValueBase_Enum : public ValueBase
+{
+public:
+ typedef gint CType;
+ static GType value_type() G_GNUC_CONST;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GParamSpec* create_param_spec(const Glib::ustring& name) const;
+#endif
+
+protected:
+ void set_enum(int data);
+ int get_enum() const;
+};
+
+
+/**
+ * @ingroup glibmmValue
+ */
+class ValueBase_Flags : public ValueBase
+{
+public:
+ typedef guint CType;
+ static GType value_type() G_GNUC_CONST;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GParamSpec* create_param_spec(const Glib::ustring& name) const;
+#endif
+
+protected:
+ void set_flags(unsigned int data);
+ unsigned int get_flags() const;
+};
+
+
+/**
+ * @ingroup glibmmValue
+ */
+class ValueBase_String : public ValueBase
+{
+public:
+ typedef const gchar* CType;
+ static GType value_type() G_GNUC_CONST;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GParamSpec* create_param_spec(const Glib::ustring& name) const;
+#endif
+
+protected:
+ void set_cstring(const char* data);
+ const char* get_cstring() const; // never returns 0
+};
+
+} // namespace Glib
+
+
+/* Include generic Glib::Value<> template, before any specializations:
+ */
+#define _GLIBMM_VALUE_H_INCLUDE_VALUE_CUSTOM_H
+#include <glibmm/value_custom.h>
+#undef _GLIBMM_VALUE_H_INCLUDE_VALUE_CUSTOM_H
+
+
+namespace Glib
+{
+
+/**
+ * @ingroup glibmmValue
+ */
+template <class T>
+class Value_Boxed : public ValueBase_Boxed
+{
+public:
+ typedef T CppType;
+ typedef typename T::BaseObjectType* CType;
+
+ static GType value_type() { return T::get_type(); }
+
+ void set(const CppType& data) { set_boxed(data.gobj()); }
+ CppType get() const { return CppType(static_cast<CType>(get_boxed())); }
+};
+
+
+/** Partial specialization for RefPtr<> to Glib::Object.
+ * @ingroup glibmmValue
+ */
+template <class T>
+class Value< Glib::RefPtr<T> > : public ValueBase_Object
+{
+public:
+ typedef Glib::RefPtr<T> CppType;
+ typedef typename T::BaseObjectType* CType;
+
+ static GType value_type() { return T::get_base_type(); }
+
+ void set(const CppType& data) { set_object(data.operator->()); }
+ CppType get() const { return Glib::RefPtr<T>::cast_dynamic(get_object_copy()); }
+};
+
+/** Partial specialization for RefPtr<> to const Glib::Object.
+ * @ingroup glibmmValue
+ */
+template <class T>
+class Value< Glib::RefPtr<const T> > : public ValueBase_Object
+{
+public:
+ typedef Glib::RefPtr<const T> CppType;
+ typedef typename T::BaseObjectType* CType;
+
+ static GType value_type() { return T::get_base_type(); }
+
+ void set(const CppType& data) { set_object(const_cast<T*>(data.operator->())); }
+ CppType get() const { return Glib::RefPtr<T>::cast_dynamic(get_object_copy()); }
+};
+
+} // namespace Glib
+
+
+/* Include generated specializations of Glib::Value<> for fundamental types:
+ */
+#define _GLIBMM_VALUE_H_INCLUDE_VALUE_BASICTYPES_H
+#include <glibmm/value_basictypes.h>
+#undef _GLIBMM_VALUE_H_INCLUDE_VALUE_BASICTYPES_H
+
+
+namespace Glib
+{
+
+/** Specialization for strings.
+ * @ingroup glibmmValue
+ */
+template <>
+class Value<std::string> : public ValueBase_String
+{
+public:
+ typedef std::string CppType;
+
+ void set(const std::string& data);
+ std::string get() const { return get_cstring(); }
+};
+
+/** Specialization for UTF-8 strings.
+ * @ingroup glibmmValue
+ */
+template <>
+class Value<Glib::ustring> : public ValueBase_String
+{
+public:
+ typedef Glib::ustring CppType;
+
+ void set(const Glib::ustring& data);
+ Glib::ustring get() const { return get_cstring(); }
+};
+
+
+/** Base class of Glib::Value<T> specializations for enum types.
+ * @ingroup glibmmValue
+ */
+template <class T>
+class Value_Enum : public ValueBase_Enum
+{
+public:
+ typedef T CppType;
+
+ void set(CppType data) { set_enum(data); }
+ CppType get() const { return CppType(get_enum()); }
+};
+
+/** Base class of Glib::Value<T> specializations for flags types.
+ * @ingroup glibmmValue
+ */
+template <class T>
+class Value_Flags : public ValueBase_Flags
+{
+public:
+ typedef T CppType;
+
+ void set(CppType data) { set_flags(data); }
+ CppType get() const { return CppType(get_flags()); }
+};
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_VALUE_H */
+
diff --git a/glib/glibmm/value_custom.cc b/glib/glibmm/value_custom.cc
new file mode 100644
index 00000000..bb0afcbc
--- /dev/null
+++ b/glib/glibmm/value_custom.cc
@@ -0,0 +1,144 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/value.h>
+#include <glibmm/utility.h>
+#include <glib.h>
+
+
+namespace
+{
+
+void warn_already_registered(const char* location, const std::string& full_name)
+{
+ g_warning("file %s: (%s): The type name `%s' has been registered already.\n"
+ "This is not supposed to happen -- please send a mail with detailed "
+ "information about your platform to gtkmm-list@gnome.org. Thanks.\n",
+ __FILE__, location, full_name.c_str());
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+GType custom_boxed_type_register(const char* type_name,
+ ValueInitFunc init_func,
+ ValueFreeFunc free_func,
+ ValueCopyFunc copy_func)
+{
+ std::string full_name ("glibmm__CustomBoxed_");
+ Glib::append_canonical_typename(full_name, type_name);
+
+ // Templates of the same type _might_ be duplicated when instantiated in
+ // multiple translation units -- I'm not sure whether this is true. If the
+ // static custom_type_ variable in Value<> is duplicated, then the type
+ // would be registered more than once.
+ //
+ // Lookup the type name to see whether this scenario actually happens.
+ // If this turns out to be common behaviour on some platform the warning
+ // should be removed.
+
+ if(const GType existing_type = g_type_from_name(full_name.c_str()))
+ {
+ warn_already_registered("Glib::custom_boxed_type_register", full_name);
+ return existing_type;
+ }
+
+ // Via GTypeValueTable, we can teach GValue how to instantiate,
+ // destroy, and copy arbitrary objects of the C++ type.
+
+ const GTypeValueTable value_table =
+ {
+ init_func,
+ free_func,
+ copy_func,
+ 0, // value_peek_pointer
+ 0, // collect_format
+ 0, // collect_value
+ 0, // lcopy_format
+ 0, // lcopy_value
+ };
+
+ const GTypeInfo type_info =
+ {
+ 0, // class_size
+ 0, // base_init
+ 0, // base_finalize
+ 0, // class_init_func
+ 0, // class_finalize
+ 0, // class_data
+ 0, // instance_size
+ 0, // n_preallocs
+ 0, // instance_init
+ &value_table,
+ };
+
+ // Don't use g_boxed_type_register_static(), because that wouldn't allow
+ // for a non-NULL default value. The implementation of g_boxed_copy() will
+ // use our custom GTypeValueTable automatically.
+
+ return g_type_register_static(G_TYPE_BOXED, full_name.c_str(), &type_info, GTypeFlags(0));
+}
+
+GType custom_pointer_type_register(const char* type_name)
+{
+ std::string full_name ("glibmm__CustomPointer_");
+ Glib::append_canonical_typename(full_name, type_name);
+
+ // Templates of the same type _might_ be duplicated when instantiated in
+ // multiple translation units -- I'm not sure whether this is true. If the
+ // static custom_type variable in Value<>::value_type_() is duplicated, then
+ // the type would be registered more than once.
+ //
+ // Lookup the type name to see whether this scenario actually happens.
+ // If this turns out to be common behaviour on some platform the warning
+ // should be removed.
+
+ if(const GType existing_type = g_type_from_name(full_name.c_str()))
+ {
+ warn_already_registered("Glib::custom_pointer_type_register", full_name);
+ return existing_type;
+ }
+
+ const GTypeInfo type_info =
+ {
+ 0, // class_size
+ 0, // base_init
+ 0, // base_finalize
+ 0, // class_init_func
+ 0, // class_finalize
+ 0, // class_data
+ 0, // instance_size
+ 0, // n_preallocs
+ 0, // instance_init
+ 0, // value_table
+ };
+
+ // We could probably use g_pointer_type_register_static(), but I want
+ // to keep this function symmetric to custom_boxed_type_register(). Also,
+ // g_pointer_type_register_static() would lookup the type name once again.
+
+ return g_type_register_static(G_TYPE_POINTER, full_name.c_str(), &type_info, GTypeFlags(0));
+}
+
+} // namespace Glib
+
diff --git a/glib/glibmm/value_custom.h b/glib/glibmm/value_custom.h
new file mode 100644
index 00000000..81221a09
--- /dev/null
+++ b/glib/glibmm/value_custom.h
@@ -0,0 +1,286 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#ifndef _GLIBMM_VALUE_H_INCLUDE_VALUE_CUSTOM_H
+#error "glibmm/value_custom.h cannot be included directly"
+#endif
+#endif
+
+#include <new>
+#include <typeinfo>
+#include <glibmmconfig.h>
+
+GTKMM_USING_STD(nothrow)
+
+
+namespace Glib
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+extern "C"
+{
+ typedef void (* ValueInitFunc) (GValue*);
+ typedef void (* ValueFreeFunc) (GValue*);
+ typedef void (* ValueCopyFunc) (const GValue*, GValue*);
+}
+
+/* When using Glib::Value<T> with custom types, each T will be registered
+ * as subtype of G_TYPE_BOXED, via this function. The type_name argument
+ * should be the C++ RTTI name.
+ */
+GType custom_boxed_type_register(const char* type_name,
+ ValueInitFunc init_func,
+ ValueFreeFunc free_func,
+ ValueCopyFunc copy_func);
+
+/* When using Glib::Value<T*> or Glib::Value<const T*> with custom types,
+ * each T* or const T* will be registered as a subtype of G_TYPE_POINTER,
+ * via this function. The type_name argument should be the C++ RTTI name.
+ */
+GType custom_pointer_type_register(const char* type_name);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+/**
+ * @ingroup glibmmValue
+ */
+template <class T, class PtrT>
+class Value_Pointer : public ValueBase_Object
+{
+public:
+ typedef PtrT CppType;
+ typedef void* CType;
+
+ static inline GType value_type() G_GNUC_CONST;
+
+ inline void set(CppType data);
+ inline CppType get() const;
+
+private:
+ inline
+ static GType value_type_(Glib::Object*);
+ static GType value_type_(void*);
+
+ inline void set_(CppType data, Glib::Object*);
+ inline void set_(CppType data, void*);
+
+ inline CppType get_(Glib::Object*) const;
+ inline CppType get_(void*) const;
+};
+
+
+/** Generic value implementation for custom types.
+ * @ingroup glibmmValue
+ * Any type to be used with this template must implement:
+ * - default constructor
+ * - copy constructor
+ * - assignment operator
+ * - destructor
+ *
+ * Compiler-generated implementations are OK, provided they do the
+ * right thing for the type. In other words, any type that works with
+ * <tt>std::vector</tt> will work with Glib::Value<>.
+ *
+ * @note None of the operations listed above are allowed to throw. If you
+ * cannot ensure that no exceptions will be thrown, consider using either
+ * a normal pointer or a smart pointer to hold your objects indirectly.
+ */
+template <class T>
+class Value : public ValueBase_Boxed
+{
+public:
+ typedef T CppType;
+ typedef T* CType;
+
+ static GType value_type() G_GNUC_CONST;
+
+ inline void set(const CppType& data);
+ inline CppType get() const;
+
+private:
+ static GType custom_type_;
+
+ static void value_init_func(GValue* value);
+ static void value_free_func(GValue* value);
+ static void value_copy_func(const GValue* src_value, GValue* dest_value);
+};
+
+
+/** Specialization for pointers to instances of any type.
+ * @ingroup glibmmValue
+ * No attempt is made to manage the memory associated with the
+ * pointer, you must take care of that yourself.
+ */
+template <class T>
+class Value<T*> : public Value_Pointer<T,T*>
+{};
+
+/** Specialization for pointers to const instances of any type.
+ * @ingroup glibmmValue
+ * No attempt is made to manage the memory associated with the
+ * pointer, you must take care of that yourself.
+ */
+template <class T>
+class Value<const T*> : public Value_Pointer<T,const T*>
+{};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/**** Glib::Value_Pointer<T, PtrT> *****************************************/
+
+/** Implementation for Glib::Object pointers **/
+
+// static
+template <class T, class PtrT> inline
+GType Value_Pointer<T,PtrT>::value_type_(Glib::Object*)
+{
+ return T::get_base_type();
+}
+
+template <class T, class PtrT> inline
+void Value_Pointer<T,PtrT>::set_(PtrT data, Glib::Object*)
+{
+ set_object(const_cast<T*>(data));
+}
+
+template <class T, class PtrT> inline
+PtrT Value_Pointer<T,PtrT>::get_(Glib::Object*) const
+{
+ return dynamic_cast<T*>(get_object());
+}
+
+/** Implementation for custom pointers **/
+
+// static
+template <class T, class PtrT>
+GType Value_Pointer<T,PtrT>::value_type_(void*)
+{
+ static GType custom_type = 0;
+
+ if(!custom_type)
+ custom_type = Glib::custom_pointer_type_register(typeid(PtrT).name());
+
+ return custom_type;
+}
+
+template <class T, class PtrT> inline
+void Value_Pointer<T,PtrT>::set_(PtrT data, void*)
+{
+ gobject_.data[0].v_pointer = const_cast<T*>(data);
+}
+
+template <class T, class PtrT> inline
+PtrT Value_Pointer<T,PtrT>::get_(void*) const
+{
+ return static_cast<T*>(gobject_.data[0].v_pointer);
+}
+
+/** Public forwarding interface **/
+
+// static
+template <class T, class PtrT> inline
+GType Value_Pointer<T,PtrT>::value_type()
+{
+ // Dispatch to the specific value_type_() overload.
+ return Value_Pointer<T,PtrT>::value_type_(static_cast<T*>(0));
+}
+
+template <class T, class PtrT> inline
+void Value_Pointer<T,PtrT>::set(PtrT data)
+{
+ // Dispatch to the specific set_() overload.
+ this->set_(data, static_cast<T*>(0));
+}
+
+template <class T, class PtrT> inline
+PtrT Value_Pointer<T,PtrT>::get() const
+{
+ // Dispatch to the specific get_() overload.
+ return this->get_(static_cast<T*>(0));
+}
+
+
+/**** Glib::Value<T> *******************************************************/
+
+// Static data, specific to each template instantiation.
+template <class T>
+GType Value<T>::custom_type_ = 0;
+
+template <class T> inline
+void Value<T>::set(const typename Value<T>::CppType& data)
+{
+ // Assume the value is already default-initialized. See value_init_func().
+ *static_cast<T*>(gobject_.data[0].v_pointer) = data;
+}
+
+template <class T> inline
+typename Value<T>::CppType Value<T>::get() const
+{
+ // Assume the pointer is not NULL. See value_init_func().
+ return *static_cast<T*>(gobject_.data[0].v_pointer);
+}
+
+// static
+template <class T>
+GType Value<T>::value_type()
+{
+ if(!custom_type_)
+ {
+ custom_type_ = Glib::custom_boxed_type_register(
+ typeid(CppType).name(),
+ &Value<T>::value_init_func,
+ &Value<T>::value_free_func,
+ &Value<T>::value_copy_func);
+ }
+ return custom_type_;
+}
+
+// static
+template <class T>
+void Value<T>::value_init_func(GValue* value)
+{
+ // Never store a NULL pointer (unless we're out of memory).
+ value->data[0].v_pointer = new(std::nothrow) T();
+}
+
+// static
+template <class T>
+void Value<T>::value_free_func(GValue* value)
+{
+ delete static_cast<T*>(value->data[0].v_pointer);
+}
+
+// static
+template <class T>
+void Value<T>::value_copy_func(const GValue* src_value, GValue* dest_value)
+{
+ // Assume the source is not NULL. See value_init_func().
+ const T& source = *static_cast<T*>(src_value->data[0].v_pointer);
+ dest_value->data[0].v_pointer = new(std::nothrow) T(source);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
diff --git a/glib/glibmm/wrap.cc b/glib/glibmm/wrap.cc
new file mode 100644
index 00000000..0f6a5f95
--- /dev/null
+++ b/glib/glibmm/wrap.cc
@@ -0,0 +1,161 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* wrap.cc
+ *
+ * Copyright (C) 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib-object.h>
+#include <glib/gtypes.h>
+#include <glib/gmacros.h>
+
+#include <vector>
+#include <glibmm/object.h>
+#include <glibmm/quark.h>
+#include <glibmm/wrap.h>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(vector)
+
+
+namespace
+{
+
+// Although the new g_type_set_qdata() interface is used now, we still need
+// a table because we cannot assume that a function pointer fits into void*
+// on any platform. Nevertheless, indexing a vector costs almost nothing
+// compared to a map lookup.
+
+typedef std::vector<Glib::WrapNewFunction> WrapFuncTable;
+
+WrapFuncTable* wrap_func_table = 0;
+
+
+Glib::ObjectBase* create_new_wrapper(GObject* object)
+{
+ g_return_val_if_fail(wrap_func_table != 0, 0);
+
+ bool gtkmm_wrapper_already_deleted = (bool)g_object_get_qdata((GObject*)object, Glib::quark_cpp_wrapper_deleted_);
+ if(gtkmm_wrapper_already_deleted)
+ {
+ g_warning("Glib::create_new_wrapper: Attempted to create a 2nd C++ wrapper for a C instance whose C++ wrapper has been deleted.");
+ return 0;
+ }
+
+ // Traverse upwards through the inheritance hierarchy
+ // to find the most-specialized wrap_new() for this GType.
+ //
+ for(GType type = G_OBJECT_TYPE(object); type != 0; type = g_type_parent(type))
+ {
+ // Look up the wrap table index stored in the type's static data.
+ // If a wrap_new() has been registered for the type then call it.
+ //
+ if(const gpointer idx = g_type_get_qdata(type, Glib::quark_))
+ {
+ const Glib::WrapNewFunction func = (*wrap_func_table)[GPOINTER_TO_UINT(idx)];
+ return (*func)(object);
+ }
+ }
+
+ return 0;
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+void wrap_register_init()
+{
+ g_type_init();
+
+ if(!Glib::quark_)
+ {
+ Glib::quark_ = g_quark_from_static_string("glibmm__Glib::quark_");
+ Glib::quark_cpp_wrapper_deleted_ = g_quark_from_static_string("glibmm__Glib::quark_cpp_wrapper_deleted_");
+ }
+
+ if(!wrap_func_table)
+ {
+ // Make the first element a dummy so we can detect unregistered types.
+ // g_type_get_qdata() returns NULL if no data has been set up.
+ wrap_func_table = new WrapFuncTable(1);
+ }
+}
+
+void wrap_register_cleanup()
+{
+ if(wrap_func_table)
+ {
+ delete wrap_func_table;
+ wrap_func_table = 0;
+ }
+}
+
+// Register the unique wrap_new() function of a new C++ wrapper type.
+// The GType argument specifies the parent C type to wrap from.
+//
+void wrap_register(GType type, WrapNewFunction func)
+{
+ const guint idx = wrap_func_table->size();
+ wrap_func_table->push_back(func);
+
+ // Store the table index in the type's static data.
+ g_type_set_qdata(type, Glib::quark_, GUINT_TO_POINTER(idx));
+}
+
+// This is a factory function that converts any type to
+// its C++ wrapper instance by looking up a wrap_new() function in a map.
+//
+ObjectBase* wrap_auto(GObject* object, bool take_copy)
+{
+ if(!object)
+ return 0;
+
+ // Look up current C++ wrapper instance:
+ ObjectBase* pCppObject =
+ static_cast<ObjectBase*>(g_object_get_qdata(object, Glib::quark_));
+
+ if(!pCppObject)
+ {
+ // There's not already a wrapper: generate a new C++ instance.
+ pCppObject = create_new_wrapper(object);
+
+ if(!pCppObject)
+ {
+ g_warning("failed to wrap type of '%s'", G_OBJECT_TYPE_NAME(object));
+ return 0;
+ }
+ }
+
+ // take_copy=true is used where the GTK+ function doesn't do
+ // an extra ref for us, and always for plain struct members.
+ if(take_copy)
+ pCppObject->reference();
+
+ return pCppObject;
+}
+
+Glib::RefPtr<Object> wrap(GObject* object, bool take_copy /* = false */)
+{
+ return Glib::RefPtr<Object>(dynamic_cast<Object*>(wrap_auto(object, take_copy)));
+}
+
+} /* namespace Glib */
+
diff --git a/glib/glibmm/wrap.h b/glib/glibmm/wrap.h
new file mode 100644
index 00000000..1ebb175e
--- /dev/null
+++ b/glib/glibmm/wrap.h
@@ -0,0 +1,118 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_WRAP_H
+#define _GLIBMM_WRAP_H
+
+/* $Id$ */
+
+/* Copyright (C) 1998-2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib-object.h>
+#include <glibmm/refptr.h>
+
+
+namespace Glib
+{
+
+class ObjectBase;
+class Object;
+
+// Type of the per-class wrap_new() functions.
+typedef Glib::ObjectBase* (*WrapNewFunction) (GObject*);
+
+// Setup and free the structures used by wrap_register().
+// Both functions might be called more than once.
+void wrap_register_init();
+void wrap_register_cleanup();
+
+// Register a new type for auto allocation.
+void wrap_register(GType type, WrapNewFunction func);
+
+// Return the current C++ wrapper instance of the GObject,
+// or automatically generate a new wrapper if there's none.
+Glib::ObjectBase* wrap_auto(GObject* object, bool take_copy = false);
+
+// Get a C++ instance that wraps the C instance.
+// This always returns the same C++ instance for the same C instance.
+// Each wrapper has it's own override of Glib::wrap().
+// use take_copy = true when wrapping a struct member.
+// TODO: move to object.h ?
+/** @relates Glib::Object */
+Glib::RefPtr<Glib::Object> wrap(GObject* object, bool take_copy = false);
+
+
+/** Get the underlying C instance from the C++ instance. This is just
+ * like calling gobj(), but it does its own check for a NULL pointer.
+ */
+template <class T> inline
+typename T::BaseObjectType* unwrap(T* ptr)
+{
+ return (ptr) ? ptr->gobj() : 0;
+}
+
+/** Get the underlying C instance from the C++ instance. This is just
+ * like calling gobj(), but it does its own check for a NULL pointer.
+ */
+template <class T> inline
+const typename T::BaseObjectType* unwrap(const T* ptr)
+{
+ return (ptr) ? ptr->gobj() : 0;
+}
+
+/** Get the underlying C instance from the C++ instance. This is just
+ * like calling gobj(), but it does its own check for a NULL pointer.
+ */
+template <class T> inline
+typename T::BaseObjectType* unwrap(const Glib::RefPtr<T>& ptr)
+{
+ return (!ptr.is_null()) ? ptr->gobj() : 0;
+}
+
+/** Get the underlying C instance from the C++ instance. This is just
+ * like calling gobj(), but it does its own check for a NULL pointer.
+ */
+template <class T> inline
+const typename T::BaseObjectType* unwrap(const Glib::RefPtr<const T>& ptr)
+{
+ return (!ptr.is_null()) ? ptr->gobj() : 0;
+}
+
+/** Get the underlying C instance from the C++ instance and acquire a
+ * reference. This is just like calling gobj_copy(), but it does its own
+ * check for a NULL pointer.
+ */
+template <class T> inline
+typename T::BaseObjectType* unwrap_copy(const Glib::RefPtr<T>& ptr)
+{
+ return (!ptr.is_null()) ? ptr->gobj_copy() : 0;
+}
+
+/** Get the underlying C instance from the C++ instance and acquire a
+ * reference. This is just like calling gobj_copy(), but it does its own
+ * check for a NULL pointer.
+ */
+template <class T> inline
+const typename T::BaseObjectType* unwrap_copy(const Glib::RefPtr<const T>& ptr)
+{
+ return (!ptr.is_null()) ? ptr->gobj_copy() : 0;
+}
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_WRAP_H */
+
diff --git a/glib/glibmm/wrap_init.h b/glib/glibmm/wrap_init.h
new file mode 100644
index 00000000..63c8a1c8
--- /dev/null
+++ b/glib/glibmm/wrap_init.h
@@ -0,0 +1,38 @@
+// -*- c++ -*-
+#ifndef _GLIBMM_WRAP_INIT_H
+#define _GLIBMM_WRAP_INIT_H
+
+/* $Id$ */
+
+/* wrap_init.h
+ *
+ * Copyright 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/error.h>
+
+
+namespace Glib
+{
+
+void wrap_init();
+
+} // namespace Glib
+
+
+#endif /* _GLIBMM_WRAP_INIT_H */
+
diff --git a/glib/glibmmconfig.h.in b/glib/glibmmconfig.h.in
new file mode 100644
index 00000000..d0973ffe
--- /dev/null
+++ b/glib/glibmmconfig.h.in
@@ -0,0 +1,71 @@
+#ifndef _GLIBMM_CONFIG_H
+#define _GLIBMM_CONFIG_H 1
+
+/* version numbers */
+#undef GTKMM_MAJOR_VERSION
+#undef GTKMM_MINOR_VERSION
+#undef GTKMM_MICRO_VERSION
+
+// detect common platforms
+#if defined(_WIN32)
+// Win32 compilers have a lot of varation
+#if defined(_MSC_VER)
+#define GTKMM_MSC
+#define GTKMM_WIN32
+#define GLIBMM_DLL
+#elif defined(__CYGWIN__)
+#define GTKMM_GCC
+#elif defined(__MINGW32__)
+#define GTKMM_WIN32
+#define GTKMM_GCC
+#define GLIBMM_DLL
+#else
+#warning "Unknown architecture (send me gcc --dumpspecs or equiv)"
+#endif
+#else
+#define GTKMM_GCC
+#endif /* _WIN32 */
+
+#ifdef GTKMM_GCC
+/* compiler feature tests that are used during compile time and run-time
+ by gtk-- only. tests used by gdk-- and gtk-- should go into
+ gdk--config.h.in */
+#undef GTKMM_CXX_HAVE_MUTABLE
+#undef GTKMM_CXX_HAVE_NAMESPACES
+//#undef GTKMM_CXX_GAUB
+//#undef GTKMM_CXX_AMBIGUOUS_TEMPLATES
+#endif
+
+#ifdef GTKMM_MSC
+#define GTKMM_CXX_HAVE_MUTABLE
+#define GTKMM_CXX_HAVE_NAMESPACES
+#pragma warning (disable: 4786 4355 4800 4181)
+#endif
+
+#undef GTKMM_DEBUG_REFCOUNTING
+
+#undef GTKMM_HAVE_NAMESPACE_STD
+#undef GTKMM_HAVE_STD_ITERATOR_TRAITS
+#undef GTKMM_HAVE_SUN_REVERSE_ITERATOR
+#undef GTKMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+
+#ifndef GTKMM_HAVE_NAMESPACE_STD
+# define GTKMM_USING_STD(Symbol) namespace std { using ::Symbol; }
+#else
+# define GTKMM_USING_STD(Symbol) /* empty */
+#endif
+
+#ifdef GLIBMM_DLL
+#if defined(glibmm_COMPILATION) && defined(DLL_EXPORT)
+#define GLIBMM_API __declspec(dllexport)
+#elif !defined(glibmm_COMPILATION)
+#define GLIBMM_API __declspec(dllimport)
+#else
+#define GLIBMM_API
+#endif /* glibmm_COMPILATION - DLL_EXPORT */
+#else
+#define GLIBMM_API
+#endif /* GLIBMM_DLL */
+
+#endif /* _GLIBMM_CONFIG_H */
+
diff --git a/glib/src/.cvsignore b/glib/src/.cvsignore
new file mode 100644
index 00000000..64687970
--- /dev/null
+++ b/glib/src/.cvsignore
@@ -0,0 +1,4 @@
+.stamps
+Makefile
+Makefile.in
+
diff --git a/glib/src/Makefile.am b/glib/src/Makefile.am
new file mode 100644
index 00000000..97c6db81
--- /dev/null
+++ b/glib/src/Makefile.am
@@ -0,0 +1,21 @@
+## Copyright (c) 2002
+## The gtkmm development team.
+
+sublib_name = glibmm
+sublib_namespace = Glib
+files_defs = glib.defs glib_enums.defs glib_functions.defs gobject.defs gobject_enums.defs gobject_functions.defs gmodule_enums.defs gmodule_functions.defs
+
+include $(top_srcdir)/build_shared/Makefile_gensrc.am_fragment
+
+glibmm_files_m4 = signalproxy.h.m4 value_basictypes.cc.m4 value_basictypes.h.m4
+
+files_stamp += $(glibmm_files_m4:%.m4=$(gensrc_destdir)/%)
+EXTRA_DIST += $(glibmm_files_m4) template.macros.m4
+
+
+$(gensrc_destdir)/%.cc: %.cc.m4 template.macros.m4
+ $(M4) -I$(srcdir) $< >$@
+
+$(gensrc_destdir)/%.h: %.h.m4 template.macros.m4
+ $(M4) -I$(srcdir) $< >$@
+
diff --git a/glib/src/Makefile_list_of_hg.am_fragment b/glib/src/Makefile_list_of_hg.am_fragment
new file mode 100644
index 00000000..479d1947
--- /dev/null
+++ b/glib/src/Makefile_list_of_hg.am_fragment
@@ -0,0 +1,8 @@
+## This file is include by other Makefile.am files, using the automake
+## include feature. The include happens in Makefile.am, not Makefile.in
+## or Makefile, so it's like copy-and-pasting this into each of those
+## Makefile.am files.
+
+files_posix_hg =
+files_win32_hg =
+files_general_hg = convert.hg date.hg fileutils.hg iochannel.hg markup.hg module.hg shell.hg spawn.hg thread.hg unicode.hg
diff --git a/glib/src/convert.ccg b/glib/src/convert.ccg
new file mode 100644
index 00000000..9b972914
--- /dev/null
+++ b/glib/src/convert.ccg
@@ -0,0 +1,276 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gconvert.h>
+#include <glib/gmessages.h>
+#include <glib/gunicode.h>
+#include <glibmm/utility.h>
+
+
+namespace Glib
+{
+
+/**** Glib::IConv **********************************************************/
+
+IConv::IConv(const std::string& to_codeset, const std::string& from_codeset)
+:
+ gobject_ (g_iconv_open(to_codeset.c_str(), from_codeset.c_str()))
+{
+ if(gobject_ == reinterpret_cast<GIConv>(-1))
+ {
+ GError* error = 0;
+
+ // Abuse g_convert() to create a GError object. This may seem a weird
+ // thing to do, but it gives us consistently translated error messages
+ // at no further cost.
+ g_convert("", 0, to_codeset.c_str(), from_codeset.c_str(), 0, 0, &error);
+
+ // If this should ever fail we're fucked.
+ g_assert(error != 0);
+
+ Error::throw_exception(error);
+ }
+}
+
+IConv::IConv(GIConv gobject)
+:
+ gobject_ (gobject)
+{}
+
+IConv::~IConv()
+{
+ g_iconv_close(gobject_);
+}
+
+size_t IConv::iconv(char** inbuf, gsize* inbytes_left, char** outbuf, gsize* outbytes_left)
+{
+ return g_iconv(gobject_, inbuf, inbytes_left, outbuf, outbytes_left);
+}
+
+void IConv::reset()
+{
+ // Apparently iconv() on Solaris <= 7 segfaults if you pass in
+ // NULL for anything but inbuf; work around that. (NULL outbuf
+ // or NULL *outbuf is allowed by Unix98.)
+
+ char* outbuf = 0;
+ gsize inbytes_left = 0;
+ gsize outbytes_left = 0;
+
+ g_iconv(gobject_, 0, &inbytes_left, &outbuf, &outbytes_left);
+}
+
+std::string IConv::convert(const std::string& str)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_convert_with_iconv(
+ str.data(), str.size(), gobject_, 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get(), bytes_written);
+}
+
+
+/**** charset conversion functions *****************************************/
+
+bool get_charset()
+{
+ return g_get_charset(0);
+}
+
+bool get_charset(std::string& charset)
+{
+ const char* charset_cstr = 0;
+ const bool is_utf8 = g_get_charset(&charset_cstr);
+
+ charset = charset_cstr;
+ return is_utf8;
+}
+
+std::string convert(const std::string& str,
+ const std::string& to_codeset,
+ const std::string& from_codeset)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_convert(
+ str.data(), str.size(), to_codeset.c_str(), from_codeset.c_str(),
+ 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get(), bytes_written);
+}
+
+std::string convert_with_fallback(const std::string& str,
+ const std::string& to_codeset,
+ const std::string& from_codeset)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_convert_with_fallback(
+ str.data(), str.size(), to_codeset.c_str(), from_codeset.c_str(), 0,
+ 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get(), bytes_written);
+}
+
+std::string convert_with_fallback(const std::string& str,
+ const std::string& to_codeset,
+ const std::string& from_codeset,
+ const Glib::ustring& fallback)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_convert_with_fallback(
+ str.data(), str.size(), to_codeset.c_str(), from_codeset.c_str(),
+ const_cast<char*>(fallback.c_str()), 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get(), bytes_written);
+}
+
+Glib::ustring locale_to_utf8(const std::string& opsys_string)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_locale_to_utf8(
+ opsys_string.data(), opsys_string.size(), 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ const ScopedPtr<char> scoped_buf (buf);
+ return Glib::ustring(scoped_buf.get(), scoped_buf.get() + bytes_written);
+}
+
+std::string locale_from_utf8(const Glib::ustring& utf8_string)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_locale_from_utf8(
+ utf8_string.data(), utf8_string.bytes(), 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get(), bytes_written);
+}
+
+Glib::ustring filename_to_utf8(const std::string& opsys_string)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_filename_to_utf8(
+ opsys_string.data(), opsys_string.size(), 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ const ScopedPtr<char> scoped_buf (buf);
+ return Glib::ustring(scoped_buf.get(), scoped_buf.get() + bytes_written);
+}
+
+std::string filename_from_utf8(const Glib::ustring& utf8_string)
+{
+ gsize bytes_written = 0;
+ GError* error = 0;
+
+ char *const buf = g_filename_from_utf8(
+ utf8_string.data(), utf8_string.bytes(), 0, &bytes_written, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get(), bytes_written);
+}
+
+std::string filename_from_uri(const Glib::ustring& uri, Glib::ustring& hostname)
+{
+ char* hostname_buf = 0;
+ GError* error = 0;
+
+ char *const buf = g_filename_from_uri(uri.c_str(), &hostname_buf, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ // Let's take ownership at this point.
+ const ScopedPtr<char> scoped_buf (buf);
+
+ if(hostname_buf)
+ hostname = ScopedPtr<char>(hostname_buf).get();
+ else
+ hostname.erase();
+
+ return std::string(scoped_buf.get());
+}
+
+std::string filename_from_uri(const Glib::ustring& uri)
+{
+ GError* error = 0;
+ char *const buf = g_filename_from_uri(uri.c_str(), 0, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get());
+}
+
+Glib::ustring filename_to_uri(const std::string& filename, const Glib::ustring& hostname)
+{
+ GError* error = 0;
+ char *const buf = g_filename_to_uri(filename.c_str(), hostname.c_str(), &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return Glib::ustring(ScopedPtr<char>(buf).get());
+}
+
+Glib::ustring filename_to_uri(const std::string& filename)
+{
+ GError* error = 0;
+ char *const buf = g_filename_to_uri(filename.c_str(), 0, &error);
+
+ if(error)
+ Error::throw_exception(error);
+
+ return Glib::ustring(ScopedPtr<char>(buf).get());
+}
+
+} // namespace Glib
+
diff --git a/glib/src/convert.hg b/glib/src/convert.hg
new file mode 100644
index 00000000..c5735663
--- /dev/null
+++ b/glib/src/convert.hg
@@ -0,0 +1,236 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glib/gtypes.h> /* for gsize */
+
+#include <glibmm/error.h>
+#include <glibmm/ustring.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GIConv* GIConv; }
+#endif
+
+
+namespace Glib
+{
+
+/** @defgroup CharsetConv Character Set Conversion
+ * Utility functions for converting strings between different character sets.
+ * @{
+ */
+
+/** Exception class for charset conversion errors.
+ * Glib::convert() and friends throw a ConvertError exception if the charset
+ * conversion failed for some reason. When writing non-trivial applications
+ * you should always catch those errors, and then try to recover, or tell the
+ * user the input was invalid.
+ */
+_WRAP_GERROR(ConvertError, GConvertError, G_CONVERT_ERROR, NO_GTYPE)
+
+
+/** Thin %iconv() wrapper.
+ * glibmm provides Glib::convert() and Glib::locale_to_utf8() which
+ * are likely more convenient than the raw iconv wrappers. However,
+ * creating an IConv object once and using the convert() method could
+ * be useful when converting multiple times between the same charsets.
+ */
+class IConv
+{
+public:
+ /** Open new conversion descriptor.
+ * @param to_codeset Destination codeset.
+ * @param from_codeset %Source codeset.
+ * @throw Glib::ConvertError
+ */
+ IConv(const std::string& to_codeset, const std::string& from_codeset);
+
+ explicit IConv(GIConv gobject);
+
+ /** Close conversion descriptor.
+ */
+ ~IConv();
+
+ /** Same as the standard UNIX routine %iconv(), but may be implemented
+ * via libiconv on UNIX flavors that lack a native implementation. glibmm
+ * provides Glib::convert() and Glib::locale_to_utf8() which are likely
+ * more convenient than the raw iconv wrappers.
+ * @param inbuf Bytes to convert.
+ * @param inbytes_left In/out parameter, bytes remaining to convert in @a inbuf.
+ * @param outbuf Converted output bytes.
+ * @param outbytes_left In/out parameter, bytes available to fill in @a outbuf.
+ * @return Count of non-reversible conversions, or <tt>static_cast<size_t>(-1)</tt> on error.
+ */
+ size_t iconv(char** inbuf, gsize* inbytes_left, char** outbuf, gsize* outbytes_left);
+
+ /** Reset conversion descriptor to initial state.
+ * Same as <tt>iconv(0, 0, 0, 0)</tt>, but implemented slightly differently
+ * in order to work on Sun Solaris <= 7. It's also more obvious so you're
+ * encouraged to use it.
+ */
+ void reset();
+
+ /** Convert from one encoding to another.
+ * @param str The string to convert.
+ * @return The converted string.
+ * @throw Glib::ConvertError
+ */
+ std::string convert(const std::string& str);
+
+ GIConv gobj() { return gobject_; }
+
+private:
+ GIConv gobject_;
+
+ // noncopyable
+ IConv(const IConv&);
+ IConv& operator=(const IConv&);
+};
+
+
+/** Get the charset used by the current locale.
+ * @return Whether the current locale uses the UTF-8 charset.
+ */
+bool get_charset();
+
+/** Get the charset used by the current locale.
+ * @param charset Will be filled with the charset's name.
+ * @return Whether the current locale uses the UTF-8 charset.
+ */
+bool get_charset(std::string& charset);
+
+/** Convert from one encoding to another.
+ * @param str The string to convert.
+ * @param to_codeset Name of the target charset.
+ * @param from_codeset Name of the source charset.
+ * @return The converted string.
+ * @throw Glib::ConvertError
+ */
+std::string convert(const std::string& str,
+ const std::string& to_codeset,
+ const std::string& from_codeset);
+
+/** Converts a string from one character set to another, possibly including
+ * fallback sequences for characters not representable in the output.
+ * Characters not in the target encoding will be represented as Unicode
+ * escapes <tt>\\x{XXXX}</tt> or <tt>\\x{XXXXXX}</tt>.
+ * @param str The string to convert.
+ * @param to_codeset Name of the target charset.
+ * @param from_codeset Name of the source charset.
+ * @return The converted string.
+ * @throw Glib::ConvertError
+ */
+std::string convert_with_fallback(const std::string& str,
+ const std::string& to_codeset,
+ const std::string& from_codeset);
+
+/** Converts a string from one character set to another, possibly including
+ * fallback sequences for characters not representable in the output.
+ * @note It is not guaranteed that the specification for the fallback sequences
+ * in @a fallback will be honored. Some systems may do a approximate conversion
+ * from @a from_codeset to @a to_codeset in their iconv() functions, in which
+ * case Glib will simply return that approximate conversion.
+ *
+ * @param str The string to convert.
+ * @param to_codeset Name of the target charset.
+ * @param from_codeset Name of the source charset.
+ * @param fallback UTF-8 string to be used in place of characters which aren't
+ * available in the target encoding. All characters in the fallback string
+ * @em must be available in the target encoding.
+ * @return The converted string.
+ * @throw Glib::ConvertError
+ */
+std::string convert_with_fallback(const std::string& str,
+ const std::string& to_codeset,
+ const std::string& from_codeset,
+ const Glib::ustring& fallback);
+
+/** Convert from the current locale's encoding to UTF-8.
+ * Convenience wrapper around Glib::convert().
+ * @param opsys_string The string to convert. Must be encoded in the charset
+ * used by the operating system's current locale.
+ * @return The input string converted to UTF-8 encoding.
+ * @throw Glib::ConvertError
+ */
+Glib::ustring locale_to_utf8(const std::string& opsys_string);
+
+/** Convert from UTF-8 to the current locale's encoding.
+ * Convenience wrapper around Glib::convert().
+ * @param utf8_string The UTF-8 string to convert.
+ * @return The input string converted to the charset used by the operating
+ * system's current locale.
+ * @throw Glib::ConvertError
+ */
+std::string locale_from_utf8(const Glib::ustring& utf8_string);
+
+/** Converts a string which is in the encoding used for filenames into
+ * a UTF-8 string.
+ * @param opsys_string A string in the encoding for filenames.
+ * @return The converted string.
+ * @throw Glib::ConvertError
+ */
+Glib::ustring filename_to_utf8(const std::string& opsys_string);
+
+/** Converts a string from UTF-8 to the encoding used for filenames.
+ * @param utf8_string A UTF-8 encoded string.
+ * @return The converted string.
+ * @throw Glib::ConvertError
+ */
+std::string filename_from_utf8(const Glib::ustring& utf8_string);
+
+/** Converts an escaped UTF-8 encoded URI to a local filename
+ * in the encoding used for filenames.
+ * @param uri A string in the encoding for filenames.
+ * @param hostname Location to store hostname for the URI. If there is no
+ * hostname in the URI, <tt>""</tt> will be stored in this location.
+ * @return The resulting filename.
+ * @throw Glib::ConvertError
+ */
+std::string filename_from_uri(const Glib::ustring& uri, Glib::ustring& hostname);
+
+/** Converts an escaped UTF-8 encoded URI to a local filename in the encoding
+ * used for filenames.
+ * @param uri A string in the encoding for filenames.
+ * @return The resulting filename.
+ * @throw Glib::ConvertError
+ */
+std::string filename_from_uri(const Glib::ustring& uri);
+
+/** Converts an absolute filename to an escaped UTF-8 encoded URI.
+ * @param filename An absolute filename specified in the encoding used
+ * for filenames by the operating system.
+ * @param hostname A UTF-8 encoded hostname.
+ * @return The resulting URI.
+ * @throw Glib::ConvertError
+ */
+Glib::ustring filename_to_uri(const std::string& filename, const Glib::ustring& hostname);
+
+/** Converts an absolute filename to an escaped UTF-8 encoded URI.
+ * @param filename An absolute filename specified in the encoding used
+ * for filenames by the operating system.
+ * @return The resulting URI.
+ * @throw Glib::ConvertError
+ */
+Glib::ustring filename_to_uri(const std::string& filename);
+
+/** @} group CharsetConv */
+
+} // namespace Glib
+
diff --git a/glib/src/date.ccg b/glib/src/date.ccg
new file mode 100644
index 00000000..f73db33d
--- /dev/null
+++ b/glib/src/date.ccg
@@ -0,0 +1,325 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gmem.h>
+#include <glib/gmessages.h>
+
+#include <ctime>
+#include <algorithm>
+#include <glibmm/convert.h>
+#include <glibmm/utility.h>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(max)
+
+
+namespace Glib
+{
+
+Date::Date()
+{
+ g_date_clear(&gobject_, 1);
+}
+
+Date::Date(Date::Day day, Date::Month month, Date::Year year)
+{
+ g_date_clear(&gobject_, 1);
+ g_date_set_dmy(&gobject_, day, (GDateMonth) month, year);
+}
+
+Date::Date(guint32 julian_day)
+{
+ g_date_clear(&gobject_, 1);
+ g_date_set_julian(&gobject_, julian_day);
+}
+
+Date::Date(const GDate& castitem)
+:
+ gobject_ (castitem)
+{}
+
+void Date::clear()
+{
+ g_date_clear(&gobject_, 1);
+}
+
+void Date::set_parse(const Glib::ustring& str)
+{
+ g_date_set_parse(&gobject_, str.c_str());
+}
+
+void Date::set_time(GTime time)
+{
+ g_date_set_time(&gobject_, time);
+}
+
+void Date::set_month(Date::Month month)
+{
+ g_date_set_month(&gobject_, (GDateMonth) month);
+}
+
+void Date::set_day(Date::Day day)
+{
+ g_date_set_day(&gobject_, day);
+}
+
+void Date::set_year(Date::Year year)
+{
+ g_date_set_year(&gobject_, year);
+}
+
+void Date::set_dmy(Date::Day day, Date::Month month, Date::Year year)
+{
+ g_date_set_dmy(&gobject_, day, (GDateMonth) month, year);
+}
+
+void Date::set_julian(guint32 julian_day)
+{
+ g_date_set_julian(&gobject_, julian_day);
+}
+
+Date& Date::add_days(int n_days)
+{
+ if(n_days >= 0)
+ g_date_add_days(&gobject_, n_days);
+ else
+ g_date_subtract_days(&gobject_, -n_days);
+ return *this;
+}
+
+Date& Date::subtract_days(int n_days)
+{
+ if(n_days >= 0)
+ g_date_subtract_days(&gobject_, n_days);
+ else
+ g_date_add_days(&gobject_, -n_days);
+ return *this;
+}
+
+Date& Date::add_months(int n_months)
+{
+ if(n_months >= 0)
+ g_date_add_months(&gobject_, n_months);
+ else
+ g_date_subtract_months(&gobject_, -n_months);
+ return *this;
+}
+
+Date& Date::subtract_months(int n_months)
+{
+ if(n_months >= 0)
+ g_date_subtract_months(&gobject_, n_months);
+ else
+ g_date_add_months(&gobject_, -n_months);
+ return *this;
+}
+
+Date& Date::add_years(int n_years)
+{
+ if(n_years >= 0)
+ g_date_add_years(&gobject_, n_years);
+ else
+ g_date_subtract_years(&gobject_, -n_years);
+ return *this;
+}
+
+Date& Date::subtract_years(int n_years)
+{
+ if(n_years >= 0)
+ g_date_subtract_years(&gobject_, n_years);
+ else
+ g_date_add_years(&gobject_, -n_years);
+ return *this;
+}
+
+int Date::days_between(const Date& rhs) const
+{
+ return g_date_days_between(&gobject_, &rhs.gobject_);
+}
+
+int Date::compare(const Date& rhs) const
+{
+ return g_date_compare(&gobject_, &rhs.gobject_);
+}
+
+Date& Date::clamp(const Date& min_date, const Date& max_date)
+{
+ g_date_clamp(&gobject_, &min_date.gobject_, &max_date.gobject_);
+ return *this;
+}
+
+void Date::order(Date& other)
+{
+ g_date_order(&gobject_, &other.gobject_);
+}
+
+Date::Weekday Date::get_weekday() const
+{
+ return (Date::Weekday) g_date_get_weekday(&gobject_);
+}
+
+Date::Month Date::get_month() const
+{
+ return (Date::Month) g_date_get_month(&gobject_);
+}
+
+Date::Year Date::get_year() const
+{
+ return g_date_get_year(&gobject_);
+}
+
+Date::Day Date::get_day() const
+{
+ return g_date_get_day(&gobject_);
+}
+
+guint32 Date::get_julian() const
+{
+ return g_date_get_julian(&gobject_);
+}
+
+unsigned int Date::get_day_of_year() const
+{
+ return g_date_get_day_of_year(&gobject_);
+}
+
+unsigned int Date::get_monday_week_of_year() const
+{
+ return g_date_get_monday_week_of_year(&gobject_);
+}
+
+unsigned int Date::get_sunday_week_of_year() const
+{
+ return g_date_get_sunday_week_of_year(&gobject_);
+}
+
+bool Date::is_first_of_month() const
+{
+ return g_date_is_first_of_month(&gobject_);
+}
+
+bool Date::is_last_of_month() const
+{
+ return g_date_is_last_of_month(&gobject_);
+}
+
+//static
+guint8 Date::get_days_in_month(Date::Month month, Date::Year year)
+{
+ return g_date_get_days_in_month((GDateMonth) month, year);
+}
+
+//static
+guint8 Date::get_monday_weeks_in_year(Date::Year year)
+{
+ return g_date_get_monday_weeks_in_year(year);
+}
+
+//static
+guint8 Date::get_sunday_weeks_in_year(Date::Year year)
+{
+ return g_date_get_sunday_weeks_in_year(year);
+}
+
+//static
+bool Date::is_leap_year(Date::Year year)
+{
+ return g_date_is_leap_year(year);
+}
+
+Glib::ustring Date::format_string(const Glib::ustring& format) const
+{
+ struct tm tm_data;
+ g_date_to_struct_tm(&gobject_, &tm_data);
+
+ const std::string locale_format = locale_from_utf8(format);
+ gsize bufsize = std::max<gsize>(2 * locale_format.size(), 128);
+
+ do
+ {
+ const ScopedPtr<char> buf (static_cast<char*>(g_malloc(bufsize)));
+
+ // Set the first byte to something other than '\0', to be able to
+ // recognize whether strftime actually failed or just returned "".
+ buf.get()[0] = '\1';
+ const gsize len = strftime(buf.get(), bufsize, locale_format.c_str(), &tm_data);
+
+ if(len != 0 || buf.get()[0] == '\0')
+ {
+ g_assert(len < bufsize);
+ return locale_to_utf8(std::string(buf.get(), len));
+ }
+ }
+ while((bufsize *= 2) <= 65536);
+
+ // This error is quite unlikely (unless strftime is buggy).
+ g_warning("Glib::Date::format_string(): maximum size of strftime buffer exceeded, giving up");
+
+ return Glib::ustring();
+}
+
+void Date::to_struct_tm(struct tm& dest) const
+{
+ g_date_to_struct_tm(&gobject_, &dest);
+}
+
+bool Date::valid() const
+{
+ return g_date_valid(&gobject_);
+}
+
+//static
+bool Date::valid_day(Date::Day day)
+{
+ return g_date_valid_day(day);
+}
+
+//static
+bool Date::valid_month(Date::Month month)
+{
+ return g_date_valid_month((GDateMonth) month);
+}
+
+//static
+bool Date::valid_year(Date::Year year)
+{
+ return g_date_valid_year(year);
+}
+
+//static
+bool Date::valid_weekday(Date::Weekday weekday)
+{
+ return g_date_valid_weekday((GDateWeekday) weekday);
+}
+
+//static
+bool Date::valid_julian(guint32 julian_day)
+{
+ return g_date_valid_julian(julian_day);
+}
+
+//static
+bool Date::valid_dmy(Date::Day day, Date::Month month, Date::Year year)
+{
+ return g_date_valid_dmy(day, (GDateMonth) month, year);
+}
+
+} // namespace Glib
+
diff --git a/glib/src/date.hg b/glib/src/date.hg
new file mode 100644
index 00000000..1434ad46
--- /dev/null
+++ b/glib/src/date.hg
@@ -0,0 +1,151 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glibmm/ustring.h>
+
+#include <glib/gdate.h>
+#include <glib/gtypes.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { struct tm; }
+#endif
+
+
+namespace Glib
+{
+
+/** Julian calendar date.
+ */
+class Date
+{
+public:
+ typedef guint8 Day;
+ typedef guint16 Year;
+
+ _WRAP_ENUM(Month, GDateMonth, s#^DATE_##, NO_GTYPE)
+ _WRAP_ENUM(Weekday, GDateWeekday, s#^DATE_##, NO_GTYPE)
+ _WRAP_ENUM(DMY, GDateDMY, s#^DATE_##, NO_GTYPE)
+
+ static const Day BAD_DAY = 0;
+ static const Year BAD_YEAR = 0;
+ static const guint32 BAD_JULIAN = 0;
+
+ Date();
+ Date(Day day, Month month, Year year);
+ explicit Date(guint32 julian_day);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ explicit Date(const GDate& castitem);
+#endif
+
+ void clear();
+ void set_parse (const Glib::ustring& str);
+ void set_time (GTime time);
+ void set_month (Month month);
+ void set_day (Day day);
+ void set_year (Year year);
+ void set_dmy (Day day, Month month, Year year);
+ void set_julian(guint32 julian_day);
+
+ Date& add_days (int n_days);
+ Date& subtract_days (int n_days);
+ Date& add_months (int n_months);
+ Date& subtract_months(int n_months);
+ Date& add_years (int n_years);
+ Date& subtract_years (int n_years);
+
+ int days_between(const Date& rhs) const;
+ int compare(const Date& rhs) const;
+
+ Date& clamp(const Date& min_date, const Date& max_date);
+ void order(Date& other);
+
+ Weekday get_weekday() const;
+ Month get_month() const;
+ Year get_year() const;
+ Day get_day() const;
+ guint32 get_julian() const;
+ unsigned int get_day_of_year() const;
+ unsigned int get_monday_week_of_year() const;
+ unsigned int get_sunday_week_of_year() const;
+ bool is_first_of_month() const;
+ bool is_last_of_month() const;
+
+ static guint8 get_days_in_month(Month month, Year year);
+ static guint8 get_monday_weeks_in_year(Year year);
+ static guint8 get_sunday_weeks_in_year(Year year);
+ static bool is_leap_year(Year year);
+
+ /** Convert date to string.
+ * @param format A format string as used by @c strftime(), in UTF-8
+ * encoding. Only date formats are allowed, the result of time formats
+ * is undefined.
+ * @return The formatted date string.
+ * @throw Glib::ConvertError
+ */
+ Glib::ustring format_string(const Glib::ustring& format) const;
+
+ void to_struct_tm(struct tm& dest) const;
+
+ bool valid() const;
+ static bool valid_day (Day day);
+ static bool valid_month (Month month);
+ static bool valid_year (Year year);
+ static bool valid_weekday(Weekday weekday);
+ static bool valid_julian (guint32 julian_day);
+ static bool valid_dmy (Day day, Month month, Year year);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GDate* gobj() { return &gobject_; }
+ const GDate* gobj() const { return &gobject_; }
+#endif
+
+private:
+ GDate gobject_;
+};
+
+
+/** @relates Glib::Date */
+inline bool operator==(const Date& lhs, const Date& rhs)
+ { return (lhs.compare(rhs) == 0); }
+
+/** @relates Glib::Date */
+inline bool operator!=(const Date& lhs, const Date& rhs)
+ { return (lhs.compare(rhs) != 0); }
+
+/** @relates Glib::Date */
+inline bool operator<(const Date& lhs, const Date& rhs)
+ { return (lhs.compare(rhs) < 0); }
+
+/** @relates Glib::Date */
+inline bool operator>(const Date& lhs, const Date& rhs)
+ { return (lhs.compare(rhs) > 0); }
+
+/** @relates Glib::Date */
+inline bool operator<=(const Date& lhs, const Date& rhs)
+ { return (lhs.compare(rhs) <= 0); }
+
+/** @relates Glib::Date */
+inline bool operator>=(const Date& lhs, const Date& rhs)
+ { return (lhs.compare(rhs) >= 0); }
+
+} // namespace Glib
+
diff --git a/glib/src/fileutils.ccg b/glib/src/fileutils.ccg
new file mode 100644
index 00000000..144c48b5
--- /dev/null
+++ b/glib/src/fileutils.ccg
@@ -0,0 +1,185 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gdir.h>
+#include <glib/gfileutils.h>
+#include <glib/gstrfuncs.h>
+#include <glibmm/utility.h>
+
+
+namespace Glib
+{
+
+/**** Glib::Dir ************************************************************/
+
+Dir::Dir(const std::string& path)
+{
+ GError* error = 0;
+ gobject_ = g_dir_open(path.c_str(), 0, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+Dir::Dir(GDir* gobject)
+:
+ gobject_ (gobject)
+{}
+
+Dir::~Dir()
+{
+ if(gobject_)
+ g_dir_close(gobject_);
+}
+
+std::string Dir::read_name()
+{
+ const char *const name = g_dir_read_name(gobject_);
+ return (name) ? std::string(name) : std::string();
+}
+
+void Dir::rewind()
+{
+ g_dir_rewind(gobject_);
+}
+
+void Dir::close()
+{
+ if(gobject_)
+ {
+ g_dir_close(gobject_);
+ gobject_ = 0;
+ }
+}
+
+DirIterator Dir::begin()
+{
+ g_dir_rewind(gobject_);
+ return DirIterator(gobject_, g_dir_read_name(gobject_));
+}
+
+DirIterator Dir::end()
+{
+ return DirIterator(gobject_, 0);
+}
+
+
+/**** Glib::DirIterator ****************************************************/
+
+DirIterator::DirIterator()
+:
+ gobject_ (0),
+ current_ (0)
+{}
+
+DirIterator::DirIterator(GDir* gobject, const char* current)
+:
+ gobject_ (gobject),
+ current_ (current)
+{}
+
+std::string DirIterator::operator*() const
+{
+ return (current_) ? std::string(current_) : std::string();
+}
+
+DirIterator& DirIterator::operator++()
+{
+ current_ = g_dir_read_name(gobject_);
+ return *this;
+}
+
+void DirIterator::operator++(int)
+{
+ current_ = g_dir_read_name(gobject_);
+}
+
+bool DirIterator::operator==(const DirIterator& rhs) const
+{
+ return (current_ == rhs.current_);
+}
+
+bool DirIterator::operator!=(const DirIterator& rhs) const
+{
+ return (current_ != rhs.current_);
+}
+
+
+bool file_test(const std::string& filename, FileTest test)
+{
+ return g_file_test(filename.c_str(), static_cast<GFileTest>(unsigned(test)));
+}
+
+int mkstemp(std::string& filename_template)
+{
+ const ScopedPtr<char> buf (g_strndup(filename_template.data(), filename_template.size()));
+ const int fileno = g_mkstemp(buf.get());
+
+ filename_template = buf.get();
+ return fileno;
+}
+
+int file_open_tmp(std::string& name_used, const std::string& prefix)
+{
+ std::string basename_template (prefix);
+ basename_template += "XXXXXX"; // this sillyness shouldn't be in the interface
+
+ GError* error = 0;
+ ScopedPtr<char> buf_name_used;
+
+ const int fileno = g_file_open_tmp(basename_template.c_str(), buf_name_used.addr(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ name_used = buf_name_used.get();
+ return fileno;
+}
+
+int file_open_tmp(std::string& name_used)
+{
+ GError* error = 0;
+ ScopedPtr<char> buf_name_used;
+
+ const int fileno = g_file_open_tmp(0, buf_name_used.addr(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ name_used = buf_name_used.get();
+ return fileno;
+}
+
+std::string file_get_contents(const std::string& filename)
+{
+ ScopedPtr<char> contents;
+ gsize length = 0;
+ GError* error = 0;
+
+ g_file_get_contents(filename.c_str(), contents.addr(), &length, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ return std::string(contents.get(), length);
+}
+
+} // namespace Glib
+
diff --git a/glib/src/fileutils.hg b/glib/src/fileutils.hg
new file mode 100644
index 00000000..e3ed50f1
--- /dev/null
+++ b/glib/src/fileutils.hg
@@ -0,0 +1,400 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GDir GDir; }
+#endif
+
+#include <iterator>
+#include <string>
+
+#include <glibmmconfig.h>
+#include <glibmm/error.h>
+
+GTKMM_USING_STD(input_iterator_tag)
+GTKMM_USING_STD(string)
+
+
+namespace Glib
+{
+
+_WRAP_ENUM(FileTest, GFileTest, NO_GTYPE)
+
+/** @defgroup FileUtils File Utilities
+ * Various file-related classes and functions.
+ */
+
+/** Exception class for file-related errors.
+ * @ingroup FileUtils
+ */
+_WRAP_GERROR(FileError, GFileError, G_FILE_ERROR, NO_GTYPE,
+ s#^EXIST$#EXISTS#,
+ s#^ISDIR$#IS_DIRECTORY#,
+ s#^ACCES$#ACCESS_DENIED#,
+ s#^NAMETOOLONG$#NAME_TOO_LONG#,
+ s#^NOENT$#NO_SUCH_ENTITY#,
+ s#^NOTDIR$#NOT_DIRECTORY#,
+ s#^NXIO$#NO_SUCH_DEVICE#,
+ s#^NODEV$#NOT_DEVICE#,
+ s#^ROFS$#READONLY_FILESYSTEM#,
+ s#^TXTBSY$#TEXT_FILE_BUSY#,
+ s#^FAULT$#FAULTY_ADDRESS#,
+ s#^LOOP$#SYMLINK_LOOP#,
+ s#^NOSPC$#NO_SPACE_LEFT#,
+ s#^NOMEM$#NOT_ENOUGH_MEMORY#,
+ s#^MFILE$#TOO_MANY_OPEN_FILES#,
+ s#^NFILE$#FILE_TABLE_OVERFLOW#,
+ s#^BADF$#BAD_FILE_DESCRIPTOR#,
+ s#^INVAL$#INVALID_ARGUMENT#,
+ s#^PIPE$#BROKEN_PIPE#,
+ s#^AGAIN$#TRYAGAIN#,
+ s#^INTR$#INTERRUPTED#,
+ s#^IO$#IO_ERROR#,
+ s#^PERM$#NOT_OWNER#
+)
+
+/** @enum FileError::Code
+ * Values corresponding to <tt>errno</tt> codes returned from file operations
+ * on UNIX.
+ * Unlike <tt>errno</tt> codes, FileError::Code values are available on all
+ * systems, even Windows. The exact meaning of each code depends on what sort
+ * of file operation you were performing; the UNIX documentation gives more
+ * details. The following error code descriptions come from the GNU C Library
+ * manual, and are under the copyright of that manual.
+ *
+ * It's not very portable to make detailed assumptions about exactly which
+ * errors will be returned from a given operation. Some errors don't occur on
+ * some systems, etc., sometimes there are subtle differences in when a system
+ * will report a given error, etc.
+ */
+
+/*! @var FileError::Code FileError::EXISTS
+ * <tt>(EEXIST)</tt> Operation not permitted; only the owner of the file (or
+ * other resource) or processes with special privileges can perform the operation.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::IS_DIRECTORY
+ * <tt>(EISDIR)</tt> File is a directory; you cannot open a directory for writing,
+ * or create or remove hard links to it.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::ACCESS_DENIED
+ * <tt>(EACCES)</tt> Permission denied; the file permissions do not allow the
+ * attempted operation.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NAME_TOO_LONG
+ * <tt>(ENAMETOOLONG)</tt> Filename too long.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NO_SUCH_ENTITY
+ * <tt>(ENOENT)</tt> No such file or directory. This is a "file doesn't exist"
+ * error for ordinary files that are referenced in contexts where they are expected
+ * to already exist.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NOT_DIRECTORY
+ * <tt>(ENOTDIR)</tt> A file that isn't a directory was specified when a directory
+ * is required.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NO_SUCH_DEVICE
+ * <tt>(ENXIO)</tt> No such device or address. The system tried to use the device
+ * represented by a file you specified, and it couldn't find the device. This can
+ * mean that the device file was installed incorrectly, or that the physical device
+ * is missing or not correctly attached to the computer.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NOT_DEVICE
+ * <tt>(ENODEV)</tt> This file is of a type that doesn't support mapping.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::READONLY_FILESYSTEM
+ * <tt>(EROFS)</tt> The directory containing the new link can't be modified
+ * because it's on a read-only file system.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::TEXT_FILE_BUSY
+ * <tt>(ETXTBSY)</tt> Text file busy.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::FAULTY_ADDRESS
+ * <tt>(EFAULT)</tt> You passed in a pointer to bad memory. (Glib won't
+ * reliably return this, don't pass in pointers to bad memory.)
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::SYMLINK_LOOP
+ * <tt>(ELOOP)</tt> Too many levels of symbolic links were encountered in
+ * looking up a file name. This often indicates a cycle of symbolic links.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NO_SPACE_LEFT
+ * <tt>(ENOSPC)</tt> No space left on device; write operation on a file failed
+ * because the disk is full.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NOT_ENOUGH_MEMORY
+ * <tt>(ENOMEM)</tt> No memory available. The system cannot allocate more
+ * virtual memory because its capacity is full.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::TOO_MANY_OPEN_FILES
+ * <tt>(EMFILE)</tt> The current process has too many files open and can't
+ * open any more. Duplicate descriptors do count toward this limit.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::FILE_TABLE_OVERFLOW
+ * <tt>(ENFILE)</tt> There are too many distinct file openings in the
+ * entire system.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::BAD_FILE_DESCRIPTOR
+ * <tt>(EBADF)</tt> Bad file descriptor; for example, I/O on a descriptor
+ * that has been closed or reading from a descriptor open only for writing
+ * (or vice versa).
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::INVALID_ARGUMENT
+ * <tt>(EINVAL)</tt> Invalid argument. This is used to indicate various kinds
+ * of problems with passing the wrong argument to a library function.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::BROKEN_PIPE
+ * <tt>(EPIPE)</tt> Broken pipe; there is no process reading from the other
+ * end of a pipe. Every library function that returns this error code also
+ * generates a <tt>SIGPIPE</tt> signal; this signal terminates the program
+ * if not handled or blocked. Thus, your program will never actually see
+ * this code unless it has handled or blocked <tt>SIGPIPE</tt>.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::TRYAGAIN
+ * <tt>(EAGAIN)</tt> Resource temporarily unavailable; the call might work
+ * if you try again later.
+ * We used TRYAGAIN instead of TRY_AGAIN, because that is a defined as a macro by a Unix header.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::INTERRUPTED
+ * <tt>(EINTR)</tt> Interrupted function call; an asynchronous signal occurred
+ * and prevented completion of the call. When this happens, you should try
+ * the call again.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::IO_ERROR
+ * <tt>(EIO)</tt> Input/output error; usually used for physical read or write
+ * errors. I.e. the disk or other physical device hardware is returning errors.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::NOT_OWNER
+ * <tt>(EPERM)</tt> Operation not permitted; only the owner of the file (or other
+ * resource) or processes with special privileges can perform the operation.
+ * <br><br>
+ */
+/*! @var FileError::Code FileError::FAILED
+ * Does not correspond to a UNIX error code; this is the standard "failed for
+ * unspecified reason" error code present in all Glib::Error error code
+ * enumerations. Returned if no specific code applies.
+ */
+
+class Dir;
+
+/** The iterator type of Glib::Dir.
+ * @ingroup FileUtils
+ */
+class DirIterator
+{
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef std::string value_type;
+ typedef int difference_type;
+ typedef value_type reference;
+ typedef void pointer;
+
+ DirIterator();
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ DirIterator(GDir* gobject, const char* current);
+#endif
+
+ std::string operator*() const;
+ DirIterator& operator++();
+
+ /*! @note DirIterator has input iterator semantics, which means real
+ * postfix increment is impossible. The return type is @c void to
+ * prevent surprising behaviour.
+ */
+ void operator++(int);
+
+ bool operator==(const DirIterator& rhs) const;
+ bool operator!=(const DirIterator& rhs) const;
+
+private:
+ GDir* gobject_;
+ const char* current_;
+};
+
+
+/** Utility class representing an open directory.
+ * @ingroup FileUtils
+ * It's highly recommended to use the iterator interface. With iterators,
+ * reading an entire directory into a STL container is really easy:
+ * @code
+ * Glib::Dir dir (directory_path);
+ * std::list<std::string> entries (dir.begin(), dir.end());
+ * @endcode
+ * @note The encoding of the directory entries isn't necessarily UTF-8.
+ * Use Glib::filename_to_utf8() if you need to display them.
+ */
+class Dir
+{
+public:
+ typedef DirIterator iterator;
+ typedef DirIterator const_iterator;
+
+ /** Opens a directory for reading. The names of the files in the
+ * directory can then be retrieved using read_name().
+ * @param path The path to the directory you are interested in.
+ * @throw Glib::FileError
+ */
+ explicit Dir(const std::string& path);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ explicit Dir(GDir* gobject);
+#endif
+
+ /** Closes the directory and deallocates all related resources.
+ */
+ ~Dir();
+
+ /** Retrieves the name of the next entry in the directory.
+ * The <tt>'.'</tt> and <tt>'..'</tt> entries are omitted.
+ * @return The entry's name or <tt>""</tt> if there are no more entries.
+ * @see begin(), end()
+ */
+ std::string read_name();
+
+ /** Resets the directory. The next call to
+ * read_name() will return the first entry again.
+ */
+ void rewind();
+
+ /** Closes the directory and deallocates all related resources.
+ * Note that close() is implicitely called by ~Dir(). Thus you don't
+ * need to call close() yourself unless you want to close the directory
+ * before the destructor runs.
+ */
+ void close();
+
+ /** Get the begin of an input iterator sequence.
+ * @return An input iterator pointing to the first directory entry.
+ */
+ DirIterator begin();
+
+ /** Get the end of an input iterator sequence.
+ * @return An input iterator pointing behind the last directory entry.
+ */
+ DirIterator end();
+
+private:
+ GDir* gobject_;
+
+ // noncopyable
+ Dir(const Dir&);
+ Dir& operator=(const Dir&);
+};
+
+
+/** Returns @c true if any of the tests in the bitfield @a test are true.
+ * @ingroup FileUtils
+ * For example, <tt>(Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_DIR)</tt> will
+ * return @c true if the file exists; the check whether it's a directory
+ * doesn't matter since the existence test is true. With the current set of
+ * available tests, there's no point passing in more than one test at a time.
+ *
+ * Apart from <tt>Glib::FILE_TEST_IS_SYMLINK</tt> all tests follow symbolic
+ * links, so for a symbolic link to a regular file file_test() will return
+ * @c true for both <tt>Glib::FILE_TEST_IS_SYMLINK</tt> and
+ * <tt>Glib::FILE_TEST_IS_REGULAR</tt>.
+ *
+ * @note For a dangling symbolic link file_test() will return @c true for
+ * <tt>Glib::FILE_TEST_IS_SYMLINK</tt> and @c false for all other flags.
+ *
+ * @param filename A filename to test.
+ * @param test Bitfield of Glib::FileTest flags.
+ * @return Whether a test was true.
+ */
+bool file_test(const std::string& filename, FileTest test);
+
+/** Opens a temporary file.
+ * @ingroup FileUtils
+ * See the %mkstemp() documentation on most UNIX-like systems. This is a
+ * portability wrapper, which simply calls %mkstemp() on systems that have
+ * it, and implements it in GLib otherwise.
+ * @param filename_template A string that should match the rules for
+ * %mkstemp(), i.e. end in <tt>"XXXXXX"</tt>. The <tt>X</tt> string
+ * will be modified to form the name of a file that didn't exist.
+ * @return A file handle (as from open()) to the file opened for reading
+ * and writing. The file is opened in binary mode on platforms where there
+ * is a difference. The file handle should be closed with close(). In
+ * case of errors, <tt>-1</tt> is returned.
+ */
+int mkstemp(std::string& filename_template);
+
+/** Opens a file for writing in the preferred directory for temporary files
+ * (as returned by Glib::get_tmp_dir()).
+ * @ingroup FileUtils
+ * @a prefix should a basename template; it'll be suffixed by 6 characters
+ * in order to form a unique filename. No directory components are allowed.
+ *
+ * The actual name used is returned in @a name_used.
+ *
+ * @param prefix Template for file name, basename only.
+ * @retval name_used The actual name used.
+ * @return A file handle (as from <tt>open()</tt>) to the file opened for reading
+ * and writing. The file is opened in binary mode on platforms where there is a
+ * difference. The file handle should be closed with <tt>close()</tt>.
+ * @throw Glib::FileError
+ */
+int file_open_tmp(std::string& name_used, const std::string& prefix);
+
+/** Opens a file for writing in the preferred directory for temporary files
+ * (as returned by Glib::get_tmp_dir()).
+ * @ingroup FileUtils
+ * This function works like file_open_tmp(std::string&, const std::string&)
+ * but uses a default basename prefix.
+ *
+ * @retval name_used The actual name used.
+ * @return A file handle (as from <tt>open()</tt>) to the file opened for reading
+ * and writing. The file is opened in binary mode on platforms where there is a
+ * difference. The file handle should be closed with <tt>close()</tt>.
+ * @throw Glib::FileError
+ */
+int file_open_tmp(std::string& name_used);
+
+/** Reads an entire file into a string, with good error checking.
+ * @ingroup FileUtils
+ * @param filename A file to read contents from.
+ * @return The file contents.
+ * @throw Glib::FileError
+ */
+std::string file_get_contents(const std::string& filename);
+
+} // namespace Glib
+
diff --git a/glib/src/glib.defs b/glib/src/glib.defs
new file mode 100644
index 00000000..ce4f36d9
--- /dev/null
+++ b/glib/src/glib.defs
@@ -0,0 +1,5 @@
+(include glib_functions.defs)
+(include glib_enums.defs)
+(include gobject_functions.defs)
+(include gmodule_functions.defs)
+(include gmodule_enums.defs)
diff --git a/glib/src/glib_enums.defs b/glib/src/glib_enums.defs
new file mode 100644
index 00000000..99396e4c
--- /dev/null
+++ b/glib/src/glib_enums.defs
@@ -0,0 +1,489 @@
+;; From glib/gconvert.h
+
+(define-enum-extended ConvertError
+ (in-module "G")
+ (c-name "GConvertError")
+ (values
+ '("no-conversion" "G_CONVERT_ERROR_NO_CONVERSION" "0")
+ '("illegal-sequence" "G_CONVERT_ERROR_ILLEGAL_SEQUENCE" "1")
+ '("failed" "G_CONVERT_ERROR_FAILED" "2")
+ '("partial-input" "G_CONVERT_ERROR_PARTIAL_INPUT" "3")
+ '("bad-uri" "G_CONVERT_ERROR_BAD_URI" "4")
+ '("not-absolute-path" "G_CONVERT_ERROR_NOT_ABSOLUTE_PATH" "5")
+ )
+)
+
+;; From glib/gdate.h
+
+(define-enum-extended DateDMY
+ (in-module "G")
+ (c-name "GDateDMY")
+ (values
+ '("day" "G_DATE_DAY" "0")
+ '("month" "G_DATE_MONTH" "1")
+ '("year" "G_DATE_YEAR" "2")
+ )
+)
+
+(define-enum-extended DateWeekday
+ (in-module "G")
+ (c-name "GDateWeekday")
+ (values
+ '("bad-weekday" "G_DATE_BAD_WEEKDAY" "0")
+ '("monday" "G_DATE_MONDAY" "1")
+ '("tuesday" "G_DATE_TUESDAY" "2")
+ '("wednesday" "G_DATE_WEDNESDAY" "3")
+ '("thursday" "G_DATE_THURSDAY" "4")
+ '("friday" "G_DATE_FRIDAY" "5")
+ '("saturday" "G_DATE_SATURDAY" "6")
+ '("sunday" "G_DATE_SUNDAY" "7")
+ )
+)
+
+(define-enum-extended DateMonth
+ (in-module "G")
+ (c-name "GDateMonth")
+ (values
+ '("bad-month" "G_DATE_BAD_MONTH" "0")
+ '("january" "G_DATE_JANUARY" "1")
+ '("february" "G_DATE_FEBRUARY" "2")
+ '("march" "G_DATE_MARCH" "3")
+ '("april" "G_DATE_APRIL" "4")
+ '("may" "G_DATE_MAY" "5")
+ '("june" "G_DATE_JUNE" "6")
+ '("july" "G_DATE_JULY" "7")
+ '("august" "G_DATE_AUGUST" "8")
+ '("september" "G_DATE_SEPTEMBER" "9")
+ '("october" "G_DATE_OCTOBER" "10")
+ '("november" "G_DATE_NOVEMBER" "11")
+ '("december" "G_DATE_DECEMBER" "12")
+ )
+)
+
+;; From glib/gfileutils.h
+
+(define-enum-extended FileError
+ (in-module "G")
+ (c-name "GFileError")
+ (values
+ '("exist" "G_FILE_ERROR_EXIST" "0")
+ '("isdir" "G_FILE_ERROR_ISDIR" "1")
+ '("acces" "G_FILE_ERROR_ACCES" "2")
+ '("nametoolong" "G_FILE_ERROR_NAMETOOLONG" "3")
+ '("noent" "G_FILE_ERROR_NOENT" "4")
+ '("notdir" "G_FILE_ERROR_NOTDIR" "5")
+ '("nxio" "G_FILE_ERROR_NXIO" "6")
+ '("nodev" "G_FILE_ERROR_NODEV" "7")
+ '("rofs" "G_FILE_ERROR_ROFS" "8")
+ '("txtbsy" "G_FILE_ERROR_TXTBSY" "9")
+ '("fault" "G_FILE_ERROR_FAULT" "10")
+ '("loop" "G_FILE_ERROR_LOOP" "11")
+ '("nospc" "G_FILE_ERROR_NOSPC" "12")
+ '("nomem" "G_FILE_ERROR_NOMEM" "13")
+ '("mfile" "G_FILE_ERROR_MFILE" "14")
+ '("nfile" "G_FILE_ERROR_NFILE" "15")
+ '("badf" "G_FILE_ERROR_BADF" "16")
+ '("inval" "G_FILE_ERROR_INVAL" "17")
+ '("pipe" "G_FILE_ERROR_PIPE" "18")
+ '("again" "G_FILE_ERROR_AGAIN" "19")
+ '("intr" "G_FILE_ERROR_INTR" "20")
+ '("io" "G_FILE_ERROR_IO" "21")
+ '("perm" "G_FILE_ERROR_PERM" "22")
+ '("failed" "G_FILE_ERROR_FAILED" "23")
+ )
+)
+
+(define-flags-extended FileTest
+ (in-module "G")
+ (c-name "GFileTest")
+ (values
+ '("is-regular" "G_FILE_TEST_IS_REGULAR" "1 << 0")
+ '("is-symlink" "G_FILE_TEST_IS_SYMLINK" "1 << 1")
+ '("is-dir" "G_FILE_TEST_IS_DIR" "1 << 2")
+ '("is-executable" "G_FILE_TEST_IS_EXECUTABLE" "1 << 3")
+ '("exists" "G_FILE_TEST_EXISTS" "1 << 4")
+ )
+)
+
+;; From glib/ghook.h
+
+(define-flags-extended HookFlagMask
+ (in-module "G")
+ (c-name "GHookFlagMask")
+ (values
+ '("active" "G_HOOK_FLAG_ACTIVE" "1 << 0")
+ '("in-call" "G_HOOK_FLAG_IN_CALL" "1 << 1")
+ '("mask" "G_HOOK_FLAG_MASK" "0x0f")
+ )
+)
+
+;; From glib/giochannel.h
+
+(define-enum-extended IOError
+ (in-module "G")
+ (c-name "GIOError")
+ (values
+ '("none" "G_IO_ERROR_NONE" "0")
+ '("again" "G_IO_ERROR_AGAIN" "1")
+ '("inval" "G_IO_ERROR_INVAL" "2")
+ '("unknown" "G_IO_ERROR_UNKNOWN" "3")
+ )
+)
+
+(define-enum-extended IOChannelError
+ (in-module "G")
+ (c-name "GIOChannelError")
+ (values
+ '("fbig" "G_IO_CHANNEL_ERROR_FBIG" "0")
+ '("inval" "G_IO_CHANNEL_ERROR_INVAL" "1")
+ '("io" "G_IO_CHANNEL_ERROR_IO" "2")
+ '("isdir" "G_IO_CHANNEL_ERROR_ISDIR" "3")
+ '("nospc" "G_IO_CHANNEL_ERROR_NOSPC" "4")
+ '("nxio" "G_IO_CHANNEL_ERROR_NXIO" "5")
+ '("overflow" "G_IO_CHANNEL_ERROR_OVERFLOW" "6")
+ '("pipe" "G_IO_CHANNEL_ERROR_PIPE" "7")
+ '("failed" "G_IO_CHANNEL_ERROR_FAILED" "8")
+ )
+)
+
+(define-enum-extended IOStatus
+ (in-module "G")
+ (c-name "GIOStatus")
+ (values
+ '("error" "G_IO_STATUS_ERROR" "0")
+ '("normal" "G_IO_STATUS_NORMAL" "1")
+ '("eof" "G_IO_STATUS_EOF" "2")
+ '("again" "G_IO_STATUS_AGAIN" "3")
+ )
+)
+
+(define-enum-extended SeekType
+ (in-module "G")
+ (c-name "GSeekType")
+ (values
+ '("cur" "G_SEEK_CUR" "0")
+ '("set" "G_SEEK_SET" "1")
+ '("end" "G_SEEK_END" "2")
+ )
+)
+
+(define-enum-extended IOCondition
+ (in-module "G")
+ (c-name "GIOCondition")
+ (values
+ )
+)
+
+(define-flags-extended IOFlags
+ (in-module "G")
+ (c-name "GIOFlags")
+ (values
+ '("append" "G_IO_FLAG_APPEND" "1 << 0")
+ '("nonblock" "G_IO_FLAG_NONBLOCK" "1 << 1")
+ '("is-readable" "G_IO_FLAG_IS_READABLE" "1 << 2")
+ '("is-writeable" "G_IO_FLAG_IS_WRITEABLE" "1 << 3")
+ '("is-seekable" "G_IO_FLAG_IS_SEEKABLE" "1 << 4")
+ '("mask" "G_IO_FLAG_MASK" "0x1F")
+ '("get-mask" "G_IO_FLAG_GET_MASK" "0x1F")
+ '("set-mask" "G_IO_FLAG_SET_MASK" "0x03")
+ )
+)
+
+;; From glib/gmarkup.h
+
+(define-enum-extended MarkupError
+ (in-module "G")
+ (c-name "GMarkupError")
+ (values
+ '("bad-utf8" "G_MARKUP_ERROR_BAD_UTF8" "0")
+ '("empty" "G_MARKUP_ERROR_EMPTY" "1")
+ '("parse" "G_MARKUP_ERROR_PARSE" "2")
+ '("unknown-element" "G_MARKUP_ERROR_UNKNOWN_ELEMENT" "3")
+ '("unknown-attribute" "G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE" "4")
+ '("invalid-content" "G_MARKUP_ERROR_INVALID_CONTENT" "5")
+ )
+)
+
+(define-flags-extended MarkupParseFlags
+ (in-module "G")
+ (c-name "GMarkupParseFlags")
+ (values
+ '("g" "G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG" "1 << 0")
+ )
+)
+
+;; From glib/gmessages.h
+
+(define-flags-extended LogLevelFlags
+ (in-module "G")
+ (c-name "GLogLevelFlags")
+ (values
+ '("flag-recursion" "G_LOG_FLAG_RECURSION" "1 << 0")
+ '("flag-fatal" "G_LOG_FLAG_FATAL" "1 << 1")
+ '("level-error" "G_LOG_LEVEL_ERROR" "1 << 2")
+ '("level-critical" "G_LOG_LEVEL_CRITICAL" "1 << 3")
+ '("level-warning" "G_LOG_LEVEL_WARNING" "1 << 4")
+ '("level-message" "G_LOG_LEVEL_MESSAGE" "1 << 5")
+ '("level-info" "G_LOG_LEVEL_INFO" "1 << 6")
+ '("level-debug" "G_LOG_LEVEL_DEBUG" "1 << 7")
+ '("level-mask" "G_LOG_LEVEL_MASK" "0xFFFFFFFE")
+ )
+)
+
+;; From glib/gnode.h
+
+(define-flags-extended TraverseFlags
+ (in-module "G")
+ (c-name "GTraverseFlags")
+ (values
+ '("leafs" "G_TRAVERSE_LEAFS" "1 << 0")
+ '("non-leafs" "G_TRAVERSE_NON_LEAFS" "1 << 1")
+ '("all" "G_TRAVERSE_ALL" "0x1")
+ '("mask" "G_TRAVERSE_MASK" "0x03")
+ )
+)
+
+(define-enum-extended TraverseType
+ (in-module "G")
+ (c-name "GTraverseType")
+ (values
+ '("in-order" "G_IN_ORDER" "0")
+ '("pre-order" "G_PRE_ORDER" "1")
+ '("post-order" "G_POST_ORDER" "2")
+ '("level-order" "G_LEVEL_ORDER" "3")
+ )
+)
+
+;; From glib/gscanner.h
+
+(define-enum-extended ErrorType
+ (in-module "G")
+ (c-name "GErrorType")
+ (values
+ '("unknown" "G_ERR_UNKNOWN" "0")
+ '("unexp-eof" "G_ERR_UNEXP_EOF" "1")
+ '("unexp-eof-in-string" "G_ERR_UNEXP_EOF_IN_STRING" "2")
+ '("unexp-eof-in-comment" "G_ERR_UNEXP_EOF_IN_COMMENT" "3")
+ '("non-digit-in-const" "G_ERR_NON_DIGIT_IN_CONST" "4")
+ '("digit-radix" "G_ERR_DIGIT_RADIX" "5")
+ '("float-radix" "G_ERR_FLOAT_RADIX" "6")
+ '("float-malformed" "G_ERR_FLOAT_MALFORMED" "7")
+ )
+)
+
+;;(define-enum-extended TokenType
+;; (in-module "G")
+;; (c-name "GTokenType")
+;; (values
+;; '("eof" "G_TOKEN_EOF" "0")
+;; '("left-paren" "G_TOKEN_LEFT_PAREN" "'('")
+;; '("right-paren" "G_TOKEN_RIGHT_PAREN" "')'")
+;; '("left-curly" "G_TOKEN_LEFT_CURLY" "'{'")
+;; '("right-curly" "G_TOKEN_RIGHT_CURLY" "']'")
+;; '("left-brace" "G_TOKEN_LEFT_BRACE" "'['")
+;; '("right-brace" "G_TOKEN_RIGHT_BRACE" "']'")
+;; '("equal-sign" "G_TOKEN_EQUAL_SIGN" "'='")
+;; '("comma" "G_TOKEN_COMMA" "','")
+;; '("none" "G_TOKEN_NONE" "256")
+;; '("error" "G_TOKEN_ERROR" "257")
+;; '("char" "G_TOKEN_CHAR" "258")
+;; '("binary" "G_TOKEN_BINARY" "259")
+;; '("octal" "G_TOKEN_OCTAL" "260")
+;; '("int" "G_TOKEN_INT" "261")
+;; '("hex" "G_TOKEN_HEX" "262")
+;; '("float" "G_TOKEN_FLOAT" "263")
+;; '("string" "G_TOKEN_STRING" "264")
+;; '("symbol" "G_TOKEN_SYMBOL" "265")
+;; '("identifier" "G_TOKEN_IDENTIFIER" "266")
+;; '("identifier-null" "G_TOKEN_IDENTIFIER_NULL" "267")
+;; '("comment-single" "G_TOKEN_COMMENT_SINGLE" "268")
+;; '("comment-multi" "G_TOKEN_COMMENT_MULTI" "269")
+;; '("last" "G_TOKEN_LAST" "270")
+;; )
+;;)
+
+;; From glib/gshell.h
+
+(define-enum-extended ShellError
+ (in-module "G")
+ (c-name "GShellError")
+ (values
+ '("bad-quoting" "G_SHELL_ERROR_BAD_QUOTING" "0")
+ '("empty-string" "G_SHELL_ERROR_EMPTY_STRING" "1")
+ '("failed" "G_SHELL_ERROR_FAILED" "2")
+ )
+)
+
+;; From glib/gspawn.h
+
+(define-enum-extended SpawnError
+ (in-module "G")
+ (c-name "GSpawnError")
+ (values
+ '("fork" "G_SPAWN_ERROR_FORK" "0")
+ '("read" "G_SPAWN_ERROR_READ" "1")
+ '("chdir" "G_SPAWN_ERROR_CHDIR" "2")
+ '("acces" "G_SPAWN_ERROR_ACCES" "3")
+ '("perm" "G_SPAWN_ERROR_PERM" "4")
+ '("2big" "G_SPAWN_ERROR_2BIG" "5")
+ '("noexec" "G_SPAWN_ERROR_NOEXEC" "6")
+ '("nametoolong" "G_SPAWN_ERROR_NAMETOOLONG" "7")
+ '("noent" "G_SPAWN_ERROR_NOENT" "8")
+ '("nomem" "G_SPAWN_ERROR_NOMEM" "9")
+ '("notdir" "G_SPAWN_ERROR_NOTDIR" "10")
+ '("loop" "G_SPAWN_ERROR_LOOP" "11")
+ '("txtbusy" "G_SPAWN_ERROR_TXTBUSY" "12")
+ '("io" "G_SPAWN_ERROR_IO" "13")
+ '("nfile" "G_SPAWN_ERROR_NFILE" "14")
+ '("mfile" "G_SPAWN_ERROR_MFILE" "15")
+ '("inval" "G_SPAWN_ERROR_INVAL" "16")
+ '("isdir" "G_SPAWN_ERROR_ISDIR" "17")
+ '("libbad" "G_SPAWN_ERROR_LIBBAD" "18")
+ )
+)
+
+(define-flags-extended SpawnFlags
+ (in-module "G")
+ (c-name "GSpawnFlags")
+ (values
+ '("leave-descriptors-open" "G_SPAWN_LEAVE_DESCRIPTORS_OPEN" "1 << 0")
+ '("do-not-reap-child" "G_SPAWN_DO_NOT_REAP_CHILD" "1 << 1")
+ '("search-path" "G_SPAWN_SEARCH_PATH" "1 << 2")
+ '("stdout-to-dev-null" "G_SPAWN_STDOUT_TO_DEV_NULL" "1 << 3")
+ '("stderr-to-dev-null" "G_SPAWN_STDERR_TO_DEV_NULL" "1 << 4")
+ '("child-inherits-stdin" "G_SPAWN_CHILD_INHERITS_STDIN" "1 << 5")
+ '("file-and-argv-zero" "G_SPAWN_FILE_AND_ARGV_ZERO" "1 << 6")
+ )
+)
+
+;; From glib/gstrfuncs.h
+
+(define-enum-extended AsciiType
+ (in-module "G")
+ (c-name "GAsciiType")
+ (values
+ '("alnum" "G_ASCII_ALNUM" "1 << 0")
+ '("alpha" "G_ASCII_ALPHA" "1 << 1")
+ '("cntrl" "G_ASCII_CNTRL" "1 << 2")
+ '("digit" "G_ASCII_DIGIT" "1 << 3")
+ '("graph" "G_ASCII_GRAPH" "1 << 4")
+ '("lower" "G_ASCII_LOWER" "1 << 5")
+ '("print" "G_ASCII_PRINT" "1 << 6")
+ '("punct" "G_ASCII_PUNCT" "1 << 7")
+ '("space" "G_ASCII_SPACE" "1 << 8")
+ '("upper" "G_ASCII_UPPER" "1 << 9")
+ '("xdigit" "G_ASCII_XDIGIT" "1 << 10")
+ )
+)
+
+;; From glib/gthread.h
+
+(define-enum-extended ThreadError
+ (in-module "G")
+ (c-name "GThreadError")
+ (values
+ '("n" "G_THREAD_ERROR_AGAIN" "0")
+ )
+)
+
+(define-enum-extended ThreadPriority
+ (in-module "G")
+ (c-name "GThreadPriority")
+ (values
+ '("low" "G_THREAD_PRIORITY_LOW" "0")
+ '("normal" "G_THREAD_PRIORITY_NORMAL" "1")
+ '("high" "G_THREAD_PRIORITY_HIGH" "2")
+ '("urgent" "G_THREAD_PRIORITY_URGENT" "3")
+ )
+)
+
+;; From glib/gunicode.h
+
+(define-enum-extended UnicodeType
+ (in-module "G")
+ (c-name "GUnicodeType")
+ (values
+ '("control" "G_UNICODE_CONTROL" "0")
+ '("format" "G_UNICODE_FORMAT" "1")
+ '("unassigned" "G_UNICODE_UNASSIGNED" "2")
+ '("private-use" "G_UNICODE_PRIVATE_USE" "3")
+ '("surrogate" "G_UNICODE_SURROGATE" "4")
+ '("lowercase-letter" "G_UNICODE_LOWERCASE_LETTER" "5")
+ '("modifier-letter" "G_UNICODE_MODIFIER_LETTER" "6")
+ '("other-letter" "G_UNICODE_OTHER_LETTER" "7")
+ '("titlecase-letter" "G_UNICODE_TITLECASE_LETTER" "8")
+ '("uppercase-letter" "G_UNICODE_UPPERCASE_LETTER" "9")
+ '("combining-mark" "G_UNICODE_COMBINING_MARK" "10")
+ '("enclosing-mark" "G_UNICODE_ENCLOSING_MARK" "11")
+ '("non-spacing-mark" "G_UNICODE_NON_SPACING_MARK" "12")
+ '("decimal-number" "G_UNICODE_DECIMAL_NUMBER" "13")
+ '("letter-number" "G_UNICODE_LETTER_NUMBER" "14")
+ '("other-number" "G_UNICODE_OTHER_NUMBER" "15")
+ '("connect-punctuation" "G_UNICODE_CONNECT_PUNCTUATION" "16")
+ '("dash-punctuation" "G_UNICODE_DASH_PUNCTUATION" "17")
+ '("close-punctuation" "G_UNICODE_CLOSE_PUNCTUATION" "18")
+ '("final-punctuation" "G_UNICODE_FINAL_PUNCTUATION" "19")
+ '("initial-punctuation" "G_UNICODE_INITIAL_PUNCTUATION" "20")
+ '("other-punctuation" "G_UNICODE_OTHER_PUNCTUATION" "21")
+ '("open-punctuation" "G_UNICODE_OPEN_PUNCTUATION" "22")
+ '("currency-symbol" "G_UNICODE_CURRENCY_SYMBOL" "23")
+ '("modifier-symbol" "G_UNICODE_MODIFIER_SYMBOL" "24")
+ '("math-symbol" "G_UNICODE_MATH_SYMBOL" "25")
+ '("other-symbol" "G_UNICODE_OTHER_SYMBOL" "26")
+ '("line-separator" "G_UNICODE_LINE_SEPARATOR" "27")
+ '("paragraph-separator" "G_UNICODE_PARAGRAPH_SEPARATOR" "28")
+ '("space-separator" "G_UNICODE_SPACE_SEPARATOR" "29")
+ )
+)
+
+(define-enum-extended UnicodeBreakType
+ (in-module "G")
+ (c-name "GUnicodeBreakType")
+ (values
+ '("mandatory" "G_UNICODE_BREAK_MANDATORY" "0")
+ '("carriage-return" "G_UNICODE_BREAK_CARRIAGE_RETURN" "1")
+ '("line-feed" "G_UNICODE_BREAK_LINE_FEED" "2")
+ '("combining-mark" "G_UNICODE_BREAK_COMBINING_MARK" "3")
+ '("surrogate" "G_UNICODE_BREAK_SURROGATE" "4")
+ '("zero-width-space" "G_UNICODE_BREAK_ZERO_WIDTH_SPACE" "5")
+ '("inseparable" "G_UNICODE_BREAK_INSEPARABLE" "6")
+ '("non-breaking-glue" "G_UNICODE_BREAK_NON_BREAKING_GLUE" "7")
+ '("contingent" "G_UNICODE_BREAK_CONTINGENT" "8")
+ '("space" "G_UNICODE_BREAK_SPACE" "9")
+ '("after" "G_UNICODE_BREAK_AFTER" "10")
+ '("before" "G_UNICODE_BREAK_BEFORE" "11")
+ '("before-and-after" "G_UNICODE_BREAK_BEFORE_AND_AFTER" "12")
+ '("hyphen" "G_UNICODE_BREAK_HYPHEN" "13")
+ '("non-starter" "G_UNICODE_BREAK_NON_STARTER" "14")
+ '("open-punctuation" "G_UNICODE_BREAK_OPEN_PUNCTUATION" "15")
+ '("close-punctuation" "G_UNICODE_BREAK_CLOSE_PUNCTUATION" "16")
+ '("quotation" "G_UNICODE_BREAK_QUOTATION" "17")
+ '("exclamation" "G_UNICODE_BREAK_EXCLAMATION" "18")
+ '("ideographic" "G_UNICODE_BREAK_IDEOGRAPHIC" "19")
+ '("numeric" "G_UNICODE_BREAK_NUMERIC" "20")
+ '("infix-separator" "G_UNICODE_BREAK_INFIX_SEPARATOR" "21")
+ '("symbol" "G_UNICODE_BREAK_SYMBOL" "22")
+ '("alphabetic" "G_UNICODE_BREAK_ALPHABETIC" "23")
+ '("prefix" "G_UNICODE_BREAK_PREFIX" "24")
+ '("postfix" "G_UNICODE_BREAK_POSTFIX" "25")
+ '("complex-context" "G_UNICODE_BREAK_COMPLEX_CONTEXT" "26")
+ '("ambiguous" "G_UNICODE_BREAK_AMBIGUOUS" "27")
+ '("unknown" "G_UNICODE_BREAK_UNKNOWN" "28")
+ )
+)
+
+(define-enum-extended NormalizeMode
+ (in-module "G")
+ (c-name "GNormalizeMode")
+ (values
+ '("default" "G_NORMALIZE_DEFAULT" "0")
+ '("nfd" "G_NORMALIZE_NFD" "0")
+ '("default-compose" "G_NORMALIZE_DEFAULT_COMPOSE" "1")
+ '("nfc" "G_NORMALIZE_NFC" "1")
+ '("all" "G_NORMALIZE_ALL" "2")
+ '("nfkd" "G_NORMALIZE_NFKD" "2")
+ '("all-compose" "G_NORMALIZE_ALL_COMPOSE" "3")
+ '("nfkc" "G_NORMALIZE_NFKC" "3")
+ )
+)
+
diff --git a/glib/src/glib_functions.defs b/glib/src/glib_functions.defs
new file mode 100644
index 00000000..615380b4
--- /dev/null
+++ b/glib/src/glib_functions.defs
@@ -0,0 +1,6328 @@
+;; -*- scheme -*-
+; object definitions ...
+;; Enumerations and flags ...
+
+(define-enum ConvertError
+ (in-module "G")
+ (c-name "GConvertError")
+ (gtype-id "G_TYPE_CONVERT_ERROR")
+ (values
+ '("no-conversion" "G_CONVERT_ERROR_NO_CONVERSION")
+ '("illegal-sequence" "G_CONVERT_ERROR_ILLEGAL_SEQUENCE")
+ '("failed" "G_CONVERT_ERROR_FAILED")
+ '("partial-input" "G_CONVERT_ERROR_PARTIAL_INPUT")
+ '("bad-uri" "G_CONVERT_ERROR_BAD_URI")
+ '("not-absolute-path" "G_CONVERT_ERROR_NOT_ABSOLUTE_PATH")
+ )
+)
+
+(define-enum DateDMY
+ (in-module "G")
+ (c-name "GDateDMY")
+ (gtype-id "G_TYPE_DATE_DMY")
+ (values
+ '("day" "G_DATE_DAY")
+ '("month" "G_DATE_MONTH")
+ '("year" "G_DATE_YEAR")
+ )
+)
+
+(define-enum DateWeekday
+ (in-module "G")
+ (c-name "GDateWeekday")
+ (gtype-id "G_TYPE_DATE_WEEKDAY")
+ (values
+ '("bad-weekday" "G_DATE_BAD_WEEKDAY")
+ '("monday" "G_DATE_MONDAY")
+ '("tuesday" "G_DATE_TUESDAY")
+ '("wednesday" "G_DATE_WEDNESDAY")
+ '("thursday" "G_DATE_THURSDAY")
+ '("friday" "G_DATE_FRIDAY")
+ '("saturday" "G_DATE_SATURDAY")
+ '("sunday" "G_DATE_SUNDAY")
+ )
+)
+
+(define-enum DateMonth
+ (in-module "G")
+ (c-name "GDateMonth")
+ (gtype-id "G_TYPE_DATE_MONTH")
+ (values
+ '("bad-month" "G_DATE_BAD_MONTH")
+ '("january" "G_DATE_JANUARY")
+ '("february" "G_DATE_FEBRUARY")
+ '("march" "G_DATE_MARCH")
+ '("april" "G_DATE_APRIL")
+ '("may" "G_DATE_MAY")
+ '("june" "G_DATE_JUNE")
+ '("july" "G_DATE_JULY")
+ '("august" "G_DATE_AUGUST")
+ '("september" "G_DATE_SEPTEMBER")
+ '("october" "G_DATE_OCTOBER")
+ '("november" "G_DATE_NOVEMBER")
+ '("december" "G_DATE_DECEMBER")
+ )
+)
+
+(define-enum FileError
+ (in-module "G")
+ (c-name "GFileError")
+ (gtype-id "G_TYPE_FILE_ERROR")
+ (values
+ '("exist" "G_FILE_ERROR_EXIST")
+ '("isdir" "G_FILE_ERROR_ISDIR")
+ '("acces" "G_FILE_ERROR_ACCES")
+ '("nametoolong" "G_FILE_ERROR_NAMETOOLONG")
+ '("noent" "G_FILE_ERROR_NOENT")
+ '("notdir" "G_FILE_ERROR_NOTDIR")
+ '("nxio" "G_FILE_ERROR_NXIO")
+ '("nodev" "G_FILE_ERROR_NODEV")
+ '("rofs" "G_FILE_ERROR_ROFS")
+ '("txtbsy" "G_FILE_ERROR_TXTBSY")
+ '("fault" "G_FILE_ERROR_FAULT")
+ '("loop" "G_FILE_ERROR_LOOP")
+ '("nospc" "G_FILE_ERROR_NOSPC")
+ '("nomem" "G_FILE_ERROR_NOMEM")
+ '("mfile" "G_FILE_ERROR_MFILE")
+ '("nfile" "G_FILE_ERROR_NFILE")
+ '("badf" "G_FILE_ERROR_BADF")
+ '("inval" "G_FILE_ERROR_INVAL")
+ '("pipe" "G_FILE_ERROR_PIPE")
+ '("again" "G_FILE_ERROR_AGAIN")
+ '("intr" "G_FILE_ERROR_INTR")
+ '("io" "G_FILE_ERROR_IO")
+ '("perm" "G_FILE_ERROR_PERM")
+ '("failed" "G_FILE_ERROR_FAILED")
+ )
+)
+
+(define-flags FileTest
+ (in-module "G")
+ (c-name "GFileTest")
+ (gtype-id "G_TYPE_FILE_TEST")
+ (values
+ '("is-regular" "G_FILE_TEST_IS_REGULAR")
+ '("is-symlink" "G_FILE_TEST_IS_SYMLINK")
+ '("is-dir" "G_FILE_TEST_IS_DIR")
+ '("is-executable" "G_FILE_TEST_IS_EXECUTABLE")
+ '("exists" "G_FILE_TEST_EXISTS")
+ )
+)
+
+(define-flags HookFlagMask
+ (in-module "G")
+ (c-name "GHookFlagMask")
+ (gtype-id "G_TYPE_HOOK_FLAG_MASK")
+ (values
+ '("active" "G_HOOK_FLAG_ACTIVE")
+ '("in-call" "G_HOOK_FLAG_IN_CALL")
+ '("mask" "G_HOOK_FLAG_MASK")
+ )
+)
+
+(define-enum IOError
+ (in-module "G")
+ (c-name "GIOError")
+ (gtype-id "G_TYPE_IO_ERROR")
+ (values
+ '("none" "G_IO_ERROR_NONE")
+ '("again" "G_IO_ERROR_AGAIN")
+ '("inval" "G_IO_ERROR_INVAL")
+ '("unknown" "G_IO_ERROR_UNKNOWN")
+ )
+)
+
+(define-enum IOChannelError
+ (in-module "G")
+ (c-name "GIOChannelError")
+ (gtype-id "G_TYPE_IO_CHANNEL_ERROR")
+ (values
+ '("fbig" "G_IO_CHANNEL_ERROR_FBIG")
+ '("inval" "G_IO_CHANNEL_ERROR_INVAL")
+ '("io" "G_IO_CHANNEL_ERROR_IO")
+ '("isdir" "G_IO_CHANNEL_ERROR_ISDIR")
+ '("nospc" "G_IO_CHANNEL_ERROR_NOSPC")
+ '("nxio" "G_IO_CHANNEL_ERROR_NXIO")
+ '("overflow" "G_IO_CHANNEL_ERROR_OVERFLOW")
+ '("pipe" "G_IO_CHANNEL_ERROR_PIPE")
+ '("failed" "G_IO_CHANNEL_ERROR_FAILED")
+ )
+)
+
+(define-enum IOStatus
+ (in-module "G")
+ (c-name "GIOStatus")
+ (gtype-id "G_TYPE_IO_STATUS")
+ (values
+ '("error" "G_IO_STATUS_ERROR")
+ '("normal" "G_IO_STATUS_NORMAL")
+ '("eof" "G_IO_STATUS_EOF")
+ '("again" "G_IO_STATUS_AGAIN")
+ )
+)
+
+(define-enum SeekType
+ (in-module "G")
+ (c-name "GSeekType")
+ (gtype-id "G_TYPE_SEEK_TYPE")
+ (values
+ '("cur" "G_SEEK_CUR")
+ '("set" "G_SEEK_SET")
+ '("end" "G_SEEK_END")
+ )
+)
+
+(define-enum IOCondition
+ (in-module "G")
+ (c-name "GIOCondition")
+ (gtype-id "G_TYPE_IO_CONDITION")
+ (values
+ '("in" "G_IO_IN")
+ '("out" "G_IO_OUT")
+ '("pri" "G_IO_PRI")
+ '("err" "G_IO_ERR")
+ '("hup" "G_IO_HUP")
+ '("nval" "G_IO_NVAL")
+ )
+)
+
+(define-flags IOFlags
+ (in-module "G")
+ (c-name "GIOFlags")
+ (gtype-id "G_TYPE_IO_FLAGS")
+ (values
+ '("append" "G_IO_FLAG_APPEND")
+ '("nonblock" "G_IO_FLAG_NONBLOCK")
+ '("is-readable" "G_IO_FLAG_IS_READABLE")
+ '("is-writeable" "G_IO_FLAG_IS_WRITEABLE")
+ '("is-seekable" "G_IO_FLAG_IS_SEEKABLE")
+ '("mask" "G_IO_FLAG_MASK")
+ '("get-mask" "G_IO_FLAG_GET_MASK")
+ '("set-mask" "G_IO_FLAG_SET_MASK")
+ )
+)
+
+(define-enum MarkupError
+ (in-module "G")
+ (c-name "GMarkupError")
+ (gtype-id "G_TYPE_MARKUP_ERROR")
+ (values
+ '("bad-utf8" "G_MARKUP_ERROR_BAD_UTF8")
+ '("empty" "G_MARKUP_ERROR_EMPTY")
+ '("parse" "G_MARKUP_ERROR_PARSE")
+ '("unknown-element" "G_MARKUP_ERROR_UNKNOWN_ELEMENT")
+ '("unknown-attribute" "G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE")
+ '("invalid-content" "G_MARKUP_ERROR_INVALID_CONTENT")
+ )
+)
+
+(define-flags MarkupParseFlags
+ (in-module "G")
+ (c-name "GMarkupParseFlags")
+ (gtype-id "G_TYPE_MARKUP_PARSE_FLAGS")
+ (values
+ '("g" "G_MARKUP_DO_NOT_USE_THIS_UNSUPPORTED_FLAG")
+ )
+)
+
+(define-flags LogLevelFlags
+ (in-module "G")
+ (c-name "GLogLevelFlags")
+ (gtype-id "G_TYPE_LOG_LEVEL_FLAGS")
+ (values
+ '("flag-recursion" "G_LOG_FLAG_RECURSION")
+ '("flag-fatal" "G_LOG_FLAG_FATAL")
+ '("level-error" "G_LOG_LEVEL_ERROR")
+ '("level-critical" "G_LOG_LEVEL_CRITICAL")
+ '("level-warning" "G_LOG_LEVEL_WARNING")
+ '("level-message" "G_LOG_LEVEL_MESSAGE")
+ '("level-info" "G_LOG_LEVEL_INFO")
+ '("level-debug" "G_LOG_LEVEL_DEBUG")
+ '("level-mask" "G_LOG_LEVEL_MASK")
+ )
+)
+
+(define-flags TraverseFlags
+ (in-module "G")
+ (c-name "GTraverseFlags")
+ (gtype-id "G_TYPE_TRAVERSE_FLAGS")
+ (values
+ '("leafs" "G_TRAVERSE_LEAFS")
+ '("non-leafs" "G_TRAVERSE_NON_LEAFS")
+ '("all" "G_TRAVERSE_ALL")
+ '("mask" "G_TRAVERSE_MASK")
+ )
+)
+
+(define-enum TraverseType
+ (in-module "G")
+ (c-name "GTraverseType")
+ (gtype-id "G_TYPE_TRAVERSE_TYPE")
+ (values
+ '("in-order" "G_IN_ORDER")
+ '("pre-order" "G_PRE_ORDER")
+ '("post-order" "G_POST_ORDER")
+ '("level-order" "G_LEVEL_ORDER")
+ )
+)
+
+(define-enum ErrorType
+ (in-module "G")
+ (c-name "GErrorType")
+ (gtype-id "G_TYPE_ERROR_TYPE")
+ (values
+ '("unknown" "G_ERR_UNKNOWN")
+ '("unexp-eof" "G_ERR_UNEXP_EOF")
+ '("unexp-eof-in-string" "G_ERR_UNEXP_EOF_IN_STRING")
+ '("unexp-eof-in-comment" "G_ERR_UNEXP_EOF_IN_COMMENT")
+ '("non-digit-in-const" "G_ERR_NON_DIGIT_IN_CONST")
+ '("digit-radix" "G_ERR_DIGIT_RADIX")
+ '("float-radix" "G_ERR_FLOAT_RADIX")
+ '("float-malformed" "G_ERR_FLOAT_MALFORMED")
+ )
+)
+
+(define-enum ShellError
+ (in-module "G")
+ (c-name "GShellError")
+ (gtype-id "G_TYPE_SHELL_ERROR")
+ (values
+ '("bad-quoting" "G_SHELL_ERROR_BAD_QUOTING")
+ '("empty-string" "G_SHELL_ERROR_EMPTY_STRING")
+ '("failed" "G_SHELL_ERROR_FAILED")
+ )
+)
+
+(define-enum SpawnError
+ (in-module "G")
+ (c-name "GSpawnError")
+ (gtype-id "G_TYPE_SPAWN_ERROR")
+ (values
+ '("fork" "G_SPAWN_ERROR_FORK")
+ '("read" "G_SPAWN_ERROR_READ")
+ '("chdir" "G_SPAWN_ERROR_CHDIR")
+ '("acces" "G_SPAWN_ERROR_ACCES")
+ '("perm" "G_SPAWN_ERROR_PERM")
+ '("2big" "G_SPAWN_ERROR_2BIG")
+ '("noexec" "G_SPAWN_ERROR_NOEXEC")
+ '("nametoolong" "G_SPAWN_ERROR_NAMETOOLONG")
+ '("noent" "G_SPAWN_ERROR_NOENT")
+ '("nomem" "G_SPAWN_ERROR_NOMEM")
+ '("notdir" "G_SPAWN_ERROR_NOTDIR")
+ '("loop" "G_SPAWN_ERROR_LOOP")
+ '("txtbusy" "G_SPAWN_ERROR_TXTBUSY")
+ '("io" "G_SPAWN_ERROR_IO")
+ '("nfile" "G_SPAWN_ERROR_NFILE")
+ '("mfile" "G_SPAWN_ERROR_MFILE")
+ '("inval" "G_SPAWN_ERROR_INVAL")
+ '("isdir" "G_SPAWN_ERROR_ISDIR")
+ '("libbad" "G_SPAWN_ERROR_LIBBAD")
+ '("failed" "G_SPAWN_ERROR_FAILED")
+ )
+)
+
+(define-flags SpawnFlags
+ (in-module "G")
+ (c-name "GSpawnFlags")
+ (gtype-id "G_TYPE_SPAWN_FLAGS")
+ (values
+ '("leave-descriptors-open" "G_SPAWN_LEAVE_DESCRIPTORS_OPEN")
+ '("do-not-reap-child" "G_SPAWN_DO_NOT_REAP_CHILD")
+ '("search-path" "G_SPAWN_SEARCH_PATH")
+ '("stdout-to-dev-null" "G_SPAWN_STDOUT_TO_DEV_NULL")
+ '("stderr-to-dev-null" "G_SPAWN_STDERR_TO_DEV_NULL")
+ '("child-inherits-stdin" "G_SPAWN_CHILD_INHERITS_STDIN")
+ '("file-and-argv-zero" "G_SPAWN_FILE_AND_ARGV_ZERO")
+ )
+)
+
+(define-flags AsciiType
+ (in-module "G")
+ (c-name "GAsciiType")
+ (gtype-id "G_TYPE_ASCII_TYPE")
+ (values
+ '("alnum" "G_ASCII_ALNUM")
+ '("alpha" "G_ASCII_ALPHA")
+ '("cntrl" "G_ASCII_CNTRL")
+ '("digit" "G_ASCII_DIGIT")
+ '("graph" "G_ASCII_GRAPH")
+ '("lower" "G_ASCII_LOWER")
+ '("print" "G_ASCII_PRINT")
+ '("punct" "G_ASCII_PUNCT")
+ '("space" "G_ASCII_SPACE")
+ '("upper" "G_ASCII_UPPER")
+ '("xdigit" "G_ASCII_XDIGIT")
+ )
+)
+
+(define-enum ThreadError
+ (in-module "G")
+ (c-name "GThreadError")
+ (gtype-id "G_TYPE_THREAD_ERROR")
+ (values
+ '("n" "G_THREAD_ERROR_AGAIN")
+ )
+)
+
+(define-enum ThreadPriority
+ (in-module "G")
+ (c-name "GThreadPriority")
+ (gtype-id "G_TYPE_THREAD_PRIORITY")
+ (values
+ '("low" "G_THREAD_PRIORITY_LOW")
+ '("normal" "G_THREAD_PRIORITY_NORMAL")
+ '("high" "G_THREAD_PRIORITY_HIGH")
+ '("urgent" "G_THREAD_PRIORITY_URGENT")
+ )
+)
+
+(define-enum UnicodeType
+ (in-module "G")
+ (c-name "GUnicodeType")
+ (gtype-id "G_TYPE_UNICODE_TYPE")
+ (values
+ '("control" "G_UNICODE_CONTROL")
+ '("format" "G_UNICODE_FORMAT")
+ '("unassigned" "G_UNICODE_UNASSIGNED")
+ '("private-use" "G_UNICODE_PRIVATE_USE")
+ '("surrogate" "G_UNICODE_SURROGATE")
+ '("lowercase-letter" "G_UNICODE_LOWERCASE_LETTER")
+ '("modifier-letter" "G_UNICODE_MODIFIER_LETTER")
+ '("other-letter" "G_UNICODE_OTHER_LETTER")
+ '("titlecase-letter" "G_UNICODE_TITLECASE_LETTER")
+ '("uppercase-letter" "G_UNICODE_UPPERCASE_LETTER")
+ '("combining-mark" "G_UNICODE_COMBINING_MARK")
+ '("enclosing-mark" "G_UNICODE_ENCLOSING_MARK")
+ '("non-spacing-mark" "G_UNICODE_NON_SPACING_MARK")
+ '("decimal-number" "G_UNICODE_DECIMAL_NUMBER")
+ '("letter-number" "G_UNICODE_LETTER_NUMBER")
+ '("other-number" "G_UNICODE_OTHER_NUMBER")
+ '("connect-punctuation" "G_UNICODE_CONNECT_PUNCTUATION")
+ '("dash-punctuation" "G_UNICODE_DASH_PUNCTUATION")
+ '("close-punctuation" "G_UNICODE_CLOSE_PUNCTUATION")
+ '("final-punctuation" "G_UNICODE_FINAL_PUNCTUATION")
+ '("initial-punctuation" "G_UNICODE_INITIAL_PUNCTUATION")
+ '("other-punctuation" "G_UNICODE_OTHER_PUNCTUATION")
+ '("open-punctuation" "G_UNICODE_OPEN_PUNCTUATION")
+ '("currency-symbol" "G_UNICODE_CURRENCY_SYMBOL")
+ '("modifier-symbol" "G_UNICODE_MODIFIER_SYMBOL")
+ '("math-symbol" "G_UNICODE_MATH_SYMBOL")
+ '("other-symbol" "G_UNICODE_OTHER_SYMBOL")
+ '("line-separator" "G_UNICODE_LINE_SEPARATOR")
+ '("paragraph-separator" "G_UNICODE_PARAGRAPH_SEPARATOR")
+ '("space-separator" "G_UNICODE_SPACE_SEPARATOR")
+ )
+)
+
+(define-enum UnicodeBreakType
+ (in-module "G")
+ (c-name "GUnicodeBreakType")
+ (gtype-id "G_TYPE_UNICODE_BREAK_TYPE")
+ (values
+ '("mandatory" "G_UNICODE_BREAK_MANDATORY")
+ '("carriage-return" "G_UNICODE_BREAK_CARRIAGE_RETURN")
+ '("line-feed" "G_UNICODE_BREAK_LINE_FEED")
+ '("combining-mark" "G_UNICODE_BREAK_COMBINING_MARK")
+ '("surrogate" "G_UNICODE_BREAK_SURROGATE")
+ '("zero-width-space" "G_UNICODE_BREAK_ZERO_WIDTH_SPACE")
+ '("inseparable" "G_UNICODE_BREAK_INSEPARABLE")
+ '("non-breaking-glue" "G_UNICODE_BREAK_NON_BREAKING_GLUE")
+ '("contingent" "G_UNICODE_BREAK_CONTINGENT")
+ '("space" "G_UNICODE_BREAK_SPACE")
+ '("after" "G_UNICODE_BREAK_AFTER")
+ '("before" "G_UNICODE_BREAK_BEFORE")
+ '("before-and-after" "G_UNICODE_BREAK_BEFORE_AND_AFTER")
+ '("hyphen" "G_UNICODE_BREAK_HYPHEN")
+ '("non-starter" "G_UNICODE_BREAK_NON_STARTER")
+ '("open-punctuation" "G_UNICODE_BREAK_OPEN_PUNCTUATION")
+ '("close-punctuation" "G_UNICODE_BREAK_CLOSE_PUNCTUATION")
+ '("quotation" "G_UNICODE_BREAK_QUOTATION")
+ '("exclamation" "G_UNICODE_BREAK_EXCLAMATION")
+ '("ideographic" "G_UNICODE_BREAK_IDEOGRAPHIC")
+ '("numeric" "G_UNICODE_BREAK_NUMERIC")
+ '("infix-separator" "G_UNICODE_BREAK_INFIX_SEPARATOR")
+ '("symbol" "G_UNICODE_BREAK_SYMBOL")
+ '("alphabetic" "G_UNICODE_BREAK_ALPHABETIC")
+ '("prefix" "G_UNICODE_BREAK_PREFIX")
+ '("postfix" "G_UNICODE_BREAK_POSTFIX")
+ '("complex-context" "G_UNICODE_BREAK_COMPLEX_CONTEXT")
+ '("ambiguous" "G_UNICODE_BREAK_AMBIGUOUS")
+ '("unknown" "G_UNICODE_BREAK_UNKNOWN")
+ )
+)
+
+(define-enum NormalizeMode
+ (in-module "G")
+ (c-name "GNormalizeMode")
+ (gtype-id "G_TYPE_NORMALIZE_MODE")
+ (values
+ '("default" "G_NORMALIZE_DEFAULT")
+ '("nfd" "G_NORMALIZE_NFD")
+ '("default-compose" "G_NORMALIZE_DEFAULT_COMPOSE")
+ '("nfc" "G_NORMALIZE_NFC")
+ '("all" "G_NORMALIZE_ALL")
+ '("nfkd" "G_NORMALIZE_NFKD")
+ '("all-compose" "G_NORMALIZE_ALL_COMPOSE")
+ '("nfkc" "G_NORMALIZE_NFKC")
+ )
+)
+
+
+;; From glib/galloca.h
+
+
+
+;; From glib/garray.h
+
+(define-function g_array_new
+ (c-name "g_array_new")
+ (return-type "GArray*")
+ (parameters
+ '("gboolean" "zero_terminated")
+ '("gboolean" "clear")
+ '("guint" "element_size")
+ )
+)
+
+(define-function g_array_sized_new
+ (c-name "g_array_sized_new")
+ (return-type "GArray*")
+ (parameters
+ '("gboolean" "zero_terminated")
+ '("gboolean" "clear")
+ '("guint" "element_size")
+ '("guint" "reserved_size")
+ )
+)
+
+(define-method free
+ (of-object "GArray")
+ (c-name "g_array_free")
+ (return-type "gchar*")
+ (parameters
+ '("gboolean" "free_segment")
+ )
+)
+
+(define-method append_vals
+ (of-object "GArray")
+ (c-name "g_array_append_vals")
+ (return-type "GArray*")
+ (parameters
+ '("gconstpointer" "data")
+ '("guint" "len")
+ )
+)
+
+(define-method prepend_vals
+ (of-object "GArray")
+ (c-name "g_array_prepend_vals")
+ (return-type "GArray*")
+ (parameters
+ '("gconstpointer" "data")
+ '("guint" "len")
+ )
+)
+
+(define-method insert_vals
+ (of-object "GArray")
+ (c-name "g_array_insert_vals")
+ (return-type "GArray*")
+ (parameters
+ '("guint" "index")
+ '("gconstpointer" "data")
+ '("guint" "len")
+ )
+)
+
+(define-method set_size
+ (of-object "GArray")
+ (c-name "g_array_set_size")
+ (return-type "GArray*")
+ (parameters
+ '("guint" "length")
+ )
+)
+
+(define-method remove_index
+ (of-object "GArray")
+ (c-name "g_array_remove_index")
+ (return-type "GArray*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method remove_index_fast
+ (of-object "GArray")
+ (c-name "g_array_remove_index_fast")
+ (return-type "GArray*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method sort
+ (of-object "GArray")
+ (c-name "g_array_sort")
+ (return-type "none")
+ (parameters
+ '("GCompareFunc" "compare_func")
+ )
+)
+
+(define-method sort_with_data
+ (of-object "GArray")
+ (c-name "g_array_sort_with_data")
+ (return-type "none")
+ (parameters
+ '("GCompareDataFunc" "compare_func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-function g_ptr_array_new
+ (c-name "g_ptr_array_new")
+ (return-type "GPtrArray*")
+)
+
+(define-function g_ptr_array_sized_new
+ (c-name "g_ptr_array_sized_new")
+ (return-type "GPtrArray*")
+ (parameters
+ '("guint" "reserved_size")
+ )
+)
+
+(define-method free
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_free")
+ (return-type "gpointer*")
+ (parameters
+ '("gboolean" "free_seg")
+ )
+)
+
+(define-method set_size
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_set_size")
+ (return-type "none")
+ (parameters
+ '("gint" "length")
+ )
+)
+
+(define-method remove_index
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_remove_index")
+ (return-type "gpointer")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method remove_index_fast
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_remove_index_fast")
+ (return-type "gpointer")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method remove
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_remove")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method remove_fast
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_remove_fast")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method add
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_add")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method sort
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_sort")
+ (return-type "none")
+ (parameters
+ '("GCompareFunc" "compare_func")
+ )
+)
+
+(define-method sort_with_data
+ (of-object "GPtrArray")
+ (c-name "g_ptr_array_sort_with_data")
+ (return-type "none")
+ (parameters
+ '("GCompareDataFunc" "compare_func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-function g_byte_array_new
+ (c-name "g_byte_array_new")
+ (return-type "GByteArray*")
+)
+
+(define-function g_byte_array_sized_new
+ (c-name "g_byte_array_sized_new")
+ (return-type "GByteArray*")
+ (parameters
+ '("guint" "reserved_size")
+ )
+)
+
+(define-method free
+ (of-object "GByteArray")
+ (c-name "g_byte_array_free")
+ (return-type "guint8*")
+ (parameters
+ '("gboolean" "free_segment")
+ )
+)
+
+(define-method append
+ (of-object "GByteArray")
+ (c-name "g_byte_array_append")
+ (return-type "GByteArray*")
+ (parameters
+ '("const-guint8*" "data")
+ '("guint" "len")
+ )
+)
+
+(define-method prepend
+ (of-object "GByteArray")
+ (c-name "g_byte_array_prepend")
+ (return-type "GByteArray*")
+ (parameters
+ '("const-guint8*" "data")
+ '("guint" "len")
+ )
+)
+
+(define-method set_size
+ (of-object "GByteArray")
+ (c-name "g_byte_array_set_size")
+ (return-type "GByteArray*")
+ (parameters
+ '("guint" "length")
+ )
+)
+
+(define-method remove_index
+ (of-object "GByteArray")
+ (c-name "g_byte_array_remove_index")
+ (return-type "GByteArray*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method remove_index_fast
+ (of-object "GByteArray")
+ (c-name "g_byte_array_remove_index_fast")
+ (return-type "GByteArray*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method sort
+ (of-object "GByteArray")
+ (c-name "g_byte_array_sort")
+ (return-type "none")
+ (parameters
+ '("GCompareFunc" "compare_func")
+ )
+)
+
+(define-method sort_with_data
+ (of-object "GByteArray")
+ (c-name "g_byte_array_sort_with_data")
+ (return-type "none")
+ (parameters
+ '("GCompareDataFunc" "compare_func")
+ '("gpointer" "user_data")
+ )
+)
+
+
+
+;; From glib/gasyncqueue.h
+
+(define-method lock
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_lock")
+ (return-type "none")
+)
+
+(define-method unlock
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_unlock")
+ (return-type "none")
+)
+
+(define-method ref
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_ref")
+ (return-type "none")
+)
+
+(define-method ref_unlocked
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_ref_unlocked")
+ (return-type "none")
+)
+
+(define-method unref
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_unref")
+ (return-type "none")
+)
+
+(define-method unref_and_unlock
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_unref_and_unlock")
+ (return-type "none")
+)
+
+(define-method push
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_push")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method push_unlocked
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_push_unlocked")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method pop
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_pop")
+ (return-type "gpointer")
+)
+
+(define-method pop_unlocked
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_pop_unlocked")
+ (return-type "gpointer")
+)
+
+(define-method try_pop
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_try_pop")
+ (return-type "gpointer")
+)
+
+(define-method try_pop_unlocked
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_try_pop_unlocked")
+ (return-type "gpointer")
+)
+
+(define-method timed_pop
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_timed_pop")
+ (return-type "gpointer")
+ (parameters
+ '("GTimeVal*" "end_time")
+ )
+)
+
+(define-method timed_pop_unlocked
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_timed_pop_unlocked")
+ (return-type "gpointer")
+ (parameters
+ '("GTimeVal*" "end_time")
+ )
+)
+
+(define-method length
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_length")
+ (return-type "gint")
+)
+
+(define-method length_unlocked
+ (of-object "GAsyncQueue")
+ (c-name "g_async_queue_length_unlocked")
+ (return-type "gint")
+)
+
+
+
+;; From glib/gbacktrace.h
+
+(define-function g_on_error_stack_trace
+ (c-name "g_on_error_stack_trace")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "prg_name")
+ )
+)
+
+
+
+;; From glib/gcache.h
+
+(define-method destroy
+ (of-object "GCache")
+ (c-name "g_cache_destroy")
+ (return-type "none")
+)
+
+(define-method insert
+ (of-object "GCache")
+ (c-name "g_cache_insert")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "key")
+ )
+)
+
+(define-method remove
+ (of-object "GCache")
+ (c-name "g_cache_remove")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "value")
+ )
+)
+
+(define-method key_foreach
+ (of-object "GCache")
+ (c-name "g_cache_key_foreach")
+ (return-type "none")
+ (parameters
+ '("GHFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method value_foreach
+ (of-object "GCache")
+ (c-name "g_cache_value_foreach")
+ (return-type "none")
+ (parameters
+ '("GHFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+
+
+;; From glib/gcompletion.h
+
+(define-function g_completion_new
+ (c-name "g_completion_new")
+ (return-type "GCompletion*")
+ (parameters
+ '("GCompletionFunc" "func")
+ )
+)
+
+(define-method add_items
+ (of-object "GCompletion")
+ (c-name "g_completion_add_items")
+ (return-type "none")
+ (parameters
+ '("GList*" "items")
+ )
+)
+
+(define-method remove_items
+ (of-object "GCompletion")
+ (c-name "g_completion_remove_items")
+ (return-type "none")
+ (parameters
+ '("GList*" "items")
+ )
+)
+
+(define-method clear_items
+ (of-object "GCompletion")
+ (c-name "g_completion_clear_items")
+ (return-type "none")
+)
+
+(define-method complete
+ (of-object "GCompletion")
+ (c-name "g_completion_complete")
+ (return-type "GList*")
+ (parameters
+ '("gchar*" "prefix")
+ '("gchar**" "new_prefix")
+ )
+)
+
+(define-method set_compare
+ (of-object "GCompletion")
+ (c-name "g_completion_set_compare")
+ (return-type "none")
+ (parameters
+ '("GCompletionStrncmpFunc" "strncmp_func")
+ )
+)
+
+(define-method free
+ (of-object "GCompletion")
+ (c-name "g_completion_free")
+ (return-type "none")
+)
+
+
+
+;; From glib/gconvert.h
+
+(define-function g_iconv_open
+ (c-name "g_iconv_open")
+ (return-type "GIConv")
+ (parameters
+ '("const-gchar*" "to_codeset")
+ '("const-gchar*" "from_codeset")
+ )
+)
+
+(define-method iconv
+ (of-object "GIConv")
+ (c-name "g_iconv")
+ (return-type "size_t")
+ (parameters
+ '("gchar**" "inbuf")
+ '("gsize*" "inbytes_left")
+ '("gchar**" "outbuf")
+ '("gsize*" "outbytes_left")
+ )
+)
+
+(define-method close
+ (of-object "GIConv")
+ (c-name "g_iconv_close")
+ (return-type "gint")
+)
+
+(define-function g_convert
+ (c-name "g_convert")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ '("const-gchar*" "to_codeset")
+ '("const-gchar*" "from_codeset")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_convert_with_iconv
+ (c-name "g_convert_with_iconv")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ '("GIConv" "converter")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_convert_with_fallback
+ (c-name "g_convert_with_fallback")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ '("const-gchar*" "to_codeset")
+ '("const-gchar*" "from_codeset")
+ '("gchar*" "fallback")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_locale_to_utf8
+ (c-name "g_locale_to_utf8")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "opsysstring")
+ '("gssize" "len")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_locale_from_utf8
+ (c-name "g_locale_from_utf8")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "utf8string")
+ '("gssize" "len")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_filename_to_utf8
+ (c-name "g_filename_to_utf8")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "opsysstring")
+ '("gssize" "len")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_filename_from_utf8
+ (c-name "g_filename_from_utf8")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "utf8string")
+ '("gssize" "len")
+ '("gsize*" "bytes_read")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_filename_from_uri
+ (c-name "g_filename_from_uri")
+ (return-type "gchar*")
+ (parameters
+ '("const-char*" "uri")
+ '("char**" "hostname")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_filename_to_uri
+ (c-name "g_filename_to_uri")
+ (return-type "gchar*")
+ (parameters
+ '("const-char*" "filename")
+ '("const-char*" "hostname")
+ '("GError**" "error")
+ )
+)
+
+
+
+;; From glib/gdataset.h
+
+(define-function g_datalist_clear
+ (c-name "g_datalist_clear")
+ (return-type "none")
+ (parameters
+ '("GData**" "datalist")
+ )
+)
+
+(define-function g_datalist_id_get_data
+ (c-name "g_datalist_id_get_data")
+ (return-type "gpointer")
+ (parameters
+ '("GData**" "datalist")
+ '("GQuark" "key_id")
+ )
+)
+
+(define-function g_datalist_id_set_data_full
+ (c-name "g_datalist_id_set_data_full")
+ (return-type "none")
+ (parameters
+ '("GData**" "datalist")
+ '("GQuark" "key_id")
+ '("gpointer" "data")
+ '("GDestroyNotify" "destroy_func")
+ )
+)
+
+(define-function g_datalist_id_remove_no_notify
+ (c-name "g_datalist_id_remove_no_notify")
+ (return-type "gpointer")
+ (parameters
+ '("GData**" "datalist")
+ '("GQuark" "key_id")
+ )
+)
+
+(define-function g_datalist_foreach
+ (c-name "g_datalist_foreach")
+ (return-type "none")
+ (parameters
+ '("GData**" "datalist")
+ '("GDataForeachFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-function g_dataset_id_get_data
+ (c-name "g_dataset_id_get_data")
+ (return-type "gpointer")
+ (parameters
+ '("gconstpointer" "dataset_location")
+ '("GQuark" "key_id")
+ )
+)
+
+(define-function g_dataset_id_set_data_full
+ (c-name "g_dataset_id_set_data_full")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "dataset_location")
+ '("GQuark" "key_id")
+ '("gpointer" "data")
+ '("GDestroyNotify" "destroy_func")
+ )
+)
+
+(define-function g_dataset_id_remove_no_notify
+ (c-name "g_dataset_id_remove_no_notify")
+ (return-type "gpointer")
+ (parameters
+ '("gconstpointer" "dataset_location")
+ '("GQuark" "key_id")
+ )
+)
+
+(define-function g_dataset_foreach
+ (c-name "g_dataset_foreach")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "dataset_location")
+ '("GDataForeachFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+
+
+;; From glib/gdate.h
+
+(define-function g_date_new
+ (c-name "g_date_new")
+ (return-type "GDate*")
+)
+
+(define-function g_date_new_dmy
+ (c-name "g_date_new_dmy")
+ (return-type "GDate*")
+ (parameters
+ '("GDateDay" "day")
+ '("GDateMonth" "month")
+ '("GDateYear" "year")
+ )
+)
+
+(define-function g_date_new_julian
+ (c-name "g_date_new_julian")
+ (return-type "GDate*")
+ (parameters
+ '("guint32" "julian_day")
+ )
+)
+
+(define-method free
+ (of-object "GDate")
+ (c-name "g_date_free")
+ (return-type "none")
+)
+
+(define-method valid
+ (of-object "GDate")
+ (c-name "g_date_valid")
+ (return-type "gboolean")
+)
+
+(define-function g_date_valid_day
+ (c-name "g_date_valid_day")
+ (return-type "gboolean")
+ (parameters
+ '("GDateDay" "day")
+ )
+)
+
+(define-function g_date_valid_month
+ (c-name "g_date_valid_month")
+ (return-type "gboolean")
+ (parameters
+ '("GDateMonth" "month")
+ )
+)
+
+(define-function g_date_valid_year
+ (c-name "g_date_valid_year")
+ (return-type "gboolean")
+ (parameters
+ '("GDateYear" "year")
+ )
+)
+
+(define-function g_date_valid_weekday
+ (c-name "g_date_valid_weekday")
+ (return-type "gboolean")
+ (parameters
+ '("GDateWeekday" "weekday")
+ )
+)
+
+(define-function g_date_valid_julian
+ (c-name "g_date_valid_julian")
+ (return-type "gboolean")
+ (parameters
+ '("guint32" "julian_date")
+ )
+)
+
+(define-function g_date_valid_dmy
+ (c-name "g_date_valid_dmy")
+ (return-type "gboolean")
+ (parameters
+ '("GDateDay" "day")
+ '("GDateMonth" "month")
+ '("GDateYear" "year")
+ )
+)
+
+(define-method get_weekday
+ (of-object "GDate")
+ (c-name "g_date_get_weekday")
+ (return-type "GDateWeekday")
+)
+
+(define-method get_month
+ (of-object "GDate")
+ (c-name "g_date_get_month")
+ (return-type "GDateMonth")
+)
+
+(define-method get_year
+ (of-object "GDate")
+ (c-name "g_date_get_year")
+ (return-type "GDateYear")
+)
+
+(define-method get_day
+ (of-object "GDate")
+ (c-name "g_date_get_day")
+ (return-type "GDateDay")
+)
+
+(define-method get_julian
+ (of-object "GDate")
+ (c-name "g_date_get_julian")
+ (return-type "guint32")
+)
+
+(define-method get_day_of_year
+ (of-object "GDate")
+ (c-name "g_date_get_day_of_year")
+ (return-type "guint")
+)
+
+(define-method get_monday_week_of_year
+ (of-object "GDate")
+ (c-name "g_date_get_monday_week_of_year")
+ (return-type "guint")
+)
+
+(define-method get_sunday_week_of_year
+ (of-object "GDate")
+ (c-name "g_date_get_sunday_week_of_year")
+ (return-type "guint")
+)
+
+(define-method clear
+ (of-object "GDate")
+ (c-name "g_date_clear")
+ (return-type "none")
+ (parameters
+ '("guint" "n_dates")
+ )
+)
+
+(define-method set_parse
+ (of-object "GDate")
+ (c-name "g_date_set_parse")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "str")
+ )
+)
+
+(define-method set_time
+ (of-object "GDate")
+ (c-name "g_date_set_time")
+ (return-type "none")
+ (parameters
+ '("GTime" "time")
+ )
+)
+
+(define-method set_month
+ (of-object "GDate")
+ (c-name "g_date_set_month")
+ (return-type "none")
+ (parameters
+ '("GDateMonth" "month")
+ )
+)
+
+(define-method set_day
+ (of-object "GDate")
+ (c-name "g_date_set_day")
+ (return-type "none")
+ (parameters
+ '("GDateDay" "day")
+ )
+)
+
+(define-method set_year
+ (of-object "GDate")
+ (c-name "g_date_set_year")
+ (return-type "none")
+ (parameters
+ '("GDateYear" "year")
+ )
+)
+
+(define-method set_dmy
+ (of-object "GDate")
+ (c-name "g_date_set_dmy")
+ (return-type "none")
+ (parameters
+ '("GDateDay" "day")
+ '("GDateMonth" "month")
+ '("GDateYear" "y")
+ )
+)
+
+(define-method set_julian
+ (of-object "GDate")
+ (c-name "g_date_set_julian")
+ (return-type "none")
+ (parameters
+ '("guint32" "julian_date")
+ )
+)
+
+(define-method is_first_of_month
+ (of-object "GDate")
+ (c-name "g_date_is_first_of_month")
+ (return-type "gboolean")
+)
+
+(define-method is_last_of_month
+ (of-object "GDate")
+ (c-name "g_date_is_last_of_month")
+ (return-type "gboolean")
+)
+
+(define-method add_days
+ (of-object "GDate")
+ (c-name "g_date_add_days")
+ (return-type "none")
+ (parameters
+ '("guint" "n_days")
+ )
+)
+
+(define-method subtract_days
+ (of-object "GDate")
+ (c-name "g_date_subtract_days")
+ (return-type "none")
+ (parameters
+ '("guint" "n_days")
+ )
+)
+
+(define-method add_months
+ (of-object "GDate")
+ (c-name "g_date_add_months")
+ (return-type "none")
+ (parameters
+ '("guint" "n_months")
+ )
+)
+
+(define-method subtract_months
+ (of-object "GDate")
+ (c-name "g_date_subtract_months")
+ (return-type "none")
+ (parameters
+ '("guint" "n_months")
+ )
+)
+
+(define-method add_years
+ (of-object "GDate")
+ (c-name "g_date_add_years")
+ (return-type "none")
+ (parameters
+ '("guint" "n_years")
+ )
+)
+
+(define-method subtract_years
+ (of-object "GDate")
+ (c-name "g_date_subtract_years")
+ (return-type "none")
+ (parameters
+ '("guint" "n_years")
+ )
+)
+
+(define-function g_date_is_leap_year
+ (c-name "g_date_is_leap_year")
+ (return-type "gboolean")
+ (parameters
+ '("GDateYear" "year")
+ )
+)
+
+(define-function g_date_get_days_in_month
+ (c-name "g_date_get_days_in_month")
+ (return-type "guint8")
+ (parameters
+ '("GDateMonth" "month")
+ '("GDateYear" "year")
+ )
+)
+
+(define-function g_date_get_monday_weeks_in_year
+ (c-name "g_date_get_monday_weeks_in_year")
+ (return-type "guint8")
+ (parameters
+ '("GDateYear" "year")
+ )
+)
+
+(define-function g_date_get_sunday_weeks_in_year
+ (c-name "g_date_get_sunday_weeks_in_year")
+ (return-type "guint8")
+ (parameters
+ '("GDateYear" "year")
+ )
+)
+
+(define-method days_between
+ (of-object "GDate")
+ (c-name "g_date_days_between")
+ (return-type "gint")
+ (parameters
+ '("const-GDate*" "date2")
+ )
+)
+
+(define-method compare
+ (of-object "GDate")
+ (c-name "g_date_compare")
+ (return-type "gint")
+ (parameters
+ '("const-GDate*" "rhs")
+ )
+)
+
+(define-method to_struct_tm
+ (of-object "GDate")
+ (c-name "g_date_to_struct_tm")
+ (return-type "none")
+ (parameters
+ '("struct-tm*" "tm")
+ )
+)
+
+(define-method clamp
+ (of-object "GDate")
+ (c-name "g_date_clamp")
+ (return-type "none")
+ (parameters
+ '("const-GDate*" "min_date")
+ '("const-GDate*" "max_date")
+ )
+)
+
+(define-method order
+ (of-object "GDate")
+ (c-name "g_date_order")
+ (return-type "none")
+ (parameters
+ '("GDate*" "date2")
+ )
+)
+
+(define-function g_date_strftime
+ (c-name "g_date_strftime")
+ (return-type "gsize")
+ (parameters
+ '("gchar*" "s")
+ '("gsize" "slen")
+ '("const-gchar*" "format")
+ '("const-GDate*" "date")
+ )
+)
+
+
+
+;; From glib/gdir.h
+
+(define-method read_name
+ (of-object "GDir")
+ (c-name "g_dir_read_name")
+ (return-type "const-gchar*")
+)
+
+(define-method rewind
+ (of-object "GDir")
+ (c-name "g_dir_rewind")
+ (return-type "none")
+)
+
+(define-method close
+ (of-object "GDir")
+ (c-name "g_dir_close")
+ (return-type "none")
+)
+
+
+
+;; From glib/gerror.h
+
+(define-function g_error_new
+ (c-name "g_error_new")
+ (return-type "GError*")
+ (parameters
+ '("GQuark" "domain")
+ '("gint" "code")
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-function g_error_new_literal
+ (c-name "g_error_new_literal")
+ (return-type "GError*")
+ (parameters
+ '("GQuark" "domain")
+ '("gint" "code")
+ '("const-gchar*" "message")
+ )
+)
+
+(define-method free
+ (of-object "GError")
+ (c-name "g_error_free")
+ (return-type "none")
+)
+
+(define-method copy
+ (of-object "GError")
+ (c-name "g_error_copy")
+ (return-type "GError*")
+)
+
+(define-method matches
+ (of-object "GError")
+ (c-name "g_error_matches")
+ (return-type "gboolean")
+ (parameters
+ '("GQuark" "domain")
+ '("gint" "code")
+ )
+)
+
+(define-function g_set_error
+ (c-name "g_set_error")
+ (return-type "none")
+ (parameters
+ '("GError**" "err")
+ '("GQuark" "domain")
+ '("gint" "code")
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-function g_propagate_error
+ (c-name "g_propagate_error")
+ (return-type "none")
+ (parameters
+ '("GError**" "dest")
+ '("GError*" "src")
+ )
+)
+
+(define-function g_clear_error
+ (c-name "g_clear_error")
+ (return-type "none")
+ (parameters
+ '("GError**" "err")
+ )
+)
+
+
+
+;; From glib/gfileutils.h
+
+(define-function g_file_error_from_errno
+ (c-name "g_file_error_from_errno")
+ (return-type "GFileError")
+ (parameters
+ '("gint" "err_no")
+ )
+)
+
+(define-function g_file_test
+ (c-name "g_file_test")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "filename")
+ '("GFileTest" "test")
+ )
+)
+
+(define-function g_file_get_contents
+ (c-name "g_file_get_contents")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "filename")
+ '("gchar**" "contents")
+ '("gsize*" "length")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_mkstemp
+ (c-name "g_mkstemp")
+ (return-type "int")
+ (parameters
+ '("char*" "tmpl")
+ )
+)
+
+(define-function g_file_open_tmp
+ (c-name "g_file_open_tmp")
+ (return-type "int")
+ (parameters
+ '("const-char*" "tmpl")
+ '("char**" "name_used")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_build_path
+ (c-name "g_build_path")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "separator")
+ '("const-gchar*" "first_element")
+ )
+ (varargs #t)
+)
+
+(define-function g_build_filename
+ (c-name "g_build_filename")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "first_element")
+ )
+ (varargs #t)
+)
+
+
+
+;; From glib/ghash.h
+
+(define-function g_hash_table_new_full
+ (c-name "g_hash_table_new_full")
+ (return-type "GHashTable*")
+ (parameters
+ '("GHashFunc" "hash_func")
+ '("GEqualFunc" "key_equal_func")
+ '("GDestroyNotify" "key_destroy_func")
+ '("GDestroyNotify" "value_destroy_func")
+ )
+)
+
+(define-method destroy
+ (of-object "GHashTable")
+ (c-name "g_hash_table_destroy")
+ (return-type "none")
+)
+
+(define-method insert
+ (of-object "GHashTable")
+ (c-name "g_hash_table_insert")
+ (return-type "none")
+ (parameters
+ '("gpointer" "key")
+ '("gpointer" "value")
+ )
+)
+
+(define-method replace
+ (of-object "GHashTable")
+ (c-name "g_hash_table_replace")
+ (return-type "none")
+ (parameters
+ '("gpointer" "key")
+ '("gpointer" "value")
+ )
+)
+
+(define-method remove
+ (of-object "GHashTable")
+ (c-name "g_hash_table_remove")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "key")
+ )
+)
+
+(define-method steal
+ (of-object "GHashTable")
+ (c-name "g_hash_table_steal")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "key")
+ )
+)
+
+(define-method lookup
+ (of-object "GHashTable")
+ (c-name "g_hash_table_lookup")
+ (return-type "gpointer")
+ (parameters
+ '("gconstpointer" "key")
+ )
+)
+
+(define-method lookup_extended
+ (of-object "GHashTable")
+ (c-name "g_hash_table_lookup_extended")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "lookup_key")
+ '("gpointer*" "orig_key")
+ '("gpointer*" "value")
+ )
+)
+
+(define-method foreach
+ (of-object "GHashTable")
+ (c-name "g_hash_table_foreach")
+ (return-type "none")
+ (parameters
+ '("GHFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method foreach_remove
+ (of-object "GHashTable")
+ (c-name "g_hash_table_foreach_remove")
+ (return-type "guint")
+ (parameters
+ '("GHRFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method foreach_steal
+ (of-object "GHashTable")
+ (c-name "g_hash_table_foreach_steal")
+ (return-type "guint")
+ (parameters
+ '("GHRFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method size
+ (of-object "GHashTable")
+ (c-name "g_hash_table_size")
+ (return-type "guint")
+)
+
+(define-function g_str_equal
+ (c-name "g_str_equal")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "v")
+ '("gconstpointer" "v2")
+ )
+)
+
+(define-function g_str_hash
+ (c-name "g_str_hash")
+ (return-type "guint")
+ (parameters
+ '("gconstpointer" "v")
+ )
+)
+
+(define-function g_int_equal
+ (c-name "g_int_equal")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "v")
+ '("gconstpointer" "v2")
+ )
+)
+
+(define-function g_int_hash
+ (c-name "g_int_hash")
+ (return-type "guint")
+ (parameters
+ '("gconstpointer" "v")
+ )
+)
+
+(define-function g_direct_hash
+ (c-name "g_direct_hash")
+ (return-type "guint")
+ (parameters
+ '("gconstpointer" "v")
+ )
+)
+
+(define-function g_direct_equal
+ (c-name "g_direct_equal")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "v")
+ '("gconstpointer" "v2")
+ )
+)
+
+
+
+;; From glib/ghook.h
+
+(define-method clear
+ (of-object "GHookList")
+ (c-name "g_hook_list_clear")
+ (return-type "none")
+)
+
+(define-function g_hook_alloc
+ (c-name "g_hook_alloc")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ )
+)
+
+(define-function g_hook_free
+ (c-name "g_hook_free")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ )
+)
+
+(define-function g_hook_ref
+ (c-name "g_hook_ref")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ )
+)
+
+(define-function g_hook_unref
+ (c-name "g_hook_unref")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ )
+)
+
+(define-function g_hook_destroy
+ (c-name "g_hook_destroy")
+ (return-type "gboolean")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gulong" "hook_id")
+ )
+)
+
+(define-function g_hook_destroy_link
+ (c-name "g_hook_destroy_link")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ )
+)
+
+(define-function g_hook_prepend
+ (c-name "g_hook_prepend")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ )
+)
+
+(define-function g_hook_insert_before
+ (c-name "g_hook_insert_before")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "sibling")
+ '("GHook*" "hook")
+ )
+)
+
+(define-function g_hook_insert_sorted
+ (c-name "g_hook_insert_sorted")
+ (return-type "none")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ '("GHookCompareFunc" "func")
+ )
+)
+
+(define-function g_hook_get
+ (c-name "g_hook_get")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gulong" "hook_id")
+ )
+)
+
+(define-function g_hook_find
+ (c-name "g_hook_find")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gboolean" "need_valids")
+ '("GHookFindFunc" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_hook_find_data
+ (c-name "g_hook_find_data")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gboolean" "need_valids")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_hook_find_func
+ (c-name "g_hook_find_func")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gboolean" "need_valids")
+ '("gpointer" "func")
+ )
+)
+
+(define-function g_hook_find_func_data
+ (c-name "g_hook_find_func_data")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gboolean" "need_valids")
+ '("gpointer" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_hook_first_valid
+ (c-name "g_hook_first_valid")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("gboolean" "may_be_in_call")
+ )
+)
+
+(define-function g_hook_next_valid
+ (c-name "g_hook_next_valid")
+ (return-type "GHook*")
+ (parameters
+ '("GHookList*" "hook_list")
+ '("GHook*" "hook")
+ '("gboolean" "may_be_in_call")
+ )
+)
+
+(define-method compare_ids
+ (of-object "GHook")
+ (c-name "g_hook_compare_ids")
+ (return-type "gint")
+ (parameters
+ '("GHook*" "sibling")
+ )
+)
+
+(define-method invoke_check
+ (of-object "GHookList")
+ (c-name "g_hook_list_invoke_check")
+ (return-type "none")
+ (parameters
+ '("gboolean" "may_recurse")
+ )
+)
+
+(define-method marshal
+ (of-object "GHookList")
+ (c-name "g_hook_list_marshal")
+ (return-type "none")
+ (parameters
+ '("gboolean" "may_recurse")
+ '("GHookMarshaller" "marshaller")
+ '("gpointer" "marshal_data")
+ )
+)
+
+(define-method marshal_check
+ (of-object "GHookList")
+ (c-name "g_hook_list_marshal_check")
+ (return-type "none")
+ (parameters
+ '("gboolean" "may_recurse")
+ '("GHookCheckMarshaller" "marshaller")
+ '("gpointer" "marshal_data")
+ )
+)
+
+
+
+;; From glib/giochannel.h
+
+(define-method init
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_init")
+ (return-type "none")
+)
+
+(define-method ref
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_ref")
+ (return-type "none")
+)
+
+(define-method unref
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_unref")
+ (return-type "none")
+)
+
+(define-method read
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_read")
+ (return-type "GIOError")
+ (parameters
+ '("gchar*" "buf")
+ '("gsize" "count")
+ '("gsize*" "bytes_read")
+ )
+)
+
+(define-method write
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_write")
+ (return-type "GIOError")
+ (parameters
+ '("const-gchar*" "buf")
+ '("gsize" "count")
+ '("gsize*" "bytes_written")
+ )
+)
+
+(define-method seek
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_seek")
+ (return-type "GIOError")
+ (parameters
+ '("gint64" "offset")
+ '("GSeekType" "type")
+ )
+)
+
+(define-method close
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_close")
+ (return-type "none")
+)
+
+(define-method shutdown
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_shutdown")
+ (return-type "GIOStatus")
+ (parameters
+ '("gboolean" "flush")
+ '("GError**" "err")
+ )
+)
+
+(define-function g_io_add_watch_full
+ (c-name "g_io_add_watch_full")
+ (return-type "guint")
+ (parameters
+ '("GIOChannel*" "channel")
+ '("gint" "priority")
+ '("GIOCondition" "condition")
+ '("GIOFunc" "func")
+ '("gpointer" "user_data")
+ '("GDestroyNotify" "notify")
+ )
+)
+
+(define-function g_io_create_watch
+ (c-name "g_io_create_watch")
+ (return-type "GSource*")
+ (parameters
+ '("GIOChannel*" "channel")
+ '("GIOCondition" "condition")
+ )
+)
+
+(define-function g_io_add_watch
+ (c-name "g_io_add_watch")
+ (return-type "guint")
+ (parameters
+ '("GIOChannel*" "channel")
+ '("GIOCondition" "condition")
+ '("GIOFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method set_buffer_size
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_set_buffer_size")
+ (return-type "none")
+ (parameters
+ '("gsize" "size")
+ )
+)
+
+(define-method get_buffer_size
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_buffer_size")
+ (return-type "gsize")
+)
+
+(define-method get_buffer_condition
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_buffer_condition")
+ (return-type "GIOCondition")
+)
+
+(define-method set_flags
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_set_flags")
+ (return-type "GIOStatus")
+ (parameters
+ '("GIOFlags" "flags")
+ '("GError**" "error")
+ )
+)
+
+(define-method get_flags
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_flags")
+ (return-type "GIOFlags")
+)
+
+(define-method set_line_term
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_set_line_term")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "line_term")
+ '("gint" "length")
+ )
+)
+
+(define-method get_line_term
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_line_term")
+ (return-type "const-gchar*")
+ (parameters
+ '("gint*" "length")
+ )
+)
+
+(define-method set_buffered
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_set_buffered")
+ (return-type "none")
+ (parameters
+ '("gboolean" "buffered")
+ )
+)
+
+(define-method get_buffered
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_buffered")
+ (return-type "gboolean")
+)
+
+(define-method set_encoding
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_set_encoding")
+ (return-type "GIOStatus")
+ (parameters
+ '("const-gchar*" "encoding")
+ '("GError**" "error")
+ )
+)
+
+(define-method get_encoding
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_encoding")
+ (return-type "const-gchar*")
+)
+
+(define-method set_close_on_unref
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_set_close_on_unref")
+ (return-type "none")
+ (parameters
+ '("gboolean" "do_close")
+ )
+)
+
+(define-method get_close_on_unref
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_get_close_on_unref")
+ (return-type "gboolean")
+)
+
+(define-method flush
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_flush")
+ (return-type "GIOStatus")
+ (parameters
+ '("GError**" "error")
+ )
+)
+
+(define-method read_line
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_read_line")
+ (return-type "GIOStatus")
+ (parameters
+ '("gchar**" "str_return")
+ '("gsize*" "length")
+ '("gsize*" "terminator_pos")
+ '("GError**" "error")
+ )
+)
+
+(define-method read_line_string
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_read_line_string")
+ (return-type "GIOStatus")
+ (parameters
+ '("GString*" "buffer")
+ '("gsize*" "terminator_pos")
+ '("GError**" "error")
+ )
+)
+
+(define-method read_to_end
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_read_to_end")
+ (return-type "GIOStatus")
+ (parameters
+ '("gchar**" "str_return")
+ '("gsize*" "length")
+ '("GError**" "error")
+ )
+)
+
+(define-method read_chars
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_read_chars")
+ (return-type "GIOStatus")
+ (parameters
+ '("gchar*" "buf")
+ '("gsize" "count")
+ '("gsize*" "bytes_read")
+ '("GError**" "error")
+ )
+)
+
+(define-method read_unichar
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_read_unichar")
+ (return-type "GIOStatus")
+ (parameters
+ '("gunichar*" "thechar")
+ '("GError**" "error")
+ )
+)
+
+(define-method write_chars
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_write_chars")
+ (return-type "GIOStatus")
+ (parameters
+ '("const-gchar*" "buf")
+ '("gssize" "count")
+ '("gsize*" "bytes_written")
+ '("GError**" "error")
+ )
+)
+
+(define-method write_unichar
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_write_unichar")
+ (return-type "GIOStatus")
+ (parameters
+ '("gunichar" "thechar")
+ '("GError**" "error")
+ )
+)
+
+(define-method seek_position
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_seek_position")
+ (return-type "GIOStatus")
+ (parameters
+ '("gint64" "offset")
+ '("GSeekType" "type")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_io_channel_new_file
+ (c-name "g_io_channel_new_file")
+ (return-type "GIOChannel*")
+ (parameters
+ '("const-gchar*" "filename")
+ '("const-gchar*" "mode")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_io_channel_error_quark
+ (c-name "g_io_channel_error_quark")
+ (return-type "GQuark")
+)
+
+(define-function g_io_channel_error_from_errno
+ (c-name "g_io_channel_error_from_errno")
+ (return-type "GIOChannelError")
+ (parameters
+ '("gint" "en")
+ )
+)
+
+(define-function g_io_channel_unix_new
+ (c-name "g_io_channel_unix_new")
+ (return-type "GIOChannel*")
+ (parameters
+ '("int" "fd")
+ )
+)
+
+(define-method unix_get_fd
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_unix_get_fd")
+ (return-type "gint")
+)
+
+(define-method win32_make_pollfd
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_win32_make_pollfd")
+ (return-type "none")
+ (parameters
+ '("GIOCondition" "condition")
+ '("GPollFD*" "fd")
+ )
+)
+
+(define-function g_io_channel_win32_poll
+ (c-name "g_io_channel_win32_poll")
+ (return-type "gint")
+ (parameters
+ '("GPollFD*" "fds")
+ '("gint" "n_fds")
+ '("gint" "timeout")
+ )
+)
+
+(define-function g_main_poll_win32_msg_add
+ (c-name "g_main_poll_win32_msg_add")
+ (return-type "none")
+ (parameters
+ '("gint" "priority")
+ '("GPollFD*" "fd")
+ '("guint" "hwnd")
+ )
+)
+
+(define-function g_io_channel_win32_new_messages
+ (c-name "g_io_channel_win32_new_messages")
+ (return-type "GIOChannel*")
+ (parameters
+ '("guint" "hwnd")
+ )
+)
+
+(define-function g_io_channel_win32_new_fd
+ (c-name "g_io_channel_win32_new_fd")
+ (return-type "GIOChannel*")
+ (parameters
+ '("gint" "fd")
+ )
+)
+
+(define-method win32_get_fd
+ (of-object "GIOChannel")
+ (c-name "g_io_channel_win32_get_fd")
+ (return-type "gint")
+)
+
+(define-function g_io_channel_win32_new_socket
+ (c-name "g_io_channel_win32_new_socket")
+ (return-type "GIOChannel*")
+ (parameters
+ '("gint" "socket")
+ )
+)
+
+
+
+;; From glib/glist.h
+
+(define-function g_list_push_allocator
+ (c-name "g_list_push_allocator")
+ (return-type "none")
+ (parameters
+ '("GAllocator*" "allocator")
+ )
+)
+
+(define-function g_list_pop_allocator
+ (c-name "g_list_pop_allocator")
+ (return-type "none")
+)
+
+(define-function g_list_alloc
+ (c-name "g_list_alloc")
+ (return-type "GList*")
+)
+
+(define-method free
+ (of-object "GList")
+ (c-name "g_list_free")
+ (return-type "none")
+)
+
+(define-method free_1
+ (of-object "GList")
+ (c-name "g_list_free_1")
+ (return-type "none")
+)
+
+(define-method append
+ (of-object "GList")
+ (c-name "g_list_append")
+ (return-type "GList*")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method prepend
+ (of-object "GList")
+ (c-name "g_list_prepend")
+ (return-type "GList*")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method insert
+ (of-object "GList")
+ (c-name "g_list_insert")
+ (return-type "GList*")
+ (parameters
+ '("gpointer" "data")
+ '("gint" "position")
+ )
+)
+
+(define-method insert_sorted
+ (of-object "GList")
+ (c-name "g_list_insert_sorted")
+ (return-type "GList*")
+ (parameters
+ '("gpointer" "data")
+ '("GCompareFunc" "func")
+ )
+)
+
+(define-method insert_before
+ (of-object "GList")
+ (c-name "g_list_insert_before")
+ (return-type "GList*")
+ (parameters
+ '("GList*" "sibling")
+ '("gpointer" "data")
+ )
+)
+
+(define-method concat
+ (of-object "GList")
+ (c-name "g_list_concat")
+ (return-type "GList*")
+ (parameters
+ '("GList*" "list2")
+ )
+)
+
+(define-method remove
+ (of-object "GList")
+ (c-name "g_list_remove")
+ (return-type "GList*")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method remove_all
+ (of-object "GList")
+ (c-name "g_list_remove_all")
+ (return-type "GList*")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method remove_link
+ (of-object "GList")
+ (c-name "g_list_remove_link")
+ (return-type "GList*")
+ (parameters
+ '("GList*" "llink")
+ )
+)
+
+(define-method delete_link
+ (of-object "GList")
+ (c-name "g_list_delete_link")
+ (return-type "GList*")
+ (parameters
+ '("GList*" "link")
+ )
+)
+
+(define-method reverse
+ (of-object "GList")
+ (c-name "g_list_reverse")
+ (return-type "GList*")
+)
+
+(define-method copy
+ (of-object "GList")
+ (c-name "g_list_copy")
+ (return-type "GList*")
+)
+
+(define-method nth
+ (of-object "GList")
+ (c-name "g_list_nth")
+ (return-type "GList*")
+ (parameters
+ '("guint" "n")
+ )
+)
+
+(define-method nth_prev
+ (of-object "GList")
+ (c-name "g_list_nth_prev")
+ (return-type "GList*")
+ (parameters
+ '("guint" "n")
+ )
+)
+
+(define-method find
+ (of-object "GList")
+ (c-name "g_list_find")
+ (return-type "GList*")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method find_custom
+ (of-object "GList")
+ (c-name "g_list_find_custom")
+ (return-type "GList*")
+ (parameters
+ '("gconstpointer" "data")
+ '("GCompareFunc" "func")
+ )
+)
+
+(define-method position
+ (of-object "GList")
+ (c-name "g_list_position")
+ (return-type "gint")
+ (parameters
+ '("GList*" "llink")
+ )
+)
+
+(define-method index
+ (of-object "GList")
+ (c-name "g_list_index")
+ (return-type "gint")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method last
+ (of-object "GList")
+ (c-name "g_list_last")
+ (return-type "GList*")
+)
+
+(define-method first
+ (of-object "GList")
+ (c-name "g_list_first")
+ (return-type "GList*")
+)
+
+(define-method length
+ (of-object "GList")
+ (c-name "g_list_length")
+ (return-type "guint")
+)
+
+(define-method foreach
+ (of-object "GList")
+ (c-name "g_list_foreach")
+ (return-type "none")
+ (parameters
+ '("GFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method sort
+ (of-object "GList")
+ (c-name "g_list_sort")
+ (return-type "GList*")
+ (parameters
+ '("GCompareFunc" "compare_func")
+ )
+)
+
+(define-method sort_with_data
+ (of-object "GList")
+ (c-name "g_list_sort_with_data")
+ (return-type "GList*")
+ (parameters
+ '("GCompareDataFunc" "compare_func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method nth_data
+ (of-object "GList")
+ (c-name "g_list_nth_data")
+ (return-type "gpointer")
+ (parameters
+ '("guint" "n")
+ )
+)
+
+
+
+;; From glib/gmacros.h
+
+
+
+;; From glib/gmain.h
+
+(define-function g_main_context_new
+ (c-name "g_main_context_new")
+ (return-type "GMainContext*")
+)
+
+(define-method ref
+ (of-object "GMainContext")
+ (c-name "g_main_context_ref")
+ (return-type "none")
+)
+
+(define-method unref
+ (of-object "GMainContext")
+ (c-name "g_main_context_unref")
+ (return-type "none")
+)
+
+(define-function g_main_context_default
+ (c-name "g_main_context_default")
+ (return-type "GMainContext*")
+)
+
+(define-method iteration
+ (of-object "GMainContext")
+ (c-name "g_main_context_iteration")
+ (return-type "gboolean")
+ (parameters
+ '("gboolean" "may_block")
+ )
+)
+
+(define-method pending
+ (of-object "GMainContext")
+ (c-name "g_main_context_pending")
+ (return-type "gboolean")
+)
+
+(define-method find_source_by_id
+ (of-object "GMainContext")
+ (c-name "g_main_context_find_source_by_id")
+ (return-type "GSource*")
+ (parameters
+ '("guint" "source_id")
+ )
+)
+
+(define-method find_source_by_user_data
+ (of-object "GMainContext")
+ (c-name "g_main_context_find_source_by_user_data")
+ (return-type "GSource*")
+ (parameters
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method find_source_by_funcs_user_data
+ (of-object "GMainContext")
+ (c-name "g_main_context_find_source_by_funcs_user_data")
+ (return-type "GSource*")
+ (parameters
+ '("GSourceFuncs*" "funcs")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method wakeup
+ (of-object "GMainContext")
+ (c-name "g_main_context_wakeup")
+ (return-type "none")
+)
+
+(define-method acquire
+ (of-object "GMainContext")
+ (c-name "g_main_context_acquire")
+ (return-type "gboolean")
+)
+
+(define-method release
+ (of-object "GMainContext")
+ (c-name "g_main_context_release")
+ (return-type "none")
+)
+
+(define-method wait
+ (of-object "GMainContext")
+ (c-name "g_main_context_wait")
+ (return-type "gboolean")
+ (parameters
+ '("GCond*" "cond")
+ '("GMutex*" "mutex")
+ )
+)
+
+(define-method prepare
+ (of-object "GMainContext")
+ (c-name "g_main_context_prepare")
+ (return-type "gboolean")
+ (parameters
+ '("gint*" "priority")
+ )
+)
+
+(define-method query
+ (of-object "GMainContext")
+ (c-name "g_main_context_query")
+ (return-type "gint")
+ (parameters
+ '("gint" "max_priority")
+ '("gint*" "timeout")
+ '("GPollFD*" "fds")
+ '("gint" "n_fds")
+ )
+)
+
+(define-method check
+ (of-object "GMainContext")
+ (c-name "g_main_context_check")
+ (return-type "gint")
+ (parameters
+ '("gint" "max_priority")
+ '("GPollFD*" "fds")
+ '("gint" "n_fds")
+ )
+)
+
+(define-method dispatch
+ (of-object "GMainContext")
+ (c-name "g_main_context_dispatch")
+ (return-type "none")
+)
+
+(define-method set_poll_func
+ (of-object "GMainContext")
+ (c-name "g_main_context_set_poll_func")
+ (return-type "none")
+ (parameters
+ '("GPollFunc" "func")
+ )
+)
+
+(define-method get_poll_func
+ (of-object "GMainContext")
+ (c-name "g_main_context_get_poll_func")
+ (return-type "GPollFunc")
+)
+
+(define-method add_poll
+ (of-object "GMainContext")
+ (c-name "g_main_context_add_poll")
+ (return-type "none")
+ (parameters
+ '("GPollFD*" "fd")
+ '("gint" "priority")
+ )
+)
+
+(define-method remove_poll
+ (of-object "GMainContext")
+ (c-name "g_main_context_remove_poll")
+ (return-type "none")
+ (parameters
+ '("GPollFD*" "fd")
+ )
+)
+
+(define-function g_main_loop_new
+ (c-name "g_main_loop_new")
+ (return-type "GMainLoop*")
+ (parameters
+ '("GMainContext*" "context")
+ '("gboolean" "is_running")
+ )
+)
+
+(define-method run
+ (of-object "GMainLoop")
+ (c-name "g_main_loop_run")
+ (return-type "none")
+)
+
+(define-method quit
+ (of-object "GMainLoop")
+ (c-name "g_main_loop_quit")
+ (return-type "none")
+)
+
+(define-method ref
+ (of-object "GMainLoop")
+ (c-name "g_main_loop_ref")
+ (return-type "GMainLoop*")
+)
+
+(define-method unref
+ (of-object "GMainLoop")
+ (c-name "g_main_loop_unref")
+ (return-type "none")
+)
+
+(define-method is_running
+ (of-object "GMainLoop")
+ (c-name "g_main_loop_is_running")
+ (return-type "gboolean")
+)
+
+(define-method get_context
+ (of-object "GMainLoop")
+ (c-name "g_main_loop_get_context")
+ (return-type "GMainContext*")
+)
+
+(define-function g_source_new
+ (c-name "g_source_new")
+ (return-type "GSource*")
+ (parameters
+ '("GSourceFuncs*" "source_funcs")
+ '("guint" "struct_size")
+ )
+)
+
+(define-method ref
+ (of-object "GSource")
+ (c-name "g_source_ref")
+ (return-type "GSource*")
+)
+
+(define-method unref
+ (of-object "GSource")
+ (c-name "g_source_unref")
+ (return-type "none")
+)
+
+(define-method attach
+ (of-object "GSource")
+ (c-name "g_source_attach")
+ (return-type "guint")
+ (parameters
+ '("GMainContext*" "context")
+ )
+)
+
+(define-method destroy
+ (of-object "GSource")
+ (c-name "g_source_destroy")
+ (return-type "none")
+)
+
+(define-method set_priority
+ (of-object "GSource")
+ (c-name "g_source_set_priority")
+ (return-type "none")
+ (parameters
+ '("gint" "priority")
+ )
+)
+
+(define-method get_priority
+ (of-object "GSource")
+ (c-name "g_source_get_priority")
+ (return-type "gint")
+)
+
+(define-method set_can_recurse
+ (of-object "GSource")
+ (c-name "g_source_set_can_recurse")
+ (return-type "none")
+ (parameters
+ '("gboolean" "can_recurse")
+ )
+)
+
+(define-method get_can_recurse
+ (of-object "GSource")
+ (c-name "g_source_get_can_recurse")
+ (return-type "gboolean")
+)
+
+(define-method get_id
+ (of-object "GSource")
+ (c-name "g_source_get_id")
+ (return-type "guint")
+)
+
+(define-method get_context
+ (of-object "GSource")
+ (c-name "g_source_get_context")
+ (return-type "GMainContext*")
+)
+
+(define-method set_callback
+ (of-object "GSource")
+ (c-name "g_source_set_callback")
+ (return-type "none")
+ (parameters
+ '("GSourceFunc" "func")
+ '("gpointer" "data")
+ '("GDestroyNotify" "notify")
+ )
+)
+
+(define-method set_callback_indirect
+ (of-object "GSource")
+ (c-name "g_source_set_callback_indirect")
+ (return-type "none")
+ (parameters
+ '("gpointer" "callback_data")
+ '("GSourceCallbackFuncs*" "callback_funcs")
+ )
+)
+
+(define-method add_poll
+ (of-object "GSource")
+ (c-name "g_source_add_poll")
+ (return-type "none")
+ (parameters
+ '("GPollFD*" "fd")
+ )
+)
+
+(define-method remove_poll
+ (of-object "GSource")
+ (c-name "g_source_remove_poll")
+ (return-type "none")
+ (parameters
+ '("GPollFD*" "fd")
+ )
+)
+
+(define-method get_current_time
+ (of-object "GSource")
+ (c-name "g_source_get_current_time")
+ (return-type "none")
+ (parameters
+ '("GTimeVal*" "timeval")
+ )
+)
+
+(define-function g_idle_source_new
+ (c-name "g_idle_source_new")
+ (return-type "GSource*")
+)
+
+(define-function g_timeout_source_new
+ (c-name "g_timeout_source_new")
+ (return-type "GSource*")
+ (parameters
+ '("guint" "interval")
+ )
+)
+
+(define-function g_get_current_time
+ (c-name "g_get_current_time")
+ (return-type "none")
+ (parameters
+ '("GTimeVal*" "result")
+ )
+)
+
+(define-function g_source_remove
+ (c-name "g_source_remove")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "tag")
+ )
+)
+
+(define-function g_source_remove_by_user_data
+ (c-name "g_source_remove_by_user_data")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "user_data")
+ )
+)
+
+(define-function g_source_remove_by_funcs_user_data
+ (c-name "g_source_remove_by_funcs_user_data")
+ (return-type "gboolean")
+ (parameters
+ '("GSourceFuncs*" "funcs")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-function g_timeout_add_full
+ (c-name "g_timeout_add_full")
+ (return-type "guint")
+ (parameters
+ '("gint" "priority")
+ '("guint" "interval")
+ '("GSourceFunc" "function")
+ '("gpointer" "data")
+ '("GDestroyNotify" "notify")
+ )
+)
+
+(define-function g_timeout_add
+ (c-name "g_timeout_add")
+ (return-type "guint")
+ (parameters
+ '("guint" "interval")
+ '("GSourceFunc" "function")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_idle_add
+ (c-name "g_idle_add")
+ (return-type "guint")
+ (parameters
+ '("GSourceFunc" "function")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_idle_add_full
+ (c-name "g_idle_add_full")
+ (return-type "guint")
+ (parameters
+ '("gint" "priority")
+ '("GSourceFunc" "function")
+ '("gpointer" "data")
+ '("GDestroyNotify" "notify")
+ )
+)
+
+(define-function g_idle_remove_by_data
+ (c-name "g_idle_remove_by_data")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_main_poll_win32_msg_add
+ (c-name "g_main_poll_win32_msg_add")
+ (return-type "none")
+ (parameters
+ '("gint" "priority")
+ '("GPollFD*" "fd")
+ '("guint" "hwnd")
+ )
+)
+
+
+
+;; From glib/gmarkup.h
+
+(define-function g_markup_parse_context_new
+ (c-name "g_markup_parse_context_new")
+ (return-type "GMarkupParseContext*")
+ (parameters
+ '("const-GMarkupParser*" "parser")
+ '("GMarkupParseFlags" "flags")
+ '("gpointer" "user_data")
+ '("GDestroyNotify" "user_data_dnotify")
+ )
+)
+
+(define-method free
+ (of-object "GMarkupParseContext")
+ (c-name "g_markup_parse_context_free")
+ (return-type "none")
+)
+
+(define-method parse
+ (of-object "GMarkupParseContext")
+ (c-name "g_markup_parse_context_parse")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "text")
+ '("gssize" "text_len")
+ '("GError**" "error")
+ )
+)
+
+(define-method end_parse
+ (of-object "GMarkupParseContext")
+ (c-name "g_markup_parse_context_end_parse")
+ (return-type "gboolean")
+ (parameters
+ '("GError**" "error")
+ )
+)
+
+(define-method get_position
+ (of-object "GMarkupParseContext")
+ (c-name "g_markup_parse_context_get_position")
+ (return-type "none")
+ (parameters
+ '("gint*" "line_number")
+ '("gint*" "char_number")
+ )
+)
+
+(define-function g_markup_escape_text
+ (c-name "g_markup_escape_text")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "text")
+ '("gssize" "length")
+ )
+)
+
+
+
+;; From glib/gmem.h
+
+(define-function g_malloc0
+ (c-name "g_malloc0")
+ (return-type "gpointer")
+ (parameters
+ '("gulong" "n_bytes")
+ )
+)
+
+(define-function g_realloc
+ (c-name "g_realloc")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "mem")
+ '("gulong" "n_bytes")
+ )
+)
+
+(define-function g_free
+ (c-name "g_free")
+ (return-type "none")
+ (parameters
+ '("gpointer" "mem")
+ )
+)
+
+(define-function g_try_malloc
+ (c-name "g_try_malloc")
+ (return-type "gpointer")
+ (parameters
+ '("gulong" "n_bytes")
+ )
+)
+
+(define-function g_try_realloc
+ (c-name "g_try_realloc")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "mem")
+ '("gulong" "n_bytes")
+ )
+)
+
+(define-function g_mem_set_vtable
+ (c-name "g_mem_set_vtable")
+ (return-type "none")
+ (parameters
+ '("GMemVTable*" "vtable")
+ )
+)
+
+(define-function g_mem_is_system_malloc
+ (c-name "g_mem_is_system_malloc")
+ (return-type "gboolean")
+)
+
+(define-function g_mem_profile
+ (c-name "g_mem_profile")
+ (return-type "none")
+)
+
+(define-method destroy
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_destroy")
+ (return-type "none")
+)
+
+(define-method alloc
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_alloc")
+ (return-type "gpointer")
+)
+
+(define-method alloc0
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_alloc0")
+ (return-type "gpointer")
+)
+
+(define-method free
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_free")
+ (return-type "none")
+ (parameters
+ '("gpointer" "mem")
+ )
+)
+
+(define-method clean
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_clean")
+ (return-type "none")
+)
+
+(define-method reset
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_reset")
+ (return-type "none")
+)
+
+(define-method print
+ (of-object "GMemChunk")
+ (c-name "g_mem_chunk_print")
+ (return-type "none")
+)
+
+(define-function g_mem_chunk_info
+ (c-name "g_mem_chunk_info")
+ (return-type "none")
+)
+
+(define-function g_blow_chunks
+ (c-name "g_blow_chunks")
+ (return-type "none")
+)
+
+(define-function g_allocator_new
+ (c-name "g_allocator_new")
+ (return-type "GAllocator*")
+ (parameters
+ '("const-gchar*" "name")
+ '("guint" "n_preallocs")
+ )
+)
+
+(define-method free
+ (of-object "GAllocator")
+ (c-name "g_allocator_free")
+ (return-type "none")
+)
+
+
+
+;; From glib/gmessages.h
+
+(define-function g_log_set_handler
+ (c-name "g_log_set_handler")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("GLogLevelFlags" "log_levels")
+ '("GLogFunc" "log_func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-function g_log_remove_handler
+ (c-name "g_log_remove_handler")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("guint" "handler_id")
+ )
+)
+
+(define-function g_log_default_handler
+ (c-name "g_log_default_handler")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("GLogLevelFlags" "log_level")
+ '("const-gchar*" "message")
+ '("gpointer" "unused_data")
+ )
+)
+
+(define-function g_log
+ (c-name "g_log")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("GLogLevelFlags" "log_level")
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-function g_logv
+ (c-name "g_logv")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("GLogLevelFlags" "log_level")
+ '("const-gchar*" "format")
+ '("va_list" "args")
+ )
+)
+
+(define-function g_log_set_fatal_mask
+ (c-name "g_log_set_fatal_mask")
+ (return-type "GLogLevelFlags")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("GLogLevelFlags" "fatal_mask")
+ )
+)
+
+(define-function g_log_set_always_fatal
+ (c-name "g_log_set_always_fatal")
+ (return-type "GLogLevelFlags")
+ (parameters
+ '("GLogLevelFlags" "fatal_mask")
+ )
+)
+
+(define-function _g_log_fallback_handler
+ (c-name "_g_log_fallback_handler")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "log_domain")
+ '("GLogLevelFlags" "log_level")
+ '("const-gchar*" "message")
+ '("gpointer" "unused_data")
+ )
+)
+
+(define-function g_set_print_handler
+ (c-name "g_set_print_handler")
+ (return-type "GPrintFunc")
+ (parameters
+ '("GPrintFunc" "func")
+ )
+)
+
+(define-function g_printerr
+ (c-name "g_printerr")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-function g_set_printerr_handler
+ (c-name "g_set_printerr_handler")
+ (return-type "GPrintFunc")
+ (parameters
+ '("GPrintFunc" "func")
+ )
+)
+
+
+
+;; From glib/gnode.h
+
+(define-function g_node_pop_allocator
+ (c-name "g_node_pop_allocator")
+ (return-type "none")
+)
+
+(define-function g_node_new
+ (c-name "g_node_new")
+ (return-type "GNode*")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method destroy
+ (of-object "GNode")
+ (c-name "g_node_destroy")
+ (return-type "none")
+)
+
+(define-method unlink
+ (of-object "GNode")
+ (c-name "g_node_unlink")
+ (return-type "none")
+)
+
+(define-method copy
+ (of-object "GNode")
+ (c-name "g_node_copy")
+ (return-type "GNode*")
+)
+
+(define-method insert
+ (of-object "GNode")
+ (c-name "g_node_insert")
+ (return-type "GNode*")
+ (parameters
+ '("gint" "position")
+ '("GNode*" "node")
+ )
+)
+
+(define-method insert_before
+ (of-object "GNode")
+ (c-name "g_node_insert_before")
+ (return-type "GNode*")
+ (parameters
+ '("GNode*" "sibling")
+ '("GNode*" "node")
+ )
+)
+
+(define-method insert_after
+ (of-object "GNode")
+ (c-name "g_node_insert_after")
+ (return-type "GNode*")
+ (parameters
+ '("GNode*" "sibling")
+ '("GNode*" "node")
+ )
+)
+
+(define-method prepend
+ (of-object "GNode")
+ (c-name "g_node_prepend")
+ (return-type "GNode*")
+ (parameters
+ '("GNode*" "node")
+ )
+)
+
+(define-method n_nodes
+ (of-object "GNode")
+ (c-name "g_node_n_nodes")
+ (return-type "guint")
+ (parameters
+ '("GTraverseFlags" "flags")
+ )
+)
+
+(define-method get_root
+ (of-object "GNode")
+ (c-name "g_node_get_root")
+ (return-type "GNode*")
+)
+
+(define-method is_ancestor
+ (of-object "GNode")
+ (c-name "g_node_is_ancestor")
+ (return-type "gboolean")
+ (parameters
+ '("GNode*" "descendant")
+ )
+)
+
+(define-method depth
+ (of-object "GNode")
+ (c-name "g_node_depth")
+ (return-type "guint")
+)
+
+(define-method find
+ (of-object "GNode")
+ (c-name "g_node_find")
+ (return-type "GNode*")
+ (parameters
+ '("GTraverseType" "order")
+ '("GTraverseFlags" "flags")
+ '("gpointer" "data")
+ )
+)
+
+(define-method max_height
+ (of-object "GNode")
+ (c-name "g_node_max_height")
+ (return-type "guint")
+)
+
+(define-method children_foreach
+ (of-object "GNode")
+ (c-name "g_node_children_foreach")
+ (return-type "none")
+ (parameters
+ '("GTraverseFlags" "flags")
+ '("GNodeForeachFunc" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-method reverse_children
+ (of-object "GNode")
+ (c-name "g_node_reverse_children")
+ (return-type "none")
+)
+
+(define-method n_children
+ (of-object "GNode")
+ (c-name "g_node_n_children")
+ (return-type "guint")
+)
+
+(define-method nth_child
+ (of-object "GNode")
+ (c-name "g_node_nth_child")
+ (return-type "GNode*")
+ (parameters
+ '("guint" "n")
+ )
+)
+
+(define-method last_child
+ (of-object "GNode")
+ (c-name "g_node_last_child")
+ (return-type "GNode*")
+)
+
+(define-method find_child
+ (of-object "GNode")
+ (c-name "g_node_find_child")
+ (return-type "GNode*")
+ (parameters
+ '("GTraverseFlags" "flags")
+ '("gpointer" "data")
+ )
+)
+
+(define-method child_position
+ (of-object "GNode")
+ (c-name "g_node_child_position")
+ (return-type "gint")
+ (parameters
+ '("GNode*" "child")
+ )
+)
+
+(define-method child_index
+ (of-object "GNode")
+ (c-name "g_node_child_index")
+ (return-type "gint")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method first_sibling
+ (of-object "GNode")
+ (c-name "g_node_first_sibling")
+ (return-type "GNode*")
+)
+
+(define-method last_sibling
+ (of-object "GNode")
+ (c-name "g_node_last_sibling")
+ (return-type "GNode*")
+)
+
+
+
+;; From glib/gpattern.h
+
+(define-method free
+ (of-object "GPatternSpec")
+ (c-name "g_pattern_spec_free")
+ (return-type "none")
+)
+
+(define-method equal
+ (of-object "GPatternSpec")
+ (c-name "g_pattern_spec_equal")
+ (return-type "gboolean")
+ (parameters
+ '("GPatternSpec*" "pspec2")
+ )
+)
+
+(define-function g_pattern_match
+ (c-name "g_pattern_match")
+ (return-type "gboolean")
+ (parameters
+ '("GPatternSpec*" "pspec")
+ '("guint" "string_length")
+ '("const-gchar*" "string")
+ '("const-gchar*" "string_reversed")
+ )
+)
+
+(define-function g_pattern_match_string
+ (c-name "g_pattern_match_string")
+ (return-type "gboolean")
+ (parameters
+ '("GPatternSpec*" "pspec")
+ '("const-gchar*" "string")
+ )
+)
+
+(define-function g_pattern_match_simple
+ (c-name "g_pattern_match_simple")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "pattern")
+ '("const-gchar*" "string")
+ )
+)
+
+
+
+;; From glib/gprimes.h
+
+
+
+;; From glib/gqsort.h
+
+
+
+;; From glib/gquark.h
+
+(define-function g_quark_from_static_string
+ (c-name "g_quark_from_static_string")
+ (return-type "GQuark")
+ (parameters
+ '("const-gchar*" "string")
+ )
+)
+
+(define-function g_quark_from_string
+ (c-name "g_quark_from_string")
+ (return-type "GQuark")
+ (parameters
+ '("const-gchar*" "string")
+ )
+)
+
+(define-method to_string
+ (of-object "GQuark")
+ (c-name "g_quark_to_string")
+ (return-type "const-gchar*")
+)
+
+
+
+;; From glib/gqueue.h
+
+(define-function g_queue_new
+ (c-name "g_queue_new")
+ (return-type "GQueue*")
+)
+
+(define-method free
+ (of-object "GQueue")
+ (c-name "g_queue_free")
+ (return-type "none")
+)
+
+(define-method push_head
+ (of-object "GQueue")
+ (c-name "g_queue_push_head")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method push_tail
+ (of-object "GQueue")
+ (c-name "g_queue_push_tail")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method pop_head
+ (of-object "GQueue")
+ (c-name "g_queue_pop_head")
+ (return-type "gpointer")
+)
+
+(define-method pop_tail
+ (of-object "GQueue")
+ (c-name "g_queue_pop_tail")
+ (return-type "gpointer")
+)
+
+(define-method is_empty
+ (of-object "GQueue")
+ (c-name "g_queue_is_empty")
+ (return-type "gboolean")
+)
+
+(define-method peek_head
+ (of-object "GQueue")
+ (c-name "g_queue_peek_head")
+ (return-type "gpointer")
+)
+
+(define-method peek_tail
+ (of-object "GQueue")
+ (c-name "g_queue_peek_tail")
+ (return-type "gpointer")
+)
+
+(define-method push_head_link
+ (of-object "GQueue")
+ (c-name "g_queue_push_head_link")
+ (return-type "none")
+ (parameters
+ '("GList*" "link")
+ )
+)
+
+(define-method push_tail_link
+ (of-object "GQueue")
+ (c-name "g_queue_push_tail_link")
+ (return-type "none")
+ (parameters
+ '("GList*" "link")
+ )
+)
+
+(define-method pop_head_link
+ (of-object "GQueue")
+ (c-name "g_queue_pop_head_link")
+ (return-type "GList*")
+)
+
+(define-method pop_tail_link
+ (of-object "GQueue")
+ (c-name "g_queue_pop_tail_link")
+ (return-type "GList*")
+)
+
+
+
+;; From glib/grand.h
+
+(define-function g_rand_new
+ (c-name "g_rand_new")
+ (return-type "GRand*")
+)
+
+(define-method free
+ (of-object "GRand")
+ (c-name "g_rand_free")
+ (return-type "none")
+)
+
+(define-method set_seed
+ (of-object "GRand")
+ (c-name "g_rand_set_seed")
+ (return-type "none")
+ (parameters
+ '("guint32" "seed")
+ )
+)
+
+(define-method int
+ (of-object "GRand")
+ (c-name "g_rand_int")
+ (return-type "guint32")
+)
+
+(define-method int_range
+ (of-object "GRand")
+ (c-name "g_rand_int_range")
+ (return-type "gint32")
+ (parameters
+ '("gint32" "begin")
+ '("gint32" "end")
+ )
+)
+
+(define-method double
+ (of-object "GRand")
+ (c-name "g_rand_double")
+ (return-type "gdouble")
+)
+
+(define-method double_range
+ (of-object "GRand")
+ (c-name "g_rand_double_range")
+ (return-type "gdouble")
+ (parameters
+ '("gdouble" "begin")
+ '("gdouble" "end")
+ )
+)
+
+(define-function g_random_set_seed
+ (c-name "g_random_set_seed")
+ (return-type "none")
+ (parameters
+ '("guint32" "seed")
+ )
+)
+
+(define-function g_random_int
+ (c-name "g_random_int")
+ (return-type "guint32")
+)
+
+(define-function g_random_int_range
+ (c-name "g_random_int_range")
+ (return-type "gint32")
+ (parameters
+ '("gint32" "begin")
+ '("gint32" "end")
+ )
+)
+
+(define-function g_random_double
+ (c-name "g_random_double")
+ (return-type "gdouble")
+)
+
+(define-function g_random_double_range
+ (c-name "g_random_double_range")
+ (return-type "gdouble")
+ (parameters
+ '("gdouble" "begin")
+ '("gdouble" "end")
+ )
+)
+
+
+
+;; From glib/grel.h
+
+(define-function g_relation_new
+ (c-name "g_relation_new")
+ (return-type "GRelation*")
+ (parameters
+ '("gint" "fields")
+ )
+)
+
+(define-method destroy
+ (of-object "GRelation")
+ (c-name "g_relation_destroy")
+ (return-type "none")
+)
+
+(define-method index
+ (of-object "GRelation")
+ (c-name "g_relation_index")
+ (return-type "none")
+ (parameters
+ '("gint" "field")
+ '("GHashFunc" "hash_func")
+ '("GEqualFunc" "key_equal_func")
+ )
+)
+
+(define-method insert
+ (of-object "GRelation")
+ (c-name "g_relation_insert")
+ (return-type "none")
+ (parameters
+ )
+ (varargs #t)
+)
+
+(define-method delete
+ (of-object "GRelation")
+ (c-name "g_relation_delete")
+ (return-type "gint")
+ (parameters
+ '("gconstpointer" "key")
+ '("gint" "field")
+ )
+)
+
+(define-method select
+ (of-object "GRelation")
+ (c-name "g_relation_select")
+ (return-type "GTuples*")
+ (parameters
+ '("gconstpointer" "key")
+ '("gint" "field")
+ )
+)
+
+(define-method count
+ (of-object "GRelation")
+ (c-name "g_relation_count")
+ (return-type "gint")
+ (parameters
+ '("gconstpointer" "key")
+ '("gint" "field")
+ )
+)
+
+(define-method exists
+ (of-object "GRelation")
+ (c-name "g_relation_exists")
+ (return-type "gboolean")
+ (parameters
+ )
+ (varargs #t)
+)
+
+(define-method print
+ (of-object "GRelation")
+ (c-name "g_relation_print")
+ (return-type "none")
+)
+
+(define-method destroy
+ (of-object "GTuples")
+ (c-name "g_tuples_destroy")
+ (return-type "none")
+)
+
+(define-method index
+ (of-object "GTuples")
+ (c-name "g_tuples_index")
+ (return-type "gpointer")
+ (parameters
+ '("gint" "index")
+ '("gint" "field")
+ )
+)
+
+
+
+;; From glib/gscanner.h
+
+(define-function g_scanner_new
+ (c-name "g_scanner_new")
+ (return-type "GScanner*")
+ (parameters
+ '("const-GScannerConfig*" "config_templ")
+ )
+)
+
+(define-method destroy
+ (of-object "GScanner")
+ (c-name "g_scanner_destroy")
+ (return-type "none")
+)
+
+(define-method input_file
+ (of-object "GScanner")
+ (c-name "g_scanner_input_file")
+ (return-type "none")
+ (parameters
+ '("gint" "input_fd")
+ )
+)
+
+(define-method sync_file_offset
+ (of-object "GScanner")
+ (c-name "g_scanner_sync_file_offset")
+ (return-type "none")
+)
+
+(define-method input_text
+ (of-object "GScanner")
+ (c-name "g_scanner_input_text")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "text")
+ '("guint" "text_len")
+ )
+)
+
+(define-method get_next_token
+ (of-object "GScanner")
+ (c-name "g_scanner_get_next_token")
+ (return-type "GTokenType")
+)
+
+(define-method peek_next_token
+ (of-object "GScanner")
+ (c-name "g_scanner_peek_next_token")
+ (return-type "GTokenType")
+)
+
+(define-method cur_token
+ (of-object "GScanner")
+ (c-name "g_scanner_cur_token")
+ (return-type "GTokenType")
+)
+
+(define-method cur_value
+ (of-object "GScanner")
+ (c-name "g_scanner_cur_value")
+ (return-type "GTokenValue")
+)
+
+(define-method cur_line
+ (of-object "GScanner")
+ (c-name "g_scanner_cur_line")
+ (return-type "guint")
+)
+
+(define-method cur_position
+ (of-object "GScanner")
+ (c-name "g_scanner_cur_position")
+ (return-type "guint")
+)
+
+(define-method eof
+ (of-object "GScanner")
+ (c-name "g_scanner_eof")
+ (return-type "gboolean")
+)
+
+(define-method set_scope
+ (of-object "GScanner")
+ (c-name "g_scanner_set_scope")
+ (return-type "guint")
+ (parameters
+ '("guint" "scope_id")
+ )
+)
+
+(define-method scope_add_symbol
+ (of-object "GScanner")
+ (c-name "g_scanner_scope_add_symbol")
+ (return-type "none")
+ (parameters
+ '("guint" "scope_id")
+ '("const-gchar*" "symbol")
+ '("gpointer" "value")
+ )
+)
+
+(define-method scope_remove_symbol
+ (of-object "GScanner")
+ (c-name "g_scanner_scope_remove_symbol")
+ (return-type "none")
+ (parameters
+ '("guint" "scope_id")
+ '("const-gchar*" "symbol")
+ )
+)
+
+(define-method scope_lookup_symbol
+ (of-object "GScanner")
+ (c-name "g_scanner_scope_lookup_symbol")
+ (return-type "gpointer")
+ (parameters
+ '("guint" "scope_id")
+ '("const-gchar*" "symbol")
+ )
+)
+
+(define-method scope_foreach_symbol
+ (of-object "GScanner")
+ (c-name "g_scanner_scope_foreach_symbol")
+ (return-type "none")
+ (parameters
+ '("guint" "scope_id")
+ '("GHFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method lookup_symbol
+ (of-object "GScanner")
+ (c-name "g_scanner_lookup_symbol")
+ (return-type "gpointer")
+ (parameters
+ '("const-gchar*" "symbol")
+ )
+)
+
+(define-method unexp_token
+ (of-object "GScanner")
+ (c-name "g_scanner_unexp_token")
+ (return-type "none")
+ (parameters
+ '("GTokenType" "expected_token")
+ '("const-gchar*" "identifier_spec")
+ '("const-gchar*" "symbol_spec")
+ '("const-gchar*" "symbol_name")
+ '("const-gchar*" "message")
+ '("gint" "is_error")
+ )
+)
+
+(define-method error
+ (of-object "GScanner")
+ (c-name "g_scanner_error")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-method warn
+ (of-object "GScanner")
+ (c-name "g_scanner_warn")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+
+
+;; From glib/gshell.h
+
+(define-function g_shell_quote
+ (c-name "g_shell_quote")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "unquoted_string")
+ )
+)
+
+(define-function g_shell_unquote
+ (c-name "g_shell_unquote")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "quoted_string")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_shell_parse_argv
+ (c-name "g_shell_parse_argv")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "command_line")
+ '("gint*" "argcp")
+ '("gchar***" "argvp")
+ '("GError**" "error")
+ )
+)
+
+
+
+;; From glib/gslist.h
+
+(define-function g_slist_push_allocator
+ (c-name "g_slist_push_allocator")
+ (return-type "none")
+ (parameters
+ '("GAllocator*" "allocator")
+ )
+)
+
+(define-function g_slist_pop_allocator
+ (c-name "g_slist_pop_allocator")
+ (return-type "none")
+)
+
+(define-function g_slist_alloc
+ (c-name "g_slist_alloc")
+ (return-type "GSList*")
+)
+
+(define-method free
+ (of-object "GSList")
+ (c-name "g_slist_free")
+ (return-type "none")
+)
+
+(define-method free_1
+ (of-object "GSList")
+ (c-name "g_slist_free_1")
+ (return-type "none")
+)
+
+(define-method append
+ (of-object "GSList")
+ (c-name "g_slist_append")
+ (return-type "GSList*")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method prepend
+ (of-object "GSList")
+ (c-name "g_slist_prepend")
+ (return-type "GSList*")
+ (parameters
+ '("gpointer" "data")
+ )
+)
+
+(define-method insert
+ (of-object "GSList")
+ (c-name "g_slist_insert")
+ (return-type "GSList*")
+ (parameters
+ '("gpointer" "data")
+ '("gint" "position")
+ )
+)
+
+(define-method insert_sorted
+ (of-object "GSList")
+ (c-name "g_slist_insert_sorted")
+ (return-type "GSList*")
+ (parameters
+ '("gpointer" "data")
+ '("GCompareFunc" "func")
+ )
+)
+
+(define-method insert_before
+ (of-object "GSList")
+ (c-name "g_slist_insert_before")
+ (return-type "GSList*")
+ (parameters
+ '("GSList*" "sibling")
+ '("gpointer" "data")
+ )
+)
+
+(define-method concat
+ (of-object "GSList")
+ (c-name "g_slist_concat")
+ (return-type "GSList*")
+ (parameters
+ '("GSList*" "list2")
+ )
+)
+
+(define-method remove
+ (of-object "GSList")
+ (c-name "g_slist_remove")
+ (return-type "GSList*")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method remove_all
+ (of-object "GSList")
+ (c-name "g_slist_remove_all")
+ (return-type "GSList*")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method remove_link
+ (of-object "GSList")
+ (c-name "g_slist_remove_link")
+ (return-type "GSList*")
+ (parameters
+ '("GSList*" "link")
+ )
+)
+
+(define-method delete_link
+ (of-object "GSList")
+ (c-name "g_slist_delete_link")
+ (return-type "GSList*")
+ (parameters
+ '("GSList*" "link")
+ )
+)
+
+(define-method reverse
+ (of-object "GSList")
+ (c-name "g_slist_reverse")
+ (return-type "GSList*")
+)
+
+(define-method copy
+ (of-object "GSList")
+ (c-name "g_slist_copy")
+ (return-type "GSList*")
+)
+
+(define-method nth
+ (of-object "GSList")
+ (c-name "g_slist_nth")
+ (return-type "GSList*")
+ (parameters
+ '("guint" "n")
+ )
+)
+
+(define-method find
+ (of-object "GSList")
+ (c-name "g_slist_find")
+ (return-type "GSList*")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method find_custom
+ (of-object "GSList")
+ (c-name "g_slist_find_custom")
+ (return-type "GSList*")
+ (parameters
+ '("gconstpointer" "data")
+ '("GCompareFunc" "func")
+ )
+)
+
+(define-method position
+ (of-object "GSList")
+ (c-name "g_slist_position")
+ (return-type "gint")
+ (parameters
+ '("GSList*" "llink")
+ )
+)
+
+(define-method index
+ (of-object "GSList")
+ (c-name "g_slist_index")
+ (return-type "gint")
+ (parameters
+ '("gconstpointer" "data")
+ )
+)
+
+(define-method last
+ (of-object "GSList")
+ (c-name "g_slist_last")
+ (return-type "GSList*")
+)
+
+(define-method length
+ (of-object "GSList")
+ (c-name "g_slist_length")
+ (return-type "guint")
+)
+
+(define-method foreach
+ (of-object "GSList")
+ (c-name "g_slist_foreach")
+ (return-type "none")
+ (parameters
+ '("GFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method sort
+ (of-object "GSList")
+ (c-name "g_slist_sort")
+ (return-type "GSList*")
+ (parameters
+ '("GCompareFunc" "compare_func")
+ )
+)
+
+(define-method sort_with_data
+ (of-object "GSList")
+ (c-name "g_slist_sort_with_data")
+ (return-type "GSList*")
+ (parameters
+ '("GCompareDataFunc" "compare_func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method nth_data
+ (of-object "GSList")
+ (c-name "g_slist_nth_data")
+ (return-type "gpointer")
+ (parameters
+ '("guint" "n")
+ )
+)
+
+
+
+;; From glib/gspawn.h
+
+(define-function g_spawn_async
+ (c-name "g_spawn_async")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "working_directory")
+ '("gchar**" "argv")
+ '("gchar**" "envp")
+ '("GSpawnFlags" "flags")
+ '("GSpawnChildSetupFunc" "child_setup")
+ '("gpointer" "user_data")
+ '("gint*" "child_pid")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_spawn_async_with_pipes
+ (c-name "g_spawn_async_with_pipes")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "working_directory")
+ '("gchar**" "argv")
+ '("gchar**" "envp")
+ '("GSpawnFlags" "flags")
+ '("GSpawnChildSetupFunc" "child_setup")
+ '("gpointer" "user_data")
+ '("gint*" "child_pid")
+ '("gint*" "standard_input")
+ '("gint*" "standard_output")
+ '("gint*" "standard_error")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_spawn_sync
+ (c-name "g_spawn_sync")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "working_directory")
+ '("gchar**" "argv")
+ '("gchar**" "envp")
+ '("GSpawnFlags" "flags")
+ '("GSpawnChildSetupFunc" "child_setup")
+ '("gpointer" "user_data")
+ '("gchar**" "standard_output")
+ '("gchar**" "standard_error")
+ '("gint*" "exit_status")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_spawn_command_line_sync
+ (c-name "g_spawn_command_line_sync")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "command_line")
+ '("gchar**" "standard_output")
+ '("gchar**" "standard_error")
+ '("gint*" "exit_status")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_spawn_command_line_async
+ (c-name "g_spawn_command_line_async")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "command_line")
+ '("GError**" "error")
+ )
+)
+
+
+
+;; From glib/gstrfuncs.h
+
+(define-function g_ascii_toupper
+ (c-name "g_ascii_toupper")
+ (return-type "gchar")
+ (parameters
+ '("gchar" "c")
+ )
+)
+
+(define-function g_ascii_digit_value
+ (c-name "g_ascii_digit_value")
+ (return-type "gint")
+ (parameters
+ '("gchar" "c")
+ )
+)
+
+(define-function g_ascii_xdigit_value
+ (c-name "g_ascii_xdigit_value")
+ (return-type "gint")
+ (parameters
+ '("gchar" "c")
+ )
+)
+
+(define-function g_strdelimit
+ (c-name "g_strdelimit")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ '("const-gchar*" "delimiters")
+ '("gchar" "new_delimiter")
+ )
+)
+
+(define-function g_strcanon
+ (c-name "g_strcanon")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ '("const-gchar*" "valid_chars")
+ '("gchar" "substitutor")
+ )
+)
+
+(define-function g_strerror
+ (c-name "g_strerror")
+ (return-type "const-gchar*")
+ (parameters
+ '("gint" "errnum")
+ )
+)
+
+(define-function g_strsignal
+ (c-name "g_strsignal")
+ (return-type "const-gchar*")
+ (parameters
+ '("gint" "signum")
+ )
+)
+
+(define-function g_strreverse
+ (c-name "g_strreverse")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ )
+)
+
+(define-function g_strlcpy
+ (c-name "g_strlcpy")
+ (return-type "gsize")
+ (parameters
+ '("gchar*" "dest")
+ '("const-gchar*" "src")
+ '("gsize" "dest_size")
+ )
+)
+
+(define-function g_strlcat
+ (c-name "g_strlcat")
+ (return-type "gsize")
+ (parameters
+ '("gchar*" "dest")
+ '("const-gchar*" "src")
+ '("gsize" "dest_size")
+ )
+)
+
+(define-function g_strstr_len
+ (c-name "g_strstr_len")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "haystack")
+ '("gssize" "haystack_len")
+ '("const-gchar*" "needle")
+ )
+)
+
+(define-function g_strrstr
+ (c-name "g_strrstr")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "haystack")
+ '("const-gchar*" "needle")
+ )
+)
+
+(define-function g_strrstr_len
+ (c-name "g_strrstr_len")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "haystack")
+ '("gssize" "haystack_len")
+ '("const-gchar*" "needle")
+ )
+)
+
+(define-function g_strtod
+ (c-name "g_strtod")
+ (return-type "gdouble")
+ (parameters
+ '("const-gchar*" "nptr")
+ '("gchar**" "endptr")
+ )
+)
+
+(define-function g_ascii_strtod
+ (c-name "g_ascii_strtod")
+ (return-type "gdouble")
+ (parameters
+ '("const-gchar*" "nptr")
+ '("gchar**" "endptr")
+ )
+)
+
+(define-function g_ascii_dtostr
+ (c-name "g_ascii_dtostr")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "buffer")
+ '("gint" "buf_len")
+ '("gdouble" "d")
+ )
+)
+
+(define-function g_ascii_formatd
+ (c-name "g_ascii_formatd")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "buffer")
+ '("gint" "buf_len")
+ '("const-gchar*" "format")
+ '("gdouble" "d")
+ )
+)
+
+(define-function g_strchug
+ (c-name "g_strchug")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ )
+)
+
+(define-function g_strchomp
+ (c-name "g_strchomp")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ )
+)
+
+(define-function g_ascii_strcasecmp
+ (c-name "g_ascii_strcasecmp")
+ (return-type "gint")
+ (parameters
+ '("const-gchar*" "s1")
+ '("const-gchar*" "s2")
+ )
+)
+
+(define-function g_ascii_strncasecmp
+ (c-name "g_ascii_strncasecmp")
+ (return-type "gint")
+ (parameters
+ '("const-gchar*" "s1")
+ '("const-gchar*" "s2")
+ '("gsize" "n")
+ )
+)
+
+(define-function g_ascii_strdown
+ (c-name "g_ascii_strdown")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ )
+)
+
+(define-function g_ascii_strup
+ (c-name "g_ascii_strup")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ )
+)
+
+(define-function g_strcasecmp
+ (c-name "g_strcasecmp")
+ (return-type "gint")
+ (parameters
+ '("const-gchar*" "s1")
+ '("const-gchar*" "s2")
+ )
+)
+
+(define-function g_strncasecmp
+ (c-name "g_strncasecmp")
+ (return-type "gint")
+ (parameters
+ '("const-gchar*" "s1")
+ '("const-gchar*" "s2")
+ '("guint" "n")
+ )
+)
+
+(define-function g_strdown
+ (c-name "g_strdown")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ )
+)
+
+(define-function g_strup
+ (c-name "g_strup")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "string")
+ )
+)
+
+(define-function g_strdup
+ (c-name "g_strdup")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ )
+)
+
+(define-function g_strdup_printf
+ (c-name "g_strdup_printf")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-function g_strdup_vprintf
+ (c-name "g_strdup_vprintf")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "format")
+ '("va_list" "args")
+ )
+)
+
+(define-function g_strndup
+ (c-name "g_strndup")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gsize" "n")
+ )
+)
+
+(define-function g_strnfill
+ (c-name "g_strnfill")
+ (return-type "gchar*")
+ (parameters
+ '("gsize" "length")
+ '("gchar" "fill_char")
+ )
+)
+
+(define-function g_strconcat
+ (c-name "g_strconcat")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "string1")
+ )
+ (varargs #t)
+)
+
+(define-function g_strjoin
+ (c-name "g_strjoin")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "separator")
+ )
+ (varargs #t)
+)
+
+(define-function g_strcompress
+ (c-name "g_strcompress")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "source")
+ )
+)
+
+(define-function g_strescape
+ (c-name "g_strescape")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "source")
+ '("const-gchar*" "exceptions")
+ )
+)
+
+(define-function g_memdup
+ (c-name "g_memdup")
+ (return-type "gpointer")
+ (parameters
+ '("gconstpointer" "mem")
+ '("guint" "byte_size")
+ )
+)
+
+(define-function g_strsplit
+ (c-name "g_strsplit")
+ (return-type "gchar**")
+ (parameters
+ '("const-gchar*" "string")
+ '("const-gchar*" "delimiter")
+ '("gint" "max_tokens")
+ )
+)
+
+(define-function g_strjoinv
+ (c-name "g_strjoinv")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "separator")
+ '("gchar**" "str_array")
+ )
+)
+
+(define-function g_strfreev
+ (c-name "g_strfreev")
+ (return-type "none")
+ (parameters
+ '("gchar**" "str_array")
+ )
+)
+
+(define-function g_strdupv
+ (c-name "g_strdupv")
+ (return-type "gchar**")
+ (parameters
+ '("gchar**" "str_array")
+ )
+)
+
+(define-function g_stpcpy
+ (c-name "g_stpcpy")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "dest")
+ '("const-char*" "src")
+ )
+)
+
+
+
+;; From glib/gstring.h
+
+(define-function g_string_chunk_new
+ (c-name "g_string_chunk_new")
+ (return-type "GStringChunk*")
+ (parameters
+ '("gsize" "size")
+ )
+)
+
+(define-method free
+ (of-object "GStringChunk")
+ (c-name "g_string_chunk_free")
+ (return-type "none")
+)
+
+(define-method insert
+ (of-object "GStringChunk")
+ (c-name "g_string_chunk_insert")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "string")
+ )
+)
+
+(define-function g_string_new
+ (c-name "g_string_new")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "init")
+ )
+)
+
+(define-function g_string_new_len
+ (c-name "g_string_new_len")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "init")
+ '("gssize" "len")
+ )
+)
+
+(define-function g_string_sized_new
+ (c-name "g_string_sized_new")
+ (return-type "GString*")
+ (parameters
+ '("gsize" "dfl_size")
+ )
+)
+
+(define-method free
+ (of-object "GString")
+ (c-name "g_string_free")
+ (return-type "gchar*")
+ (parameters
+ '("gboolean" "free_segment")
+ )
+)
+
+(define-method equal
+ (of-object "GString")
+ (c-name "g_string_equal")
+ (return-type "gboolean")
+ (parameters
+ '("const-GString*" "v2")
+ )
+)
+
+(define-method hash
+ (of-object "GString")
+ (c-name "g_string_hash")
+ (return-type "guint")
+)
+
+(define-method assign
+ (of-object "GString")
+ (c-name "g_string_assign")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "rval")
+ )
+)
+
+(define-method truncate
+ (of-object "GString")
+ (c-name "g_string_truncate")
+ (return-type "GString*")
+ (parameters
+ '("gsize" "len")
+ )
+)
+
+(define-method set_size
+ (of-object "GString")
+ (c-name "g_string_set_size")
+ (return-type "GString*")
+ (parameters
+ '("gsize" "len")
+ )
+)
+
+(define-method insert_len
+ (of-object "GString")
+ (c-name "g_string_insert_len")
+ (return-type "GString*")
+ (parameters
+ '("gssize" "pos")
+ '("const-gchar*" "val")
+ '("gssize" "len")
+ )
+)
+
+(define-method append
+ (of-object "GString")
+ (c-name "g_string_append")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "val")
+ )
+)
+
+(define-method append_len
+ (of-object "GString")
+ (c-name "g_string_append_len")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "val")
+ '("gssize" "len")
+ )
+)
+
+(define-method append_c
+ (of-object "GString")
+ (c-name "g_string_append_c")
+ (return-type "GString*")
+ (parameters
+ '("gchar" "c")
+ )
+)
+
+(define-method append_unichar
+ (of-object "GString")
+ (c-name "g_string_append_unichar")
+ (return-type "GString*")
+ (parameters
+ '("gunichar" "wc")
+ )
+)
+
+(define-method prepend
+ (of-object "GString")
+ (c-name "g_string_prepend")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "val")
+ )
+)
+
+(define-method prepend_c
+ (of-object "GString")
+ (c-name "g_string_prepend_c")
+ (return-type "GString*")
+ (parameters
+ '("gchar" "c")
+ )
+)
+
+(define-method prepend_unichar
+ (of-object "GString")
+ (c-name "g_string_prepend_unichar")
+ (return-type "GString*")
+ (parameters
+ '("gunichar" "wc")
+ )
+)
+
+(define-method prepend_len
+ (of-object "GString")
+ (c-name "g_string_prepend_len")
+ (return-type "GString*")
+ (parameters
+ '("const-gchar*" "val")
+ '("gssize" "len")
+ )
+)
+
+(define-method insert
+ (of-object "GString")
+ (c-name "g_string_insert")
+ (return-type "GString*")
+ (parameters
+ '("gssize" "pos")
+ '("const-gchar*" "val")
+ )
+)
+
+(define-method insert_c
+ (of-object "GString")
+ (c-name "g_string_insert_c")
+ (return-type "GString*")
+ (parameters
+ '("gssize" "pos")
+ '("gchar" "c")
+ )
+)
+
+(define-method insert_unichar
+ (of-object "GString")
+ (c-name "g_string_insert_unichar")
+ (return-type "GString*")
+ (parameters
+ '("gssize" "pos")
+ '("gunichar" "wc")
+ )
+)
+
+(define-method erase
+ (of-object "GString")
+ (c-name "g_string_erase")
+ (return-type "GString*")
+ (parameters
+ '("gssize" "pos")
+ '("gssize" "len")
+ )
+)
+
+(define-method ascii_down
+ (of-object "GString")
+ (c-name "g_string_ascii_down")
+ (return-type "GString*")
+)
+
+(define-method ascii_up
+ (of-object "GString")
+ (c-name "g_string_ascii_up")
+ (return-type "GString*")
+)
+
+(define-method printf
+ (of-object "GString")
+ (c-name "g_string_printf")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-method append_printf
+ (of-object "GString")
+ (c-name "g_string_append_printf")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "format")
+ )
+ (varargs #t)
+)
+
+(define-method down
+ (of-object "GString")
+ (c-name "g_string_down")
+ (return-type "GString*")
+)
+
+(define-method up
+ (of-object "GString")
+ (c-name "g_string_up")
+ (return-type "GString*")
+)
+
+
+
+;; From glib/gthread.h
+
+(define-function g_thread_init
+ (c-name "g_thread_init")
+ (return-type "none")
+ (parameters
+ '("GThreadFunctions*" "vtable")
+ )
+)
+
+(define-function g_thread_init_with_errorcheck_mutexes
+ (c-name "g_thread_init_with_errorcheck_mutexes")
+ (return-type "none")
+ (parameters
+ '("GThreadFunctions*" "vtable")
+ )
+)
+
+(define-function g_static_mutex_get_mutex_impl
+ (c-name "g_static_mutex_get_mutex_impl")
+ (return-type "GMutex*")
+ (parameters
+ '("GMutex**" "mutex")
+ )
+)
+
+(define-function g_thread_self
+ (c-name "g_thread_self")
+ (return-type "GThread*")
+)
+
+(define-function g_thread_exit
+ (c-name "g_thread_exit")
+ (return-type "none")
+ (parameters
+ '("gpointer" "retval")
+ )
+)
+
+(define-method join
+ (of-object "GThread")
+ (c-name "g_thread_join")
+ (return-type "gpointer")
+)
+
+(define-method set_priority
+ (of-object "GThread")
+ (c-name "g_thread_set_priority")
+ (return-type "none")
+ (parameters
+ '("GThreadPriority" "priority")
+ )
+)
+
+(define-method free
+ (of-object "GStaticMutex")
+ (c-name "g_static_mutex_free")
+ (return-type "none")
+)
+
+(define-method init
+ (of-object "GStaticPrivate")
+ (c-name "g_static_private_init")
+ (return-type "none")
+)
+
+(define-method get
+ (of-object "GStaticPrivate")
+ (c-name "g_static_private_get")
+ (return-type "gpointer")
+)
+
+(define-method set
+ (of-object "GStaticPrivate")
+ (c-name "g_static_private_set")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ '("GDestroyNotify" "notify")
+ )
+)
+
+(define-method free
+ (of-object "GStaticPrivate")
+ (c-name "g_static_private_free")
+ (return-type "none")
+)
+
+(define-method init
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_init")
+ (return-type "none")
+)
+
+(define-method lock
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_lock")
+ (return-type "none")
+)
+
+(define-method trylock
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_trylock")
+ (return-type "gboolean")
+)
+
+(define-method unlock
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_unlock")
+ (return-type "none")
+)
+
+(define-method lock_full
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_lock_full")
+ (return-type "none")
+ (parameters
+ '("guint" "depth")
+ )
+)
+
+(define-method unlock_full
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_unlock_full")
+ (return-type "guint")
+)
+
+(define-method free
+ (of-object "GStaticRecMutex")
+ (c-name "g_static_rec_mutex_free")
+ (return-type "none")
+)
+
+(define-method init
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_init")
+ (return-type "none")
+)
+
+(define-method reader_lock
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_reader_lock")
+ (return-type "none")
+)
+
+(define-method reader_trylock
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_reader_trylock")
+ (return-type "gboolean")
+)
+
+(define-method reader_unlock
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_reader_unlock")
+ (return-type "none")
+)
+
+(define-method writer_lock
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_writer_lock")
+ (return-type "none")
+)
+
+(define-method writer_trylock
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_writer_trylock")
+ (return-type "gboolean")
+)
+
+(define-method writer_unlock
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_writer_unlock")
+ (return-type "none")
+)
+
+(define-method free
+ (of-object "GStaticRWLock")
+ (c-name "g_static_rw_lock_free")
+ (return-type "none")
+)
+
+(define-function G_LOCK_NAME
+ (c-name "G_LOCK_NAME")
+ (return-type "GStaticMutex")
+ (parameters
+ )
+)
+
+
+
+;; From glib/gthreadpool.h
+
+(define-function g_thread_pool_new
+ (c-name "g_thread_pool_new")
+ (return-type "GThreadPool*")
+ (parameters
+ '("GFunc" "func")
+ '("gpointer" "user_data")
+ '("gint" "max_threads")
+ '("gboolean" "exclusive")
+ '("GError**" "error")
+ )
+)
+
+(define-method push
+ (of-object "GThreadPool")
+ (c-name "g_thread_pool_push")
+ (return-type "none")
+ (parameters
+ '("gpointer" "data")
+ '("GError**" "error")
+ )
+)
+
+(define-method set_max_threads
+ (of-object "GThreadPool")
+ (c-name "g_thread_pool_set_max_threads")
+ (return-type "none")
+ (parameters
+ '("gint" "max_threads")
+ '("GError**" "error")
+ )
+)
+
+(define-method get_max_threads
+ (of-object "GThreadPool")
+ (c-name "g_thread_pool_get_max_threads")
+ (return-type "gint")
+)
+
+(define-method get_num_threads
+ (of-object "GThreadPool")
+ (c-name "g_thread_pool_get_num_threads")
+ (return-type "guint")
+)
+
+(define-method unprocessed
+ (of-object "GThreadPool")
+ (c-name "g_thread_pool_unprocessed")
+ (return-type "guint")
+)
+
+(define-method free
+ (of-object "GThreadPool")
+ (c-name "g_thread_pool_free")
+ (return-type "none")
+ (parameters
+ '("gboolean" "immediate")
+ '("gboolean" "wait")
+ )
+)
+
+(define-function g_thread_pool_set_max_unused_threads
+ (c-name "g_thread_pool_set_max_unused_threads")
+ (return-type "none")
+ (parameters
+ '("gint" "max_threads")
+ )
+)
+
+(define-function g_thread_pool_get_max_unused_threads
+ (c-name "g_thread_pool_get_max_unused_threads")
+ (return-type "gint")
+)
+
+(define-function g_thread_pool_get_num_unused_threads
+ (c-name "g_thread_pool_get_num_unused_threads")
+ (return-type "guint")
+)
+
+(define-function g_thread_pool_stop_unused_threads
+ (c-name "g_thread_pool_stop_unused_threads")
+ (return-type "none")
+)
+
+
+
+;; From glib/gtimer.h
+
+(define-method destroy
+ (of-object "GTimer")
+ (c-name "g_timer_destroy")
+ (return-type "none")
+)
+
+(define-method start
+ (of-object "GTimer")
+ (c-name "g_timer_start")
+ (return-type "none")
+)
+
+(define-method stop
+ (of-object "GTimer")
+ (c-name "g_timer_stop")
+ (return-type "none")
+)
+
+(define-method reset
+ (of-object "GTimer")
+ (c-name "g_timer_reset")
+ (return-type "none")
+)
+
+(define-method elapsed
+ (of-object "GTimer")
+ (c-name "g_timer_elapsed")
+ (return-type "gdouble")
+ (parameters
+ '("gulong*" "microseconds")
+ )
+)
+
+(define-function g_usleep
+ (c-name "g_usleep")
+ (return-type "none")
+ (parameters
+ '("gulong" "microseconds")
+ )
+)
+
+(define-method add
+ (of-object "GTimeVal")
+ (c-name "g_time_val_add")
+ (return-type "none")
+ (parameters
+ '("glong" "microseconds")
+ )
+)
+
+
+
+;; From glib/gtree.h
+
+(define-function g_tree_new_with_data
+ (c-name "g_tree_new_with_data")
+ (return-type "GTree*")
+ (parameters
+ '("GCompareDataFunc" "key_compare_func")
+ '("gpointer" "key_compare_data")
+ )
+)
+
+(define-function g_tree_new_full
+ (c-name "g_tree_new_full")
+ (return-type "GTree*")
+ (parameters
+ '("GCompareDataFunc" "key_compare_func")
+ '("gpointer" "key_compare_data")
+ '("GDestroyNotify" "key_destroy_func")
+ '("GDestroyNotify" "value_destroy_func")
+ )
+)
+
+(define-method destroy
+ (of-object "GTree")
+ (c-name "g_tree_destroy")
+ (return-type "none")
+)
+
+(define-method insert
+ (of-object "GTree")
+ (c-name "g_tree_insert")
+ (return-type "none")
+ (parameters
+ '("gpointer" "key")
+ '("gpointer" "value")
+ )
+)
+
+(define-method replace
+ (of-object "GTree")
+ (c-name "g_tree_replace")
+ (return-type "none")
+ (parameters
+ '("gpointer" "key")
+ '("gpointer" "value")
+ )
+)
+
+(define-method remove
+ (of-object "GTree")
+ (c-name "g_tree_remove")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "key")
+ )
+)
+
+(define-method steal
+ (of-object "GTree")
+ (c-name "g_tree_steal")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "key")
+ )
+)
+
+(define-method lookup
+ (of-object "GTree")
+ (c-name "g_tree_lookup")
+ (return-type "gpointer")
+ (parameters
+ '("gconstpointer" "key")
+ )
+)
+
+(define-method lookup_extended
+ (of-object "GTree")
+ (c-name "g_tree_lookup_extended")
+ (return-type "gboolean")
+ (parameters
+ '("gconstpointer" "lookup_key")
+ '("gpointer*" "orig_key")
+ '("gpointer*" "value")
+ )
+)
+
+(define-method foreach
+ (of-object "GTree")
+ (c-name "g_tree_foreach")
+ (return-type "none")
+ (parameters
+ '("GTraverseFunc" "func")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method traverse
+ (of-object "GTree")
+ (c-name "g_tree_traverse")
+ (return-type "none")
+ (parameters
+ '("GTraverseFunc" "traverse_func")
+ '("GTraverseType" "traverse_type")
+ '("gpointer" "user_data")
+ )
+)
+
+(define-method search
+ (of-object "GTree")
+ (c-name "g_tree_search")
+ (return-type "gpointer")
+ (parameters
+ '("GCompareFunc" "search_func")
+ '("gconstpointer" "user_data")
+ )
+)
+
+(define-method height
+ (of-object "GTree")
+ (c-name "g_tree_height")
+ (return-type "gint")
+)
+
+(define-method nnodes
+ (of-object "GTree")
+ (c-name "g_tree_nnodes")
+ (return-type "gint")
+)
+
+
+
+;; From glib/gtypes.h
+
+
+
+;; From glib/gunicode.h
+
+(define-method isalnum
+ (of-object "gunichar")
+ (c-name "g_unichar_isalnum")
+ (return-type "gboolean")
+)
+
+(define-method isalpha
+ (of-object "gunichar")
+ (c-name "g_unichar_isalpha")
+ (return-type "gboolean")
+)
+
+(define-method iscntrl
+ (of-object "gunichar")
+ (c-name "g_unichar_iscntrl")
+ (return-type "gboolean")
+)
+
+(define-method isdigit
+ (of-object "gunichar")
+ (c-name "g_unichar_isdigit")
+ (return-type "gboolean")
+)
+
+(define-method isgraph
+ (of-object "gunichar")
+ (c-name "g_unichar_isgraph")
+ (return-type "gboolean")
+)
+
+(define-method islower
+ (of-object "gunichar")
+ (c-name "g_unichar_islower")
+ (return-type "gboolean")
+)
+
+(define-method isprint
+ (of-object "gunichar")
+ (c-name "g_unichar_isprint")
+ (return-type "gboolean")
+)
+
+(define-method ispunct
+ (of-object "gunichar")
+ (c-name "g_unichar_ispunct")
+ (return-type "gboolean")
+)
+
+(define-method isspace
+ (of-object "gunichar")
+ (c-name "g_unichar_isspace")
+ (return-type "gboolean")
+)
+
+(define-method isupper
+ (of-object "gunichar")
+ (c-name "g_unichar_isupper")
+ (return-type "gboolean")
+)
+
+(define-method isxdigit
+ (of-object "gunichar")
+ (c-name "g_unichar_isxdigit")
+ (return-type "gboolean")
+)
+
+(define-method istitle
+ (of-object "gunichar")
+ (c-name "g_unichar_istitle")
+ (return-type "gboolean")
+)
+
+(define-method isdefined
+ (of-object "gunichar")
+ (c-name "g_unichar_isdefined")
+ (return-type "gboolean")
+)
+
+(define-method iswide
+ (of-object "gunichar")
+ (c-name "g_unichar_iswide")
+ (return-type "gboolean")
+)
+
+(define-method toupper
+ (of-object "gunichar")
+ (c-name "g_unichar_toupper")
+ (return-type "gunichar")
+)
+
+(define-method tolower
+ (of-object "gunichar")
+ (c-name "g_unichar_tolower")
+ (return-type "gunichar")
+)
+
+(define-method totitle
+ (of-object "gunichar")
+ (c-name "g_unichar_totitle")
+ (return-type "gunichar")
+)
+
+(define-method digit_value
+ (of-object "gunichar")
+ (c-name "g_unichar_digit_value")
+ (return-type "gint")
+)
+
+(define-method xdigit_value
+ (of-object "gunichar")
+ (c-name "g_unichar_xdigit_value")
+ (return-type "gint")
+)
+
+(define-method type
+ (of-object "gunichar")
+ (c-name "g_unichar_type")
+ (return-type "GUnicodeType")
+)
+
+(define-method break_type
+ (of-object "gunichar")
+ (c-name "g_unichar_break_type")
+ (return-type "GUnicodeBreakType")
+)
+
+(define-function g_unicode_canonical_ordering
+ (c-name "g_unicode_canonical_ordering")
+ (return-type "none")
+ (parameters
+ '("gunichar*" "string")
+ '("gsize" "len")
+ )
+)
+
+(define-function g_unicode_canonical_decomposition
+ (c-name "g_unicode_canonical_decomposition")
+ (return-type "gunichar*")
+ (parameters
+ '("gunichar" "ch")
+ '("gsize*" "result_len")
+ )
+)
+
+(define-function g_utf8_get_char
+ (c-name "g_utf8_get_char")
+ (return-type "gunichar")
+ (parameters
+ '("const-gchar*" "p")
+ )
+)
+
+(define-function g_utf8_get_char_validated
+ (c-name "g_utf8_get_char_validated")
+ (return-type "gunichar")
+ (parameters
+ '("const-gchar*" "p")
+ '("gssize" "max_len")
+ )
+)
+
+(define-function g_utf8_offset_to_pointer
+ (c-name "g_utf8_offset_to_pointer")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("glong" "offset")
+ )
+)
+
+(define-function g_utf8_pointer_to_offset
+ (c-name "g_utf8_pointer_to_offset")
+ (return-type "glong")
+ (parameters
+ '("const-gchar*" "str")
+ '("const-gchar*" "pos")
+ )
+)
+
+(define-function g_utf8_prev_char
+ (c-name "g_utf8_prev_char")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "p")
+ )
+)
+
+(define-function g_utf8_find_next_char
+ (c-name "g_utf8_find_next_char")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "p")
+ '("const-gchar*" "end")
+ )
+)
+
+(define-function g_utf8_find_prev_char
+ (c-name "g_utf8_find_prev_char")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("const-gchar*" "p")
+ )
+)
+
+(define-function g_utf8_strlen
+ (c-name "g_utf8_strlen")
+ (return-type "glong")
+ (parameters
+ '("const-gchar*" "p")
+ '("gssize" "max")
+ )
+)
+
+(define-function g_utf8_strncpy
+ (c-name "g_utf8_strncpy")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "dest")
+ '("const-gchar*" "src")
+ '("gsize" "n")
+ )
+)
+
+(define-function g_utf8_strchr
+ (c-name "g_utf8_strchr")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "p")
+ '("gssize" "len")
+ '("gunichar" "c")
+ )
+)
+
+(define-function g_utf8_strrchr
+ (c-name "g_utf8_strrchr")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "p")
+ '("gssize" "len")
+ '("gunichar" "c")
+ )
+)
+
+(define-function g_utf8_to_utf16
+ (c-name "g_utf8_to_utf16")
+ (return-type "gunichar2*")
+ (parameters
+ '("const-gchar*" "str")
+ '("glong" "len")
+ '("glong*" "items_read")
+ '("glong*" "items_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_utf8_to_ucs4
+ (c-name "g_utf8_to_ucs4")
+ (return-type "gunichar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("glong" "len")
+ '("glong*" "items_read")
+ '("glong*" "items_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_utf8_to_ucs4_fast
+ (c-name "g_utf8_to_ucs4_fast")
+ (return-type "gunichar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("glong" "len")
+ '("glong*" "items_written")
+ )
+)
+
+(define-function g_utf16_to_ucs4
+ (c-name "g_utf16_to_ucs4")
+ (return-type "gunichar*")
+ (parameters
+ '("const-gunichar2*" "str")
+ '("glong" "len")
+ '("glong*" "items_read")
+ '("glong*" "items_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_utf16_to_utf8
+ (c-name "g_utf16_to_utf8")
+ (return-type "gchar*")
+ (parameters
+ '("const-gunichar2*" "str")
+ '("glong" "len")
+ '("glong*" "items_read")
+ '("glong*" "items_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_ucs4_to_utf16
+ (c-name "g_ucs4_to_utf16")
+ (return-type "gunichar2*")
+ (parameters
+ '("const-gunichar*" "str")
+ '("glong" "len")
+ '("glong*" "items_read")
+ '("glong*" "items_written")
+ '("GError**" "error")
+ )
+)
+
+(define-function g_ucs4_to_utf8
+ (c-name "g_ucs4_to_utf8")
+ (return-type "gchar*")
+ (parameters
+ '("const-gunichar*" "str")
+ '("glong" "len")
+ '("glong*" "items_read")
+ '("glong*" "items_written")
+ '("GError**" "error")
+ )
+)
+
+(define-method to_utf8
+ (of-object "gunichar")
+ (c-name "g_unichar_to_utf8")
+ (return-type "gint")
+ (parameters
+ '("gchar*" "outbuf")
+ )
+)
+
+(define-function g_utf8_validate
+ (c-name "g_utf8_validate")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "max_len")
+ '("const-gchar**" "end")
+ )
+)
+
+(define-method validate
+ (of-object "gunichar")
+ (c-name "g_unichar_validate")
+ (return-type "gboolean")
+)
+
+(define-function g_utf8_strup
+ (c-name "g_utf8_strup")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ )
+)
+
+(define-function g_utf8_strdown
+ (c-name "g_utf8_strdown")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ )
+)
+
+(define-function g_utf8_casefold
+ (c-name "g_utf8_casefold")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ )
+)
+
+(define-function g_utf8_normalize
+ (c-name "g_utf8_normalize")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ '("GNormalizeMode" "mode")
+ )
+)
+
+(define-function g_utf8_collate
+ (c-name "g_utf8_collate")
+ (return-type "gint")
+ (parameters
+ '("const-gchar*" "str1")
+ '("const-gchar*" "str2")
+ )
+)
+
+(define-function g_utf8_collate_key
+ (c-name "g_utf8_collate_key")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "str")
+ '("gssize" "len")
+ )
+)
+
+
+
+;; From glib/gutils.h
+
+(define-function g_get_real_name
+ (c-name "g_get_real_name")
+ (return-type "const-gchar*")
+)
+
+(define-function g_get_home_dir
+ (c-name "g_get_home_dir")
+ (return-type "const-gchar*")
+)
+
+(define-function g_get_tmp_dir
+ (c-name "g_get_tmp_dir")
+ (return-type "const-gchar*")
+)
+
+(define-function g_get_prgname
+ (c-name "g_get_prgname")
+ (return-type "gchar*")
+)
+
+(define-function g_set_prgname
+ (c-name "g_set_prgname")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "prgname")
+ )
+)
+
+(define-function g_parse_debug_string
+ (c-name "g_parse_debug_string")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "string")
+ '("const-GDebugKey*" "keys")
+ '("guint" "nkeys")
+ )
+)
+
+(define-function g_snprintf
+ (c-name "g_snprintf")
+ (return-type "gint")
+ (parameters
+ '("gchar*" "string")
+ '("gulong" "n")
+ '("gchar-const*" "format")
+ )
+ (varargs #t)
+)
+
+(define-function g_vsnprintf
+ (c-name "g_vsnprintf")
+ (return-type "gint")
+ (parameters
+ '("gchar*" "string")
+ '("gulong" "n")
+ '("gchar-const*" "format")
+ '("va_list" "args")
+ )
+)
+
+(define-function g_path_is_absolute
+ (c-name "g_path_is_absolute")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "file_name")
+ )
+)
+
+(define-function g_path_skip_root
+ (c-name "g_path_skip_root")
+ (return-type "const-gchar*")
+ (parameters
+ '("const-gchar*" "file_name")
+ )
+)
+
+(define-function g_basename
+ (c-name "g_basename")
+ (return-type "const-gchar*")
+ (parameters
+ '("const-gchar*" "file_name")
+ )
+)
+
+(define-function g_get_current_dir
+ (c-name "g_get_current_dir")
+ (return-type "gchar*")
+)
+
+(define-function g_path_get_basename
+ (c-name "g_path_get_basename")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "file_name")
+ )
+)
+
+(define-function g_path_get_dirname
+ (c-name "g_path_get_dirname")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "file_name")
+ )
+)
+
+(define-function g_nullify_pointer
+ (c-name "g_nullify_pointer")
+ (return-type "none")
+ (parameters
+ '("gpointer*" "nullify_location")
+ )
+)
+
+(define-function g_getenv
+ (c-name "g_getenv")
+ (return-type "const-gchar*")
+ (parameters
+ '("const-gchar*" "variable")
+ )
+)
+
+(define-function g_atexit
+ (c-name "g_atexit")
+ (return-type "none")
+ (parameters
+ '("GVoidFunc" "func")
+ )
+)
+
+(define-function g_find_program_in_path
+ (c-name "g_find_program_in_path")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "program")
+ )
+)
+
+
+
+;; From glib/gwin32.h
+
+(define-function g_win32_getlocale
+ (c-name "g_win32_getlocale")
+ (return-type "gchar*")
+)
+
+(define-function g_win32_error_message
+ (c-name "g_win32_error_message")
+ (return-type "gchar*")
+ (parameters
+ '("gint" "error")
+ )
+)
+
+(define-function g_win32_get_package_installation_directory
+ (c-name "g_win32_get_package_installation_directory")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "package")
+ '("gchar*" "dll_name")
+ )
+)
+
+(define-function g_win32_get_package_installation_subdirectory
+ (c-name "g_win32_get_package_installation_subdirectory")
+ (return-type "gchar*")
+ (parameters
+ '("gchar*" "package")
+ '("gchar*" "dll_name")
+ '("gchar*" "subdir")
+ )
+)
+
+
diff --git a/glib/src/gmodule_enums.defs b/glib/src/gmodule_enums.defs
new file mode 100644
index 00000000..ef495330
--- /dev/null
+++ b/glib/src/gmodule_enums.defs
@@ -0,0 +1,11 @@
+;; From gmodule.h
+
+(define-flags-extended ModuleFlags
+ (in-module "G")
+ (c-name "GModuleFlags")
+ (values
+ '("lazy" "G_MODULE_BIND_LAZY" "1 << 0")
+ '("mask" "G_MODULE_BIND_MASK" "0x01")
+ )
+)
+
diff --git a/glib/src/gmodule_functions.defs b/glib/src/gmodule_functions.defs
new file mode 100644
index 00000000..6b4d926b
--- /dev/null
+++ b/glib/src/gmodule_functions.defs
@@ -0,0 +1,79 @@
+;; -*- scheme -*-
+; object definitions ...
+;; Enumerations and flags ...
+
+(define-flags ModuleFlags
+ (in-module "G")
+ (c-name "GModuleFlags")
+ (gtype-id "G_TYPE_MODULE_FLAGS")
+ (values
+ '("lazy" "G_MODULE_BIND_LAZY")
+ '("mask" "G_MODULE_BIND_MASK")
+ )
+)
+
+
+;; From /gnome/head/cvs/glib/gmodule/gmoduleconf.h
+
+
+
+;; From /gnome/head/cvs/glib/gmodule/gmodule.h
+
+(define-function g_module_open
+ (c-name "g_module_open")
+ (return-type "GModule*")
+ (parameters
+ '("const-gchar*" "file_name")
+ '("GModuleFlags" "flags")
+ )
+)
+
+(define-method close
+ (of-object "GModule")
+ (c-name "g_module_close")
+ (return-type "gboolean")
+)
+
+(define-method make_resident
+ (of-object "GModule")
+ (c-name "g_module_make_resident")
+ (return-type "none")
+)
+
+(define-function g_module_error
+ (c-name "g_module_error")
+ (return-type "const-gchar*")
+)
+
+(define-method symbol
+ (of-object "GModule")
+ (c-name "g_module_symbol")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "symbol_name")
+ '("gpointer*" "symbol")
+ )
+)
+
+(define-method name
+ (of-object "GModule")
+ (c-name "g_module_name")
+ (return-type "const-gchar*")
+)
+
+(define-function g_module_build_path
+ (c-name "g_module_build_path")
+ (return-type "gchar*")
+ (parameters
+ '("const-gchar*" "directory")
+ '("const-gchar*" "module_name")
+ )
+)
+
+;; custom-written:
+(define-function g_module_supported
+ (c-name "g_module_supported")
+ (return-type "gboolean")
+)
+
+
diff --git a/glib/src/gobject.defs b/glib/src/gobject.defs
new file mode 100644
index 00000000..0c9f4b99
--- /dev/null
+++ b/glib/src/gobject.defs
@@ -0,0 +1,3 @@
+(include gobject_functions.defs)
+(include gobject_enums.defs)
+
diff --git a/glib/src/gobject_enums.defs b/glib/src/gobject_enums.defs
new file mode 100644
index 00000000..d234bdb3
--- /dev/null
+++ b/glib/src/gobject_enums.defs
@@ -0,0 +1,80 @@
+;; From gobject/gparam.h
+
+(define-flags-extended ParamFlags
+ (in-module "G")
+ (c-name "GParamFlags")
+ (values
+ '("readable" "G_PARAM_READABLE" "1 << 0")
+ '("writable" "G_PARAM_WRITABLE" "1 << 1")
+ '("construct" "G_PARAM_CONSTRUCT" "1 << 2")
+ '("construct-only" "G_PARAM_CONSTRUCT_ONLY" "1 << 3")
+ '("lax-validation" "G_PARAM_LAX_VALIDATION" "1 << 4")
+ '("private" "G_PARAM_PRIVATE" "1 << 5")
+ )
+)
+
+;; From gobject/gsignal.h
+
+(define-flags-extended SignalFlags
+ (in-module "G")
+ (c-name "GSignalFlags")
+ (values
+ '("run-first" "G_SIGNAL_RUN_FIRST" "1 << 0")
+ '("run-last" "G_SIGNAL_RUN_LAST" "1 << 1")
+ '("run-cleanup" "G_SIGNAL_RUN_CLEANUP" "1 << 2")
+ '("no-recurse" "G_SIGNAL_NO_RECURSE" "1 << 3")
+ '("detailed" "G_SIGNAL_DETAILED" "1 << 4")
+ '("action" "G_SIGNAL_ACTION" "1 << 5")
+ '("no-hooks" "G_SIGNAL_NO_HOOKS" "1 << 6")
+ )
+)
+
+(define-flags-extended ConnectFlags
+ (in-module "G")
+ (c-name "GConnectFlags")
+ (values
+ '("after" "G_CONNECT_AFTER" "1 << 0")
+ '("swapped" "G_CONNECT_SWAPPED" "1 << 1")
+ )
+)
+
+(define-flags-extended SignalMatchType
+ (in-module "G")
+ (c-name "GSignalMatchType")
+ (values
+ '("id" "G_SIGNAL_MATCH_ID" "1 << 0")
+ '("detail" "G_SIGNAL_MATCH_DETAIL" "1 << 1")
+ '("closure" "G_SIGNAL_MATCH_CLOSURE" "1 << 2")
+ '("func" "G_SIGNAL_MATCH_FUNC" "1 << 3")
+ '("data" "G_SIGNAL_MATCH_DATA" "1 << 4")
+ '("unblocked" "G_SIGNAL_MATCH_UNBLOCKED" "1 << 5")
+ )
+)
+
+;; From gobject/gtype.h
+
+(define-flags-extended TypeDebugFlags
+ (in-module "G")
+ (c-name "GTypeDebugFlags")
+ (values
+ '("none" "G_TYPE_DEBUG_NONE" "0")
+ '("objects" "G_TYPE_DEBUG_OBJECTS" "1 << 0")
+ '("signals" "G_TYPE_DEBUG_SIGNALS" "1 << 1")
+ '("mask" "G_TYPE_DEBUG_MASK" "0x03")
+ )
+)
+
+(define-enum-extended TypeFundamentalFlags
+ (in-module "G")
+ (c-name "GTypeFundamentalFlags")
+ (values
+ )
+)
+
+(define-enum-extended TypeFlags
+ (in-module "G")
+ (c-name "GTypeFlags")
+ (values
+ )
+)
+
diff --git a/glib/src/gobject_functions.defs b/glib/src/gobject_functions.defs
new file mode 100644
index 00000000..f06327ca
--- /dev/null
+++ b/glib/src/gobject_functions.defs
@@ -0,0 +1,2608 @@
+;; -*- scheme -*-
+; object definitions ...
+(define-object TypeModule
+ (in-module "G")
+ (parent "GObject")
+ (c-name "GTypeModule")
+ (gtype-id "G_TYPE_TYPE_MODULE")
+)
+
+;; Enumerations and flags ...
+
+(define-flags ParamFlags
+ (in-module "G")
+ (c-name "GParamFlags")
+ (gtype-id "G_TYPE_PARAM_FLAGS")
+ (values
+ '("readable" "G_PARAM_READABLE")
+ '("writable" "G_PARAM_WRITABLE")
+ '("construct" "G_PARAM_CONSTRUCT")
+ '("construct-only" "G_PARAM_CONSTRUCT_ONLY")
+ '("lax-validation" "G_PARAM_LAX_VALIDATION")
+ '("private" "G_PARAM_PRIVATE")
+ )
+)
+
+(define-flags SignalFlags
+ (in-module "G")
+ (c-name "GSignalFlags")
+ (gtype-id "G_TYPE_SIGNAL_FLAGS")
+ (values
+ '("run-first" "G_SIGNAL_RUN_FIRST")
+ '("run-last" "G_SIGNAL_RUN_LAST")
+ '("run-cleanup" "G_SIGNAL_RUN_CLEANUP")
+ '("no-recurse" "G_SIGNAL_NO_RECURSE")
+ '("detailed" "G_SIGNAL_DETAILED")
+ '("action" "G_SIGNAL_ACTION")
+ '("no-hooks" "G_SIGNAL_NO_HOOKS")
+ )
+)
+
+(define-flags ConnectFlags
+ (in-module "G")
+ (c-name "GConnectFlags")
+ (gtype-id "G_TYPE_CONNECT_FLAGS")
+ (values
+ '("after" "G_CONNECT_AFTER")
+ '("swapped" "G_CONNECT_SWAPPED")
+ )
+)
+
+(define-flags SignalMatchType
+ (in-module "G")
+ (c-name "GSignalMatchType")
+ (gtype-id "G_TYPE_SIGNAL_MATCH_TYPE")
+ (values
+ '("id" "G_SIGNAL_MATCH_ID")
+ '("detail" "G_SIGNAL_MATCH_DETAIL")
+ '("closure" "G_SIGNAL_MATCH_CLOSURE")
+ '("func" "G_SIGNAL_MATCH_FUNC")
+ '("data" "G_SIGNAL_MATCH_DATA")
+ '("unblocked" "G_SIGNAL_MATCH_UNBLOCKED")
+ )
+)
+
+(define-flags TypeDebugFlags
+ (in-module "G")
+ (c-name "GTypeDebugFlags")
+ (gtype-id "G_TYPE_TYPE_DEBUG_FLAGS")
+ (values
+ '("none" "G_TYPE_DEBUG_NONE")
+ '("objects" "G_TYPE_DEBUG_OBJECTS")
+ '("signals" "G_TYPE_DEBUG_SIGNALS")
+ '("mask" "G_TYPE_DEBUG_MASK")
+ )
+)
+
+(define-flags TypeFundamentalFlags
+ (in-module "G")
+ (c-name "GTypeFundamentalFlags")
+ (gtype-id "G_TYPE_TYPE_FUNDAMENTAL_FLAGS")
+ (values
+ '("classed" "G_TYPE_FLAG_CLASSED")
+ '("instantiatable" "G_TYPE_FLAG_INSTANTIATABLE")
+ '("derivable" "G_TYPE_FLAG_DERIVABLE")
+ '("deep-derivable" "G_TYPE_FLAG_DEEP_DERIVABLE")
+ )
+)
+
+(define-flags TypeFlags
+ (in-module "G")
+ (c-name "GTypeFlags")
+ (gtype-id "G_TYPE_TYPE_FLAGS")
+ (values
+ '("abstract" "G_TYPE_FLAG_ABSTRACT")
+ '("value-abstract" "G_TYPE_FLAG_VALUE_ABSTRACT")
+ )
+)
+
+
+;; From gobject/gboxed.h
+
+(define-function g_boxed_free
+ (c-name "g_boxed_free")
+ (return-type "none")
+ (parameters
+ '("GType" "boxed_type")
+ '("gpointer" "boxed")
+ )
+)
+
+(define-method set_boxed
+ (of-object "GValue")
+ (c-name "g_value_set_boxed")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "v_boxed")
+ )
+)
+
+(define-method set_static_boxed
+ (of-object "GValue")
+ (c-name "g_value_set_static_boxed")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "v_boxed")
+ )
+)
+
+(define-method get_boxed
+ (of-object "GValue")
+ (c-name "g_value_get_boxed")
+ (return-type "gpointer")
+)
+
+(define-method dup_boxed
+ (of-object "GValue")
+ (c-name "g_value_dup_boxed")
+ (return-type "gpointer")
+)
+
+(define-function g_boxed_type_register_static
+ (c-name "g_boxed_type_register_static")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ '("GBoxedCopyFunc" "boxed_copy")
+ '("GBoxedFreeFunc" "boxed_free")
+ )
+)
+
+(define-method set_boxed_take_ownership
+ (of-object "GValue")
+ (c-name "g_value_set_boxed_take_ownership")
+ (return-type "none")
+ (parameters
+ '("gconstpointer" "v_boxed")
+ )
+)
+
+(define-function g_closure_get_type
+ (c-name "g_closure_get_type")
+ (return-type "GType")
+)
+
+(define-function g_value_get_type
+ (c-name "g_value_get_type")
+ (return-type "GType")
+)
+
+(define-function g_value_array_get_type
+ (c-name "g_value_array_get_type")
+ (return-type "GType")
+)
+
+(define-function g_gstring_get_type
+ (c-name "g_gstring_get_type")
+ (return-type "GType")
+)
+
+
+
+;; From gobject/gclosure.h
+
+(define-function g_cclosure_new
+ (c-name "g_cclosure_new")
+ (return-type "GClosure*")
+ (parameters
+ '("GCallback" "callback_func")
+ '("gpointer" "user_data")
+ '("GClosureNotify" "destroy_data")
+ )
+)
+
+(define-function g_cclosure_new_swap
+ (c-name "g_cclosure_new_swap")
+ (return-type "GClosure*")
+ (parameters
+ '("GCallback" "callback_func")
+ '("gpointer" "user_data")
+ '("GClosureNotify" "destroy_data")
+ )
+)
+
+(define-function g_signal_type_cclosure_new
+ (c-name "g_signal_type_cclosure_new")
+ (return-type "GClosure*")
+ (parameters
+ '("GType" "itype")
+ '("guint" "struct_offset")
+ )
+)
+
+(define-method ref
+ (of-object "GClosure")
+ (c-name "g_closure_ref")
+ (return-type "GClosure*")
+)
+
+(define-method sink
+ (of-object "GClosure")
+ (c-name "g_closure_sink")
+ (return-type "none")
+)
+
+(define-method unref
+ (of-object "GClosure")
+ (c-name "g_closure_unref")
+ (return-type "none")
+)
+
+(define-function g_closure_new_simple
+ (c-name "g_closure_new_simple")
+ (return-type "GClosure*")
+ (parameters
+ '("guint" "sizeof_closure")
+ '("gpointer" "data")
+ )
+)
+
+(define-method add_finalize_notifier
+ (of-object "GClosure")
+ (c-name "g_closure_add_finalize_notifier")
+ (return-type "none")
+ (parameters
+ '("gpointer" "notify_data")
+ '("GClosureNotify" "notify_func")
+ )
+)
+
+(define-method remove_finalize_notifier
+ (of-object "GClosure")
+ (c-name "g_closure_remove_finalize_notifier")
+ (return-type "none")
+ (parameters
+ '("gpointer" "notify_data")
+ '("GClosureNotify" "notify_func")
+ )
+)
+
+(define-method add_invalidate_notifier
+ (of-object "GClosure")
+ (c-name "g_closure_add_invalidate_notifier")
+ (return-type "none")
+ (parameters
+ '("gpointer" "notify_data")
+ '("GClosureNotify" "notify_func")
+ )
+)
+
+(define-method remove_invalidate_notifier
+ (of-object "GClosure")
+ (c-name "g_closure_remove_invalidate_notifier")
+ (return-type "none")
+ (parameters
+ '("gpointer" "notify_data")
+ '("GClosureNotify" "notify_func")
+ )
+)
+
+(define-method add_marshal_guards
+ (of-object "GClosure")
+ (c-name "g_closure_add_marshal_guards")
+ (return-type "none")
+ (parameters
+ '("gpointer" "pre_marshal_data")
+ '("GClosureNotify" "pre_marshal_notify")
+ '("gpointer" "post_marshal_data")
+ '("GClosureNotify" "post_marshal_notify")
+ )
+)
+
+(define-method set_marshal
+ (of-object "GClosure")
+ (c-name "g_closure_set_marshal")
+ (return-type "none")
+ (parameters
+ '("GClosureMarshal" "marshal")
+ )
+)
+
+(define-method set_meta_marshal
+ (of-object "GClosure")
+ (c-name "g_closure_set_meta_marshal")
+ (return-type "none")
+ (parameters
+ '("gpointer" "marshal_data")
+ '("GClosureMarshal" "meta_marshal")
+ )
+)
+
+(define-method invalidate
+ (of-object "GClosure")
+ (c-name "g_closure_invalidate")
+ (return-type "none")
+)
+
+(define-method invoke
+ (of-object "GClosure")
+ (c-name "g_closure_invoke")
+ (return-type "none")
+ (parameters
+ '("GValue*" "return_value")
+ '("guint" "n_param_values")
+ '("const-GValue*" "param_values")
+ '("gpointer" "invocation_hint")
+ )
+)
+
+
+
+;; From gobject/genums.h
+
+(define-function g_enum_get_value
+ (c-name "g_enum_get_value")
+ (return-type "GEnumValue*")
+ (parameters
+ '("GEnumClass*" "enum_class")
+ '("gint" "value")
+ )
+)
+
+(define-function g_enum_get_value_by_name
+ (c-name "g_enum_get_value_by_name")
+ (return-type "GEnumValue*")
+ (parameters
+ '("GEnumClass*" "enum_class")
+ '("const-gchar*" "name")
+ )
+)
+
+(define-function g_enum_get_value_by_nick
+ (c-name "g_enum_get_value_by_nick")
+ (return-type "GEnumValue*")
+ (parameters
+ '("GEnumClass*" "enum_class")
+ '("const-gchar*" "nick")
+ )
+)
+
+(define-function g_flags_get_first_value
+ (c-name "g_flags_get_first_value")
+ (return-type "GFlagsValue*")
+ (parameters
+ '("GFlagsClass*" "flags_class")
+ '("guint" "value")
+ )
+)
+
+(define-function g_flags_get_value_by_name
+ (c-name "g_flags_get_value_by_name")
+ (return-type "GFlagsValue*")
+ (parameters
+ '("GFlagsClass*" "flags_class")
+ '("const-gchar*" "name")
+ )
+)
+
+(define-function g_flags_get_value_by_nick
+ (c-name "g_flags_get_value_by_nick")
+ (return-type "GFlagsValue*")
+ (parameters
+ '("GFlagsClass*" "flags_class")
+ '("const-gchar*" "nick")
+ )
+)
+
+(define-method set_enum
+ (of-object "GValue")
+ (c-name "g_value_set_enum")
+ (return-type "none")
+ (parameters
+ '("gint" "v_enum")
+ )
+)
+
+(define-method get_enum
+ (of-object "GValue")
+ (c-name "g_value_get_enum")
+ (return-type "gint")
+)
+
+(define-method set_flags
+ (of-object "GValue")
+ (c-name "g_value_set_flags")
+ (return-type "none")
+ (parameters
+ '("guint" "v_flags")
+ )
+)
+
+(define-method get_flags
+ (of-object "GValue")
+ (c-name "g_value_get_flags")
+ (return-type "guint")
+)
+
+(define-function g_enum_register_static
+ (c-name "g_enum_register_static")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-GEnumValue*" "const_static_values")
+ )
+)
+
+(define-function g_flags_register_static
+ (c-name "g_flags_register_static")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-GFlagsValue*" "const_static_values")
+ )
+)
+
+(define-function g_enum_complete_type_info
+ (c-name "g_enum_complete_type_info")
+ (return-type "none")
+ (parameters
+ '("GType" "g_enum_type")
+ '("GTypeInfo*" "info")
+ '("const-GEnumValue*" "const_values")
+ )
+)
+
+(define-function g_flags_complete_type_info
+ (c-name "g_flags_complete_type_info")
+ (return-type "none")
+ (parameters
+ '("GType" "g_flags_type")
+ '("GTypeInfo*" "info")
+ '("const-GFlagsValue*" "const_values")
+ )
+)
+
+
+
+;; From gobject/gmarshal.h
+
+
+
+;; From gobject/gobject.h
+
+(define-method install_property
+ (of-object "GObjectClass")
+ (c-name "g_object_class_install_property")
+ (return-type "none")
+ (parameters
+ '("guint" "property_id")
+ '("GParamSpec*" "pspec")
+ )
+)
+
+(define-method find_property
+ (of-object "GObjectClass")
+ (c-name "g_object_class_find_property")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "property_name")
+ )
+)
+
+(define-function g_object_new
+ (c-name "g_object_new")
+ (return-type "gpointer")
+ (parameters
+ '("GType" "object_type")
+ '("const-gchar*" "first_property_name")
+ )
+ (varargs #t)
+)
+
+(define-function g_object_newv
+ (c-name "g_object_newv")
+ (return-type "gpointer")
+ (parameters
+ '("GType" "object_type")
+ '("guint" "n_parameters")
+ '("GParameter*" "parameters")
+ )
+)
+
+(define-function g_object_new_valist
+ (c-name "g_object_new_valist")
+ (return-type "GObject*")
+ (parameters
+ '("GType" "object_type")
+ '("const-gchar*" "first_property_name")
+ '("va_list" "var_args")
+ )
+)
+
+(define-function g_object_set
+ (c-name "g_object_set")
+ (return-type "none")
+ (parameters
+ '("gpointer" "object")
+ '("const-gchar*" "first_property_name")
+ )
+ (varargs #t)
+)
+
+(define-function g_object_get
+ (c-name "g_object_get")
+ (return-type "none")
+ (parameters
+ '("gpointer" "object")
+ '("const-gchar*" "first_property_name")
+ )
+ (varargs #t)
+)
+
+(define-function g_object_connect
+ (c-name "g_object_connect")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "object")
+ '("const-gchar*" "signal_spec")
+ )
+ (varargs #t)
+)
+
+(define-function g_object_disconnect
+ (c-name "g_object_disconnect")
+ (return-type "none")
+ (parameters
+ '("gpointer" "object")
+ '("const-gchar*" "signal_spec")
+ )
+ (varargs #t)
+)
+
+(define-method set_valist
+ (of-object "GObject")
+ (c-name "g_object_set_valist")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "first_property_name")
+ '("va_list" "var_args")
+ )
+)
+
+(define-method get_valist
+ (of-object "GObject")
+ (c-name "g_object_get_valist")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "first_property_name")
+ '("va_list" "var_args")
+ )
+)
+
+(define-method set_property
+ (of-object "GObject")
+ (c-name "g_object_set_property")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "property_name")
+ '("const-GValue*" "value")
+ )
+)
+
+(define-method get_property
+ (of-object "GObject")
+ (c-name "g_object_get_property")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "property_name")
+ '("GValue*" "value")
+ )
+)
+
+(define-method freeze_notify
+ (of-object "GObject")
+ (c-name "g_object_freeze_notify")
+ (return-type "none")
+)
+
+(define-method notify
+ (of-object "GObject")
+ (c-name "g_object_notify")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "property_name")
+ )
+)
+
+(define-method thaw_notify
+ (of-object "GObject")
+ (c-name "g_object_thaw_notify")
+ (return-type "none")
+)
+
+(define-function g_object_ref
+ (c-name "g_object_ref")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "object")
+ )
+)
+
+(define-function g_object_unref
+ (c-name "g_object_unref")
+ (return-type "none")
+ (parameters
+ '("gpointer" "object")
+ )
+)
+
+(define-method weak_ref
+ (of-object "GObject")
+ (c-name "g_object_weak_ref")
+ (return-type "none")
+ (parameters
+ '("GWeakNotify" "notify")
+ '("gpointer" "data")
+ )
+)
+
+(define-method weak_unref
+ (of-object "GObject")
+ (c-name "g_object_weak_unref")
+ (return-type "none")
+ (parameters
+ '("GWeakNotify" "notify")
+ '("gpointer" "data")
+ )
+)
+
+(define-method add_weak_pointer
+ (of-object "GObject")
+ (c-name "g_object_add_weak_pointer")
+ (return-type "none")
+ (parameters
+ '("gpointer*" "weak_pointer_location")
+ )
+)
+
+(define-method remove_weak_pointer
+ (of-object "GObject")
+ (c-name "g_object_remove_weak_pointer")
+ (return-type "none")
+ (parameters
+ '("gpointer*" "weak_pointer_location")
+ )
+)
+
+(define-method get_qdata
+ (of-object "GObject")
+ (c-name "g_object_get_qdata")
+ (return-type "gpointer")
+ (parameters
+ '("GQuark" "quark")
+ )
+)
+
+(define-method set_qdata
+ (of-object "GObject")
+ (c-name "g_object_set_qdata")
+ (return-type "none")
+ (parameters
+ '("GQuark" "quark")
+ '("gpointer" "data")
+ )
+)
+
+(define-method set_qdata_full
+ (of-object "GObject")
+ (c-name "g_object_set_qdata_full")
+ (return-type "none")
+ (parameters
+ '("GQuark" "quark")
+ '("gpointer" "data")
+ '("GDestroyNotify" "destroy")
+ )
+)
+
+(define-method steal_qdata
+ (of-object "GObject")
+ (c-name "g_object_steal_qdata")
+ (return-type "gpointer")
+ (parameters
+ '("GQuark" "quark")
+ )
+)
+
+(define-method get_data
+ (of-object "GObject")
+ (c-name "g_object_get_data")
+ (return-type "gpointer")
+ (parameters
+ '("const-gchar*" "key")
+ )
+)
+
+(define-method set_data
+ (of-object "GObject")
+ (c-name "g_object_set_data")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "key")
+ '("gpointer" "data")
+ )
+)
+
+(define-method set_data_full
+ (of-object "GObject")
+ (c-name "g_object_set_data_full")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "key")
+ '("gpointer" "data")
+ '("GDestroyNotify" "destroy")
+ )
+)
+
+(define-method steal_data
+ (of-object "GObject")
+ (c-name "g_object_steal_data")
+ (return-type "gpointer")
+ (parameters
+ '("const-gchar*" "key")
+ )
+)
+
+(define-method watch_closure
+ (of-object "GObject")
+ (c-name "g_object_watch_closure")
+ (return-type "none")
+ (parameters
+ '("GClosure*" "closure")
+ )
+)
+
+(define-function g_cclosure_new_object
+ (c-name "g_cclosure_new_object")
+ (return-type "GClosure*")
+ (parameters
+ '("GCallback" "callback_func")
+ '("GObject*" "object")
+ )
+)
+
+(define-function g_cclosure_new_object_swap
+ (c-name "g_cclosure_new_object_swap")
+ (return-type "GClosure*")
+ (parameters
+ '("GCallback" "callback_func")
+ '("GObject*" "object")
+ )
+)
+
+(define-function g_closure_new_object
+ (c-name "g_closure_new_object")
+ (return-type "GClosure*")
+ (parameters
+ '("guint" "sizeof_closure")
+ '("GObject*" "object")
+ )
+)
+
+(define-method set_object
+ (of-object "GValue")
+ (c-name "g_value_set_object")
+ (return-type "none")
+ (parameters
+ '("gpointer" "v_object")
+ )
+)
+
+(define-method get_object
+ (of-object "GValue")
+ (c-name "g_value_get_object")
+ (return-type "gpointer")
+)
+
+(define-method dup_object
+ (of-object "GValue")
+ (c-name "g_value_dup_object")
+ (return-type "GObject*")
+)
+
+(define-function g_signal_connect_object
+ (c-name "g_signal_connect_object")
+ (return-type "gulong")
+ (parameters
+ '("gpointer" "instance")
+ '("const-gchar*" "detailed_signal")
+ '("GCallback" "c_handler")
+ '("gpointer" "gobject")
+ '("GConnectFlags" "connect_flags")
+ )
+)
+
+(define-method run_dispose
+ (of-object "GObject")
+ (c-name "g_object_run_dispose")
+ (return-type "none")
+)
+
+(define-method set_object_take_ownership
+ (of-object "GValue")
+ (c-name "g_value_set_object_take_ownership")
+ (return-type "none")
+ (parameters
+ '("gpointer" "v_object")
+ )
+)
+
+
+
+;; From gobject/gparam.h
+
+(define-method ref
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_ref")
+ (return-type "GParamSpec*")
+)
+
+(define-method unref
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_unref")
+ (return-type "none")
+)
+
+(define-method sink
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_sink")
+ (return-type "none")
+)
+
+(define-method get_qdata
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_get_qdata")
+ (return-type "gpointer")
+ (parameters
+ '("GQuark" "quark")
+ )
+)
+
+(define-method set_qdata
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_set_qdata")
+ (return-type "none")
+ (parameters
+ '("GQuark" "quark")
+ '("gpointer" "data")
+ )
+)
+
+(define-method set_qdata_full
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_set_qdata_full")
+ (return-type "none")
+ (parameters
+ '("GQuark" "quark")
+ '("gpointer" "data")
+ '("GDestroyNotify" "destroy")
+ )
+)
+
+(define-method steal_qdata
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_steal_qdata")
+ (return-type "gpointer")
+ (parameters
+ '("GQuark" "quark")
+ )
+)
+
+(define-function g_param_value_set_default
+ (c-name "g_param_value_set_default")
+ (return-type "none")
+ (parameters
+ '("GParamSpec*" "pspec")
+ '("GValue*" "value")
+ )
+)
+
+(define-function g_param_value_defaults
+ (c-name "g_param_value_defaults")
+ (return-type "gboolean")
+ (parameters
+ '("GParamSpec*" "pspec")
+ '("GValue*" "value")
+ )
+)
+
+(define-function g_param_value_validate
+ (c-name "g_param_value_validate")
+ (return-type "gboolean")
+ (parameters
+ '("GParamSpec*" "pspec")
+ '("GValue*" "value")
+ )
+)
+
+(define-function g_param_value_convert
+ (c-name "g_param_value_convert")
+ (return-type "gboolean")
+ (parameters
+ '("GParamSpec*" "pspec")
+ '("const-GValue*" "src_value")
+ '("GValue*" "dest_value")
+ '("gboolean" "strict_validation")
+ )
+)
+
+(define-function g_param_values_cmp
+ (c-name "g_param_values_cmp")
+ (return-type "gint")
+ (parameters
+ '("GParamSpec*" "pspec")
+ '("const-GValue*" "value1")
+ '("const-GValue*" "value2")
+ )
+)
+
+(define-method get_name
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_get_name")
+ (return-type "const-gchar*")
+)
+
+(define-method get_nick
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_get_nick")
+ (return-type "const-gchar*")
+)
+
+(define-method get_blurb
+ (of-object "GParamSpec")
+ (c-name "g_param_spec_get_blurb")
+ (return-type "const-gchar*")
+)
+
+(define-method set_param
+ (of-object "GValue")
+ (c-name "g_value_set_param")
+ (return-type "none")
+ (parameters
+ '("GParamSpec*" "param")
+ )
+)
+
+(define-method get_param
+ (of-object "GValue")
+ (c-name "g_value_get_param")
+ (return-type "GParamSpec*")
+)
+
+(define-method dup_param
+ (of-object "GValue")
+ (c-name "g_value_dup_param")
+ (return-type "GParamSpec*")
+)
+
+(define-method set_param_take_ownership
+ (of-object "GValue")
+ (c-name "g_value_set_param_take_ownership")
+ (return-type "none")
+ (parameters
+ '("GParamSpec*" "param")
+ )
+)
+
+(define-function g_param_type_register_static
+ (c-name "g_param_type_register_static")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-GParamSpecTypeInfo*" "pspec_info")
+ )
+)
+
+(define-function _g_param_type_register_static_constant
+ (c-name "_g_param_type_register_static_constant")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-GParamSpecTypeInfo*" "pspec_info")
+ '("GType" "opt_type")
+ )
+)
+
+(define-function g_param_spec_internal
+ (c-name "g_param_spec_internal")
+ (return-type "gpointer")
+ (parameters
+ '("GType" "param_type")
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_pool_new
+ (c-name "g_param_spec_pool_new")
+ (return-type "GParamSpecPool*")
+ (parameters
+ '("gboolean" "type_prefixing")
+ )
+)
+
+(define-method insert
+ (of-object "GParamSpecPool")
+ (c-name "g_param_spec_pool_insert")
+ (return-type "none")
+ (parameters
+ '("GParamSpec*" "pspec")
+ '("GType" "owner_type")
+ )
+)
+
+(define-method remove
+ (of-object "GParamSpecPool")
+ (c-name "g_param_spec_pool_remove")
+ (return-type "none")
+ (parameters
+ '("GParamSpec*" "pspec")
+ )
+)
+
+(define-method lookup
+ (of-object "GParamSpecPool")
+ (c-name "g_param_spec_pool_lookup")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "param_name")
+ '("GType" "owner_type")
+ '("gboolean" "walk_ancestors")
+ )
+)
+
+(define-method list_owned
+ (of-object "GParamSpecPool")
+ (c-name "g_param_spec_pool_list_owned")
+ (return-type "GList*")
+ (parameters
+ '("GType" "owner_type")
+ )
+)
+
+(define-method list
+ (of-object "GParamSpecPool")
+ (c-name "g_param_spec_pool_list")
+ (return-type "GParamSpec**")
+ (parameters
+ '("GType" "owner_type")
+ '("guint*" "n_pspecs_p")
+ )
+)
+
+
+
+;; From gobject/gparamspecs.h
+
+(define-function g_param_spec_char
+ (c-name "g_param_spec_char")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gint8" "minimum")
+ '("gint8" "maximum")
+ '("gint8" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_uchar
+ (c-name "g_param_spec_uchar")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("guint8" "minimum")
+ '("guint8" "maximum")
+ '("guint8" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_boolean
+ (c-name "g_param_spec_boolean")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gboolean" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_int
+ (c-name "g_param_spec_int")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gint" "minimum")
+ '("gint" "maximum")
+ '("gint" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_uint
+ (c-name "g_param_spec_uint")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("guint" "minimum")
+ '("guint" "maximum")
+ '("guint" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_long
+ (c-name "g_param_spec_long")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("glong" "minimum")
+ '("glong" "maximum")
+ '("glong" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_ulong
+ (c-name "g_param_spec_ulong")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gulong" "minimum")
+ '("gulong" "maximum")
+ '("gulong" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_int64
+ (c-name "g_param_spec_int64")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gint64" "minimum")
+ '("gint64" "maximum")
+ '("gint64" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_uint64
+ (c-name "g_param_spec_uint64")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("guint64" "minimum")
+ '("guint64" "maximum")
+ '("guint64" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_unichar
+ (c-name "g_param_spec_unichar")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gunichar" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_enum
+ (c-name "g_param_spec_enum")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GType" "enum_type")
+ '("gint" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_flags
+ (c-name "g_param_spec_flags")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GType" "flags_type")
+ '("guint" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_float
+ (c-name "g_param_spec_float")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gfloat" "minimum")
+ '("gfloat" "maximum")
+ '("gfloat" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_double
+ (c-name "g_param_spec_double")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("gdouble" "minimum")
+ '("gdouble" "maximum")
+ '("gdouble" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_string
+ (c-name "g_param_spec_string")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("const-gchar*" "default_value")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_param
+ (c-name "g_param_spec_param")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GType" "param_type")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_boxed
+ (c-name "g_param_spec_boxed")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GType" "boxed_type")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_pointer
+ (c-name "g_param_spec_pointer")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_value_array
+ (c-name "g_param_spec_value_array")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GParamSpec*" "element_spec")
+ '("GParamFlags" "flags")
+ )
+)
+
+(define-function g_param_spec_object
+ (c-name "g_param_spec_object")
+ (return-type "GParamSpec*")
+ (parameters
+ '("const-gchar*" "name")
+ '("const-gchar*" "nick")
+ '("const-gchar*" "blurb")
+ '("GType" "object_type")
+ '("GParamFlags" "flags")
+ )
+)
+
+
+
+;; From gobject/gsignal.h
+
+(define-function g_signal_newv
+ (c-name "g_signal_newv")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "signal_name")
+ '("GType" "itype")
+ '("GSignalFlags" "signal_flags")
+ '("GClosure*" "class_closure")
+ '("GSignalAccumulator" "accumulator")
+ '("gpointer" "accu_data")
+ '("GSignalCMarshaller" "c_marshaller")
+ '("GType" "return_type")
+ '("guint" "n_params")
+ '("GType*" "param_types")
+ )
+)
+
+(define-function g_signal_new_valist
+ (c-name "g_signal_new_valist")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "signal_name")
+ '("GType" "itype")
+ '("GSignalFlags" "signal_flags")
+ '("GClosure*" "class_closure")
+ '("GSignalAccumulator" "accumulator")
+ '("gpointer" "accu_data")
+ '("GSignalCMarshaller" "c_marshaller")
+ '("GType" "return_type")
+ '("guint" "n_params")
+ '("va_list" "args")
+ )
+)
+
+(define-function g_signal_new
+ (c-name "g_signal_new")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "signal_name")
+ '("GType" "itype")
+ '("GSignalFlags" "signal_flags")
+ '("guint" "class_offset")
+ '("GSignalAccumulator" "accumulator")
+ '("gpointer" "accu_data")
+ '("GSignalCMarshaller" "c_marshaller")
+ '("GType" "return_type")
+ '("guint" "n_params")
+ )
+ (varargs #t)
+)
+
+(define-function g_signal_emitv
+ (c-name "g_signal_emitv")
+ (return-type "none")
+ (parameters
+ '("const-GValue*" "instance_and_params")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("GValue*" "return_value")
+ )
+)
+
+(define-function g_signal_emit_valist
+ (c-name "g_signal_emit_valist")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("va_list" "var_args")
+ )
+)
+
+(define-function g_signal_emit
+ (c-name "g_signal_emit")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ )
+ (varargs #t)
+)
+
+(define-function g_signal_emit_by_name
+ (c-name "g_signal_emit_by_name")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("const-gchar*" "detailed_signal")
+ )
+ (varargs #t)
+)
+
+(define-function g_signal_lookup
+ (c-name "g_signal_lookup")
+ (return-type "guint")
+ (parameters
+ '("const-gchar*" "name")
+ '("GType" "itype")
+ )
+)
+
+(define-function g_signal_name
+ (c-name "g_signal_name")
+ (return-type "const-gchar*")
+ (parameters
+ '("guint" "signal_id")
+ )
+)
+
+(define-function g_signal_query
+ (c-name "g_signal_query")
+ (return-type "none")
+ (parameters
+ '("guint" "signal_id")
+ '("GSignalQuery*" "query")
+ )
+)
+
+(define-function g_signal_list_ids
+ (c-name "g_signal_list_ids")
+ (return-type "guint*")
+ (parameters
+ '("GType" "itype")
+ '("guint*" "n_ids")
+ )
+)
+
+(define-function g_signal_parse_name
+ (c-name "g_signal_parse_name")
+ (return-type "gboolean")
+ (parameters
+ '("const-gchar*" "detailed_signal")
+ '("GType" "itype")
+ '("guint*" "signal_id_p")
+ '("GQuark*" "detail_p")
+ '("gboolean" "force_detail_quark")
+ )
+)
+
+(define-function g_signal_get_invocation_hint
+ (c-name "g_signal_get_invocation_hint")
+ (return-type "GSignalInvocationHint*")
+ (parameters
+ '("gpointer" "instance")
+ )
+)
+
+(define-function g_signal_stop_emission
+ (c-name "g_signal_stop_emission")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ )
+)
+
+(define-function g_signal_stop_emission_by_name
+ (c-name "g_signal_stop_emission_by_name")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("const-gchar*" "detailed_signal")
+ )
+)
+
+(define-function g_signal_add_emission_hook
+ (c-name "g_signal_add_emission_hook")
+ (return-type "gulong")
+ (parameters
+ '("guint" "signal_id")
+ '("GQuark" "quark")
+ '("GSignalEmissionHook" "hook_func")
+ '("gpointer" "hook_data")
+ '("GDestroyNotify" "data_destroy")
+ )
+)
+
+(define-function g_signal_remove_emission_hook
+ (c-name "g_signal_remove_emission_hook")
+ (return-type "none")
+ (parameters
+ '("guint" "signal_id")
+ '("gulong" "hook_id")
+ )
+)
+
+(define-function g_signal_has_handler_pending
+ (c-name "g_signal_has_handler_pending")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "instance")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("gboolean" "may_be_blocked")
+ )
+)
+
+(define-function g_signal_connect_closure_by_id
+ (c-name "g_signal_connect_closure_by_id")
+ (return-type "gulong")
+ (parameters
+ '("gpointer" "instance")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("GClosure*" "closure")
+ '("gboolean" "after")
+ )
+)
+
+(define-function g_signal_connect_closure
+ (c-name "g_signal_connect_closure")
+ (return-type "gulong")
+ (parameters
+ '("gpointer" "instance")
+ '("const-gchar*" "detailed_signal")
+ '("GClosure*" "closure")
+ '("gboolean" "after")
+ )
+)
+
+(define-function g_signal_connect_data
+ (c-name "g_signal_connect_data")
+ (return-type "gulong")
+ (parameters
+ '("gpointer" "instance")
+ '("const-gchar*" "detailed_signal")
+ '("GCallback" "c_handler")
+ '("gpointer" "data")
+ '("GClosureNotify" "destroy_data")
+ '("GConnectFlags" "connect_flags")
+ )
+)
+
+(define-function g_signal_handler_block
+ (c-name "g_signal_handler_block")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("gulong" "handler_id")
+ )
+)
+
+(define-function g_signal_handler_unblock
+ (c-name "g_signal_handler_unblock")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("gulong" "handler_id")
+ )
+)
+
+(define-function g_signal_handler_disconnect
+ (c-name "g_signal_handler_disconnect")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ '("gulong" "handler_id")
+ )
+)
+
+(define-function g_signal_handler_is_connected
+ (c-name "g_signal_handler_is_connected")
+ (return-type "gboolean")
+ (parameters
+ '("gpointer" "instance")
+ '("gulong" "handler_id")
+ )
+)
+
+(define-function g_signal_handler_find
+ (c-name "g_signal_handler_find")
+ (return-type "gulong")
+ (parameters
+ '("gpointer" "instance")
+ '("GSignalMatchType" "mask")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("GClosure*" "closure")
+ '("gpointer" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_signal_handlers_block_matched
+ (c-name "g_signal_handlers_block_matched")
+ (return-type "guint")
+ (parameters
+ '("gpointer" "instance")
+ '("GSignalMatchType" "mask")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("GClosure*" "closure")
+ '("gpointer" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_signal_handlers_unblock_matched
+ (c-name "g_signal_handlers_unblock_matched")
+ (return-type "guint")
+ (parameters
+ '("gpointer" "instance")
+ '("GSignalMatchType" "mask")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("GClosure*" "closure")
+ '("gpointer" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_signal_handlers_disconnect_matched
+ (c-name "g_signal_handlers_disconnect_matched")
+ (return-type "guint")
+ (parameters
+ '("gpointer" "instance")
+ '("GSignalMatchType" "mask")
+ '("guint" "signal_id")
+ '("GQuark" "detail")
+ '("GClosure*" "closure")
+ '("gpointer" "func")
+ '("gpointer" "data")
+ )
+)
+
+(define-function g_signal_override_class_closure
+ (c-name "g_signal_override_class_closure")
+ (return-type "none")
+ (parameters
+ '("guint" "signal_id")
+ '("GType" "instance_type")
+ '("GClosure*" "class_closure")
+ )
+)
+
+(define-function g_signal_chain_from_overridden
+ (c-name "g_signal_chain_from_overridden")
+ (return-type "none")
+ (parameters
+ '("const-GValue*" "instance_and_params")
+ '("GValue*" "return_value")
+ )
+)
+
+(define-function _g_signals_destroy
+ (c-name "_g_signals_destroy")
+ (return-type "none")
+ (parameters
+ '("GType" "itype")
+ )
+)
+
+
+
+;; From gobject/gsourceclosure.h
+
+(define-function g_io_channel_get_type
+ (c-name "g_io_channel_get_type")
+ (return-type "GType")
+)
+
+(define-function g_io_condition_get_type
+ (c-name "g_io_condition_get_type")
+ (return-type "GType")
+)
+
+
+
+;; From gobject/gtype.h
+
+(define-function g_type_init
+ (c-name "g_type_init")
+ (return-type "none")
+)
+
+(define-function g_type_init_with_debug_flags
+ (c-name "g_type_init_with_debug_flags")
+ (return-type "none")
+ (parameters
+ '("GTypeDebugFlags" "debug_flags")
+ )
+)
+
+(define-method name
+ (of-object "GType")
+ (c-name "g_type_name")
+ (return-type "const-gchar*")
+)
+
+(define-method qname
+ (of-object "GType")
+ (c-name "g_type_qname")
+ (return-type "GQuark")
+)
+
+(define-function g_type_from_name
+ (c-name "g_type_from_name")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ )
+)
+
+(define-method parent
+ (of-object "GType")
+ (c-name "g_type_parent")
+ (return-type "GType")
+)
+
+(define-method depth
+ (of-object "GType")
+ (c-name "g_type_depth")
+ (return-type "guint")
+)
+
+(define-method next_base
+ (of-object "GType")
+ (c-name "g_type_next_base")
+ (return-type "GType")
+ (parameters
+ '("GType" "root_type")
+ )
+)
+
+(define-method is_a
+ (of-object "GType")
+ (c-name "g_type_is_a")
+ (return-type "gboolean")
+ (parameters
+ '("GType" "is_a_type")
+ )
+)
+
+(define-method class_ref
+ (of-object "GType")
+ (c-name "g_type_class_ref")
+ (return-type "gpointer")
+)
+
+(define-method class_peek
+ (of-object "GType")
+ (c-name "g_type_class_peek")
+ (return-type "gpointer")
+)
+
+(define-function g_type_class_unref
+ (c-name "g_type_class_unref")
+ (return-type "none")
+ (parameters
+ '("gpointer" "g_class")
+ )
+)
+
+(define-function g_type_class_peek_parent
+ (c-name "g_type_class_peek_parent")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "g_class")
+ )
+)
+
+(define-function g_type_interface_peek
+ (c-name "g_type_interface_peek")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "instance_class")
+ '("GType" "iface_type")
+ )
+)
+
+(define-function g_type_interface_peek_parent
+ (c-name "g_type_interface_peek_parent")
+ (return-type "gpointer")
+ (parameters
+ '("gpointer" "g_iface")
+ )
+)
+
+(define-method children
+ (of-object "GType")
+ (c-name "g_type_children")
+ (return-type "GType*")
+ (parameters
+ '("guint*" "n_children")
+ )
+)
+
+(define-method interfaces
+ (of-object "GType")
+ (c-name "g_type_interfaces")
+ (return-type "GType*")
+ (parameters
+ '("guint*" "n_interfaces")
+ )
+)
+
+(define-method set_qdata
+ (of-object "GType")
+ (c-name "g_type_set_qdata")
+ (return-type "none")
+ (parameters
+ '("GQuark" "quark")
+ '("gpointer" "data")
+ )
+)
+
+(define-method get_qdata
+ (of-object "GType")
+ (c-name "g_type_get_qdata")
+ (return-type "gpointer")
+ (parameters
+ '("GQuark" "quark")
+ )
+)
+
+(define-method query
+ (of-object "GType")
+ (c-name "g_type_query")
+ (return-type "none")
+ (parameters
+ '("GTypeQuery*" "query")
+ )
+)
+
+(define-method register_static
+ (of-object "GType")
+ (c-name "g_type_register_static")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "type_name")
+ '("const-GTypeInfo*" "info")
+ '("GTypeFlags" "flags")
+ )
+)
+
+(define-method register_dynamic
+ (of-object "GType")
+ (c-name "g_type_register_dynamic")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "type_name")
+ '("GTypePlugin*" "plugin")
+ '("GTypeFlags" "flags")
+ )
+)
+
+(define-method register_fundamental
+ (of-object "GType")
+ (c-name "g_type_register_fundamental")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "type_name")
+ '("const-GTypeInfo*" "info")
+ '("const-GTypeFundamentalInfo*" "finfo")
+ '("GTypeFlags" "flags")
+ )
+)
+
+(define-method add_interface_static
+ (of-object "GType")
+ (c-name "g_type_add_interface_static")
+ (return-type "none")
+ (parameters
+ '("GType" "interface_type")
+ '("const-GInterfaceInfo*" "info")
+ )
+)
+
+(define-method add_interface_dynamic
+ (of-object "GType")
+ (c-name "g_type_add_interface_dynamic")
+ (return-type "none")
+ (parameters
+ '("GType" "interface_type")
+ '("GTypePlugin*" "plugin")
+ )
+)
+
+(define-method interface_add_prerequisite
+ (of-object "GType")
+ (c-name "g_type_interface_add_prerequisite")
+ (return-type "none")
+ (parameters
+ '("GType" "prerequisite_type")
+ )
+)
+
+(define-method get_plugin
+ (of-object "GType")
+ (c-name "g_type_get_plugin")
+ (return-type "GTypePlugin*")
+)
+
+(define-method interface_get_plugin
+ (of-object "GType")
+ (c-name "g_type_interface_get_plugin")
+ (return-type "GTypePlugin*")
+ (parameters
+ '("GType" "implementation_type")
+ )
+)
+
+(define-function g_type_fundamental_next
+ (c-name "g_type_fundamental_next")
+ (return-type "GType")
+)
+
+(define-method fundamental
+ (of-object "GType")
+ (c-name "g_type_fundamental")
+ (return-type "GType")
+)
+
+(define-method create_instance
+ (of-object "GType")
+ (c-name "g_type_create_instance")
+ (return-type "GTypeInstance*")
+)
+
+(define-function g_type_free_instance
+ (c-name "g_type_free_instance")
+ (return-type "none")
+ (parameters
+ '("GTypeInstance*" "instance")
+ )
+)
+
+(define-function g_type_add_class_cache_func
+ (c-name "g_type_add_class_cache_func")
+ (return-type "none")
+ (parameters
+ '("gpointer" "cache_data")
+ '("GTypeClassCacheFunc" "cache_func")
+ )
+)
+
+(define-function g_type_remove_class_cache_func
+ (c-name "g_type_remove_class_cache_func")
+ (return-type "none")
+ (parameters
+ '("gpointer" "cache_data")
+ '("GTypeClassCacheFunc" "cache_func")
+ )
+)
+
+(define-function g_type_class_unref_uncached
+ (c-name "g_type_class_unref_uncached")
+ (return-type "none")
+ (parameters
+ '("gpointer" "g_class")
+ )
+)
+
+(define-method value_table_peek
+ (of-object "GType")
+ (c-name "g_type_value_table_peek")
+ (return-type "GTypeValueTable*")
+)
+
+(define-function g_type_check_instance
+ (c-name "g_type_check_instance")
+ (return-type "gboolean")
+ (parameters
+ '("GTypeInstance*" "instance")
+ )
+)
+
+(define-function g_type_check_instance_cast
+ (c-name "g_type_check_instance_cast")
+ (return-type "GTypeInstance*")
+ (parameters
+ '("GTypeInstance*" "instance")
+ '("GType" "iface_type")
+ )
+)
+
+(define-function g_type_check_instance_is_a
+ (c-name "g_type_check_instance_is_a")
+ (return-type "gboolean")
+ (parameters
+ '("GTypeInstance*" "instance")
+ '("GType" "iface_type")
+ )
+)
+
+(define-function g_type_check_class_cast
+ (c-name "g_type_check_class_cast")
+ (return-type "GTypeClass*")
+ (parameters
+ '("GTypeClass*" "g_class")
+ '("GType" "is_a_type")
+ )
+)
+
+(define-function g_type_check_class_is_a
+ (c-name "g_type_check_class_is_a")
+ (return-type "gboolean")
+ (parameters
+ '("GTypeClass*" "g_class")
+ '("GType" "is_a_type")
+ )
+)
+
+(define-method check_is_value_type
+ (of-object "GType")
+ (c-name "g_type_check_is_value_type")
+ (return-type "gboolean")
+)
+
+(define-function g_type_check_value
+ (c-name "g_type_check_value")
+ (return-type "gboolean")
+ (parameters
+ '("GValue*" "value")
+ )
+)
+
+(define-function g_type_check_value_holds
+ (c-name "g_type_check_value_holds")
+ (return-type "gboolean")
+ (parameters
+ '("GValue*" "value")
+ '("GType" "type")
+ )
+)
+
+(define-method test_flags
+ (of-object "GType")
+ (c-name "g_type_test_flags")
+ (return-type "gboolean")
+ (parameters
+ '("guint" "flags")
+ )
+)
+
+(define-function g_type_name_from_instance
+ (c-name "g_type_name_from_instance")
+ (return-type "const-gchar*")
+ (parameters
+ '("GTypeInstance*" "instance")
+ )
+)
+
+(define-function g_type_name_from_class
+ (c-name "g_type_name_from_class")
+ (return-type "const-gchar*")
+ (parameters
+ '("GTypeClass*" "g_class")
+ )
+)
+
+
+
+;; From gobject/gtypemodule.h
+
+(define-function g_type_module_get_type
+ (c-name "g_type_module_get_type")
+ (return-type "GType")
+)
+
+(define-method use
+ (of-object "GTypeModule")
+ (c-name "g_type_module_use")
+ (return-type "gboolean")
+)
+
+(define-method unuse
+ (of-object "GTypeModule")
+ (c-name "g_type_module_unuse")
+ (return-type "none")
+)
+
+(define-method set_name
+ (of-object "GTypeModule")
+ (c-name "g_type_module_set_name")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "name")
+ )
+)
+
+(define-method register_type
+ (of-object "GTypeModule")
+ (c-name "g_type_module_register_type")
+ (return-type "GType")
+ (parameters
+ '("GType" "parent_type")
+ '("const-gchar*" "type_name")
+ '("const-GTypeInfo*" "type_info")
+ '("GTypeFlags" "flags")
+ )
+)
+
+(define-method add_interface
+ (of-object "GTypeModule")
+ (c-name "g_type_module_add_interface")
+ (return-type "none")
+ (parameters
+ '("GType" "instance_type")
+ '("GType" "interface_type")
+ '("const-GInterfaceInfo*" "interface_info")
+ )
+)
+
+
+
+;; From gobject/gtypeplugin.h
+
+(define-function g_type_plugin_get_type
+ (c-name "g_type_plugin_get_type")
+ (return-type "GType")
+)
+
+(define-method use
+ (of-object "GTypePlugin")
+ (c-name "g_type_plugin_use")
+ (return-type "none")
+)
+
+(define-method unuse
+ (of-object "GTypePlugin")
+ (c-name "g_type_plugin_unuse")
+ (return-type "none")
+)
+
+(define-method complete_type_info
+ (of-object "GTypePlugin")
+ (c-name "g_type_plugin_complete_type_info")
+ (return-type "none")
+ (parameters
+ '("GType" "g_type")
+ '("GTypeInfo*" "info")
+ '("GTypeValueTable*" "value_table")
+ )
+)
+
+(define-method complete_interface_info
+ (of-object "GTypePlugin")
+ (c-name "g_type_plugin_complete_interface_info")
+ (return-type "none")
+ (parameters
+ '("GType" "interface_type")
+ '("GType" "instance_type")
+ '("GInterfaceInfo*" "info")
+ )
+)
+
+
+
+;; From gobject/gvaluearray.h
+
+(define-method get_nth
+ (of-object "GValueArray")
+ (c-name "g_value_array_get_nth")
+ (return-type "GValue*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-function g_value_array_new
+ (c-name "g_value_array_new")
+ (return-type "GValueArray*")
+ (parameters
+ '("guint" "n_prealloced")
+ )
+)
+
+(define-method free
+ (of-object "GValueArray")
+ (c-name "g_value_array_free")
+ (return-type "none")
+)
+
+(define-method copy
+ (of-object "GValueArray")
+ (c-name "g_value_array_copy")
+ (return-type "GValueArray*")
+)
+
+(define-method prepend
+ (of-object "GValueArray")
+ (c-name "g_value_array_prepend")
+ (return-type "GValueArray*")
+ (parameters
+ '("const-GValue*" "value")
+ )
+)
+
+(define-method append
+ (of-object "GValueArray")
+ (c-name "g_value_array_append")
+ (return-type "GValueArray*")
+ (parameters
+ '("const-GValue*" "value")
+ )
+)
+
+(define-method insert
+ (of-object "GValueArray")
+ (c-name "g_value_array_insert")
+ (return-type "GValueArray*")
+ (parameters
+ '("guint" "index")
+ '("const-GValue*" "value")
+ )
+)
+
+(define-method remove
+ (of-object "GValueArray")
+ (c-name "g_value_array_remove")
+ (return-type "GValueArray*")
+ (parameters
+ '("guint" "index")
+ )
+)
+
+(define-method sort
+ (of-object "GValueArray")
+ (c-name "g_value_array_sort")
+ (return-type "GValueArray*")
+ (parameters
+ '("GCompareFunc" "compare_func")
+ )
+)
+
+(define-method sort_with_data
+ (of-object "GValueArray")
+ (c-name "g_value_array_sort_with_data")
+ (return-type "GValueArray*")
+ (parameters
+ '("GCompareDataFunc" "compare_func")
+ '("gpointer" "user_data")
+ )
+)
+
+
+
+;; From gobject/gvaluecollector.h
+
+
+
+;; From gobject/gvalue.h
+
+(define-method init
+ (of-object "GValue")
+ (c-name "g_value_init")
+ (return-type "GValue*")
+ (parameters
+ '("GType" "g_type")
+ )
+)
+
+(define-method copy
+ (of-object "GValue")
+ (c-name "g_value_copy")
+ (return-type "none")
+ (parameters
+ '("GValue*" "dest_value")
+ )
+)
+
+(define-method reset
+ (of-object "GValue")
+ (c-name "g_value_reset")
+ (return-type "GValue*")
+)
+
+(define-method unset
+ (of-object "GValue")
+ (c-name "g_value_unset")
+ (return-type "none")
+)
+
+(define-method set_instance
+ (of-object "GValue")
+ (c-name "g_value_set_instance")
+ (return-type "none")
+ (parameters
+ '("gpointer" "instance")
+ )
+)
+
+(define-method fits_pointer
+ (of-object "GValue")
+ (c-name "g_value_fits_pointer")
+ (return-type "gboolean")
+)
+
+(define-method peek_pointer
+ (of-object "GValue")
+ (c-name "g_value_peek_pointer")
+ (return-type "gpointer")
+)
+
+(define-function g_value_type_compatible
+ (c-name "g_value_type_compatible")
+ (return-type "gboolean")
+ (parameters
+ '("GType" "src_type")
+ '("GType" "dest_type")
+ )
+)
+
+(define-function g_value_type_transformable
+ (c-name "g_value_type_transformable")
+ (return-type "gboolean")
+ (parameters
+ '("GType" "src_type")
+ '("GType" "dest_type")
+ )
+)
+
+(define-method transform
+ (of-object "GValue")
+ (c-name "g_value_transform")
+ (return-type "gboolean")
+ (parameters
+ '("GValue*" "dest_value")
+ )
+)
+
+(define-function g_value_register_transform_func
+ (c-name "g_value_register_transform_func")
+ (return-type "none")
+ (parameters
+ '("GType" "src_type")
+ '("GType" "dest_type")
+ '("GValueTransform" "transform_func")
+ )
+)
+
+
+
+;; From gobject/gvaluetypes.h
+
+(define-method get_char
+ (of-object "GValue")
+ (c-name "g_value_get_char")
+ (return-type "gchar")
+)
+
+(define-method set_uchar
+ (of-object "GValue")
+ (c-name "g_value_set_uchar")
+ (return-type "none")
+ (parameters
+ '("guchar" "v_uchar")
+ )
+)
+
+(define-method get_uchar
+ (of-object "GValue")
+ (c-name "g_value_get_uchar")
+ (return-type "guchar")
+)
+
+(define-method set_boolean
+ (of-object "GValue")
+ (c-name "g_value_set_boolean")
+ (return-type "none")
+ (parameters
+ '("gboolean" "v_boolean")
+ )
+)
+
+(define-method get_boolean
+ (of-object "GValue")
+ (c-name "g_value_get_boolean")
+ (return-type "gboolean")
+)
+
+(define-method set_int
+ (of-object "GValue")
+ (c-name "g_value_set_int")
+ (return-type "none")
+ (parameters
+ '("gint" "v_int")
+ )
+)
+
+(define-method get_int
+ (of-object "GValue")
+ (c-name "g_value_get_int")
+ (return-type "gint")
+)
+
+(define-method set_uint
+ (of-object "GValue")
+ (c-name "g_value_set_uint")
+ (return-type "none")
+ (parameters
+ '("guint" "v_uint")
+ )
+)
+
+(define-method get_uint
+ (of-object "GValue")
+ (c-name "g_value_get_uint")
+ (return-type "guint")
+)
+
+(define-method set_long
+ (of-object "GValue")
+ (c-name "g_value_set_long")
+ (return-type "none")
+ (parameters
+ '("glong" "v_long")
+ )
+)
+
+(define-method get_long
+ (of-object "GValue")
+ (c-name "g_value_get_long")
+ (return-type "glong")
+)
+
+(define-method set_ulong
+ (of-object "GValue")
+ (c-name "g_value_set_ulong")
+ (return-type "none")
+ (parameters
+ '("gulong" "v_ulong")
+ )
+)
+
+(define-method get_ulong
+ (of-object "GValue")
+ (c-name "g_value_get_ulong")
+ (return-type "gulong")
+)
+
+(define-method set_int64
+ (of-object "GValue")
+ (c-name "g_value_set_int64")
+ (return-type "none")
+ (parameters
+ '("gint64" "v_int64")
+ )
+)
+
+(define-method get_int64
+ (of-object "GValue")
+ (c-name "g_value_get_int64")
+ (return-type "gint64")
+)
+
+(define-method set_uint64
+ (of-object "GValue")
+ (c-name "g_value_set_uint64")
+ (return-type "none")
+ (parameters
+ '("guint64" "v_uint64")
+ )
+)
+
+(define-method get_uint64
+ (of-object "GValue")
+ (c-name "g_value_get_uint64")
+ (return-type "guint64")
+)
+
+(define-method set_float
+ (of-object "GValue")
+ (c-name "g_value_set_float")
+ (return-type "none")
+ (parameters
+ '("gfloat" "v_float")
+ )
+)
+
+(define-method get_float
+ (of-object "GValue")
+ (c-name "g_value_get_float")
+ (return-type "gfloat")
+)
+
+(define-method set_double
+ (of-object "GValue")
+ (c-name "g_value_set_double")
+ (return-type "none")
+ (parameters
+ '("gdouble" "v_double")
+ )
+)
+
+(define-method get_double
+ (of-object "GValue")
+ (c-name "g_value_get_double")
+ (return-type "gdouble")
+)
+
+(define-method set_string
+ (of-object "GValue")
+ (c-name "g_value_set_string")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "v_string")
+ )
+)
+
+(define-method set_static_string
+ (of-object "GValue")
+ (c-name "g_value_set_static_string")
+ (return-type "none")
+ (parameters
+ '("const-gchar*" "v_string")
+ )
+)
+
+(define-method get_string
+ (of-object "GValue")
+ (c-name "g_value_get_string")
+ (return-type "const-gchar*")
+)
+
+(define-method dup_string
+ (of-object "GValue")
+ (c-name "g_value_dup_string")
+ (return-type "gchar*")
+)
+
+(define-method set_pointer
+ (of-object "GValue")
+ (c-name "g_value_set_pointer")
+ (return-type "none")
+ (parameters
+ '("gpointer" "v_pointer")
+ )
+)
+
+(define-method get_pointer
+ (of-object "GValue")
+ (c-name "g_value_get_pointer")
+ (return-type "gpointer")
+)
+
+(define-function g_pointer_type_register_static
+ (c-name "g_pointer_type_register_static")
+ (return-type "GType")
+ (parameters
+ '("const-gchar*" "name")
+ )
+)
+
+(define-function g_strdup_value_contents
+ (c-name "g_strdup_value_contents")
+ (return-type "gchar*")
+ (parameters
+ '("const-GValue*" "value")
+ )
+)
+
+(define-method set_string_take_ownership
+ (of-object "GValue")
+ (c-name "g_value_set_string_take_ownership")
+ (return-type "none")
+ (parameters
+ '("gchar*" "v_string")
+ )
+)
+
+
diff --git a/glib/src/iochannel.ccg b/glib/src/iochannel.ccg
new file mode 100644
index 00000000..9aee28d6
--- /dev/null
+++ b/glib/src/iochannel.ccg
@@ -0,0 +1,540 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/iochannel.h>
+#include <glibmm/utility.h>
+#include <glibmm/main.h>
+#include <glib.h>
+
+
+namespace
+{
+
+// Glib::IOChannel reference counting issues:
+//
+// Normally, you'd expect that the C++ object stays around as long as the
+// C instance does. Also Glib::wrap() usually returns always the same C++
+// wrapper object for a single C instance.
+//
+// Unfortunately it isn't possible to implement these features if we didn't
+// create the underlying GIOChannel. That is, when wrapping existing
+// GIOChannel instances such as returned by e.g. g_io_channel_unix_new() or
+// g_io_channel_new_file(). Neither is there a way to hook up a wrapper
+// object in an existing GIOChannel, nor exists any destroy notification.
+//
+// So that means: If the IOChannel is implemented in C++ -- that is, our
+// GlibmmIOChannel backend is used -- we use the GIOChannel reference
+// counting mechanism. If the IOChannel backend is unknown, then the
+// wrapper instance holds always exactly one reference to the GIOChannel.
+// The wrapper object itself is then managed via the SigC::Object refcounting
+// mechanism. To do that a utility class ForeignIOChannel is introduced to
+// override reference() and unreference().
+
+class ForeignIOChannel : public Glib::IOChannel
+{
+public:
+ ForeignIOChannel(GIOChannel* gobject, bool take_copy)
+ : Glib::IOChannel(gobject, take_copy) {}
+
+ virtual void reference() const;
+ virtual void unreference() const;
+};
+
+void ForeignIOChannel::reference() const
+{
+ SigC::ObjectBase::reference();
+}
+
+void ForeignIOChannel::unreference() const
+{
+ SigC::ObjectBase::unreference();
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+class GlibmmIOChannel
+{
+public:
+ GIOChannel base;
+ Glib::IOChannel* wrapper;
+
+ static const GIOFuncs vfunc_table;
+
+ static GIOStatus io_read(GIOChannel* channel, char* buf, gsize count,
+ gsize* bytes_read, GError** err);
+
+ static GIOStatus io_write(GIOChannel* channel, const char* buf, gsize count,
+ gsize* bytes_written, GError** err);
+
+ static GIOStatus io_seek (GIOChannel* channel, gint64 offset, GSeekType type, GError** err);
+ static GIOStatus io_close(GIOChannel* channel, GError** err);
+
+ static GSource* io_create_watch(GIOChannel* channel, GIOCondition condition);
+ static void io_free(GIOChannel* channel);
+
+ static GIOStatus io_set_flags(GIOChannel* channel, GIOFlags flags, GError** err);
+ static GIOFlags io_get_flags(GIOChannel* channel);
+};
+
+// static
+const GIOFuncs GlibmmIOChannel::vfunc_table =
+{
+ &GlibmmIOChannel::io_read,
+ &GlibmmIOChannel::io_write,
+ &GlibmmIOChannel::io_seek,
+ &GlibmmIOChannel::io_close,
+ &GlibmmIOChannel::io_create_watch,
+ &GlibmmIOChannel::io_free,
+ &GlibmmIOChannel::io_set_flags,
+ &GlibmmIOChannel::io_get_flags,
+};
+
+
+/**** GLib::IOChannel ******************************************************/
+
+/* Construct a custom C++-implemented IOChannel. GlibmmIOChannel is an
+ * extended GIOChannel struct which allows us to hook up a pointer to this
+ * persistent wrapper instance.
+ */
+IOChannel::IOChannel()
+:
+ gobject_ (static_cast<GIOChannel*>(g_malloc(sizeof(GlibmmIOChannel))))
+{
+ g_io_channel_init(gobject_);
+ gobject_->funcs = const_cast<GIOFuncs*>(&GlibmmIOChannel::vfunc_table);
+
+ reinterpret_cast<GlibmmIOChannel*>(gobject_)->wrapper = this;
+}
+
+/* Construct an IOChannel wrapper for an already created GIOChannel.
+ * See the comment at the top of this file for an explanation of the
+ * problems with this approach.
+ */
+IOChannel::IOChannel(GIOChannel* gobject, bool take_copy)
+:
+ gobject_ (gobject)
+{
+ // This ctor should never be called for GlibmmIOChannel instances.
+ g_assert(gobject != 0);
+ g_assert(gobject->funcs != &GlibmmIOChannel::vfunc_table);
+
+ if(take_copy)
+ g_io_channel_ref(gobject_);
+}
+
+IOChannel::~IOChannel()
+{
+ if(gobject_)
+ {
+ // Check whether this IOChannel is implemented in C++, i.e. whether it
+ // uses our GlibmmIOChannel forwarding backend. Normally, this will never
+ // be true because the wrapper should only be deleted in the io_free()
+ // callback, which clears gobject_ before deleting. But in case the ctor
+ // of a derived class threw an exception the GIOChannel must be destroyed
+ // prematurely.
+ //
+ if(gobject_->funcs == &GlibmmIOChannel::vfunc_table)
+ {
+ // Disconnect the wrapper object so that it won't be deleted twice.
+ reinterpret_cast<GlibmmIOChannel*>(gobject_)->wrapper = 0;
+ }
+
+ GIOChannel *const tmp_gobject = gobject_;
+ gobject_ = 0;
+
+ g_io_channel_unref(tmp_gobject);
+ }
+}
+
+Glib::RefPtr<IOChannel> IOChannel::create_from_file(const std::string& filename, const std::string& mode)
+{
+ GError* error = 0;
+ GIOChannel *const channel = g_io_channel_new_file(filename.c_str(), mode.c_str(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ return Glib::wrap(channel, false);
+}
+
+Glib::RefPtr<IOChannel> IOChannel::create_from_fd(int fd)
+{
+ return Glib::wrap(g_io_channel_unix_new(fd), false);
+}
+
+#ifdef G_OS_WIN32
+
+Glib::RefPtr<IOChannel> IOChannel::create_from_win32_fd(int fd)
+{
+ return Glib::wrap(g_io_channel_win32_new_fd(fd), false);
+}
+
+Glib::RefPtr<IOChannel> IOChannel::create_from_win32_socket(int socket)
+{
+ return Glib::wrap(g_io_channel_win32_new_socket(socket), false);
+}
+
+#endif /* G_OS_WIN32 */
+
+IOStatus IOChannel::write(const Glib::ustring& str)
+{
+ gsize bytes_written = 0;
+ return write(str.data(), str.bytes(), bytes_written);
+}
+
+IOStatus IOChannel::read_line(Glib::ustring& line)
+{
+ Glib::ScopedPtr<char> buf;
+ GError* error = 0;
+ gsize bytes = 0;
+
+ const GIOStatus status = g_io_channel_read_line(gobj(), buf.addr(), &bytes, 0, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ if(buf.get())
+ line.assign(buf.get(), buf.get() + bytes);
+ else
+ line.erase();
+
+ return (IOStatus) status;
+}
+
+IOStatus IOChannel::read_to_end(Glib::ustring& str)
+{
+ Glib::ScopedPtr<char> buf;
+ GError* error = 0;
+ gsize bytes = 0;
+
+ const GIOStatus status = g_io_channel_read_to_end(gobj(), buf.addr(), &bytes, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ if(buf.get())
+ str.assign(buf.get(), buf.get() + bytes);
+ else
+ str.erase();
+
+ return (IOStatus) status;
+}
+
+IOStatus IOChannel::read(Glib::ustring& str, gsize count)
+{
+ Glib::ScopedPtr<char> buf (g_new(char, count));
+ GError* error = 0;
+ gsize bytes = 0;
+
+ const GIOStatus status = g_io_channel_read_chars(gobj(), buf.get(), count, &bytes, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ if(buf.get())
+ str.assign(buf.get(), buf.get() + bytes);
+ else
+ str.erase();
+
+ return (IOStatus) status;
+}
+
+IOStatus IOChannel::set_encoding(const std::string& encoding)
+{
+ GError* error = 0;
+
+ const GIOStatus status = g_io_channel_set_encoding(
+ gobj(), (encoding.empty()) ? 0 : encoding.c_str(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ return (IOStatus) status;
+}
+
+std::string IOChannel::get_encoding() const
+{
+ const char *const encoding = g_io_channel_get_encoding(gobject_);
+ return (encoding) ? std::string(encoding) : std::string();
+}
+
+void IOChannel::set_line_term(const std::string& term)
+{
+ if(term.empty())
+ g_io_channel_set_line_term(gobj(), 0, 0);
+ else
+ g_io_channel_set_line_term(gobj(), term.data(), term.size());
+}
+
+std::string IOChannel::get_line_term() const
+{
+ int len = 0;
+ const char *const term = g_io_channel_get_line_term(gobject_, &len);
+
+ return (term) ? std::string(term, len) : std::string();
+}
+
+Glib::RefPtr<IOSource> IOChannel::create_watch(IOCondition condition)
+{
+ // The corresponding unreference() takes place in the dtor
+ // of the Glib::RefPtr<IOChannel> object below.
+ reference();
+ return IOSource::create(Glib::RefPtr<IOChannel>(this), condition);
+}
+
+IOStatus IOChannel::read_vfunc(char*, gsize, gsize&)
+{
+ g_assert_not_reached();
+ return IO_STATUS_ERROR;
+}
+
+IOStatus IOChannel::write_vfunc(const char*, gsize, gsize&)
+{
+ g_assert_not_reached();
+ return IO_STATUS_ERROR;
+}
+
+IOStatus IOChannel::seek_vfunc(gint64, SeekType)
+{
+ g_assert_not_reached();
+ return IO_STATUS_ERROR;
+}
+
+IOStatus IOChannel::close_vfunc()
+{
+ g_assert_not_reached();
+ return IO_STATUS_ERROR;
+}
+
+Glib::RefPtr<Glib::Source> IOChannel::create_watch_vfunc(IOCondition)
+{
+ g_assert_not_reached();
+ return Glib::RefPtr<Glib::Source>();
+}
+
+IOStatus IOChannel::set_flags_vfunc(IOFlags)
+{
+ g_assert_not_reached();
+ return IO_STATUS_ERROR;
+}
+
+IOFlags IOChannel::get_flags_vfunc()
+{
+ g_assert_not_reached();
+ return IOFlags(0);
+}
+
+void IOChannel::reference() const
+{
+ g_io_channel_ref(gobject_);
+}
+
+void IOChannel::unreference() const
+{
+ g_io_channel_unref(gobject_);
+}
+
+Glib::RefPtr<IOChannel> wrap(GIOChannel* gobject, bool take_copy)
+{
+ IOChannel* cpp_object = 0;
+
+ if(gobject)
+ {
+ if(gobject->funcs == &GlibmmIOChannel::vfunc_table)
+ {
+ cpp_object = reinterpret_cast<GlibmmIOChannel*>(gobject)->wrapper;
+
+ if(take_copy && cpp_object)
+ cpp_object->reference();
+ }
+ else
+ {
+ cpp_object = SigC::manage(new ForeignIOChannel(gobject, take_copy));
+ cpp_object->reference(); // the SigC::Object refcount is initially 0
+ }
+ }
+
+ return Glib::RefPtr<IOChannel>(cpp_object);
+}
+
+
+/**** Glib::GlibmmIOChannel ************************************************/
+
+// static
+GIOStatus GlibmmIOChannel::io_read(GIOChannel* channel, char* buf, gsize count,
+ gsize* bytes_read, GError** err)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ return (GIOStatus) wrapper->read_vfunc(buf, count, *bytes_read);
+ }
+ catch(Glib::Error& error)
+ {
+ error.propagate(err);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return G_IO_STATUS_ERROR;
+}
+
+// static
+GIOStatus GlibmmIOChannel::io_write(GIOChannel* channel, const char* buf, gsize count,
+ gsize* bytes_written, GError** err)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ return (GIOStatus) wrapper->write_vfunc(buf, count, *bytes_written);
+ }
+ catch(Glib::Error& error)
+ {
+ error.propagate(err);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return G_IO_STATUS_ERROR;
+}
+
+// static
+GIOStatus GlibmmIOChannel::io_seek(GIOChannel* channel, gint64 offset, GSeekType type, GError** err)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ return (GIOStatus) wrapper->seek_vfunc(offset, (SeekType) type);
+ }
+ catch(Glib::Error& error)
+ {
+ error.propagate(err);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return G_IO_STATUS_ERROR;
+}
+
+// static
+GIOStatus GlibmmIOChannel::io_close(GIOChannel* channel, GError** err)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ return (GIOStatus) wrapper->close_vfunc();
+ }
+ catch(Glib::Error& error)
+ {
+ error.propagate(err);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return G_IO_STATUS_ERROR;
+}
+
+// static
+GSource* GlibmmIOChannel::io_create_watch(GIOChannel* channel, GIOCondition condition)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ const Glib::RefPtr<Source> source = wrapper->create_watch_vfunc((IOCondition) condition);
+ return (source) ? source->gobj_copy() : 0;
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return 0;
+}
+
+// static
+void GlibmmIOChannel::io_free(GIOChannel* channel)
+{
+ if(IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper)
+ {
+ wrapper->gobject_ = 0;
+ delete wrapper;
+ }
+
+ g_free(channel);
+}
+
+// static
+GIOStatus GlibmmIOChannel::io_set_flags(GIOChannel* channel, GIOFlags flags, GError** err)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ return (GIOStatus) wrapper->set_flags_vfunc((IOFlags) flags);
+ }
+ catch(Glib::Error& error)
+ {
+ error.propagate(err);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return G_IO_STATUS_ERROR;
+}
+
+// static
+GIOFlags GlibmmIOChannel::io_get_flags(GIOChannel* channel)
+{
+ IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+
+ try
+ {
+ return (GIOFlags) wrapper->get_flags_vfunc();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return GIOFlags(0);
+}
+
+} // namespace Glib
+
diff --git a/glib/src/iochannel.hg b/glib/src/iochannel.hg
new file mode 100644
index 00000000..ab9f4b38
--- /dev/null
+++ b/glib/src/iochannel.hg
@@ -0,0 +1,452 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glibmm/error.h>
+#include <glibmm/main.h>
+#include <glibmm/refptr.h>
+#include <glibmm/ustring.h>
+#include <glib/gtypes.h>
+
+#include <string>
+#include <glibmmconfig.h>
+
+GTKMM_USING_STD(string)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GIOChannel GIOChannel; }
+#endif
+
+
+namespace Glib
+{
+
+class Source;
+class IOSource;
+
+_WRAP_ENUM(SeekType, GSeekType, NO_GTYPE, s#^SEEK_#SEEK_TYPE_#)
+_WRAP_ENUM(IOStatus, GIOStatus, NO_GTYPE)
+_WRAP_ENUM(IOFlags, GIOFlags, NO_GTYPE)
+
+/** Exception class for IOChannel errors.
+ */
+_WRAP_GERROR(IOChannelError, GIOChannelError, G_IO_CHANNEL_ERROR, NO_GTYPE,
+ s#^INVAL$#INVALID_ARGUMENT#,
+ s#^ISDIR$#IS_DIRECTORY#,
+ s#^PIPE$#BROKEN_PIPE#,
+ s#^NOSPC$#NO_SPACE_LEFT#,
+ s#^NXIO$#NO_SUCH_DEVICE#,
+ s#^ACCES$#ACCESS_DENIED#,
+ s#^FBIG$#FILE_TOO_BIG#,
+ s#^IO$#IO_ERROR#,
+ s#^OVERFLOW$#OVERFLOWN#)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class GlibmmIOChannel;
+#endif
+
+/** IOChannel aims to provide portable I/O support for files, pipes
+ * and sockets, and to integrate them with the GLib main event loop.
+ *
+ * Note that IOChannels implement an automatic implicit character set
+ * conversion to the data stream, and usually will not pass by default
+ * binary data unchanged. To set the encoding of the channel, use e.g.
+ * set_encoding("ISO-8859-15"). To set the channel to no encoding, use
+ * set_encoding() without any arguments.
+ *
+ * You can create an IOChannel with one of the static create methods, or
+ * implement one yourself, in which case you have to 1)&nbsp;override all
+ * _vfunc() members. 2)&nbsp;set the GIOChannel flags in your constructor.
+ *
+ * @note This feature of being able to implement a custom Glib::IOChannel is
+ * deprecated in glibmm&nbsp;2.2. The vfunc interface has not yet stabilized
+ * enough to allow that -- the C++ wrapper went in by pure accident. Besides,
+ * it isn't terribly useful either. Thus please refrain from overriding any
+ * IOChannel vfuncs.
+ */
+class IOChannel : public SigC::Object
+{
+ _CLASS_GENERIC(IOChannel, GIOChannel)
+
+ dnl // We can't support get_fd() properly because it is impossible
+ dnl // to detect the specific GIOChannel type at runtime.
+ _IGNORE(g_io_channel_unix_get_fd, g_io_channel_win32_get_fd)
+
+ dnl // deprecated or internal
+ _IGNORE(g_io_channel_seek, g_io_channel_close, g_io_channel_read,
+ g_io_channel_write, g_io_channel_win32_make_pollfd)
+
+public:
+ virtual ~IOChannel();
+
+ /** Open a file @a filename as an I/O channel using mode @a mode.
+ * This channel will be closed when the last reference to it is dropped,
+ * so there is no need to call close() (though doing so will not cause
+ * problems, as long as no attempt is made to access the channel after
+ * it is closed).
+ * @param filename The name of the file to open.
+ * @param mode One of <tt>"r"</tt>, <tt>"w"</tt>, <tt>"a"</tt>,
+ * <tt>"r+"</tt>, <tt>"w+"</tt>, <tt>"a+"</tt>. These have the
+ * same meaning as in <tt>fopen()</tt>.
+ * @return An IOChannel for the opened file.
+ * @throw Glib::FileError
+ */
+ static Glib::RefPtr<IOChannel> create_from_file(const std::string& filename, const std::string& mode);
+ _IGNORE(g_io_channel_new_file)
+
+ /** Creates an I/O channel from a file descriptor.
+ * On Unix, IOChannels created with this function work for any file
+ * descriptor or socket.
+ *
+ * On Win32, this can be used either for files opened with the MSVCRT (the
+ * Microsoft run-time C library) <tt>_open()</tt> or <tt>_pipe()</tt>,
+ * including file descriptors 0, 1 and 2 (corresponding to <tt>stdin</tt>,
+ * <tt>stdout</tt> and <tt>stderr</tt>), or for Winsock <tt>SOCKET</tt>s. If
+ * the parameter is a legal file descriptor, it is assumed to be such,
+ * otherwise it should be a <tt>SOCKET</tt>. This relies on <tt>SOCKET</tt>s
+ * and file descriptors not overlapping. If you want to be certain, call
+ * either create_from_win32_fd() or create_from_win32_socket() instead as
+ * appropriate.
+ *
+ * The term file descriptor as used in the context of Win32 refers to the
+ * emulated Unix-like file descriptors MSVCRT provides. The native
+ * corresponding concept is file <tt>HANDLE</tt>. There isn't as of yet
+ * a way to get IOChannels for Win32 file <tt>HANDLE</tt>s.
+ */
+ static Glib::RefPtr<IOChannel> create_from_fd(int fd);
+ _IGNORE(g_io_channel_unix_new)
+
+/* defined(DOXYGEN_SHOULD_SKIP_THIS) actually does the opposite of what it looks like... */
+#if defined(G_OS_WIN32) || defined(DOXYGEN_SHOULD_SKIP_THIS)
+
+ /** Create an I/O channel for C runtime (emulated Unix-like) file descriptors.
+ * After calling add_watch() on a I/O channel returned by this function, you
+ * shouldn't call read() on the file descriptor. This is because adding
+ * polling for a file descriptor is implemented on Win32 by starting a thread
+ * that sits blocked in a <tt>%read()</tt> from the file descriptor most of
+ * the time. All reads from the file descriptor should be done by this
+ * internal GLib thread. Your code should call only IOChannel::read().
+ */
+ static Glib::RefPtr<IOChannel> create_from_win32_fd(int fd);
+ _IGNORE(g_io_channel_win32_new_fd)
+
+ /** Create an I/O channel for a winsock socket. The parameter should be a
+ * <tt>SOCKET</tt>. Contrary to I/O channels for file descriptors (on Win32),
+ * you can use normal <tt>recv()</tt> or <tt>recvfrom()</tt> on sockets even
+ * if GLib is polling them.
+ */
+ static Glib::RefPtr<IOChannel> create_from_win32_socket(int socket);
+ _IGNORE(g_io_channel_win32_new_socket)
+
+#endif /* defined(G_OS_WIN32) || defined(DOXYGEN_SHOULD_SKIP_THIS) */
+
+ /** Read a single UCS-4 character.
+ * @retval unichar The Unicode character.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ _WRAP_METHOD(IOStatus read(gunichar& unichar), g_io_channel_read_unichar, errthrow)
+
+ /** Read a character sequence into memory.
+ * @param buf A buffer to read data into.
+ * @param count The size of the buffer in bytes. Note that the buffer may
+ * not be complelely filled even if there is data in the buffer if the
+ * remaining data is not a complete character.
+ * @retval bytes_read The number of bytes read. This may be zero even on
+ * success if @a count < 6 and the channel's encoding is not <tt>""</tt>.
+ * This indicates that the next UTF-8 character is too wide for the buffer.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ _WRAP_METHOD(IOStatus read(char* buf, gsize count, gsize& bytes_read),
+ g_io_channel_read_chars, errthrow)
+
+ /** Read a maximum of @a count bytes into @a str.
+ * @param count The maximum number of bytes to read.
+ * @retval str The characters that have been read.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ IOStatus read(Glib::ustring& str, gsize count);
+
+ /** Read a whole line.
+ * Reads until the line separator is found, which is included
+ * in the result string.
+ * @retval line The line that was read.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ IOStatus read_line(Glib::ustring& line);
+ _IGNORE(g_io_channel_read_line, g_io_channel_read_line_string)
+
+ /** Reads all the remaining data from the file.
+ * @retval str The resulting string.
+ * @return Glib::IO_STATUS_NORMAL on success. This function never
+ * returns Glib::IO_STATUS_EOF.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ IOStatus read_to_end(Glib::ustring& str);
+ _IGNORE(g_io_channel_read_to_end)
+
+ /** Write a string to the I/O channel.
+ * Note that this method does not return the number of characters written.
+ * If the channel is blocking and the returned value is
+ * Glib::IO_STATUS_NORMAL, the whole string was written.
+ * @param str the string to write.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ IOStatus write(const Glib::ustring& str);
+
+ /** Write a memory area of @a count bytes to the I/O channel.
+ * @param buf The start of the memory area.
+ * @param count The number of bytes to write.
+ * @retval bytes_written The number of bytes written to the channel.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ _WRAP_METHOD(IOStatus write(const char* buf, gssize count, gsize& bytes_written),
+ g_io_channel_write_chars, errthrow)
+
+ /** Write a single UCS-4 character to the I/O channel.
+ * @param unichar The character to write.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ _WRAP_METHOD(IOStatus write(gunichar unichar), g_io_channel_write_unichar, errthrow)
+
+ /** Seek the I/O channel to a specific position.
+ * @param offset The offset in bytes from the position specified by @a type.
+ * @param type A SeekType. The type Glib::SEEK_TYPE_CUR is only allowed in
+ * those cases where a call to set_encoding() is allowed. See the
+ * documentation for set_encoding() for details.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ _WRAP_METHOD(IOStatus seek(gint64 offset, SeekType type = SEEK_TYPE_SET),
+ g_io_channel_seek_position, errthrow)
+
+ /** Flush the buffers of the I/O channel.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ * @throw Glib::ConvertError
+ */
+ _WRAP_METHOD(IOStatus flush(), g_io_channel_flush, errthrow)
+
+ /** Close the I/O channel.
+ * Any pending data to be written will be flushed if @a flush is <tt>true</tt>.
+ * The channel will not be freed until the last reference is dropped.
+ * Accessing the channel after closing it is considered an error.
+ * @param flush Whether to flush() pending data before closing the channel.
+ * @return The status of the operation.
+ * @throw Glib::IOChannelError
+ */
+ _WRAP_METHOD(IOStatus close(bool flush = true), g_io_channel_shutdown, errthrow)
+
+ /** Get the IOChannel internal buffer size.
+ * @return The buffer size.
+ */
+ _WRAP_METHOD(gsize get_buffer_size() const, g_io_channel_get_buffer_size)
+
+ /** Set the internal IOChannel buffer size.
+ * @param size The buffer size the IOChannel should use.
+ */
+ _WRAP_METHOD(void set_buffer_size(gsize size), g_io_channel_set_buffer_size)
+
+ /** Get the current flags for a IOChannel, including read-only
+ * flags such as Glib::IO_FLAG_IS_READABLE.
+ *
+ * The values of the flags Glib::IO_FLAG_IS_READABLE and
+ * Glib::IO_FLAG_IS_WRITEABLE are cached for internal use by the channel when
+ * it is created. If they should change at some later point (e.g. partial
+ * shutdown of a socket with the UNIX <tt>shutdown()</tt> function), the user
+ * should immediately call get_flags() to update the internal values of these
+ * flags.
+ * @return Bitwise combination of the flags set on the channel.
+ */
+ _WRAP_METHOD(IOFlags get_flags() const, g_io_channel_get_flags)
+
+ /** Set flags on the IOChannel.
+ * @param flags Bitwise combination of the flags to set.
+ * @return The operation result code.
+ * @throw Glib::IOChannelError
+ */
+ _WRAP_METHOD(IOStatus set_flags(IOFlags flags), g_io_channel_set_flags, errthrow)
+
+ /** Set the buffering status of the I/O channel.
+ * The buffering state can only be set if the channel's encoding is
+ * <tt>""</tt>. For any other encoding, the channel must be buffered.
+ *
+ * A buffered channel can only be set unbuffered if the channel's internal
+ * buffers have been flushed. Newly created channels or channels which have
+ * returned Glib::IO_STATUS_EOF not require such a flush. For write-only
+ * channels, a call to flush() is sufficient. For all other channels, the
+ * buffers may be flushed by a call to seek(). This includes the possibility
+ * of seeking with seek type Glib::SEEK_TYPE_CUR and an offset of zero. Note
+ * that this means that socket-based channels cannot be set unbuffered once
+ * they have had data read from them.
+ *
+ * The default state of the channel is buffered.
+ *
+ * @param buffered Whether to set the channel buffered or unbuffered.
+ */
+ _WRAP_METHOD(void set_buffered(bool buffered), g_io_channel_set_buffered)
+
+ /** Get the buffering status of the I/O channel.
+ * @return The buffering status of the channel.
+ */
+ _WRAP_METHOD(bool get_buffered() const, g_io_channel_get_buffered)
+
+ /** Returns an IOCondition depending on whether there is data to be
+ * read/space to write data in the internal buffers in the I/O channel.
+ * Only the flags Glib::IO_IN and Glib::IO_OUT may be set.
+ * @return Bitwise combination of Glib::IOCondition flags.
+ */
+ _WRAP_METHOD(IOCondition get_buffer_condition() const, g_io_channel_get_buffer_condition)
+
+ /** Returns whether the file/socket/whatever associated with the I/O channel
+ * will be closed when the channel receives its final unref and is destroyed.
+ * The default value of this is <tt>true</tt> for channels created by
+ * create_from_file(), and <tt>false</tt> for all other channels.
+ * @return Whether the channel will be closed on the final unref of the
+ * IOChannel object.
+ */
+ _WRAP_METHOD(bool get_close_on_unref() const, g_io_channel_get_close_on_unref)
+
+ /** Setting this flag to <tt>true</tt> for a channel you have already closed
+ * can cause problems.
+ * @param do_close Whether to close the channel on the final unref of the
+ * IOChannel object. The default value of this is <tt>true</tt> for channels
+ * created by create_from_file(), and <tt>false</tt> for all other channels.
+ */
+ _WRAP_METHOD(void set_close_on_unref(bool do_close), g_io_channel_set_close_on_unref)
+
+ /** Sets the encoding for the input/output of the channel.
+ * The internal encoding is always UTF-8. The default encoding for the
+ * external file is UTF-8. The encoding <tt>""</tt> is safe to use with
+ * binary data.
+ *
+ * The encoding can only be set if one of the following conditions
+ * is true:
+ *
+ * -# The channel was just created, and has not been written to or read from
+ * yet.
+ * -# The channel is write-only.
+ * -# The channel is a file, and the file pointer was just repositioned by a
+ * call to seek_position(). (This flushes all the internal buffers.)
+ * -# The current encoding is <tt>""</tt> or UTF-8.
+ * -# One of the read methods has just returned Glib::IO_STATUS_EOF (or, in
+ * the case of read_to_end(), Glib::IO_STATUS_NORMAL).
+ * -# The read() method has returned Glib::IO_STATUS_AGAIN or thrown
+ * a Glib::Error exception. This may be useful in the case of
+ * ConvertError::ILLEGAL_SEQUENCE. Returning one of these statuses
+ * from read_line() or read_to_end() does <em>not</em> guarantee that
+ * the encoding can be changed.
+ *
+ * Channels which do not meet one of the above conditions cannot call
+ * seek_position() with a seek type of Glib::SEEK_TYPE_CUR and, if they
+ * are "seekable", cannot call write() after calling one of the API
+ * "read" methods.
+ *
+ * @param encoding The encoding name, or <tt>""</tt> for binary.
+ * @return Glib::IO_STATUS_NORMAL if the encoding was successfully set.
+ * @throw Glib::IOChannelError
+ */
+ IOStatus set_encoding(const std::string& encoding = std::string());
+ _IGNORE(g_io_channel_set_encoding)
+
+ /** Get the encoding of the I/O channel.
+ * @return The current encoding of the channel.
+ */
+ std::string get_encoding() const;
+ _IGNORE(g_io_channel_get_encoding)
+
+ void set_line_term(const std::string& term = std::string());
+ _IGNORE(g_io_channel_set_line_term)
+
+ std::string get_line_term() const;
+ _IGNORE(g_io_channel_get_line_term)
+
+ /** Creates an IOSource object.
+ * Create a slot from a function to be called when condition is met
+ * for the channel with SigC::slot() and pass it into the connect()
+ * function of the returned IOSource object. Polling of the channel
+ * will start when you attach a MainContext object to the returned
+ * IOSource object using its attach() function.
+ *
+ * Glib::signal_io().connect() is a simpler interface to the same
+ * functionality, for the case where you want to add the source to the
+ * default main context.
+ * @param condition The condition to watch for.
+ * @return An IOSource object that can be polled from a MainContext's event loop.
+ */
+ Glib::RefPtr<IOSource> create_watch(IOCondition condition);
+ _IGNORE(g_io_channel_create_watch)
+
+ virtual void reference() const;
+ virtual void unreference() const;
+ _IGNORE(g_io_channel_ref, g_io_channel_unref)
+
+ GIOChannel* gobj() { return gobject_; }
+ const GIOChannel* gobj() const { return gobject_; }
+
+protected:
+ GIOChannel* gobject_;
+
+ /** Constructor that should be used by derived classes.
+ * Use this constructor if you want to inherit from IOChannel.
+ * It will set up a GIOChannel that will call the vfuncs of your
+ * class even if it is being used from C code, and it will keep
+ * a reference to the C++ code while the GIOChannel exists.
+ */
+ IOChannel();
+ _IGNORE(g_io_channel_init)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ IOChannel(GIOChannel* gobject, bool take_copy);
+#endif
+
+ virtual IOStatus read_vfunc(char* buf, gsize count, gsize& bytes_read);
+ virtual IOStatus write_vfunc(const char* buf, gsize count, gsize& bytes_written);
+ virtual IOStatus seek_vfunc(gint64 offset, SeekType type);
+ virtual IOStatus close_vfunc();
+ virtual IOStatus set_flags_vfunc(IOFlags flags);
+ virtual IOFlags get_flags_vfunc();
+ virtual Glib::RefPtr<Glib::Source> create_watch_vfunc(IOCondition cond);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ friend class Glib::GlibmmIOChannel;
+#endif
+};
+
+Glib::RefPtr<IOChannel> wrap(GIOChannel* gobject, bool take_copy = false);
+
+} // namespace Glib
+
diff --git a/glib/src/markup.ccg b/glib/src/markup.ccg
new file mode 100644
index 00000000..2b61a358
--- /dev/null
+++ b/glib/src/markup.ccg
@@ -0,0 +1,318 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/markup.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/utility.h>
+#include <glib.h>
+
+
+namespace Glib
+{
+
+namespace Markup
+{
+
+Glib::ustring escape_text(const Glib::ustring& text)
+{
+ const Glib::ScopedPtr<char> buf (g_markup_escape_text(text.data(), text.bytes()));
+ return Glib::ustring(buf.get());
+}
+
+
+/**** Glib::Markup::AttributeKeyLess ***************************************/
+
+bool AttributeKeyLess::operator()(const Glib::ustring& lhs, const Glib::ustring& rhs) const
+{
+ return (lhs.raw() < rhs.raw());
+}
+
+
+/**** Glib::Markup::ParserCallbacks ****************************************/
+
+class ParserCallbacks
+{
+public:
+ static const GMarkupParser vfunc_table;
+
+ static void start_element(GMarkupParseContext* context,
+ const char* element_name,
+ const char** attribute_names,
+ const char** attribute_values,
+ void* user_data,
+ GError** error);
+
+ static void end_element(GMarkupParseContext* context,
+ const char* element_name,
+ void* user_data,
+ GError** error);
+
+ static void text(GMarkupParseContext* context,
+ const char* text,
+ gsize text_len,
+ void* user_data,
+ GError** error);
+
+ static void passthrough(GMarkupParseContext* context,
+ const char* passthrough_text,
+ gsize text_len,
+ void* user_data,
+ GError** error);
+
+ static void error(GMarkupParseContext* context,
+ GError* error,
+ void* user_data);
+};
+
+
+const GMarkupParser ParserCallbacks::vfunc_table =
+{
+ &ParserCallbacks::start_element,
+ &ParserCallbacks::end_element,
+ &ParserCallbacks::text,
+ &ParserCallbacks::passthrough,
+ &ParserCallbacks::error,
+};
+
+void ParserCallbacks::start_element(GMarkupParseContext* context,
+ const char* element_name,
+ const char** attribute_names,
+ const char** attribute_values,
+ void* user_data,
+ GError** error)
+{
+ ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
+ g_return_if_fail(context == cpp_context.gobj());
+
+ try
+ {
+ Parser::AttributeMap attributes;
+
+ if(attribute_names && attribute_values)
+ {
+ const char *const * pname = attribute_names;
+ const char *const * pvalue = attribute_values;
+
+ for(; *pname && *pvalue; ++pname, ++pvalue)
+ attributes.insert(Parser::AttributeMap::value_type(*pname, *pvalue));
+
+ g_return_if_fail(*pname == 0 && *pvalue == 0);
+ }
+
+ cpp_context.get_parser()->on_start_element(cpp_context, element_name, attributes);
+ }
+ catch(MarkupError& err)
+ {
+ err.propagate(error);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+void ParserCallbacks::end_element(GMarkupParseContext* context,
+ const char* element_name,
+ void* user_data,
+ GError** error)
+{
+ ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
+ g_return_if_fail(context == cpp_context.gobj());
+
+ try
+ {
+ cpp_context.get_parser()->on_end_element(cpp_context, element_name);
+ }
+ catch(MarkupError& err)
+ {
+ err.propagate(error);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+void ParserCallbacks::text(GMarkupParseContext* context,
+ const char* text,
+ gsize text_len,
+ void* user_data,
+ GError** error)
+{
+ ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
+ g_return_if_fail(context == cpp_context.gobj());
+
+ try
+ {
+ cpp_context.get_parser()->on_text(cpp_context, Glib::ustring(text, text + text_len));
+ }
+ catch(MarkupError& err)
+ {
+ err.propagate(error);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+void ParserCallbacks::passthrough(GMarkupParseContext* context,
+ const char* passthrough_text,
+ gsize text_len,
+ void* user_data,
+ GError** error)
+{
+ ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
+ g_return_if_fail(context == cpp_context.gobj());
+
+ try
+ {
+ cpp_context.get_parser()->on_passthrough(
+ cpp_context, Glib::ustring(passthrough_text, passthrough_text + text_len));
+ }
+ catch(MarkupError& err)
+ {
+ err.propagate(error);
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+void ParserCallbacks::error(GMarkupParseContext* context,
+ GError* error,
+ void* user_data)
+{
+ ParseContext& cpp_context = *static_cast<ParseContext*>(user_data);
+
+ g_return_if_fail(context == cpp_context.gobj());
+ g_return_if_fail(error->domain == G_MARKUP_ERROR);
+
+ try
+ {
+ cpp_context.get_parser()->on_error(cpp_context, MarkupError(g_error_copy(error)));
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+
+/**** Glib::Markup::Parser *************************************************/
+
+Parser::Parser()
+{}
+
+Parser::~Parser()
+{}
+
+void Parser::on_start_element(ParseContext&, const Glib::ustring&, const Parser::AttributeMap&)
+{}
+
+void Parser::on_end_element(ParseContext&, const Glib::ustring&)
+{}
+
+void Parser::on_text(ParseContext&, const Glib::ustring&)
+{}
+
+void Parser::on_passthrough(ParseContext&, const Glib::ustring&)
+{}
+
+void Parser::on_error(ParseContext&, const MarkupError&)
+{}
+
+
+/**** Glib::Markup::ParseContext *******************************************/
+
+ParseContext::ParseContext(Parser& parser, ParseFlags flags)
+:
+ parser_ (&parser),
+ gobject_ (g_markup_parse_context_new(&ParserCallbacks::vfunc_table, (GMarkupParseFlags) flags,
+ this, &ParseContext::destroy_notify_callback))
+{}
+
+ParseContext::~ParseContext()
+{
+ parser_ = 0;
+ g_markup_parse_context_free(gobject_);
+}
+
+void ParseContext::parse(const Glib::ustring& text)
+{
+ GError* error = 0;
+ g_markup_parse_context_parse(gobject_, text.data(), text.bytes(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void ParseContext::parse(const char* text_begin, const char* text_end)
+{
+ GError* error = 0;
+ g_markup_parse_context_parse(gobject_, text_begin, text_end - text_begin, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void ParseContext::end_parse()
+{
+ GError* error = 0;
+ g_markup_parse_context_end_parse(gobject_, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+Glib::ustring ParseContext::get_element() const
+{
+ const char *const element_name = g_markup_parse_context_get_element(gobject_);
+ return (element_name) ? Glib::ustring(element_name) : Glib::ustring();
+}
+
+int ParseContext::get_line_number() const
+{
+ int line_number = 0;
+ g_markup_parse_context_get_position(gobject_, &line_number, 0);
+ return line_number;
+}
+
+int ParseContext::get_char_number() const
+{
+ int char_number = 0;
+ g_markup_parse_context_get_position(gobject_, 0, &char_number);
+ return char_number;
+}
+
+// static
+void ParseContext::destroy_notify_callback(void* data)
+{
+ ParseContext *const self = static_cast<ParseContext*>(data);
+
+ // Detect premature destruction.
+ g_return_if_fail(self->parser_ == 0);
+}
+
+} // namespace Markup
+
+} // namespace Glib
+
diff --git a/glib/src/markup.hg b/glib/src/markup.hg
new file mode 100644
index 00000000..911602c9
--- /dev/null
+++ b/glib/src/markup.hg
@@ -0,0 +1,346 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glibmm/error.h>
+#include <sigc++/sigc++.h>
+
+#include <map>
+#include <glibmmconfig.h>
+
+GTKMM_USING_STD(map)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GMarkupParseContext GMarkupParseContext; }
+#endif
+
+
+namespace Glib
+{
+
+/** @defgroup Markup Simple XML Subset Parser
+ *
+ * The Glib::Markup parser is intended to parse a simple markup format that's a
+ * subset of XML. This is a small, efficient, easy-to-use parser. It should not
+ * be used if you expect to interoperate with other applications generating
+ * full-scale XML. However, it's very useful for application data files, config
+ * files, etc. where you know your application will be the only one writing the
+ * file. Full-scale XML parsers should be able to parse the subset used by
+ * Glib::Markup parser, so you can easily migrate to full-scale XML at a later
+ * time if the need arises.
+ *
+ * Glib::Markup is not guaranteed to signal an error on all invalid XML;
+ * the parser may accept documents that an XML parser would not. However,
+ * invalid XML documents are not considered valid Glib::Markup documents.
+ *
+ * @par Simplifications to XML include:
+ *
+ * - Only UTF-8 encoding is allowed.
+ * - No user-defined entities.
+ * - Processing instructions, comments and the doctype declaration are "passed
+ * through" but are not interpreted in any way.
+ * - No DTD or validation.
+ *
+ * @par The markup format does support:
+ *
+ * - Elements
+ * - Attributes
+ * - 5 standard entities: <tt>\&amp; \&lt; \&gt; \&quot; \&apos;</tt>
+ * - Character references
+ * - Sections marked as <tt>CDATA</tt>
+ *
+ * @{
+ */
+
+/** %Exception class for markup parsing errors.
+ */
+_WRAP_GERROR(MarkupError, GMarkupError, G_MARKUP_ERROR, NO_GTYPE)
+
+/*! @var MarkupError::Code MarkupError::BAD_UTF8
+ * Text being parsed was not valid UTF-8.
+ */
+/*! @var MarkupError::Code MarkupError::EMPTY
+ * Document contained nothing, or only whitespace.
+ */
+/*! @var MarkupError::Code MarkupError::PARSE
+ * Document was ill-formed.
+ */
+/*! @var MarkupError::Code MarkupError::UNKNOWN_ELEMENT
+ * This error should be set by Glib::Markup::Parser virtual methods;
+ * element wasn't known.
+ */
+/*! @var MarkupError::Code MarkupError::UNKNOWN_ATTRIBUTE
+ * This error should be set by Glib::Markup::Parser virtual methods;
+ * attribute wasn't known.
+ */
+/*! @var MarkupError::Code MarkupError::INVALID_CONTENT
+ * This error should be set by Glib::Markup::Parser virtual methods;
+ * something was wrong with contents of the document, e.g. invalid attribute value.
+ */
+
+/** @} group Markup */
+
+
+namespace Markup
+{
+
+class ParseContext;
+
+/** @ingroup Markup */
+typedef Glib::MarkupError Error;
+
+
+/** Escapes text so that the markup parser will parse it verbatim.
+ * Less than, greater than, ampersand, etc. are replaced with the corresponding
+ * entities. This function would typically be used when writing out a file to
+ * be parsed with the markup parser.
+ * @ingroup Markup
+ * @param text Some valid UTF-8 text.
+ * @return Escaped text.
+ */
+Glib::ustring escape_text(const Glib::ustring& text);
+
+
+/** There are no flags right now. Pass <tt>Glib::Markup::ParseFlags(0)</tt> for
+ * the flags argument to all functions (this should be the default argument
+ * anyway).
+ */
+_WRAP_ENUM(ParseFlags, GMarkupParseFlags, NO_GTYPE, s#^MARKUP_##)
+
+/*! @var Markup::ParseFlags DO_NOT_USE_THIS_UNSUPPORTED_FLAG
+ * Flag you should not use.
+ */
+
+
+/** Binary predicate used by Markup::Parser::AttributeMap.
+ * @ingroup Markup
+ * Unlike <tt>operator<(const ustring& lhs, const ustring& rhs)</tt>
+ * which would be used by the default <tt>std::less<></tt> predicate,
+ * the AttributeKeyLess predicate is locale-independent. This is both
+ * more correct and much more efficient.
+ */
+class AttributeKeyLess
+{
+public:
+ typedef Glib::ustring first_argument_type;
+ typedef Glib::ustring second_argument_type;
+ typedef bool result_type;
+
+ bool operator()(const Glib::ustring& lhs, const Glib::ustring& rhs) const;
+};
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class ParserCallbacks;
+#endif
+
+/** The abstract markup parser base class.
+ * @ingroup Markup
+ * To implement a parser for your markup format, derive from
+ * Glib::Markup::Parser and implement the virtual methods.
+ *
+ * You don't have to override all of the virtual methods. If a particular
+ * method is not implement the data passed to it will be ignored. Except for
+ * the error method, any of these callbacks can throw an error exception; in
+ * particular the MarkupError::UNKNOWN_ELEMENT,
+ * MarkupError::UNKNOWN_ATTRIBUTE, and MarkupError::INVALID_CONTENT errors
+ * are intended to be thrown from these overridden methods. If you throw an
+ * error from a method, Glib::Markup::ParseContext::parse() will report that
+ * error back to its caller.
+ */
+class Parser : public SigC::Object
+{
+public:
+ typedef std::map<Glib::ustring, Glib::ustring, Glib::Markup::AttributeKeyLess> AttributeMap;
+
+ virtual ~Parser() = 0;
+
+protected:
+ /** Constructs a Parser object.
+ * Note that Markup::Parser is an abstract class which can't be instantiated
+ * directly. To implement the parser for your markup format, derive from
+ * Markup::Parser and implement the virtual methods.
+ */
+ Parser();
+
+ /** Called for open tags <tt>\<foo bar="baz"\></tt>.
+ * This virtual method is invoked when the opening tag of an element is seen.
+ * @param context The Markup::ParseContext object the parsed data belongs to.
+ * @param element_name The name of the element.
+ * @param attributes A map of attribute name/value pairs.
+ * @throw Glib::MarkupError An exception <em>you</em> should throw if
+ * something went wrong, for instance if an unknown attribute name was
+ * encountered. In particular the MarkupError::UNKNOWN_ELEMENT,
+ * MarkupError::UNKNOWN_ATTRIBUTE, and MarkupError::INVALID_CONTENT
+ * errors are intended to be thrown from user-implemented methods.
+ */
+ virtual void on_start_element(ParseContext& context,
+ const Glib::ustring& element_name,
+ const AttributeMap& attributes);
+
+ /** Called for close tags <tt>\</foo\></tt>.
+ * This virtual method is invoked when the closing tag of an element is seen.
+ * @param context The Markup::ParseContext object the parsed data belongs to.
+ * @param element_name The name of the element.
+ * @throw Glib::MarkupError An exception <em>you</em> should throw if
+ * something went wrong, for instance if an unknown attribute name was
+ * encountered. In particular the MarkupError::UNKNOWN_ELEMENT,
+ * MarkupError::UNKNOWN_ATTRIBUTE, and MarkupError::INVALID_CONTENT
+ * errors are intended to be thrown from user-implemented methods.
+ */
+ virtual void on_end_element(ParseContext& context, const Glib::ustring& element_name);
+
+ /** Called for character data.
+ * This virtual method is invoked when some text is seen (text is always
+ * inside an element).
+ * @param context The Markup::ParseContext object the parsed data belongs to.
+ * @param text The parsed text in UTF-8 encoding.
+ * @throw Glib::MarkupError An exception <em>you</em> should throw if
+ * something went wrong, for instance if an unknown attribute name was
+ * encountered. In particular the MarkupError::UNKNOWN_ELEMENT,
+ * MarkupError::UNKNOWN_ATTRIBUTE, and MarkupError::INVALID_CONTENT
+ * errors are intended to be thrown from user-implemented methods.
+ */
+ virtual void on_text(ParseContext& context, const Glib::ustring& text);
+
+ /** Called for strings that should be re-saved verbatim in this same
+ * position, but are not otherwise interpretable.
+ * This virtual method is invoked for comments, processing instructions and
+ * doctype declarations; if you're re-writing the parsed document, write the
+ * passthrough text back out in the same position.
+ * @param context The Markup::ParseContext object the parsed data belongs to.
+ * @param passthrough_text The text that should be passed through.
+ * @throw Glib::MarkupError An exception <em>you</em> should throw if
+ * something went wrong, for instance if an unknown attribute name was
+ * encountered. In particular the MarkupError::UNKNOWN_ELEMENT,
+ * MarkupError::UNKNOWN_ATTRIBUTE, and MarkupError::INVALID_CONTENT
+ * errors are intended to be thrown from user-implemented methods.
+ */
+ virtual void on_passthrough(ParseContext& context, const Glib::ustring& passthrough_text);
+
+ /** Called on error, including one thrown by an overridden virtual method.
+ * @param context The Markup::ParseContext object the parsed data belongs to.
+ * @param error A MarkupError object with detailed information about the error.
+ */
+ virtual void on_error(ParseContext& context, const MarkupError& error);
+
+private:
+ // noncopyable
+ Parser(const Parser&);
+ Parser& operator=(const Parser&);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ friend class Glib::Markup::ParserCallbacks;
+#endif
+};
+
+
+/** A parse context is used to parse marked-up documents.
+ * @ingroup Markup
+ * You can feed any number of documents into a context, as long as no errors
+ * occur; once an error occurs, the parse context can't continue to parse text
+ * (you have to destroy it and create a new parse context).
+ */
+class ParseContext : public SigC::Object
+{
+public:
+ /** Creates a new parse context.
+ * @param parser A Markup::Parser instance.
+ * @param flags Bitwise combination of Markup::ParseFlags.
+ */
+ explicit ParseContext(Parser& parser, ParseFlags flags = ParseFlags(0));
+ virtual ~ParseContext();
+
+ /** Feed some data to the ParseContext.
+ * The data need not be valid UTF-8; an error will be signalled if it's
+ * invalid. The data need not be an entire document; you can feed a document
+ * into the parser incrementally, via multiple calls to this function.
+ * Typically, as you receive data from a network connection or file, you feed
+ * each received chunk of data into this function, aborting the process if an
+ * error occurs. Once an error is reported, no further data may be fed to the
+ * ParseContext; all errors are fatal.
+ * @param text Chunk of text to parse.
+ * @throw Glib::MarkupError
+ */
+ void parse(const Glib::ustring& text);
+
+ /** Feed some data to the ParseContext.
+ * The data need not be valid UTF-8; an error will be signalled if it's
+ * invalid. The data need not be an entire document; you can feed a document
+ * into the parser incrementally, via multiple calls to this function.
+ * Typically, as you receive data from a network connection or file, you feed
+ * each received chunk of data into this function, aborting the process if an
+ * error occurs. Once an error is reported, no further data may be fed to the
+ * ParseContext; all errors are fatal.
+ * @param text_begin Begin of chunk of text to parse.
+ * @param text_end End of chunk of text to parse.
+ * @throw Glib::MarkupError
+ */
+ void parse(const char* text_begin, const char* text_end);
+
+ /** Signals to the ParseContext that all data has been fed into the parse
+ * context with parse(). This method reports an error if the document isn't
+ * complete, for example if elements are still open.
+ * @throw Glib::MarkupError
+ */
+ void end_parse();
+
+ /** Retrieves the name of the currently open element.
+ * @return The name of the currently open element, or <tt>""</tt>.
+ */
+ Glib::ustring get_element() const;
+
+ /** Retrieves the current line number.
+ * Intended for use in error messages; there are no strict semantics for what
+ * constitutes the "current" line number other than "the best number we could
+ * come up with for error messages."
+ */
+ int get_line_number() const;
+
+ /** Retrieves the number of the current character on the current line.
+ * Intended for use in error messages; there are no strict semantics for what
+ * constitutes the "current" character number other than "the best number we
+ * could come up with for error messages."
+ */
+ int get_char_number() const;
+
+ Parser* get_parser() { return parser_; }
+ const Parser* get_parser() const { return parser_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GMarkupParseContext* gobj() { return gobject_; }
+ const GMarkupParseContext* gobj() const { return gobject_; }
+#endif
+
+private:
+ Markup::Parser* parser_;
+ GMarkupParseContext* gobject_;
+
+ // noncopyable
+ ParseContext(const ParseContext&);
+ ParseContext& operator=(const ParseContext&);
+
+ static void destroy_notify_callback(void* data);
+};
+
+} // namespace Markup
+
+} // namespace Glib
+
diff --git a/glib/src/module.ccg b/glib/src/module.ccg
new file mode 100644
index 00000000..416b9cdd
--- /dev/null
+++ b/glib/src/module.ccg
@@ -0,0 +1,39 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/utility.h>
+#include <gmodule.h>
+
+namespace Glib
+{
+
+Module::Module(const std::string& file_name, ModuleFlags flags)
+:
+ gobject_ (g_module_open(file_name.c_str(), (GModuleFlags) flags))
+{}
+
+Module::~Module()
+{
+ if(gobject_)
+ g_module_close(gobject_);
+}
+
+} // namespace Glib
+
diff --git a/glib/src/module.hg b/glib/src/module.hg
new file mode 100644
index 00000000..dd4a9fa6
--- /dev/null
+++ b/glib/src/module.hg
@@ -0,0 +1,68 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glibmmconfig.h>
+#include <string>
+
+GTKMM_USING_STD(string)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" { typedef struct _GModule GModule; }
+#endif
+
+
+namespace Glib
+{
+
+_WRAP_ENUM(ModuleFlags, GModuleFlags, NO_GTYPE)
+
+//TODO: Replace get_last_error() with exceptions?
+//Provide operator()?
+class Module
+{
+ _CLASS_GENERIC(Module, GModule)
+ _IGNORE(g_module_open, g_module_close)
+
+public:
+ explicit Module(const std::string& file_name, ModuleFlags flags = ModuleFlags(0));
+ virtual ~Module();
+
+ _WRAP_METHOD(static bool get_supported(), g_module_supported)
+ _WRAP_METHOD(void make_resident(), g_module_make_resident)
+ _WRAP_METHOD(static std::string get_last_error(), g_module_error)
+ _WRAP_METHOD(bool get_symbol(const std::string& symbol_name, void*& symbol) const, g_module_symbol)
+ _WRAP_METHOD(std::string get_name() const, g_module_name)
+ _WRAP_METHOD(static std::string build_path(const std::string& directory, const std::string& module_name), g_module_build_path)
+
+ GModule* gobj() { return gobject_; }
+ const GModule* gobj() const { return gobject_; }
+
+protected:
+ GModule* gobject_;
+
+private:
+ // noncopyable
+ Module(const Module&);
+ Module& operator=(const Module&);
+};
+
+} // namespace Glib
+
diff --git a/glib/src/shell.ccg b/glib/src/shell.ccg
new file mode 100644
index 00000000..07e901d4
--- /dev/null
+++ b/glib/src/shell.ccg
@@ -0,0 +1,61 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/utility.h>
+
+
+namespace Glib
+{
+
+/**** shell utility functions **********************************************/
+
+Glib::ArrayHandle<std::string> shell_parse_argv(const std::string& command_line)
+{
+ char** argv = 0;
+ int argc = 0;
+ GError* error = 0;
+
+ g_shell_parse_argv(command_line.c_str(), &argc, &argv, &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ return Glib::ArrayHandle<std::string>(argv, argc, Glib::OWNERSHIP_DEEP);
+}
+
+std::string shell_quote(const std::string& unquoted_string)
+{
+ const ScopedPtr<char> buf (g_shell_quote(unquoted_string.c_str()));
+ return std::string(buf.get());
+}
+
+std::string shell_unquote(const std::string& quoted_string)
+{
+ GError* error = 0;
+ char *const buf = g_shell_unquote(quoted_string.c_str(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ return std::string(ScopedPtr<char>(buf).get());
+}
+
+} // namespace Glib
+
diff --git a/glib/src/shell.hg b/glib/src/shell.hg
new file mode 100644
index 00000000..08086153
--- /dev/null
+++ b/glib/src/shell.hg
@@ -0,0 +1,96 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glib/gshell.h>
+#include <string>
+
+#include <glibmm/arrayhandle.h>
+#include <glibmm/error.h>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(string)
+
+
+namespace Glib
+{
+
+/** @defgroup ShellUtils Shell-related Utilities
+ * Shell-like command line handling.
+ * @{
+ */
+
+/** Exception class for shell utility errors.
+ */
+_WRAP_GERROR(ShellError, GShellError, G_SHELL_ERROR, NO_GTYPE)
+
+
+/** Parses a command line into an argument vector, in much the same way the
+ * shell would, but without many of the expansions the shell would perform
+ * (variable expansion, globs, operators, filename expansion, etc.\ are not
+ * supported). The results are defined to be the same as those you would
+ * get from a UNIX98 /bin/sh, as long as the input contains none of the
+ * unsupported shell expansions. If the input does contain such expansions,
+ * they are passed through literally.
+ * @param command_line Command line to parse.
+ * @return Array of args (The generic ArrayHandle will be implicitly
+ * converted to any STL compatible container type).
+ * @throw Glib::ShellError
+ */
+Glib::ArrayHandle<std::string> shell_parse_argv(const std::string& command_line);
+
+/** Quotes a string so that the shell (/bin/sh) will interpret the quoted
+ * string to mean @a unquoted_string. If you pass a filename to the shell,
+ * for example, you should first quote it with this function. The quoting
+ * style used is undefined (single or double quotes may be used).
+ * @param unquoted_string A literal string.
+ * @return A quoted string.
+ */
+std::string shell_quote(const std::string& unquoted_string);
+
+/** Unquotes a string as the shell (/bin/sh) would. Only handles quotes; if
+ * a string contains file globs, arithmetic operators, variables, backticks,
+ * redirections, or other special-to-the-shell features, the result will be
+ * different from the result a real shell would produce (the variables,
+ * backticks, etc. will be passed through literally instead of being expanded).
+ * This function is guaranteed to succeed if applied to the result of
+ * shell_quote(). If it fails, it throws a Glib::ShellError exception. The
+ * @a quoted_string need not actually contain quoted or escaped text;
+ * shell_unquote() simply goes through the string and unquotes/unescapes
+ * anything that the shell would. Both single and double quotes are handled,
+ * as are escapes including escaped newlines.
+ *
+ * Shell quoting rules are a bit strange. Single quotes preserve the literal
+ * string exactly. Escape sequences are not allowed; not even <tt>\\'</tt> --
+ * if you want a <tt>'</tt> in the quoted text, you have to do something like
+ * <tt>'foo'\\''bar'</tt>. Double quotes allow <tt>$</tt>, <tt>`</tt>,
+ * <tt>"</tt>, <tt>\\</tt>, and newline to be escaped with backslash.
+ * Otherwise double quotes preserve things literally.
+ *
+ * @param quoted_string Shell-quoted string.
+ * @return An unquoted string.
+ * @throw Glib::ShellError
+ */
+std::string shell_unquote(const std::string& quoted_string);
+
+/** @} group ShellUtils */
+
+} // namespace Glib
+
diff --git a/glib/src/signalproxy.h.m4 b/glib/src/signalproxy.h.m4
new file mode 100644
index 00000000..3face310
--- /dev/null
+++ b/glib/src/signalproxy.h.m4
@@ -0,0 +1,158 @@
+// -*- c++ -*-
+dnl
+dnl Glib SignalProxy Templates
+dnl
+dnl Copyright 2001 Free Software Foundation
+dnl Copyright 1999 Karl Nelson <kenelson@ece.ucdavis.edu>
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Library General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Library General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Library General Public
+dnl License along with this library; if not, write to the Free
+dnl Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+dnl
+dnl Ignore the next line
+/* This is a generated file, do not edit. Generated from __file__ */
+include(template.macros.m4)
+#ifndef __header__
+#define __header__
+
+extern "C"
+{
+ typedef void (*GCallback) (void);
+ typedef struct _GObject GObject;
+}
+
+#include <sigc++/sigc++.h>
+
+
+namespace Glib
+{
+
+// Forward declarations
+class ObjectBase;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+struct SignalProxyInfo
+{
+ const char* signal_name;
+ GCallback callback;
+ GCallback notify_callback;
+};
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+// This base class is used by SignalProxyNormal and SignalProxyProperty.
+class SignalProxyBase
+{
+public:
+ SignalProxyBase(Glib::ObjectBase* obj);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ static inline SigC::SlotNode* data_to_slot(void* data)
+ {
+ // We store a ProxyConnection_ on the data slot of the closure.
+ // But that type is not exposed, so we use the base type.
+ SigC::ConnectionNode *const conn = static_cast<SigC::ConnectionNode*>(data);
+
+ // Return 0 if the connection is blocked.
+ return (!conn->blocked()) ? static_cast<SigC::SlotNode*>(conn->slot_.impl()) : 0;
+ }
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+protected:
+ ObjectBase* obj_;
+
+private:
+ SignalProxyBase& operator=(const SignalProxyBase&); // not implemented
+};
+
+
+// shared portion of a Signal
+// The proxy just serves to hold the name of the signal and the object
+// which is to be connected. Actually, proxies are controlled by
+// the template derivatives, which serve as gatekeepers for the
+// types allowed on a particular signal.
+class SignalProxyNormal : public SignalProxyBase
+{
+public:
+ ~SignalProxyNormal();
+
+ /// stops the current signal emmision (not in SigC++)
+ void emission_stop();
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // This callback for SignalProxy0<void>
+ // is defined here to avoid code duplication.
+ static void slot0_void_callback(GObject*, void* data);
+#endif
+
+protected:
+ SignalProxyNormal(Glib::ObjectBase* obj, const SignalProxyInfo* info);
+
+ SigC::ConnectionNode* connect_(const SigC::SlotBase& slot_base, bool after);
+ SigC::ConnectionNode* connect_notify_(const SigC::SlotBase& slot_base, bool after);
+
+private:
+ const SignalProxyInfo* info_;
+
+ SigC::ConnectionNode* connect_impl_(GCallback callback, const SigC::SlotBase& slot_base, bool after);
+
+ // no copy assignment
+ SignalProxyNormal& operator=(const SignalProxyNormal&);
+};
+
+
+dnl
+dnl GLIB_SIGNAL_PROXY([P1, P2, ...],return type)
+dnl
+define([GLIB_SIGNAL_PROXY],[dnl
+LINE(]__line__[)dnl
+
+/**** Glib::[SignalProxy]NUM($1) ***************************************************/
+
+/** Proxy for signals with NUM($1) arguments.
+ * Use the connect() method, with SigC::slot() to connect signals to signal handlers.
+ */
+template <LIST(class R,ARG_CLASS($1))>
+class [SignalProxy]NUM($1) : public SignalProxyNormal
+{
+public:
+ typedef SigC::[Slot]NUM($1)<LIST(R,ARG_TYPE($1))> SlotType;
+ typedef SigC::[Slot]NUM($1)<LIST(void,ARG_TYPE($1))> VoidSlotType;
+
+ [SignalProxy]NUM($1)(ObjectBase* obj, const SignalProxyInfo* info)
+ : SignalProxyNormal(obj, info) {}
+
+ SigC::Connection connect(const SlotType& slot, bool after = true)
+ { return SigC::Connection(connect_(slot, after)); }
+
+ SigC::Connection connect_notify(const VoidSlotType& slot, bool after = false)
+ { return SigC::Connection(connect_notify_(slot, after)); }
+};
+])dnl
+
+dnl Template forms of SignalProxy
+
+GLIB_SIGNAL_PROXY(ARGS(P,0))
+GLIB_SIGNAL_PROXY(ARGS(P,1))
+GLIB_SIGNAL_PROXY(ARGS(P,2))
+GLIB_SIGNAL_PROXY(ARGS(P,3))
+GLIB_SIGNAL_PROXY(ARGS(P,4))
+GLIB_SIGNAL_PROXY(ARGS(P,5))
+GLIB_SIGNAL_PROXY(ARGS(P,6))
+
+} // namespace Glib
+
+
+#endif /* __header__ */
+
diff --git a/glib/src/spawn.ccg b/glib/src/spawn.ccg
new file mode 100644
index 00000000..3168e705
--- /dev/null
+++ b/glib/src/spawn.ccg
@@ -0,0 +1,264 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gspawn.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/utility.h>
+
+
+namespace
+{
+
+/* Helper callback to invoke the actual sigc++ slot.
+ * We don't need to worry about (un)referencing, since the
+ * child process gets its own copy of the parent's memory anyway.
+ */
+void child_setup_callback(void* user_data)
+{
+ try
+ {
+ SigC::Slot0<void> slot (static_cast<SigC::SlotNode*>(user_data));
+ slot();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+}
+
+void copy_output_buf(std::string* dest, const char* buf)
+{
+ if(dest)
+ {
+ if(buf)
+ *dest = buf;
+ else
+ dest->erase();
+ }
+}
+
+}
+
+
+namespace Glib
+{
+
+/**** process spawning functions *******************************************/
+
+void spawn_async_with_pipes(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ const Glib::ArrayHandle<std::string>& envp,
+ SpawnFlags flags,
+ const SigC::Slot0<void>& child_setup,
+ int* child_pid,
+ int* standard_input,
+ int* standard_output,
+ int* standard_error)
+{
+ const bool setup_slot = !child_setup.empty();
+ GError* error = 0;
+
+ g_spawn_async_with_pipes(
+ working_directory.c_str(),
+ const_cast<char**>(argv.data()),
+ const_cast<char**>(envp.data()),
+ static_cast<GSpawnFlags>(unsigned(flags)),
+ (setup_slot) ? &child_setup_callback : 0,
+ (setup_slot) ? child_setup.impl() : 0,
+ child_pid,
+ standard_input, standard_output, standard_error,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void spawn_async_with_pipes(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ SpawnFlags flags,
+ const SigC::Slot0<void>& child_setup,
+ int* child_pid,
+ int* standard_input,
+ int* standard_output,
+ int* standard_error)
+{
+ const bool setup_slot = !child_setup.empty();
+ GError* error = 0;
+
+ g_spawn_async_with_pipes(
+ working_directory.c_str(),
+ const_cast<char**>(argv.data()), 0,
+ static_cast<GSpawnFlags>(unsigned(flags)),
+ (setup_slot) ? &child_setup_callback : 0,
+ (setup_slot) ? child_setup.impl() : 0,
+ child_pid,
+ standard_input, standard_output, standard_error,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void spawn_async(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ const Glib::ArrayHandle<std::string>& envp,
+ SpawnFlags flags,
+ const SigC::Slot0<void>& child_setup,
+ int* child_pid)
+{
+ const bool setup_slot = !child_setup.empty();
+ GError* error = 0;
+
+ g_spawn_async(
+ working_directory.c_str(),
+ const_cast<char**>(argv.data()),
+ const_cast<char**>(envp.data()),
+ static_cast<GSpawnFlags>(unsigned(flags)),
+ (setup_slot) ? &child_setup_callback : 0,
+ (setup_slot) ? child_setup.impl() : 0,
+ child_pid,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void spawn_async(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ SpawnFlags flags,
+ const SigC::Slot0<void>& child_setup,
+ int* child_pid)
+{
+ const bool setup_slot = !child_setup.empty();
+ GError* error = 0;
+
+ g_spawn_async(
+ working_directory.c_str(),
+ const_cast<char**>(argv.data()), 0,
+ static_cast<GSpawnFlags>(unsigned(flags)),
+ (setup_slot) ? &child_setup_callback : 0,
+ (setup_slot) ? child_setup.impl() : 0,
+ child_pid,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void spawn_sync(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ const Glib::ArrayHandle<std::string>& envp,
+ SpawnFlags flags,
+ const SigC::Slot0<void>& child_setup,
+ std::string* standard_output,
+ std::string* standard_error,
+ int* exit_status)
+{
+ const bool setup_slot = !child_setup.empty();
+
+ Glib::ScopedPtr<char> buf_standard_output;
+ Glib::ScopedPtr<char> buf_standard_error;
+ GError* error = 0;
+
+ g_spawn_sync(
+ working_directory.c_str(),
+ const_cast<char**>(argv.data()),
+ const_cast<char**>(envp.data()),
+ static_cast<GSpawnFlags>(unsigned(flags)),
+ (setup_slot) ? &child_setup_callback : 0,
+ (setup_slot) ? child_setup.impl() : 0,
+ (standard_output) ? buf_standard_output.addr() : 0,
+ (standard_error) ? buf_standard_error.addr() : 0,
+ exit_status,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ copy_output_buf(standard_output, buf_standard_output.get());
+ copy_output_buf(standard_error, buf_standard_error.get());
+}
+
+void spawn_sync(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ SpawnFlags flags,
+ const SigC::Slot0<void>& child_setup,
+ std::string* standard_output,
+ std::string* standard_error,
+ int* exit_status)
+{
+ const bool setup_slot = !child_setup.empty();
+
+ Glib::ScopedPtr<char> buf_standard_output;
+ Glib::ScopedPtr<char> buf_standard_error;
+ GError* error = 0;
+
+ g_spawn_sync(
+ working_directory.c_str(),
+ const_cast<char**>(argv.data()), 0,
+ static_cast<GSpawnFlags>(unsigned(flags)),
+ (setup_slot) ? &child_setup_callback : 0,
+ (setup_slot) ? child_setup.impl() : 0,
+ (standard_output) ? buf_standard_output.addr() : 0,
+ (standard_error) ? buf_standard_error.addr() : 0,
+ exit_status,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ copy_output_buf(standard_output, buf_standard_output.get());
+ copy_output_buf(standard_error, buf_standard_error.get());
+}
+
+void spawn_command_line_async(const std::string& command_line)
+{
+ GError* error = 0;
+ g_spawn_command_line_async(command_line.c_str(), &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+}
+
+void spawn_command_line_sync(const std::string& command_line,
+ std::string* standard_output,
+ std::string* standard_error,
+ int* exit_status)
+{
+ Glib::ScopedPtr<char> buf_standard_output;
+ Glib::ScopedPtr<char> buf_standard_error;
+ GError* error = 0;
+
+ g_spawn_command_line_sync(
+ command_line.c_str(),
+ (standard_output) ? buf_standard_output.addr() : 0,
+ (standard_error) ? buf_standard_error.addr() : 0,
+ exit_status,
+ &error);
+
+ if(error)
+ Glib::Error::throw_exception(error);
+
+ copy_output_buf(standard_output, buf_standard_output.get());
+ copy_output_buf(standard_error, buf_standard_error.get());
+}
+
+} // namespace Glib
+
diff --git a/glib/src/spawn.hg b/glib/src/spawn.hg
new file mode 100644
index 00000000..9f214d44
--- /dev/null
+++ b/glib/src/spawn.hg
@@ -0,0 +1,105 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <string>
+#include <sigc++/sigc++.h>
+#include <glibmm/arrayhandle.h>
+#include <glibmm/error.h>
+
+#include <glibmmconfig.h>
+GTKMM_USING_STD(string)
+
+
+namespace Glib
+{
+
+_WRAP_ENUM(SpawnFlags, GSpawnFlags, NO_GTYPE)
+
+/** @defgroup Spawn Spawning Processes
+ * Process launching with fork()/exec().
+ * @{
+ */
+
+/** Exception class for errors occuring when spawning processes.
+ */
+_WRAP_GERROR(SpawnError, GSpawnError, G_SPAWN_ERROR, NO_GTYPE, s#^2BIG$#TOOBIG#)
+
+
+void spawn_async_with_pipes(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ const Glib::ArrayHandle<std::string>& envp,
+ SpawnFlags flags = SpawnFlags(0),
+ const SigC::Slot0<void>& child_setup = SigC::Slot0<void>(),
+ int* child_pid = 0,
+ int* standard_input = 0,
+ int* standard_output = 0,
+ int* standard_error = 0);
+
+void spawn_async_with_pipes(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ SpawnFlags flags = SpawnFlags(0),
+ const SigC::Slot0<void>& child_setup = SigC::Slot0<void>(),
+ int* child_pid = 0,
+ int* standard_input = 0,
+ int* standard_output = 0,
+ int* standard_error = 0);
+
+void spawn_async(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ const Glib::ArrayHandle<std::string>& envp,
+ SpawnFlags flags = SpawnFlags(0),
+ const SigC::Slot0<void>& child_setup = SigC::Slot0<void>(),
+ int* child_pid = 0);
+
+void spawn_async(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ SpawnFlags flags = SpawnFlags(0),
+ const SigC::Slot0<void>& child_setup = SigC::Slot0<void>(),
+ int* child_pid = 0);
+
+void spawn_sync(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ const Glib::ArrayHandle<std::string>& envp,
+ SpawnFlags flags = SpawnFlags(0),
+ const SigC::Slot0<void>& child_setup = SigC::Slot0<void>(),
+ std::string* standard_output = 0,
+ std::string* standard_error = 0,
+ int* exit_status = 0);
+
+void spawn_sync(const std::string& working_directory,
+ const Glib::ArrayHandle<std::string>& argv,
+ SpawnFlags flags = SpawnFlags(0),
+ const SigC::Slot0<void>& child_setup = SigC::Slot0<void>(),
+ std::string* standard_output = 0,
+ std::string* standard_error = 0,
+ int* exit_status = 0);
+
+void spawn_command_line_async(const std::string& command_line);
+
+void spawn_command_line_sync(const std::string& command_line,
+ std::string* standard_output = 0,
+ std::string* standard_error = 0,
+ int* exit_status = 0);
+
+/** @} group Spawn */
+
+} // namespace Glib
+
diff --git a/glib/src/template.macros.m4 b/glib/src/template.macros.m4
new file mode 100644
index 00000000..38e7927b
--- /dev/null
+++ b/glib/src/template.macros.m4
@@ -0,0 +1,229 @@
+dnl-----------------------------------------------------------------------
+dnl
+dnl Karls M4 macros for the signal system used by gtk--
+dnl
+dnl Copyright (C) 1998-2002 The gtkmm Development Team
+dnl
+dnl Currently maintained by Tero Pulkkinen. <terop@modeemi.cs.tut.fi>
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Library General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Library General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Library General Public
+dnl License along with this library; if not, write to the Free
+dnl Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+dnl
+dnl-----------------------------------------------------------------------
+dnl Recursion prevention. (Don't attempt to understand why this works!)
+changequote(, )dnl
+changequote([, ])dnl
+pushdef([DIVERSION],divnum)dnl
+divert(-1)dnl
+
+ifdef([__template_macros__],[],[
+define(__template_macros__)
+dnl-----------------------------------------------------------------------
+
+
+dnl
+dnl M4 macros for general sanity
+dnl
+
+dnl M4 Quotas are hard to work with, so use braces like autoconf
+dnl (which are matched by vi, emacs)
+changequote(, )
+changequote([, ])
+
+dnl
+dnl M4 comments conflict with compiler directives
+changecom(, )
+
+dnl BRACE(text) => [text]
+dnl When we want something to appear with braces
+define([BRACE],[[[$*]]])
+
+dnl
+dnl PROT(macro)
+dnl If a macro generates an output with commas we need to protect it
+dnl from being broken down and interpreted
+define([PROT],[[$*]])
+
+dnl
+dnl LOWER(string)
+dnl lowercase a string
+define([LOWER],[translit([$*],[ABCDEFGHIJKLMNOPQRSTUVWXYZ],[abcdefghijklmnopqrstuvwxyz])])
+
+dnl
+dnl UPPER(string)
+dnl uppercase a string
+define([UPPER],[translit([$*],[abcdefghijklmnopqrstuvwxyz],[ABCDEFGHIJKLMNOPQRSTUVWXYZ])])
+define([UPPER_SAFE],[translit([$*],[abcdefghijklmnopqrstuvwxyz.-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ__])])
+
+dnl
+dnl BASENAME(string)
+dnl extract the basename of a string
+define([BASENAME],[patsubst([$*],[^.*/],[])])
+
+dnl
+dnl M4NAME(string)
+dnl extract the basename of a string
+define([M4NAME],[patsubst(BASENAME([$*]),[\.m4$],[])])
+
+dnl NUM(arg,arg,...)
+dnl M4 defines $# very badly (empty list=1). So we need a better one
+define([NUM],[ifelse(len([$*]),0,0,[$#])])
+
+dnl
+dnl IF(cond,string1,string2)
+dnl places string1 if length (without spaces) of cond is zero,
+dnl else string2
+define([IF],[ifelse(len(PROT(translit([$1],[ ]))),0,[$3],[$2])])
+dnl define([IF],[ifelse(len(PROT(patsubst([$1],[ ]))),0,[$3],[$2])])
+
+dnl
+dnl minclude(filename)
+dnl This includes only the macros from a file but throws away the output.
+dnl Used to take the macros from a file without getting it extra output.
+define([minclude],[IF([$1],[dnl
+pushdef([CURRENT_DIVERSION],divnum)dnl
+divert(-1)
+include($1)
+divert(CURRENT_DIVERSION)dnl
+popdef([CURRENT_DIVERSION])dnl],[[minclude]])])
+
+dnl
+dnl makes the current filename into a string approprate for use as
+dnl C identified define. (Defaults to this library name)
+dnl
+dnl example: (filename test.hh.m4)
+dnl __header__ => SIGCXX_TEST_H
+dnl __header__(MYHEAD) => MYHEAD_TEST_H
+dnl define([__header__],[ifelse($1,,[SIGCXX],UPPER($1))[_]UPPER(patsubst(translit(BASENAME(__file__),[.-],[__]),[_m4],[]))])
+define([__header__],[ifelse($1,,[_GLIBMM],UPPER($1))[_]UPPER_SAFE(M4NAME(__file__))])
+
+dnl
+dnl Set of M4 macros for variable argument template building
+dnl
+
+dnl ARGS(name,number)
+dnl Builds a comma seperated protected list of numbered names
+dnl Use this as short hand to specify arguement names
+dnl
+dnl ARGS(arg,3) => ARG1,ARG2,ARG3
+define([_ARGS],[ifelse(eval($2<$3),0,[$1$2],[$1$2,_ARGS($1,eval($2+1),$3)])])
+define([ARGS],[ifelse(eval($2>0),1,[PROT(_ARGS(UPPER([$1]),1,$2))],[PROT])])
+
+dnl
+dnl LIST(string1,string2,...)
+dnl These are intended for making extended argument lists
+dnl parameters are in pairs, the first is output if the
+dnl 2nd is nonzero length, the process is then repeated
+dnl with the next set of arguments.
+dnl
+dnl Macro expansions that expand to result in commas must call
+dnl PROT to prevent permature expansion. ARG* macros do
+dnl this automatically. (If unsure, add braces until it stops
+dnl interpreting inter macros, remove one set of braces, if
+dnl still not right use PROT)
+dnl
+dnl (LIST is probably the most useful macro in the set.)
+define([LIST],[ifelse($#,0,,$#,1,[$1],[$1],,[LIST(shift($@))],[__LIST($@)])])
+define([__LIST],[ifelse($#,0,,$#,1,[$1],[$1[]ifelse([$2],,,[[,]])__LIST(shift($@))])])
+
+dnl
+dnl ARG_LOOP(macro_name,seperator,argument_list)
+dnl Very powerful macro for construction of list of variables
+dnl formated in specify ways. To use define a macro taking
+dnl one variable which is called the format. The second argument
+dnl is a seperator which will appear between each argument.
+dnl The rest is then interpreted as arguments to form the list.
+dnl
+dnl Example:
+dnl define([FOO],[foo([$1])])
+dnl ARG_LOOP([FOO],[[, ]],A,B,C)
+dnl
+dnl Gives: foo(A), foo(B), foo(C)
+dnl
+define([_ARG_LOOP],[dnl
+ifelse(NUM($*),0,,NUM($*),1,[dnl
+indir(LOOP_FORMAT,[$1])],[dnl
+indir(LOOP_FORMAT,[$1])[]LOOP_SEPERATOR[]_ARG_LOOP(shift($*))])])
+
+define([ARG_LOOP],[dnl
+pushdef([LOOP_FORMAT],[[$1]])dnl
+pushdef([LOOP_SEPERATOR],[$2])dnl
+_ARG_LOOP(shift(shift($*)))[]dnl
+popdef([LOOP_FORMAT])dnl
+popdef([LOOP_SEPERATOR])dnl
+])
+
+
+dnl
+dnl Define some useful formats for use with ARG_LOOP.
+define([FORMAT_ARG_CLASS],[class [$1]])
+define([FORMAT_ARG_BOTH],[[$1] LOWER([$1])])
+define([FORMAT_ARG_REF],[Type<[$1]>::ref LOWER([$1])])
+define([FORMAT_ARG_TYPE],[[$1]])
+define([FORMAT_ARG_NAME],[LOWER($1)])
+define([FORMAT_ARG_CBNAME],[LOWER($1)_])
+define([FORMAT_ARG_CBDECL],[[$1] LOWER([$1])_;])
+define([FORMAT_ARG_CBINIT],[LOWER([$1])_(LOWER([$1]))])
+
+
+dnl
+dnl The following functions generate various types of parameter lists
+dnl For parameter lists
+dnl ARG_CLASS([P1,P2]) -> class P1,class P2
+dnl ARG_BOTH([P1,P2]) -> P1 p1,P2 p2
+dnl ARG_TYPE([P1,P2]) -> P1,P2
+dnl ARG_NAME([P1,P2]) -> p1,p2
+dnl For callback lists
+dnl ARG_CBNAME([C1,C2]) -> c1_,c2_
+dnl ARG_CBINIT([C1,C2]) -> c1_(c1),c2_(c2)
+dnl ARG_CBDECL([C1,C2]) -> C1 c1_; C2 c2_;
+dnl
+define([ARG_CLASS],[PROT(ARG_LOOP([FORMAT_ARG_CLASS],[[,]],$*))])
+define([ARG_BOTH],[PROT(ARG_LOOP([FORMAT_ARG_BOTH],[[,]],$*))])
+define([ARG_REF],[PROT(ARG_LOOP([FORMAT_ARG_REF],[[,]],$*))])
+define([ARG_TYPE],[PROT([$*])])
+define([ARG_NAME],[PROT(LOWER($*))])
+define([ARG_CBNAME],[PROT(ARG_LOOP([FORMAT_ARG_CBNAME],[[,]],$*))])
+define([ARG_CBDECL],[PROT(ARG_LOOP([FORMAT_ARG_CBDECL],[ ],$*))])
+define([ARG_CBINIT],[PROT(ARG_LOOP([FORMAT_ARG_CBINIT],[[,]],$*))])
+
+
+dnl
+dnl T_DROP(string)
+dnl Removes unnecessary <> with empty templates
+dnl (occasionally useful)
+define([T_DROP],[ifelse([$1],<>,,[$*])])
+
+dnl
+dnl DROP(string,drop)
+dnl Removes unnecessary strings if they match drop
+dnl (occasionally useful)
+define([DROP],[ifelse([$1],[$2],,[$*])])
+
+dnl
+dnl LINE(linenum)
+dnl places a #line statement if __debug__ set
+dnl Use this at top of macro template and following
+dnl macros that contain newlines.
+dnl
+dnl example:
+dnl LINE(]__line__[)dnl
+define([LINE],[ifdef([__debug__],[#line $1 "]__file__["
+])])
+
+dnl-----------------------------------------------------------------------
+dnl End of recursion protection. Do not put anything below this line.
+])
+divert(DIVERSION)dnl
+popdef([DIVERSION])dnl
diff --git a/glib/src/thread.ccg b/glib/src/thread.ccg
new file mode 100644
index 00000000..84499b0e
--- /dev/null
+++ b/glib/src/thread.ccg
@@ -0,0 +1,377 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/exceptionhandler.h>
+#include <glib/gmessages.h>
+
+
+namespace
+{
+
+void* call_thread_entry_slot(void* data)
+{
+ try
+ {
+ SigC::SlotNode *const slot_node = static_cast<SigC::SlotNode*>(data);
+
+ // Recreate the specific slot, and drop the reference obtained by create().
+ SigC::Slot0<void> slot (slot_node);
+ slot_node->unreference();
+
+ slot();
+ }
+ catch(Glib::Thread::Exit&)
+ {
+ // Just exit from the thread. The Thread::Exit exception
+ // is our sane C++ replacement of g_thread_exit().
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+
+ return 0;
+}
+
+} // anonymous namespace
+
+
+namespace Glib
+{
+
+// internal
+void thread_init_impl()
+{
+ // Make sure the exception map is initialized before creating any thread.
+ Glib::Error::register_init();
+}
+
+
+/**** Glib::Thread *********************************************************/
+
+// static
+Thread* Thread::create(const SigC::Slot0<void>& slot, bool joinable)
+{
+ // Obtain ownership of the slot node, and let the slot forget about it.
+ // That avoids a thread-unsafe call to unreference() in the slot's dtor.
+ //
+ // TODO: This isn't entirely safe yet, we still have reentrancy issues if
+ // the slot has been copied from another slot that still holds a reference.
+ // We need either thread-safe refcounting, or a way to force copying of the
+ // underlying slot node. The latter approach would get my vote. daniel.
+
+ SigC::SlotNode *const slot_node = static_cast<SigC::SlotNode*>(slot.impl());
+ slot_node->reference();
+ slot.clear();
+
+ GError* error = 0;
+
+ GThread *const thread = g_thread_create(
+ &call_thread_entry_slot, slot_node, joinable, &error);
+
+ if(error)
+ {
+ slot_node->unreference();
+ Glib::Error::throw_exception(error);
+ }
+
+ return reinterpret_cast<Thread*>(thread);
+}
+
+// static
+Thread* Thread::create(const SigC::Slot0<void>& slot, unsigned long stack_size,
+ bool joinable, bool bound, ThreadPriority priority)
+{
+ // Obtain ownership of the slot node, and let the slot forget about it.
+ // That avoids a thread-unsafe call to unreference() in the slot's dtor.
+ // See the TODO comment in the other create() method.
+
+ SigC::SlotNode *const slot_node = static_cast<SigC::SlotNode*>(slot.impl());
+ slot_node->reference();
+ slot.clear();
+
+ GError* error = 0;
+
+ GThread *const thread = g_thread_create_full(
+ &call_thread_entry_slot, slot_node, stack_size, joinable,
+ bound, (GThreadPriority) priority, &error);
+
+ if(error)
+ {
+ slot_node->unreference();
+ Glib::Error::throw_exception(error);
+ }
+
+ return reinterpret_cast<Thread*>(thread);
+}
+
+// static
+Thread* Thread::self()
+{
+ return reinterpret_cast<Thread*>(g_thread_self());
+}
+
+bool Thread::joinable() const
+{
+ return gobject_.joinable;
+}
+
+void Thread::join()
+{
+ g_thread_join(&gobject_);
+}
+
+void Thread::set_priority(ThreadPriority priority)
+{
+ g_thread_set_priority(&gobject_, (GThreadPriority) priority);
+}
+
+ThreadPriority Thread::get_priority() const
+{
+ return (ThreadPriority) gobject_.priority;
+}
+
+// static
+void Thread::yield()
+{
+ g_thread_yield();
+}
+
+Thread* wrap(GThread* gobject)
+{
+ return reinterpret_cast<Thread*>(gobject);
+}
+
+
+/**** Glib::StaticMutex ****************************************************/
+
+void StaticMutex::lock()
+{
+ g_static_mutex_lock(&gobject_);
+}
+
+bool StaticMutex::trylock()
+{
+ return g_static_mutex_trylock(&gobject_);
+}
+
+void StaticMutex::unlock()
+{
+ g_static_mutex_unlock(&gobject_);
+}
+
+StaticMutex::operator Mutex&()
+{
+ // If GStaticMutex is implemented as struct (e.g. on Linux), its first struct
+ // member (runtime_mutex) is a GMutex pointer. If the gthread implementation
+ // is native (i.e. the vtable pointer passed to g_thread_init() was 0), then
+ // the runtime_mutex pointer is unused, and the rest of the GStaticMutex
+ // struct resembles the mutex data.
+ //
+ // On Win32, GStaticMutex is just a typedef to struct _GMutex*. Either way,
+ // the first sizeof(GMutex*) bytes of GStaticMutex always resemble a GMutex
+ // pointer. The gthread implementation relies on that, and we'll also do so.
+
+ GMutex*& runtime_mutex = reinterpret_cast<GMutex*&>(gobject_);
+
+ // Fortunately, it cannot hurt if we set this to the GMutex pointer returned
+ // by g_static_mutex_get_mutex(). Either we just overwrite it with the same
+ // value, or it was unused anyway. Doing that allows casting the pointer
+ // location to a Glib::Mutex reference (its only data member is a GMutex*).
+
+ runtime_mutex = g_static_mutex_get_mutex(&gobject_);
+
+ return reinterpret_cast<Mutex&>(runtime_mutex);
+}
+
+
+/**** Glib::Mutex **********************************************************/
+
+Mutex::Mutex()
+:
+ gobject_ (g_mutex_new())
+{}
+
+Mutex::~Mutex()
+{
+ g_mutex_free(gobject_);
+}
+
+void Mutex::lock()
+{
+ g_mutex_lock(gobject_);
+}
+
+bool Mutex::trylock()
+{
+ return g_mutex_trylock(gobject_);
+}
+
+void Mutex::unlock()
+{
+ g_mutex_unlock(gobject_);
+}
+
+
+/**** Glib::StaticRecMutex *************************************************/
+
+void StaticRecMutex::lock()
+{
+ g_static_rec_mutex_lock(&gobject_);
+}
+
+bool StaticRecMutex::trylock()
+{
+ return g_static_rec_mutex_trylock(&gobject_);
+}
+
+void StaticRecMutex::unlock()
+{
+ g_static_rec_mutex_unlock(&gobject_);
+}
+
+void StaticRecMutex::lock_full(unsigned int depth)
+{
+ g_static_rec_mutex_lock_full(&gobject_, depth);
+}
+
+unsigned int StaticRecMutex::unlock_full()
+{
+ return g_static_rec_mutex_unlock_full(&gobject_);
+}
+
+StaticRecMutex::operator RecMutex&()
+{
+ return static_cast<RecMutex&>(*this);
+}
+
+
+/**** Glib::RecMutex *******************************************************/
+
+RecMutex::RecMutex()
+{
+ g_static_rec_mutex_init(&gobject_);
+
+ // GLib doesn't have GRecMutex, only GStaticRecMutex. Force initialization
+ // of the mutex now, to mimic the behaviour of a (hypothetical) GRecMutex.
+ g_static_mutex_get_mutex(&gobject_.mutex);
+}
+
+RecMutex::~RecMutex()
+{
+ g_static_rec_mutex_free(&gobject_);
+}
+
+
+/**** Glib::StaticRWLock ***************************************************/
+
+void StaticRWLock::reader_lock()
+{
+ g_static_rw_lock_reader_lock(&gobject_);
+}
+
+bool StaticRWLock::reader_trylock()
+{
+ return g_static_rw_lock_reader_trylock(&gobject_);
+}
+
+void StaticRWLock::reader_unlock()
+{
+ g_static_rw_lock_reader_unlock(&gobject_);
+}
+
+void StaticRWLock::writer_lock()
+{
+ g_static_rw_lock_writer_lock(&gobject_);
+}
+
+bool StaticRWLock::writer_trylock()
+{
+ return g_static_rw_lock_writer_trylock(&gobject_);
+}
+
+void StaticRWLock::writer_unlock()
+{
+ g_static_rw_lock_writer_unlock(&gobject_);
+}
+
+StaticRWLock::operator RWLock&()
+{
+ return static_cast<RWLock&>(*this);
+}
+
+
+/**** Glib::RWLock *********************************************************/
+
+RWLock::RWLock()
+{
+ g_static_rw_lock_init(&gobject_);
+
+ // GLib doesn't have GRWLock, only GStaticRWLock. Force initialization
+ // of the mutex and the condition variables now, to mimic the behaviour
+ // of a (hypothetical) GRWLock.
+
+ if(g_static_mutex_get_mutex(&gobject_.mutex))
+ {
+ gobject_.read_cond = g_cond_new();
+ gobject_.write_cond = g_cond_new();
+ }
+}
+
+RWLock::~RWLock()
+{
+ g_static_rw_lock_free(&gobject_);
+}
+
+
+/**** Glib::Cond ***********************************************************/
+
+Cond::Cond()
+:
+ gobject_ (g_cond_new())
+{}
+
+Cond::~Cond()
+{
+ g_cond_free(gobject_);
+}
+
+void Cond::signal()
+{
+ g_cond_signal(gobject_);
+}
+
+void Cond::broadcast()
+{
+ g_cond_broadcast(gobject_);
+}
+
+void Cond::wait(Mutex& mutex)
+{
+ g_cond_wait(gobject_, mutex.gobj());
+}
+
+bool Cond::timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time)
+{
+ return g_cond_timed_wait(gobject_, mutex.gobj(), const_cast<Glib::TimeVal*>(&abs_time));
+}
+
+} // namespace Glib
+
diff --git a/glib/src/thread.hg b/glib/src/thread.hg
new file mode 100644
index 00000000..4f57b57b
--- /dev/null
+++ b/glib/src/thread.hg
@@ -0,0 +1,968 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#include <glib/gthread.h>
+#include <cstddef>
+
+#include <sigc++/sigc++.h>
+#include <glibmm/error.h>
+#include <glibmm/timeval.h>
+
+/* Shadow THREAD_PRIORITY_NORMAL macro (from winbase.h).
+ */
+#if defined(THREAD_PRIORITY_NORMAL) && !defined(GTKMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL)
+enum { GTKMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL = THREAD_PRIORITY_NORMAL };
+#undef THREAD_PRIORITY_NORMAL
+enum { THREAD_PRIORITY_NORMAL = GTKMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL };
+#define THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL
+#define GTKMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL 1
+#endif
+
+
+/** Initializer macro for Glib::StaticMutex.
+ * @relates Glib::StaticMutex
+ * @hideinitializer
+ */
+#define GLIBMM_STATIC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
+
+/** Initializer macro for Glib::StaticRecMutex.
+ * @relates Glib::StaticRecMutex
+ * @hideinitializer
+ */
+#define GLIBMM_STATIC_REC_MUTEX_INIT { G_STATIC_REC_MUTEX_INIT }
+
+/** Initializer macro for Glib::StaticRWLock.
+ * @relates Glib::StaticRWLock
+ * @hideinitializer
+ */
+#define GLIBMM_STATIC_RW_LOCK_INIT { G_STATIC_RW_LOCK_INIT }
+
+/** Initializer macro for Glib::StaticPrivate.
+ * @relates Glib::StaticPrivate
+ * @hideinitializer
+ */
+#define GLIBMM_STATIC_PRIVATE_INIT { G_STATIC_PRIVATE_INIT }
+
+
+namespace Glib
+{
+
+/** Specifies the priority of a thread.
+ * @note It is not guaranteed, that threads with different priorities really
+ * behave accordingly. On some systems (e.g. Linux) only <tt>root</tt> can
+ * increase priorities. On other systems (e.g. Solaris) there doesn't seem to
+ * be different scheduling for different priorities. All in all try to avoid
+ * being dependent on priorities.
+ */
+_WRAP_ENUM(ThreadPriority, GThreadPriority, NO_GTYPE)
+
+/*! @var ThreadPriority THREAD_PRIORITY_LOW
+ * A priority lower than normal.
+ */
+/*! @var ThreadPriority THREAD_PRIORITY_NORMAL
+ * The default priority.
+ */
+/*! @var ThreadPriority THREAD_PRIORITY_HIGH
+ * A priority higher than normal.
+ */
+/*! @var ThreadPriority THREAD_PRIORITY_URGENT
+ * The highest priority.
+ */
+
+
+/** @defgroup Threads Threads
+ * Thread abstraction; including threads, different mutexes,
+ * conditions and thread private data.
+ * @{
+ */
+
+enum NotLock { NOT_LOCK };
+enum TryLock { TRY_LOCK };
+
+/** Initializes the GLib thread system.
+ * Before you use a thread related function in glibmm, you should initialize
+ * the thread system. This is done by calling Glib::thread_init().
+ *
+ * @note You should only call thread_init() with a non-<tt>0</tt> parameter
+ * if you really know what you are doing.
+ *
+ * @note thread_init() must not be called directly or indirectly as
+ * a callback from glibmm. Also no mutexes may be currently locked while
+ * calling thread_init().
+ *
+ * thread_init() might only be called once. On the second call it will
+ * abort with an error. If you want to make sure that the thread system
+ * is initialized, you can do that too:
+ * @code
+ * if(!Glib::thread_supported()) Glib::thread_init();
+ * @endcode
+ * After that line either the thread system is initialized, or the program
+ * will abort if no thread system is available in GLib, i.e. either
+ * @c G_THREADS_ENABLED is not defined or @c G_THREADS_IMPL_NONE is defined.
+ *
+ * If no thread system is available and @a vtable is <tt>0</tt> or if not all
+ * elements of @a vtable are non-<tt>0</tt>, then thread_init() will abort.
+ *
+ * @note To use thread_init() in your program, you have to link with the
+ * libraries that the command <tt>pkg-config&nbsp;--libs&nbsp;gthread-2.0</tt>
+ * outputs. This is not the case for all the other thread related functions
+ * of glibmm. Those can be used without having to link with the thread
+ * libraries. (You @em have to link with <tt>gthread-2.0</tt> if you actually
+ * want to use threads in your application, though.)
+ *
+ * @param vtable A function table of type @c GThreadFunctions, that provides
+ * the entry points to the thread system to be used.
+ */
+inline void thread_init(GThreadFunctions* vtable = 0);
+
+/** Returns whether the thread system is initialized.
+ * @return @c true, if the thread system is initialized.
+ */
+inline bool thread_supported();
+
+
+class Mutex;
+class RecMutex;
+class RWLock;
+struct StaticMutex;
+struct StaticRecMutex;
+struct StaticRWLock;
+
+
+/** Exception class for thread-related errors.
+ */
+_WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
+
+
+/** Represents a running thread.
+ * An instance of this class can only be obtained with create(), self(),
+ * or wrap(GThread*). It's not possible to delete a Thread object. If the
+ * thread is @em not joinable, its resources will be freed automatically
+ * when it exits. Otherwise, if the thread @em is joinable, you must call
+ * join() to avoid a memory leak.
+ *
+ * @note g_thread_exit() is not wrapped, because that function exits a thread
+ * without any cleanup. That's especially dangerous in C++ code, since the
+ * destructors of automatic objects won't be invoked. Instead, you can throw
+ * a Thread::Exit exception, which will be caught by the internal thread
+ * entry function.
+ *
+ * @note You might have noticed that the thread entry slot doesn't have the
+ * usual void* return value. If you want to return any data from your thread
+ * you can pass an additional output argument to the thread's entry slot.
+ */
+class Thread
+{
+public:
+ class Exit;
+
+ /** Creates a new thread with the priority <tt>THREAD_PRIORITY_NORMAL</tt>.
+ * If @a joinable is @c true, you can wait for this thread's termination by
+ * calling join(). Otherwise the thread will just disappear, when ready.
+ *
+ * The new thread executes the function or method @a slot points to. You can
+ * pass additional arguments using SigC::bind(). If the thread was created
+ * successfully, it is returned, otherwise a ThreadError exception is thrown.
+ *
+ * @param slot A slot to execute in the new thread.
+ * @param joinable Should this thread be joinable?
+ * @return The new Thread* on success.
+ * @throw Glib::ThreadError
+ */
+ static Thread* create(const SigC::Slot0<void>& slot, bool joinable);
+
+ /** Creates a new thread with the priority @a priority. The stack gets the
+ * size @a stack_size or the default value for the current platform, if
+ * @a stack_size is <tt>0</tt>.
+ *
+ * If @a joinable is @c true, you can wait for this thread's termination by
+ * calling join(). Otherwise the thread will just disappear, when ready.
+ * If @a bound is @c true, this thread will be scheduled in the system scope,
+ * otherwise the implementation is free to do scheduling in the process
+ * scope. The first variant is more expensive resource-wise, but generally
+ * faster. On some systems (e.g. Linux) all threads are bound.
+ *
+ * The new thread executes the function or method @a slot points to. You can
+ * pass additional arguments using SigC::bind(). If the thread was created
+ * successfully, it is returned.
+ *
+ * @note It is not guaranteed, that threads with different priorities really
+ * behave accordingly. On some systems (e.g. Linux) only root can increase
+ * priorities. On other systems (e.g. Solaris) there doesn't seem to be
+ * different scheduling for different priorities. All in all try to avoid
+ * being dependent on priorities. Use <tt>Glib::THREAD_PRIORITY_NORMAL</tt>
+ * here as a default.
+ *
+ * @note Only use the extended
+ * create(const SigC::Slot0<void>&, unsigned long, bool, bool, ThreadPriority)
+ * function, when you really can't use the simple
+ * create(const SigC::Slot0<void>&, bool)
+ * instead. The latter overload does not take @a stack_size, @a bound and
+ * @a priority as arguments, as they should only be used for cases, where
+ * it is inevitable.
+ *
+ * @param slot A slot to execute in the new thread.
+ * @param stack_size A stack size for the new thread, or <tt>0</tt>.
+ * @param joinable Should this thread be joinable?
+ * @param bound Should this thread be bound to a system thread?
+ * @param priority A priority for the thread.
+ * @return The new Thread* on success.
+ * @throw Glib::ThreadError
+ */
+ static Thread* create(const SigC::Slot0<void>& slot, unsigned long stack_size,
+ bool joinable, bool bound, ThreadPriority priority);
+
+ /** Returns the Thread* corresponding to the calling thread.
+ * @return The current thread.
+ */
+ static Thread* self();
+
+ /** Returns whether the thread is joinable.
+ * @return Whether the thread is joinable.
+ */
+ bool joinable() const;
+
+ /** Waits until the thread finishes.
+ * Waits until the thread finishes, i.e. the slot, as given to create(),
+ * returns or g_thread_exit() is called by the thread. (Calling
+ * g_thread_exit() in a C++ program should be avoided.) All resources of
+ * the thread including the Glib::Thread object are released. The thread
+ * must have been created with <tt>joinable&nbsp;=&nbsp;true</tt>.
+ */
+ void join();
+
+ /** Changes the priority of the thread to @a priority.
+ * @note It is not guaranteed, that threads with different priorities really
+ * behave accordingly. On some systems (e.g. Linux) only @c root can
+ * increase priorities. On other systems (e.g. Solaris) there doesn't seem
+ * to be different scheduling for different priorities. All in all try to
+ * avoid being dependent on priorities.
+ * @param priority A new priority for the thread.
+ */
+ void set_priority(ThreadPriority priority);
+
+ /** Returns the priority of the thread.
+ * @return The thread's priority.
+ */
+ ThreadPriority get_priority() const;
+
+ /** Gives way to other threads waiting to be scheduled.
+ * This function is often used as a method to make busy wait less evil. But
+ * in most cases, you will encounter, there are better methods to do that.
+ * So in general you shouldn't use this function.
+ */
+ static void yield();
+
+ GThread* gobj() { return &gobject_; }
+ const GThread* gobj() const { return &gobject_; }
+
+private:
+ GThread gobject_;
+
+ // Glib::Thread can neither be constructed nor deleted.
+ Thread();
+ void operator delete(void*, size_t);
+
+ // noncopyable
+ Thread(const Thread&);
+ Thread& operator=(const Thread&);
+};
+
+/** %Exception class used to exit from a thread.
+ * @code
+ * throw Glib::Thread::Exit();
+ * @endcode
+ * Write this if you want to exit from a thread created by Thread::create().
+ * Of course you must make sure not to catch Thread::Exit by accident, i.e.
+ * when using <tt>catch(...)</tt> somewhere in your code.
+ */
+class Thread::Exit
+{};
+
+/** @relates Glib::Thread */
+Thread* wrap(GThread* gobject);
+
+
+/** Like Glib::Mutex, but can be defined at compile time.
+ * Use @c GLIBMM_STATIC_MUTEX_INIT to initialize a StaticMutex:
+ * @code
+ * Glib::StaticMutex mutex = GLIBMM_STATIC_MUTEX_INIT;
+ * @endcode
+ * A StaticMutex can be used without calling Glib::thread_init(), it will
+ * silently do nothing then. That will also work when using the implicit
+ * conversion to Mutex&, thus you can safely use Mutex::Lock with a
+ * StaticMutex.
+ */
+struct StaticMutex
+{
+ void lock();
+ bool trylock();
+ void unlock();
+
+ operator Mutex&();
+
+ GStaticMutex* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // Must be public to allow initialization at compile time.
+ GStaticMutex gobject_;
+#endif
+};
+
+/** Represents a mutex (mutual exclusion).
+ * It can be used to protect data against shared access. Try to use
+ * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
+ * it will make your life much easier.
+ *
+ * @note Before creating a Glib::Mutex, Glib::thread_init() has to be called.
+ *
+ * @note Glib::Mutex is not recursive, i.e. a thread will deadlock, if it
+ * already has locked the mutex while calling lock(). Use Glib::RecMutex
+ * instead, if you need recursive mutexes.
+ */
+class Mutex
+{
+public:
+ class Lock;
+
+ Mutex();
+ ~Mutex();
+
+ /** Locks the mutex.
+ * If mutex is already locked by another thread, the current thread will
+ * block until mutex is unlocked by the other thread.
+ * @see Mutex::Lock
+ */
+ void lock();
+
+ /** Tries to lock the mutex.
+ * If the mutex is already locked by another thread, it immediately returns
+ * @c false. Otherwise it locks the mutex and returns @c true.
+ * @return Whether the mutex could be locked.
+ * @see Mutex::Lock
+ */
+ bool trylock();
+
+ /** Unlocks the mutex.
+ * If another thread is blocked in a lock() call for this mutex, it will be
+ * woken and can lock the mutex itself.
+ * @see Mutex::Lock
+ */
+ void unlock();
+
+ GMutex* gobj() { return gobject_; }
+
+private:
+ GMutex* gobject_;
+
+ // noncopyable
+ Mutex(const Mutex&);
+ Mutex& operator=(const Mutex&);
+};
+
+/** Utility class for exception-safe mutex locking.
+ * @par Usage example:
+ * @code
+ * {
+ * Glib::Mutex::Lock lock (mutex); // calls mutex.lock()
+ * do_something();
+ * } // the destructor calls mutex.unlock()
+ * @endcode
+ * As you can see, the compiler takes care of the unlocking. This is not
+ * only exception safe but also much less error-prone. You could even
+ * <tt>return</tt> while still holding the lock and it will be released
+ * properly.
+ */
+class Mutex::Lock
+{
+public:
+ explicit inline Lock(Mutex& mutex);
+ inline Lock(Mutex& mutex, NotLock);
+ inline Lock(Mutex& mutex, TryLock);
+ inline ~Lock();
+
+ inline void acquire();
+ inline bool try_acquire();
+ inline void release();
+ inline bool locked() const;
+
+private:
+ Mutex& mutex_;
+ bool locked_;
+
+ // noncopyable
+ Lock(const Mutex::Lock&);
+ Mutex::Lock& operator=(const Mutex::Lock&);
+};
+
+
+/** Like Glib::RecMutex, but can be defined at compile time.
+ * Use @c GLIBMM_STATIC_REC_MUTEX_INIT to initialize a StaticRecMutex:
+ * @code
+ * Glib::StaticRecMutex mutex = GLIBMM_STATIC_REC_MUTEX_INIT;
+ * @endcode
+ * A StaticRecMutex can be used without calling Glib::thread_init(), it will
+ * silently do nothing then. That will also work when using the implicit
+ * conversion to RecMutex&, thus you can safely use RecMutex::Lock with a
+ * StaticRecMutex.
+ */
+struct StaticRecMutex
+{
+ void lock();
+ bool trylock();
+ void unlock();
+
+ void lock_full(unsigned int depth);
+ unsigned int unlock_full();
+
+ operator RecMutex&();
+
+ GStaticRecMutex* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // Must be public to allow initialization at compile time.
+ GStaticRecMutex gobject_;
+#endif
+};
+
+class RecMutex : public StaticRecMutex
+{
+public:
+ class Lock;
+
+ RecMutex();
+ ~RecMutex();
+
+private:
+ // noncopyable
+ RecMutex(const RecMutex&);
+ RecMutex& operator=(const RecMutex&);
+};
+
+/** Utility class for exception-safe locking of recursive mutexes.
+ */
+class RecMutex::Lock
+{
+public:
+ explicit inline Lock(RecMutex& mutex);
+ inline Lock(RecMutex& mutex, NotLock);
+ inline Lock(RecMutex& mutex, TryLock);
+ inline ~Lock();
+
+ inline void acquire();
+ inline bool try_acquire();
+ inline void release();
+ inline bool locked() const;
+
+private:
+ RecMutex& mutex_;
+ bool locked_;
+
+ // noncopyable
+ Lock(const RecMutex::Lock&);
+ RecMutex::Lock& operator=(const RecMutex::Lock&);
+};
+
+
+/** Like Glib::RWLock, but can be defined at compile time.
+ * Use @c GLIBMM_STATIC_RW_LOCK_INIT to initialize a StaticRWLock:
+ * @code
+ * Glib::StaticRWLock rw_lock = GLIBMM_STATIC_RW_LOCK_INIT;
+ * @endcode
+ * A StaticRWLock can be used without calling Glib::thread_init(), it will
+ * silently do nothing then. That will also work when using the implicit
+ * conversion to RWLock&, thus you can safely use RWLock::ReaderLock and
+ * RWLock::WriterLock with a StaticRWLock.
+ */
+struct StaticRWLock
+{
+ void reader_lock();
+ bool reader_trylock();
+ void reader_unlock();
+
+ void writer_lock();
+ bool writer_trylock();
+ void writer_unlock();
+
+ operator RWLock&();
+
+ GStaticRWLock* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // Must be public to allow initialization at compile time.
+ GStaticRWLock gobject_;
+#endif
+};
+
+class RWLock : public StaticRWLock
+{
+public:
+ class ReaderLock;
+ class WriterLock;
+
+ RWLock();
+ ~RWLock();
+
+private:
+ // noncopyable
+ RWLock(const RWLock&);
+ RWLock& operator=(const RWLock&);
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ */
+class RWLock::ReaderLock
+{
+public:
+ explicit inline ReaderLock(RWLock& rwlock);
+ inline ReaderLock(RWLock& rwlock, NotLock);
+ inline ReaderLock(RWLock& rwlock, TryLock);
+ inline ~ReaderLock();
+
+ inline void acquire();
+ inline bool try_acquire();
+ inline void release();
+ inline bool locked() const;
+
+private:
+ RWLock& rwlock_;
+ bool locked_;
+
+ // noncopyable
+ ReaderLock(const RWLock::ReaderLock&);
+ RWLock::ReaderLock& operator=(const RWLock::ReaderLock&);
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ */
+class RWLock::WriterLock
+{
+public:
+ explicit inline WriterLock(RWLock& rwlock);
+ inline WriterLock(RWLock& rwlock, NotLock);
+ inline WriterLock(RWLock& rwlock, TryLock);
+ inline ~WriterLock();
+
+ inline void acquire();
+ inline bool try_acquire();
+ inline void release();
+ inline bool locked() const;
+
+private:
+ RWLock& rwlock_;
+ bool locked_;
+
+ // noncopyable
+ WriterLock(const RWLock::WriterLock&);
+ RWLock::WriterLock& operator=(const RWLock::WriterLock&);
+};
+
+
+class Cond
+{
+public:
+ Cond();
+ ~Cond();
+
+ void signal();
+ void broadcast();
+
+ void wait(Mutex& mutex);
+ bool timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time);
+
+ GCond* gobj() { return gobject_; }
+
+private:
+ GCond* gobject_;
+
+ // noncopyable
+ Cond(const Cond&);
+ Cond& operator=(const Cond&);
+};
+
+
+template <class T>
+struct StaticPrivate
+{
+ typedef void (*DestroyNotifyFunc) (void*);
+
+ static void delete_ptr(void* data);
+
+ inline T* get();
+ inline void set(T* data, DestroyNotifyFunc notify_func = &StaticPrivate<T>::delete_ptr);
+
+ GStaticPrivate* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // Must be public to allow initialization at compile time.
+ GStaticPrivate gobject_;
+#endif
+};
+
+template <class T>
+class Private
+{
+public:
+ typedef void (*DestructorFunc) (void*);
+
+ static void delete_ptr(void* data);
+
+ explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr);
+ inline T* get();
+ inline void set(T* data);
+
+ GPrivate* gobj() { return gobject_; }
+
+private:
+ GPrivate* gobject_;
+
+ // noncopyable
+ Private(const Private<T>&);
+ Private<T>& operator=(const Private<T>&);
+};
+
+/** @} group Threads */
+
+/*! A glibmm thread example.
+ * @example thread/thread.cc
+ */
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/***************************************************************************/
+/* inline implementation */
+/***************************************************************************/
+
+// internal
+void thread_init_impl();
+
+/* This function must be inline, to avoid an unnecessary dependency on
+ * libgthread even if the thread system is not used. libgthread might
+ * not even be available if GLib was compiled without thread support.
+ */
+inline
+void thread_init(GThreadFunctions* vtable)
+{
+ g_thread_init(vtable);
+ Glib::thread_init_impl();
+}
+
+inline
+bool thread_supported()
+{
+ return g_thread_supported();
+}
+
+
+/**** Glib::Mutex::Lock ****************************************************/
+
+inline
+Mutex::Lock::Lock(Mutex& mutex)
+:
+ mutex_ (mutex),
+ locked_ (true)
+{
+ mutex_.lock();
+}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, NotLock)
+:
+ mutex_ (mutex),
+ locked_ (false)
+{}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, TryLock)
+:
+ mutex_ (mutex),
+ locked_ (mutex.trylock())
+{}
+
+inline
+Mutex::Lock::~Lock()
+{
+ if(locked_)
+ mutex_.unlock();
+}
+
+inline
+void Mutex::Lock::acquire()
+{
+ mutex_.lock();
+ locked_ = true;
+}
+
+inline
+bool Mutex::Lock::try_acquire()
+{
+ locked_ = mutex_.trylock();
+ return locked_;
+}
+
+inline
+void Mutex::Lock::release()
+{
+ mutex_.unlock();
+ locked_ = false;
+}
+
+inline
+bool Mutex::Lock::locked() const
+{
+ return locked_;
+}
+
+
+/**** Glib::RecMutex::Lock *************************************************/
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex)
+:
+ mutex_ (mutex),
+ locked_ (true)
+{
+ mutex_.lock();
+}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, NotLock)
+:
+ mutex_ (mutex),
+ locked_ (false)
+{}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, TryLock)
+:
+ mutex_ (mutex),
+ locked_ (mutex.trylock())
+{}
+
+inline
+RecMutex::Lock::~Lock()
+{
+ if(locked_)
+ mutex_.unlock();
+}
+
+inline
+void RecMutex::Lock::acquire()
+{
+ mutex_.lock();
+ locked_ = true;
+}
+
+inline
+bool RecMutex::Lock::try_acquire()
+{
+ locked_ = mutex_.trylock();
+ return locked_;
+}
+
+inline
+void RecMutex::Lock::release()
+{
+ mutex_.unlock();
+ locked_ = false;
+}
+
+inline
+bool RecMutex::Lock::locked() const
+{
+ return locked_;
+}
+
+
+/**** Glib::RWLock::ReaderLock *********************************************/
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
+:
+ rwlock_ (rwlock),
+ locked_ (true)
+{
+ rwlock_.reader_lock();
+}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, NotLock)
+:
+ rwlock_ (rwlock),
+ locked_ (false)
+{}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, TryLock)
+:
+ rwlock_ (rwlock),
+ locked_ (rwlock.reader_trylock())
+{}
+
+inline
+RWLock::ReaderLock::~ReaderLock()
+{
+ if(locked_)
+ rwlock_.reader_unlock();
+}
+
+inline
+void RWLock::ReaderLock::acquire()
+{
+ rwlock_.reader_lock();
+ locked_ = true;
+}
+
+inline
+bool RWLock::ReaderLock::try_acquire()
+{
+ locked_ = rwlock_.reader_trylock();
+ return locked_;
+}
+
+inline
+void RWLock::ReaderLock::release()
+{
+ rwlock_.reader_unlock();
+ locked_ = false;
+}
+
+inline
+bool RWLock::ReaderLock::locked() const
+{
+ return locked_;
+}
+
+
+/**** Glib::RWLock::WriterLock *********************************************/
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock)
+:
+ rwlock_ (rwlock),
+ locked_ (true)
+{
+ rwlock_.writer_lock();
+}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, NotLock)
+:
+ rwlock_ (rwlock),
+ locked_ (false)
+{}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, TryLock)
+:
+ rwlock_ (rwlock),
+ locked_ (rwlock.writer_trylock())
+{}
+
+inline
+RWLock::WriterLock::~WriterLock()
+{
+ if(locked_)
+ rwlock_.writer_unlock();
+}
+
+inline
+void RWLock::WriterLock::acquire()
+{
+ rwlock_.writer_lock();
+ locked_ = true;
+}
+
+inline
+bool RWLock::WriterLock::try_acquire()
+{
+ locked_ = rwlock_.writer_trylock();
+ return locked_;
+}
+
+inline
+void RWLock::WriterLock::release()
+{
+ rwlock_.writer_unlock();
+ locked_ = false;
+}
+
+inline
+bool RWLock::WriterLock::locked() const
+{
+ return locked_;
+}
+
+
+/**** Glib::StaticPrivate **************************************************/
+
+// static
+template <class T>
+void StaticPrivate<T>::delete_ptr(void* data)
+{
+ delete static_cast<T*>(data);
+}
+
+template <class T> inline
+T* StaticPrivate<T>::get()
+{
+ return static_cast<T*>(g_static_private_get(&gobject_));
+}
+
+template <class T> inline
+void StaticPrivate<T>::set(T* data, typename StaticPrivate<T>::DestroyNotifyFunc notify_func)
+{
+ g_static_private_set(&gobject_, data, notify_func);
+}
+
+
+/**** Glib::Private ********************************************************/
+
+// static
+template <class T>
+void Private<T>::delete_ptr(void* data)
+{
+ delete static_cast<T*>(data);
+}
+
+template <class T> inline
+Private<T>::Private(typename Private<T>::DestructorFunc destructor_func)
+:
+ gobject_ (g_private_new(destructor_func))
+{}
+
+template <class T> inline
+T* Private<T>::get()
+{
+ return static_cast<T*>(g_private_get(gobject_));
+}
+
+template <class T> inline
+void Private<T>::set(T* data)
+{
+ g_private_set(gobject_, data);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
diff --git a/glib/src/unicode.ccg b/glib/src/unicode.ccg
new file mode 100644
index 00000000..c023088f
--- /dev/null
+++ b/glib/src/unicode.ccg
@@ -0,0 +1,22 @@
+// -*- c++ -*-
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/unicode.h>
+
diff --git a/glib/src/unicode.hg b/glib/src/unicode.hg
new file mode 100644
index 00000000..a8b82193
--- /dev/null
+++ b/glib/src/unicode.hg
@@ -0,0 +1,141 @@
+/* $Id$ */
+
+/* Copyright (C) 2002 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+
+#m4begin
+_PUSH()
+
+// m4 helper macros to generate the character-class inline functions.
+
+m4_define(`_UNICHAR_FUNC',`dnl
+inline $1 $2(gunichar uc)
+ { return g_unichar_$2(uc); }
+`'dnl`'')
+
+m4_define(`_ASCII_FUNC',`dnl
+inline $1 $2(char c)
+ { return g_ascii_$2(c); }
+`'dnl`'')
+
+_POP()
+#m4end
+
+#include <glib/gmacros.h>
+#include <glib/gstrfuncs.h>
+#include <glib/gunicode.h>
+
+// Not used, but we want to get rid of possible <ctype.h> macros.
+#include <cctype>
+
+#undef isalnum
+#undef isalpha
+#undef iscntrl
+#undef isdigit
+#undef isgraph
+#undef islower
+#undef isprint
+#undef ispunct
+#undef isspace
+#undef isupper
+#undef isxdigit
+#undef istitle
+#undef isdefined
+#undef iswide
+#undef toupper
+#undef tolower
+#undef totitle
+
+
+namespace Glib
+{
+
+_WRAP_ENUM(UnicodeType, GUnicodeType, NO_GTYPE)
+_WRAP_ENUM(UnicodeBreakType, GUnicodeBreakType, NO_GTYPE)
+_WRAP_ENUM(AsciiType, GAsciiType, NO_GTYPE)
+_WRAP_ENUM(NormalizeMode, GNormalizeMode, NO_GTYPE)
+
+/** @defgroup Unicode Unicode Manipulation
+ * Functions operating on Unicode characters and UTF-8 strings.
+ * @{
+ */
+
+namespace Unicode
+{
+
+_UNICHAR_FUNC(bool, validate)
+_UNICHAR_FUNC(bool, isalnum)
+_UNICHAR_FUNC(bool, isalpha)
+_UNICHAR_FUNC(bool, iscntrl)
+_UNICHAR_FUNC(bool, isdigit)
+_UNICHAR_FUNC(bool, isgraph)
+_UNICHAR_FUNC(bool, islower)
+_UNICHAR_FUNC(bool, isprint)
+_UNICHAR_FUNC(bool, ispunct)
+_UNICHAR_FUNC(bool, isspace)
+_UNICHAR_FUNC(bool, isupper)
+_UNICHAR_FUNC(bool, isxdigit)
+_UNICHAR_FUNC(bool, istitle)
+_UNICHAR_FUNC(bool, isdefined)
+_UNICHAR_FUNC(bool, iswide)
+
+_UNICHAR_FUNC(gunichar, toupper)
+_UNICHAR_FUNC(gunichar, tolower)
+_UNICHAR_FUNC(gunichar, totitle)
+
+_UNICHAR_FUNC(int, digit_value)
+_UNICHAR_FUNC(int, xdigit_value)
+
+inline Glib::UnicodeType type(gunichar uc)
+ { return static_cast<Glib::UnicodeType>(static_cast<int>(g_unichar_type(uc))); }
+
+inline Glib::UnicodeBreakType break_type(gunichar uc)
+ { return static_cast<Glib::UnicodeBreakType>(static_cast<int>(g_unichar_break_type(uc))); }
+
+} // namespace Unicode
+
+
+namespace Ascii
+{
+
+_ASCII_FUNC(bool, isalnum)
+_ASCII_FUNC(bool, isalpha)
+_ASCII_FUNC(bool, iscntrl)
+_ASCII_FUNC(bool, isdigit)
+_ASCII_FUNC(bool, isgraph)
+_ASCII_FUNC(bool, islower)
+_ASCII_FUNC(bool, isprint)
+_ASCII_FUNC(bool, ispunct)
+_ASCII_FUNC(bool, isspace)
+_ASCII_FUNC(bool, isupper)
+_ASCII_FUNC(bool, isxdigit)
+
+_ASCII_FUNC(char, tolower)
+_ASCII_FUNC(char, toupper)
+
+_ASCII_FUNC(int, digit_value)
+_ASCII_FUNC(int, xdigit_value)
+
+} // namespace Ascii
+
+
+/** @} group Unicode */
+
+} // namespace Glib
+
diff --git a/glib/src/value_basictypes.cc.m4 b/glib/src/value_basictypes.cc.m4
new file mode 100644
index 00000000..b9a4b6dc
--- /dev/null
+++ b/glib/src/value_basictypes.cc.m4
@@ -0,0 +1,84 @@
+divert(-1)
+
+dnl $Id$
+
+dnl Glib::Value specializations for fundamental types
+dnl
+dnl Copyright 2002 The gtkmm Development Team
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Library General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Library General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Library General Public
+dnl License along with this library; if not, write to the Free
+dnl Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+include(template.macros.m4)
+
+dnl
+dnl GLIB_VALUE_BASIC(bool, boolean)
+dnl
+define([GLIB_VALUE_BASIC],[dnl
+LINE(]__line__[)dnl
+
+dnl Please ignore the format stuff. I was just tired and played a little.
+/**** Glib::Value<$1> translit(format([%]eval(57-len([$1]))[s],[****/]),[ ],[*])
+
+// static
+GType Value<$1>::value_type()
+{
+ return G_TYPE_[]UPPER($2);
+}
+
+void Value<$1>::set($1 data)
+{
+ g_value_set_$2(&gobject_, data);
+}
+
+$1 Value<$1>::get() const
+{
+ return g_value_get_$2(&gobject_);
+}
+
+GParamSpec* Value<$1>::create_param_spec(const Glib::ustring& name) const
+{
+ return g_param_spec_$2(
+ name.c_str(), 0, 0,ifelse($2,pointer,,[
+ ifelse($3,,,[$3, $4, ])[]g_value_get_$2(&gobject_),])
+ GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE));
+}
+])
+
+divert[]dnl
+// -*- c++ -*-
+// This is a generated file, do not edit. Generated from __file__
+
+#include <glibmm/value.h>
+
+namespace Glib
+{
+
+G_GNUC_EXTENSION typedef long long long_long;
+G_GNUC_EXTENSION typedef unsigned long long unsigned_long_long;
+
+GLIB_VALUE_BASIC(bool, boolean)
+GLIB_VALUE_BASIC(char, char, -128, 127)
+GLIB_VALUE_BASIC(unsigned char, uchar, 0, 255)
+GLIB_VALUE_BASIC(int, int, G_MININT, G_MAXINT)
+GLIB_VALUE_BASIC(unsigned int, uint, 0, G_MAXUINT)
+GLIB_VALUE_BASIC(long, long, G_MINLONG, G_MAXLONG)
+GLIB_VALUE_BASIC(unsigned long, ulong, 0, G_MAXULONG)
+GLIB_VALUE_BASIC(long_long, int64, G_GINT64_CONSTANT[](0x8000000000000000), G_GINT64_CONSTANT[](0x7fffffffffffffff))
+GLIB_VALUE_BASIC(unsigned_long_long, uint64, G_GINT64_CONSTANT[](0U), G_GINT64_CONSTANT[](0xffffffffffffffffU))
+GLIB_VALUE_BASIC(float, float, G_MINFLOAT, G_MAXFLOAT)
+GLIB_VALUE_BASIC(double, double, G_MINDOUBLE, G_MAXDOUBLE)
+GLIB_VALUE_BASIC(void*, pointer)
+} // namespace Glib
+
diff --git a/glib/src/value_basictypes.h.m4 b/glib/src/value_basictypes.h.m4
new file mode 100644
index 00000000..077d52f4
--- /dev/null
+++ b/glib/src/value_basictypes.h.m4
@@ -0,0 +1,83 @@
+divert(-1)
+
+dnl $Id$
+
+dnl Glib::Value specializations for fundamental types
+dnl
+dnl Copyright 2002 The gtkmm Development Team
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Library General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Library General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Library General Public
+dnl License along with this library; if not, write to the Free
+dnl Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+include(template.macros.m4)
+
+dnl
+dnl GLIB_VALUE_BASIC(bool, boolean)
+dnl
+define([GLIB_VALUE_BASIC],[dnl
+LINE(]__line__[)dnl
+
+/**
+ * @ingroup glibmmValue
+ */
+template <>
+class Value<$1> : public ValueBase
+{
+public:
+ typedef $1 CppType;
+ typedef g$2 CType;
+
+ static GType value_type() G_GNUC_CONST;
+
+ void set($1 data);
+ $1 get() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ GParamSpec* create_param_spec(const Glib::ustring& name) const;
+#endif
+};
+])
+
+divert[]dnl
+// -*- c++ -*-
+// This is a generated file, do not edit. Generated from __file__
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#ifndef _GLIBMM_VALUE_H_INCLUDE_VALUE_BASICTYPES_H
+#error "glibmm/value_basictypes.h cannot be included directly"
+#endif
+#endif
+
+/* Suppress warnings about `long long' when GCC is in -pedantic mode.
+ */
+#if (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
+#pragma GCC system_header
+#endif
+
+namespace Glib
+{
+GLIB_VALUE_BASIC(bool, boolean)
+GLIB_VALUE_BASIC(char, char)
+GLIB_VALUE_BASIC(unsigned char, uchar)
+GLIB_VALUE_BASIC(int, int)
+GLIB_VALUE_BASIC(unsigned int, uint)
+GLIB_VALUE_BASIC(long, long)
+GLIB_VALUE_BASIC(unsigned long, ulong)
+GLIB_VALUE_BASIC(long long, int64)
+GLIB_VALUE_BASIC(unsigned long long, uint64)
+GLIB_VALUE_BASIC(float, float)
+GLIB_VALUE_BASIC(double, double)
+GLIB_VALUE_BASIC(void*, pointer)
+} // namespace Glib
+