diff options
Diffstat (limited to 'glib')
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_, ¤t_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 + 10</tt> for resizing operations, and + * <tt>PRIORITY_HIGH_IDLE + 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(¶m.value, G_PARAM_SPEC_VALUE_TYPE(pspec)); + G_VALUE_COLLECT(¶m.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(¶meters[--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 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 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 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> - <tt>0x1F</tt> (everything below <tt>SPACE</tt>) + * and in the range <tt>0x80</tt> - <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> - <tt>0x1F</tt> (everything below <tt>SPACE</tt>) + * and in the range <tt>0x80</tt> - <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 = -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_, µseconds); +} + + +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µ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>== != < > <= >=</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 -- more commonly known as + * ASCII -- 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 -- 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>== != < > <= >=</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 s + * <tt>"ß"</tt> will be replaced by two characters <tt>"SS"</tt> + * because there is no capital <tt>"ß"</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) override all + * _vfunc() members. 2) set the GIOChannel flags in your constructor. + * + * @note This feature of being able to implement a custom Glib::IOChannel is + * deprecated in glibmm 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>\& \< \> \" \'</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 --libs 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 = 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 -- + * 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 + |