Please enter the commit message for your changes. Lines starting

with '' will be ignored, and an empty message aborts the commit.
 On branch master
 Changes to be committed:
   (use "git reset HEAD <file>..." to unstage)

	new file:   lib/ruby-gtk2-2.0.2/AUTHORS
	new file:   lib/ruby-gtk2-2.0.2/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/NEWS
	new file:   lib/ruby-gtk2-2.0.2/README
	new file:   lib/ruby-gtk2-2.0.2/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/atk/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/atk/README
	new file:   lib/ruby-gtk2-2.0.2/atk/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/atk.def
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/depend
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatk.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatk.h
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkaction.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkcomponent.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkconversions.h
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkdocument.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkeditabletext.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkgobjectaccessible.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkhyperlink.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkhypertext.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkimage.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkimplementor.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatknoopobject.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatknoopobjectfactory.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkobject.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkobjectfactory.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkobjectrole.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkprivate.h
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkregistry.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkrelation.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkrelationset.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkrelationtype.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkselection.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkstate.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkstateset.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkstreamablecontent.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatktable.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatktext.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatktextattribute.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatktextrange.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatktextrectangle.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkutil.c
	new file:   lib/ruby-gtk2-2.0.2/atk/ext/atk/rbatkvalue.c
	new file:   lib/ruby-gtk2-2.0.2/atk/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/atk/lib/atk.rb
	new file:   lib/ruby-gtk2-2.0.2/atk/test/atk-test-utils.rb
	new file:   lib/ruby-gtk2-2.0.2/atk/test/run-test.rb
	new file:   lib/ruby-gtk2-2.0.2/atk/test/test-text-rectangle.rb
	new file:   lib/ruby-gtk2-2.0.2/exec_make.rb
	new file:   lib/ruby-gtk2-2.0.2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/README
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/depend
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/gdk_pixbuf2.def
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbuf-format.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbuf-loader.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbuf.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbuf.h
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbuf2conversions.h
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbuf2private.h
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbufanimation.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbufanimationiter.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixbufsimpleanim.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/ext/gdk_pixbuf2/rbgdk-pixdata.c
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/lib/gdk_pixbuf2.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/anim.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/composite.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/flip.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/floppybuddy.gif
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/format.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/gnome-foot.png
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/inline.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/loader.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/pixdata.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/rotate.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/save.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/scale.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/simpleanim.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/utils.rb
	new file:   lib/ruby-gtk2-2.0.2/gdk_pixbuf2/sample/xpm.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/README
	new file:   lib/ruby-gtk2-2.0.2/gio2/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/gio2/TODO
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/depend
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/gio2.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/gio2.def
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/gio2.h
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgio.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgio2.h
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgio2conversions.h
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgio2private.h
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioappinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioapplaunchcontext.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioasyncinitable.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioasyncresult.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiobufferedinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiobufferedoutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiocancellable.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiocharsetconverter.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiocontenttype.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioconverter.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioconverterinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioconverteroutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiodatainputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiodataoutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiodesktopappinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiodrive.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioemblem.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioemblemedicon.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofile.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileattribute.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileattributeinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileattributeinfolist.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileattributematcher.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofiledescriptorbased.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileenumerator.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileicon.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileiostream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofilemonitor.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofilenamecompleter.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofileoutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofilterinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiofilteroutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioicon.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioinetaddress.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioinetsocketaddress.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioinitable.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioio.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioiomodule.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioiomodules.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioioscheduler.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioioschedulerjob.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioiostream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioloadableicon.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiomemoryinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiomemoryoutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiomount.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiomountoperation.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgionetworkaddress.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgionetworkservice.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiooutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioresolver.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgioseekable.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosimpleasyncresult.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocket.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketaddress.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketaddressenumerator.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketclient.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketconnectable.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketconnection.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketconnectionfactory.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketcontrolmessage.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketlistener.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosocketservice.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiosrvtarget.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiotcpconnection.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiothemedicon.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiothreadedsocketservice.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiotlscertificate.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixconnection.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixfdlist.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixfdmessage.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixinputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixmount.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixmountmonitor.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixmountpoint.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixmountpoints.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixmounts.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixoutputstream.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiounixsocketaddress.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiovfs.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiovolume.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiovolumemonitor.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiozlibcompressor.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/rbgiozlibdecompressor.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/ext/gio2/util.c
	new file:   lib/ruby-gtk2-2.0.2/gio2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/lib/gio2.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/lib/gio2/deprecated.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/load-test.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/test_bufferedinputstream.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/test_charsetconverter.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/test_datainputstream.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/test_fileenumerator.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/test_filemonitor.rb
	new file:   lib/ruby-gtk2-2.0.2/gio2/test/test_inetaddress.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/glib2/README
	new file:   lib/ruby-gtk2-2.0.2/glib2/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/glib2/TODO
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/depend
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/glib2.def
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgcompat.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib2conversions.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_bookmarkfile.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_convert.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_error.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_fileutils.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_i18n.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_int64.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_io_constants.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_iochannel.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_iochannel_win32_socket.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_iochannelerror.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_keyfile.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_maincontext.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_mainloop.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_messages.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_pollfd.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_shell.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_shellerror.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_source.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_spawn.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_spawnerror.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_threads.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_timer.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_ucs4.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_unichar.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_unicode.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_utf16.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_utf8.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_utils.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglib_win32.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglibdeprecated.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbglibdeprecated.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_boxed.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_closure.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_convert.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_enumflags.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_enums.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_flags.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_object.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_param.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_paramspecs.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_signal.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_strv.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_type.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_typeinstance.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_typeinterface.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_typemodule.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_typeplugin.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_value.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_valuearray.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobj_valuetypes.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobject.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgobject.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgprivate.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutil.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutil.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutil_callback.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutil_list.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutil_list.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutildeprecated.c
	new file:   lib/ruby-gtk2-2.0.2/glib2/ext/glib2/rbgutildeprecated.h
	new file:   lib/ruby-gtk2-2.0.2/glib2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/glib-mkenums.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/glib2.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/glib2/deprecatable.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2-raketask.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/external-package.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/native-binary-build-task.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/package-task.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/package.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/source-download-task.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/win32-binary-build-task.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/gnome2/rake/win32-binary-download-task.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/lib/mkmf-gnome2.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/bookmarkfile.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/idle.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/iochannel.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/keyfile.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/shell.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/spawn.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/timeout.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/timeout2.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/timer.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/type-register.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/type-register2.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/sample/utils.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/glib-test-init.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/glib-test-utils.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/run-test.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_enum.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_file_utils.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_flags.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_glib2.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_iochannel.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_key_file.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_mkenums.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_poll_fd.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_signal.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_source.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_spawn.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_timeout.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_unicode.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_utils.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_value.rb
	new file:   lib/ruby-gtk2-2.0.2/glib2/test/test_win32.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/README.md
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/depend
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/gobject_introspection.def
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-arg-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-argument.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-base-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-boxed-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-callable-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-callback-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-constant-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-constructor-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-conversions.h
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-enum-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-field-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-flags-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-function-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-interface-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-loader.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-method-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-object-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-private.h
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-property-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-registered-type-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-repository.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-signal-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-struct-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-type-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-type-tag.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-types.h
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-union-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-unresolved-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-value-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gi-vfunc-info.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gobject-introspection.c
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/ext/gobject-introspection/rb-gobject-introspection.h
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/boxed-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/callable-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/collection-reader.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/interface-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/loader.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/object-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/repository.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/struct-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/lib/gobject-introspection/union-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/patches/0001-Support-external-g-ir-scanner.patch
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/patches/cross-g-ir-scanner.diff
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/gobject-introspection-test-utils.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/run-test.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-arg-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-base-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-boxed-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-callable-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-callback-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-constant-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-enum-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-field-type.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-flags-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-function-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-interface-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-loader.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-object-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-property-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-registered-type-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-repository.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-signal-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-struct-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-type-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-type-tag.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-union-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-value-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gobject-introspection/test/test-vfunc-info.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/gtk2/README
	new file:   lib/ruby-gtk2-2.0.2/gtk2/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/depend
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/global.h
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/gtk2.def
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/init.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdk.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdk.h
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkatom.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkcairo.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkcolor.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkcolormap.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkconst.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkconversions.h
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkcursor.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkdevice.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkdisplay.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkdisplaymanager.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkdragcontext.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkdraw.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkevent.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkgc.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkgeometry.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkimage.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkinput.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkkeymap.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkkeyval.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkpango.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkpangorenderer.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkpixbuf.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkpixmap.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkproperty.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkrectangle.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkregion.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkrgb.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkscreen.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkselection.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkthreads.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdktimecoord.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkvisual.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkwindow.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkwindowattr.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgdkx11.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtk.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtk.h
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaboutdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccelerator.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccelgroup.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccelgroupentry.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccelkey.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccellabel.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccelmap.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaccessible.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaction.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkactiongroup.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkadjustment.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkalignment.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkallocation.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkarrow.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkaspectframe.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkassistant.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbin.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbindingset.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkborder.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbuildable.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbuilder.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcalendar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcelleditable.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcelllayout.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrenderer.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrendereraccel.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrenderercombo.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrendererpixbuf.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrendererprogress.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrendererspin.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrendererspinner.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrenderertext.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellrenderertoggle.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcellview.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcheckbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcheckmenuitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkclipboard.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcolorbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcolorsel.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcolorselectiondialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcombo.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcombobox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcomboboxentry.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkconst.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcontainer.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkconversions.h
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkcurve.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkdrag.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkdrawingarea.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkeditable.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkentry.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkentrycompletion.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkeventbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkexpander.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilechooser.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilechooserbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilechooserdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilechooserwidget.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilefilter.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilesel.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfilesystemerror.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfixed.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfontbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfontselection.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkfontselectiondialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkframe.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkgamma.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhandlebox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhbbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhpaned.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhruler.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhscale.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhscrollbar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkhseparator.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkiconfactory.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkiconinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkiconset.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkiconsize.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkiconsource.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkicontheme.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkiconview.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkimage.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkimagemenuitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkimcontext.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkimcontextsimple.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkimmulticontext.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkinfobar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkinputdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkinvisible.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkitemfactory.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtklabel.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtklayout.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtklinkbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkliststore.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmacros.h
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmenu.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmenubar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmenuitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmenushell.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmenutoolbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmessagedialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkmisc.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtknotebook.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkobject.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkoptionmenu.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkpagesetup.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkpagesetupunixdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkpaned.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkpapersize.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkplug.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprintcontext.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprinter.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprintjob.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprintoperation.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprintoperationpreview.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprintsettings.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprintunixdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprogress.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkprogressbar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkradioaction.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkradiobutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkradiomenuitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkradiotoolbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrange.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrc.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrcstyle.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentaction.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentchooser.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentchooserdialog.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentchoosermenu.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentchooserwidget.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentdata.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentfilter.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentfilterinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentinfo.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkrecentmanager.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkruler.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkscale.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkscalebutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkscrollbar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkscrolledwindow.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkselection.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkselectiondata.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkseparator.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkseparatormenuitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkseparatortoolitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtksettings.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtksizegroup.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtksocket.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkspinbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkspinner.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkstatusbar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkstatusicon.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkstock.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkstyle.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktable.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktargetlist.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktearoffmenuitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextappearance.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextattributes.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextbuffer.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextchild.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextiter.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextmark.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktexttag.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktexttagtable.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktextview.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktoggleaction.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktogglebutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktoggletoolbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktoolbar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktoolbutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktoolitem.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktooltip.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktooltips.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreedragdest.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreedragsource.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreeiter.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreemodel.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreemodelfilter.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreemodelsort.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreepath.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreerowreference.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreeselection.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreesortable.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreestore.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreeview.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtktreeviewcolumn.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkuimanager.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvbbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvbox.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkviewport.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvolumebutton.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvpaned.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvruler.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvscale.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvscrollbar.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkvseparator.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkwidget.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkwindow.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/ext/gtk2/rbgtkwindowgroup.c
	new file:   lib/ruby-gtk2-2.0.2/gtk2/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/lib/gtk2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/lib/gtk2/base.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/patches/gtk+-2.24.14-add-missing-exeext.diff
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/README
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/alphatest.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/apple-red.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/appwindow.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/background.jpg
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/builder.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/button_box.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-arc-negative.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-arc.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-clip-image.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-clip-rectangle.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-clip.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-curve-rectangle.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-curve-to.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-dash.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-fill-and-stroke.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-fill-and-stroke2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-gradient.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-image-pattern.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-image.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-line-cap.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-line-join.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-long-lines.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-operator.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-path.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-pattern-fill.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-self-intersect.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-text-align-center.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-text-extents.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/cairo-text.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/changedisplay.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/clipboard.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/colorsel.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/common.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/demo.ui
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/dialog.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/drawingarea.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/editable_cells.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/entry_completion.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/expander.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/floppybuddy.gif
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-applets.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-calendar.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-foot.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-fs-directory.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-fs-regular.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-gimp.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-gmush.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnome-gsame.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gnu-keys.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/gtk-logo-rgb.gif
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/hypertext.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/iconview.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/images.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/item_factory.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/list_store.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/main.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/menus.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/panes.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/pixbufs.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/printing.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/rotated_text.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/ruby-gnome2-logo.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/sizegroup.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/stock_browser.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/textview.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/gtk-demo/tree_store.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/aboutdialog.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/aboutdialog2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/alpha-demo.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/assistant.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/bindings.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/button.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/button2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/buttonbox.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/cairo-pong.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/calendar.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/checkbutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/colorselection.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/combo_check.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/combobox.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/composited-windows.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/cursor.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/dialog.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/dialog2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/dnd.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/dndtreeview.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/drag-move.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/drawing.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/entry.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/entrycompletion.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/expander.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/filechooser.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/fileselection.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/frame.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/gc.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/gdkscreen.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/gnome-logo-icon.png
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/helloworld.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/iconview.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/image.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/infobar.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/itemfactory.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/itemfactory2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/keyboard_grab.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/label.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/linkbutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/listview.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/menu.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/misc_button.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/mouse-gesture.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/pangorenderer.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/pointer_grab.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/print.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/properties.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/radiobutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/recentchooserdialog.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/rgtk+cairo.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/scalebutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/settings.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/statusicon.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/stock.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/style_property.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/style_property.rc
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/t-gtkplug.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/t-gtksocket.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/test.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/textbuffer_serialize.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/threads.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/to_drawable.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/togglebutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/toolbar.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/tooltips.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/tree_combo.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/tree_progress.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/treemodelfilter.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/treeview.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/uimanager.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/uimanager2.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/uimanager2.xml
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/window.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/misc/xbm_cursor.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/3DRings.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/FilesQueue.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/Modeller.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/README
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/button.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/buttonbox.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/check-n.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/check-y.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/checkbutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/circles.xbm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/colorselect.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/dialog.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/entry.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/filesel.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/fontselection.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/gammacurve.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/labels.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/layout.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/marble.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/menu.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/notebook.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/pixmap.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/progressbar.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/radiobutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/range.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/reparent.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/rulers.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/sample.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/savedposition.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/scrolledwindow.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/shapedwindow.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/spinbutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/statusbar.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/test.xpm
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/testgtk.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/testgtkrc
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/testgtkrc2
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/togglebutton.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/toolbar.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/tooltips.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/sample/testgtk/wmhints.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/gtk-test-utils.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/run-test.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gc.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_color.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_display.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_event.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_gc.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_geometry.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_keymap.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_pango.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_rectangle.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_selection_data.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_window.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gdk_window_attribute.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_about_dialog.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_accel_group_entry.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_accel_key.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_allocation.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_border.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_buildable.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_builder.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_entry.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_icon_theme.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_image.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_list_store.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_menu_item.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_rc_style.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_recent_data.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_recent_filter_info.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_tree_path.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_unix_print.rb
	new file:   lib/ruby-gtk2-2.0.2/gtk2/test/test_gtk_widget.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/COPYING.LIB
	new file:   lib/ruby-gtk2-2.0.2/pango/README
	new file:   lib/ruby-gtk2-2.0.2/pango/Rakefile
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/depend
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/pango.def
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpango.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpango.h
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoanalysis.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoattribute.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoattriterator.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoattrlist.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangocairo.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangocairocontext.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangocolor.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangocontext.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoconversions.h
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangocoverage.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoengine.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofont.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontdescription.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontface.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontfamily.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontmap.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontmetrics.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontset.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangofontsetsimple.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoglyphinfo.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoglyphitem.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoglyphstring.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangogravity.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoitem.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangolanguage.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangolayout.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangolayoutiter.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangolayoutline.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangologattr.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangomatrix.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoprivate.h
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangorectangle.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangorenderer.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoscript.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangoscriptiter.c
	new file:   lib/ruby-gtk2-2.0.2/pango/ext/pango/rbpangotabarray.c
	new file:   lib/ruby-gtk2-2.0.2/pango/extconf.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/lib/pango.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/patches/harfbuzz-0.9.17-disable-uniscribe.diff
	new file:   lib/ruby-gtk2-2.0.2/pango/patches/pango-1.34.0-enable-fc-font.diff
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/attribute.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/break.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/gdk_layout.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/glyphstring.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/item.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/label.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/layout.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/pango_cairo.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/parse.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/sample.txt
	new file:   lib/ruby-gtk2-2.0.2/pango/sample/script.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/pango-test-utils.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/run-test.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-analysis.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-attribute.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-color.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-language.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-log-attr.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-matrix.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test-rectangle.rb
	new file:   lib/ruby-gtk2-2.0.2/pango/test/test_layout.rb
	new file:   lib/ruby-gtk2-2.0.2/run-test.rb
This commit is contained in:
Quentin
2013-12-17 11:20:08 +01:00
parent 2e835fac51
commit 26e8968796
929 changed files with 121236 additions and 0 deletions

View File

@ -0,0 +1,18 @@
install-so: install-headers
install-headers:
$(INSTALL_DATA) $(srcdir)/rbglib.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbglibdeprecated.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbglib2conversions.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbgutil.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbgutil_list.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbgutildeprecated.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbgobject.h $(RUBYARCHDIR)
$(INSTALL_DATA) $(srcdir)/rbgcompat.h $(RUBYARCHDIR)
$(INSTALL_DATA) glib-enum-types.h $(RUBYARCHDIR)
install: install-pc
install-pc:
if test -n "$(pkgconfigdir)"; then \
$(MAKEDIRS) $(pkgconfigdir); \
$(INSTALL_DATA) ruby-glib2.pc $(pkgconfigdir); \
fi

View File

@ -0,0 +1,78 @@
=begin
extconf.rb for Ruby/GLib extention library
=end
require 'pathname'
base_dir = Pathname(__FILE__).dirname.parent.parent.expand_path
mkmf_gnome2_dir = base_dir + 'lib'
$LOAD_PATH.unshift(mkmf_gnome2_dir.to_s)
module_name = "glib2"
package_id = "gobject-2.0"
require 'mkmf-gnome2'
setup_win32(module_name, base_dir)
unless required_pkg_config_package(package_id,
:debian => "libglib2.0-dev",
:redhat => "glib2-devel",
:homebrew => "glib",
:macports => "glib2")
exit(false)
end
PKGConfig.have_package('gthread-2.0')
have_header("unistd.h")
have_header("io.h")
glib_header = "glib.h"
have_func("g_spawn_close_pid", glib_header)
have_func("g_thread_init", glib_header)
have_func("g_main_depth", glib_header)
have_func("g_listenv", glib_header)
ruby_header = "ruby.h"
have_func("rb_check_array_type", ruby_header)
have_func("rb_check_hash_type", ruby_header)
have_func("rb_exec_recursive", ruby_header)
have_func("rb_errinfo", ruby_header)
have_func("rb_sourcefile", ruby_header)
have_func("rb_sourceline", ruby_header)
have_func("ruby_set_current_source", ruby_header)
have_func("rb_thread_blocking_region", ruby_header)
have_func("ruby_native_thread_p", ruby_header)
have_func("rb_thread_call_with_gvl", ruby_header)
have_func("rb_str_new_cstr", ruby_header)
have_func("rb_gc_register_mark_object", ruby_header)
have_var("curr_thread", [ruby_header, "node.h"])
have_var("rb_curr_thread", [ruby_header, "node.h"])
create_pkg_config_file("Ruby/GLib2", package_id)
enum_types_prefix = "glib-enum-types"
include_paths = PKGConfig.cflags_only_I("glib-2.0")
headers = include_paths.split.inject([]) do |result, path|
result + Dir.glob(File.join(path.sub(/^-I/, ""), "glib", "*.h"))
end.reject do |file|
/g(iochannel|main|scanner)\.h/ =~ file
end
include_paths = PKGConfig.cflags_only_I("gobject-2.0")
headers = include_paths.split.inject(headers) do |result, path|
result + Dir.glob(File.join(path.sub(/^-I/, ""), "gobject", "gsignal.h"))
end
glib_mkenums(enum_types_prefix, headers, "G_TYPE_", ["glib-object.h"])
$defs << "-DRUBY_GLIB2_COMPILATION"
create_makefile(module_name)
pkg_config_dir = with_config("pkg-config-dir")
if pkg_config_dir.is_a?(String)
File.open("Makefile", "ab") do |makefile|
makefile.puts
makefile.puts("pkgconfigdir=#{pkg_config_dir}")
end
end

View File

@ -0,0 +1,144 @@
EXPORTS
Init_glib2
mGLib DATA
rbgobj_cType DATA
rbgobj_id_children DATA
rbgobj_add_relative
rbgobj_invalidate_relatives
rbgobj_add_relative_removable
rbgobj_get_relative_removable
rbgobj_remove_relative
rbgobj_remove_relative_all
rbgobj_define_class
rbgobj_define_class_dynamic
rbgobj_register_mark_func
rbgobj_register_free_func
rbgobj_instance_from_ruby_object
rbgobj_ruby_object_from_instance
rbgobj_ruby_object_from_instance2
rbgobj_ruby_object_from_instance_with_unref
rbgobj_get_ruby_object_from_gobject
rbgobj_create_object
rbgobj_gobject_new
rbgobj_gobject_initialize
rbgobj_boxed_create
rbgobj_boxed_get
rbgobj_boxed_get_default
rbgobj_boxed_not_copy_obj
rbgobj_boxed_unown
rbgobj_make_boxed
rbgobj_make_boxed_raw
rbgobj_make_boxed_default
rbgobj_add_abstract_but_create_instance_class
rbgobj_gtype_get
rbgobj_gtype_new
rbgobj_gvalue_to_rvalue
rbgobj_gvalue_to_rvalue_unset
rbgobj_rvalue_to_gvalue
rbgobj_initialize_gvalue
rbgobj_initialize_object
rbgobj_lookup_class
rbgobj_lookup_class_by_gtype
rbgobj_gtype_to_ruby_class
rbgobj_ptr2cptr
rbgobj_ptr_new
rbgobj_make_enum
rbgobj_get_enum
rbgobj_make_flags
rbgobj_get_flags
rbgobj_register_g2r_func
rbgobj_register_r2g_func
rbgobj_register_class
rbgobj_register_property_getter
rbgobj_register_property_setter
rbgobj_set_signal_func
rbgobj_get_signal_func
rbgobj_add_constants
rbgobj_constant_remap
rbgobj_signal_wrap
g_rclosure_new
g_rclosure_attach
g_rclosure_set_tag
rbgobj_ruby_value_get_type
g_value_get_ruby_value
g_value_set_ruby_value
g_key_file_get_type
rbg_rval_inspect
rbg_string_value_ptr
rbg_rval2cstr
rbg_rval2cstr_accept_nil
rbg_rval2cstr_accept_symbol
rbg_rval2cstr_accept_symbol_accept_nil
rbg_rval2glibid
rbg_cstr2rval
rbg_cstr2rval_len
rbg_cstr2rval_len_free
rbg_cstr2rval_with_encoding
rbg_cstr2rval_len_with_encoding
rbg_cstr2rval_free
rbg_cstr2rval_with_free
rbg_filename_to_ruby
rbg_filename_to_ruby_free
rbg_filename_from_ruby
rbg_filename_gslist_to_array_free
rbg_rval2strv
rbg_rval2strv_accept_nil
rbg_rval2strv_dup
rbg_rval2strv_dup_accept_nil
rbg_strv2rval
rbg_strv2rval_free
rbg_rval2gbooleans
rbg_rval2gints
rbg_rval2gint8s
rbg_rval2guint8s
rbg_rval2guint16s
rbg_rval2guint32s
rbg_rval2gdoubles
rbg_gints2rval
rbg_gints2rval_free
rbg_glist2rval
rbg_gslist2rval
rbg_glist2rval_with_type
rbg_gslist2rval_with_type
rbg_define_method
rbg_define_singleton_method
rbg_to_array
rbg_to_hash
rbg_check_array_type
rbg_check_hash_type
rbg_scan_options
rbgutil_id_module_eval DATA
rbgutil_def_setters
rbgutil_glist2ary
rbgutil_glist2ary_boxed
rbgutil_glist2ary_string
rbgutil_glist2ary_and_free
rbgutil_glist2ary_boxed_and_free
rbgutil_glist2ary_string_and_free
rbgutil_gslist2ary
rbgutil_gslist2ary_boxed
rbgutil_gslist2ary_and_free
rbgutil_gslist2ary_boxed_and_free
rbgutil_set_properties
rbgutil_glibid_r2g_func
rbgutil_sym_g2r_func
rbgutil_protect
rbgutil_invoke_callback
rbgutil_start_callback_dispatch_thread
rbgutil_stop_callback_dispatch_thread
rbgutil_string_set_utf8_encoding
rbgutil_key_equal
rbgerr_define_gerror
rbgerr_gerror2exception
rbgobj_convert_define
rbgobj_gc_mark_gvalue
rbgobj_gc_mark_instance
rbglib_num_to_uint64
rbglib_uint64_to_num
rbglib_num_to_int64
rbglib_int64_to_num
g_source_get_type
g_connect_flags_get_type
g_poll_fd_get_type
g_signal_flags_get_type

View File

@ -0,0 +1,29 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2007 Ruby-GNOME2 Project Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGCOMPAT_H__
#define __RBGCOMPAT_H__
G_BEGIN_DECLS
G_END_DECLS
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2005 Ruby-GNOME2 Project
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include <glib.h>
#include "ruby.h"
#include "rbglibdeprecated.h"
#include "rbglib2conversions.h"
#ifndef __RBGLIB_H__
#define __RBGLIB_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define RBGLIB_MAJOR_VERSION 2
#define RBGLIB_MINOR_VERSION 0
#define RBGLIB_MICRO_VERSION 2
#ifndef RSTRING_PTR
# define RSTRING_PTR(s) (RSTRING(s)->ptr)
# define RSTRING_LEN(s) (RSTRING(s)->len)
#endif
#ifndef RARRAY_PTR
# define RARRAY_PTR(s) (RARRAY(s)->ptr)
# define RARRAY_LEN(s) (RARRAY(s)->len)
#endif
#ifndef DBL2NUM
# define DBL2NUM(v) (rb_float_new(v))
#endif
#if ! GLIB_CHECK_VERSION(2,4,0)
typedef int GPid;
#endif
#ifndef G_SOURCE_REMOVE
# define G_SOURCE_REMOVE FALSE
#endif
#ifndef G_SOURCE_CONTINUE
# define G_SOURCE_CONTINUE TRUE
#endif
#define RBG_INSPECT(object) (rbg_rval_inspect(object))
#define RVAL2CSTR(v) (rbg_rval2cstr(&(v)))
#define RVAL2CSTR_ACCEPT_NIL(v) (rbg_rval2cstr_accept_nil(&(v)))
#define RVAL2CSTR2(v) (RVAL2CSTR_ACCEPT_NIL(v))
#define RVAL2CSTR_ACCEPT_SYMBOL(v) (rbg_rval2cstr_accept_symbol(&(v)))
#define RVAL2CSTR_ACCEPT_SYMBOL_ACCEPT_NIL(v) (rbg_rval2cstr_accept_symbol_accept_nil(&(v)))
#define RVAL2GLIBID(v, buf) (rbg_rval2glibid(&(v), &(buf), FALSE))
#define RVAL2GLIBID_ACCEPT_NIL(v, buf) (rbg_rval2glibid(&(v), &(buf), TRUE))
#define CSTR2RVAL(s) (rbg_cstr2rval(s))
#define CSTR2RVAL_LEN(s, l) (rbg_cstr2rval_len(s, l))
#define CSTR2RVAL_LEN_FREE(s, l) (rbg_cstr2rval_len_free(s, l))
#define CSTR2RVAL_ENC(s, e) (rbg_cstr2rval_with_encoding(s, e))
#define CSTR2RVAL_LEN_ENC(s, l, e) (rbg_cstr2rval_len_with_encoding(s, l, e))
#define CSTR2RVAL_FREE(s) (rbg_cstr2rval_free(s))
#define CSTR2RVAL2(s) (CSTR2RVAL_FREE(s))
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
# define CSTR2RVAL_LEN_UCS4(s, l) (CSTR2RVAL_LEN_ENC(s, l, "UTF-32LE"))
# define CSTR2RVAL_LEN_UTF16(s, l) (CSTR2RVAL_LEN_ENC(s, l, "UTF-16LE"))
#else
# define CSTR2RVAL_LEN_UCS4(s, l) (CSTR2RVAL_LEN_ENC(s, l, "UTF-32BE"))
# define CSTR2RVAL_LEN_UTF16(s, l) (CSTR2RVAL_LEN_ENC(s, l, "UTF-16BE"))
#endif
#define RVAL2CSTRFILENAME(v) (rbg_filename_from_ruby(v))
#define CSTRFILENAME2RVAL(s) (rbg_filename_to_ruby(s))
#define CSTRFILENAME2RVAL_FREE(s) (rbg_filename_to_ruby_free(s))
#define RVAL2STRS(ary, n) rbg_rval2strv(&(ary), &(n))
#define RVAL2STRS_ACCEPT_NIL(ary, n) rbg_rval2strv_accept_nil(&(ary), &(n))
#define RVAL2STRV(ary) rbg_rval2strv(&(ary), NULL)
#define RVAL2STRV_ACCEPT_NIL(ary) rbg_rval2strv_accept_nil(&(ary), NULL)
#define RVAL2STRS_DUP(ary, n) rbg_rval2strv_dup(&(ary), &(n))
#define RVAL2STRS_DUP_ACCEPT_NIL(ary, n) rbg_rval2strv_dup_accept_nil(&(ary), &(n))
#define RVAL2STRV_DUP(ary) rbg_rval2strv_dup(&(ary), NULL)
#define RVAL2STRV_DUP_ACCEPT_NIL(ary) rbg_rval2strv_dup_accept_nil(&(ary), NULL)
#define STRV2RVAL(strings) rbg_strv2rval(strings)
#define STRV2RVAL_FREE(strings) rbg_strv2rval_free(strings)
#define RVAL2GBOOLEANS(ary, n) rbg_rval2gbooleans(&(ary), &(n))
#define RVAL2GINTS(ary, n) rbg_rval2gints(&(ary), &(n))
#define RVAL2GINT8S(ary, n) rbg_rval2gint8s(&(ary), &(n))
#define RVAL2GUINT8S(ary, n) rbg_rval2guint8s(&(ary), &(n))
#define RVAL2GUINT16S(ary, n) rbg_rval2guint16s(&(ary), &(n))
#define RVAL2GUINT32S(ary, n) rbg_rval2guint32s(&(ary), &(n))
#define RVAL2GDOUBLES(ary, n) rbg_rval2gdoubles(&(ary), &(n))
#define GINTS2RVAL(ary, n) rbg_gints2rval(ary, n)
#define GINTS2RVAL_FREE(ary, n) rbg_gints2rval(ary, n)
#define CBOOL2RVAL(b) ((b) ? Qtrue : Qfalse)
#define RVAL2CBOOL(b) (RTEST(b))
#define GERROR2RVAL(error) (rbgerr_gerror2exception(error))
#define RG_RAISE_ERROR(error) rb_exc_raise(GERROR2RVAL(error))
#define RAISE_GERROR(error) RG_RAISE_ERROR(error) /* deprecated */
#define G_DEF_ERROR(domain, name, module, parent, gtype) \
rbgerr_define_gerror(domain, name, module, parent, gtype)
#define G_DEF_ERROR2(domain, name, module, parent) \
rbgerr_define_gerror(domain, name, module, parent, Qnil)
#if defined(G_PLATFORM_WIN32) && !defined(RUBY_GLIB2_STATIC_COMPILATION)
# ifdef RUBY_GLIB2_COMPILATION
# define RUBY_GLIB2_VAR __declspec(dllexport)
# else
# define RUBY_GLIB2_VAR extern __declspec(dllimport)
# endif
#else
# define RUBY_GLIB2_VAR extern
#endif
RUBY_GLIB2_VAR VALUE mGLib;
extern const gchar *rbg_rval_inspect(VALUE object);
extern gchar* rbg_string_value_ptr(volatile VALUE* ptr); /* no longer used */
extern const gchar *rbg_rval2cstr(VALUE *str);
extern const gchar *rbg_rval2cstr_accept_nil(VALUE *str);
extern const gchar *rbg_rval2cstr_accept_symbol(volatile VALUE *value);
extern const gchar *rbg_rval2cstr_accept_symbol_accept_nil(volatile VALUE *value);
extern const gchar *rbg_rval2glibid(volatile VALUE *value, volatile VALUE *buf, gboolean accept_nil);
extern VALUE rbg_cstr2rval(const gchar* str);
extern VALUE rbg_cstr2rval_len(const gchar* str, gsize len);
extern VALUE rbg_cstr2rval_len_free(gchar *str, gsize len);
extern VALUE rbg_cstr2rval_with_encoding(const gchar* str,
const gchar *encoding);
extern VALUE rbg_cstr2rval_len_with_encoding(const gchar* str, gsize len,
const gchar *encoding);
extern VALUE rbg_cstr2rval_free(gchar *str);
/* just for backward compatibility. */
extern VALUE rbg_cstr2rval_with_free(gchar *str);
VALUE rbg_filename_to_ruby(const gchar *filename);
extern VALUE rbg_filename_to_ruby_free(gchar *filename);
extern gchar *rbg_filename_from_ruby(VALUE filename);
const gchar **rbg_rval2strv(volatile VALUE *value, long *n);
const gchar **rbg_rval2strv_accept_nil(volatile VALUE *value, long *n);
gchar **rbg_rval2strv_dup(volatile VALUE *value, long *n);
gchar **rbg_rval2strv_dup_accept_nil(volatile VALUE *value, long *n);
VALUE rbg_strv2rval(const gchar **strings);
VALUE rbg_strv2rval_free(gchar **strings);
gboolean *rbg_rval2gbooleans(volatile VALUE *value, long *n);
gint *rbg_rval2gints(volatile VALUE *value, long *n);
gint8 *rbg_rval2gint8s(volatile VALUE *value, long *n);
guint8 *rbg_rval2guint8s(volatile VALUE *value, long *n);
guint16 *rbg_rval2guint16s(volatile VALUE *value, long *n);
guint32 *rbg_rval2guint32s(volatile VALUE *value, long *n);
gdouble *rbg_rval2gdoubles(volatile VALUE *value, long *n);
VALUE rbg_gints2rval(const gint *gints, long n);
VALUE rbg_gints2rval_free(gint *gints, long n);
extern VALUE rbg_to_array(VALUE object);
extern VALUE rbg_to_hash(VALUE object);
extern VALUE rbg_check_array_type(VALUE object);
extern VALUE rbg_check_hash_type(VALUE object);
extern void rbg_scan_options(VALUE options, ...);
/* rbgerror.h */
extern VALUE rbgerr_gerror2exception(GError *error);
extern VALUE rbgerr_define_gerror(GQuark domain, const gchar* name, VALUE module, VALUE parent, VALUE gtype);
extern VALUE rbglib_int64_to_num(guint64 val);
extern VALUE rbglib_uint64_to_num(guint64 val);
extern gint64 rbglib_num_to_int64(VALUE val);
extern guint64 rbglib_num_to_uint64(VALUE val);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __RBGLIB_H__ */

View File

@ -0,0 +1,55 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __GLIB2CONVERSIONS_H__
#define __GLIB2CONVERSIONS_H__
#define RVAL2GPARAMSPEC(o) (G_PARAM_SPEC(RVAL2GOBJ(o)))
#define RVAL2GCLOSURE(o) ((GClosure*)RVAL2BOXED(o, G_TYPE_CLOSURE))
#define GCLOSURE2RVAL(o) (BOXED2RVAL(o, G_TYPE_CLOSURE))
#define RVAL2GIOCHANNEL(o) ((GIOChannel*)RVAL2BOXED(o, G_TYPE_IO_CHANNEL))
#define GIOCHANNEL2RVAL(o) (BOXED2RVAL(o, G_TYPE_IO_CHANNEL))
#define RVAL2GKEYFILE(o) ((GKeyFile*)RVAL2BOXED(o, G_TYPE_KEY_FILE))
#define GKEYFILE2RVAL(o) (BOXED2RVAL(o, G_TYPE_KEY_FILE))
#define RVAL2GMAINCONTEXT(o) ((GMainContext*)RVAL2BOXED(o, G_TYPE_MAIN_CONTEXT))
#define GMAINCONTEXT2RVAL(o) (BOXED2RVAL(o, G_TYPE_MAIN_CONTEXT))
#define RVAL2GMAINLOOP(o) ((GMainLoop*)RVAL2BOXED(o, G_TYPE_MAIN_LOOP))
#define GMAINLOOP2RVAL(o) (BOXED2RVAL(o, G_TYPE_MAIN_LOOP))
#define RVAL2GPOLLFD(o) ((GPollFD*)RVAL2BOXED(o, G_TYPE_POLL_FD))
#define GPOLLFD2RVAL(o) (BOXED2RVAL(o, G_TYPE_POLL_FD))
#define RVAL2GSOURCE(o) ((GSource*)RVAL2BOXED(o, G_TYPE_SOURCE))
#define GSOURCE2RVAL(o) (BOXED2RVAL(o, G_TYPE_SOURCE))
#define RVAL2GTIMER(o) ((GTimer*)RVAL2BOXED(o, G_TYPE_TIMER))
#define GTIMER2RVAL(o) (BOXED2RVAL(o, G_TYPE_TIMER))
#define RVAL2GVALUE(o) ((GValue*)RVAL2BOXED(o, G_TYPE_VALUE))
#define GVALUE2RVAL(o) (BOXED2RVAL(o, G_TYPE_VALUE))
#define RVAL2GIOCONDITION(o) (RVAL2GFLAGS(o, G_TYPE_IO_CONDITION))
#define GIOCONDITION2RVAL(o) (GFLAGS2RVAL(o, G_TYPE_IO_CONDITION))
#define RVAL2GNORMALIZEMODE(o) (RVAL2GENUM(o, G_TYPE_NORMALIZE_MODE))
#define GNORMALIZEMODE2RVAL(o) (GENUM2RVAL(o, G_TYPE_NORMALIZE_MODE))
#define RVAL2GCONNECTFLAGS(o) (RVAL2GFLAGS(o, G_TYPE_CONNECT_FLAGS))
#define GCONNECTFLAGS2RVAL(o) (GFLAGS2RVAL(o, G_TYPE_CONNECT_FLAGS))
#define RVAL2GKEYFILEFLAGS(o) (RVAL2GFLAGS(o, G_TYPE_KEY_FILE_FLAGS))
#define GKEYFILEFLAGS2RVAL(o) (GFLAGS2RVAL(o, G_TYPE_KEY_FILE_FLAGS))
#endif /* __GLIB2CONVERSIONS_H__ */

View File

@ -0,0 +1,551 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#if GLIB_CHECK_VERSION(2,12,0)
/************************************************/
static GBookmarkFile*
bookmarkfile_copy(const GBookmarkFile* file)
{
/*
GBookmarkFile* new_file;
g_return_val_if_fail (file != NULL, NULL);
new_file = g_key_file_new();
*new_file = (GBookmarkFile*)*file;
return new_file;
*/
return (GBookmarkFile*)file;
}
static GType
g_bookmark_file_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static("GBookmarkFile",
(GBoxedCopyFunc)bookmarkfile_copy,
(GBoxedFreeFunc)g_bookmark_file_free);
return our_type;
}
/************************************************/
#define G_TYPE_BOOKMARK_FILE (g_bookmark_file_get_type())
#define RG_TARGET_NAMESPACE cBookmarkFile
#define _SELF(self) ((GBookmarkFile*)(RVAL2BOXED(self, G_TYPE_BOOKMARK_FILE)))
static VALUE
rg_initialize(VALUE self)
{
G_INITIALIZE(self, g_bookmark_file_new());
return Qnil;
}
static VALUE
rg_load_from_file(VALUE self, VALUE rbfilename)
{
gchar *filename = RVAL2CSTRFILENAME(rbfilename);
GError* error = NULL;
gboolean ret = g_bookmark_file_load_from_file(_SELF(self), filename, &error);
g_free(filename);
if (!ret)
RAISE_GERROR(error);
return self;
}
static VALUE
rg_load_from_data(VALUE self, VALUE data)
{
GError *error = NULL;
StringValue(data);
if (!g_bookmark_file_load_from_data(_SELF(self),
RSTRING_PTR(data),
RSTRING_LEN(data),
&error))
RAISE_GERROR(error);
return Qnil;
}
static VALUE
rg_load_from_data_dirs(VALUE self, VALUE file)
{
GError* error = NULL;
gboolean ret;
gchar* full_path;
ret = g_bookmark_file_load_from_data_dirs(_SELF(self),
RVAL2CSTR(file),
&full_path, &error);
if (! ret) RAISE_GERROR(error);
return full_path ? CSTR2RVAL(full_path) : Qnil;
}
static VALUE
rg_to_data(VALUE self)
{
GError* error = NULL;
gchar* data = g_bookmark_file_to_data(_SELF(self), NULL, &error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(data);
}
static VALUE
rg_to_file(VALUE self, VALUE rbfilename)
{
gchar *filename = RVAL2CSTRFILENAME(rbfilename);
GError* error = NULL;
gboolean ret = g_bookmark_file_to_file(_SELF(self), filename, &error);
g_free(filename);
if (!ret)
RAISE_GERROR(error);
return self;
}
static VALUE
rg_has_item_p(VALUE self, VALUE uri)
{
return CBOOL2RVAL(g_bookmark_file_has_item(_SELF(self),
RVAL2CSTR(uri)));
}
static VALUE
rg_has_group_p(VALUE self, VALUE uri, VALUE group)
{
GError* error = NULL;
return CBOOL2RVAL(g_bookmark_file_has_group(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(group),
&error));
}
static VALUE
rg_has_application_p(VALUE self, VALUE uri, VALUE name)
{
GError* error = NULL;
return CBOOL2RVAL(g_bookmark_file_has_application(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(name),
&error));
}
static VALUE
rg_size(VALUE self)
{
return INT2NUM(g_bookmark_file_get_size(_SELF(self)));
}
static VALUE
rg_uris(VALUE self)
{
return STRV2RVAL_FREE(g_bookmark_file_get_uris(_SELF(self), NULL));
}
static VALUE
rg_get_title(VALUE self, VALUE uri)
{
GError *error = NULL;
gchar* ret = g_bookmark_file_get_title(_SELF(self),
RVAL2CSTR(uri),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_get_description(VALUE self, VALUE uri)
{
GError *error = NULL;
gchar* ret = g_bookmark_file_get_description(_SELF(self),
RVAL2CSTR(uri),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_get_mime_type(VALUE self, VALUE uri)
{
GError *error = NULL;
gchar* ret = g_bookmark_file_get_mime_type(_SELF(self),
RVAL2CSTR(uri),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_private_p(VALUE self, VALUE uri)
{
GError *error = NULL;
gboolean ret = g_bookmark_file_get_is_private(_SELF(self),
RVAL2CSTR(uri),
&error);
if (error) RAISE_GERROR(error);
return CBOOL2RVAL(ret);
}
static VALUE
rg_get_icon(VALUE self, VALUE uri)
{
gchar* href;
gchar* mime_type;
GError *error = NULL;
gboolean ret = g_bookmark_file_get_icon(_SELF(self),
RVAL2CSTR(uri),
&href, &mime_type,
&error);
if (!ret){
if (error) RAISE_GERROR(error);
return Qnil;
}
return rb_assoc_new(CSTR2RVAL_FREE(href), CSTR2RVAL_FREE(mime_type));
}
static VALUE
rg_get_added(VALUE self, VALUE uri)
{
GError *error = NULL;
time_t ret = g_bookmark_file_get_added(_SELF(self),
RVAL2CSTR(uri),
&error);
if (!ret) RAISE_GERROR(error);
return rb_time_new(ret, 0);
}
static VALUE
rg_get_modified(VALUE self, VALUE uri)
{
GError *error = NULL;
time_t ret = g_bookmark_file_get_modified(_SELF(self),
RVAL2CSTR(uri),
&error);
if (!ret) RAISE_GERROR(error);
return rb_time_new(ret, 0);
}
static VALUE
rg_get_visited(VALUE self, VALUE uri)
{
GError *error = NULL;
time_t ret = g_bookmark_file_get_visited(_SELF(self),
RVAL2CSTR(uri),
&error);
if (!ret) RAISE_GERROR(error);
return rb_time_new(ret, 0);
}
static VALUE
rg_get_groups(VALUE self, VALUE uri)
{
gsize length;
VALUE ary;
gsize i;
GError* error = NULL;
gchar** ret = g_bookmark_file_get_groups(_SELF(self),
RVAL2CSTR(uri),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, CSTR2RVAL(ret[i]));
}
g_strfreev(ret);
return ary;
}
static VALUE
rg_get_applications(VALUE self, VALUE uri)
{
gsize length;
VALUE ary;
gsize i;
GError* error = NULL;
gchar** ret = g_bookmark_file_get_applications(_SELF(self),
RVAL2CSTR(uri),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, CSTR2RVAL(ret[i]));
}
g_strfreev(ret);
return ary;
}
static VALUE
rg_get_app_info(VALUE self, VALUE uri, VALUE name)
{
gchar* exec;
guint count;
time_t stamp;
GError* error = NULL;
gboolean ret = g_bookmark_file_get_app_info(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(name),
&exec, &count, &stamp, &error);
if (!ret) RAISE_GERROR(error);
return rb_ary_new3(3, CSTR2RVAL(exec), UINT2NUM(count), rb_time_new(stamp, 0));
}
static VALUE
rg_set_title(VALUE self, VALUE uri, VALUE title)
{
g_bookmark_file_set_title(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(title));
return self;
}
static VALUE
rg_set_description(VALUE self, VALUE uri, VALUE description)
{
g_bookmark_file_set_description(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(description));
return self;
}
static VALUE
rg_set_mime_type(VALUE self, VALUE uri, VALUE mime_type)
{
g_bookmark_file_set_mime_type(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(mime_type));
return self;
}
static VALUE
rg_set_private(VALUE self, VALUE uri, VALUE is_private)
{
g_bookmark_file_set_is_private(_SELF(self),
RVAL2CSTR(uri),
RVAL2CBOOL(is_private));
return self;
}
static VALUE
rg_set_icon(VALUE self, VALUE uri, VALUE href, VALUE mime_type)
{
g_bookmark_file_set_icon(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(href),
RVAL2CSTR(mime_type));
return self;
}
static VALUE
rg_set_added(VALUE self, VALUE uri, VALUE time)
{
g_bookmark_file_set_added(_SELF(self),
RVAL2CSTR(uri),
(time_t)NUM2LONG(rb_Integer(time)));
return self;
}
static VALUE
rg_set_groups(VALUE self, VALUE rburi, VALUE rbgroups)
{
GBookmarkFile *bookmark = _SELF(self);
const gchar *uri = RVAL2CSTR(rburi);
long n;
const gchar **groups = RVAL2STRS(rbgroups, n);
g_bookmark_file_set_groups(bookmark, uri, groups, n);
g_free(groups);
return self;
}
static VALUE
rg_set_modified(VALUE self, VALUE uri, VALUE time)
{
g_bookmark_file_set_modified(_SELF(self),
RVAL2CSTR(uri),
(time_t)NUM2LONG(rb_Integer(time)));
return self;
}
static VALUE
rg_set_visited(VALUE self, VALUE uri, VALUE time)
{
g_bookmark_file_set_visited(_SELF(self),
RVAL2CSTR(uri),
(time_t)NUM2LONG(rb_Integer(time)));
return self;
}
static VALUE
rg_set_app_info(VALUE self, VALUE uri, VALUE name, VALUE exec, VALUE count, VALUE stamp)
{
GError* error = NULL;
gboolean ret = g_bookmark_file_set_app_info(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(name),
RVAL2CSTR(exec),
NUM2INT(count),
(time_t)NUM2LONG(rb_Integer(stamp)),
&error);
if (! ret) RAISE_GERROR(error);
return self;
}
static VALUE
rg_add_group(VALUE self, VALUE uri, VALUE group)
{
g_bookmark_file_add_group(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(group));
return self;
}
static VALUE
rg_add_application(VALUE self, VALUE uri, VALUE name, VALUE exec)
{
g_bookmark_file_add_application(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(name),
RVAL2CSTR(exec));
return self;
}
static VALUE
rg_remove_group(VALUE self, VALUE uri, VALUE group)
{
GError* error = NULL;
gboolean ret = g_bookmark_file_remove_group(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(group),
&error);
if (! ret) RAISE_GERROR(error);
return self;
}
static VALUE
rg_remove_application(VALUE self, VALUE uri, VALUE name)
{
GError *error = NULL;
gboolean ret = g_bookmark_file_remove_application(_SELF(self),
RVAL2CSTR(uri),
RVAL2CSTR(name),
&error);
if (! ret) RAISE_GERROR(error);
return self;
}
static VALUE
rg_remove_item(VALUE self, VALUE uri)
{
GError *error = NULL;
gboolean ret = g_bookmark_file_remove_item(_SELF(self),
RVAL2CSTR(uri),
&error);
if (! ret) RAISE_GERROR(error);
return self;
}
static VALUE
rg_move_item(VALUE self, VALUE old_uri, VALUE new_uri)
{
GError *error = NULL;
gboolean ret = g_bookmark_file_move_item(_SELF(self),
RVAL2CSTR(old_uri),
RVAL2CSTR(new_uri),
&error);
if (! ret) RAISE_GERROR(error);
return self;
}
#endif
void
Init_glib_bookmark_file(void)
{
#if GLIB_CHECK_VERSION(2,12,0)
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_BOOKMARK_FILE, "BookmarkFile", mGLib);
G_DEF_ERROR(G_BOOKMARK_FILE_ERROR, "BookmarkFileError", mGLib,
rb_eRuntimeError, G_TYPE_BOOKMARK_FILE_ERROR);
RG_DEF_METHOD(initialize, 0);
RG_DEF_METHOD(load_from_file, 1);
RG_DEF_METHOD(load_from_data, 1);
RG_DEF_METHOD(load_from_data_dirs, 1);
RG_DEF_METHOD(to_data, 0);
RG_DEF_METHOD(to_file, 1);
RG_DEF_METHOD_P(has_item, 1);
RG_DEF_METHOD_P(has_group, 2);
RG_DEF_METHOD_P(has_application, 2);
RG_DEF_METHOD(size, 0);
RG_DEF_METHOD(uris, 0);
RG_DEF_METHOD(get_title, 1);
RG_DEF_METHOD(get_description, 1);
RG_DEF_METHOD(get_mime_type, 1);
RG_DEF_METHOD_P(private, 1);
RG_DEF_METHOD(get_icon, 1);
RG_DEF_METHOD(get_added, 1);
RG_DEF_METHOD(get_modified, 1);
RG_DEF_METHOD(get_visited, 1);
RG_DEF_METHOD(get_groups, 1);
RG_DEF_METHOD(get_applications, 1);
RG_DEF_METHOD(get_app_info, 2);
RG_DEF_METHOD(set_title, 2);
RG_DEF_METHOD(set_description, 2);
RG_DEF_METHOD(set_mime_type, 2);
RG_DEF_METHOD(set_private, 2);
RG_DEF_METHOD(set_icon, 3);
RG_DEF_METHOD(set_added, 2);
RG_DEF_METHOD(set_groups, 2);
RG_DEF_METHOD(set_modified, 2);
RG_DEF_METHOD(set_visited, 2);
RG_DEF_METHOD(set_app_info, 5);
RG_DEF_METHOD(add_group, 2);
RG_DEF_METHOD(add_application, 3);
RG_DEF_METHOD(remove_group, 2);
RG_DEF_METHOD(remove_application, 2);
RG_DEF_METHOD(remove_item, 1);
RG_DEF_METHOD(move_item, 2);
#endif
}

View File

@ -0,0 +1,197 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2009 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 KUBO Takehiro
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mGLib
static VALUE
rg_s_convert(G_GNUC_UNUSED VALUE self, VALUE str, VALUE to, VALUE from)
{
GError *err = NULL;
gchar* ret;
gsize written;
VALUE s = Qnil;
StringValue(str);
ret = g_convert(RSTRING_PTR(str), RSTRING_LEN(str),
StringValuePtr(to), StringValuePtr(from),
NULL, &written, &err);
if (err != NULL)
RAISE_GERROR(err);
s = rb_str_new(ret, written);
g_free(ret);
return s;
}
static VALUE
rg_s_locale_to_utf8(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
VALUE s = Qnil;
gchar* ret;
gsize written;
StringValue(str);
ret = g_locale_to_utf8(RSTRING_PTR(str), RSTRING_LEN(str),
NULL, &written, &err);
if (err != NULL)
RAISE_GERROR(err);
s = rb_str_new(ret, written);
g_free(ret);
return s;
}
static VALUE
rg_s_locale_from_utf8(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
VALUE s = Qnil;
gchar* ret;
gsize written;
StringValue(str);
ret = g_locale_from_utf8(RSTRING_PTR(str), RSTRING_LEN(str),
NULL, &written, &err);
if (err != NULL)
RAISE_GERROR(err);
s = rb_str_new(ret, written);
g_free(ret);
return s;
}
static VALUE
rg_s_filename_to_utf8(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
VALUE s = Qnil;
gchar* ret;
gsize written;
StringValue(str);
ret = g_filename_to_utf8(RSTRING_PTR(str), RSTRING_LEN(str),
NULL, &written, &err);
if (err != NULL)
RAISE_GERROR(err);
s = rb_str_new(ret, written);
g_free(ret);
return s;
}
static VALUE
rg_s_filename_from_utf8(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
VALUE s = Qnil;
gchar* ret;
gsize written;
StringValue(str);
ret = g_filename_from_utf8(RSTRING_PTR(str), RSTRING_LEN(str),
NULL, &written, &err);
if (err != NULL)
RAISE_GERROR(err);
s = rb_str_new(ret, written);
g_free(ret);
return s;
}
static VALUE
rg_s_filename_to_uri(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE filename, hostname, s;
GError *err = NULL;
gchar* ret;
rb_scan_args(argc, argv, "11", &filename, &hostname);
ret = g_filename_to_uri(StringValuePtr(filename),
NIL_P(hostname) ? NULL : StringValuePtr(hostname),
&err);
if (err)
RAISE_GERROR(err);
s = rb_str_new2(ret);
g_free(ret);
return s;
}
static VALUE
rg_s_filename_from_uri(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
VALUE s;
gchar* filename;
char* hostname;
filename = g_filename_from_uri(StringValuePtr(str), &hostname, &err);
if (err)
RAISE_GERROR(err);
s = rb_ary_new3(2, rb_str_new2(filename),
hostname ? rb_str_new2(hostname) : Qnil);
g_free(filename);
g_free(hostname);
return s;
}
static VALUE
rg_s_utf8_validate(G_GNUC_UNUSED VALUE self, VALUE str)
{
rb_warning("GLib.utf8_validate is deprecated. Use GLib::UTF8.validate instead.");
StringValue(str);
return CBOOL2RVAL(g_utf8_validate(RSTRING_PTR(str), RSTRING_LEN(str), NULL));
}
void
Init_glib_convert(void)
{
VALUE cCharError = G_DEF_ERROR2(G_CONVERT_ERROR, "ConvertError", RG_TARGET_NAMESPACE, rb_eIOError);
rb_define_const(cCharError, "NO_CONVERSION", INT2NUM(G_CONVERT_ERROR_NO_CONVERSION));
rb_define_const(cCharError, "ILLEGAL_SEQUENCE", INT2NUM(G_CONVERT_ERROR_ILLEGAL_SEQUENCE));
rb_define_const(cCharError, "FAILED", INT2NUM(G_CONVERT_ERROR_FAILED));
rb_define_const(cCharError, "PARTIAL_INPUT", INT2NUM(G_CONVERT_ERROR_PARTIAL_INPUT));
rb_define_const(cCharError, "BAD_URI", INT2NUM(G_CONVERT_ERROR_BAD_URI));
rb_define_const(cCharError, "NOT_ABSOLUTE_PATH", INT2NUM(G_CONVERT_ERROR_NOT_ABSOLUTE_PATH));
/* glib/gunicode.h */
/* just for backward compatibility.
Use GLib::UTF8.validate instead. */
RG_DEF_SMETHOD(utf8_validate, 1);
/* glib/gconvert.h */
RG_DEF_SMETHOD(convert, 3);
RG_DEF_SMETHOD(locale_to_utf8, 1);
RG_DEF_SMETHOD(locale_from_utf8, 1);
RG_DEF_SMETHOD(filename_to_utf8, 1);
RG_DEF_SMETHOD(filename_from_utf8, 1);
RG_DEF_SMETHOD(filename_to_uri, -1);
RG_DEF_SMETHOD(filename_from_uri, 1);
}

View File

@ -0,0 +1,99 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include <ctype.h>
static ID id_code;
static ID id_domain;
static VALUE gerror_table;
static VALUE generic_error;
VALUE
rbgerr_gerror2exception(GError *error)
{
VALUE exc = Qnil;
VALUE klass = Qnil;
if (! error){
return rb_exc_new2(rb_eRuntimeError, "GError parameter doesn't have a value.");
}
klass = rb_hash_aref(gerror_table, UINT2NUM(error->domain));
if (NIL_P(klass)) {
exc = rb_exc_new2(generic_error, error->message);
rb_ivar_set(exc, id_domain, CSTR2RVAL(g_quark_to_string(error->domain)));
rb_ivar_set(exc, id_code, INT2NUM(error->code));
} else {
exc = rb_exc_new2(klass, error->message);
rb_ivar_set(exc, id_domain, CSTR2RVAL(g_quark_to_string(error->domain)));
rb_ivar_set(exc, id_code, INT2NUM(error->code));
}
g_error_free(error);
return exc;
}
VALUE
rbgerr_define_gerror(GQuark domain, const gchar *name, VALUE module, VALUE parent, VALUE gtype)
{
VALUE klass = rb_define_class_under(module, name, parent);
rb_funcall(klass, rbgutil_id_module_eval, 1, CSTR2RVAL("def code; @code; end\n"));
rb_funcall(klass, rbgutil_id_module_eval, 1, CSTR2RVAL("def domain; @domain; end\n"));
rb_hash_aset(gerror_table, UINT2NUM(domain), klass);
if (! NIL_P(gtype)){
GEnumClass* gclass = g_type_class_ref(gtype);
guint i;
for (i = 0; i < gclass->n_values; i++) {
GEnumValue* entry = &(gclass->values[i]);
gchar* nick = g_strdup(entry->value_nick);
gchar* p;
for (p = nick; *p; p++) {
if (*p == '-')
*p = '_';
else
*p = g_ascii_toupper(*p);
}
rbgobj_define_const(klass, nick, INT2NUM(i));
g_free(nick);
}
g_type_class_unref(gclass);
}
return klass;
}
void
Init_glib_error(void)
{
id_code = rb_intern("@code");
id_domain = rb_intern("@domain");
gerror_table = rb_hash_new();
rb_global_variable(&gerror_table);
generic_error = rb_define_class_under(mGLib, "Error", rb_eRuntimeError);
rb_funcall(generic_error, rbgutil_id_module_eval, 1, CSTR2RVAL("def code; @code; end\n"));
rb_funcall(generic_error, rbgutil_id_module_eval, 1, CSTR2RVAL("def domain; @domain; end\n"));
}

View File

@ -0,0 +1,94 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE cFileError
/* Use Ruby standard libraries.
enum GFileTest;
GFileError g_file_error_from_errno (gint err_no);
gboolean g_file_get_contents (const gchar *filename,
gchar **contents,
gsize *length,
GError **error);
gboolean g_file_test (const gchar *filename,
GFileTest test);
gint g_mkstemp (gchar *tmpl);
gint g_file_open_tmp (const gchar *tmpl,
gchar **name_used,
GError **error);
gchar* g_file_read_link (const gchar *filename,
GError **error);
struct GDir;
GDir* g_dir_open (const gchar *path,
guint flags,
GError **error);
G_CONST_RETURN gchar* g_dir_read_name (GDir *dir);
void g_dir_rewind (GDir *dir);
void g_dir_close (GDir *dir);
*/
#if GLIB_CHECK_VERSION(2, 16, 0)
static VALUE
rbglib_m_format_size_for_display(G_GNUC_UNUSED VALUE self, VALUE size)
{
return CSTR2RVAL_FREE(g_format_size_for_display(NUM2INT(size)));
}
#endif
void
Init_glib_fileutils(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_ERROR2(G_FILE_ERROR, "FileError", mGLib, rb_eIOError);
rb_define_const(RG_TARGET_NAMESPACE, "EXIST", INT2NUM(G_FILE_ERROR_EXIST));
rb_define_const(RG_TARGET_NAMESPACE, "ISDIR", INT2NUM(G_FILE_ERROR_ISDIR));
rb_define_const(RG_TARGET_NAMESPACE, "ACCES", INT2NUM(G_FILE_ERROR_ACCES));
rb_define_const(RG_TARGET_NAMESPACE, "NAMETOOLONG", INT2NUM(G_FILE_ERROR_NAMETOOLONG));
rb_define_const(RG_TARGET_NAMESPACE, "NOENT", INT2NUM(G_FILE_ERROR_NOENT));
rb_define_const(RG_TARGET_NAMESPACE, "NOTDIR", INT2NUM(G_FILE_ERROR_NOTDIR));
rb_define_const(RG_TARGET_NAMESPACE, "NXIO", INT2NUM(G_FILE_ERROR_NXIO));
rb_define_const(RG_TARGET_NAMESPACE, "NODEV", INT2NUM(G_FILE_ERROR_NODEV));
rb_define_const(RG_TARGET_NAMESPACE, "ROFS", INT2NUM(G_FILE_ERROR_ROFS));
rb_define_const(RG_TARGET_NAMESPACE, "TXTBSY", INT2NUM(G_FILE_ERROR_TXTBSY));
rb_define_const(RG_TARGET_NAMESPACE, "FAULT", INT2NUM(G_FILE_ERROR_FAULT));
rb_define_const(RG_TARGET_NAMESPACE, "LOOP", INT2NUM(G_FILE_ERROR_LOOP));
rb_define_const(RG_TARGET_NAMESPACE, "NOSPC", INT2NUM(G_FILE_ERROR_NOSPC));
rb_define_const(RG_TARGET_NAMESPACE, "NOMEM", INT2NUM(G_FILE_ERROR_NOMEM));
rb_define_const(RG_TARGET_NAMESPACE, "MFILE", INT2NUM(G_FILE_ERROR_MFILE));
rb_define_const(RG_TARGET_NAMESPACE, "NFILE", INT2NUM(G_FILE_ERROR_NFILE));
rb_define_const(RG_TARGET_NAMESPACE, "BADF", INT2NUM(G_FILE_ERROR_BADF));
rb_define_const(RG_TARGET_NAMESPACE, "INVAL", INT2NUM(G_FILE_ERROR_INVAL));
rb_define_const(RG_TARGET_NAMESPACE, "PIPE", INT2NUM(G_FILE_ERROR_PIPE));
rb_define_const(RG_TARGET_NAMESPACE, "AGAIN", INT2NUM(G_FILE_ERROR_AGAIN));
rb_define_const(RG_TARGET_NAMESPACE, "INTR", INT2NUM(G_FILE_ERROR_INTR));
rb_define_const(RG_TARGET_NAMESPACE, "IO", INT2NUM(G_FILE_ERROR_IO));
rb_define_const(RG_TARGET_NAMESPACE, "PERM", INT2NUM(G_FILE_ERROR_PERM));
rb_define_const(RG_TARGET_NAMESPACE, "FAILED", INT2NUM(G_FILE_ERROR_FAILED));
#if GLIB_CHECK_VERSION(2, 16, 0)
rbg_define_singleton_method(mGLib, "format_size_for_display",
rbglib_m_format_size_for_display, 1);
#endif
}

View File

@ -0,0 +1,44 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#undef _
#include <glib/gi18n.h>
#define RG_TARGET_NAMESPACE mGLib
#if GLIB_CHECK_VERSION(2,6,0)
static VALUE
rg_s_language_names(G_GNUC_UNUSED VALUE self)
{
return STRV2RVAL((const gchar **)g_get_language_names());
}
#endif
void
Init_glib_i18n(void)
{
/* glib/gi18n.h */
#if GLIB_CHECK_VERSION(2,6,0)
RG_DEF_SMETHOD(language_names, 0);
#endif
}

View File

@ -0,0 +1,165 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2003 Masahiro Sakai
* Copyright (C) 2002 Masahiro Sakai
* Kenichi Komiya
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
static ID id_and;
static ID id_rshift;
static ID id_lshift;
static ID id_lt;
static ID id_plus;
static ID id_uminus;
static ID id_abs;
static VALUE max_PRUint32;
typedef guint64 PRUint64;
typedef gint64 PRInt64;
#define LL_ZERO G_GINT64_CONSTANT(0)
#define LL_UI2L(lhs,rhs) ((lhs)=(rhs))
#define LL_L2UI(lhs,rhs) ((lhs)=(guint32)(rhs))
#define LL_SHL(lhs,v1,v2) ((lhs)=(v1)<<(v2))
#define LL_SHR(lhs,v1,v2) ((lhs)=(v1)>>(v2))
#define LL_ADD(lhs,v1,v2) ((lhs)=(v1)+(v2))
#define LL_NEG(lhs,rhs) ((lhs)=-(rhs))
#define LL_CMP(v1,op,v2) ((v1) op (v2))
/**********************************************************************/
/*
following is ripped from rbXPCOM-0.0.3
http://www.ruby-lang.org/en/raa-list.rhtml?name=rbXPCOM
Copyright (C) 2001 Kenichi Komiya <kom@mail1.accsnet.ne.jp>
*/
static PRUint64
RubyTo64BitInt(VALUE aRuby)
{
VALUE bitMask = max_PRUint32;
VALUE lo = rb_funcall(aRuby, id_and, 1, bitMask);
VALUE hi = rb_funcall(aRuby, id_rshift, 1, INT2FIX(32));
PRUint64 result, hi64, lo64;
LL_UI2L(hi64, NUM2UINT(hi));
LL_UI2L(lo64, NUM2UINT(lo));
LL_SHL(result, hi64, 32);
LL_ADD(result, result, lo64);
return result;
}
static inline PRUint64
RubyToPRUint64(VALUE aRuby)
{
return RubyTo64BitInt(aRuby);
}
static PRInt64
RubyToPRInt64(VALUE aRuby)
{
if(RVAL2CBOOL(rb_funcall(aRuby, id_lt, 1, INT2FIX(0))))
{
VALUE absRuby = rb_funcall(aRuby, id_abs, 0);
PRInt64 result;
LL_NEG(result, RubyTo64BitInt(absRuby));
return result;
} else
return (PRInt64)RubyTo64BitInt(aRuby);
}
static VALUE
RubyFrom64BitInt(PRUint64 aNative)
{
PRUint64 lo64, hi64;
LL_L2UI(lo64, aNative);
LL_SHR(hi64, aNative, 32);
{
VALUE lo = UINT2NUM(lo64);
VALUE hi = UINT2NUM(hi64);
VALUE hiRuby = rb_funcall(hi, id_lshift, 1, INT2FIX(32));
return rb_funcall(hiRuby, id_plus, 1, lo);
}
}
static inline VALUE
PRUint64ToRuby(PRUint64 aNative)
{
return RubyFrom64BitInt(aNative);
}
static VALUE
PRInt64ToRuby(PRInt64 aNative)
{
if(LL_CMP(aNative, <, LL_ZERO))
{
PRUint64 abs64;
LL_NEG(abs64, aNative);
return rb_funcall(RubyFrom64BitInt(abs64), id_uminus, 0);
}
else
return RubyFrom64BitInt((PRUint64)aNative);
}
/* end of ripping */
/**********************************************************************/
VALUE
rbglib_int64_to_num(guint64 val)
{
return PRInt64ToRuby(val);
}
VALUE
rbglib_uint64_to_num(guint64 val)
{
return PRUint64ToRuby(val);
}
gint64
rbglib_num_to_int64(VALUE val)
{
return RubyToPRInt64(val);
}
guint64
rbglib_num_to_uint64(VALUE val)
{
return RubyToPRUint64(val);
}
/**********************************************************************/
void
Init_glib_int64(void)
{
id_and = rb_intern("&");
id_rshift = rb_intern(">>");
id_lshift = rb_intern("<<");
id_lt = rb_intern("<");
id_plus = rb_intern("+");
id_uminus = rb_intern("-@");
id_abs = rb_intern("abs");
rb_global_variable(&max_PRUint32);
max_PRUint32 = UINT2NUM(0xffffffffL);
}

View File

@ -0,0 +1,30 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2012 Ruby-GNOME2 Project Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
void
Init_glib_io_constants(void)
{
VALUE RG_TARGET_NAMESPACE = mGLib;
/* GIOCondition */
G_DEF_CLASS(G_TYPE_IO_CONDITION, "IOCondition", RG_TARGET_NAMESPACE);
}

View File

@ -0,0 +1,824 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
static ID id_call;
static ID id_puts;
static ID id_unpack;
static VALUE default_rs;
#define RG_TARGET_NAMESPACE cIOChannel
#define _SELF(s) ((GIOChannel*)RVAL2BOXED(s, G_TYPE_IO_CHANNEL))
static void
ioc_error(GIOStatus status, GError *err)
{
if (err != NULL) RAISE_GERROR(err);
if (status == G_IO_STATUS_EOF){
rb_raise(rb_eEOFError, "End of file reached");
} else if (status == G_IO_STATUS_AGAIN){
rb_raise(rb_eRuntimeError, "G_IO_STATUS_AGAIN");
} else if (status == G_IO_STATUS_NORMAL){
/* Do nothing */
} else {
rb_raise(rb_eRuntimeError, "An error occured. status = %d\n", status);
}
}
static VALUE
rg_initialize(gint argc, VALUE *argv, VALUE self)
{
VALUE arg1, arg2;
GIOChannel* io = NULL;
rb_secure(4);
rb_scan_args(argc, argv, "11", &arg1, &arg2);
if (TYPE(arg1) != T_STRING){
gint fd;
if (TYPE(arg1) == T_FIXNUM){
fd = NUM2INT(arg1);
} else {
fd = NUM2INT(rb_funcall(arg1, rb_intern("to_i"), 0));
}
#ifdef G_OS_UNIX
io = g_io_channel_unix_new(fd);
#elif defined(G_OS_WIN32)
io = g_io_channel_win32_new_fd(fd);
#else
rb_raise(rb_eRuntimeError, "GLib::IOChannel.new(fd) is supported on UNIX environment only");
#endif
} else {
GError* err = NULL;
io = g_io_channel_new_file(RVAL2CSTR(arg1),
NIL_P(arg2) ? "r" : RVAL2CSTR(arg2), &err);
if (err != NULL) RAISE_GERROR(err);
}
G_INITIALIZE(self, io);
return Qnil;
}
static VALUE
ioc_close(VALUE self)
{
GError* err = NULL;
GIOStatus status = g_io_channel_shutdown(_SELF(self), TRUE, &err);
ioc_error(status, err);
return self;
}
static VALUE
rg_s_open(gint argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE arg1, arg2;
VALUE rio;
GIOChannel* io = NULL;
rb_scan_args(argc, argv, "11", &arg1, &arg2);
if (TYPE(arg1) == T_FIXNUM){
#ifdef G_OS_UNIX
io = g_io_channel_unix_new(NUM2INT(arg1));
#elif defined(G_OS_WIN32)
io = g_io_channel_win32_new_fd(NUM2INT(arg1));
#else
rb_raise(rb_eRuntimeError,
"GLib::IOChannel.new(fd) is supported on "
"UNIX and Windows environment only");
#endif
} else {
GError* err = NULL;
io = g_io_channel_new_file(RVAL2CSTR(arg1),
NIL_P(arg2) ? "r" : RVAL2CSTR(arg2), &err);
if (err != NULL) RAISE_GERROR(err);
}
rio = BOXED2RVAL(io, G_TYPE_IO_CHANNEL);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, rio, ioc_close, rio);
}
return rio;
}
static VALUE
rg_fileno(VALUE self)
{
#ifdef G_OS_UNIX
return INT2NUM(g_io_channel_unix_get_fd(_SELF(self)));
#elif defined(G_OS_WIN32)
return INT2NUM(g_io_channel_win32_get_fd(_SELF(self)));
#else
rb_warn("GLib::IOChannel#fd is supported on "
"UNIX and Windows environment only.");
return Qnil;
#endif
}
/* Don't need this
void g_io_channel_init (GIOChannel *channel);
*/
static VALUE
rg_read(gint argc, VALUE *argv, VALUE self)
{
VALUE rbcount;
gsize count;
gchar *buffer;
gsize bytes_read;
GIOChannel *channel = _SELF(self);
GError *error = NULL;
GIOStatus status;
rb_scan_args(argc, argv, "01", &rbcount);
if (NIL_P(rbcount)) {
status = g_io_channel_read_to_end(channel, &buffer, &bytes_read, &error);
ioc_error(status, error);
return buffer != NULL ? CSTR2RVAL_LEN_FREE(buffer, bytes_read) : CSTR2RVAL("");
}
count = NUM2UINT(rbcount);
buffer = g_new(gchar, count);
memset(buffer, '\0', count);
status = g_io_channel_read_chars(channel, buffer, count, &bytes_read, &error);
if (status == G_IO_STATUS_NORMAL)
return CSTR2RVAL_LEN_FREE(buffer, bytes_read);
else if (status == G_IO_STATUS_EOF)
return CSTR2RVAL("");
ioc_error(status, error);
/* Not reached. */
return Qnil;
}
static VALUE
rg_readchar(VALUE self)
{
gunichar thechar;
GError* err = NULL;
GIOStatus status = g_io_channel_read_unichar(_SELF(self), &thechar, &err);
ioc_error(status, err);
return UINT2NUM(thechar);
}
static VALUE
rg_getc(VALUE self)
{
gunichar thechar;
GError* err = NULL;
VALUE ret;
GIOStatus status = g_io_channel_read_unichar(_SELF(self), &thechar, &err);
if (status == G_IO_STATUS_EOF){
ret = Qnil;
} else {
ioc_error(status, err);
ret = UINT2NUM(thechar);
}
return ret;
}
static VALUE
rg_each_char(VALUE self)
{
if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "called without a block");
}
while (TRUE){
gunichar thechar;
GError* err = NULL;
GIOStatus status = g_io_channel_read_unichar(_SELF(self), &thechar, &err);
if (status == G_IO_STATUS_EOF){
break;
} else {
ioc_error(status, err);
rb_yield(UINT2NUM(thechar));
}
}
return self;
}
static VALUE
rg_readline(gint argc, VALUE *argv, VALUE self)
{
gchar* str;
VALUE line_term, ret;
GIOStatus status;
GError* err = NULL;
const gchar* old_line_term = NULL;
gint old_line_term_len;
rb_scan_args(argc, argv, "01", &line_term);
if (! NIL_P(line_term)){
StringValue(line_term);
old_line_term = g_io_channel_get_line_term(_SELF(self), &old_line_term_len);
g_io_channel_set_line_term(_SELF(self), RVAL2CSTR(line_term),
RSTRING_LEN(line_term));
}
status = g_io_channel_read_line(_SELF(self), &str, NULL, NULL, &err);
if (! NIL_P(line_term)){
g_io_channel_set_line_term(_SELF(self), old_line_term, old_line_term_len);
}
ioc_error(status, err);
ret = str ? CSTR2RVAL(str) : CSTR2RVAL("");
g_free(str);
return ret;
}
static VALUE
rg_gets(gint argc, VALUE *argv, VALUE self)
{
gchar* str;
VALUE line_term, ret;
GIOStatus status;
GError* err = NULL;
const gchar* old_line_term = NULL;
gint old_line_term_len;
rb_scan_args(argc, argv, "01", &line_term);
if (! NIL_P(line_term)){
StringValue(line_term);
old_line_term = g_io_channel_get_line_term(_SELF(self), &old_line_term_len);
g_io_channel_set_line_term(_SELF(self), RVAL2CSTR(line_term),
RSTRING_LEN(line_term));
}
status = g_io_channel_read_line(_SELF(self), &str, NULL, NULL, &err);
if (! NIL_P(line_term)){
g_io_channel_set_line_term(_SELF(self), old_line_term, old_line_term_len);
}
if (status == G_IO_STATUS_EOF){
ret = Qnil;
} else {
ioc_error(status, err);
ret = str ? CSTR2RVAL(str) : CSTR2RVAL("");
}
g_free(str);
return ret;
}
/* Internal use only */
static VALUE
ioc_set_line_term(VALUE args)
{
VALUE self = RARRAY_PTR(args)[0];
VALUE doit = RARRAY_PTR(args)[1];
VALUE line_term = RARRAY_PTR(args)[2];
if (doit == Qtrue){
StringValue(line_term);
g_io_channel_set_line_term(_SELF(self), RVAL2CSTR(line_term),
RSTRING_LEN(line_term));
}
return self;
}
static VALUE
rg_each(gint argc, VALUE *argv, VALUE self)
{
gchar* str;
VALUE line_term;
GIOStatus status;
GError* err = NULL;
GIOChannel *channel;
const gchar* old_line_term = NULL;
gint old_line_term_len;
if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "called without a block");
}
rb_scan_args(argc, argv, "01", &line_term);
channel = _SELF(self);
if (!NIL_P(line_term)) {
StringValue(line_term);
old_line_term = g_io_channel_get_line_term(channel, &old_line_term_len);
g_io_channel_set_line_term(channel, RVAL2CSTR(line_term),
RSTRING_LEN(line_term));
}
while (TRUE) {
status = g_io_channel_read_line(channel, &str, NULL, NULL, &err);
if (status == G_IO_STATUS_EOF) {
break;
} else {
VALUE rstr;
ioc_error(status, err);
if (str) {
rstr = CSTR2RVAL(str);
} else {
rstr = CSTR2RVAL("");
}
g_free(str);
rb_ensure(rb_yield, rstr, ioc_set_line_term,
rb_ary_new3(3, self,
NIL_P(line_term) ? Qfalse : Qtrue,
CSTR2RVAL(old_line_term)));
}
}
return self;
}
/* Don't need this.
GIOStatus g_io_channel_read_line_string (GIOChannel *channel,
GString *buffer,
gsize *terminator_pos,
GError **error);
*/
/* Use GLib::IOChannel#read instead.
static VALUE
ioc_read_to_end(VALUE self)
{
gchar* str;
gsize length;
VALUE ret;
GError* err = NULL;
GIOStatus status = g_io_channel_read_to_end(_SELF(self), &str,
&length, &err);
ioc_error(status, err);
ret = str ? rb_str_new(str, length) : CSTR2RVAL("");
g_free(str);
return ret;
}
*/
static VALUE
rg_write(VALUE self, VALUE buf)
{
gssize count;
gsize bytes_written;
GIOStatus status;
GError* err = NULL;
rb_secure(4);
buf = rb_obj_as_string(buf);
StringValue(buf);
count = RSTRING_LEN(buf);
status = g_io_channel_write_chars(_SELF(self), RVAL2CSTR(buf), count, &bytes_written, &err);
ioc_error(status, err);
return UINT2NUM(bytes_written);
}
static VALUE
rg_putc(VALUE self, VALUE thechar)
{
GError* err = NULL;
GIOStatus status;
gunichar unichar;
rb_secure(4);
if (TYPE(thechar) == T_FIXNUM) {
unichar = NUM2UINT(thechar);
} else {
VALUE ary = rb_funcall(thechar, id_unpack, 1, CSTR2RVAL("U"));
unichar = NUM2UINT(RARRAY_PTR(ary)[0]);
}
status = g_io_channel_write_unichar(_SELF(self), unichar, &err);
ioc_error(status, err);
return self;
}
static VALUE
rg_flush(VALUE self)
{
GError* err = NULL;
GIOStatus status = g_io_channel_flush(_SELF(self), &err);
ioc_error(status, err);
return self;
}
static VALUE
rg_seek(gint argc, VALUE *argv, VALUE self)
{
VALUE ofs, type;
GIOStatus status;
GError* err = NULL;
GSeekType gtype = G_SEEK_SET;
rb_scan_args(argc, argv, "11", &ofs, &type);
if (!NIL_P(type))
gtype = NUM2INT(type);
status = g_io_channel_seek_position(_SELF(self), NUM2INT(ofs),
gtype, &err);
ioc_error(status, err);
return self;
}
static VALUE
rg_set_pos(VALUE self, VALUE pos)
{
GError* err = NULL;
GIOStatus status = g_io_channel_seek_position(_SELF(self), NUM2INT(pos),
G_SEEK_SET, &err);
ioc_error(status, err);
return self;
}
static VALUE
rg_close(gint argc, VALUE *argv, VALUE self)
{
VALUE flush;
GError* err = NULL;
gboolean gflush = TRUE;
GIOStatus status;
rb_scan_args(argc, argv, "01", &flush);
if (!NIL_P(flush)){
gflush = RVAL2CBOOL(flush);
}
status = g_io_channel_shutdown(_SELF(self), gflush, &err);
ioc_error(status, err);
return self;
}
static VALUE
rg_create_watch(VALUE self, VALUE condition)
{
return BOXED2RVAL(g_io_create_watch(_SELF(self), NUM2INT(condition)),
G_TYPE_SOURCE);
}
static gboolean
io_func(GIOChannel *source, GIOCondition condition, gpointer func)
{
return RVAL2CBOOL(rb_funcall((VALUE)func, id_call, 2,
BOXED2RVAL(source, G_TYPE_IO_CHANNEL),
INT2NUM(condition)));
}
static VALUE
rg_add_watch(VALUE self, VALUE condition)
{
VALUE func = rb_block_proc();
G_RELATIVE(self, func);
return UINT2NUM(g_io_add_watch(_SELF(self), NUM2INT(condition),
(GIOFunc)io_func, (gpointer)func));
}
/* Don't need this
guint g_io_add_watch_full (GIOChannel *channel,
gint priority,
GIOCondition condition,
GIOFunc func,
gpointer user_data,
GDestroyNotify notify);
*/
static VALUE
rg_buffer_size(VALUE self)
{
return UINT2NUM(g_io_channel_get_buffer_size(_SELF(self)));
}
static VALUE
rg_set_buffer_size(VALUE self, VALUE buffer_size)
{
g_io_channel_set_buffer_size(_SELF(self), NUM2UINT(buffer_size));
return self;
}
static VALUE
rg_buffer_condition(VALUE self)
{
return INT2NUM(g_io_channel_get_buffer_condition(_SELF(self)));
}
static VALUE
rg_flags(VALUE self)
{
return INT2NUM(g_io_channel_get_flags(_SELF(self)));
}
static VALUE
rg_set_flags(VALUE self, VALUE flags)
{
GError* err = NULL;
GIOStatus status = g_io_channel_set_flags(_SELF(self),
NUM2INT(flags), &err);
ioc_error(status, err);
return self;
}
/* Use them with GLib::IOChannel#gets, #readline, #readlines
static VALUE
ioc_get_line_term(VALUE self)
{
gint length;
const gchar* ret = g_io_channel_get_line_term(_SELF(self), &length);
if (ret) {
if (length < 0) {
return CSTR2RVAL(ret);
} else {
return rb_str_new(ret, length);
}
}
return Qnil;
}
static VALUE
ioc_set_line_term(VALUE self, VALUE line_term)
{
StringValue(line_term);
g_io_channel_set_line_term(_SELF(self), RVAL2CSTR(line_term),
RSTRING_LEN(line_term));
return self;
}
*/
static VALUE
rg_buffered(VALUE self)
{
return CBOOL2RVAL(g_io_channel_get_buffered(_SELF(self)));
}
static VALUE
rg_set_buffered(VALUE self, VALUE buffered)
{
g_io_channel_set_buffered(_SELF(self), RVAL2CBOOL(buffered));
return self;
}
static VALUE
rg_encoding(VALUE self)
{
return CSTR2RVAL(g_io_channel_get_encoding(_SELF(self)));
}
static VALUE
rg_set_encoding(VALUE self, VALUE encoding)
{
GError* err = NULL;
GIOStatus status;
status = g_io_channel_set_encoding(_SELF(self),
RVAL2CSTR_ACCEPT_NIL(encoding),
&err);
ioc_error(status, err);
return self;
}
/* Don't we need them ?
gboolean g_io_channel_get_close_on_unref (GIOChannel *channel);
void g_io_channel_set_close_on_unref (GIOChannel *channel,
gboolean do_close);
*/
/* Deprecated
GIOError g_io_channel_read (GIOChannel *channel,
gchar *buf,
gsize count,
gsize *bytes_read);
enum GIOError;
GIOError g_io_channel_write (GIOChannel *channel,
const gchar *buf,
gsize count,
gsize *bytes_written);
GIOError g_io_channel_seek (GIOChannel *channel,
gint64 offset,
GSeekType type);
void g_io_channel_close (GIOChannel *channel);
*/
/*
* Stolen some convenient methods from io.c
*/
static VALUE
rg_printf(int argc, VALUE *argv, VALUE self)
{
rg_write(self, rb_f_sprintf(argc, argv));
return Qnil;
}
static VALUE
ioc_puts_ary(VALUE ary, VALUE out, int recur)
{
VALUE tmp;
long i;
for (i=0; i<RARRAY_LEN(ary); i++) {
tmp = RARRAY_PTR(ary)[i];
if (recur) {
tmp = rb_str_new2("[...]");
}
rb_funcall(out, id_puts, 1, tmp);
}
return Qnil;
}
static VALUE
rg_puts(int argc, VALUE *argv, VALUE self)
{
int i;
VALUE line;
/* if no argument given, print newline. */
if (argc == 0) {
rg_write(self, default_rs);
return Qnil;
}
for (i=0; i<argc; i++) {
if (NIL_P(argv[i])) {
line = rb_str_new2("nil");
}
else {
line = rbg_check_array_type(argv[i]);
if (!NIL_P(line)) {
#ifdef HAVE_RB_EXEC_RECURSIVE
rb_exec_recursive(ioc_puts_ary, line, self);
#else
rb_protect_inspect(ioc_puts_ary, line, self);
#endif
continue;
}
line = rb_obj_as_string(argv[i]);
}
rg_write(self, line);
if (RSTRING_LEN(line) == 0 ||
RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
rg_write(self, default_rs);
}
}
return Qnil;
}
static VALUE
rg_print(int argc, VALUE *argv, VALUE out)
{
int i;
VALUE line;
VALUE output_field_separator;
/* if no argument given, print `$_' */
if (argc == 0) {
argc = 1;
line = rb_lastline_get();
argv = &line;
}
output_field_separator = rb_gv_get("$,");
for (i=0; i<argc; i++) {
if (!NIL_P(output_field_separator) && i>0) {
rg_write(out, output_field_separator);
}
switch (TYPE(argv[i])) {
case T_NIL:
rg_write(out, rb_str_new2("nil"));
break;
default:
rg_write(out, argv[i]);
break;
}
}
if (!NIL_P(output_field_separator)) {
rg_write(out, output_field_separator);
}
return Qnil;
}
void
Init_glib_io_channel(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_IO_CHANNEL, "IOChannel", mGLib);
rb_include_module(RG_TARGET_NAMESPACE, rb_mEnumerable);
id_call = rb_intern("call");
id_puts = rb_intern("puts");
id_unpack = rb_intern("unpack");
default_rs = rb_str_new_cstr("\n");
#ifdef HAVE_RB_GC_REGISTER_MARK_OBJECT
rb_gc_register_mark_object(default_rs);
#else
rb_global_variable(&default_rs);
#endif
RG_DEF_METHOD(initialize, -1);
RG_DEF_SMETHOD(open, -1);
RG_DEF_METHOD(fileno, 0);
RG_DEF_ALIAS("to_i", "fileno");
RG_DEF_METHOD(read, -1);
RG_DEF_METHOD(readchar, 0);
RG_DEF_METHOD(getc, 0);
RG_DEF_METHOD(readline, -1);
RG_DEF_METHOD(gets, -1);
RG_DEF_METHOD(each, -1);
RG_DEF_ALIAS("each_line", "each");
RG_DEF_METHOD(each_char, 0);
RG_DEF_METHOD(write, 1);
RG_DEF_METHOD(printf, -1);
RG_DEF_METHOD(print, -1);
RG_DEF_METHOD(puts, -1);
RG_DEF_METHOD(putc, 1);
RG_DEF_METHOD(flush, 0);
RG_DEF_METHOD(seek, -1);
RG_DEF_METHOD(set_pos, 1);
RG_DEF_METHOD(close, -1);
RG_DEF_METHOD(create_watch, 1);
RG_DEF_METHOD(add_watch, 1);
RG_DEF_METHOD(buffer_size, 0);
RG_DEF_METHOD(set_buffer_size, 1);
RG_DEF_METHOD(buffer_condition, 0);
RG_DEF_METHOD(flags, 0);
RG_DEF_METHOD(set_flags, 1);
RG_DEF_METHOD(buffered, 0);
RG_DEF_METHOD(set_buffered, 1);
RG_DEF_METHOD(encoding, 0);
RG_DEF_METHOD(set_encoding, 1);
/* GSeekType */
rb_define_const(RG_TARGET_NAMESPACE, "SEEK_CUR", INT2NUM(G_SEEK_CUR));
rb_define_const(RG_TARGET_NAMESPACE, "SEEK_SET", INT2NUM(G_SEEK_SET));
rb_define_const(RG_TARGET_NAMESPACE, "SEEK_END", INT2NUM(G_SEEK_END));
/* GIOStatus */
rb_define_const(RG_TARGET_NAMESPACE, "STATUS_ERROR", INT2NUM(G_IO_STATUS_ERROR));
rb_define_const(RG_TARGET_NAMESPACE, "STATUS_NORMAL", INT2NUM(G_IO_STATUS_NORMAL));
rb_define_const(RG_TARGET_NAMESPACE, "STATUS_EOF", INT2NUM(G_IO_STATUS_EOF));
rb_define_const(RG_TARGET_NAMESPACE, "STATUS_AGAIN", INT2NUM(G_IO_STATUS_AGAIN));
/* GIOCondition */
/* Deprecated. Just for bacakward compatibility. Use
* GLib::IOCondition::* instead. */
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_IO_CONDITION, "G_IO_");
/* GIOFlags */
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_APPEND", INT2NUM(G_IO_FLAG_APPEND));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_NONBLOCK", INT2NUM(G_IO_FLAG_NONBLOCK));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_READABLE", INT2NUM(G_IO_FLAG_IS_READABLE));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_WRITEABLE", INT2NUM(G_IO_FLAG_IS_WRITEABLE));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_IS_SEEKABLE", INT2NUM(G_IO_FLAG_IS_SEEKABLE));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_MASK", INT2NUM(G_IO_FLAG_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_GET_MASK", INT2NUM(G_IO_FLAG_GET_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_SET_MASK", INT2NUM(G_IO_FLAG_SET_MASK));
}

View File

@ -0,0 +1,56 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#ifdef G_OS_WIN32
#define RG_TARGET_NAMESPACE cIOChannelWin32Socket
static VALUE
rg_initialize(VALUE self, VALUE socket)
{
GIOChannel *io = NULL;
int fd;
rb_secure(4);
/* TODO: support IO object */
fd = NUM2INT(socket);
io = g_io_channel_win32_new_socket(rb_w32_get_osfhandle(fd));
G_INITIALIZE(self, io);
return Qnil;
}
#endif
void
Init_glib_io_channel_win32_socket(void)
{
#ifdef G_OS_WIN32
/* GIOWin32Channel */
VALUE RG_TARGET_NAMESPACE;
RG_TARGET_NAMESPACE =
rb_define_class_under(mGLib,
"IOChannelWin32Socket",
rb_const_get(mGLib, rb_intern("IOChannel")));
RG_DEF_METHOD(initialize, 1);
#endif
}

View File

@ -0,0 +1,49 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cIOChannelError
static VALUE
rg_s_from_errno(G_GNUC_UNUSED VALUE self, VALUE errno_)
{
return INT2NUM(g_io_channel_error_from_errno(NUM2INT(errno_)));
}
void
Init_glib_io_channelerror(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_ERROR2(G_IO_CHANNEL_ERROR, "IOChannelError", mGLib, rb_eIOError);
/* GIOChannelError */
RG_DEF_SMETHOD(from_errno, 1);
rb_define_const(RG_TARGET_NAMESPACE, "FBIG", INT2NUM(G_IO_CHANNEL_ERROR_FBIG));
rb_define_const(RG_TARGET_NAMESPACE, "INVAL", INT2NUM(G_IO_CHANNEL_ERROR_INVAL));
rb_define_const(RG_TARGET_NAMESPACE, "IO", INT2NUM(G_IO_CHANNEL_ERROR_IO));
rb_define_const(RG_TARGET_NAMESPACE, "ISDIR", INT2NUM(G_IO_CHANNEL_ERROR_ISDIR));
rb_define_const(RG_TARGET_NAMESPACE, "NOSPC", INT2NUM(G_IO_CHANNEL_ERROR_NOSPC));
rb_define_const(RG_TARGET_NAMESPACE, "NXIO", INT2NUM(G_IO_CHANNEL_ERROR_NXIO));
rb_define_const(RG_TARGET_NAMESPACE, "OVERFLOW", INT2NUM(G_IO_CHANNEL_ERROR_OVERFLOW));
rb_define_const(RG_TARGET_NAMESPACE, "PIPE", INT2NUM(G_IO_CHANNEL_ERROR_PIPE));
rb_define_const(RG_TARGET_NAMESPACE, "FAILED", INT2NUM(G_IO_CHANNEL_ERROR_FAILED));
}

View File

@ -0,0 +1,775 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#if GLIB_CHECK_VERSION(2,6,0)
#if !GLIB_CHECK_VERSION(2,31,2)
/************************************************/
static GKeyFile*
keyfile_copy(const GKeyFile* keyfile)
{
// GKeyFile* new_keyfile;
g_return_val_if_fail (keyfile != NULL, NULL);
/*
new_keyfile = g_key_file_new();
*new_keyfile = (GKeyFile*)*keyfile;
return new_keyfile;
*/
return (GKeyFile*)keyfile;
}
GType
g_key_file_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static("GKeyFile",
(GBoxedCopyFunc)keyfile_copy,
(GBoxedFreeFunc)g_key_file_free);
return our_type;
}
/************************************************/
#endif
#define RG_TARGET_NAMESPACE cKeyFile
#define _SELF(self) ((GKeyFile*)(RVAL2BOXED(self, G_TYPE_KEY_FILE)))
static VALUE
rg_initialize(VALUE self)
{
G_INITIALIZE(self, g_key_file_new());
return Qnil;
}
static VALUE
rg_set_list_separator(VALUE self, VALUE sep)
{
g_key_file_set_list_separator(_SELF(self), NUM2INT(sep));
return self;
}
static VALUE
rg_load_from_file(int argc, VALUE *argv, VALUE self)
{
VALUE file, flags;
GError* error = NULL;
gboolean ret;
GKeyFileFlags gflags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
rb_scan_args(argc, argv, "11", &file, &flags);
if (!NIL_P(flags)){
gflags = RVAL2GFLAGS(flags, G_TYPE_KEY_FILE_FLAGS);
}
ret = g_key_file_load_from_file(_SELF(self),
RVAL2CSTR(file),
gflags, &error);
if (! ret) RAISE_GERROR(error);
return self;
}
static VALUE
rg_load_from_data(int argc, VALUE *argv, VALUE self)
{
VALUE data, flags;
GError* error = NULL;
gboolean ret;
GKeyFileFlags gflags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
rb_scan_args(argc, argv, "11", &data, &flags);
if (!NIL_P(flags)){
gflags = RVAL2GFLAGS(flags, G_TYPE_KEY_FILE_FLAGS);
}
StringValue(data);
ret = g_key_file_load_from_data(_SELF(self),
(const gchar*)RVAL2CSTR(data),
(gsize)RSTRING_LEN(data),
gflags, &error);
if (! ret) RAISE_GERROR(error);
return self;
}
static VALUE
rg_load_from_data_dirs(int argc, VALUE *argv, VALUE self)
{
VALUE file, flags;
GError* error = NULL;
gboolean ret;
gchar* full_path;
GKeyFileFlags gflags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
rb_scan_args(argc, argv, "11", &file, &flags);
if (!NIL_P(flags)){
gflags = RVAL2GFLAGS(flags, G_TYPE_KEY_FILE_FLAGS);
}
StringValue(file);
ret = g_key_file_load_from_data_dirs(_SELF(self),
(const gchar*)RVAL2CSTR(file),
&full_path,
gflags, &error);
if (! ret) RAISE_GERROR(error);
return full_path ? CSTR2RVAL(full_path) : Qnil;
}
#if GLIB_CHECK_VERSION(2, 14, 0)
static VALUE
rg_load_from_dirs(int argc, VALUE *argv, VALUE self)
{
VALUE rb_file, rb_search_dirs, rb_flags;
GError* error = NULL;
gboolean success;
const gchar *file;
const gchar **search_dirs;
gchar* full_path;
GKeyFileFlags flags;
rb_scan_args(argc, argv, "12", &rb_file, &rb_search_dirs, &rb_flags);
file = RVAL2CSTR(rb_file);
search_dirs = RVAL2STRV_ACCEPT_NIL(rb_search_dirs);
flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
if (!NIL_P(rb_flags))
flags = RVAL2GFLAGS(rb_flags, G_TYPE_KEY_FILE_FLAGS);
if (search_dirs != NULL)
success = g_key_file_load_from_dirs(_SELF(self), file,
search_dirs,
&full_path, flags, &error);
else
success = g_key_file_load_from_data_dirs(_SELF(self), file,
&full_path, flags, &error);
g_free(search_dirs);
if (!success)
RAISE_GERROR(error);
return CSTR2RVAL(full_path);
}
#endif
static VALUE
rg_to_data(VALUE self)
{
GError* error = NULL;
gchar* data = g_key_file_to_data(_SELF(self), NULL, &error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(data);
}
static VALUE
rg_start_group(VALUE self)
{
return CSTR2RVAL(g_key_file_get_start_group(_SELF(self)));
}
static VALUE
rg_groups(VALUE self)
{
return STRV2RVAL_FREE(g_key_file_get_groups(_SELF(self), NULL));
}
static VALUE
rg_get_keys(VALUE self, VALUE group_name)
{
GError *error = NULL;
gchar **keys = g_key_file_get_keys(_SELF(self),
RVAL2CSTR(group_name),
NULL,
&error);
if (error != NULL)
RAISE_GERROR(error);
return STRV2RVAL_FREE(keys);
}
static VALUE
rg_has_group_p(VALUE self, VALUE group_name)
{
return CBOOL2RVAL(g_key_file_has_group(_SELF(self),
(const gchar*)RVAL2CSTR(group_name)));
}
static VALUE
rg_has_key_p(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gboolean ret = g_key_file_has_key(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return CBOOL2RVAL(ret);
}
static VALUE
rg_get_value(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gchar* ret = g_key_file_get_value(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_get_string(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gchar* ret = g_key_file_get_string(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_get_locale_string(int argc, VALUE *argv, VALUE self)
{
VALUE group_name, key, locale;
GError* error = NULL;
gchar* ret;
rb_scan_args(argc, argv, "21", &group_name, &key, &locale);
ret = g_key_file_get_locale_string(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
(const gchar*)RVAL2CSTR_ACCEPT_NIL(locale),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_get_boolean(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gboolean ret = g_key_file_get_boolean(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return CBOOL2RVAL(ret);
}
static VALUE
rg_get_integer(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gint ret = g_key_file_get_integer(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return INT2NUM(ret);
}
#if GLIB_CHECK_VERSION(2,12,0)
static VALUE
rg_get_double(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gdouble ret = g_key_file_get_double(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return rb_float_new(ret);
}
#endif
static VALUE
rg_get_string_list(VALUE self, VALUE group_name, VALUE key)
{
VALUE ary;
gsize i;
gsize length;
GError* error = NULL;
gchar** ret = g_key_file_get_string_list(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, CSTR2RVAL(ret[i]));
}
g_strfreev(ret);
return ary;
}
static VALUE
rg_get_locale_string_list(int argc, VALUE *argv, VALUE self)
{
VALUE group_name, key, locale;
GError* error = NULL;
VALUE ary;
gsize i;
gsize length;
gchar** ret;
rb_scan_args(argc, argv, "21", &group_name, &key, &locale);
ret = g_key_file_get_locale_string_list(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
(const gchar*)RVAL2CSTR_ACCEPT_NIL(locale),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, CSTR2RVAL(ret[i]));
}
g_strfreev(ret);
return ary;
}
static VALUE
rg_get_boolean_list(VALUE self, VALUE group_name, VALUE key)
{
VALUE ary;
gsize i;
gsize length;
GError* error = NULL;
gboolean* ret = g_key_file_get_boolean_list(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, CBOOL2RVAL(ret[i]));
}
return ary;
}
static VALUE
rg_get_integer_list(VALUE self, VALUE group_name, VALUE key)
{
VALUE ary;
gsize i;
gsize length;
GError* error = NULL;
gint* ret = g_key_file_get_integer_list(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, INT2NUM(ret[i]));
}
return ary;
}
#if GLIB_CHECK_VERSION(2,12,0)
static VALUE
rg_get_double_list(VALUE self, VALUE group_name, VALUE key)
{
VALUE ary;
gsize i;
gsize length;
GError* error = NULL;
gdouble* ret = g_key_file_get_double_list(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&length, &error);
if (error) RAISE_GERROR(error);
ary = rb_ary_new();
for(i = 0; i < length; i++){
rb_ary_push(ary, rb_float_new(ret[i]));
}
return ary;
}
#endif
static VALUE
rg_get_comment(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
gchar* ret = g_key_file_get_comment(_SELF(self),
(const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
&error);
if (error) RAISE_GERROR(error);
return CSTR2RVAL_FREE(ret);
}
static VALUE
rg_set_value(VALUE self, VALUE group_name, VALUE key, VALUE value)
{
g_key_file_set_value(_SELF(self), (const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
(const gchar*)RVAL2CSTR(value));
return self;
}
static VALUE
rg_set_string(VALUE self, VALUE group_name, VALUE key, VALUE string)
{
g_key_file_set_string(_SELF(self), (const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
(const gchar*)RVAL2CSTR(string));
return self;
}
static VALUE
rg_set_locale_string(VALUE self, VALUE group_name, VALUE key, VALUE locale, VALUE locale_string)
{
g_key_file_set_locale_string(_SELF(self), (const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
(const gchar*)RVAL2CSTR(locale),
(const gchar*)RVAL2CSTR(locale_string));
return self;
}
static VALUE
rg_set_boolean(VALUE self, VALUE group_name, VALUE key, VALUE value)
{
g_key_file_set_boolean(_SELF(self), (const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
RVAL2CBOOL(value));
return self;
}
static VALUE
rg_set_integer(VALUE self, VALUE group_name, VALUE key, VALUE value)
{
g_key_file_set_integer(_SELF(self), (const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
NUM2INT(value));
return self;
}
#if GLIB_CHECK_VERSION(2,12,0)
static VALUE
rg_set_double(VALUE self, VALUE group_name, VALUE key, VALUE value)
{
g_key_file_set_double(_SELF(self), (const gchar*)RVAL2CSTR(group_name),
(const gchar*)RVAL2CSTR(key),
NUM2DBL(value));
return self;
}
#endif
static VALUE
rg_set_string_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist)
{
GKeyFile *key_file = _SELF(self);
const gchar *group_name = RVAL2CSTR(rbgroup_name);
const gchar *key = RVAL2CSTR(rbkey);
long n;
const gchar **list = RVAL2STRS(rblist, n);
g_key_file_set_string_list(key_file, group_name, key, list, n);
g_free(list);
return self;
}
static VALUE
rg_set_locale_string_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblocale, VALUE rblist)
{
GKeyFile *key_file = _SELF(self);
const gchar *group_name = RVAL2CSTR(rbgroup_name);
const gchar *key = RVAL2CSTR(rbkey);
const gchar *locale = RVAL2CSTR(rblocale);
long n;
const gchar **list = RVAL2STRS(rblist, n);
g_key_file_set_locale_string_list(key_file, group_name, key, locale, list, n);
g_free(list);
return self;
}
static VALUE
rg_set_boolean_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist)
{
GKeyFile *key_file = _SELF(self);
const gchar *group_name = RVAL2CSTR(rbgroup_name);
const gchar *key = RVAL2CSTR(rbkey);
long n;
gboolean *list = RVAL2GBOOLEANS(rblist, n);
g_key_file_set_boolean_list(key_file, group_name, key, list, n);
g_free(list);
return self;
}
static VALUE
rg_set_integer_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist)
{
GKeyFile *key_file = _SELF(self);
const gchar *group_name = RVAL2CSTR(rbgroup_name);
const gchar *key = RVAL2CSTR(rbkey);
long n;
gint *list = RVAL2GINTS(rblist, n);
g_key_file_set_integer_list(key_file, group_name, key, list, n);
g_free(list);
return self;
}
#if GLIB_CHECK_VERSION(2,12,0)
static VALUE
rg_set_double_list(VALUE self, VALUE rbgroup_name, VALUE rbkey, VALUE rblist)
{
GKeyFile *key_file = _SELF(self);
const gchar *group_name = RVAL2CSTR(rbgroup_name);
const gchar *key = RVAL2CSTR(rbkey);
long n;
gdouble *list = RVAL2GDOUBLES(rblist, n);
g_key_file_set_double_list(key_file, group_name, key, list, n);
return self;
}
#endif
static VALUE
rg_set_comment(VALUE self, VALUE group_name, VALUE key, VALUE comment)
{
GError* error = NULL;
g_key_file_set_comment(_SELF(self),
RVAL2CSTR(group_name),
RVAL2CSTR_ACCEPT_NIL(key),
RVAL2CSTR(comment),
&error);
if (error != NULL)
RAISE_GERROR(error);
return self;
}
static VALUE
rg_remove_group(VALUE self, VALUE group_name)
{
GError* error = NULL;
g_key_file_remove_group(_SELF(self), RVAL2CSTR(group_name), &error);
if (error != NULL)
RAISE_GERROR(error);
return self;
}
static VALUE
rg_remove_key(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
g_key_file_remove_key(_SELF(self),
RVAL2CSTR(group_name),
RVAL2CSTR(key),
&error);
if (error != NULL)
RAISE_GERROR(error);
return self;
}
static VALUE
rg_remove_comment(VALUE self, VALUE group_name, VALUE key)
{
GError* error = NULL;
g_key_file_remove_comment(_SELF(self),
RVAL2CSTR(group_name),
RVAL2CSTR(key),
&error);
if (error != NULL)
RAISE_GERROR(error);
return self;
}
#endif
void
Init_glib_keyfile(void)
{
#if GLIB_CHECK_VERSION(2,6,0)
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_KEY_FILE, "KeyFile", mGLib);
G_DEF_ERROR(G_KEY_FILE_ERROR, "KeyFileError", mGLib,
rb_eRuntimeError, G_TYPE_KEY_FILE_ERROR);
RG_DEF_METHOD(initialize, 0);
RG_DEF_METHOD(set_list_separator, 1);
RG_DEF_METHOD(load_from_file, -1);
RG_DEF_METHOD(load_from_data, -1);
RG_DEF_METHOD(load_from_data_dirs, -1);
#if GLIB_CHECK_VERSION(2, 14, 0)
RG_DEF_METHOD(load_from_dirs, -1);
#endif
RG_DEF_METHOD(to_data, 0);
RG_DEF_METHOD(start_group, 0);
RG_DEF_METHOD(groups, 0);
RG_DEF_METHOD(get_keys, 1);
RG_DEF_METHOD_P(has_group, 1);
RG_DEF_METHOD_P(has_key, 2);
RG_DEF_METHOD(get_value, 2);
RG_DEF_METHOD(get_string, 2);
RG_DEF_METHOD(get_locale_string, -1);
RG_DEF_METHOD(get_boolean, 2);
RG_DEF_METHOD(get_integer, 2);
#if GLIB_CHECK_VERSION(2,12,0)
RG_DEF_METHOD(get_double, 2);
#endif
RG_DEF_METHOD(get_string_list, 2);
RG_DEF_METHOD(get_locale_string_list, -1);
RG_DEF_METHOD(get_boolean_list, 2);
RG_DEF_METHOD(get_integer_list, 2);
#if GLIB_CHECK_VERSION(2,12,0)
RG_DEF_METHOD(get_double_list, 2);
#endif
RG_DEF_METHOD(get_comment, 2);
RG_DEF_METHOD(set_value, 3);
RG_DEF_METHOD(set_string, 3);
RG_DEF_METHOD(set_locale_string, 4);
RG_DEF_METHOD(set_boolean, 3);
RG_DEF_METHOD(set_integer, 3);
#if GLIB_CHECK_VERSION(2,12,0)
RG_DEF_METHOD(set_double, 3);
#endif
RG_DEF_METHOD(set_string_list, 3);
RG_DEF_METHOD(set_locale_string_list, 4);
RG_DEF_METHOD(set_boolean_list, 3);
RG_DEF_METHOD(set_integer_list, 3);
#if GLIB_CHECK_VERSION(2,12,0)
RG_DEF_METHOD(set_double_list, 3);
#endif
RG_DEF_METHOD(set_comment, 3);
RG_DEF_METHOD(remove_group, 1);
RG_DEF_METHOD(remove_key, 2);
RG_DEF_METHOD(remove_comment, 2);
/* GKeyFileFlags */
G_DEF_CLASS(G_TYPE_KEY_FILE_FLAGS, "Flags", RG_TARGET_NAMESPACE);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_KEY_FILE_FLAGS, "G_KEY_FILE_");
#if GLIB_CHECK_VERSION(2, 14, 0)
/* Defines for handling freedesktop.org Desktop files */
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_GROUP", CSTR2RVAL(G_KEY_FILE_DESKTOP_GROUP));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_TYPE",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_TYPE));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_VERSION",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_VERSION));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_NAME",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_NAME));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_GENERIC_NAME",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_GENERIC_NAME));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_NO_DISPLAY",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_COMMENT",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_COMMENT));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_ICON",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_ICON));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_HIDDEN",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_HIDDEN));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_ONLY_SHOW_IN",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_NOT_SHOW_IN",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_TRY_EXEC",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_TRY_EXEC));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_EXEC",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_EXEC));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_PATH",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_PATH));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_TERMINAL",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_TERMINAL));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_MIME_TYPE",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_MIME_TYPE));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_CATEGORIES",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_CATEGORIES));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_STARTUP_NOTIFY",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_STARTUP_WM_CLASS",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_KEY_URL",
CSTR2RVAL(G_KEY_FILE_DESKTOP_KEY_URL));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_TYPE_APPLICATION",
CSTR2RVAL(G_KEY_FILE_DESKTOP_TYPE_APPLICATION));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_TYPE_LINK",
CSTR2RVAL(G_KEY_FILE_DESKTOP_TYPE_LINK));
rb_define_const(RG_TARGET_NAMESPACE, "DESKTOP_TYPE_DIRECTORY",
CSTR2RVAL(G_KEY_FILE_DESKTOP_TYPE_DIRECTORY));
#endif
#endif
}

View File

@ -0,0 +1,925 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
# include <version.h>
# include <rubysig.h>
# include <node.h>
# include <time.h>
# ifdef HAVE_CURR_THREAD
# define rb_curr_thread curr_thread
# endif
#endif
GStaticPrivate rg_polling_key = G_STATIC_PRIVATE_INIT;
/*
static ID id_poll_func;
*/
static ID id_call;
static VALUE mGLibSource;
static ID id__callbacks__;
static GHashTable *callbacks_table;
typedef struct _callback_info_t
{
VALUE callback;
guint id;
} callback_info_t;
/*****************************************/
static GPollFunc default_poll_func;
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
/* just for ruby-1.9.0. */
#if !defined(RUBY_UBF_IO) && defined(RB_UBF_DFL)
# define RUBY_UBF_IO RB_UBF_DFL
#endif
typedef struct _PollInfo
{
GPollFD *ufds;
guint nfsd;
gint timeout;
gint result;
} PollInfo;
static VALUE
rg_poll_in_blocking(void *data)
{
PollInfo *info = data;
info->result = default_poll_func(info->ufds, info->nfsd, info->timeout);
return Qnil;
}
static gint
rg_poll(GPollFD *ufds, guint nfsd, gint timeout)
{
PollInfo info;
info.ufds = ufds;
info.nfsd = nfsd;
info.timeout = timeout;
info.result = 0;
g_static_private_set(&rg_polling_key, GINT_TO_POINTER(TRUE), NULL);
rb_thread_blocking_region(rg_poll_in_blocking, &info, RUBY_UBF_IO, NULL);
g_static_private_set(&rg_polling_key, GINT_TO_POINTER(FALSE), NULL);
return info.result;
}
static VALUE
ruby_source_set_priority (G_GNUC_UNUSED VALUE self, G_GNUC_UNUSED VALUE priority)
{
return Qnil;
}
#else
static gint
rg_poll(GPollFD *ufds, guint nfsd, gint timeout)
{
gint result;
TRAP_BEG;
result = default_poll_func(ufds, nfsd, timeout);
TRAP_END;
return result;
}
#endif
static void
restore_poll_func(G_GNUC_UNUSED VALUE data)
{
if (g_main_context_get_poll_func(NULL) == (GPollFunc)rg_poll) {
g_main_context_set_poll_func(NULL, default_poll_func);
}
}
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
static guint ruby_source_id = 0;
/* from eval.c */
#define WAIT_FD (1<<0)
#define WAIT_SELECT (1<<1)
#define WAIT_TIME (1<<2)
#define WAIT_JOIN (1<<3)
#define WAIT_PID (1<<4)
#define DELAY_INFTY 1E30
#ifdef RUBY_RELEASE_YEAR
# define CHECK_RUBY_RELEASE_DATE(year, month, day) \
(RUBY_RELEASE_YEAR >= (year) && \
RUBY_RELEASE_MONTH >= (month) && \
RUBY_RELEASE_DAY >= (day))
#else
# define CHECK_RUBY_RELEASE_DATE(year, month, day) 0
#endif
static double
timeofday(void)
{
struct timeval tv;
#if CHECK_RUBY_RELEASE_DATE(2009, 1, 7)
/* The following CLOCK_MONOTONIC change was introduced into
* Ruby 1.8.6 and 1.8.7 at 2009-01-07.
*
* 1.8.6:
* Wed Jan 7 10:06:12 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
*
* * eval.c (timeofday): use monotonic clock. based on a patch
* from zimbatm <zimbatm@oree.ch> in [ruby-core:16627].
*
* 1.8.7:
* Wed Jan 7 10:09:46 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
*
* * eval.c (timeofday): use monotonic clock. based on a patch
* from zimbatm <zimbatm@oree.ch> in [ruby-core:16627].
*/
# ifdef CLOCK_MONOTONIC
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
}
# endif
#endif
gettimeofday(&tv, NULL);
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
}
/*****************************************/
typedef struct _RGSource
{
GSource source;
GList *poll_fds;
GList *old_poll_fds;
gboolean ready;
} RGSource;
static void
source_cleanup_poll_fds(GSource *source)
{
RGSource *rg_source = (RGSource *)source;
GList *node;
for (node = rg_source->old_poll_fds; node; node = g_list_next(node)) {
GPollFD *poll_fd = node->data;
g_source_remove_poll(source, poll_fd);
g_slice_free(GPollFD, poll_fd);
}
g_list_free(rg_source->old_poll_fds);
rg_source->old_poll_fds = NULL;
}
static inline void
source_prepare_add_poll_fd(GSource *source, gint fd, guchar events)
{
GPollFD *poll_fd;
GList *node;
RGSource *rg_source = (RGSource *)source;
for (node = rg_source->old_poll_fds; node; node = g_list_next(node)) {
poll_fd = node->data;
if (poll_fd->fd == fd && poll_fd->events == events) {
rg_source->old_poll_fds =
g_list_remove_link(rg_source->old_poll_fds, node);
rg_source->poll_fds = g_list_concat(rg_source->poll_fds, node);
return;
}
}
poll_fd = g_slice_new0(GPollFD);
poll_fd->fd = fd;
poll_fd->events = events;
g_source_add_poll(source, poll_fd);
rg_source->poll_fds = g_list_prepend(rg_source->poll_fds, poll_fd);
}
static inline void
source_prepare_add_poll(GSource *source, rb_thread_t thread)
{
if (thread->wait_for == WAIT_FD) {
/* The thread is blocked on thread->fd for read. */
source_prepare_add_poll_fd(source, thread->fd, G_IO_IN);
return;
}
if (thread->wait_for & WAIT_SELECT) {
/* thread->fd is the maximum fd of the fds in the various sets. Need to
* check the sets to see which fd's to wait for */
int fd;
for (fd = 0; fd < thread->fd; fd++) {
gushort events = 0;
if (FD_ISSET(fd, &thread->readfds))
events |= G_IO_IN;
if (FD_ISSET(fd, &thread->writefds))
events |= G_IO_OUT;
if (FD_ISSET(fd, &thread->exceptfds))
events |= G_IO_PRI | G_IO_ERR | G_IO_HUP;
if (events != 0)
source_prepare_add_poll_fd(source, fd, events);
}
}
}
static inline gboolean
source_prepare_setup_poll_fd(GSource *source, gint *timeout)
{
RGSource *rg_source = (RGSource *)source;
rb_thread_t thread;
gdouble now;
g_assert(rg_source->old_poll_fds == NULL);
rg_source->old_poll_fds = rg_source->poll_fds;
rg_source->poll_fds = NULL;
now = timeofday();
thread = rb_curr_thread;
do {
thread = thread->next;
if ((thread->wait_for == 0 && thread->status == THREAD_RUNNABLE &&
thread != rb_curr_thread) ||
(thread->wait_for & WAIT_JOIN &&
thread->join->status == THREAD_KILLED)) {
rg_source->poll_fds = g_list_concat(rg_source->poll_fds,
rg_source->old_poll_fds);
rg_source->old_poll_fds = NULL;
return TRUE;
}
if (thread->wait_for & WAIT_TIME && thread->delay != DELAY_INFTY) {
gint delay;
delay = (thread->delay - now) * 1000;
if (delay <= 0) {
rg_source->poll_fds = g_list_concat(rg_source->poll_fds,
rg_source->old_poll_fds);
rg_source->old_poll_fds = NULL;
return TRUE;
}
if (*timeout == -1 || delay < *timeout)
*timeout = delay;
}
if (thread->wait_for == WAIT_FD || thread->wait_for & WAIT_SELECT)
source_prepare_add_poll(source, thread);
} while (thread != rb_curr_thread);
source_cleanup_poll_fds(source);
return FALSE;
}
static gboolean
source_prepare(GSource *source, gint *timeout)
{
RGSource *rg_source = (RGSource *)source;
*timeout = -1;
rg_source->ready = source_prepare_setup_poll_fd(source, timeout);
return rg_source->ready;
}
static gboolean
source_check(GSource *source)
{
RGSource *rg_source = (RGSource *)source;
GList *node;
if (rg_source->ready)
return TRUE;
for (node = rg_source->poll_fds; node; node = g_list_next(node)) {
GPollFD *poll_fd = node->data;
if (poll_fd->revents)
return TRUE;
}
return FALSE;
}
static gboolean
source_dispatch(G_GNUC_UNUSED GSource *source,
G_GNUC_UNUSED GSourceFunc callback,
G_GNUC_UNUSED gpointer user_data)
{
TRAP_BEG;
rb_thread_schedule();
TRAP_END;
return TRUE;
}
static void
source_finalize(GSource *source)
{
RGSource *rg_source = (RGSource *)source;
GList *node;
for (node = rg_source->old_poll_fds; node; node = g_list_next(node)) {
GPollFD *poll_fd = node->data;
g_slice_free(GPollFD, poll_fd);
}
for (node = rg_source->poll_fds; node; node = g_list_next(node)) {
GPollFD *poll_fd = node->data;
g_slice_free(GPollFD, poll_fd);
}
g_list_free(rg_source->old_poll_fds);
rg_source->old_poll_fds = NULL;
g_list_free(rg_source->poll_fds);
rg_source->poll_fds = NULL;
}
static GSourceFuncs source_funcs = {
source_prepare,
source_check,
source_dispatch,
source_finalize,
NULL,
NULL
};
static GSource *
ruby_source_new(void)
{
GSource *source;
RGSource *rg_source;
source = g_source_new(&source_funcs, sizeof(RGSource));
g_source_set_can_recurse(source, TRUE);
rg_source = (RGSource *)source;
rg_source->poll_fds = NULL;
rg_source->old_poll_fds = NULL;
return source;
}
static VALUE
ruby_source_set_priority(G_GNUC_UNUSED VALUE self, VALUE priority)
{
GSource *ruby_source = NULL;
if (ruby_source_id != 0)
ruby_source = g_main_context_find_source_by_id(NULL, ruby_source_id);
if (ruby_source)
g_source_set_priority(ruby_source, NUM2INT(priority));
return Qnil;
}
#endif
static VALUE
source_remove(G_GNUC_UNUSED VALUE self, VALUE tag)
{
VALUE callback;
callback = G_GET_RELATIVE(mGLibSource, id__callbacks__, tag);
G_REMOVE_RELATIVE(mGLibSource, id__callbacks__, tag);
g_hash_table_remove(callbacks_table, (gpointer)callback);
return CBOOL2RVAL(g_source_remove(NUM2UINT(tag)));
}
#if GLIB_CHECK_VERSION(2,12,0)
static VALUE
source_current_source(G_GNUC_UNUSED VALUE self)
{
return BOXED2RVAL(g_main_current_source, G_TYPE_SOURCE);
}
#endif
static gboolean
invoke_source_func(gpointer data)
{
callback_info_t *info = (callback_info_t *)data;
gboolean ret;
ret = RVAL2CBOOL(rb_funcall(info->callback, id_call, 0));
if (!ret)
G_REMOVE_RELATIVE(mGLibSource, id__callbacks__, UINT2NUM(info->id));
return ret;
}
/*****************************************/
#if !GLIB_CHECK_VERSION(2,30,0)
GType
g_main_context_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static ("GMainContext",
(GBoxedCopyFunc)g_main_context_ref,
(GBoxedFreeFunc)g_main_context_unref);
return our_type;
}
#endif
/*****************************************/
#define RG_TARGET_NAMESPACE cMainContext
#define _SELF(s) ((GMainContext*)RVAL2BOXED(s, G_TYPE_MAIN_CONTEXT))
static VALUE
rg_initialize(VALUE self)
{
GMainContext *context;
context = g_main_context_new();
g_main_context_set_poll_func(context, rg_poll);
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
{
GSource *source;
source = ruby_source_new();
g_source_attach(source, context);
g_source_unref(source);
}
#endif
G_INITIALIZE(self, context);
return Qnil;
}
static VALUE
rg_s_default(G_GNUC_UNUSED VALUE self)
{
return BOXED2RVAL(g_main_context_default(), G_TYPE_MAIN_CONTEXT);
}
static VALUE
rg_iteration(VALUE self, VALUE may_block)
{
return CBOOL2RVAL(g_main_context_iteration(_SELF(self), RVAL2CBOOL(may_block)));
}
static VALUE
rg_pending_p(VALUE self)
{
return CBOOL2RVAL(g_main_context_pending(_SELF(self)));
}
static VALUE
rg_find_source(VALUE self, VALUE source_id)
{
GSource* src = g_main_context_find_source_by_id(_SELF(self), NUM2UINT(source_id));
return BOXED2RVAL(src, G_TYPE_SOURCE);
}
/*
GSource* g_main_context_find_source_by_user_data
(GMainContext *context,
gpointer user_data);
GSource* g_main_context_find_source_by_funcs_user_data
(GMainContext *context,
GSourceFuncs *funcs,
gpointer user_data);
*/
static VALUE
rg_wakeup(VALUE self)
{
g_main_context_wakeup(_SELF(self));
return self;
}
static VALUE
rg_acquire(VALUE self)
{
return CBOOL2RVAL(g_main_context_acquire(_SELF(self)));
}
static VALUE
rg_release(VALUE self)
{
g_main_context_release(_SELF(self));
return self;
}
#if GLIB_CHECK_VERSION(2,10,0)
static VALUE
rg_owner_p(VALUE self)
{
return CBOOL2RVAL(g_main_context_is_owner(_SELF(self)));
}
#endif
/*
gboolean g_main_context_wait (GMainContext *context,
GCond *cond,
GMutex *mutex);
*/
static VALUE
rg_prepare(VALUE self)
{
gint priority;
gboolean ret = g_main_context_prepare(_SELF(self), &priority);
return rb_assoc_new(CBOOL2RVAL(ret), INT2NUM(priority));
}
struct mc_query_body_args {
gint timeout_;
GPollFD *fds;
gint n_fds;
};
static VALUE
mc_query_body(VALUE value)
{
struct mc_query_body_args *args = (struct mc_query_body_args *)value;
gint i;
VALUE ary = rb_ary_new();
for (i = 0; i < args->n_fds; i++)
rb_ary_push(ary, BOXED2RVAL(&args->fds[i], G_TYPE_POLL_FD));
return rb_assoc_new(INT2NUM(args->timeout_), ary);
}
static VALUE
mc_query_ensure(VALUE value)
{
g_free((GPollFD *)value);
return Qnil;
}
#define QUERY_DEFAULT_FDS 100
static VALUE
rg_query(VALUE self, VALUE rbmax_priority)
{
GMainContext *context = _SELF(self);
gint max_priority = NUM2INT(rbmax_priority);
gint timeout_;
GPollFD *fds;
gint n_fds;
struct mc_query_body_args args;
fds = g_new(GPollFD, QUERY_DEFAULT_FDS);
n_fds = g_main_context_query(context, max_priority, &timeout_, fds, QUERY_DEFAULT_FDS);
if (n_fds > QUERY_DEFAULT_FDS) {
g_free(fds);
fds = g_new(GPollFD, n_fds);
g_main_context_query(context, max_priority, &timeout_, fds, n_fds);
}
args.timeout_ = timeout_;
args.fds = fds;
args.n_fds = n_fds;
return rb_ensure(mc_query_body, (VALUE)&args,
mc_query_ensure, (VALUE)fds);
}
/* How can I implement this?
static VALUE
rg_check(VALUE self, VALUE max_priority)
{
gint i, timeout_;
VALUE ary;
GPollFD* fds;
gint ret, n_fds;
fds = g_new (GPollFD, 10);
n_fds = g_main_context_query(_SELF(self), NUM2INT(max_priority),
&timeout_, fds, 10);
printf("n_fds = %d\n", n_fds);
g_free(fds);
fds = g_new (GPollFD, n_fds);
ret = g_main_context_check(_SELF(self), NUM2INT(max_priority),
fds, n_fds);
printf("ret = %d\n", ret);
ary = rb_ary_new();
for (i = 0; i < ret; i++)
rb_ary_push(ary, BOXED2RVAL(&fds[i], G_TYPE_POLL_FD));
g_free(fds);
return ary;
}
*/
static VALUE
rg_dispatch(VALUE self)
{
g_main_context_dispatch(_SELF(self));
return self;
}
/* How can I get "self" or something like it as key ....
static gint
poll_func(GPollFD *ufds, guint nfsd, gint timeout_)
{
VALUE func = rb_ivar_get(self, id_poll_func);
if (NIL_P(func)) return -1;
return INT2NUM(rb_funcall(func, 3, BOXED2RVAL(ufds, G_TYPE_POLL_FD),
UINT2NUM(nfsd), INT2NUM(timeout_)));
}
static VALUE
rg_set_poll_func(VALUE self)
{
rb_ivar_set(self, id_poll_func, rb_block_proc());
g_main_context_set_poll_func(_SELF(self), (GPollFunc)poll_func);
return self;
}
*/
/*
GPollFunc g_main_context_get_poll_func (GMainContext *context);
*/
static VALUE
rg_add_poll(VALUE self, VALUE fd, VALUE priority)
{
g_main_context_add_poll(_SELF(self), RVAL2BOXED(fd, G_TYPE_POLL_FD),
NUM2INT(priority));
return self;
}
static VALUE
rg_remove_poll(VALUE self, VALUE fd)
{
g_main_context_remove_poll(_SELF(self), RVAL2BOXED(fd, G_TYPE_POLL_FD));
return self;
}
#ifdef HAVE_G_MAIN_DEPTH
static VALUE
rg_s_depth(G_GNUC_UNUSED VALUE self)
{
return INT2NUM(g_main_depth());
}
#endif
static VALUE
timeout_source_new(G_GNUC_UNUSED VALUE self, VALUE interval)
{
return BOXED2RVAL(g_timeout_source_new(NUM2UINT(interval)), G_TYPE_SOURCE);
}
#if GLIB_CHECK_VERSION(2,14,0)
static VALUE
timeout_source_new_seconds(G_GNUC_UNUSED VALUE self, VALUE interval)
{
return BOXED2RVAL(g_timeout_source_new_seconds(NUM2UINT(interval)), G_TYPE_SOURCE);
}
#endif
static VALUE
timeout_add(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE interval, rb_priority, func, rb_id;
gint priority;
callback_info_t *info;
guint id;
rb_scan_args(argc, argv, "11&", &interval, &rb_priority, &func);
priority = NIL_P(rb_priority) ? G_PRIORITY_DEFAULT : NUM2INT(rb_priority);
info = ALLOC(callback_info_t);
info->callback = func;
id = g_timeout_add_full(priority, NUM2UINT(interval),
(GSourceFunc)invoke_source_func,
(gpointer)info, g_free);
info->id = id;
rb_id = UINT2NUM(id);
G_RELATIVE2(mGLibSource, func, id__callbacks__, rb_id);
g_hash_table_insert(callbacks_table, (gpointer)func, info);
return rb_id;
}
#if GLIB_CHECK_VERSION(2,14,0)
static VALUE
timeout_add_seconds(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE interval, rb_priority, func, rb_id;
gint priority;
callback_info_t *info;
guint id;
rb_scan_args(argc, argv, "11&", &interval, &rb_priority, &func);
priority = NIL_P(rb_priority) ? G_PRIORITY_DEFAULT : NUM2INT(rb_priority);
info = ALLOC(callback_info_t);
info->callback = func;
id = g_timeout_add_seconds_full(priority,
NUM2UINT(interval),
(GSourceFunc)invoke_source_func,
(gpointer)info,
g_free);
info->id = id;
rb_id = UINT2NUM(id);
G_RELATIVE2(mGLibSource, func, id__callbacks__, rb_id);
g_hash_table_insert(callbacks_table, (gpointer)func, info);
return rb_id;
}
#endif
static VALUE
idle_source_new(G_GNUC_UNUSED VALUE self)
{
return BOXED2RVAL(g_idle_source_new(), G_TYPE_SOURCE);
}
static VALUE
idle_add(gint argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE arg1, arg2, func, rb_id;
callback_info_t *info;
guint id;
gint priority = G_PRIORITY_DEFAULT_IDLE;
rb_scan_args(argc, argv, "02", &arg1, &arg2);
if (RVAL2CBOOL(rb_obj_is_kind_of(arg1, rb_cProc))) {
func = arg1;
} else if (RVAL2CBOOL(rb_obj_is_kind_of(arg1, rb_cInteger))) {
priority = NUM2INT(arg1);
func = rb_block_proc();
} else {
func = rb_block_proc();
}
info = ALLOC(callback_info_t);
info->callback = func;
id = g_idle_add_full(priority, (GSourceFunc)invoke_source_func,
(gpointer)info, g_free);
info->id = id;
rb_id = UINT2NUM(id);
G_RELATIVE2(mGLibSource, func, id__callbacks__, rb_id);
g_hash_table_insert(callbacks_table, (gpointer)func, info);
return rb_id;
}
static VALUE
idle_remove(G_GNUC_UNUSED VALUE self, VALUE func)
{
callback_info_t *info;
info = g_hash_table_lookup(callbacks_table, (gpointer)func);
G_REMOVE_RELATIVE(mGLibSource, id__callbacks__, UINT2NUM(info->id));
g_hash_table_remove(callbacks_table, (gpointer)func);
return CBOOL2RVAL(g_idle_remove_by_data((gpointer)info));
}
#if GLIB_CHECK_VERSION(2,4,0)
static VALUE
child_watch_source_new(G_GNUC_UNUSED VALUE self, VALUE pid)
{
return BOXED2RVAL(g_child_watch_source_new((GPid)NUM2INT(pid)), G_TYPE_SOURCE);
}
static void
child_watch_func(GPid pid, gint status, gpointer func)
{
rb_funcall((VALUE)func, id_call, 2, INT2NUM((long)pid), INT2NUM(status));
}
static VALUE
child_watch_add(VALUE self, VALUE pid)
{
VALUE func = rb_block_proc();
G_RELATIVE(self, func);
return UINT2NUM(g_child_watch_add((GPid)NUM2INT(pid),
(GChildWatchFunc)child_watch_func, (gpointer)func));
}
#endif
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
static void
ruby_source_remove(G_GNUC_UNUSED VALUE data)
{
if (ruby_source_id != 0) {
g_source_remove(ruby_source_id);
ruby_source_id = 0;
}
}
#endif
void
Init_glib_main_context(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_MAIN_CONTEXT, "MainContext", mGLib);
VALUE timeout = rb_define_module_under(mGLib, "Timeout");
VALUE idle = rb_define_module_under(mGLib, "Idle");
#if GLIB_CHECK_VERSION(2,4,0)
VALUE child_watch = rb_define_module_under(mGLib, "ChildWatch");
#endif
id_call = rb_intern("call");
id__callbacks__ = rb_intern("__callbacks__");
callbacks_table = g_hash_table_new(NULL, NULL);
rbg_define_singleton_method(mGLib, "set_ruby_thread_priority",
ruby_source_set_priority, 1);
mGLibSource = rb_const_get(mGLib, rb_intern("Source"));
rbg_define_singleton_method(mGLibSource, "remove", source_remove, 1);
#if GLIB_CHECK_VERSION(2,12,0)
rbg_define_singleton_method(mGLibSource, "current", source_current_source, 0);
#endif
/*
id_poll_func = rb_intern("__poll_func__");
*/
RG_DEF_METHOD(initialize, 0);
RG_DEF_SMETHOD(default, 0);
RG_DEF_METHOD(iteration, 1);
RG_DEF_METHOD_P(pending, 0);
RG_DEF_METHOD(find_source, 1);
RG_DEF_METHOD(wakeup, 0);
RG_DEF_METHOD(acquire, 0);
RG_DEF_METHOD(release, 0);
#if GLIB_CHECK_VERSION(2,10,0)
RG_DEF_METHOD_P(owner, 0);
#endif
RG_DEF_METHOD(prepare, 0);
RG_DEF_METHOD(query, 1);
/*
RG_DEF_METHOD(check, 1);
*/
RG_DEF_METHOD(dispatch, 0);
/*
RG_DEF_METHOD(set_poll_func, 0);
*/
RG_DEF_METHOD(add_poll, 2);
RG_DEF_METHOD(remove_poll, 1);
#ifdef HAVE_G_MAIN_DEPTH
RG_DEF_SMETHOD(depth, 0);
#endif
rbg_define_singleton_method(timeout, "source_new", timeout_source_new, 1);
#if GLIB_CHECK_VERSION(2,14,0)
rbg_define_singleton_method(timeout, "source_new_seconds", timeout_source_new_seconds, 1);
#endif
rbg_define_singleton_method(timeout, "add", timeout_add, -1);
#if GLIB_CHECK_VERSION(2,14,0)
rbg_define_singleton_method(timeout, "add_seconds", timeout_add_seconds, -1);
#endif
rbg_define_singleton_method(idle, "source_new", idle_source_new, 0);
rbg_define_singleton_method(idle, "add", idle_add, -1);
rbg_define_singleton_method(idle, "remove", idle_remove, 1);
#if GLIB_CHECK_VERSION(2,4,0)
rbg_define_singleton_method(child_watch, "source_new", child_watch_source_new, 1);
rbg_define_singleton_method(child_watch, "add", child_watch_add, 1);
#endif
default_poll_func = g_main_context_get_poll_func(NULL);
g_main_context_set_poll_func(NULL, rg_poll);
rb_set_end_proc(restore_poll_func, Qnil);
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
{
GSource *source;
source = ruby_source_new();
g_source_set_priority(source, G_PRIORITY_DEFAULT_IDLE);
ruby_source_id = g_source_attach(source, NULL);
g_source_unref(source);
rb_set_end_proc(ruby_source_remove, Qnil);
}
#endif
}

View File

@ -0,0 +1,96 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005,2006 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
/*****************************************/
#if !GLIB_CHECK_VERSION(2,30,0)
GType
g_main_loop_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static ("GMainLoop",
(GBoxedCopyFunc)g_main_loop_ref,
(GBoxedFreeFunc)g_main_loop_unref);
return our_type;
}
#endif
/*****************************************/
#define RG_TARGET_NAMESPACE cMainLoop
#define _SELF(s) ((GMainLoop*)RVAL2BOXED(s, G_TYPE_MAIN_LOOP))
/*****************************************/
static VALUE
rg_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE context, is_running;
GMainLoop *loop;
GMainContext *main_context = NULL;
rb_scan_args(argc, argv, "02", &context, &is_running);
if (!NIL_P(context))
main_context = RVAL2BOXED(context, G_TYPE_MAIN_CONTEXT);
loop = g_main_loop_new(main_context, RVAL2CBOOL(is_running));
G_INITIALIZE(self, loop);
return Qnil;
}
static VALUE
rg_run(VALUE self)
{
g_main_loop_run(_SELF(self));
return self;
}
static VALUE
rg_quit(VALUE self)
{
g_main_loop_quit(_SELF(self));
return Qnil;
}
static VALUE
rg_running_p(VALUE self)
{
return CBOOL2RVAL(g_main_loop_is_running(_SELF(self)));
}
static VALUE
rg_context(VALUE self)
{
return BOXED2RVAL(g_main_loop_get_context(_SELF(self)), G_TYPE_MAIN_CONTEXT);
}
void
Init_glib_main_loop(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_MAIN_LOOP, "MainLoop", mGLib);
RG_DEF_METHOD(initialize, -1);
RG_DEF_METHOD(run, 0);
RG_DEF_METHOD(quit, 0);
RG_DEF_METHOD_P(running, 0);
RG_DEF_METHOD(context, 0);
}

View File

@ -0,0 +1,148 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2005 Masao Mutoh
* Copyright (C) 1998-2000 Yukihiro Matsumoto,
* Daisuke Kanda,
* Hiroshi Igarashi
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#ifndef HAVE_RB_SOURCEFILE
#define rb_sourcefile() (ruby_sourcefile)
#endif
#ifndef HAVE_RB_SOURCELINE
#define rb_sourceline() (ruby_sourceline)
#endif
#define RG_TARGET_NAMESPACE mLog
static VALUE rbglib_log_handler_procs;
static gboolean log_canceled;
static const gchar *
logmessage(GLogLevelFlags level)
{
if (level & G_LOG_LEVEL_ERROR){
return "ERROR";
} else if (level & G_LOG_LEVEL_CRITICAL){
return "CRITICAL";
} else if (level & G_LOG_LEVEL_WARNING){
return "WARNING";
} else if (level & G_LOG_LEVEL_MESSAGE){
return "MESSAGE";
} else if (level & G_LOG_LEVEL_INFO){
return "INFO";
} else if (level & G_LOG_LEVEL_DEBUG){
return "DEBUG";
}
return "UNKNOWN";
}
static void
rbglib_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
{
if (! log_canceled){
#ifdef HAVE_RUBY_SET_CURRENT_SOURCE
ruby_set_current_source();
#endif
g_printerr("%s: line %d\n", rb_sourcefile(), rb_sourceline());
g_printerr(" %s-%s **:%s\n", log_domain, logmessage(log_level), message);
} else {
g_log_default_handler(log_domain, log_level, message, user_data);
}
}
/* Use Internal only */
static VALUE
rg_s_cancel_handler(G_GNUC_UNUSED VALUE self)
{
log_canceled = TRUE;
return Qnil;
}
static VALUE
rg_s_set_handler(VALUE self, VALUE domain, VALUE levels)
{
guint handler_id = g_log_set_handler(RVAL2CSTR_ACCEPT_NIL(domain),
NUM2INT(levels),
(GLogFunc)rbglib_log_handler, (gpointer)self);
return UINT2NUM(handler_id);
}
static VALUE
rg_s_remove_handler(VALUE self, VALUE domain, VALUE handler_id)
{
g_log_remove_handler(RVAL2CSTR_ACCEPT_NIL(domain),
NUM2UINT(handler_id));
G_REMOVE_RELATIVE(self, handler_id, rbglib_log_handler_procs);
return Qnil;
}
static VALUE
rg_s_set_always_fatal(G_GNUC_UNUSED VALUE self, VALUE fatal_mask)
{
return INT2NUM(g_log_set_always_fatal(NUM2INT(fatal_mask)));
}
static VALUE
rg_s_set_fatal_mask(G_GNUC_UNUSED VALUE self, VALUE domain, VALUE fatal_mask)
{
return INT2NUM(g_log_set_fatal_mask(RVAL2CSTR_ACCEPT_NIL(domain),
NUM2INT(fatal_mask)));
}
static VALUE
rg_s_log(G_GNUC_UNUSED VALUE self, VALUE domain, VALUE level, VALUE str)
{
g_log(RVAL2CSTR_ACCEPT_NIL(domain), NUM2INT(level), "%s", RVAL2CSTR(str));
return Qnil;
}
void
Init_glib_messages(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "Log");
log_canceled = FALSE;
rb_global_variable(&rbglib_log_handler_procs);
rbglib_log_handler_procs = rb_hash_new();
RG_DEF_SMETHOD(set_handler, 2);
RG_DEF_SMETHOD(remove_handler, 2);
RG_DEF_SMETHOD(cancel_handler, 0);
RG_DEF_SMETHOD(set_always_fatal, 1);
RG_DEF_SMETHOD(set_fatal_mask, 2);
RG_DEF_SMETHOD(log, 3);
rb_define_const(RG_TARGET_NAMESPACE, "FATAL_MASK", INT2NUM(G_LOG_FATAL_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_USER_SHIFT", INT2NUM(G_LOG_LEVEL_USER_SHIFT));
/* GLogLevelFlags */
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_RECURSION", INT2NUM(G_LOG_FLAG_RECURSION));
rb_define_const(RG_TARGET_NAMESPACE, "FLAG_FATAL", INT2NUM(G_LOG_FLAG_FATAL));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_ERROR", INT2NUM(G_LOG_LEVEL_ERROR));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_CRITICAL", INT2NUM(G_LOG_LEVEL_CRITICAL));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_WARNING", INT2NUM(G_LOG_LEVEL_WARNING));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_MESSAGE", INT2NUM(G_LOG_LEVEL_MESSAGE));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_INFO", INT2NUM(G_LOG_LEVEL_INFO));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_DEBUG", INT2NUM(G_LOG_LEVEL_DEBUG));
rb_define_const(RG_TARGET_NAMESPACE, "LEVEL_MASK", INT2NUM(G_LOG_LEVEL_MASK));
}

View File

@ -0,0 +1,112 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
/*****************************************/
static GPollFD*
pollfd_copy(const GPollFD* pollfd)
{
GPollFD* new_pollfd;
g_return_val_if_fail (pollfd != NULL, NULL);
new_pollfd = g_new(GPollFD, 1);
*new_pollfd = *pollfd;
return new_pollfd;
}
GType
g_poll_fd_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static ("GPollFD",
(GBoxedCopyFunc)pollfd_copy,
(GBoxedFreeFunc)g_free);
return our_type;
}
/*****************************************/
#define RG_TARGET_NAMESPACE cPollFD
#define _SELF(s) ((GPollFD*)RVAL2BOXED(s, G_TYPE_POLL_FD))
static VALUE
rg_initialize(VALUE self, VALUE fd, VALUE events, VALUE revents)
{
GPollFD gfd;
gfd.fd = NUM2INT(fd);
gfd.events = NUM2INT(events);
gfd.revents = NUM2INT(revents);
G_INITIALIZE(self, g_boxed_copy(G_TYPE_POLL_FD, &gfd));
return Qnil;
}
static VALUE
rg_set_fd(VALUE self, VALUE fd)
{
_SELF(self)->fd = fd;
return self;
}
static VALUE
rg_fd(VALUE self)
{
return INT2NUM(_SELF(self)->fd);
}
static VALUE
rg_set_events(VALUE self, VALUE events)
{
_SELF(self)->events = events;
return self;
}
static VALUE
rg_events(VALUE self)
{
return INT2NUM(_SELF(self)->events);
}
static VALUE
rg_set_revents(VALUE self, VALUE revents)
{
_SELF(self)->revents = revents;
return self;
}
static VALUE
rg_revents(VALUE self)
{
return INT2NUM(_SELF(self)->revents);
}
void
Init_glib_poll_fd(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_POLL_FD, "PollFD", mGLib);
RG_DEF_METHOD(initialize, 3);
RG_DEF_METHOD(set_fd, 1);
RG_DEF_METHOD(fd, 0);
RG_DEF_METHOD(set_events, 1);
RG_DEF_METHOD(events, 0);
RG_DEF_METHOD(set_revents, 1);
RG_DEF_METHOD(revents, 0);
}

View File

@ -0,0 +1,64 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE mShell
static VALUE
rg_s_parse(G_GNUC_UNUSED VALUE self, VALUE command_line)
{
gint argc;
gchar **argv;
GError *error = NULL;
if (!g_shell_parse_argv(RVAL2CSTR(command_line), &argc, &argv, &error))
RAISE_GERROR(error);
return STRV2RVAL_FREE(argv);
}
static VALUE
rg_s_quote(G_GNUC_UNUSED VALUE self, VALUE unquoted_string)
{
return CSTR2RVAL_FREE(g_shell_quote(RVAL2CSTR(unquoted_string)));
}
static VALUE
rg_s_unquote(G_GNUC_UNUSED VALUE self, VALUE quoted_string)
{
GError *error = NULL;
gchar *str = g_shell_unquote(RVAL2CSTR(quoted_string), &error);
if (str == NULL)
RAISE_GERROR(error);
return CSTR2RVAL_FREE(str);
}
void
Init_glib_shell(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "Shell");
RG_DEF_SMETHOD(parse, 1);
RG_DEF_SMETHOD(quote, 1);
RG_DEF_SMETHOD(unquote, 1);
}

View File

@ -0,0 +1,34 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cShellError
void
Init_glib_shellerror(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_ERROR2(G_SHELL_ERROR, "ShellError", mGLib, rb_eRuntimeError);
rb_define_const(RG_TARGET_NAMESPACE, "BAD_QUOTING", INT2FIX(G_SHELL_ERROR_BAD_QUOTING));
rb_define_const(RG_TARGET_NAMESPACE, "EMPTY_STRING", INT2FIX(G_SHELL_ERROR_EMPTY_STRING));
rb_define_const(RG_TARGET_NAMESPACE, "FAILED", INT2FIX(G_SHELL_ERROR_FAILED));
}

View File

@ -0,0 +1,198 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
static ID id_call;
/*****************************************/
#if !GLIB_CHECK_VERSION(2,30,0)
static void
source_free(GSource *source)
{
g_source_unref(source);
g_source_destroy(source);
}
GType
g_source_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static ("GSource",
(GBoxedCopyFunc)g_source_ref,
(GBoxedFreeFunc)source_free);
return our_type;
}
#endif
/*****************************************/
#define RG_TARGET_NAMESPACE cSource
#define _SELF(s) ((GSource*)RVAL2BOXED(s, G_TYPE_SOURCE))
/*
GSource* g_source_new (GSourceFuncs *source_funcs,
guint struct_size);
*/
static VALUE
rg_attach(int argc, VALUE *argv, VALUE self)
{
VALUE context;
rb_scan_args(argc, argv, "01", &context);
return UINT2NUM(g_source_attach(_SELF(self),
RVAL2BOXED(context, G_TYPE_MAIN_CONTEXT)));
}
#if GLIB_CHECK_VERSION(2,12,0)
static VALUE
rg_destroyed_p(VALUE self)
{
return CBOOL2RVAL(g_source_is_destroyed(_SELF(self)));
}
#endif
static VALUE
rg_set_priority(VALUE self, VALUE priority)
{
g_source_set_priority(_SELF(self), NUM2INT(priority));
return self;
}
static VALUE
rg_priority(VALUE self)
{
return INT2NUM(g_source_get_priority(_SELF(self)));
}
static VALUE
rg_set_can_recurse(VALUE self, VALUE can_recurse)
{
g_source_set_can_recurse(_SELF(self), RVAL2CBOOL(can_recurse));
return self;
}
static VALUE
rg_can_recurse_p(VALUE self)
{
return CBOOL2RVAL(g_source_get_can_recurse(_SELF(self)));
}
static VALUE
rg_id(VALUE self)
{
return UINT2NUM(g_source_get_id(_SELF(self)));
}
static VALUE
rg_context(VALUE self)
{
GMainContext* context = g_source_get_context(_SELF(self));
return BOXED2RVAL(context, G_TYPE_MAIN_CONTEXT);
}
static gboolean
source_func(gpointer func)
{
return RVAL2CBOOL(rb_funcall((VALUE)func, id_call, 0));
}
static VALUE
rg_set_callback(VALUE self)
{
VALUE func = rb_block_proc();
G_RELATIVE(self, func);
g_source_set_callback(_SELF(self),
(GSourceFunc)source_func,
(gpointer)func,
(GDestroyNotify)NULL);
return self;
}
/*
void g_source_set_callback_indirect (GSource *source,
gpointer callback_data,
GSourceCallbackFuncs *callback_funcs);
*/
static VALUE
rg_add_poll(VALUE self, VALUE fd)
{
g_source_add_poll(_SELF(self), RVAL2BOXED(fd, G_TYPE_POLL_FD));
return self;
}
static VALUE
rg_remove_poll(VALUE self, VALUE fd)
{
g_source_remove_poll(_SELF(self), RVAL2BOXED(fd, G_TYPE_POLL_FD));
return self;
}
#if GLIB_CHECK_VERSION(2, 28, 0)
static VALUE
rg_time(VALUE self)
{
gint64 time;
time = g_source_get_time(_SELF(self));
return LL2NUM(time);
}
#endif
/* How can I implement them ?
gboolean g_source_remove_by_funcs_user_data
(GSourceFuncs *funcs,
gpointer user_data);
gboolean g_source_remove_by_user_data (gpointer user_data);
*/
void
Init_glib_source(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_SOURCE, "Source", mGLib);
id_call = rb_intern("call");
rb_define_const(RG_TARGET_NAMESPACE,
"REMOVE", CBOOL2RVAL(G_SOURCE_REMOVE));
rb_define_const(RG_TARGET_NAMESPACE,
"CONTINUE", CBOOL2RVAL(G_SOURCE_CONTINUE));
RG_DEF_METHOD(attach, -1);
#if GLIB_CHECK_VERSION(2,12,0)
RG_DEF_METHOD_P(destroyed, 0);
#endif
RG_DEF_METHOD(set_priority, 1);
RG_DEF_METHOD(priority, 0);
RG_DEF_METHOD(set_can_recurse, 1);
RG_DEF_METHOD_P(can_recurse, 0);
RG_DEF_METHOD(id, 0);
RG_DEF_METHOD(context, 0);
RG_DEF_METHOD(set_callback, 0);
RG_DEF_METHOD(add_poll, 1);
RG_DEF_METHOD(remove_poll, 1);
#if GLIB_CHECK_VERSION(2, 28, 0)
RG_DEF_METHOD(time, 0);
#endif
/* GLib::Source.remove is moved to rbglib_maincontext.c */
}

View File

@ -0,0 +1,245 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Masao Mutoh
* Copyright (C) 2004 Kazuhiro NISHIYAMA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mSpawn
static ID id_call;
static ID id_new;
static void
child_setup(gpointer func)
{
if (! NIL_P(func)){
rb_funcall((VALUE)func, id_call, 0);
}
}
static VALUE
rg_s_async_with_pipes(VALUE self, VALUE working_directory, VALUE argv, VALUE envp, VALUE flags)
{
GError *err = NULL;
gboolean ret;
GPid child_pid;
VALUE func = Qnil;
gchar **gargv;
gchar **genvp;
gint standard_input, standard_output, standard_error;
if (rb_block_given_p()) {
func = rb_block_proc();
G_RELATIVE(self, func);
}
gargv = (gchar **)RVAL2STRV(argv);
genvp = (gchar **)RVAL2STRV_ACCEPT_NIL(envp);
ret = g_spawn_async_with_pipes(RVAL2CSTR_ACCEPT_NIL(working_directory),
gargv, genvp, NUM2INT(flags),
(GSpawnChildSetupFunc)child_setup,
(gpointer)func,
&child_pid,
&standard_input, &standard_output,
&standard_error, &err);
g_free(gargv);
g_free(genvp);
if (!ret)
RAISE_GERROR(err);
return rb_ary_new3(4, INT2NUM((gint)child_pid),
rb_funcall(rb_cIO, id_new, 1, INT2NUM(standard_input)),
rb_funcall(rb_cIO, id_new, 1, INT2NUM(standard_output)),
rb_funcall(rb_cIO, id_new, 1, INT2NUM(standard_error)));
}
static VALUE
rg_s_async(VALUE self, VALUE working_directory, VALUE argv, VALUE envp, VALUE flags)
{
GError *err = NULL;
gboolean ret;
GPid child_pid;
VALUE func = Qnil;
gchar **gargv;
gchar **genvp;
if (rb_block_given_p()) {
func = rb_block_proc();
G_RELATIVE(self, func);
}
gargv = (gchar **)RVAL2STRV(argv);
genvp = (gchar **)RVAL2STRV_ACCEPT_NIL(envp);
ret = g_spawn_async(RVAL2CSTR_ACCEPT_NIL(working_directory),
gargv, genvp, NUM2INT(flags),
(GSpawnChildSetupFunc)child_setup, (gpointer)func,
&child_pid, &err);
g_free(gargv);
g_free(genvp);
if (!ret)
RAISE_GERROR(err);
return INT2NUM((int)child_pid);
}
static VALUE
rg_s_sync(VALUE self, VALUE working_directory, VALUE argv, VALUE envp, VALUE flags)
{
GError *err = NULL;
gboolean ret;
VALUE func = Qnil;
gchar** gargv;
gchar** genvp;
gchar *standard_output = NULL, *standard_error = NULL;
gint exit_status;
VALUE std_out, std_err;
if (rb_block_given_p()) {
func = rb_block_proc();
G_RELATIVE(self, func);
}
gargv = (gchar **)RVAL2STRV(argv);
genvp = (gchar **)RVAL2STRV_ACCEPT_NIL(envp);
ret = g_spawn_sync(RVAL2CSTR_ACCEPT_NIL(working_directory),
gargv, genvp, NUM2INT(flags),
(GSpawnChildSetupFunc)child_setup, (gpointer)func,
&standard_output, &standard_error,
&exit_status, &err);
g_free(gargv);
g_free(genvp);
if (!ret)
RAISE_GERROR(err);
if (standard_output) {
std_out = CSTR2RVAL(standard_output);
g_free(standard_output);
} else {
std_out = Qnil;
standard_output = NULL;
}
if (standard_error) {
std_err = CSTR2RVAL(standard_error);
g_free(standard_error);
standard_error = NULL;
} else {
std_err = Qnil;
}
if (! ret)
RAISE_GERROR(err);
return rb_ary_new3(3, std_out, std_err, INT2FIX(exit_status));
}
static VALUE
rg_s_command_line_sync(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
const gchar *command_line;
gchar *standard_output = NULL, *standard_error = NULL;
gint exit_status;
VALUE std_out, std_err;
gboolean ret;
command_line = RVAL2CSTR(str);
ret = g_spawn_command_line_sync(command_line,
&standard_output,
&standard_error,
&exit_status,
&err);
if (standard_output) {
std_out = CSTR2RVAL(standard_output);
g_free(standard_output);
} else {
std_out = Qnil;
standard_output = NULL;
}
if (standard_error) {
std_err = CSTR2RVAL(standard_error);
g_free(standard_error);
standard_error = NULL;
} else {
std_err = Qnil;
}
if (! ret)
RAISE_GERROR(err);
return rb_ary_new3(3, std_out, std_err, INT2FIX(exit_status));
}
static VALUE
rg_s_command_line_async(G_GNUC_UNUSED VALUE self, VALUE str)
{
GError *err = NULL;
const gchar *command_line;
VALUE ret;
command_line = StringValuePtr(str);
ret = CBOOL2RVAL(g_spawn_command_line_async(command_line, &err));
if (err != NULL)
RAISE_GERROR(err);
return ret;
}
#ifdef HAVE_G_SPAWN_CLOSE_PID
#define RVAL2GPID(value) ((GPid)NUM2INT(pid))
static VALUE
rg_s_close_pid(G_GNUC_UNUSED VALUE self, VALUE pid)
{
g_spawn_close_pid(RVAL2GPID(pid));
return Qnil;
}
#endif
void
Init_glib_spawn(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "Spawn");
id_call = rb_intern("call");
id_new = rb_intern("new");
/* glib/gspawn.h */
RG_DEF_SMETHOD(async_with_pipes, 4);
RG_DEF_SMETHOD(async, 4);
RG_DEF_SMETHOD(sync, 4);
RG_DEF_SMETHOD(command_line_sync, 1);
RG_DEF_SMETHOD(command_line_async, 1);
#ifdef HAVE_G_SPAWN_CLOSE_PID
RG_DEF_SMETHOD(close_pid, 1);
#endif
rb_define_const(RG_TARGET_NAMESPACE, "LEAVE_DESCRIPTORS_OPEN", INT2NUM(G_SPAWN_LEAVE_DESCRIPTORS_OPEN));
rb_define_const(RG_TARGET_NAMESPACE, "DO_NOT_REAP_CHILD", INT2NUM(G_SPAWN_DO_NOT_REAP_CHILD));
rb_define_const(RG_TARGET_NAMESPACE, "SEARCH_PATH", INT2NUM(G_SPAWN_SEARCH_PATH));
rb_define_const(RG_TARGET_NAMESPACE, "STDOUT_TO_DEV_NULL", INT2NUM(G_SPAWN_STDOUT_TO_DEV_NULL));
rb_define_const(RG_TARGET_NAMESPACE, "STDERR_TO_DEV_NULL", INT2NUM(G_SPAWN_STDERR_TO_DEV_NULL));
rb_define_const(RG_TARGET_NAMESPACE, "CHILD_INHERITS_STDIN", INT2NUM(G_SPAWN_CHILD_INHERITS_STDIN));
rb_define_const(RG_TARGET_NAMESPACE, "FILE_AND_ARGV_ZERO", INT2NUM(G_SPAWN_FILE_AND_ARGV_ZERO));
}

View File

@ -0,0 +1,53 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Masao Mutoh
* Copyright (C) 2004 Kazuhiro NISHIYAMA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE cSpawnError
void
Init_glib_spawnerror(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_ERROR2(G_SPAWN_ERROR, "SpawnError", mGLib, rb_eIOError);
rb_define_const(RG_TARGET_NAMESPACE, "FORK", INT2NUM(G_SPAWN_ERROR_FORK));
rb_define_const(RG_TARGET_NAMESPACE, "READ", INT2NUM(G_SPAWN_ERROR_READ));
rb_define_const(RG_TARGET_NAMESPACE, "CHDIR", INT2NUM(G_SPAWN_ERROR_CHDIR));
rb_define_const(RG_TARGET_NAMESPACE, "EACCES", INT2NUM(G_SPAWN_ERROR_ACCES));
rb_define_const(RG_TARGET_NAMESPACE, "EPERM", INT2NUM(G_SPAWN_ERROR_PERM));
rb_define_const(RG_TARGET_NAMESPACE, "E2BIG", INT2NUM(G_SPAWN_ERROR_2BIG));
rb_define_const(RG_TARGET_NAMESPACE, "ENOEXEC", INT2NUM(G_SPAWN_ERROR_NOEXEC));
rb_define_const(RG_TARGET_NAMESPACE, "ENAMETOOLONG", INT2NUM(G_SPAWN_ERROR_NAMETOOLONG));
rb_define_const(RG_TARGET_NAMESPACE, "ENOENT", INT2NUM(G_SPAWN_ERROR_NOENT));
rb_define_const(RG_TARGET_NAMESPACE, "ENOMEM", INT2NUM(G_SPAWN_ERROR_NOMEM));
rb_define_const(RG_TARGET_NAMESPACE, "ENOTDIR", INT2NUM(G_SPAWN_ERROR_NOTDIR));
rb_define_const(RG_TARGET_NAMESPACE, "ELOOP", INT2NUM(G_SPAWN_ERROR_LOOP));
rb_define_const(RG_TARGET_NAMESPACE, "ETXTBUSY", INT2NUM(G_SPAWN_ERROR_TXTBUSY));
rb_define_const(RG_TARGET_NAMESPACE, "EIO", INT2NUM(G_SPAWN_ERROR_IO));
rb_define_const(RG_TARGET_NAMESPACE, "ENFILE", INT2NUM(G_SPAWN_ERROR_NFILE));
rb_define_const(RG_TARGET_NAMESPACE, "EMFILE", INT2NUM(G_SPAWN_ERROR_MFILE));
rb_define_const(RG_TARGET_NAMESPACE, "EINVAL", INT2NUM(G_SPAWN_ERROR_INVAL));
rb_define_const(RG_TARGET_NAMESPACE, "EISDIR", INT2NUM(G_SPAWN_ERROR_ISDIR));
rb_define_const(RG_TARGET_NAMESPACE, "ELIBBAD", INT2NUM(G_SPAWN_ERROR_LIBBAD));
rb_define_const(RG_TARGET_NAMESPACE, "FAILED", INT2NUM(G_SPAWN_ERROR_FAILED));
}

View File

@ -0,0 +1,61 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cThread
static VALUE RG_TARGET_NAMESPACE;
static VALUE
rg_s_init(VALUE self)
{
#ifdef HAVE_G_THREAD_INIT
#ifdef G_THREADS_ENABLED
g_thread_init(NULL);
#endif
#endif
return self;
}
static VALUE
rg_s_supported_p(G_GNUC_UNUSED VALUE self)
{
#ifdef HAVE_G_THREAD_INIT
#ifdef G_THREADS_ENABLED
return CBOOL2RVAL(g_thread_supported());
#else
return Qfalse;
#endif
#else
return Qfalse;
#endif
}
void
Init_glib_threads(void)
{
RG_TARGET_NAMESPACE = rb_define_class_under(mGLib, "Thread", rb_cObject);
RG_DEF_SMETHOD(init, 0);
RG_DEF_SMETHOD_P(supported, 0);
}

View File

@ -0,0 +1,131 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#ifdef G_OS_WIN32
#include <windows.h>
#endif
/*****************************************/
/* This is stolen from gtimer.c of glib-2.6.2. */
struct _GTimer
{
#ifdef G_OS_WIN32
DWORD start;
DWORD end;
#else /* !G_OS_WIN32 */
struct timeval start;
struct timeval end;
#endif /* !G_OS_WIN32 */
guint active : 1;
};
static GTimer*
timer_copy(GTimer *timer)
{
GTimer* new_timer;
g_return_val_if_fail (timer != NULL, NULL);
new_timer = g_new(struct _GTimer, 1);
*new_timer = *timer;
return new_timer;
}
static GType
g_timer_get_type(void)
{
static GType our_type = 0;
if (our_type == 0)
our_type = g_boxed_type_register_static ("GTimer",
(GBoxedCopyFunc)timer_copy,
(GBoxedFreeFunc)g_timer_destroy);
return our_type;
}
/*****************************************/
#define G_TYPE_TIMER (g_timer_get_type())
#define RG_TARGET_NAMESPACE cTimer
#define _SELF(s) ((GTimer*)RVAL2BOXED(s, G_TYPE_TIMER))
static VALUE
rg_initialize(VALUE self)
{
G_INITIALIZE(self, g_timer_new());
return Qnil;
}
static VALUE
rg_start(VALUE self)
{
g_timer_start(_SELF(self));
return self;
}
static VALUE
rg_stop(VALUE self)
{
g_timer_stop(_SELF(self));
return self;
}
#if GLIB_CHECK_VERSION(2,4,0)
static VALUE
rg_continue(VALUE self)
{
g_timer_continue(_SELF(self));
return self;
}
#endif
static VALUE
rg_elapsed(VALUE self)
{
gulong microseconds;
gdouble ret = g_timer_elapsed(_SELF(self), &microseconds);
return rb_assoc_new(rb_float_new(ret), ULONG2NUM(microseconds));
}
static VALUE
rg_reset(VALUE self)
{
g_timer_reset(_SELF(self));
return self;
}
void
Init_glib_timer(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_TIMER, "Timer", mGLib);
RG_DEF_METHOD(initialize, 0);
RG_DEF_METHOD(start, 0);
RG_DEF_METHOD(stop, 0);
#if GLIB_CHECK_VERSION(2,4,0)
RG_DEF_METHOD(continue, 0);
#endif
RG_DEF_METHOD(elapsed, 0);
RG_DEF_METHOD(reset, 0);
}

View File

@ -0,0 +1,79 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mUCS4
static VALUE
rg_s_to_utf16(G_GNUC_UNUSED VALUE self, VALUE rb_ucs4)
{
VALUE result;
gunichar *ucs4;
gunichar2 *utf16;
glong len, items_written;
GError *error = NULL;
ucs4 = (gunichar *)StringValuePtr(rb_ucs4);
len = RSTRING_LEN(rb_ucs4) / sizeof(*ucs4);
utf16 = g_ucs4_to_utf16(ucs4, len, NULL, &items_written, &error);
if (error)
RAISE_GERROR(error);
result = CSTR2RVAL_LEN_UTF16((char *)utf16,
items_written * sizeof(*utf16));
g_free(utf16);
return result;
}
static VALUE
rg_s_to_utf8(G_GNUC_UNUSED VALUE self, VALUE rb_ucs4)
{
VALUE result;
gunichar *ucs4;
gchar *utf8;
glong len, items_written;
GError *error = NULL;
ucs4 = (gunichar *)StringValuePtr(rb_ucs4);
len = RSTRING_LEN(rb_ucs4) / sizeof(*ucs4);
utf8 = g_ucs4_to_utf8(ucs4, len, NULL, &items_written, &error);
if (error)
RAISE_GERROR(error);
result = CSTR2RVAL_LEN(utf8, items_written);
g_free(utf8);
return result;
}
void
Init_glib_ucs4(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "UCS4");
RG_DEF_SMETHOD(to_utf16, 1);
RG_DEF_SMETHOD(to_utf8, 1);
}

View File

@ -0,0 +1,209 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mUniChar
#define DEF_IS_UNICHAR(name) \
static VALUE \
rbglib_m_unichar_is ## name(G_GNUC_UNUSED VALUE self, VALUE unichar) \
{ \
return CBOOL2RVAL(g_unichar_is ## name(NUM2UINT(unichar))); \
}
DEF_IS_UNICHAR(alnum)
DEF_IS_UNICHAR(alpha)
DEF_IS_UNICHAR(cntrl)
DEF_IS_UNICHAR(digit)
DEF_IS_UNICHAR(graph)
DEF_IS_UNICHAR(lower)
DEF_IS_UNICHAR(print)
DEF_IS_UNICHAR(punct)
DEF_IS_UNICHAR(space)
DEF_IS_UNICHAR(upper)
DEF_IS_UNICHAR(xdigit)
DEF_IS_UNICHAR(title)
DEF_IS_UNICHAR(defined)
DEF_IS_UNICHAR(wide)
#if GLIB_CHECK_VERSION(2,12,0)
DEF_IS_UNICHAR(wide_cjk)
#endif
#undef DEF_IS_UNICHAR
static VALUE
rg_s_to_upper(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return UINT2NUM(g_unichar_toupper(NUM2UINT(unichar)));
}
static VALUE
rg_s_to_lower(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return UINT2NUM(g_unichar_tolower(NUM2UINT(unichar)));
}
static VALUE
rg_s_to_title(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return UINT2NUM(g_unichar_totitle(NUM2UINT(unichar)));
}
static VALUE
rg_s_digit_value(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return INT2NUM(g_unichar_digit_value(NUM2UINT(unichar)));
}
static VALUE
rg_s_xdigit_value(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return INT2NUM(g_unichar_xdigit_value(NUM2UINT(unichar)));
}
static VALUE
rg_s_type(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return GENUM2RVAL(g_unichar_type(NUM2UINT(unichar)),
G_TYPE_UNICODE_TYPE);
}
static VALUE
rg_s_break_type(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return GENUM2RVAL(g_unichar_break_type(NUM2UINT(unichar)),
G_TYPE_UNICODE_BREAK_TYPE);
}
#if GLIB_CHECK_VERSION(2,4,0)
static VALUE
rg_s_get_mirror_char(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
gunichar mirrored_char;
if (g_unichar_get_mirror_char(NUM2UINT(unichar), &mirrored_char)) {
return UINT2NUM(mirrored_char);
} else {
return unichar;
}
}
#endif
#if GLIB_CHECK_VERSION(2,14,0)
static VALUE
rg_s_combining_class(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return INT2NUM(g_unichar_combining_class(NUM2UINT(unichar)));
}
static VALUE
rg_s_get_script(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return GENUM2RVAL(g_unichar_get_script(NUM2UINT(unichar)),
G_TYPE_UNICODE_SCRIPT);
}
static VALUE
rg_s_mark_p(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return CBOOL2RVAL(g_unichar_ismark(NUM2UINT(unichar)));
}
static VALUE
rg_s_zero_width_p(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
return CBOOL2RVAL(g_unichar_iszerowidth(NUM2UINT(unichar)));
}
#endif
static VALUE
rg_s_to_utf8(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
gchar utf8[6];
gint len;
len = g_unichar_to_utf8(NUM2UINT(unichar), utf8);
return CSTR2RVAL_LEN(utf8, len);
}
void
Init_glib_unichar(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "UniChar");
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "alnum?",
rbglib_m_unichar_isalnum, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "alpha?",
rbglib_m_unichar_isalpha, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "cntrl?",
rbglib_m_unichar_iscntrl, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "digit?",
rbglib_m_unichar_isdigit, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "graph?",
rbglib_m_unichar_isgraph, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "lower?",
rbglib_m_unichar_islower, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "print?",
rbglib_m_unichar_isprint, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "punct?",
rbglib_m_unichar_ispunct, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "space?",
rbglib_m_unichar_isspace, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "upper?",
rbglib_m_unichar_isupper, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "xdigit?",
rbglib_m_unichar_isxdigit, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "title?",
rbglib_m_unichar_istitle, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "defined?",
rbglib_m_unichar_isdefined, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "wide?",
rbglib_m_unichar_iswide, 1);
#if GLIB_CHECK_VERSION(2,12,0)
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "wide_cjk?",
rbglib_m_unichar_iswide_cjk, 1);
#endif
RG_DEF_SMETHOD(to_upper, 1);
RG_DEF_SMETHOD(to_lower, 1);
RG_DEF_SMETHOD(to_title, 1);
RG_DEF_SMETHOD(digit_value, 1);
RG_DEF_SMETHOD(xdigit_value, 1);
RG_DEF_SMETHOD(type, 1);
RG_DEF_SMETHOD(break_type, 1);
#if GLIB_CHECK_VERSION(2,4,0)
RG_DEF_SMETHOD(get_mirror_char, 1);
#endif
#if GLIB_CHECK_VERSION(2,14,0)
RG_DEF_SMETHOD(combining_class, 1);
RG_DEF_SMETHOD(get_script, 1);
RG_DEF_SMETHOD_P(mark, 1);
RG_DEF_SMETHOD_P(zero_width, 1);
#endif
RG_DEF_SMETHOD(to_utf8, 1);
}

View File

@ -0,0 +1,90 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mUnicode
static VALUE
rbglib_m_charset(G_GNUC_UNUSED VALUE self)
{
const char *charset;
g_get_charset(&charset);
return CSTR2RVAL(charset);
}
static VALUE
rg_s_canonical_ordering(G_GNUC_UNUSED VALUE self, VALUE rb_ucs4)
{
VALUE normalized_ucs4;
gchar *original_str;
gunichar *ucs4;
gint len;
original_str = StringValuePtr(rb_ucs4);
len = RSTRING_LEN(rb_ucs4);
ucs4 = g_memdup(original_str, len);
g_unicode_canonical_ordering(ucs4, len);
normalized_ucs4 = CSTR2RVAL_LEN_UCS4((const char *)ucs4, len);
g_free(ucs4);
return normalized_ucs4;
}
static VALUE
rg_s_canonical_decomposition(G_GNUC_UNUSED VALUE self, VALUE unichar)
{
VALUE normalized_ucs4;
gunichar *ucs4;
gsize len;
ucs4 = g_unicode_canonical_decomposition(NUM2UINT(unichar), &len);
normalized_ucs4 = CSTR2RVAL_LEN_UCS4((const char *)ucs4,
len * sizeof(gunichar));
g_free(ucs4);
return normalized_ucs4;
}
void
Init_glib_unicode(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "Unicode");
/* GUnicodeType */
G_DEF_CLASS(G_TYPE_UNICODE_TYPE, "Type", RG_TARGET_NAMESPACE);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_UNICODE_TYPE, "G_UNICODE_");
/* GUnicodeBreakType */
G_DEF_CLASS(G_TYPE_UNICODE_BREAK_TYPE, "BreakType", RG_TARGET_NAMESPACE);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_UNICODE_BREAK_TYPE, "G_UNICODE_");
#if GLIB_CHECK_VERSION(2,14,0)
/* GUnicodeScript */
G_DEF_CLASS(G_TYPE_UNICODE_SCRIPT, "Script", RG_TARGET_NAMESPACE);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_UNICODE_SCRIPT, "G_UNICODE_");
#endif
G_DEF_CLASS(G_TYPE_NORMALIZE_MODE, "NormalizeMode", mGLib);
rbg_define_singleton_method(mGLib, "charset", rbglib_m_charset, 0);
RG_DEF_SMETHOD(canonical_ordering, 1);
RG_DEF_SMETHOD(canonical_decomposition, 1);
}

View File

@ -0,0 +1,78 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mUTF16
static VALUE
rg_s_to_ucs4(G_GNUC_UNUSED VALUE self, VALUE rb_utf16)
{
VALUE result;
gunichar *ucs4;
gunichar2 *utf16;
glong len, items_written;
GError *error = NULL;
utf16 = (gunichar2 *)StringValueCStr(rb_utf16);
len = RSTRING_LEN(rb_utf16) / sizeof(*utf16);
ucs4 = g_utf16_to_ucs4(utf16, len, NULL, &items_written, &error);
if (error)
RAISE_GERROR(error);
result = CSTR2RVAL_LEN_UCS4((char *)ucs4, items_written * sizeof(*ucs4));
g_free(ucs4);
return result;
}
static VALUE
rg_s_to_utf8(G_GNUC_UNUSED VALUE self, VALUE rb_utf16)
{
VALUE result;
gchar *utf8;
gunichar2 *utf16;
glong len, items_written;
GError *error = NULL;
utf16 = (gunichar2 *)StringValueCStr(rb_utf16);
len = RSTRING_LEN(rb_utf16) / sizeof(*utf16);
utf8 = g_utf16_to_utf8(utf16, len, NULL, &items_written, &error);
if (error)
RAISE_GERROR(error);
result = CSTR2RVAL_LEN(utf8, items_written * sizeof(*utf8));
g_free(utf8);
return result;
}
void
Init_glib_utf16(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "UTF16");
RG_DEF_SMETHOD(to_ucs4, 1);
RG_DEF_SMETHOD(to_utf8, 1);
}

View File

@ -0,0 +1,259 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#define RG_TARGET_NAMESPACE mUTF8
static VALUE
rg_s_get_char(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE utf8, validate;
gunichar result;
rb_scan_args(argc, argv, "11", &utf8, &validate);
if (RVAL2CBOOL(validate)) {
StringValue(utf8);
result = g_utf8_get_char_validated(RSTRING_PTR(utf8),
RSTRING_LEN(utf8));
if (result == (gunichar)-1) {
return INT2NUM(-1);
} else if (result == (gunichar)-2) {
return INT2NUM(-2);
}
} else {
result = g_utf8_get_char(StringValueCStr(utf8));
}
return UINT2NUM(result);
}
static VALUE
rg_s_size(G_GNUC_UNUSED VALUE self, VALUE rb_utf8)
{
gchar *utf8;
utf8 = StringValueCStr(rb_utf8);
return INT2NUM(g_utf8_strlen(utf8, RSTRING_LEN(rb_utf8)));
}
static VALUE
rg_s_reverse(G_GNUC_UNUSED VALUE self, VALUE rb_utf8)
{
VALUE result;
gchar *utf8, *reversed_utf8;
utf8 = StringValueCStr(rb_utf8);
reversed_utf8 = g_utf8_strreverse(utf8, RSTRING_LEN(rb_utf8));
result = CSTR2RVAL(reversed_utf8);
g_free(reversed_utf8);
return result;
}
static VALUE
rg_s_validate(G_GNUC_UNUSED VALUE self, VALUE str)
{
StringValue(str);
return CBOOL2RVAL(g_utf8_validate(RSTRING_PTR(str), RSTRING_LEN(str),
NULL));
}
static VALUE
rg_s_upcase(G_GNUC_UNUSED VALUE self, VALUE rb_utf8)
{
VALUE result;
gchar *utf8, *upcased_utf8;
utf8 = StringValueCStr(rb_utf8);
upcased_utf8 = g_utf8_strup(utf8, RSTRING_LEN(rb_utf8));
result = CSTR2RVAL(upcased_utf8);
g_free(upcased_utf8);
return result;
}
static VALUE
rg_s_downcase(G_GNUC_UNUSED VALUE self, VALUE rb_utf8)
{
VALUE result;
gchar *utf8, *downcased_utf8;
utf8 = StringValueCStr(rb_utf8);
downcased_utf8 = g_utf8_strdown(utf8, RSTRING_LEN(rb_utf8));
result = CSTR2RVAL(downcased_utf8);
g_free(downcased_utf8);
return result;
}
static VALUE
rg_s_casefold(G_GNUC_UNUSED VALUE self, VALUE rb_utf8)
{
VALUE result;
gchar *utf8, *casefolded_utf8;
utf8 = StringValueCStr(rb_utf8);
casefolded_utf8 = g_utf8_casefold(utf8, RSTRING_LEN(rb_utf8));
result = CSTR2RVAL(casefolded_utf8);
g_free(casefolded_utf8);
return result;
}
static VALUE
rg_s_normalize(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE rb_utf8, rb_mode, result;
gchar *utf8, *normalized_utf8;
GNormalizeMode mode = G_NORMALIZE_DEFAULT;
rb_scan_args(argc, argv, "11", &rb_utf8, &rb_mode);
if (!NIL_P(rb_mode))
mode = RVAL2GENUM(rb_mode, G_TYPE_NORMALIZE_MODE);
utf8 = StringValueCStr(rb_utf8);
normalized_utf8 = g_utf8_normalize(utf8, RSTRING_LEN(rb_utf8), mode);
result = CSTR2RVAL(normalized_utf8);
g_free(normalized_utf8);
return result;
}
static VALUE
rg_s_collate(G_GNUC_UNUSED VALUE self, VALUE utf8a, VALUE utf8b)
{
return INT2NUM(g_utf8_collate(StringValueCStr(utf8a),
StringValueCStr(utf8b)));
}
static VALUE
rg_s_collate_key(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE result, rb_utf8, for_filename;
gchar *key, *utf8;
gssize len;
rb_scan_args(argc, argv, "11", &rb_utf8, &for_filename);
utf8 = StringValueCStr(rb_utf8);
len = RSTRING_LEN(rb_utf8);
#if GLIB_CHECK_VERSION(2,8,0)
if (RVAL2CBOOL(for_filename))
key = g_utf8_collate_key_for_filename(utf8, len);
else
#endif
key = g_utf8_collate_key(utf8, len);
result = CSTR2RVAL(key);
g_free(key);
return result;
}
static VALUE
rg_s_to_utf16(G_GNUC_UNUSED VALUE self, VALUE rb_utf8)
{
VALUE result;
gchar *utf8;
gunichar2 *utf16;
glong len, items_written;
GError *error = NULL;
utf8 = StringValueCStr(rb_utf8);
len = RSTRING_LEN(rb_utf8);
utf16 = g_utf8_to_utf16(utf8, len, NULL, &items_written, &error);
if (error)
RAISE_GERROR(error);
result = CSTR2RVAL_LEN_UTF16((char *)utf16,
items_written * sizeof(*utf16));
g_free(utf16);
return result;
}
static VALUE
rg_s_to_ucs4(int argc, VALUE *argv, G_GNUC_UNUSED VALUE self)
{
VALUE result, rb_utf8, is_fast;
gchar *utf8;
gunichar *ucs4;
glong len, items_written;
rb_scan_args(argc, argv, "11", &rb_utf8, &is_fast);
utf8 = StringValueCStr(rb_utf8);
len = RSTRING_LEN(rb_utf8);
if (RVAL2CBOOL(is_fast)) {
ucs4 = g_utf8_to_ucs4_fast(utf8, len, &items_written);
} else {
GError *error = NULL;
ucs4 = g_utf8_to_ucs4(utf8, len, NULL, &items_written, &error);
if (error)
RAISE_GERROR(error);
}
result = CSTR2RVAL_LEN_UCS4((char *)ucs4, items_written * sizeof(*ucs4));
g_free(ucs4);
return result;
}
void
Init_glib_utf8(void)
{
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "UTF8");
/*
Not implemented.
g_utf8_next_char
*/
RG_DEF_SMETHOD(get_char, -1);
/*
Not implemented.
g_utf8_offset_to_pointer
g_utf8_pointer_to_offset
g_utf8_prev_char
g_utf8_find_next_char
g_utf8_find_prev_char
g_utf8_prev_char
*/
RG_DEF_SMETHOD(size, 1);
/*
Not implemented.
g_utf8_strncpy
g_utf8_strrchr
*/
RG_DEF_SMETHOD(reverse, 1);
RG_DEF_SMETHOD(validate, 1);
RG_DEF_SMETHOD(upcase, 1);
RG_DEF_SMETHOD(downcase, 1);
RG_DEF_SMETHOD(casefold, 1);
RG_DEF_SMETHOD(normalize, -1);
RG_DEF_SMETHOD(collate, 2);
RG_DEF_SMETHOD(collate_key, -1);
RG_DEF_SMETHOD(to_utf16, 1);
RG_DEF_SMETHOD(to_ucs4, -1);
}

View File

@ -0,0 +1,350 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Pascal Terjan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE mGLib
#if GLIB_CHECK_VERSION(2,2,0)
static VALUE
rg_s_application_name(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_application_name());
}
static VALUE
rg_s_set_application_name(VALUE self, VALUE application_name)
{
g_set_prgname(RVAL2CSTR_ACCEPT_NIL(application_name));
return self;
}
#endif
static VALUE
rg_s_prgname(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_prgname());
}
static VALUE
rg_s_set_prgname(VALUE self, VALUE prgname)
{
g_set_prgname(RVAL2CSTR_ACCEPT_NIL(prgname));
return self;
}
static VALUE
rg_s_getenv(G_GNUC_UNUSED VALUE self, VALUE variable)
{
return CSTR2RVAL(g_getenv(RVAL2CSTR(variable)));
}
#if GLIB_CHECK_VERSION(2,4,0)
static VALUE
rg_s_setenv(G_GNUC_UNUSED VALUE self, VALUE variable, VALUE value, VALUE overwrite)
{
return CBOOL2RVAL(g_setenv(RVAL2CSTR(variable),
RVAL2CSTR_ACCEPT_NIL(value),
RVAL2CBOOL(overwrite)));
}
static VALUE
rg_s_unsetenv(VALUE self, VALUE variable)
{
g_unsetenv(RVAL2CSTR(variable));
return self;
}
#endif
#if GLIB_CHECK_VERSION(2,8,0)
#ifdef HAVE_G_LISTENV
static VALUE
rg_s_listenv(G_GNUC_UNUSED VALUE self)
{
gchar** c_list;
gchar** c_var;
VALUE r_list = rb_ary_new();
c_list = g_listenv();
c_var = c_list;
while(*c_var) {
rb_ary_push(r_list, CSTR2RVAL(*(c_var++)));
}
g_strfreev(c_list);
return r_list;
}
#endif
static VALUE
rg_s_host_name(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_host_name());
}
#endif
static VALUE
rg_s_user_name(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_user_name());
}
static VALUE
rg_s_real_name(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_real_name());
}
#if GLIB_CHECK_VERSION(2, 6, 0)
static VALUE
rg_s_user_cache_dir(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_user_cache_dir());
}
static VALUE
rg_s_user_data_dir(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_user_data_dir());
}
static VALUE
rg_s_user_config_dir(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_user_config_dir());
}
static VALUE
rg_s_system_data_dirs(G_GNUC_UNUSED VALUE self)
{
return STRV2RVAL((const gchar **)g_get_system_data_dirs());
}
static VALUE
rg_s_system_config_dirs(G_GNUC_UNUSED VALUE self)
{
return STRV2RVAL((const gchar **)g_get_system_config_dirs());
}
#endif
#if GLIB_CHECK_VERSION(2, 14, 0)
static VALUE
rg_s_get_user_special_dir(G_GNUC_UNUSED VALUE self, VALUE directory)
{
return CSTR2RVAL(g_get_user_special_dir(RVAL2GENUM(directory,
G_TYPE_USER_DIRECTORY)));
}
#endif
static VALUE
rg_s_home_dir(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_home_dir());
}
static VALUE
rg_s_tmp_dir(G_GNUC_UNUSED VALUE self)
{
return CSTR2RVAL(g_get_tmp_dir());
}
static VALUE
rg_s_current_dir(G_GNUC_UNUSED VALUE self)
{
gchar* dir = g_get_current_dir();
VALUE ret = CSTR2RVAL(dir);
g_free(dir);
return ret;
}
static VALUE
rg_s_path_is_absolute_p(G_GNUC_UNUSED VALUE self, VALUE fname)
{
return CBOOL2RVAL(g_path_is_absolute(RVAL2CSTR(fname)));
}
static VALUE
rg_s_path_skip_root(G_GNUC_UNUSED VALUE self, VALUE fname)
{
return CSTR2RVAL(g_path_skip_root(RVAL2CSTR(fname)));
}
static VALUE
rg_s_path_get_basename(G_GNUC_UNUSED VALUE self, VALUE fname)
{
return CSTR2RVAL(g_path_get_basename(RVAL2CSTR(fname)));
}
static VALUE
rg_s_path_get_dirname(G_GNUC_UNUSED VALUE self, VALUE fname)
{
return CSTR2RVAL(g_path_get_dirname(RVAL2CSTR(fname)));
}
/*
Use File.join()
gchar* g_build_filename (const gchar *first_element,
...);
gchar* g_build_filenamev (gchar **args);
gchar* g_build_path (const gchar *separator,
const gchar *first_element,
...);
gchar* g_build_pathv (const gchar *separator,
gchar **args);
*/
static VALUE
rg_s_find_program_in_path(G_GNUC_UNUSED VALUE self, VALUE program)
{
gchar* path = g_find_program_in_path(RVAL2CSTR(program));
VALUE ret = CSTR2RVAL(path);
g_free(path);
return ret;
}
static VALUE
rg_s_bit_nth_lsf(G_GNUC_UNUSED VALUE self, VALUE mask, VALUE nth_bit)
{
return INT2NUM(g_bit_nth_lsf(NUM2ULONG(mask), NUM2INT(nth_bit)));
}
static VALUE
rg_s_bit_nth_msf(G_GNUC_UNUSED VALUE self, VALUE mask, VALUE nth_bit)
{
return INT2NUM(g_bit_nth_msf(NUM2ULONG(mask), NUM2INT(nth_bit)));
}
static VALUE
rg_s_bit_storage(G_GNUC_UNUSED VALUE self, VALUE number)
{
return UINT2NUM(g_bit_storage(NUM2ULONG(number)));
}
static VALUE
rg_s_spaced_primes_closest(G_GNUC_UNUSED VALUE self, VALUE num)
{
return UINT2NUM(g_spaced_primes_closest(NUM2UINT(num)));
}
/*
Use at_exit of ruby instead.
void g_atexit (GVoidFunc func);
*/
static VALUE
rg_s_parse_debug_string(G_GNUC_UNUSED VALUE self, VALUE string, VALUE keys)
{
gint i, nkeys;
VALUE ary;
GDebugKey* gkeys;
Check_Type(keys, RUBY_T_HASH);
ary = rb_funcall(keys, rb_intern("to_a"), 0);
nkeys = RARRAY_LEN(ary);
gkeys = ALLOCA_N(GDebugKey, nkeys);
for (i = 0; i < nkeys; i++) {
gkeys[i].key = RVAL2CSTR(RARRAY_PTR(RARRAY_PTR(ary)[i])[0]);
gkeys[i].value = NUM2UINT(RARRAY_PTR(RARRAY_PTR(ary)[i])[1]);
}
return UINT2NUM(g_parse_debug_string(RVAL2CSTR(string), gkeys, nkeys));
}
/*
void (*GVoidFunc) (void);
void (*GFreeFunc) (gpointer data);
Don't need them.
void g_qsort_with_data (gconstpointer pbase,
gint total_elems,
gsize size,
GCompareDataFunc compare_func,
gpointer user_data);
void g_nullify_pointer (gpointer *nullify_location);
*/
static VALUE
rg_s_check_version_p(G_GNUC_UNUSED VALUE self, VALUE major, VALUE minor, VALUE micro)
{
return CBOOL2RVAL(glib_major_version > NUM2UINT(major) ||
(glib_major_version == NUM2UINT(major) &&
glib_minor_version > NUM2UINT(minor)) ||
(glib_major_version == NUM2UINT(major) &&
glib_minor_version == NUM2UINT(minor) &&
glib_micro_version >= NUM2UINT(micro)));
}
void
Init_glib_utils(void)
{
/* glib/gutils.h */
#if GLIB_CHECK_VERSION(2, 14, 0)
G_DEF_CLASS(G_TYPE_USER_DIRECTORY, "UserDirectory", RG_TARGET_NAMESPACE);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_USER_DIRECTORY, "G_");
#endif
#if GLIB_CHECK_VERSION(2,2,0)
RG_DEF_SMETHOD(application_name, 0);
RG_DEF_SMETHOD(set_application_name, 1);
#endif
RG_DEF_SMETHOD(prgname, 0);
RG_DEF_SMETHOD(set_prgname, 1);
RG_DEF_SMETHOD(getenv, 1);
#if GLIB_CHECK_VERSION(2,4,0)
RG_DEF_SMETHOD(setenv, 2);
RG_DEF_SMETHOD(unsetenv, 1);
#endif
#if GLIB_CHECK_VERSION(2,8,0)
#ifdef HAVE_G_LISTENV
RG_DEF_SMETHOD(listenv, 0);
#endif
RG_DEF_SMETHOD(host_name, 0);
#endif
RG_DEF_SMETHOD(user_name, 0);
RG_DEF_SMETHOD(real_name, 0);
#if GLIB_CHECK_VERSION(2, 6, 0)
RG_DEF_SMETHOD(user_cache_dir, 0);
RG_DEF_SMETHOD(user_data_dir, 0);
RG_DEF_SMETHOD(user_config_dir, 0);
RG_DEF_SMETHOD(system_data_dirs, 0);
RG_DEF_SMETHOD(system_config_dirs, 0);
#endif
#if GLIB_CHECK_VERSION(2, 14, 0)
RG_DEF_SMETHOD(get_user_special_dir, 1);
#endif
RG_DEF_SMETHOD(home_dir, 0);
RG_DEF_SMETHOD(tmp_dir, 0);
RG_DEF_SMETHOD(current_dir, 0);
RG_DEF_SMETHOD_P(path_is_absolute, 1);
RG_DEF_SMETHOD(path_skip_root, 1);
RG_DEF_SMETHOD(path_get_basename, 1);
RG_DEF_SMETHOD(path_get_dirname, 1);
RG_DEF_SMETHOD(find_program_in_path, 1);
RG_DEF_SMETHOD(bit_nth_lsf, 2);
RG_DEF_SMETHOD(bit_nth_msf, 2);
RG_DEF_SMETHOD(bit_storage, 1);
RG_DEF_SMETHOD(spaced_primes_closest, 1);
RG_DEF_SMETHOD(parse_debug_string, 2);
RG_DEF_SMETHOD_P(check_version, 3);
}

View File

@ -0,0 +1,119 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Kouhei Sutou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbglib.h"
#ifdef G_OS_WIN32
#define RG_TARGET_NAMESPACE mWin32
static VALUE
rg_s_error_message(VALUE self, VALUE error)
{
return CSTR2RVAL_FREE(g_win32_error_message(NUM2INT(error)));
}
static VALUE
rg_s_locale(VALUE self)
{
return CSTR2RVAL_FREE(g_win32_getlocale());
}
static VALUE
rbglib_m_win32_locale_deprecated(VALUE self)
{
rb_warn("GLib.win32_locale() is deprecated. Use GLib::Win32.locale instead");
return rg_s_locale(self);
}
#if GLIB_CHECK_VERSION(2,6,0)
static VALUE
rg_s_version(VALUE self)
{
return UINT2NUM(g_win32_get_windows_version());
}
#endif
#if GLIB_CHECK_VERSION(2,8,0)
static VALUE
rg_s_locale_filename_from_utf8(VALUE self, VALUE utf8_filename)
{
return CSTR2RVAL_FREE(g_win32_locale_filename_from_utf8(RVAL2CSTR(utf8_filename)));
}
static VALUE
rbglib_m_win32_locale_filename_from_utf8_deprecated(VALUE self,
VALUE utf8_filename)
{
rb_warn("GLib.win32_locale_filename_from_utf8() is deprecated. Use GLib::Win32.locale_filename_from_utf8 instead");
return rg_s_locale_filename_from_utf8(self, utf8_filename);
}
#endif
# if GLIB_CHECK_VERSION(2, 16, 0)
static VALUE
rg_s_get_package_installation_directory_of_module(int argc,
VALUE *argv,
VALUE self)
{
VALUE rb_module;
gchar *directory;
gpointer hmodule;
rb_scan_args(argc, argv, "01", &rb_module);
if (NIL_P(rb_module))
hmodule = NULL;
else
hmodule = GINT_TO_POINTER(NUM2INT(rb_module));
directory = g_win32_get_package_installation_directory_of_module(hmodule);
return CSTR2RVAL_FREE(directory);
}
# endif
#endif
void
Init_glib_win32(void)
{
#ifdef G_OS_WIN32
/* glib/gwin32.h */
VALUE RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "Win32");
RG_DEF_SMETHOD(error_message, 1);
RG_DEF_SMETHOD(locale, 0);
RG_DEF_SMETHOD(version, 0);
/* Deprecated */
rbg_define_singleton_method(mGLib, "win32_locale", rbglib_m_win32_locale_deprecated, 0);
# if GLIB_CHECK_VERSION(2,8,0)
RG_DEF_SMETHOD(locale_filename_from_utf8, 1);
/* Deprecated */
rbg_define_singleton_method(mGLib, "win32_locale_filename_from_utf8",
rbglib_m_win32_locale_filename_from_utf8_deprecated, 1);
# endif
# if GLIB_CHECK_VERSION(2, 16, 0)
RG_DEF_SMETHOD(get_package_installation_directory_of_module, -1);
# endif
#endif
}

View File

@ -0,0 +1,56 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
static VALUE
rbg_filename_gslist_to_array_free_body(VALUE list)
{
VALUE ary = rb_ary_new();
GSList *p;
for (p = (GSList *)list; p != NULL; p = g_slist_next(p))
rb_ary_push(ary, CSTRFILENAME2RVAL(p->data));
return ary;
}
static VALUE
rbg_filename_gslist_to_array_free_ensure(VALUE val)
{
GSList *list = (GSList *)val;
GSList *p;
for (p = list; p != NULL; p = g_slist_next(p))
g_free((gchar *)p->data);
g_slist_free(list);
return Qnil;
}
VALUE
rbg_filename_gslist_to_array_free(GSList *list)
{
return rb_ensure(rbg_filename_gslist_to_array_free_body, (VALUE)list,
rbg_filename_gslist_to_array_free_ensure, (VALUE)list);
}

View File

@ -0,0 +1,34 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2005 Ruby-GNOME2 Project
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGLIBDEPRECATED_H__
#define __RBGLIBDEPRECATED_H__
G_BEGIN_DECLS
#define CSTRFILENAMEARRAY2RVAL_FREE(s) (rbg_filename_gslist_to_array_free(s))
extern VALUE rbg_filename_gslist_to_array_free(GSList *list);
G_END_DECLS
#endif /* __RBGLIBDEPRECATED_H__ */

View File

@ -0,0 +1,279 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE rbgobj_cBoxed
VALUE RG_TARGET_NAMESPACE;
static void
boxed_mark(boxed_holder *holder)
{
const RGObjClassInfo *cinfo;
cinfo = GTYPE2CINFO_NO_CREATE(holder->type);
if (cinfo && cinfo->mark)
cinfo->mark(holder->boxed);
}
static void
boxed_free(boxed_holder *holder)
{
const RGObjClassInfo *cinfo;
cinfo = GTYPE2CINFO_NO_CREATE(holder->type);
if (cinfo && cinfo->free)
cinfo->free(holder->boxed);
if (holder->own && holder->boxed)
g_boxed_free(holder->type, holder->boxed);
free(holder);
}
/**********************************************************************/
static VALUE
rbgobj_boxed_s_allocate(VALUE klass)
{
const RGObjClassInfo *cinfo = rbgobj_lookup_class(klass);
boxed_holder *holder;
VALUE result;
if (cinfo->gtype == G_TYPE_BOXED)
rb_raise(rb_eTypeError, "abstract class");
result = Data_Make_Struct(klass, boxed_holder,
boxed_mark, boxed_free, holder);
holder->type = cinfo->gtype;
holder->boxed = NULL;
holder->own = FALSE;
return result;
}
static G_GNUC_NORETURN VALUE
rg_initialize(VALUE self)
{
rb_raise(rb_eTypeError, "can't initialize %s",
rb_class2name(CLASS_OF(self)));
}
static VALUE
rg_inspect(VALUE self)
{
boxed_holder *holder;
gchar *s;
VALUE result;
Data_Get_Struct(self, boxed_holder, holder);
s = g_strdup_printf("#<%s:%p ptr=%p own=%s>",
rb_class2name(CLASS_OF(self)),
(void *)self,
holder->boxed,
holder->own ? "true" : "false");
result = rb_str_new2(s);
g_free(s);
return result;
}
static VALUE
rg_initialize_copy(VALUE self, VALUE orig)
{
boxed_holder *holder1;
boxed_holder *holder2;
if (self == orig) return self;
if (!rb_obj_is_instance_of(orig, rb_obj_class(self))) {
rb_raise(rb_eTypeError, "wrong argument class");
}
Data_Get_Struct(self, boxed_holder, holder1);
Data_Get_Struct(orig, boxed_holder, holder2);
holder1->boxed = g_boxed_copy(holder2->type, holder2->boxed);
holder1->own = TRUE;
if (!holder1->boxed)
rb_raise(rb_eRuntimeError, "g_boxed_copy() failed");
return self;
}
/* deprecated */
VALUE
rbgobj_boxed_create(VALUE klass)
{
return rbgobj_boxed_s_allocate(klass);
}
/**********************************************************************/
void
rbgobj_boxed_initialize(VALUE obj, gpointer boxed)
{
boxed_holder *holder;
Data_Get_Struct(obj, boxed_holder, holder);
holder->boxed = boxed;
holder->own = TRUE;
}
gpointer
rbgobj_boxed_get_default(VALUE obj, GType gtype)
{
boxed_holder *holder;
if (!RVAL2CBOOL(rb_obj_is_kind_of(obj, GTYPE2CLASS(gtype))))
rb_raise(rb_eArgError, "invalid argument %s (expect %s)",
rb_class2name(CLASS_OF(obj)),
rb_class2name(GTYPE2CLASS(gtype)));
Data_Get_Struct(obj, boxed_holder, holder);
if (!holder->boxed)
rb_raise(rb_eArgError, "uninitialize %s", rb_class2name(CLASS_OF(obj)));
return holder->boxed;
}
gpointer
rbgobj_boxed_get(VALUE obj, GType gtype)
{
gpointer boxed = NULL;
if (NIL_P(obj))
return NULL;
if (rbgobj_convert_robj2instance(gtype, obj, &boxed)) {
return boxed;
}
return rbgobj_boxed_get_default(obj, gtype);
}
VALUE
rbgobj_make_boxed_raw(gpointer p, GType gtype, VALUE klass, gint flags)
{
VALUE result;
boxed_holder *holder;
result = rbgobj_boxed_s_allocate(klass);
Data_Get_Struct(result, boxed_holder, holder);
if (flags & RBGOBJ_BOXED_NOT_COPY) {
holder->boxed = p;
holder->own = FALSE;
} else {
holder->boxed = g_boxed_copy(gtype, p);
holder->own = TRUE;
}
return result;
}
VALUE
rbgobj_make_boxed_default(gpointer p, GType gtype)
{
const RGObjClassInfo *cinfo;
cinfo = GTYPE2CINFO(gtype);
return rbgobj_make_boxed_raw(p, gtype, cinfo->klass, cinfo->flags);
}
VALUE
rbgobj_make_boxed(gpointer p, GType gtype)
{
VALUE result;
if (!p)
return Qnil;
if (rbgobj_convert_instance2robj(gtype, p, &result)) {
return result;
}
return rbgobj_make_boxed_default(p, gtype);
}
void
rbgobj_boxed_not_copy_obj(GType gtype)
{
RGObjClassInfo *cinfo = (RGObjClassInfo *)GTYPE2CINFO(gtype);
cinfo->flags |= RBGOBJ_BOXED_NOT_COPY;
}
void
rbgobj_boxed_unown(VALUE boxed)
{
boxed_holder *holder;
Data_Get_Struct(boxed, boxed_holder, holder);
if (!holder->own) {
rb_raise(rb_eArgError,
"The boxed is already unowned: %p",
boxed);
}
holder->own = FALSE;
}
/**********************************************************************/
static VALUE
boxed_to_ruby(const GValue *from)
{
gpointer boxed;
boxed = g_value_get_boxed(from);
return rbgobj_make_boxed(boxed, G_VALUE_TYPE(from));
}
static void
boxed_from_ruby(VALUE from, GValue *to)
{
gpointer boxed;
boxed = rbgobj_boxed_get(from, G_VALUE_TYPE(to));
g_value_set_boxed(to, boxed);
}
/**********************************************************************/
void
Init_gobject_gboxed(void)
{
RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_BOXED, "Boxed", mGLib);
rbgobj_register_g2r_func(G_TYPE_BOXED, boxed_to_ruby);
rbgobj_register_r2g_func(G_TYPE_BOXED, boxed_from_ruby);
rb_define_alloc_func(RG_TARGET_NAMESPACE, (VALUE(*)_((VALUE)))rbgobj_boxed_s_allocate);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "gtype", generic_s_gtype, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "gtype", generic_gtype, 0);
RG_DEF_METHOD(initialize, 0);
RG_DEF_METHOD(inspect, 0);
RG_DEF_METHOD(initialize_copy, 1);
RG_DEF_ALIAS("copy", "dup");
}

View File

@ -0,0 +1,345 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2006 Ruby-GNOME2 Project
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cClosure
static ID id_call, id_closures;
static gboolean rclosure_initialized = FALSE;
#define TAG_SIZE 64
typedef struct _GRClosure GRClosure;
struct _GRClosure
{
GClosure closure;
VALUE callback;
VALUE extra_args;
VALUE rb_holder;
gint count;
GList *objects;
GValToRValSignalFunc g2r_func;
gchar tag[TAG_SIZE];
};
static VALUE
rclosure_default_g2r_func(guint num, const GValue *values)
{
guint i;
VALUE args = rb_ary_new2(num);
for (i = 0; i < num; i++)
rb_ary_store(args, i, GVAL2RVAL(&values[i]));
return args;
}
struct marshal_arg
{
GClosure* closure;
GValue* return_value;
guint n_param_values;
const GValue* param_values;
gpointer invocation_hint;
gpointer marshal_data;
};
static int
rclosure_alive_p(GRClosure *rclosure)
{
return (rclosure->count > 0 && !NIL_P(rclosure->rb_holder));
}
static VALUE
rclosure_marshal_do(VALUE arg_)
{
struct marshal_arg *arg;
GRClosure* rclosure;
GValue* return_value;
guint n_param_values;
const GValue* param_values;
/* gpointer invocation_hint;*/
/* gpointer marshal_data; */
VALUE ret = Qnil;
VALUE args;
GValToRValSignalFunc func;
arg = (struct marshal_arg*)arg_;
rclosure = (GRClosure *)(arg->closure);
return_value = arg->return_value;
n_param_values = arg->n_param_values;
param_values = arg->param_values;
/* invocation_hint = arg->invocation_hint; */
/* marshal_data = arg->marshal_data; */
if (rclosure->g2r_func){
func = (GValToRValSignalFunc)rclosure->g2r_func;
} else {
func = (GValToRValSignalFunc)rclosure_default_g2r_func;
}
args = (*func)(n_param_values, param_values);
if (rclosure_alive_p(rclosure)) {
VALUE callback, extra_args;
callback = rclosure->callback;
extra_args = rclosure->extra_args;
if (!NIL_P(extra_args)) {
args = rb_ary_concat(args, extra_args);
}
ret = rb_apply(callback, id_call, args);
} else {
rb_warn("GRClosure invoking callback: already destroyed: %s",
rclosure->tag[0] ? rclosure->tag : "(anonymous)");
}
if (return_value && G_VALUE_TYPE(return_value))
rbgobj_rvalue_to_gvalue(ret, return_value);
return Qnil;
}
static void
rclosure_marshal(GClosure* closure,
GValue* return_value,
guint n_param_values,
const GValue* param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
struct marshal_arg arg;
if (!rclosure_initialized) {
g_closure_invalidate(closure);
return;
}
arg.closure = closure;
arg.return_value = return_value;
arg.n_param_values = n_param_values;
arg.param_values = param_values;
arg.invocation_hint = invocation_hint;
arg.marshal_data = marshal_data;
G_PROTECT_CALLBACK(rclosure_marshal_do, &arg);
}
static void rclosure_weak_notify(gpointer data, GObject* where_the_object_was);
static void
rclosure_unref(GRClosure *rclosure)
{
rclosure->count--;
if (!rclosure_alive_p(rclosure)) {
GList *next;
for (next = rclosure->objects; next; next = next->next) {
GObject *object = G_OBJECT(next->data);
g_object_weak_unref(object, rclosure_weak_notify, rclosure);
}
g_list_free(rclosure->objects);
rclosure->objects = NULL;
if (!NIL_P(rclosure->rb_holder)) {
DATA_PTR(rclosure->rb_holder) = NULL;
rclosure->rb_holder = Qnil;
}
}
}
static void
rclosure_invalidate(G_GNUC_UNUSED gpointer data, GClosure *closure)
{
GRClosure *rclosure = (GRClosure*)closure;
if (rclosure->count > 0) {
GList *next;
rclosure->count = 1;
for (next = rclosure->objects; next; next = next->next) {
GObject *object = G_OBJECT(next->data);
VALUE obj = rbgobj_ruby_object_from_instance2(object, FALSE);
if (!NIL_P(rclosure->rb_holder) && !NIL_P(obj))
G_REMOVE_RELATIVE(obj, id_closures, rclosure->rb_holder);
}
rclosure_unref(rclosure);
}
}
static void
gr_closure_holder_mark(GRClosure *rclosure)
{
if (!rclosure)
return;
rb_gc_mark(rclosure->callback);
rb_gc_mark(rclosure->extra_args);
}
static void
gr_closure_holder_free(GRClosure *rclosure)
{
if (!rclosure)
return;
if (rclosure->count > 0) {
rclosure->count = 1;
/* No need to remove us from the relatives hash of our objects, as
* those aren't alive anymore anyway */
rclosure_unref(rclosure);
}
}
GClosure*
g_rclosure_new(VALUE callback_proc, VALUE extra_args, GValToRValSignalFunc g2r_func)
{
GRClosure* closure;
closure = (GRClosure*)g_closure_new_simple(sizeof(GRClosure), NULL);
closure->count = 1;
closure->g2r_func = g2r_func;
closure->objects = NULL;
closure->callback = callback_proc;
closure->extra_args = extra_args;
closure->rb_holder = Data_Wrap_Struct(rb_cData,
gr_closure_holder_mark,
gr_closure_holder_free,
closure);
closure->tag[0] = '\0';
g_closure_set_marshal((GClosure*)closure, &rclosure_marshal);
g_closure_add_invalidate_notifier((GClosure*)closure, NULL,
&rclosure_invalidate);
return (GClosure*)closure;
}
static void
rclosure_weak_notify(gpointer data, GObject* where_the_object_was)
{
GRClosure *rclosure = data;
if (rclosure_alive_p(rclosure)) {
rclosure->objects =
g_list_remove(rclosure->objects, where_the_object_was);
rclosure_unref(rclosure);
}
}
void
g_rclosure_attach(GClosure *closure, VALUE object)
{
static VALUE mGLibObject = (VALUE)NULL;
GRClosure *rclosure = (GRClosure *)closure;
G_RELATIVE2(object, Qnil, id_closures, rclosure->rb_holder);
if (!mGLibObject) {
mGLibObject = rb_const_get(mGLib, rb_intern("Object"));
}
if (rb_obj_is_kind_of(object, mGLibObject)) {
GObject *gobject;
gobject = RVAL2GOBJ(object);
rclosure->count++;
g_object_weak_ref(gobject, rclosure_weak_notify, rclosure);
rclosure->objects = g_list_prepend(rclosure->objects, gobject);
}
}
void
g_rclosure_set_tag(GClosure *closure, const gchar *tag)
{
GRClosure *rclosure = (GRClosure *)closure;
if (tag) {
strncpy(rclosure->tag, tag, TAG_SIZE);
rclosure->tag[TAG_SIZE - 1] = '\0';
} else {
rclosure->tag[0] = '\0';
}
}
static void
rclosure_end_proc(G_GNUC_UNUSED VALUE _)
{
rclosure_initialized = FALSE;
}
static void
init_rclosure(void)
{
id_call = rb_intern("call");
id_closures = rb_intern("closures");
rclosure_initialized = TRUE;
rb_set_end_proc(rclosure_end_proc, Qnil);
}
/**********************************************************************/
static VALUE
rg_initialize(VALUE self)
{
GClosure* closure = g_rclosure_new(rb_block_proc(), Qnil, NULL);
G_INITIALIZE(self, closure);
g_closure_sink(closure);
return self;
}
static VALUE
rg_in_marshal_p(VALUE self)
{
GClosure* closure = RVAL2BOXED(self, G_TYPE_CLOSURE);
return CBOOL2RVAL(closure->in_marshal);
}
static VALUE
rg_invalid_p(VALUE self)
{
GClosure* closure = RVAL2BOXED(self, G_TYPE_CLOSURE);
return CBOOL2RVAL(closure->is_invalid);
}
static VALUE
rg_invalidate(VALUE self)
{
GClosure* closure = RVAL2BOXED(self, G_TYPE_CLOSURE);
g_closure_invalidate(closure);
return self;
}
/**********************************************************************/
void
Init_gobject_gclosure(void)
{
VALUE RG_TARGET_NAMESPACE;
init_rclosure();
RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_CLOSURE, "Closure", mGLib);
RG_DEF_METHOD(initialize, 0);
RG_DEF_METHOD_P(in_marshal, 0);
RG_DEF_METHOD_P(invalid, 0);
RG_DEF_METHOD(invalidate, 0);
}

View File

@ -0,0 +1,192 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Sjoerd Simons, Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgobject.h"
#include "rbgprivate.h"
static GHashTable *tables, *class_to_g_type_map;
static void
rg_convert_table_free(gpointer data)
{
RGConvertTable *table = data;
if (table->notify) {
table->notify(table->user_data);
}
g_free(table);
}
void
Init_gobject_convert(void)
{
/* TODO: unref the below tables on exit. */
tables = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
rg_convert_table_free);
class_to_g_type_map = g_hash_table_new(g_int_hash, g_int_equal);
}
void
rbgobj_convert_define(const RGConvertTable *table)
{
RGConvertTable *copied_table;
copied_table = g_memdup(table, sizeof(RGConvertTable));
g_hash_table_insert(tables, &(copied_table->type), copied_table);
if (copied_table->klass != Qfalse && !NIL_P(copied_table->klass)) {
g_hash_table_insert(class_to_g_type_map,
&(copied_table->klass), &(copied_table->type));
}
}
RGConvertTable *
rbgobj_convert_lookup(GType type)
{
return g_hash_table_lookup(tables, &type);
}
gboolean
rbgobj_convert_has_type(GType type)
{
return rbgobj_convert_lookup(type) != NULL;
}
gboolean
rbgobj_convert_get_superclass(GType type, VALUE *result)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->get_superclass) {
*result = table->get_superclass(table->user_data);
return TRUE;
}
return FALSE;
}
gboolean
rbgobj_convert_type_init_hook(GType type, VALUE klass)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->type_init_hook) {
table->type_init_hook(klass, table->user_data);
return TRUE;
}
return FALSE;
}
gboolean
rbgobj_convert_rvalue2gvalue(GType type, VALUE value, GValue *result)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->rvalue2gvalue) {
table->rvalue2gvalue(value, result, table->user_data);
return TRUE;
}
return FALSE;
}
gboolean
rbgobj_convert_gvalue2rvalue(GType type, const GValue *value, VALUE *result)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->gvalue2rvalue) {
*result = table->gvalue2rvalue(value, table->user_data);
return TRUE;
}
return FALSE;
}
GType
rbgobj_convert_rvalue2gtype(VALUE value)
{
VALUE klass;
GType *result;
klass = rb_class_of(value);
result = g_hash_table_lookup(class_to_g_type_map, &klass);
return result ? *result : 0;
}
gboolean
rbgobj_convert_initialize(GType type, VALUE obj, gpointer cobj)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->initialize) {
table->initialize(obj, cobj, table->user_data);
return TRUE;
}
return FALSE;
}
gboolean
rbgobj_convert_robj2instance(GType type, VALUE obj, gpointer *result)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->robj2instance) {
*result = table->robj2instance(obj, table->user_data);
return TRUE;
}
return FALSE;
}
gboolean
rbgobj_convert_instance2robj(GType type, gpointer instance, VALUE *result)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->instance2robj) {
*result = table->instance2robj(instance, table->user_data);
return TRUE;
}
return FALSE;
}
gboolean
rbgobj_convert_unref(GType type, gpointer instance)
{
RGConvertTable *table;
table = rbgobj_convert_lookup(type);
if (table && table->unref) {
table->unref(instance, table->user_data);
return TRUE;
}
return FALSE;
}

View File

@ -0,0 +1,109 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004-2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include <ctype.h>
typedef struct {
char *original;
char *replacement;
} constant_map;
static GSList *rbgobj_cmap = NULL;
static gint
rbgobj_constant_find(constant_map *a, char *name)
{
return strcmp(a->original, name);
}
void
rbgobj_constant_remap(const char *original, const char *replacement)
{
constant_map *map = g_new(constant_map,1);
map->original = g_strdup(original);
map->replacement = g_strdup(replacement);
rbgobj_cmap = g_slist_append(rbgobj_cmap, map);
}
char *
rg_obj_constant_lookup(const char *name)
{
GSList *p = rbgobj_cmap;
p = g_slist_find_custom(rbgobj_cmap, name,
(GCompareFunc)rbgobj_constant_find);
if (p) {
char *replacement;
constant_map *map;
map = (constant_map *)p->data;
rbgobj_cmap = g_slist_delete_link(rbgobj_cmap, p);
replacement = map->replacement;
g_free(map->original);
g_free(map);
return replacement;
}
return NULL;
}
void
rbgobj_define_const(VALUE mod, const char *name,
VALUE value)
{
if (name[0] >= 'A' && name[0] <= 'Z') {
rb_define_const(mod, name, value);
} else {
char *new_name = rg_obj_constant_lookup(name);
if (new_name) {
rb_define_const(mod, new_name, value);
g_free(new_name);
} else {
rb_warn("Invalid constant name '%s' - skipped", name);
}
}
}
void
rbgobj_add_constants(VALUE mod, GType type, const gchar *strip_prefix)
{
if (G_TYPE_IS_ENUM(type)) {
rg_enum_add_constants(mod, type, strip_prefix);
} else if (G_TYPE_IS_FLAGS(type)) {
rg_flags_add_constants(mod, type, strip_prefix);
} else {
g_warning("`%s' is not an enum/flags type", g_type_name(type));
}
}
void
Init_gobject_genumflags(void)
{
Init_gobject_genums();
Init_gobject_gflags();
}

View File

@ -0,0 +1,401 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004-2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include <ctype.h>
#define RG_TARGET_NAMESPACE rbgobj_cEnum
VALUE RG_TARGET_NAMESPACE;
static ID id_new;
static ID id_to_s;
/**********************************************************************/
static gchar *
nick_to_const_name(const gchar *nick)
{
gchar *const_name;
gchar *p;
if (!nick)
return NULL;
const_name = g_strdup(nick);
for (p = const_name; *p; p++) {
if (*p == '-' || *p == ' ')
*p = '_';
else
*p = g_ascii_toupper(*p);
}
return const_name;
}
VALUE
rg_enum_resolve_value(VALUE klass, VALUE nick)
{
VALUE value = Qnil;
gchar *const_nick;
ID const_nick_id;
if (RVAL2CBOOL(rb_obj_is_kind_of(nick, klass)))
return nick;
nick = rb_funcall(nick, id_to_s, 0);
const_nick = nick_to_const_name(RVAL2CSTR(nick));
const_nick_id = rb_intern(const_nick);
if (rb_const_defined(klass, const_nick_id)) {
value = rb_const_get(klass, const_nick_id);
}
g_free(const_nick);
return value;
}
void
rg_enum_add_constants(VALUE mod, GType enum_type, const gchar *strip_prefix)
{
GEnumClass *gclass;
guint i;
int prefix_len = strlen(strip_prefix);
gclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
for (i = 0; i < gclass->n_values; i++) {
const GEnumValue* value = &gclass->values[i];
if (strncmp(value->value_name, strip_prefix, prefix_len)) {
g_warning("\"%s\" doesn't have prefix \"%s\"",
value->value_name, strip_prefix);
} else {
const char* name = value->value_name + prefix_len;
rbgobj_define_const(mod, name,
rbgobj_make_enum(value->value, enum_type));
}
}
g_type_class_unref(gclass);
}
/**********************************************************************/
typedef struct {
GEnumClass* gclass;
gint value;
GEnumValue* info;
} enum_holder;
static void
enum_free(enum_holder* p)
{
g_type_class_unref(p->gclass);
free(p);
}
static enum_holder*
enum_get_holder(VALUE obj)
{
enum_holder* p;
Data_Get_Struct(obj, enum_holder, p);
return p;
}
static VALUE
make_enum(gint n, VALUE klass)
{
return rb_funcall(klass, id_new, 1, INT2NUM(n));
}
VALUE
rbgobj_make_enum(gint n, GType gtype)
{
return make_enum(n, GTYPE2CLASS(gtype));
}
gint
rbgobj_get_enum(VALUE obj, GType gtype)
{
VALUE klass;
if (!g_type_is_a(gtype, G_TYPE_ENUM))
rb_raise(rb_eTypeError, "%s is not a %s: %s",
g_type_name(gtype), g_type_name(G_TYPE_ENUM),
RBG_INSPECT(obj));
/* for compatibility */
if (rb_obj_is_kind_of(obj, rb_cInteger))
obj = rbgobj_make_enum(NUM2INT(obj), gtype);
klass = GTYPE2CLASS(gtype);
if (!rb_obj_is_kind_of(obj, klass)) {
VALUE enum_value;
enum_value = rg_enum_resolve_value(klass, obj);
if (!NIL_P(enum_value))
obj = enum_value;
}
if (rb_obj_is_kind_of(obj, klass))
return enum_get_holder(obj)->value;
else
rb_raise(rb_eTypeError, "not a %s: %s",
rb_class2name(klass), RBG_INSPECT(obj));
}
/**********************************************************************/
void
rbgobj_init_enum_class(VALUE klass)
{
GEnumClass* gclass = g_type_class_ref(CLASS2GTYPE(klass));
guint i;
for (i = 0; i < gclass->n_values; i++) {
GEnumValue* entry = &(gclass->values[i]);
gchar *const_nick_name;
const_nick_name = nick_to_const_name(entry->value_nick);
#if 0
{
ID id = rb_intern(const_nick_name);
if (rb_is_const_id(id)) {
VALUE value;
value = make_enum(entry->value, klass);
rb_define_const(klass, const_nick_name, value);
}
}
#else
{
if (const_nick_name) {
VALUE value;
value = make_enum(entry->value, klass);
rbgobj_define_const(klass, const_nick_name, value);
}
}
#endif
g_free(const_nick_name);
}
g_type_class_unref(gclass);
}
static VALUE
rg_s_range(VALUE self)
{
GEnumClass* gclass = g_type_class_ref(CLASS2GTYPE(self));
VALUE result = rb_range_new(INT2NUM(gclass->minimum),
INT2NUM(gclass->maximum),
FALSE);
g_type_class_unref(gclass);
return result;
}
struct enum_s_values_body_args {
GEnumClass *gclass;
VALUE self;
};
static VALUE
enum_s_values_body(VALUE value)
{
struct enum_s_values_body_args *args = (struct enum_s_values_body_args *)value;
VALUE result = rb_ary_new();
guint i;
for (i = 0; i < args->gclass->n_values; i++)
rb_ary_push(result, make_enum(args->gclass->values[i].value, args->self));
return result;
}
static VALUE
enum_s_values_ensure(VALUE gclass)
{
g_type_class_unref((GEnumClass *)gclass);
return Qnil;
}
static VALUE
rg_s_values(VALUE self)
{
struct enum_s_values_body_args args = {
g_type_class_ref(CLASS2GTYPE(self)),
self
};
return rb_ensure(enum_s_values_body, (VALUE)&args,
enum_s_values_ensure, (VALUE)args.gclass);
}
static VALUE
enum_s_allocate(VALUE self)
{
GType gtype = CLASS2GTYPE(self);
if (G_TYPE_IS_ABSTRACT(gtype)) {
rb_raise(rb_eTypeError, "abstract class");
} else {
enum_holder* p;
VALUE result = Data_Make_Struct(self, enum_holder, NULL, enum_free, p);
p->gclass = g_type_class_ref(gtype);
p->info = NULL;
return result;
}
}
static VALUE
rg_initialize(VALUE self, VALUE arg)
{
enum_holder* p = enum_get_holder(self);
if (rb_respond_to(arg, rb_intern("to_str"))) {
const char* str = StringValuePtr(arg);
p->info = g_enum_get_value_by_name(p->gclass, str);
if (! p->info)
p->info = g_enum_get_value_by_nick(p->gclass, str);
if (! p->info)
rb_raise(rb_eArgError, "invalid argument");
} else {
p->value = NUM2INT(arg);
p->info = g_enum_get_value(p->gclass, p->value);
}
return Qnil;
}
static VALUE
rg_to_i(VALUE self)
{
enum_holder* p = enum_get_holder(self);
return INT2NUM(p->value);
}
static VALUE
rg_name(VALUE self)
{
enum_holder* p = enum_get_holder(self);
return p->info ? rb_str_new2(p->info->value_name) : Qnil;
}
static VALUE
rg_nick(VALUE self)
{
enum_holder* p = enum_get_holder(self);
return p->info ? rb_str_new2(p->info->value_nick) : Qnil;
}
static VALUE
rg_inspect(VALUE self)
{
const char* cname = rb_class2name(CLASS_OF(self));
enum_holder* p = enum_get_holder(self);
gchar* str;
VALUE result;
if (p->info)
str = g_strdup_printf("#<%s %s>",
cname, p->info->value_nick);
else
str = g_strdup_printf("#<%s %d>",
cname, p->value);
result = rb_str_new2(str);
g_free(str);
return result;
}
static VALUE
rg_operator_enum_eqv(VALUE self, VALUE rhs)
{
enum_holder* p = enum_get_holder(self);
GType gtype = G_TYPE_FROM_CLASS(p->gclass);
VALUE klass = GTYPE2CLASS(gtype);
if (!rb_obj_is_kind_of(rhs, rb_cInteger)) {
rhs = rg_enum_resolve_value(klass, rhs);
if (CLASS_OF(rhs) != CLASS_OF(self))
return Qnil;
}
return CBOOL2RVAL(rbgobj_get_enum(self, gtype) == rbgobj_get_enum(rhs, gtype));
}
static VALUE
rg_hash(VALUE self)
{
enum_holder* p = enum_get_holder(self);
return UINT2NUM(p->value ^ G_TYPE_FROM_CLASS(p->gclass));
}
static VALUE
rg_coerce(VALUE self, VALUE other)
{
enum_holder *holder;
GType gtype;
if (!rb_obj_is_kind_of(other, rb_cInteger))
rb_raise(rb_eTypeError, "can't coerce");
holder = enum_get_holder(self);
gtype = G_TYPE_FROM_CLASS(holder->gclass);
other = rbgobj_make_enum(NUM2INT(other), gtype);
return rb_ary_new3(2, other, self);
}
/**********************************************************************/
void
Init_gobject_genums(void)
{
id_new = rb_intern("new");
id_to_s = rb_intern("to_s");
RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_ENUM, "Enum", mGLib);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "gtype", generic_s_gtype, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "gtype", generic_gtype, 0);
RG_DEF_SMETHOD(range, 0);
RG_DEF_SMETHOD(values, 0);
rb_define_alloc_func(RG_TARGET_NAMESPACE, enum_s_allocate);
RG_DEF_METHOD(initialize, 1);
RG_DEF_METHOD(to_i, 0);
RG_DEF_METHOD(name, 0);
RG_DEF_METHOD(nick, 0);
RG_DEF_METHOD(inspect, 0);
RG_DEF_METHOD_OPERATOR("==", enum_eqv, 1);
RG_DEF_METHOD(hash, 0);
RG_DEF_ALIAS("eql?", "==");
/* for compatibility */
RG_DEF_METHOD(coerce, 1);
RG_DEF_ALIAS("to_int", "to_i");
}

View File

@ -0,0 +1,522 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004-2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include <ctype.h>
#define RG_TARGET_NAMESPACE rbgobj_cFlags
VALUE RG_TARGET_NAMESPACE;
static ID id_new;
static ID id_module_eval;
static ID id_or;
/**********************************************************************/
static VALUE
resolve_flags_value(VALUE klass, VALUE nick_or_nicks)
{
int i, len;
VALUE flags_value;
if (!RVAL2CBOOL(rb_obj_is_kind_of(nick_or_nicks, rb_cArray)))
return rg_enum_resolve_value(klass, nick_or_nicks);
len = RARRAY_LEN(nick_or_nicks);
flags_value = rb_funcall(klass, id_new, 0);
for (i = 0; i < len; i++) {
VALUE value;
value = rg_enum_resolve_value(klass, RARRAY_PTR(nick_or_nicks)[i]);
if (NIL_P(value))
return Qnil;
flags_value = rb_funcall(flags_value, id_or, 1, value);
}
return flags_value;
}
void
rg_flags_add_constants(VALUE mod, GType flags_type, const gchar *strip_prefix)
{
GFlagsClass *gclass;
guint i;
int prefix_len = strlen(strip_prefix);
gclass = G_FLAGS_CLASS(g_type_class_ref(flags_type));
for (i = 0; i < gclass->n_values; i++) {
const GFlagsValue* value = &gclass->values[i];
if (strncmp(value->value_name, strip_prefix, prefix_len)) {
g_warning("\"%s\" doesn't have prefix \"%s\"",
value->value_name, strip_prefix);
} else {
const char* name = value->value_name + prefix_len;
rbgobj_define_const(mod, name,
rbgobj_make_flags(value->value, flags_type));
}
}
g_type_class_unref(gclass);
}
/**********************************************************************/
typedef struct {
GFlagsClass* gclass;
guint value;
GFlagsValue* info;
} flags_holder;
static void
flags_free(flags_holder* p)
{
g_type_class_unref(p->gclass);
free(p);
}
static flags_holder*
flags_get_holder(VALUE obj)
{
flags_holder* p;
Data_Get_Struct(obj, flags_holder, p);
return p;
}
static VALUE
make_flags(guint n, VALUE klass)
{
return rb_funcall(klass, id_new, 1, UINT2NUM(n));
}
VALUE
rbgobj_make_flags(guint n, GType gtype)
{
return make_flags(n, GTYPE2CLASS(gtype));
}
guint
rbgobj_get_flags(VALUE obj, GType gtype)
{
VALUE klass;
if (!g_type_is_a(gtype, G_TYPE_FLAGS))
rb_raise(rb_eTypeError, "%s is not a %s",
g_type_name(gtype), g_type_name(G_TYPE_FLAGS));
/* for compatibility */
if (rb_obj_is_kind_of(obj, rb_cInteger))
obj = rbgobj_make_flags(NUM2UINT(obj), gtype);
klass = GTYPE2CLASS(gtype);
if (!rb_obj_is_kind_of(obj, klass)) {
VALUE flags_value = Qnil;
flags_value = resolve_flags_value(klass, obj);
if (!NIL_P(flags_value))
obj = flags_value;
}
if (rb_obj_is_kind_of(obj, klass))
return flags_get_holder(obj)->value;
else
rb_raise(rb_eTypeError, "not a %s: %s",
rb_class2name(klass), RBG_INSPECT(obj));
}
/**********************************************************************/
void
rbgobj_init_flags_class(VALUE klass)
{
GFlagsClass* gclass = g_type_class_ref(CLASS2GTYPE(klass));
GString* source = g_string_new(NULL);
guint i;
for (i = 0; i < gclass->n_values; i++) {
GFlagsValue* entry = &(gclass->values[i]);
gchar* nick;
gchar* p;
gchar* replace_nick;
replace_nick = rg_obj_constant_lookup(entry->value_nick);
if (replace_nick){
nick = g_strdup(replace_nick);
} else {
nick = g_strdup(entry->value_nick);
}
for (p = nick; *p; p++)
if (*p == '-' || *p == ' ')
*p = '_';
else
*p = tolower(*p);
g_string_append_printf(
source,
"def %s%s?; self >= self.class.new(%d); end\n",
g_ascii_isdigit(nick[0]) ? "_" : "",
nick, entry->value);
for (p = nick; *p; p++)
*p = g_ascii_toupper(*p);
#if 0
{
ID id = rb_intern(nick);
if (rb_is_const_id(id)) {
rb_define_const(klass, nick, make_flags(entry->value, klass));
}
}
#else
{
rbgobj_define_const(klass, nick, make_flags(entry->value, klass));
}
#endif
g_free(nick);
}
rb_funcall(klass, id_module_eval, 1, rb_str_new2(source->str));
g_string_free(source, TRUE);
g_type_class_unref(gclass);
}
static VALUE
rg_s_mask(VALUE klass)
{
GFlagsClass* gclass = g_type_class_ref(CLASS2GTYPE(klass));
VALUE result = UINT2NUM(gclass->mask);
g_type_class_unref(gclass);
return result;
}
static VALUE
rg_s_values(VALUE klass)
{
GFlagsClass *gclass;
VALUE result;
guint i;
gclass = g_type_class_ref(CLASS2GTYPE(klass));
result = rb_ary_new();
for (i = 0; i < gclass->n_values; i++) {
GFlagsValue *p = &(gclass->values[i]);
rb_ary_push(result, make_flags(p->value, klass));
}
g_type_class_unref(gclass);
return result;
}
static VALUE
flags_s_allocate(VALUE self)
{
GType gtype = CLASS2GTYPE(self);
if (G_TYPE_IS_ABSTRACT(gtype)) {
rb_raise(rb_eTypeError, "abstract class");
} else {
flags_holder* p;
VALUE result = Data_Make_Struct(self, flags_holder, NULL, flags_free, p);
p->gclass = g_type_class_ref(gtype);
p->value = 0;
p->info = NULL;
return result;
}
}
static VALUE
rg_initialize(int argc, VALUE* argv, VALUE self)
{
flags_holder* p = flags_get_holder(self);
VALUE arg;
rb_scan_args(argc, argv, "01", &arg);
if (argc == 0) {
p->value = 0;
} else {
if (rb_respond_to(arg, rb_intern("to_str"))) {
const char* str = StringValuePtr(arg);
p->info = g_flags_get_value_by_name(p->gclass, str);
if (!p->info)
p->info = g_flags_get_value_by_nick(p->gclass, str);
if (!p->info)
rb_raise(rb_eArgError, "invalid argument");
p->value = p->info->value;
} else {
p->value = NUM2UINT(arg);
}
}
if (!p->info) {
guint i;
for (i = 0; i < p->gclass->n_values; i++){
GFlagsValue* val = &(p->gclass->values[i]);
if (val->value == p->value){
p->info = val;
break;
}
}
}
return Qnil;
}
static VALUE
rg_to_i(VALUE self)
{
flags_holder* p = flags_get_holder(self);
return UINT2NUM(p->value);
}
static VALUE
rg_name(VALUE self)
{
flags_holder* p = flags_get_holder(self);
return p->info ? rb_str_new2(p->info->value_name) : Qnil;
}
static VALUE
rg_nick(VALUE self)
{
flags_holder* p = flags_get_holder(self);
return p->info ? rb_str_new2(p->info->value_nick) : Qnil;
}
#define FLAGS_COMP_EQUAL 0
#define FLAGS_COMP_GREATER 1
#define FLAGS_COMP_LESS -1
#define FLAGS_COMP_ELSE -2
#define FLAGS_COMP_INCOMPARABLE -3
static gint
flags_compare(VALUE self, VALUE rhs)
{
flags_holder* p = flags_get_holder(self);
GType gtype = G_TYPE_FROM_CLASS(p->gclass);
VALUE klass = GTYPE2CLASS(gtype);
guint rhs_val;
if (!rb_obj_is_kind_of(rhs, rb_cInteger)) {
rhs = resolve_flags_value(klass, rhs);
if (CLASS_OF(rhs) != CLASS_OF(self))
return FLAGS_COMP_INCOMPARABLE;
}
rhs_val = rbgobj_get_flags(rhs, gtype);
if (p->value == rhs_val)
return FLAGS_COMP_EQUAL;
else if ((p->value & rhs_val) == rhs_val)
return FLAGS_COMP_GREATER;
else if ((p->value & rhs_val) == p->value)
return FLAGS_COMP_LESS;
else
return FLAGS_COMP_ELSE;
}
static VALUE
rg_operator_flags_compare(VALUE self, VALUE rhs)
{
gint ret = flags_compare(self, rhs);
switch (ret) {
case FLAGS_COMP_EQUAL:
case FLAGS_COMP_GREATER:
case FLAGS_COMP_LESS:
return INT2FIX(ret);
default:
return Qnil;
}
}
static VALUE
rg_operator_flags_eqv(VALUE self, VALUE rhs)
{
gint ret = flags_compare(self, rhs);
if (ret == FLAGS_COMP_INCOMPARABLE)
return Qnil;
return CBOOL2RVAL(ret == FLAGS_COMP_EQUAL);
}
static VALUE
rg_operator_flags_gt_eq(VALUE self, VALUE rhs)
{
gint ret = flags_compare(self, rhs);
if (ret == FLAGS_COMP_INCOMPARABLE)
return Qnil;
return CBOOL2RVAL(ret == FLAGS_COMP_GREATER || ret == FLAGS_COMP_EQUAL);
}
static VALUE
rg_operator_flags_lt_eq(VALUE self, VALUE rhs)
{
gint ret = flags_compare(self, rhs);
if (ret == FLAGS_COMP_INCOMPARABLE)
return Qnil;
return CBOOL2RVAL(ret == FLAGS_COMP_LESS || ret == FLAGS_COMP_EQUAL);
}
static VALUE
rg_operator_flags_gt(VALUE self, VALUE rhs)
{
gint ret = flags_compare(self, rhs);
if (ret == FLAGS_COMP_INCOMPARABLE)
return Qnil;
return CBOOL2RVAL(ret == FLAGS_COMP_GREATER);
}
static VALUE
rg_operator_flags_lt(VALUE self, VALUE rhs)
{
gint ret = flags_compare(self, rhs);
if (ret == FLAGS_COMP_INCOMPARABLE)
return Qnil;
return CBOOL2RVAL(ret == FLAGS_COMP_LESS);
}
static VALUE
rg_operator_flags_not(VALUE self, G_GNUC_UNUSED VALUE rhs)
{
flags_holder* p = flags_get_holder(self);
return rbgobj_make_flags((~ p->value) & p->gclass->mask,
G_TYPE_FROM_CLASS(p->gclass));
}
#define LIFT_BINARY_OP(funcname, op) \
static VALUE \
funcname(VALUE self, VALUE rhs) \
{ \
flags_holder* p = flags_get_holder(self); \
GType gtype = G_TYPE_FROM_CLASS(p->gclass); \
return rbgobj_make_flags(p->value op rbgobj_get_flags(rhs, gtype), \
gtype); \
}
LIFT_BINARY_OP(flags_and, &)
LIFT_BINARY_OP(flags_or, |)
LIFT_BINARY_OP(flags_xor, ^)
static VALUE
rg_operator_flags_minus(VALUE self, VALUE rhs)
{
flags_holder* p = flags_get_holder(self);
GType gtype = G_TYPE_FROM_CLASS(p->gclass);
return rbgobj_make_flags(p->value & ~rbgobj_get_flags(rhs, gtype),
gtype);
}
static VALUE
rg_empty_p(VALUE self)
{
flags_holder* p = flags_get_holder(self);
return CBOOL2RVAL(p->value == 0);
}
static VALUE
rg_hash(VALUE self)
{
flags_holder* p = flags_get_holder(self);
return UINT2NUM(p->value ^ G_TYPE_FROM_CLASS(p->gclass));
}
static VALUE
rg_coerce(VALUE self, VALUE other)
{
flags_holder *holder;
GType gtype;
if (rb_obj_is_kind_of(other, rb_cInteger))
rb_raise(rb_eTypeError, "can't coerce");
holder = flags_get_holder(self);
gtype = G_TYPE_FROM_CLASS(holder->gclass);
other = rbgobj_make_flags(NUM2UINT(other), gtype);
return rb_ary_new3(2, other, self);
}
static VALUE
rg_nonzero_p(VALUE self)
{
flags_holder* p = flags_get_holder(self);
return CBOOL2RVAL(p->value != 0);
}
/**********************************************************************/
void
Init_gobject_gflags(void)
{
id_module_eval = rb_intern("module_eval");
id_new = rb_intern("new");
id_or = rb_intern("|");
RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_FLAGS, "Flags", mGLib);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "gtype", generic_s_gtype, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "gtype", generic_gtype, 0);
RG_DEF_SMETHOD(mask, 0);
RG_DEF_SMETHOD(values, 0);
rb_define_alloc_func(RG_TARGET_NAMESPACE, flags_s_allocate);
RG_DEF_METHOD(initialize, -1);
RG_DEF_METHOD(to_i, 0);
RG_DEF_ALIAS("to_int", "to_i");
RG_DEF_METHOD(name, 0);
RG_DEF_METHOD(nick, 0);
/*
rbg_define_method(RG_TARGET_NAMESPACE, "inspect", flags_inspect, 0);
*/
RG_DEF_METHOD_OPERATOR("<=>", flags_compare, 1);
RG_DEF_METHOD_OPERATOR("==", flags_eqv, 1);
RG_DEF_METHOD_OPERATOR(">=", flags_gt_eq, 1);
RG_DEF_METHOD_OPERATOR("<=", flags_lt_eq, 1);
RG_DEF_METHOD_OPERATOR(">", flags_gt, 1);
RG_DEF_METHOD_OPERATOR("<", flags_lt, 1);
RG_DEF_METHOD_OPERATOR("~", flags_not, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "&", flags_and, 1);
rbg_define_method(RG_TARGET_NAMESPACE, "|", flags_or, 1);
rbg_define_method(RG_TARGET_NAMESPACE, "^", flags_xor, 1);
RG_DEF_METHOD_OPERATOR("-", flags_minus, 1);
RG_DEF_METHOD_P(empty, 0);
RG_DEF_METHOD(hash, 0);
RG_DEF_ALIAS("eql?", "==");
/* for compatibility */
RG_DEF_METHOD(coerce, 1);
RG_DEF_ALIAS("zero?", "empty?");
RG_DEF_METHOD_P(nonzero, 0);
}

View File

@ -0,0 +1,865 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2004 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2003 Masahiro Sakai
* Copyright (C) 1998-2000 Yukihiro Matsumoto,
* Daisuke Kanda,
* Hiroshi Igarashi
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE rbgobj_cObject
VALUE RG_TARGET_NAMESPACE;
static VALUE eNoPropertyError;
static GQuark RUBY_GOBJECT_OBJ_KEY;
/* deperecated */
void
rbgobj_add_abstract_but_create_instance_class(G_GNUC_UNUSED GType gtype)
{
}
static void
weak_notify(gpointer data, G_GNUC_UNUSED GObject *where_the_object_was)
{
gobj_holder *holder = data;
rbgobj_instance_call_cinfo_free(holder->gobj);
rbgobj_invalidate_relatives(holder->self);
holder->destroyed = TRUE;
g_object_unref(holder->gobj);
holder->gobj = NULL;
}
static void
holder_mark(gobj_holder *holder)
{
if (holder->gobj && !holder->destroyed)
rbgobj_instance_call_cinfo_mark(holder->gobj);
}
static void
holder_free(gobj_holder *holder)
{
if (holder->gobj) {
if (!holder->destroyed) {
g_object_set_qdata(holder->gobj, RUBY_GOBJECT_OBJ_KEY, NULL);
g_object_weak_unref(holder->gobj, (GWeakNotify)weak_notify, holder);
weak_notify(holder, holder->gobj);
}
holder->gobj = NULL;
}
xfree(holder);
}
static VALUE
gobj_s_allocate(VALUE klass)
{
gobj_holder* holder;
VALUE result;
result = Data_Make_Struct(klass, gobj_holder, holder_mark, holder_free, holder);
holder->self = result;
holder->gobj = NULL;
holder->cinfo = NULL;
holder->destroyed = FALSE;
return result;
}
/* deprecated */
VALUE
rbgobj_create_object(VALUE klass)
{
return gobj_s_allocate(klass);
}
void
rbgobj_gobject_initialize(VALUE obj, gpointer cobj)
{
gobj_holder* holder = g_object_get_qdata((GObject*)cobj, RUBY_GOBJECT_OBJ_KEY);
if (holder)
rb_raise(rb_eRuntimeError, "ruby wrapper for this GObject* already exists.");
Data_Get_Struct(obj, gobj_holder, holder);
holder->cinfo = RVAL2CINFO(obj);
holder->gobj = (GObject*)cobj;
holder->destroyed = FALSE;
g_object_set_qdata((GObject*)cobj, RUBY_GOBJECT_OBJ_KEY, (gpointer)holder);
g_object_weak_ref((GObject*)cobj, (GWeakNotify)weak_notify, holder);
{
GType t1 = G_TYPE_FROM_INSTANCE(cobj);
GType t2 = CLASS2GTYPE(CLASS_OF(obj));
if (t1 != t2) {
if (!g_type_is_a(t1, t2))
rb_raise(rb_eTypeError, "%s is not subtype of %s",
g_type_name(t1), g_type_name(t2));
}
}
}
VALUE
rbgobj_get_ruby_object_from_gobject(GObject* gobj, gboolean alloc)
{
gobj_holder *holder;
holder = g_object_get_qdata(gobj, RUBY_GOBJECT_OBJ_KEY);
if (holder) {
return holder->self;
} else if (alloc) {
VALUE obj;
obj = gobj_s_allocate(GTYPE2CLASS(G_OBJECT_TYPE(gobj)));
gobj = g_object_ref(gobj);
rbgobj_gobject_initialize(obj, (gpointer)gobj);
return obj;
} else {
return Qnil;
}
}
GObject*
rbgobj_get_gobject(VALUE obj)
{
gobj_holder* holder;
if (!RVAL2CBOOL(rb_obj_is_kind_of(obj, GTYPE2CLASS(G_TYPE_OBJECT))))
rb_raise(rb_eTypeError, "not a GLib::Object");
Data_Get_Struct(obj, gobj_holder, holder);
if (holder->destroyed)
rb_raise(rb_eTypeError, "destroyed GLib::Object");
if (!holder->gobj)
rb_raise(rb_eTypeError, "uninitialize GLib::Object");
return holder->gobj;
}
static VALUE
dummy_init(int argc, VALUE *argv, VALUE self)
{
GType gtype = CLASS2GTYPE(CLASS_OF(self));
if (G_TYPE_IS_ABSTRACT(gtype))
rb_raise(rb_eTypeError, "initializing abstract class");
else
return rb_call_super(argc, argv);
}
void
rbgobj_init_object_class(VALUE klass)
{
rbgobj_define_property_accessors(klass);
if (G_TYPE_IS_ABSTRACT(CLASS2GTYPE(klass)))
rbg_define_method(klass, "initialize", dummy_init, -1);
}
/**********************************************************************/
static gboolean
is_gtkobject(GObject *gobj)
{
static GType gtype_gtkobject = G_TYPE_INVALID;
if (!gtype_gtkobject)
gtype_gtkobject = g_type_from_name("GtkObject");
return gtype_gtkobject && g_type_is_a(G_OBJECT_TYPE(gobj), gtype_gtkobject);
}
static void
gobj_mark(gpointer ptr)
{
GObject* gobj = ptr;
guint n_properties;
GParamSpec** properties;
GValue gval = G_VALUE_INIT;
guint i;
properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(gobj), &n_properties);
for (i = 0; i < n_properties; i++) {
GParamSpec* pspec = properties[i];
GType value_type = G_PARAM_SPEC_VALUE_TYPE(pspec);
if (G_TYPE_FUNDAMENTAL(value_type) != G_TYPE_OBJECT) continue;
if (!(pspec->flags & G_PARAM_READABLE)) continue;
/* FIXME: exclude types that doesn't have identity. */
{
g_value_init(&gval, value_type);
g_object_get_property(gobj, pspec->name, &gval);
rbgobj_gc_mark_gvalue(&gval);
g_value_unset(&gval);
}
}
g_free(properties);
}
static VALUE
rg_s_new_bang(int argc, VALUE *argv, VALUE self)
{
const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
VALUE params_hash;
GObject* gobj;
VALUE result;
rb_scan_args(argc, argv, "01", &params_hash);
if (!NIL_P(params_hash))
Check_Type(params_hash, RUBY_T_HASH);
if (cinfo->klass != self)
rb_raise(rb_eTypeError, "%s isn't registered class",
rb_class2name(self));
gobj = rbgobj_gobject_new(cinfo->gtype, params_hash);
result = GOBJ2RVAL(gobj);
// XXX: Ughhhhh
if (is_gtkobject(gobj)){
// We can't call gtk_object_sink() here.
// But hopefully someone will call it in the future.
//gtk_object_sink(gobj);
} else {
g_object_unref(gobj);
}
return result;
}
struct param_setup_arg {
GObjectClass* gclass;
GParameter* params;
guint param_size;
VALUE params_hash;
guint index;
};
static VALUE
_params_setup(VALUE arg, struct param_setup_arg *param_setup_arg)
{
guint index;
VALUE name, val;
GParamSpec* pspec;
index = param_setup_arg->index;
if (index >= param_setup_arg->param_size)
rb_raise(rb_eArgError, "too many parameters");
name = rb_ary_entry(arg, 0);
val = rb_ary_entry(arg, 1);
if (SYMBOL_P(name))
param_setup_arg->params[index].name = rb_id2name(SYM2ID(name));
else
param_setup_arg->params[index].name = StringValuePtr(name);
pspec = g_object_class_find_property(
param_setup_arg->gclass,
param_setup_arg->params[index].name);
if (!pspec)
rb_raise(rb_eArgError, "No such property: %s",
param_setup_arg->params[index].name);
g_value_init(&(param_setup_arg->params[index].value),
G_PARAM_SPEC_VALUE_TYPE(pspec));
rbgobj_rvalue_to_gvalue(val, &(param_setup_arg->params[index].value));
param_setup_arg->index++;
return Qnil;
}
static VALUE
gobj_new_body(struct param_setup_arg* arg)
{
rb_iterate(rb_each, (VALUE)arg->params_hash, _params_setup, (VALUE)arg);
return (VALUE)g_object_newv(G_TYPE_FROM_CLASS(arg->gclass),
arg->param_size, arg->params);
}
static VALUE
gobj_new_ensure(struct param_setup_arg* arg)
{
guint i;
g_type_class_unref(arg->gclass);
for (i = 0; i < arg->param_size; i++) {
if (G_IS_VALUE(&arg->params[i].value))
g_value_unset(&arg->params[i].value);
}
return Qnil;
}
GObject*
rbgobj_gobject_new(GType gtype, VALUE params_hash)
{
GObject* result;
if (!g_type_is_a(gtype, G_TYPE_OBJECT))
rb_raise(rb_eArgError,
"type \"%s\" is not descendant of GObject",
g_type_name(gtype));
if (NIL_P(params_hash)) {
result = g_object_newv(gtype, 0, NULL);
} else {
size_t param_size;
struct param_setup_arg arg;
param_size = NUM2INT(rb_funcall(params_hash, rb_intern("length"), 0));
arg.param_size = param_size;
arg.gclass = G_OBJECT_CLASS(g_type_class_ref(gtype));
arg.params = ALLOCA_N(GParameter, param_size);
memset(arg.params, 0, sizeof(GParameter) * param_size);
arg.params_hash = params_hash;
arg.index = 0;
result = (GObject*)rb_ensure(&gobj_new_body, (VALUE)&arg,
&gobj_new_ensure, (VALUE)&arg);
}
if (!result)
rb_raise(rb_eRuntimeError, "g_object_newv failed");
return result;
}
static VALUE
rg_s_install_property(int argc, VALUE* argv, VALUE self)
{
const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
gpointer gclass;
GParamSpec* pspec;
VALUE pspec_obj, prop_id;
if (cinfo->klass != self)
rb_raise(rb_eTypeError, "%s isn't registered class",
rb_class2name(self));
rb_scan_args(argc, argv, "11", &pspec_obj, &prop_id);
pspec = G_PARAM_SPEC(RVAL2GOBJ(pspec_obj));
gclass = g_type_class_ref(cinfo->gtype);
g_object_class_install_property(gclass,
NIL_P(prop_id) ? 1 : NUM2UINT(prop_id),
pspec);
g_type_class_unref(gclass);
/* FIXME: define accessor methods */
return Qnil;
}
static VALUE
gobj_s_property(VALUE self, VALUE property_name)
{
GObjectClass* oclass;
const char* name;
GParamSpec* prop;
VALUE result;
if (SYMBOL_P(property_name))
name = rb_id2name(SYM2ID(property_name));
else
name = StringValuePtr(property_name);
oclass = g_type_class_ref(CLASS2GTYPE(self));
prop = g_object_class_find_property(oclass, name);
if (!prop){
g_type_class_unref(oclass);
rb_raise(eNoPropertyError, "No such property: %s", name);
}
result = GOBJ2RVAL(prop);
g_type_class_unref(oclass);
return result;
}
static VALUE
gobj_s_properties(int argc, VALUE* argv, VALUE self)
{
GObjectClass* oclass = g_type_class_ref(CLASS2GTYPE(self));
guint n_properties;
GParamSpec** props;
VALUE inherited_too;
VALUE ary;
guint i;
if (rb_scan_args(argc, argv, "01", &inherited_too) == 0)
inherited_too = Qtrue;
props = g_object_class_list_properties(oclass, &n_properties);
ary = rb_ary_new();
for (i = 0; i < n_properties; i++){
if (RVAL2CBOOL(inherited_too)
|| GTYPE2CLASS(props[i]->owner_type) == self)
rb_ary_push(ary, rb_str_new2(props[i]->name));
}
g_free(props);
g_type_class_unref(oclass);
return ary;
}
static VALUE type_to_prop_setter_table;
static VALUE type_to_prop_getter_table;
void
rbgobj_register_property_setter(GType gtype, const char *name, RValueToGValueFunc func)
{
GObjectClass* oclass;
GParamSpec* pspec;
VALUE table = rb_hash_aref(type_to_prop_setter_table, INT2FIX(gtype));
if (NIL_P(table)){
table = rb_hash_new();
rb_hash_aset(type_to_prop_setter_table, INT2FIX(gtype), table);
}
oclass = g_type_class_ref(gtype);
pspec = g_object_class_find_property(oclass, name);
rb_hash_aset(table, CSTR2RVAL(g_param_spec_get_name(pspec)),
Data_Wrap_Struct(rb_cData, NULL, NULL, func));
g_type_class_unref(oclass);
}
void
rbgobj_register_property_getter(GType gtype, const char *name, GValueToRValueFunc func)
{
GObjectClass* oclass;
GParamSpec* pspec;
VALUE table = rb_hash_aref(type_to_prop_getter_table, INT2FIX(gtype));
if (NIL_P(table)){
table = rb_hash_new();
rb_hash_aset(type_to_prop_getter_table, INT2FIX(gtype), table);
}
oclass = g_type_class_ref(gtype);
pspec = g_object_class_find_property(oclass, name);
rb_hash_aset(table, CSTR2RVAL(g_param_spec_get_name(pspec)),
Data_Wrap_Struct(rb_cData, NULL, NULL, func));
g_type_class_unref(oclass);
}
static VALUE
rg_set_property(VALUE self, VALUE prop_name, VALUE val)
{
GParamSpec* pspec;
const char* name;
if (SYMBOL_P(prop_name))
name = rb_id2name(SYM2ID(prop_name));
else
name = StringValuePtr(prop_name);
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(RVAL2GOBJ(self)),
name);
if (!pspec)
rb_raise(eNoPropertyError, "No such property: %s", name);
else {
// FIXME: use rb_ensure to call g_value_unset()
RValueToGValueFunc setter = NULL;
GValue gval = G_VALUE_INIT;
g_value_init(&gval, G_PARAM_SPEC_VALUE_TYPE(pspec));
{
VALUE table = rb_hash_aref(type_to_prop_setter_table,
INT2FIX(pspec->owner_type));
if (!NIL_P(table)){
VALUE obj = rb_hash_aref(table, CSTR2RVAL(g_param_spec_get_name(pspec)));
if (!NIL_P(obj))
Data_Get_Struct(obj, void, setter);
}
}
if (setter) {
setter(val, &gval);
} else {
rbgobj_rvalue_to_gvalue(val, &gval);
}
g_object_set_property(RVAL2GOBJ(self), name, &gval);
g_value_unset(&gval);
G_CHILD_SET(self, rb_intern(name), val);
return self;
}
}
static VALUE
rg_get_property(VALUE self, VALUE prop_name)
{
GParamSpec* pspec;
const char* name;
if (SYMBOL_P(prop_name))
name = rb_id2name(SYM2ID(prop_name));
else
name = StringValuePtr(prop_name);
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(RVAL2GOBJ(self)),
name);
if (!pspec)
rb_raise(eNoPropertyError, "No such property: %s", name);
else {
// FIXME: use rb_ensure to call g_value_unset()
GValueToRValueFunc getter = NULL;
GValue gval = G_VALUE_INIT;
VALUE ret;
{
VALUE table = rb_hash_aref(type_to_prop_getter_table,
INT2FIX(pspec->owner_type));
if (!NIL_P(table)){
VALUE obj = rb_hash_aref(table, CSTR2RVAL(g_param_spec_get_name(pspec)));
if (!NIL_P(obj))
Data_Get_Struct(obj, void, getter);
}
}
g_value_init(&gval, G_PARAM_SPEC_VALUE_TYPE(pspec));
g_object_get_property(RVAL2GOBJ(self), name, &gval);
ret = getter ? getter(&gval) : GVAL2RVAL(&gval);
g_value_unset(&gval);
G_CHILD_SET(self, rb_intern(name), ret);
return ret;
}
}
static VALUE rg_thaw_notify(VALUE self);
static VALUE
rg_freeze_notify(VALUE self)
{
g_object_freeze_notify(RVAL2GOBJ(self));
if (rb_block_given_p()) {
return rb_ensure(rb_yield, self, rg_thaw_notify, self);
}
return self;
}
static VALUE
rg_notify(VALUE self, VALUE property_name)
{
g_object_notify(RVAL2GOBJ(self), StringValuePtr(property_name));
return self;
}
static VALUE
rg_thaw_notify(VALUE self)
{
g_object_thaw_notify(RVAL2GOBJ(self));
return self;
}
static VALUE
rg_destroyed_p(VALUE self)
{
gobj_holder* holder;
if (!RVAL2CBOOL(rb_obj_is_kind_of(self, GTYPE2CLASS(G_TYPE_OBJECT))))
rb_raise(rb_eTypeError, "not a GLib::Object");
Data_Get_Struct(self, gobj_holder, holder);
return CBOOL2RVAL(holder->destroyed);
}
static VALUE
rg_inspect(VALUE self)
{
gobj_holder* holder;
const char *class_name;
char *s;
VALUE result;
Data_Get_Struct(self, gobj_holder, holder);
class_name = rb_class2name(CLASS_OF(self));
if (!holder->destroyed)
s = g_strdup_printf("#<%s:%p ptr=%p>", class_name, (void *)self,
holder->gobj);
else
s = g_strdup_printf("#<%s:%p destroyed>", class_name, (void *)self);
result = rb_str_new2(s);
g_free(s);
return result;
}
static VALUE
rg_type_name(VALUE self)
{
return CSTR2RVAL(G_OBJECT_TYPE_NAME(RVAL2GOBJ(self)));
}
static VALUE
rg_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE params_hash;
GObject* gobj;
rb_scan_args(argc, argv, "01", &params_hash);
if (!NIL_P(params_hash))
Check_Type(params_hash, RUBY_T_HASH);
gobj = rbgobj_gobject_new(RVAL2GTYPE(self), params_hash);
if (is_gtkobject(gobj)){
gobj = g_object_ref(gobj);
// We can't call gtk_object_sink() here.
// But hopefully someone will call it in the future.
//gtk_object_sink(gobj);
}
G_INITIALIZE(self, gobj);
return Qnil;
}
static VALUE
gobj_ref_count(VALUE self)
{
gobj_holder* holder;
Data_Get_Struct(self, gobj_holder, holder);
return INT2NUM(holder->gobj ? holder->gobj->ref_count : 0);
}
/**********************************************************************/
static VALUE proc_mod_eval;
static GQuark q_ruby_setter;
static GQuark q_ruby_getter;
// FIXME: use rb_protect
static void
get_prop_func(GObject* object,
G_GNUC_UNUSED guint property_id,
GValue* value,
GParamSpec* pspec)
{
ID ruby_getter = (ID)g_param_spec_get_qdata(pspec, q_ruby_getter);
if (!ruby_getter) {
gchar* name = g_strdup(g_param_spec_get_name(pspec));
gchar* p;
for (p = name; *p; p++) {
if (*p == '-')
*p = '_';
}
ruby_getter = rb_intern(name);
g_param_spec_set_qdata(pspec, q_ruby_getter, (gpointer)ruby_getter);
g_free(name);
}
{
VALUE ret = rb_funcall(GOBJ2RVAL(object), ruby_getter, 0);
rbgobj_rvalue_to_gvalue(ret, value);
}
}
// FIXME: use rb_protect
static void
set_prop_func(GObject* object,
G_GNUC_UNUSED guint property_id,
const GValue* value,
GParamSpec* pspec)
{
ID ruby_setter = (ID)g_param_spec_get_qdata(pspec, q_ruby_setter);
if (!ruby_setter) {
gchar* name = g_strconcat(g_param_spec_get_name(pspec), "=", NULL);
gchar* p;
for (p = name; *p; p++) {
if (*p == '-')
*p = '_';
}
ruby_setter = rb_intern(name);
g_param_spec_set_qdata(pspec, q_ruby_setter, (gpointer)ruby_setter);
g_free(name);
}
rb_funcall(GOBJ2RVAL(object), ruby_setter, 1, GVAL2RVAL(value));
}
// FIXME: use rb_protect
static void
class_init_func(gpointer g_class_, G_GNUC_UNUSED gpointer class_data)
{
GObjectClass* g_class = G_OBJECT_CLASS(g_class_);
g_class->set_property = set_prop_func;
g_class->get_property = get_prop_func;
#if 0
VALUE class_init_proc = (VALUE)class_data;
rb_funcall(proc_mod_eval, rb_intern("call"), 2,
GTYPE2CLASS(G_TYPE_FROM_CLASS(g_class)), class_init_proc);
#endif
}
static VALUE
rg_s_type_register(int argc, VALUE* argv, VALUE self)
{
VALUE type_name, flags;
volatile VALUE class_init_proc = Qnil;
GType parent_type;
GTypeInfo* info;
rb_scan_args(argc, argv, "03", &type_name, &info, &flags);
{
const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
if (cinfo->klass == self)
rb_raise(rb_eTypeError, "already registered");
}
{
VALUE superclass = rb_funcall(self, rb_intern("superclass"), 0);
const RGObjClassInfo* cinfo = rbgobj_lookup_class(superclass);
if (cinfo->klass != superclass)
rb_raise(rb_eTypeError, "super class must be registered to GLib");
parent_type = cinfo->gtype;
}
if (NIL_P(type_name)) {
VALUE s = rb_funcall(self, rb_intern("name"), 0);
if (strlen(StringValuePtr(s)) == 0)
rb_raise(rb_eTypeError, "can't determine type name");
type_name = rb_funcall(
rb_eval_string("lambda{|x| x.gsub(/::/,'') }"),
rb_intern("call"), 1, s);
}
{
GTypeQuery query;
g_type_query(parent_type, &query);
/* TODO: Why new? g_type_register_static() doesnt retain a copy, so
* this should be allocated on the stack. */
info = g_new0(GTypeInfo, 1);
info->class_size = query.class_size;
info->base_init = NULL;
info->base_finalize = NULL;
info->class_init = class_init_func;
info->class_finalize = NULL;
info->class_data = (gpointer)class_init_proc;
info->instance_size = query.instance_size;
info->n_preallocs = 0;
info->instance_init = NULL;
info->value_table = NULL;
}
{
GType type = g_type_register_static(parent_type,
StringValuePtr(type_name),
info,
NIL_P(flags) ? 0 : NUM2INT(flags));
G_RELATIVE(self, class_init_proc);
rbgobj_register_class(self, type, TRUE, TRUE);
{
RGObjClassInfo* cinfo = (RGObjClassInfo*)rbgobj_lookup_class(self);
cinfo->flags |= RBGOBJ_DEFINED_BY_RUBY;
}
{
GType parent = g_type_parent(type);
const RGObjClassInfo* cinfo = GTYPE2CINFO(parent);
VALUE m = rb_define_module_under(self, RubyGObjectHookModule);
if (! (cinfo->flags & RBGOBJ_DEFINED_BY_RUBY)) {
rbg_define_method(m, "initialize", rg_initialize, -1);
}
rb_include_module(self, m);
}
return Qnil;
}
}
/**********************************************************************/
void
Init_gobject_gobject(void)
{
RG_TARGET_NAMESPACE = G_DEF_CLASS_WITH_GC_FUNC(G_TYPE_OBJECT, "Object", mGLib,
gobj_mark, NULL);
#ifdef G_TYPE_INITIALLY_UNOWNED
G_DEF_CLASS(G_TYPE_INITIALLY_UNOWNED, "InitiallyUnowned", mGLib);
#endif
RUBY_GOBJECT_OBJ_KEY = g_quark_from_static_string("__ruby_gobject_object__");
rb_define_alloc_func(RG_TARGET_NAMESPACE, (VALUE(*)_((VALUE)))gobj_s_allocate);
RG_DEF_SMETHOD_BANG(new, -1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "property", &gobj_s_property, 1);
rbg_define_singleton_method(RG_TARGET_NAMESPACE, "properties", &gobj_s_properties, -1);
RG_DEF_SMETHOD(install_property, -1);
q_ruby_getter = g_quark_from_static_string("__ruby_getter");
q_ruby_setter = g_quark_from_static_string("__ruby_setter");
RG_DEF_METHOD(set_property, 2);
RG_DEF_METHOD(get_property, 1);
RG_DEF_METHOD(freeze_notify, 0);
rb_undef_method(RG_TARGET_NAMESPACE, "notify");
RG_DEF_METHOD(notify, 1);
RG_DEF_METHOD(thaw_notify, 0);
RG_DEF_METHOD_P(destroyed, 0);
RG_DEF_METHOD(initialize, -1);
rbg_define_method(RG_TARGET_NAMESPACE, "ref_count", gobj_ref_count, 0); /* for debugging */
RG_DEF_METHOD(inspect, 0);
RG_DEF_METHOD(type_name, 0);
eNoPropertyError = rb_define_class_under(mGLib, "NoPropertyError",
rb_eNameError);
rb_global_variable(&type_to_prop_setter_table);
rb_global_variable(&type_to_prop_getter_table);
type_to_prop_setter_table = rb_hash_new();
type_to_prop_getter_table = rb_hash_new();
/* subclass */
RG_DEF_SMETHOD(type_register, -1);
rb_global_variable(&proc_mod_eval);
proc_mod_eval = rb_eval_string("lambda{|obj,proc| obj.module_eval(&proc)}");
}

View File

@ -0,0 +1,378 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE rbgobj_cParam
VALUE RG_TARGET_NAMESPACE;
static GQuark qparamspec;
static VALUE pspec_s_allocate(VALUE klass);
typedef struct {
GParamSpec* instance;
const RGObjClassInfo* cinfo;
} pspec_holder;
static void
pspec_mark(pspec_holder *holder)
{
if (holder->instance)
rbgobj_instance_call_cinfo_mark(holder->instance);
}
static void
pspec_free(pspec_holder *holder)
{
if (holder->instance){
rbgobj_instance_call_cinfo_free(holder->instance);
g_param_spec_set_qdata(holder->instance, qparamspec, NULL);
g_param_spec_unref(holder->instance);
}
free(holder);
}
GParamSpec*
rbgobj_get_param_spec(VALUE obj)
{
pspec_holder* holder;
Data_Get_Struct(obj, pspec_holder, holder);
return G_PARAM_SPEC(holder->instance);
}
void
rbgobj_param_spec_initialize(VALUE self, GParamSpec *pspec)
{
pspec_holder* holder;
Data_Get_Struct(self, pspec_holder, holder);
pspec = g_param_spec_ref(pspec);
g_param_spec_sink(pspec);
holder->instance = pspec;
holder->cinfo = GTYPE2CINFO(G_PARAM_SPEC_TYPE(pspec));
g_param_spec_set_qdata(pspec, qparamspec, (gpointer)self);
}
VALUE
rbgobj_get_ruby_object_from_param_spec(GParamSpec* pspec, gboolean alloc)
{
gpointer data = g_param_spec_get_qdata(pspec, qparamspec);
if (data)
return (VALUE)data;
else if (alloc) {
VALUE result = pspec_s_allocate(GTYPE2CLASS(G_PARAM_SPEC_TYPE(pspec)));
rbgobj_param_spec_initialize(result, pspec);
return result;
} else
return Qnil;
}
/**********************************************************************/
static VALUE
pspec_s_allocate(VALUE klass)
{
const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
if (G_TYPE_IS_ABSTRACT(cinfo->gtype))
rb_raise(rb_eTypeError, "abstract class");
{
pspec_holder* holder;
VALUE result;
result = Data_Make_Struct(klass, pspec_holder, pspec_mark, pspec_free,
holder);
holder->instance = NULL;
holder->cinfo = NULL;
return result;
}
}
static VALUE
rg_inspect(VALUE self)
{
GParamSpec* pspec = rbgobj_get_param_spec(self);
VALUE v = rb_inspect(GTYPE2CLASS(pspec->owner_type));
gchar* str = g_strdup_printf("#<%s: %s#%s>",
rb_class2name(CLASS_OF(self)),
StringValuePtr(v),
g_param_spec_get_name(pspec));
VALUE result = rb_str_new2(str);
g_free(str);
return result;
}
static VALUE
rg_name(VALUE self)
{
return rb_str_new2(g_param_spec_get_name(rbgobj_get_param_spec(self)));
}
static VALUE
rg_nick(VALUE self)
{
const gchar* str = g_param_spec_get_nick(rbgobj_get_param_spec(self));
return str ? rb_str_new2(str) : Qnil;
}
static VALUE
rg_blurb(VALUE self)
{
const gchar* str = g_param_spec_get_blurb(rbgobj_get_param_spec(self));
return str ? rb_str_new2(str) : Qnil;
}
static VALUE
rg_flags(VALUE self)
{
return INT2NUM(rbgobj_get_param_spec(self)->flags);
}
static VALUE
rg_value_type(VALUE self)
{
return rbgobj_gtype_new(G_PARAM_SPEC_VALUE_TYPE(rbgobj_get_param_spec(self)));
}
static VALUE
rg_owner_type(VALUE self)
{
return rbgobj_gtype_new(rbgobj_get_param_spec(self)->owner_type);
}
static VALUE
rg_owner(VALUE self)
{
return GTYPE2CLASS(rbgobj_get_param_spec(self)->owner_type);
}
static VALUE
rg_value_default(VALUE self)
{
GValue tmp = G_VALUE_INIT;
VALUE result;
g_value_init(&tmp,
G_PARAM_SPEC_VALUE_TYPE(rbgobj_get_param_spec(self)));
g_param_value_set_default(rbgobj_get_param_spec(self), &tmp);
result = rbgobj_gvalue_to_rvalue(&tmp);
g_value_unset(&tmp);
return result;
}
#if 0
static VALUE
rg_value_defaults_p(VALUE self, VALUE val)
{
GValue tmp = {0,};
gboolean result;
/* FIXME: use rb_ensure to ensure following g_value_unset() call*/
g_value_init(&tmp,
G_PARAM_SPEC_VALUE_TYPE(rbgobj_get_param_spec(self)));
rbgobj_rvalue_to_gvalue(val, &tmp);
result = g_param_value_defaults(rbgobj_get_param_spec(self), &tmp);
g_value_unset(&tmp);
return CBOOL2RVAL(result);
}
#endif
struct validate_arg{
GParamSpec* pspec;
GValue* value;
VALUE obj;
};
static VALUE
value_validate_body(struct validate_arg* arg)
{
VALUE ret;
gboolean b;
rbgobj_rvalue_to_gvalue(arg->obj, arg->value);
b = g_param_value_validate(arg->pspec, arg->value);
ret = rbgobj_gvalue_to_rvalue(arg->value);
return rb_ary_new3(2, CBOOL2RVAL(b), ret);
}
static VALUE
value_validate_ensure(struct validate_arg* arg)
{
g_value_unset(arg->value);
return Qnil;
}
static VALUE
rg_value_validate(VALUE self, VALUE obj)
{
struct validate_arg arg;
GValue value = G_VALUE_INIT;
arg.pspec = rbgobj_get_param_spec(self);
arg.value = &value;
arg.obj = obj;
g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(arg.pspec));
return rb_ensure(value_validate_body, (VALUE)&arg,
value_validate_ensure, (VALUE)&arg);
}
static VALUE
rg_value_convert(int argc, VALUE* argv, VALUE self)
{
GParamSpec* pspec = rbgobj_get_param_spec(self);
VALUE src, strict_validation;
VALUE src_type;
VALUE result = Qnil;
GValue src_value = G_VALUE_INIT;
GValue dest_value = G_VALUE_INIT;
gboolean b;
rb_scan_args(argc, argv, "21", &src, &src_type, &strict_validation);
/* FIXME: use rb_ensure to ensure following g_value_unset() call*/
g_value_init(&src_value, rbgobj_gtype_get(src_type));
g_value_init(&dest_value, G_PARAM_SPEC_VALUE_TYPE(pspec));
rbgobj_rvalue_to_gvalue(src, &src_value);
b = g_param_value_convert(rbgobj_get_param_spec(self),
&src_value, &dest_value,
RVAL2CBOOL(strict_validation));
if (b)
result = rbgobj_gvalue_to_rvalue(&dest_value);
g_value_unset(&src_value);
g_value_unset(&dest_value);
if (b)
return result;
else
rb_raise(rb_eTypeError, "can't convert");
}
static VALUE
rg_value_compare(VALUE self, VALUE a, VALUE b)
{
GParamSpec* pspec = rbgobj_get_param_spec(self);
GType type = G_PARAM_SPEC_VALUE_TYPE(pspec);
GValue v1 = G_VALUE_INIT;
GValue v2 = G_VALUE_INIT;
gint result;
g_value_init(&v1, type);
g_value_init(&v2, type);
/* FIXME: use rb_ensure to ensure following g_value_unset() call*/
rbgobj_rvalue_to_gvalue(a, &v1);
rbgobj_rvalue_to_gvalue(b, &v2);
result = g_param_values_cmp(pspec, &v1, &v2);
g_value_unset(&v1);
g_value_unset(&v2);
return INT2NUM(result);
}
static VALUE
rg_ref_count(VALUE self)
{
return INT2NUM(G_PARAM_SPEC(rbgobj_get_param_spec(self))->ref_count);
}
#define param_is_flag(flag) \
static VALUE \
param_is_##flag(VALUE self) \
{ \
GParamSpec* pspec = G_PARAM_SPEC(rbgobj_get_param_spec(self)); \
return CBOOL2RVAL(pspec->flags & flag); \
}
param_is_flag(G_PARAM_READABLE)
param_is_flag(G_PARAM_WRITABLE)
param_is_flag(G_PARAM_CONSTRUCT)
param_is_flag(G_PARAM_CONSTRUCT_ONLY)
param_is_flag(G_PARAM_LAX_VALIDATION)
param_is_flag(G_PARAM_PRIVATE)
param_is_flag(G_PARAM_READWRITE)
/**********************************************************************/
void
Init_gobject_gparam(void)
{
qparamspec = g_quark_from_static_string("__ruby_gobject_param_spec__");
RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_PARAM, "Param", mGLib);
/* GParamFlags */
rb_define_const(RG_TARGET_NAMESPACE, "READABLE", INT2FIX(G_PARAM_READABLE));
rb_define_const(RG_TARGET_NAMESPACE, "WRITABLE", INT2FIX(G_PARAM_WRITABLE));
rb_define_const(RG_TARGET_NAMESPACE, "CONSTRUCT", INT2FIX(G_PARAM_CONSTRUCT));
rb_define_const(RG_TARGET_NAMESPACE, "CONSTRUCT_ONLY", INT2FIX(G_PARAM_CONSTRUCT_ONLY));
rb_define_const(RG_TARGET_NAMESPACE, "LAX_VALIDATION", INT2FIX(G_PARAM_LAX_VALIDATION));
rb_define_const(RG_TARGET_NAMESPACE, "PRIVATE", INT2FIX(G_PARAM_PRIVATE));
rb_define_const(RG_TARGET_NAMESPACE, "READWRITE", INT2FIX(G_PARAM_READWRITE));
rb_define_const(RG_TARGET_NAMESPACE, "MASK", INT2FIX(G_PARAM_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "USER_SHIFT", INT2FIX(G_PARAM_USER_SHIFT));
rb_define_alloc_func(RG_TARGET_NAMESPACE, pspec_s_allocate);
RG_DEF_METHOD(inspect, 0);
RG_DEF_METHOD(name, 0);
RG_DEF_METHOD(nick, 0);
RG_DEF_METHOD(blurb, 0);
RG_DEF_METHOD(flags, 0);
RG_DEF_METHOD(value_type, 0);
RG_DEF_METHOD(owner_type, 0);
RG_DEF_METHOD(owner, 0);
RG_DEF_METHOD(value_default, 0);
RG_DEF_ALIAS("default", "value_default");
// FIXME: better name
#if 0
RG_DEF_METHOD_P(value_defaults, 1);
#endif
RG_DEF_METHOD(value_validate, 1);
RG_DEF_METHOD(value_convert, -1);
RG_DEF_METHOD(value_compare, 2);
/* for debugging */
RG_DEF_METHOD(ref_count, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "readable?", param_is_G_PARAM_READABLE, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "writable?", param_is_G_PARAM_WRITABLE, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "construct?", param_is_G_PARAM_CONSTRUCT, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "construct_only?", param_is_G_PARAM_CONSTRUCT_ONLY, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "lax_validation?", param_is_G_PARAM_LAX_VALIDATION, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "private?", param_is_G_PARAM_PRIVATE, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "readwrite?", param_is_G_PARAM_READWRITE, 0);
}

View File

@ -0,0 +1,311 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2004 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define DEF_NUMERIC_PSPEC_METHODS_FUNC(pspec_type, typename, from_ruby, to_ruby, pspec_cast) \
static VALUE \
typename##_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb, \
VALUE minimum, VALUE maximum, VALUE default_value, \
VALUE flags) \
{ \
GParamSpec* pspec; \
pspec = g_param_spec_##typename(StringValuePtr(name), \
StringValuePtr(nick), \
StringValuePtr(blurb), \
from_ruby(minimum), \
from_ruby(maximum), \
from_ruby(default_value), \
NUM2UINT(flags)); \
rbgobj_param_spec_initialize(self, pspec); \
return Qnil; \
} \
\
static VALUE \
typename##_minimum(VALUE self) \
{ \
return to_ruby(pspec_cast(RVAL2GOBJ(self))->minimum); \
} \
\
static VALUE \
typename##_maximum(VALUE self) \
{ \
return to_ruby(pspec_cast(RVAL2GOBJ(self))->maximum); \
} \
\
static VALUE \
typename##_range(VALUE self) \
{ \
pspec_type* pspec = pspec_cast(RVAL2GOBJ(self)); \
return rb_range_new(pspec->minimum, pspec->maximum, 0); \
}
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecChar, char, NUM2INT, INT2FIX, G_PARAM_SPEC_CHAR)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecUChar, uchar, NUM2UINT, INT2FIX, G_PARAM_SPEC_UCHAR)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecInt, int, NUM2INT, INT2NUM, G_PARAM_SPEC_INT)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecUInt, uint, NUM2UINT, UINT2NUM, G_PARAM_SPEC_UINT)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecLong, long, NUM2LONG, INT2NUM, G_PARAM_SPEC_LONG)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecULong, ulong, NUM2ULONG, UINT2NUM, G_PARAM_SPEC_ULONG)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecInt64, int64, rbglib_num_to_int64, rbglib_int64_to_num, G_PARAM_SPEC_INT64)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecUInt64, uint64, rbglib_num_to_uint64, rbglib_uint64_to_num, G_PARAM_SPEC_UINT64)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecFloat, float, NUM2DBL, rb_float_new, G_PARAM_SPEC_FLOAT)
DEF_NUMERIC_PSPEC_METHODS_FUNC(GParamSpecDouble, double, NUM2DBL, rb_float_new, G_PARAM_SPEC_DOUBLE)
static VALUE
float_epsilon(VALUE self)
{
return rb_float_new(G_PARAM_SPEC_FLOAT(RVAL2GOBJ(self))->epsilon);
}
static VALUE
double_epsilon(VALUE self)
{
return rb_float_new(G_PARAM_SPEC_DOUBLE(RVAL2GOBJ(self))->epsilon);
}
static VALUE
boolean_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE default_value, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_boolean(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
RVAL2CBOOL(default_value),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
unichar_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE default_value, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_unichar(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
NUM2UINT(default_value),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
enum_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE enum_type, VALUE default_value, VALUE flags)
{
GParamSpec* pspec;
GType gtype = rbgobj_gtype_get(enum_type);
pspec = g_param_spec_enum(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
gtype,
RVAL2GENUM(default_value, gtype),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
flags_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE flags_type, VALUE default_value, VALUE flags)
{
GParamSpec* pspec;
GType gtype = rbgobj_gtype_get(flags_type);
pspec = g_param_spec_flags(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
gtype,
RVAL2GFLAGS(default_value, gtype),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
string_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE default_value, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_string(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
NIL_P(default_value) ? NULL : StringValuePtr(default_value),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
param_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE param_type, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_param(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
rbgobj_gtype_get(param_type),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
boxed_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE boxed_type, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_boxed(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
rbgobj_gtype_get(boxed_type),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
pointer_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_pointer(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
value_array_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE element_spec, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_value_array(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
RVAL2GOBJ(element_spec),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
static VALUE
object_initialize(VALUE self, VALUE name, VALUE nick, VALUE blurb,
VALUE object_type, VALUE flags)
{
GParamSpec* pspec;
pspec = g_param_spec_object(StringValuePtr(name),
StringValuePtr(nick),
StringValuePtr(blurb),
rbgobj_gtype_get(object_type),
NUM2UINT(flags));
rbgobj_param_spec_initialize(self, pspec);
return Qnil;
}
void
Init_gobject_gparamspecs(void)
{
VALUE cParamSpec = GTYPE2CLASS(G_TYPE_PARAM);
VALUE c;
#define DEF_NUMERIC_PSPEC_METHODS(c, typename) \
G_STMT_START {\
rbg_define_method(c, "initialize", typename##_initialize, 7); \
rbg_define_method(c, "minimum", typename##_minimum, 0); \
rbg_define_method(c, "maximum", typename##_maximum, 0); \
rbg_define_method(c, "range", typename##_range, 0); \
} G_STMT_END
#if 0
rbg_define_method(c, "default_value", typename##_default_value, 0); \
rb_define_alias(c, "default", "default_value"); \
#endif
c = G_DEF_CLASS(G_TYPE_PARAM_CHAR, "Char", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, char);
c = G_DEF_CLASS(G_TYPE_PARAM_UCHAR, "UChar", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, uchar);
c = G_DEF_CLASS(G_TYPE_PARAM_INT, "Int", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, int);
c = G_DEF_CLASS(G_TYPE_PARAM_UINT, "UInt", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, uint);
c = G_DEF_CLASS(G_TYPE_PARAM_LONG, "Long", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, long);
c = G_DEF_CLASS(G_TYPE_PARAM_ULONG, "ULong", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, ulong);
c = G_DEF_CLASS(G_TYPE_PARAM_INT64, "Int64", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, int64);
c = G_DEF_CLASS(G_TYPE_PARAM_UINT64, "UInt64", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, uint64);
c = G_DEF_CLASS(G_TYPE_PARAM_FLOAT, "Float", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, float);
rbg_define_method(c, "epsilon", float_epsilon, 0);
c = G_DEF_CLASS(G_TYPE_PARAM_DOUBLE, "Double", cParamSpec);
DEF_NUMERIC_PSPEC_METHODS(c, double);
rbg_define_method(c, "epsilon", double_epsilon, 0);
c = G_DEF_CLASS(G_TYPE_PARAM_BOOLEAN, "Boolean", cParamSpec);
rbg_define_method(c, "initialize", boolean_initialize, 5);
c = G_DEF_CLASS(G_TYPE_PARAM_UNICHAR, "UniChar", cParamSpec);
rbg_define_method(c, "initialize", unichar_initialize, 5);
c = G_DEF_CLASS(G_TYPE_PARAM_ENUM, "Enum", cParamSpec);
rbg_define_method(c, "initialize", enum_initialize, 6);
c = G_DEF_CLASS(G_TYPE_PARAM_FLAGS, "Flags", cParamSpec);
rbg_define_method(c, "initialize", flags_initialize, 6);
c = G_DEF_CLASS(G_TYPE_PARAM_STRING, "String", cParamSpec);
rbg_define_method(c, "initialize", string_initialize, 5);
c = G_DEF_CLASS(G_TYPE_PARAM_PARAM, "Param", cParamSpec);
rbg_define_method(c, "initialize", param_initialize, 5);
c = G_DEF_CLASS(G_TYPE_PARAM_BOXED, "Boxed", cParamSpec);
rbg_define_method(c, "initialize", boxed_initialize, 5);
c = G_DEF_CLASS(G_TYPE_PARAM_POINTER, "Pointer", cParamSpec);
rbg_define_method(c, "initialize", pointer_initialize, 4);
c = G_DEF_CLASS(G_TYPE_PARAM_VALUE_ARRAY, "ValueArray", cParamSpec);
rbg_define_method(c, "initialize", value_array_initialize, 5);
c = G_DEF_CLASS(G_TYPE_PARAM_OBJECT, "Object", cParamSpec);
rbg_define_method(c, "initialize", object_initialize, 5);
}

View File

@ -0,0 +1,978 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2004 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cSignal
static VALUE RG_TARGET_NAMESPACE;
VALUE rbgobj_signal_wrap(guint sig_id);
#define default_handler_method_prefix "signal_do_"
/**********************************************************************/
static VALUE signal_func_table;
void
rbgobj_set_signal_func(VALUE klass, const gchar *sig_name, GValToRValSignalFunc func)
{
VALUE obj = Data_Wrap_Struct(rb_cData, NULL, NULL, func);
guint signal_id = g_signal_lookup(sig_name, CLASS2GTYPE(klass));
rb_hash_aset(signal_func_table, UINT2NUM(signal_id), obj);
}
GValToRValSignalFunc
rbgobj_get_signal_func(guint signal_id)
{
GValToRValSignalFunc func = NULL;
VALUE func_obj = rb_hash_aref(signal_func_table, UINT2NUM(signal_id));
if (!NIL_P(func_obj))
Data_Get_Struct(func_obj, void, func);
return func;
}
/**********************************************************************/
static VALUE eNoSignalError;
// FIXME: use rb_protect
static gboolean
accumulator_func(G_GNUC_UNUSED GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data)
{
VALUE proc = (VALUE)data;
VALUE val = GVAL2RVAL(return_accu);
VALUE new = GVAL2RVAL(handler_return);
VALUE hint = Qnil; // FIXME
VALUE tmp;
gboolean continue_emission = TRUE;
tmp = rb_funcall(proc, rb_intern("call"), 3, hint, val, new);
/* FIXME */
if (TYPE(tmp) == T_ARRAY) {
continue_emission = RVAL2CBOOL(rb_ary_entry(tmp, 0));
val = rb_ary_entry(tmp, 1);
} else {
val = tmp;
}
rbgobj_rvalue_to_gvalue(val, return_accu);
return continue_emission;
}
struct rval2gtypes_args {
VALUE ary;
long n;
GType *result;
};
static VALUE
rbg_rval2gtypes_body(VALUE value)
{
long i;
struct rval2gtypes_args *args = (struct rval2gtypes_args *)value;
for (i = 0; i < args->n; i++)
args->result[i] = rbgobj_gtype_get(RARRAY_PTR(args->ary)[i]);
return Qnil;
}
static G_GNUC_NORETURN VALUE
rbg_rval2gtypes_rescue(VALUE value)
{
g_free(((struct rval2gtypes_args *)value)->result);
rb_exc_raise(rb_errinfo());
}
static GType *
rbg_rval2gtypes(volatile VALUE *value, long *n)
{
struct rval2gtypes_args args;
args.ary = *value = rb_ary_dup(rb_ary_to_ary(*value));
args.n = RARRAY_LEN(args.ary);
args.result = g_new(GType, args.n + 1);
rb_rescue(rbg_rval2gtypes_body, (VALUE)&args,
rbg_rval2gtypes_rescue, (VALUE)&args);
if (n != NULL)
*n = args.n;
return args.result;
}
static GType *
rbg_rval2gtypes_accept_nil(volatile VALUE *value, long *n)
{
if (!NIL_P(*value))
return rbg_rval2gtypes(value, n);
if (n != NULL)
*n = 0;
return NULL;
}
#define RVAL2GTYPES(value, n) rbg_rval2gtypes(&(value), &(n))
#define RVAL2GTYPES_ACCEPT_NIL(value, n) rbg_rval2gtypes_accept_nil(&(value), &(n))
static VALUE
gobj_s_signal_new(int argc, VALUE* argv, VALUE self)
{
const RGObjClassInfo *cinfo = rbgobj_lookup_class(self);
VALUE rbsignal_name, rbsignal_flags, accumulator, rbreturn_type, params;
const gchar *signal_name;
GSignalFlags signal_flags;
GClosure *class_closure;
GType return_type;
GType *param_types;
long n_params;
guint signal;
rb_scan_args(argc, argv, "4*",
&rbsignal_name, &rbsignal_flags, &accumulator, &rbreturn_type, &params);
if (cinfo->klass != self)
rb_raise(rb_eTypeError, "not a registered class: %s",
rb_class2name(self));
if (SYMBOL_P(rbsignal_name))
rbsignal_name = rb_str_new2(rb_id2name(SYM2ID(rbsignal_name)));
signal_name = RVAL2CSTR(rbsignal_name);
signal_flags = NUM2INT(rbsignal_flags);
{
VALUE factory;
VALUE proc;
ID method_id;
method_id = rb_to_id(rb_str_concat(rb_str_new2(default_handler_method_prefix), rbsignal_name));
factory = rb_eval_string(
"lambda{|klass, id|\n"
" lambda{|instance,*args|\n"
" klass.instance_method(id).bind(instance).call(*args)\n"
" }\n"
"}\n");
proc = rb_funcall(factory, rb_intern("call"), 2, self, ID2SYM(method_id));
class_closure = g_rclosure_new(proc, Qnil, NULL);
/* TODO: Should this be done even if something below it fails? */
g_rclosure_attach(class_closure, self);
}
return_type = rbgobj_gtype_get(rbreturn_type);
param_types = RVAL2GTYPES_ACCEPT_NIL(params, n_params);
signal = g_signal_newv(signal_name,
cinfo->gtype,
signal_flags,
class_closure,
NIL_P(accumulator) ? NULL : accumulator_func,
NIL_P(accumulator) ? NULL : (gpointer)accumulator,
NULL, /* c_marshaller */
return_type,
n_params,
param_types);
g_free(param_types);
if (!signal)
rb_raise(rb_eRuntimeError, "g_signal_newv failed");
if (!NIL_P(accumulator))
G_RELATIVE(self, accumulator); /* FIXME */
return rbgobj_signal_wrap(signal);
}
static void
_signal_list(VALUE result, GType gtype)
{
guint n_ids, i;
guint* ids = g_signal_list_ids(gtype, &n_ids);
for (i = 0; i < n_ids; i++)
rb_ary_push(result, rb_str_new2(g_signal_name(ids[i])));
g_free(ids);
}
static VALUE
gobj_s_signals(int argc, VALUE* argv, VALUE self)
{
GType gtype;
VALUE inherited_too, result;
if (rb_scan_args(argc, argv, "01", &inherited_too) == 0)
inherited_too = Qtrue;
gtype = CLASS2GTYPE(self);
result = rb_ary_new();
if (RVAL2CBOOL(inherited_too)){
guint n_interfaces, i;
GType* interfaces = g_type_interfaces(gtype, &n_interfaces);
for (i = 0; i < n_interfaces; i++)
_signal_list(result, interfaces[i]);
g_free(interfaces);
for (; gtype; gtype = g_type_parent(gtype))
_signal_list(result, gtype);
} else if (GTYPE2CLASS(gtype) == self) {
_signal_list(result, gtype);
}
return result;
}
static VALUE
gobj_s_signal(VALUE self, VALUE name)
{
const char* sig_name;
guint sig_id;
if (SYMBOL_P(name))
sig_name = rb_id2name(SYM2ID(name));
else
sig_name = StringValuePtr(name);
sig_id = g_signal_lookup(sig_name, CLASS2GTYPE(self));
if (!sig_id)
rb_raise(eNoSignalError, "no such signal: %s", sig_name);
return rbgobj_signal_wrap(sig_id);
}
static VALUE
gobj_sig_has_handler_pending(int argc, VALUE *argv, VALUE self)
{
VALUE sig, may_be_blocked;
const char* sig_name;
guint signal_id;
GQuark detail;
rb_scan_args(argc, argv, "11", &sig, &may_be_blocked);
if (SYMBOL_P(sig))
sig_name = rb_id2name(SYM2ID(sig));
else
sig_name = StringValuePtr(sig);
if (!g_signal_parse_name(sig_name, CLASS2GTYPE(CLASS_OF(self)), &signal_id, &detail, TRUE))
rb_raise(eNoSignalError, "no such signal: %s", sig_name);
return CBOOL2RVAL(g_signal_has_handler_pending(RVAL2GOBJ(self),
signal_id, detail,
RVAL2CBOOL(may_be_blocked)));
}
static VALUE
gobj_sig_connect_impl(gboolean after, int argc, VALUE *argv, VALUE self)
{
VALUE sig, rest;
gulong handler_id;
GClosure* rclosure;
const char* sig_name;
guint signal_id;
GQuark detail;
VALUE func;
GObject *g_object;
gchar *tag;
rb_scan_args(argc, argv, "1*", &sig, &rest);
if (NIL_P(rest)) rest = rb_ary_new();
if (SYMBOL_P(sig))
sig_name = rb_id2name(SYM2ID(sig));
else
sig_name = StringValuePtr(sig);
if (!g_signal_parse_name(sig_name, CLASS2GTYPE(CLASS_OF(self)), &signal_id, &detail, TRUE))
rb_raise(eNoSignalError, "no such signal: %s", sig_name);
func = rb_block_proc();
rclosure = g_rclosure_new(func, rest,
rbgobj_get_signal_func(signal_id));
g_rclosure_attach((GClosure *)rclosure, self);
g_object = RVAL2GOBJ(self);
tag = g_strdup_printf("%s::%s",
G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(g_object)),
sig_name);
g_rclosure_set_tag((GClosure *)rclosure, tag);
g_free(tag);
handler_id = g_signal_connect_closure_by_id(g_object, signal_id, detail,
rclosure, after);
return ULONG2NUM(handler_id);
}
static VALUE
gobj_sig_connect(int argc, VALUE *argv, VALUE self)
{
return gobj_sig_connect_impl(FALSE, argc, argv, self);
}
static VALUE
gobj_sig_connect_after(int argc, VALUE *argv, VALUE self)
{
return gobj_sig_connect_impl(TRUE, argc, argv, self);
}
#if 0
static VALUE
gobj_sig_get_invocation_hint(VALUE self)
{
GSignalInvocationHint* hint;
hint = g_signal_get_invocation_hint(RVAL2GOBJ(self));
return rb_ary_new3(3,
rbgobj_signal_wrap(hint->signal_id),
hint->detail ? rb_str_new2(g_quark_to_string(hint->detail)) : Qnil,
INT2NUM(hint->run_type));
}
#endif
struct emit_arg {
VALUE self;
VALUE args;
GSignalQuery query;
GQuark detail;
GValueArray* instance_and_params;
};
static VALUE
emit_body(struct emit_arg* arg)
{
GValue param = G_VALUE_INIT;
g_value_init(&param, G_TYPE_FROM_INSTANCE(RVAL2GOBJ(arg->self)));
rbgobj_rvalue_to_gvalue(arg->self, &param);
g_value_array_append(arg->instance_and_params, &param);
g_value_unset(&param);
{
guint i;
for (i = 0; i < arg->query.n_params; i++){
GType gtype = arg->query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
g_value_init(&param, gtype);
rbgobj_rvalue_to_gvalue(rb_ary_entry(arg->args, i), &param);
g_value_array_append(arg->instance_and_params, &param);
g_value_unset(&param);
}
}
{
gboolean use_ret = (arg->query.return_type != G_TYPE_NONE);
GValue return_value = G_VALUE_INIT;
if (use_ret)
g_value_init(&return_value,
arg->query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
g_signal_emitv(arg->instance_and_params->values,
arg->query.signal_id, arg->detail,
(use_ret) ? &return_value : NULL);
if (use_ret) {
VALUE ret = GVAL2RVAL(&return_value);
g_value_unset(&return_value);
return ret;
} else {
return Qnil;
}
}
}
static VALUE
emit_ensure(struct emit_arg* arg)
{
g_value_array_free(arg->instance_and_params);
return Qnil;
}
static VALUE
gobj_sig_emit(int argc, VALUE *argv, VALUE self)
{
VALUE sig;
const char* sig_name;
guint signal_id;
struct emit_arg arg;
rb_scan_args(argc, argv, "1*", &sig, &arg.args);
if (SYMBOL_P(sig))
sig_name = rb_id2name(SYM2ID(sig));
else
sig_name = StringValuePtr(sig);
if (!g_signal_parse_name(sig_name,
CLASS2GTYPE(CLASS_OF(self)),
&signal_id, &arg.detail, FALSE))
rb_raise(eNoSignalError, "invalid signal \"%s\"", sig_name);
g_signal_query(signal_id, &arg.query);
if (arg.query.n_params != (guint)RARRAY_LEN(arg.args))
rb_raise(rb_eArgError, "wrong number of arguments(%ld for %d)",
RARRAY_LEN(arg.args) + 1,
arg.query.n_params + 1);
arg.self = self;
arg.instance_and_params = g_value_array_new(1 + arg.query.n_params);
return rb_ensure(emit_body, (VALUE)&arg, emit_ensure, (VALUE)&arg);
}
static VALUE
gobj_sig_emit_stop(VALUE self, VALUE sig)
{
gpointer instance = RVAL2GOBJ(self);
const char* sig_name;
guint signal_id;
GQuark detail;
if (SYMBOL_P(sig))
sig_name = rb_id2name(SYM2ID(sig));
else
sig_name = StringValuePtr(sig);
if (!g_signal_parse_name(sig_name,
CLASS2GTYPE(CLASS_OF(self)),
&signal_id, &detail, FALSE))
rb_raise(eNoSignalError, "invalid signal \"%s\"", sig_name);
g_signal_stop_emission(instance, signal_id, detail);
return self;
}
static VALUE gobj_sig_handler_unblock(VALUE self, VALUE id);
static VALUE
_sig_handler_block_ensure(VALUE arg)
{
VALUE self = RARRAY_PTR(arg)[0];
VALUE id = RARRAY_PTR(arg)[1];
gobj_sig_handler_unblock(self, id);
return Qnil;
}
static VALUE
gobj_sig_handler_block(VALUE self, VALUE id)
{
g_signal_handler_block(RVAL2GOBJ(self), NUM2ULONG(id));
if (rb_block_given_p())
rb_ensure(rb_yield, self, _sig_handler_block_ensure,
rb_ary_new3(2, self, id));
return self;
}
static VALUE
gobj_sig_handler_unblock(VALUE self, VALUE id)
{
g_signal_handler_unblock(RVAL2GOBJ(self), NUM2ULONG(id));
return self;
}
static VALUE
gobj_sig_handler_disconnect(VALUE self, VALUE id)
{
g_signal_handler_disconnect(RVAL2GOBJ(self), NUM2ULONG(id));
return self;
}
static VALUE
gobj_sig_handler_is_connected(VALUE self, VALUE id)
{
return CBOOL2RVAL(g_signal_handler_is_connected(RVAL2GOBJ(self), NUM2ULONG(id)));
}
#if 0
gulong g_signal_handler_find (gpointer instance,
GSignalMatchType mask,
guint signal_id,
GQuark detail,
GClosure *closure,
gpointer func,
gpointer data);
guint g_signal_handlers_block_matched (gpointer instance,
GSignalMatchType mask,
guint signal_id,
GQuark detail,
GClosure *closure,
gpointer func,
gpointer data);
guint g_signal_handlers_unblock_matched (gpointer instance,
GSignalMatchType mask,
guint signal_id,
GQuark detail,
GClosure *closure,
gpointer func,
gpointer data);
guint g_signal_handlers_disconnect_matched (gpointer instance,
GSignalMatchType mask,
guint signal_id,
GQuark detail,
GClosure *closure,
gpointer func,
gpointer data);
#endif
static VALUE
chain_from_overridden_body(struct emit_arg* arg)
{
g_value_init(arg->instance_and_params->values,
G_TYPE_FROM_INSTANCE(RVAL2GOBJ(arg->self)));
rbgobj_rvalue_to_gvalue(arg->self, arg->instance_and_params->values);
{
GValue* params = arg->instance_and_params->values + 1;
guint i;
for (i = 0; i < arg->query.n_params; i++) {
GType gtype = arg->query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
g_value_init(params + i, gtype);
rbgobj_rvalue_to_gvalue(rb_ary_entry(arg->args, i), params + i);
}
}
{
gboolean use_ret = (arg->query.return_type != G_TYPE_NONE);
GValue return_value = G_VALUE_INIT;
if (use_ret)
g_value_init(&return_value,
arg->query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
g_signal_chain_from_overridden(arg->instance_and_params->values,
(use_ret) ? &return_value : NULL);
if (use_ret) {
VALUE ret = GVAL2RVAL(&return_value);
g_value_unset(&return_value);
return ret;
} else {
return Qnil;
}
}
}
static VALUE
gobj_sig_chain_from_overridden(int argc, VALUE *argv, VALUE self)
{
struct emit_arg arg;
{
GSignalInvocationHint* hint;
hint = g_signal_get_invocation_hint(RVAL2GOBJ(self));
if (!hint)
rb_raise(rb_eRuntimeError, "can't get signal invocation hint");
g_signal_query(hint->signal_id, &arg.query);
}
if (arg.query.n_params != (guint)argc)
rb_raise(rb_eArgError, "wrong number of arguments(%d for %d)",
argc, arg.query.n_params);
arg.self = self;
arg.args = rb_ary_new4(argc, argv);
arg.instance_and_params = g_value_array_new(1 + argc);
return rb_ensure(chain_from_overridden_body, (VALUE)&arg,
emit_ensure, (VALUE)&arg);
}
static VALUE
gobj_s_method_added(VALUE klass, VALUE id)
{
const RGObjClassInfo* cinfo = rbgobj_lookup_class(klass);
const char* name = rb_id2name(SYM2ID(id));
const int prefix_len = strlen(default_handler_method_prefix);
guint signal_id;
if (cinfo->klass != klass) return Qnil;
if (strncmp(default_handler_method_prefix, name, prefix_len)) return Qnil;
signal_id = g_signal_lookup(name + prefix_len, cinfo->gtype);
if (!signal_id) return Qnil;
{
GSignalQuery query;
g_signal_query(signal_id, &query);
if (query.itype == cinfo->gtype)
return Qnil;
}
{
VALUE f = rb_eval_string(
"lambda{|klass, id|\n"
" lambda{|instance,*args|\n"
" klass.instance_method(id).bind(instance).call(*args)\n"
" }\n"
"}\n");
VALUE proc = rb_funcall(f, rb_intern("call"), 2, klass, id);
GClosure* rclosure = g_rclosure_new(proc, Qnil,
rbgobj_get_signal_func(signal_id));
g_rclosure_attach((GClosure *)rclosure, klass);
g_signal_override_class_closure(signal_id, cinfo->gtype, rclosure);
}
{
VALUE mod = rb_define_module_under(klass, RubyGObjectHookModule);
rb_include_module(klass, mod);
rbg_define_method(mod, name, gobj_sig_chain_from_overridden, -1);
}
return Qnil;
}
/**********************************************************************/
VALUE
rbgobj_signal_wrap(guint sig_id)
{
VALUE result;
GSignalQuery* query;
result = Data_Make_Struct(RG_TARGET_NAMESPACE, GSignalQuery, NULL, free, query);
g_signal_query(sig_id, query);
return result;
}
static VALUE
rg_id(VALUE self)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
return UINT2NUM(query->signal_id);
}
static VALUE
rg_name(VALUE self)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
return rb_str_new2(query->signal_name);
}
static VALUE
rg_itype(VALUE self)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
return rbgobj_gtype_new(query->itype);
}
static VALUE
rg_owner(VALUE self)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
return GTYPE2CLASS(query->itype);
}
static VALUE
rg_return_type(VALUE self)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
return rbgobj_gtype_new(query->return_type);
}
static VALUE
rg_flags(VALUE self)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
return UINT2NUM(query->signal_flags);
}
static VALUE
rg_param_types(VALUE self)
{
GSignalQuery* query;
VALUE result;
guint i;
Data_Get_Struct(self, GSignalQuery, query);
result = rb_ary_new2(query->n_params);
for (i = 0; i < query->n_params; i++)
rb_ary_store(result, i, rbgobj_gtype_new(query->param_types[i]));
return result;
}
static VALUE
rg_inspect(VALUE self)
{
GSignalQuery* query;
gchar* s;
VALUE result, v;
Data_Get_Struct(self, GSignalQuery, query);
v = rb_inspect(GTYPE2CLASS(query->itype));
s = g_strdup_printf("#<%s: %s#%s>",
rb_class2name(CLASS_OF(self)),
StringValuePtr(v),
query->signal_name);
result = rb_str_new2(s);
g_free(s);
return result;
}
#define query_is_flag(flag) \
static VALUE \
query_is_##flag(VALUE self) \
{ \
GSignalQuery* query; \
Data_Get_Struct(self, GSignalQuery, query); \
return CBOOL2RVAL(query->signal_flags & flag); \
}
query_is_flag(G_SIGNAL_RUN_FIRST)
query_is_flag(G_SIGNAL_RUN_LAST)
query_is_flag(G_SIGNAL_RUN_CLEANUP)
query_is_flag(G_SIGNAL_NO_RECURSE)
query_is_flag(G_SIGNAL_DETAILED)
query_is_flag(G_SIGNAL_ACTION)
query_is_flag(G_SIGNAL_NO_HOOKS)
static gboolean
hook_func(GSignalInvocationHint* ihint,
guint n_param_values,
const GValue* param_values,
gpointer data)
{
GClosure* closure = data;
GValue ret_val =G_VALUE_INIT;
gboolean ret;
g_value_init(&ret_val, G_TYPE_BOOLEAN);
g_closure_invoke(closure, &ret_val, n_param_values, param_values, ihint);
ret = g_value_get_boolean(&ret_val);
g_value_unset(&ret_val);
return ret;
}
static gulong
g_signal_add_emission_hook_closure (guint signal_id,
GQuark detail,
GClosure* closure)
{
guint hook_id;
g_closure_ref(closure);
g_closure_sink(closure);
hook_id = g_signal_add_emission_hook(signal_id, detail,
&hook_func, closure,
(GDestroyNotify)&g_closure_unref);
return hook_id;
}
static VALUE
rg_add_emission_hook(int argc, VALUE* argv, VALUE self)
{
GSignalQuery* query;
VALUE proc;
guint hook_id;
GQuark detail = 0;
GClosure* closure;
Data_Get_Struct(self, GSignalQuery, query);
if (query->signal_flags & G_SIGNAL_DETAILED) {
VALUE detail_obj;
if (rb_scan_args(argc, argv, "01&", &detail_obj, &proc) == 1) {
if (SYMBOL_P(detail_obj))
detail = g_quark_from_string(rb_id2name(SYM2ID(detail_obj)));
else
detail = g_quark_from_string(StringValuePtr(detail_obj));
}
} else {
rb_scan_args(argc, argv, "00&", &proc);
}
closure = g_rclosure_new(proc, Qnil,
rbgobj_get_signal_func(query->signal_id));
g_rclosure_attach(closure, self);
hook_id = g_signal_add_emission_hook_closure(query->signal_id, detail, closure);
return ULONG2NUM(hook_id);
}
static VALUE
rg_remove_emission_hook(VALUE self, VALUE hook_id)
{
GSignalQuery* query;
Data_Get_Struct(self, GSignalQuery, query);
g_signal_remove_emission_hook(query->signal_id, NUM2ULONG(hook_id));
return Qnil;
}
/**********************************************************************/
void
rbgobj_define_action_methods(VALUE klass)
{
GType gtype = CLASS2GTYPE(klass);
GString* source;
guint n_ids;
guint* ids;
guint i;
if (gtype == G_TYPE_INTERFACE)
return;
ids = g_signal_list_ids(gtype, &n_ids);
if (n_ids == 0)
return;
source = g_string_new(NULL);
for (i = 0; i < n_ids; i++){
GSignalQuery query;
g_signal_query(ids[i], &query);
if (query.signal_flags & G_SIGNAL_ACTION) {
gchar* method_name = g_strdup(query.signal_name);
gchar* p;
GString* args;
guint j;
for (p = method_name; *p; p++)
if (*p == '-')
*p = '_';
args = g_string_new(NULL);
for (j = 0; j < query.n_params; j++)
g_string_append_printf(args, ",x%d", j);
g_string_append_printf(
source,
"def %s(%s)\n signal_emit('%s'%s)\nend\n",
method_name,
(query.n_params > 0) ? args->str + 1 : "", // Skip initial ','
query.signal_name,
args->str);
g_free(method_name);
g_string_free(args, TRUE);
}
}
if (source->len > 0)
rb_funcall(klass, rb_intern("module_eval"), 1, rb_str_new2(source->str));
g_string_free(source, TRUE);
}
/**********************************************************************/
void
Init_gobject_gsignal(void)
{
VALUE cSignalFlags, cSignalMatchType;
RG_TARGET_NAMESPACE = rb_define_class_under(mGLib, "Signal", rb_cData);
RG_DEF_METHOD(id, 0);
RG_DEF_METHOD(name, 0);
RG_DEF_METHOD(flags, 0);
RG_DEF_METHOD(itype, 0);
RG_DEF_METHOD(owner, 0);
RG_DEF_METHOD(return_type, 0);
RG_DEF_METHOD(param_types, 0);
RG_DEF_METHOD(inspect, 0);
RG_DEF_METHOD(add_emission_hook, -1);
RG_DEF_METHOD(remove_emission_hook, 1);
/* GSignalFlags */
cSignalFlags = G_DEF_CLASS(G_TYPE_SIGNAL_FLAGS, "SignalFlags", mGLib);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_SIGNAL_FLAGS, "G_SIGNAL_");
rb_define_const(cSignalFlags, "MASK", INT2NUM(G_SIGNAL_FLAGS_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "FLAGS_MASK", INT2NUM(G_SIGNAL_FLAGS_MASK));
rbg_define_method(RG_TARGET_NAMESPACE, "run_first?", query_is_G_SIGNAL_RUN_FIRST, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "run_last?", query_is_G_SIGNAL_RUN_LAST, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "run_cleanup?", query_is_G_SIGNAL_RUN_CLEANUP, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "no_recurse?", query_is_G_SIGNAL_NO_RECURSE, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "detailed?", query_is_G_SIGNAL_DETAILED, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "action?", query_is_G_SIGNAL_ACTION, 0);
rbg_define_method(RG_TARGET_NAMESPACE, "no_hooks?", query_is_G_SIGNAL_NO_HOOKS, 0);
/* GConnectFlags */
G_DEF_CLASS(G_TYPE_CONNECT_FLAGS, "ConnectFlags", mGLib);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_CONNECT_FLAGS, "G_");
/* GSignalMatchType */
cSignalMatchType = G_DEF_CLASS(G_TYPE_SIGNAL_MATCH_TYPE,
"SignalMatchType", mGLib);
G_DEF_CONSTANTS(RG_TARGET_NAMESPACE, G_TYPE_SIGNAL_MATCH_TYPE, "G_SIGNAL_");
rb_define_const(cSignalMatchType, "MASK", INT2NUM(G_SIGNAL_MATCH_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "MATCH_MASK", INT2NUM(G_SIGNAL_MATCH_MASK));
rb_define_const(RG_TARGET_NAMESPACE, "TYPE_STATIC_SCOPE", INT2FIX(G_SIGNAL_TYPE_STATIC_SCOPE));
eNoSignalError = rb_define_class_under(mGLib, "NoSignalError", rb_eNameError);
signal_func_table = rb_hash_new();
rb_global_variable(&signal_func_table);
rbg_define_method(mMetaInterface, "signal_new", gobj_s_signal_new, -1);
rbg_define_method(mMetaInterface, "signals", gobj_s_signals, -1);
rbg_define_method(mMetaInterface, "signal", gobj_s_signal, 1);
rbg_define_method(cInstantiatable, "signal_has_handler_pending?",
gobj_sig_has_handler_pending, -1);
rbg_define_method(cInstantiatable, "signal_connect", gobj_sig_connect, -1);
rbg_define_method(cInstantiatable, "signal_connect_after",
gobj_sig_connect_after, -1);
#if 0
rbg_define_method(cInstantiatable, "signal_invocation_hint",
gobj_sig_get_invocation_hint, 0);
#endif
rbg_define_method(cInstantiatable, "signal_emit",
gobj_sig_emit, -1);
rbg_define_method(cInstantiatable, "signal_emit_stop",
gobj_sig_emit_stop, 1);
rbg_define_method(cInstantiatable, "signal_handler_block",
gobj_sig_handler_block, 1);
rbg_define_method(cInstantiatable, "signal_handler_unblock",
gobj_sig_handler_unblock, 1);
rbg_define_method(cInstantiatable, "signal_handler_disconnect",
gobj_sig_handler_disconnect, 1);
rbg_define_method(cInstantiatable, "signal_handler_is_connected?",
gobj_sig_handler_is_connected, 1);
rbg_define_singleton_method(cInstantiatable, "method_added",
gobj_s_method_added, 1);
}

View File

@ -0,0 +1,48 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2005 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#if GLIB_CHECK_VERSION(2,6,0)
static VALUE
strv_to_ruby(const GValue *from)
{
return STRV2RVAL((const gchar **)g_value_get_boxed(from));
}
static void
strv_from_ruby(VALUE from, GValue *to)
{
const gchar **strings = RVAL2STRV(from);
g_value_set_boxed(to, strings);
g_free(strings);
}
void
Init_gobject_gstrv(void)
{
/* GStrv is treated as Array */
rbgobj_register_g2r_func(G_TYPE_STRV, strv_to_ruby);
rbgobj_register_r2g_func(G_TYPE_STRV, strv_from_ruby);
}
#endif

View File

@ -0,0 +1,841 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2002-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE rbgobj_cType
/**********************************************************************/
/* Type Mapping */
static VALUE rb_cMutex;
static VALUE lookup_class_mutex;
static ID id_new;
static ID id_superclass;
static ID id_lock;
static ID id_unlock;
static GHashTable *gtype_to_cinfo;
static VALUE klass_to_cinfo;
static GHashTable* dynamic_gtype_list;
typedef struct {
const gchar* name;
VALUE module;
RGMarkFunc mark;
RGFreeFunc free;
int flags; /* RGObjClassFlag */
} RGObjClassInfoDynamic;
typedef struct {
VALUE parent;
GType gtype;
gboolean create_class;
} RGObjClassByGtypeData;
static void
cinfo_mark(RGObjClassInfo* cinfo)
{
rb_gc_mark(cinfo->klass);
}
const RGObjClassInfo *
rbgobj_lookup_class(VALUE klass)
{
VALUE data = rb_hash_aref(klass_to_cinfo, klass);
if (!NIL_P(data)){
RGObjClassInfo* cinfo;
Data_Get_Struct(data, RGObjClassInfo, cinfo);
return cinfo;
}
if (TYPE(klass) == T_CLASS) {
VALUE super;
if (FL_TEST(klass, FL_SINGLETON)) {
super = rb_class_real(klass);
} else {
super = rb_funcall(klass, id_superclass, 0);
}
return rbgobj_lookup_class(super);
}
rb_raise(rb_eRuntimeError, "can't get gobject class information");
}
static const RGObjClassInfo *rbgobj_lookup_class_by_gtype_without_lock(GType gtype,
VALUE parent,
gboolean create_class);
static VALUE
get_superclass(GType gtype)
{
VALUE super_class;
if (rbgobj_convert_get_superclass(gtype, &super_class))
return super_class;
switch (gtype) {
case G_TYPE_PARAM:
case G_TYPE_OBJECT:
return cInstantiatable;
case G_TYPE_BOXED:
return rb_cObject;
case G_TYPE_POINTER:
return rb_cData;
case G_TYPE_ENUM:
case G_TYPE_FLAGS:
return rb_cObject;
default:
{
GType parent_type;
parent_type = g_type_parent(gtype);
if (parent_type == G_TYPE_INVALID) {
return cInstantiatable;
} else {
const RGObjClassInfo *cinfo_super;
cinfo_super =
rbgobj_lookup_class_by_gtype_without_lock(parent_type,
Qnil,
TRUE);
return cinfo_super->klass;
}
}
}
}
static const RGObjClassInfo *
rbgobj_lookup_class_by_gtype_without_lock(GType gtype, VALUE parent,
gboolean create_class)
{
GType fundamental_type;
RGObjClassInfo* cinfo;
RGObjClassInfoDynamic* cinfod;
void* gclass = NULL;
VALUE c;
if (gtype == G_TYPE_INVALID)
return NULL;
cinfo = g_hash_table_lookup(gtype_to_cinfo, GUINT_TO_POINTER(gtype));
if (cinfo)
return cinfo;
if (!create_class)
return NULL;
c = Data_Make_Struct(rb_cData, RGObjClassInfo, cinfo_mark, NULL, cinfo);
cinfo->gtype = gtype;
cinfo->mark = NULL;
cinfo->free = NULL;
cinfo->flags = 0;
fundamental_type = G_TYPE_FUNDAMENTAL(gtype);
switch (fundamental_type){
case G_TYPE_POINTER:
case G_TYPE_BOXED:
case G_TYPE_PARAM:
case G_TYPE_OBJECT:
case G_TYPE_ENUM:
case G_TYPE_FLAGS:
if (NIL_P(parent)) parent = get_superclass(gtype);
cinfo->klass = rb_funcall(rb_cClass, id_new, 1, parent);
break;
case G_TYPE_INTERFACE:
cinfo->klass = rb_module_new();
break;
default:
if (NIL_P(parent)) parent = get_superclass(gtype);
if (NIL_P(parent)) {
fprintf(stderr,
"%s: %s's fundamental type %s isn't supported\n",
"rbgobj_lookup_class_by_gtype",
g_type_name(gtype),
g_type_name(fundamental_type));
return NULL;
}
cinfo->klass = rb_funcall(rb_cClass, id_new, 1, parent);
}
cinfod = (RGObjClassInfoDynamic *)g_hash_table_lookup(dynamic_gtype_list,
g_type_name(gtype));
if (cinfod){
cinfo->mark = cinfod->mark;
cinfo->free = cinfod->free;
rb_define_const(cinfod->module, cinfod->name, cinfo->klass);
}
rb_hash_aset(klass_to_cinfo, cinfo->klass, c);
g_hash_table_insert(gtype_to_cinfo, GUINT_TO_POINTER(gtype), cinfo);
if (G_TYPE_IS_CLASSED(gtype))
gclass = g_type_class_ref(gtype);
if (G_TYPE_IS_INSTANTIATABLE(gtype) || G_TYPE_IS_INTERFACE(gtype))
rbgobj_define_action_methods(cinfo->klass);
if (G_TYPE_IS_INSTANTIATABLE(gtype)){
GType* interfaces = NULL;
guint n_interfaces = 0;
guint i;
interfaces = g_type_interfaces(gtype, &n_interfaces);
for (i = 0; i < n_interfaces; i++){
const RGObjClassInfo *iface_cinfo;
iface_cinfo =
rbgobj_lookup_class_by_gtype_without_lock(interfaces[i],
Qnil,
TRUE);
rb_include_module(cinfo->klass, iface_cinfo->klass);
}
g_free(interfaces);
}
if (!rbgobj_convert_type_init_hook(gtype, cinfo->klass)) {
switch (fundamental_type) {
case G_TYPE_OBJECT:
rbgobj_init_object_class(cinfo->klass);
break;
case G_TYPE_ENUM:
rbgobj_init_enum_class(cinfo->klass);
break;
case G_TYPE_FLAGS:
rbgobj_init_flags_class(cinfo->klass);
break;
case G_TYPE_INTERFACE:
rbgobj_init_interface(cinfo->klass);
break;
default:
rbgobj_convert_type_init_hook(fundamental_type, cinfo->klass);
break;
}
}
if (gclass)
g_type_class_unref(gclass);
return cinfo;
}
static VALUE
rbgobj_lookup_class_by_gtype_body(VALUE data)
{
RGObjClassByGtypeData *cdata = (RGObjClassByGtypeData *)data;
const RGObjClassInfo *cinfo;
cinfo = rbgobj_lookup_class_by_gtype_without_lock(cdata->gtype,
cdata->parent,
cdata->create_class);
return (VALUE)cinfo;
}
static VALUE
rbgobj_lookup_class_by_gtype_ensure(G_GNUC_UNUSED VALUE data)
{
rb_funcall(lookup_class_mutex, id_unlock, 0);
return Qundef;
}
const RGObjClassInfo *
rbgobj_lookup_class_by_gtype(GType gtype, VALUE parent)
{
return rbgobj_lookup_class_by_gtype_full(gtype, parent, TRUE);
}
const RGObjClassInfo *
rbgobj_lookup_class_by_gtype_full(GType gtype, VALUE parent,
gboolean create_class)
{
RGObjClassByGtypeData data;
data.gtype = gtype;
data.parent = parent;
data.create_class = create_class;
if (create_class) {
rb_funcall(lookup_class_mutex, id_lock, 0);
return (RGObjClassInfo *)rb_ensure(rbgobj_lookup_class_by_gtype_body,
(VALUE)&data,
rbgobj_lookup_class_by_gtype_ensure,
(VALUE)&data);
} else {
return rbgobj_lookup_class_by_gtype_without_lock(gtype, parent,
create_class);
}
}
VALUE
rbgobj_gtype_to_ruby_class(GType gtype)
{
const RGObjClassInfo *cinfo;
cinfo = GTYPE2CINFO(gtype);
return cinfo ? cinfo->klass : Qnil;
}
VALUE
rbgobj_define_class(GType gtype, const gchar *name, VALUE module,
RGMarkFunc mark, RGFreeFunc free, VALUE parent)
{
RGObjClassInfo* cinfo;
if (gtype == 0)
rb_bug("rbgobj_define_class: Invalid gtype [%s]\n", name);
cinfo = (RGObjClassInfo*)rbgobj_lookup_class_by_gtype(gtype, parent);
cinfo->mark = mark;
cinfo->free = free;
rb_define_const(module, name, cinfo->klass);
return cinfo->klass;
}
void
rbgobj_register_mark_func(GType gtype, RGMarkFunc mark)
{
RGObjClassInfo *cinfo;
cinfo =
(RGObjClassInfo *)rbgobj_lookup_class_by_gtype_full(gtype, Qnil, FALSE);
if (!cinfo) {
rb_raise(rb_eArgError,
"rbgobj_register_free_func(): no class is defined: <%s>",
g_type_name(gtype));
}
cinfo->mark = mark;
}
void
rbgobj_register_free_func(GType gtype, RGFreeFunc free)
{
RGObjClassInfo *cinfo;
cinfo =
(RGObjClassInfo *)rbgobj_lookup_class_by_gtype_full(gtype, Qnil, FALSE);
if (!cinfo) {
rb_raise(rb_eArgError,
"rbgobj_register_free_func(): no class is defined: <%s>",
g_type_name(gtype));
}
cinfo->free = free;
}
VALUE
rbgobj_define_class_dynamic(const gchar *gtype_name, const gchar *name,
VALUE module, RGMarkFunc mark, RGFreeFunc free)
{
RGObjClassInfoDynamic* cinfo;
cinfo = (RGObjClassInfoDynamic*)g_new(RGObjClassInfoDynamic, 1);
cinfo->name = name;
cinfo->module = module;
cinfo->mark = mark;
cinfo->free = free;
g_hash_table_insert(dynamic_gtype_list, (void*)gtype_name, (void*)cinfo);
return Qnil;
}
void
rbgobj_register_class(VALUE klass,
GType gtype,
gboolean klass2gtype,
gboolean gtype2klass)
{
RGObjClassInfo* cinfo = NULL;
VALUE c = Qnil;
if (klass2gtype)
c = Data_Make_Struct(rb_cData, RGObjClassInfo, cinfo_mark, NULL, cinfo);
if (gtype2klass && !cinfo)
cinfo = g_new(RGObjClassInfo, 1);
if (cinfo) {
cinfo->klass = klass;
cinfo->gtype = gtype;
cinfo->mark = NULL;
cinfo->free = NULL;
cinfo->flags = 0;
}
if (klass2gtype)
rb_hash_aset(klass_to_cinfo, cinfo->klass, c);
if (gtype2klass)
g_hash_table_insert(gtype_to_cinfo, GUINT_TO_POINTER(gtype), cinfo);
}
#define _register_fundamental_klass_to_gtype(klass, gtype) \
rbgobj_register_class(klass, gtype, TRUE, FALSE)
#define _register_fundamental_gtype_to_klass(gtype,klass) \
rbgobj_register_class(klass, gtype, FALSE, TRUE)
static void
init_typemap(void)
{
id_new = rb_intern("new");
id_superclass = rb_intern("superclass");
gtype_to_cinfo = g_hash_table_new(g_direct_hash, g_direct_equal);
rb_global_variable(&klass_to_cinfo);
klass_to_cinfo = rb_hash_new();
_register_fundamental_klass_to_gtype(rb_cFixnum, G_TYPE_LONG);
_register_fundamental_klass_to_gtype(rb_cFloat, G_TYPE_DOUBLE);
_register_fundamental_klass_to_gtype(rb_cInteger, G_TYPE_LONG);
_register_fundamental_klass_to_gtype(rb_cString, G_TYPE_STRING);
_register_fundamental_klass_to_gtype(rb_cSymbol, G_TYPE_STRING);
_register_fundamental_klass_to_gtype(Qnil, G_TYPE_NONE);
_register_fundamental_klass_to_gtype(rb_cNilClass, G_TYPE_NONE);
_register_fundamental_klass_to_gtype(rb_cTrueClass, G_TYPE_BOOLEAN);
_register_fundamental_klass_to_gtype(rb_cFalseClass, G_TYPE_BOOLEAN);
_register_fundamental_klass_to_gtype(Qtrue, G_TYPE_BOOLEAN);
_register_fundamental_klass_to_gtype(Qfalse, G_TYPE_BOOLEAN);
_register_fundamental_klass_to_gtype(rb_cObject, RBGOBJ_TYPE_RUBY_VALUE);
_register_fundamental_gtype_to_klass(G_TYPE_UINT, rb_cInteger);
_register_fundamental_gtype_to_klass(G_TYPE_FLOAT, rb_cFloat);
_register_fundamental_gtype_to_klass(G_TYPE_DOUBLE, rb_cFloat);
_register_fundamental_gtype_to_klass(G_TYPE_INT64, rb_cInteger);
_register_fundamental_gtype_to_klass(G_TYPE_UINT64, rb_cInteger);
_register_fundamental_gtype_to_klass(G_TYPE_INT, rb_cInteger);
_register_fundamental_gtype_to_klass(G_TYPE_LONG, rb_cInteger);
_register_fundamental_gtype_to_klass(G_TYPE_CHAR, rb_cFixnum);
_register_fundamental_gtype_to_klass(G_TYPE_UCHAR, rb_cFixnum);
_register_fundamental_gtype_to_klass(G_TYPE_STRING, rb_cString);
_register_fundamental_gtype_to_klass(G_TYPE_ULONG, rb_cInteger);
_register_fundamental_gtype_to_klass(G_TYPE_NONE, rb_cNilClass);
_register_fundamental_gtype_to_klass(G_TYPE_BOOLEAN, rb_cTrueClass);
}
/**********************************************************************/
/* GLib::Type */
VALUE RG_TARGET_NAMESPACE;
static ID id_gtype;
VALUE
rbgobj_gtype_new(GType gtype)
{
VALUE result = rb_obj_alloc(RG_TARGET_NAMESPACE);
VALUE arg = ULONG2NUM(gtype);
rb_obj_call_init(result, 1, &arg);
return result;
}
GType
rbgobj_gtype_get(VALUE self)
{
if (RVAL2CBOOL(rb_obj_is_kind_of(self, RG_TARGET_NAMESPACE))) {
return NUM2ULONG(rb_ivar_get(self, id_gtype));
} else {
return CLASS2GTYPE(self);
}
rb_raise(rb_eTypeError, "Not a GLib::Type");
}
static VALUE
rg_initialize(VALUE self, VALUE type)
{
GType gtype;
if (RVAL2CBOOL(rb_obj_is_kind_of(type, rb_cInteger))) {
gtype = NUM2ULONG(type);
if (!g_type_name(gtype))
gtype = G_TYPE_INVALID;
} else {
gtype = g_type_from_name(StringValuePtr(type));
}
if (G_TYPE_INVALID == gtype)
rb_raise(rb_eArgError, "invalid type");
rb_ivar_set(self, id_gtype, ULONG2NUM(gtype));
return Qnil;
}
static VALUE
rg_inspect(VALUE self)
{
GType gtype = rbgobj_gtype_get(self);
gchar* str;
VALUE result;
str = g_strdup_printf("GLib::Type[\"%s\"]", g_type_name(gtype));
result = rb_str_new2(str);
g_free(str);
return result;
}
static VALUE
rg_operator_type_compare(VALUE self, VALUE other)
{
if (!RVAL2CBOOL(rb_obj_is_kind_of(other, RG_TARGET_NAMESPACE)))
return Qnil;
else {
GType a = rbgobj_gtype_get(self);
GType b = rbgobj_gtype_get(other);
if (a==b)
return INT2FIX(0);
else if (g_type_is_a(a,b))
return INT2FIX(-1);
else if (g_type_is_a(b,a))
return INT2FIX(1);
else
return Qnil;
}
}
static VALUE
rg_operator_type_eq(VALUE self, VALUE other)
{
if (!RVAL2CBOOL(rb_obj_is_kind_of(other, RG_TARGET_NAMESPACE)))
return Qnil;
else {
GType a = rbgobj_gtype_get(self);
GType b = rbgobj_gtype_get(other);
return CBOOL2RVAL(a == b);
}
}
static VALUE
rg_operator_type_lt_eq(VALUE self, VALUE other)
{
if (!RVAL2CBOOL(rb_obj_is_kind_of(other, RG_TARGET_NAMESPACE)))
return Qnil;
else {
GType a = rbgobj_gtype_get(self);
GType b = rbgobj_gtype_get(other);
return CBOOL2RVAL(g_type_is_a(a, b));
}
}
static VALUE
rg_operator_type_gt_eq(VALUE self, VALUE other)
{
if (!RVAL2CBOOL(rb_obj_is_kind_of(other, RG_TARGET_NAMESPACE)))
return Qnil;
else {
GType a = rbgobj_gtype_get(self);
GType b = rbgobj_gtype_get(other);
return CBOOL2RVAL(g_type_is_a(b, a));
}
}
static VALUE
rg_operator_type_lt(VALUE self, VALUE other)
{
if (!RVAL2CBOOL(rb_obj_is_kind_of(other, RG_TARGET_NAMESPACE)))
return Qnil;
else {
GType a = rbgobj_gtype_get(self);
GType b = rbgobj_gtype_get(other);
return CBOOL2RVAL(g_type_is_a(a, b) && a != b);
}
}
static VALUE
rg_operator_type_gt(VALUE self, VALUE other)
{
if (!RVAL2CBOOL(rb_obj_is_kind_of(other, RG_TARGET_NAMESPACE)))
return Qnil;
else {
GType a = rbgobj_gtype_get(self);
GType b = rbgobj_gtype_get(other);
return CBOOL2RVAL(g_type_is_a(b, a) && a != b);
}
}
static VALUE
rg_hash(VALUE self)
{
return rb_ivar_get(self, id_gtype);
}
static VALUE
rg_to_class(VALUE self)
{
return GTYPE2CLASS(rbgobj_gtype_get(self));
}
static VALUE
rg_fundamental(VALUE self)
{
return rbgobj_gtype_new(G_TYPE_FUNDAMENTAL(rbgobj_gtype_get(self)));
}
static VALUE
rg_fundamental_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_FUNDAMENTAL(rbgobj_gtype_get(self)));
}
static VALUE
rg_derived_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_DERIVED(rbgobj_gtype_get(self)));
}
static VALUE
rg_interface_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_INTERFACE(rbgobj_gtype_get(self)));
}
static VALUE
rg_classed_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_CLASSED(rbgobj_gtype_get(self)));
}
static VALUE
rg_instantiatable_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_INSTANTIATABLE(rbgobj_gtype_get(self)));
}
static VALUE
rg_derivable_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_DERIVABLE(rbgobj_gtype_get(self)));
}
static VALUE
rg_deep_derivable_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_DEEP_DERIVABLE(rbgobj_gtype_get(self)));
}
static VALUE
rg_abstract_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_ABSTRACT(rbgobj_gtype_get(self)));
}
static VALUE
rg_value_abstract_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_VALUE_ABSTRACT(rbgobj_gtype_get(self)));
}
static VALUE
rg_value_type_p(VALUE self)
{
return CBOOL2RVAL(G_TYPE_IS_VALUE_TYPE(rbgobj_gtype_get(self)));
}
static VALUE
rg_has_value_table(VALUE self)
{
return CBOOL2RVAL(G_TYPE_HAS_VALUE_TABLE(rbgobj_gtype_get(self)));
}
static VALUE
rg_name(VALUE self)
{
return rb_str_new2(g_type_name(rbgobj_gtype_get(self)));
}
static VALUE
rg_parent(VALUE self)
{
GType parent = g_type_parent(rbgobj_gtype_get(self));
return parent ? rbgobj_gtype_new(parent) : Qnil;
}
static VALUE
rg_depth(VALUE self)
{
return UINT2NUM(g_type_depth(rbgobj_gtype_get(self)));
}
static VALUE
rg_next_base(VALUE leaf_type, VALUE root_type)
{
GType ret = g_type_next_base(rbgobj_gtype_get(leaf_type),
rbgobj_gtype_get(root_type));
return ret ? rbgobj_gtype_new(ret) : Qnil;
}
static VALUE
rg_type_is_a_p(VALUE self, VALUE is_a_type)
{
return CBOOL2RVAL(g_type_is_a(rbgobj_gtype_get(self), rbgobj_gtype_get(is_a_type)));
}
#if 0
gpointer g_type_class_ref (GType type);
gpointer g_type_class_peek (GType type);
void g_type_class_unref (gpointer g_class);
gpointer g_type_class_peek_parent (gpointer g_class);
gpointer g_type_interface_peek (gpointer instance_class,
GType iface_type);
gpointer g_type_interface_peek_parent (gpointer g_iface);
#endif
static VALUE
rg_children(VALUE self)
{
guint n_children;
GType* types;
VALUE result;
guint i;
types = g_type_children(rbgobj_gtype_get(self), &n_children);
result = rb_ary_new2(n_children);
for (i = 0; i < n_children; i++)
rb_ary_store(result, i, rbgobj_gtype_new(types[i]));
g_free(types);
return result;
}
static VALUE
rg_interfaces(VALUE self)
{
guint n_interfaces;
GType* types;
VALUE result;
guint i;
types = g_type_interfaces(rbgobj_gtype_get(self), &n_interfaces);
result = rb_ary_new2(n_interfaces);
for (i = 0; i < n_interfaces; i++)
rb_ary_store(result, i, rbgobj_gtype_new(types[i]));
g_free(types);
return result;
}
static VALUE
rg_class_size(VALUE self)
{
GTypeQuery query;
g_type_query(rbgobj_gtype_get(self), &query);
return UINT2NUM(query.class_size);
}
static VALUE
rg_instance_size(VALUE self)
{
GTypeQuery query;
g_type_query(rbgobj_gtype_get(self), &query);
return UINT2NUM(query.instance_size);
}
static inline void
_def_fundamental_type(VALUE ary, GType gtype, const char* name)
{
VALUE c = rbgobj_gtype_new(gtype);
rb_define_const(RG_TARGET_NAMESPACE, name, c);
rb_ary_push(ary, c);
}
/**********************************************************************/
void
Init_gobject_gtype(void)
{
#if !GLIB_CHECK_VERSION(2, 35, 1)
g_type_init();
#endif
init_typemap();
/* type */
rb_cMutex = rb_const_get(rb_cObject, rb_intern("Mutex"));
id_lock = rb_intern("lock");
id_unlock = rb_intern("unlock");
lookup_class_mutex = rb_funcall(rb_cMutex, id_new, 0);
rb_iv_set(mGLib, "lookup_class_mutex", lookup_class_mutex);
dynamic_gtype_list = g_hash_table_new(g_str_hash, g_str_equal);
id_gtype = rb_intern("__gobject_gtype__");
RG_TARGET_NAMESPACE = rb_define_class_under(mGLib, "Type", rb_cObject);
rb_define_alias(CLASS_OF(RG_TARGET_NAMESPACE), "[]", "new");
RG_DEF_METHOD(initialize, 1);
RG_DEF_METHOD(inspect, 0);
RG_DEF_METHOD_OPERATOR("<=>", type_compare, 1);
RG_DEF_METHOD_OPERATOR("==", type_eq, 1);
RG_DEF_METHOD_OPERATOR("<=", type_lt_eq, 1);
RG_DEF_METHOD_OPERATOR(">=", type_gt_eq, 1);
RG_DEF_METHOD_OPERATOR("<", type_lt, 1);
RG_DEF_METHOD_OPERATOR(">", type_gt, 1);
RG_DEF_ALIAS("eql?", "==");
RG_DEF_METHOD(hash, 0);
RG_DEF_ALIAS("to_i", "hash");
RG_DEF_ALIAS("to_int", "hash");
RG_DEF_METHOD(to_class, 0);
RG_DEF_METHOD(fundamental, 0);
RG_DEF_METHOD_P(fundamental, 0);
RG_DEF_METHOD_P(derived, 0);
RG_DEF_METHOD_P(interface, 0);
RG_DEF_METHOD_P(classed, 0);
RG_DEF_METHOD_P(instantiatable, 0);
RG_DEF_METHOD_P(derivable, 0);
RG_DEF_METHOD_P(deep_derivable, 0);
RG_DEF_METHOD_P(abstract, 0);
RG_DEF_METHOD_P(value_abstract, 0);
RG_DEF_METHOD_P(value_type, 0);
RG_DEF_METHOD(has_value_table, 0);
RG_DEF_METHOD(name, 0);
RG_DEF_ALIAS("to_s", "name");
RG_DEF_METHOD(parent, 0);
RG_DEF_METHOD(depth, 0);
RG_DEF_METHOD(next_base, 1);
RG_DEF_METHOD_P(type_is_a, 1);
RG_DEF_METHOD(children, 0);
RG_DEF_METHOD(interfaces, 0);
RG_DEF_METHOD(class_size, 0);
RG_DEF_METHOD(instance_size, 0);
{
VALUE ary = rb_ary_new();
rb_define_const(RG_TARGET_NAMESPACE, "FUNDAMENTAL_MAX", INT2FIX(G_TYPE_FUNDAMENTAL_MAX));
_def_fundamental_type(ary, G_TYPE_NONE, "NONE");
_def_fundamental_type(ary, G_TYPE_INTERFACE, "INTERFACE");
_def_fundamental_type(ary, G_TYPE_CHAR, "CHAR");
_def_fundamental_type(ary, G_TYPE_UCHAR, "UCHAR");
_def_fundamental_type(ary, G_TYPE_BOOLEAN, "BOOLEAN");
_def_fundamental_type(ary, G_TYPE_INT, "INT");
_def_fundamental_type(ary, G_TYPE_UINT, "UINT");
_def_fundamental_type(ary, G_TYPE_LONG, "LONG");
_def_fundamental_type(ary, G_TYPE_ULONG, "ULONG");
_def_fundamental_type(ary, G_TYPE_INT64, "INT64");
_def_fundamental_type(ary, G_TYPE_UINT64, "UINT64");
_def_fundamental_type(ary, G_TYPE_ENUM, "ENUM");
_def_fundamental_type(ary, G_TYPE_FLAGS, "FLAGS");
_def_fundamental_type(ary, G_TYPE_FLOAT, "FLOAT");
_def_fundamental_type(ary, G_TYPE_DOUBLE, "DOUBLE");
_def_fundamental_type(ary, G_TYPE_STRING, "STRING");
_def_fundamental_type(ary, G_TYPE_POINTER, "POINTER");
_def_fundamental_type(ary, G_TYPE_BOXED, "BOXED");
_def_fundamental_type(ary, G_TYPE_PARAM, "PARAM");
_def_fundamental_type(ary, G_TYPE_OBJECT, "OBJECT");
rb_define_const(RG_TARGET_NAMESPACE, "FUNDAMENTAL_TYPES", ary); /* FIXME: better name */
}
}

View File

@ -0,0 +1,128 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cInstantiatable
VALUE RG_TARGET_NAMESPACE;
typedef void (*ClassInfoCallbackFunc) (gpointer instance,
const RGObjClassInfo *class_info,
gpointer user_data);
static G_GNUC_NORETURN VALUE
instantiatable_s_allocate(G_GNUC_UNUSED VALUE klass)
{
rb_raise(rb_eTypeError, "abstract class");
}
static VALUE
rg_gtype(VALUE self)
{
return rbgobj_gtype_new(G_TYPE_FROM_INSTANCE(rbgobj_instance_from_ruby_object(self)));
}
static G_GNUC_NORETURN VALUE
rg_clone(VALUE self)
{
rb_raise(rb_eTypeError, "can't clone %s", rb_class2name(CLASS_OF(self)));
}
/**********************************************************************/
static void
each_cinfo(gpointer instance, ClassInfoCallbackFunc func, gpointer user_data)
{
const GType gtype = G_TYPE_FROM_INSTANCE(instance);
GType* interfaces;
guint n_interfaces = 0;
interfaces = g_type_interfaces(gtype, &n_interfaces);
{
guint i;
for (i = 0; i < n_interfaces; i++) {
const RGObjClassInfo *info;
info = GTYPE2CINFO_NO_CREATE(interfaces[i]);
if (info)
func(instance, info, user_data);
}
}
g_free(interfaces);
{
GType type;
for (type = gtype; type != G_TYPE_INVALID; type = g_type_parent(type)) {
const RGObjClassInfo *info;
info = GTYPE2CINFO_NO_CREATE(type);
if (info)
func(instance, info, user_data);
}
}
}
static void
call_cinfo_free(gpointer instance, const RGObjClassInfo *cinfo, G_GNUC_UNUSED gpointer user_data)
{
if (cinfo->free) cinfo->free(instance);
}
static void
call_cinfo_mark(gpointer instance, const RGObjClassInfo *cinfo, G_GNUC_UNUSED gpointer user_data)
{
if (cinfo->mark) cinfo->mark(instance);
}
void
rbgobj_instance_call_cinfo_mark(gpointer instance)
{
each_cinfo(instance, call_cinfo_mark, NULL);
}
void
rbgobj_instance_call_cinfo_free(gpointer instance)
{
each_cinfo(instance, call_cinfo_free, NULL);
}
void
rbgobj_gc_mark_instance(gpointer instance)
{
VALUE obj = rbgobj_ruby_object_from_instance2(instance, FALSE);
rb_gc_mark(obj);
}
/**********************************************************************/
void
Init_gobject_typeinstance(void)
{
/* should be renamed to GLib::Instance? */
RG_TARGET_NAMESPACE = rb_define_class_under(mGLib, "Instantiatable", rb_cObject);
rb_extend_object(RG_TARGET_NAMESPACE, mMetaInterface);
rb_define_alloc_func(RG_TARGET_NAMESPACE, (VALUE(*)_((VALUE)))instantiatable_s_allocate);
RG_DEF_METHOD(gtype, 0);
RG_DEF_METHOD(clone, 0);
}

View File

@ -0,0 +1,155 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE mMetaInterface
VALUE rbgobj_mInterface;
VALUE RG_TARGET_NAMESPACE;
static VALUE
rg_append_features(G_GNUC_UNUSED VALUE self, VALUE klass)
{
if (!rb_obj_is_kind_of(klass, cInstantiatable))
rb_raise(rb_eTypeError, "Not a subclass of GLib::Instantiatable");
return rb_call_super(1, &klass);
}
#if GLIB_CHECK_VERSION(2,4,0)
static VALUE
rg_install_property(VALUE self, VALUE pspec_obj)
{
const RGObjClassInfo* cinfo = rbgobj_lookup_class(self);
gpointer ginterface;
GParamSpec* pspec;
if (cinfo->klass != self)
rb_raise(rb_eTypeError, "%s isn't registered class", rb_class2name(self));
pspec = G_PARAM_SPEC(RVAL2GOBJ(pspec_obj));
ginterface = g_type_default_interface_ref(cinfo->gtype);
g_object_interface_install_property(ginterface, pspec);
g_type_default_interface_unref(ginterface);
/* FIXME: define accessor methods */
return Qnil;
}
static VALUE
rg_property(VALUE self, VALUE property_name)
{
gpointer ginterface;
const char* name;
GParamSpec* prop;
VALUE result;
GType gtype = CLASS2GTYPE(self);
if (SYMBOL_P(property_name))
name = rb_id2name(SYM2ID(property_name));
else
name = StringValuePtr(property_name);
if (!G_TYPE_IS_INTERFACE(gtype))
rb_raise(rb_eTypeError, "%s isn't interface module", rb_class2name(self));
/* XXX: g_type_default_interface_ref(G_TYPE_INTERFACE) causes SEGV. */
if (gtype == G_TYPE_INTERFACE) {
rb_raise(rb_const_get(mGLib, rb_intern("NoPropertyError")),
"No such property: %s", name);
}
ginterface = g_type_default_interface_ref(gtype);
prop = g_object_interface_find_property(ginterface, name);
if (!prop){
g_type_default_interface_unref(ginterface);
rb_raise(rb_const_get(mGLib, rb_intern("NoPropertyError")),
"No such property: %s", name);
}
result = GOBJ2RVAL(prop);
g_type_default_interface_unref(ginterface);
return result;
}
static VALUE
rg_properties(int argc, VALUE* argv, VALUE self)
{
guint n_properties;
GParamSpec** props;
VALUE inherited_too;
VALUE ary = rb_ary_new();
guint i;
gpointer ginterface;
GType gtype = CLASS2GTYPE(self);
if (rb_scan_args(argc, argv, "01", &inherited_too) == 0)
inherited_too = Qtrue;
if (!G_TYPE_IS_INTERFACE(gtype))
rb_raise(rb_eTypeError, "%s isn't interface module", rb_class2name(self));
/* XXX: g_type_default_interface_ref(G_TYPE_INTERFACE) causes SEGV. */
if (gtype == G_TYPE_INTERFACE) return ary;
ginterface = g_type_default_interface_ref(gtype);
props = g_object_interface_list_properties(ginterface, &n_properties);
for (i = 0; i < n_properties; i++){
if (RVAL2CBOOL(inherited_too) || GTYPE2CLASS(props[i]->owner_type) == self)
rb_ary_push(ary, rb_str_new2(props[i]->name));
}
g_free(props);
g_type_default_interface_unref(ginterface);
return ary;
}
#endif
void
rbgobj_init_interface(VALUE interf)
{
static VALUE rb_mGLibInterface = Qnil;
rb_extend_object(interf, RG_TARGET_NAMESPACE);
if (CLASS2GTYPE(interf) == G_TYPE_INTERFACE) {
rb_mGLibInterface = interf;
} else {
rb_extend_object(interf, rb_mGLibInterface);
rb_include_module(interf, rb_mGLibInterface);
rbgobj_define_property_accessors(interf);
}
}
void
Init_gobject_typeinterface(void)
{
RG_TARGET_NAMESPACE = rb_define_module_under(mGLib, "MetaInterface");
rbg_define_method(RG_TARGET_NAMESPACE, "gtype", generic_s_gtype, 0);
RG_DEF_METHOD(append_features, 1);
#if GLIB_CHECK_VERSION(2,4,0)
RG_DEF_METHOD(install_property, 1);
RG_DEF_METHOD(property, 1);
RG_DEF_METHOD(properties, -1);
#endif
rbgobj_mInterface = G_DEF_INTERFACE(G_TYPE_INTERFACE, "Interface", mGLib);
}

View File

@ -0,0 +1,72 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE cTypeModule
static VALUE
rg_use(VALUE self)
{
return CBOOL2RVAL(g_type_module_use(G_TYPE_MODULE(RVAL2GOBJ(self))));
}
static VALUE
rg_unuse(VALUE self)
{
g_type_module_unuse(G_TYPE_MODULE(RVAL2GOBJ(self)));
return self;
}
static VALUE
rg_name(VALUE self)
{
return rb_str_new2(G_TYPE_MODULE(RVAL2GOBJ(self))->name);
}
static VALUE
rg_operator_set_name(VALUE self, VALUE name)
{
g_type_module_set_name(G_TYPE_MODULE(RVAL2GOBJ(self)), StringValuePtr(name));
return name;
}
#if 0
GType g_type_module_register_type (GTypeModule *module,
GType parent_type,
const gchar *type_name,
const GTypeInfo *type_info,
GTypeFlags flags);
void g_type_module_add_interface (GTypeModule *module,
GType instance_type,
GType interface_type,
const GInterfaceInfo *interface_info);
#endif
void
Init_gobject_gtypemodule(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_TYPE_MODULE, "TypeModule", mGLib);
RG_DEF_METHOD(use, 0);
RG_DEF_METHOD(unuse, 0);
RG_DEF_METHOD(name, 0);
RG_DEF_METHOD_OPERATOR("name=", set_name, 1);
}

View File

@ -0,0 +1,57 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#define RG_TARGET_NAMESPACE mTypePlugin
static VALUE
rg_use(VALUE self)
{
g_type_plugin_use(G_TYPE_PLUGIN(RVAL2GOBJ(self)));
return self;
}
static VALUE
rg_unuse(VALUE self)
{
g_type_plugin_unuse(G_TYPE_PLUGIN(RVAL2GOBJ(self)));
return self;
}
#if 0
void g_type_plugin_complete_type_info (GTypePlugin *plugin,
GType g_type,
GTypeInfo *info,
GTypeValueTable *value_table);
void g_type_plugin_complete_interface_info (GTypePlugin *plugin,
GType interface_type,
GType instance_type,
GInterfaceInfo *info);
#endif
void
Init_gobject_gtypeplugin(void)
{
VALUE RG_TARGET_NAMESPACE = G_DEF_INTERFACE(G_TYPE_TYPE_PLUGIN, "TypePlugin", mGLib);
RG_DEF_METHOD(use, 0);
RG_DEF_METHOD(unuse, 0);
}

View File

@ -0,0 +1,383 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
/**********************************************************************/
#define RG_TARGET_NAMESPACE rbgobj_cValue
#define _SELF(self) RVAL2GVALUE(self)
static ID id_to_s;
static GQuark qRValueToGValueFunc;
static GQuark qGValueToRValueFunc;
void
rbgobj_register_r2g_func(GType gtype, RValueToGValueFunc func)
{
g_type_set_qdata(gtype, qRValueToGValueFunc, func);
}
void
rbgobj_register_g2r_func(GType gtype, GValueToRValueFunc func)
{
g_type_set_qdata(gtype, qGValueToRValueFunc, func);
}
/**********************************************************************/
VALUE
rbgobj_gvalue_to_rvalue(const GValue* value)
{
GType type, fundamental_type;
VALUE rvalue;
if (!value)
return Qnil;
type = G_VALUE_TYPE(value);
if (rbgobj_convert_gvalue2rvalue(type, value, &rvalue))
return rvalue;
fundamental_type = G_TYPE_FUNDAMENTAL(type);
switch (fundamental_type) {
case G_TYPE_NONE:
return Qnil;
case G_TYPE_CHAR:
return CHR2FIX(g_value_get_char(value));
case G_TYPE_UCHAR:
return INT2FIX(g_value_get_uchar(value));
case G_TYPE_BOOLEAN:
return CBOOL2RVAL(g_value_get_boolean(value));
case G_TYPE_INT:
return INT2NUM(g_value_get_int(value));
case G_TYPE_UINT:
return UINT2NUM(g_value_get_uint(value));
case G_TYPE_LONG:
return LONG2NUM(g_value_get_long(value));
case G_TYPE_ULONG:
return ULONG2NUM(g_value_get_ulong(value));
case G_TYPE_INT64:
return rbglib_int64_to_num(g_value_get_int64(value));
case G_TYPE_UINT64:
return rbglib_uint64_to_num(g_value_get_uint64(value));
case G_TYPE_FLOAT:
return rb_float_new(g_value_get_float(value));
case G_TYPE_DOUBLE:
return rb_float_new(g_value_get_double(value));
case G_TYPE_STRING:
return CSTR2RVAL(g_value_get_string(value));
case G_TYPE_ENUM:
return rbgobj_make_enum(g_value_get_enum(value), type);
case G_TYPE_FLAGS:
return rbgobj_make_flags(g_value_get_flags(value), type);
case G_TYPE_OBJECT:
case G_TYPE_INTERFACE:
{
GObject* gobj = g_value_get_object(value);
return gobj ? GOBJ2RVAL(gobj) : Qnil;
}
case G_TYPE_PARAM:
{
GParamSpec* pspec = g_value_get_param(value);
return pspec ? rbgobj_ruby_object_from_instance(pspec) : Qnil;
}
case G_TYPE_POINTER:
{
gpointer ptr = g_value_get_pointer(value);
if (!ptr)
return Qnil;
else
return rbgobj_ptr_new(type, ptr);
}
case G_TYPE_BOXED:
{
GType gtype;
for (gtype = type;
gtype != G_TYPE_INVALID;
gtype = g_type_parent(gtype))
{
GValueToRValueFunc func =
g_type_get_qdata(gtype, qGValueToRValueFunc);
if (!func)
continue;
return func(value);
}
}
default:
if (!rbgobj_convert_gvalue2rvalue(fundamental_type, value, &rvalue)) {
GValueToRValueFunc func;
func = g_type_get_qdata(type, qGValueToRValueFunc);
if (!func) {
g_warning("rbgobj_gvalue_to_rvalue: unsupported type: %s\n",
g_type_name(type));
} else {
rvalue = func(value);
}
}
return rvalue;
}
}
static VALUE
rbgobj_gvalue_to_rvalue_unset_body(VALUE value)
{
return GVAL2RVAL((GValue *)value);
}
static VALUE
rbgobj_gvalue_to_rvalue_unset_ensure(VALUE value)
{
g_value_unset((GValue *)value);
return Qnil;
}
VALUE
rbgobj_gvalue_to_rvalue_unset(GValue *value)
{
return rb_ensure(rbgobj_gvalue_to_rvalue_unset_body, (VALUE)value,
rbgobj_gvalue_to_rvalue_unset_ensure, (VALUE)value);
}
void
rbgobj_initialize_gvalue(GValue *result, VALUE value)
{
GType type;
type = rbgobj_convert_rvalue2gtype(value);
if (type == 0) {
switch (TYPE(value)) {
case T_NONE:
case T_NIL:
type = G_TYPE_NONE;
break;
case T_FLOAT:
type = G_TYPE_DOUBLE;
break;
case T_STRING:
case T_SYMBOL:
type = G_TYPE_STRING;
break;
case T_FIXNUM:
type = G_TYPE_INT;
break;
case T_BIGNUM:
type = G_TYPE_INT64;
break;
case T_TRUE:
case T_FALSE:
type = G_TYPE_BOOLEAN;
break;
default:
if (RVAL2CBOOL(rb_obj_is_kind_of(value, rbgobj_cEnum))) {
type = G_TYPE_ENUM;
}
else if (RVAL2CBOOL(rb_obj_is_kind_of(value, rbgobj_cFlags))) {
type = G_TYPE_FLAGS;
}
else if (RVAL2CBOOL(rb_obj_is_kind_of(value, rbgobj_cBoxed))) {
type = G_TYPE_BOXED;
}
else if (RVAL2CBOOL(rb_obj_is_kind_of(value, rbgobj_cParam))) {
type = G_TYPE_PARAM;
}
else if (RVAL2CBOOL(rb_obj_is_kind_of(value, rbgobj_cObject))) {
type = G_TYPE_OBJECT;
}
else if (RVAL2CBOOL(rb_obj_is_kind_of(value, rbgobj_mInterface))) {
/* should use rbgobj_mMetaInterface? */
type = G_TYPE_INTERFACE;
}
else {
VALUE inspected_value;
inspected_value = rb_funcall(value, rb_intern("inspect"), 0);
rb_raise(rb_eArgError,
"unsupported value type: %s",
RSTRING_PTR(inspected_value));
}
break;
}
}
g_value_init(result, type);
rbgobj_rvalue_to_gvalue(value, result);
}
void
rbgobj_rvalue_to_gvalue(VALUE val, GValue* result)
{
GType type, fundamental_type;
type = G_VALUE_TYPE(result);
if (rbgobj_convert_rvalue2gvalue(type, val, result))
return;
fundamental_type = G_TYPE_FUNDAMENTAL(type);
switch (fundamental_type) {
case G_TYPE_NONE:
return;
case G_TYPE_CHAR:
g_value_set_char(result, NUM2INT(val));
return;
case G_TYPE_UCHAR:
g_value_set_uchar(result, NUM2UINT(val));
return;
case G_TYPE_BOOLEAN:
g_value_set_boolean(result, RVAL2CBOOL(val));
return;
case G_TYPE_INT:
g_value_set_int(result, NUM2INT(val));
return;
case G_TYPE_UINT:
g_value_set_uint(result, NUM2UINT(val));
return;
case G_TYPE_LONG:
g_value_set_long(result, NUM2LONG(val));
return;
case G_TYPE_ULONG:
g_value_set_ulong(result, NUM2ULONG(val));
return;
case G_TYPE_INT64:
g_value_set_int64(result, rbglib_num_to_int64(val));
return;
case G_TYPE_UINT64:
g_value_set_uint64(result, rbglib_num_to_uint64(val));
return;
case G_TYPE_ENUM:
g_value_set_enum(result, rbgobj_get_enum(val, G_VALUE_TYPE(result)));
return;
case G_TYPE_FLAGS:
g_value_set_flags(result, rbgobj_get_flags(val, G_VALUE_TYPE(result)));
return;
case G_TYPE_FLOAT:
g_value_set_float(result, NUM2DBL(val));
return;
case G_TYPE_DOUBLE:
g_value_set_double(result, NUM2DBL(val));
return;
case G_TYPE_STRING:
{
if (SYMBOL_P(val))
val = rb_funcall(val, id_to_s, 0);
g_value_set_string(result, RVAL2CSTR_ACCEPT_NIL(val));
return;
}
case G_TYPE_OBJECT:
case G_TYPE_INTERFACE:
g_value_set_object(result, NIL_P(val) ? NULL : RVAL2GOBJ(val));
return;
case G_TYPE_PARAM:
g_value_set_param(result, NIL_P(val) ? NULL : RVAL2GOBJ(val));
return;
case G_TYPE_POINTER:
g_value_set_pointer(result, NIL_P(val) ? NULL : rbgobj_ptr2cptr(val));
return;
case G_TYPE_BOXED:
{
GType gtype;
for (gtype = type;
gtype != G_TYPE_INVALID;
gtype = g_type_parent(gtype))
{
RValueToGValueFunc func =
g_type_get_qdata(gtype, qRValueToGValueFunc);
if (!func)
continue;
func(val, result);
return;
}
}
default:
if (!rbgobj_convert_rvalue2gvalue(fundamental_type, val, result)) {
RValueToGValueFunc func =
g_type_get_qdata(type, qRValueToGValueFunc);
if (!func){
g_warning("rbgobj_rvalue_to_gvalue: unsupported type: %s\n",
g_type_name(type));
} else {
func(val, result);
}
}
}
}
/**********************************************************************/
void
rbgobj_gc_mark_gvalue(GValue* value)
{
GType gtype = G_VALUE_TYPE(value);
/* FIXME */
if (G_TYPE_FUNDAMENTAL(gtype) == G_TYPE_OBJECT)
rbgobj_gc_mark_instance(g_value_get_object(value));
}
/**********************************************************************/
static VALUE
rg_initialize(VALUE self, VALUE rb_gtype, VALUE rb_value)
{
GValue value = G_VALUE_INIT;
g_value_init(&value, NUM2INT(rb_to_int(rb_gtype)));
rbgobj_rvalue_to_gvalue(rb_value, &value);
G_INITIALIZE(self, g_boxed_copy(G_TYPE_VALUE, &value));
g_value_unset(&value);
return Qnil;
}
static VALUE
rg_type(VALUE self)
{
GValue *value;
value = _SELF(self);
return rbgobj_gtype_new(value->g_type);
}
static VALUE
rg_value(VALUE self)
{
GValue *value;
value = _SELF(self);
return GVAL2RVAL(value);
}
void
Init_gobject_gvalue(void)
{
VALUE RG_TARGET_NAMESPACE;
id_to_s = rb_intern("to_s");
qRValueToGValueFunc = g_quark_from_static_string("__ruby_r2g_func__");
qGValueToRValueFunc = g_quark_from_static_string("__ruby_g2r_func__");
RG_TARGET_NAMESPACE = G_DEF_CLASS(G_TYPE_VALUE, "Value", mGLib);
RG_DEF_METHOD(initialize, 2);
RG_DEF_METHOD(type, 0);
RG_DEF_METHOD(value, 0);
}

View File

@ -0,0 +1,100 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2006 Sjoerd Simons
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
static VALUE
value_array_to_ruby(const GValue *from)
{
VALUE ary;
guint i;
GValueArray *array = (GValueArray *)g_value_get_boxed(from);
if (array == NULL)
return Qnil;
ary = rb_ary_new();
for (i = 0; i < array->n_values; i++)
rb_ary_push(ary, GVAL2RVAL(g_value_array_get_nth(array, i)));
return ary;
}
struct value_array_from_ruby_args {
VALUE ary;
long n;
GValueArray *result;
};
static VALUE
value_array_from_ruby_body(VALUE value)
{
long i;
struct value_array_from_ruby_args *args = (struct value_array_from_ruby_args *)value;
for (i = 0; i < args->n; i++) {
GValue v = G_VALUE_INIT;
g_value_init(&v, RVAL2GTYPE(RARRAY_PTR(args->ary)[i]));
rbgobj_rvalue_to_gvalue(RARRAY_PTR(args->ary)[i], &v);
g_value_array_append(args->result, &v);
}
return Qnil;
}
static G_GNUC_NORETURN VALUE
value_array_from_ruby_rescue(VALUE value)
{
g_value_array_free(((struct value_array_from_ruby_args *)value)->result);
rb_exc_raise(rb_errinfo());
}
static void
value_array_from_ruby(const VALUE from, GValue *to)
{
struct value_array_from_ruby_args args;
if (NIL_P(from)) {
g_value_set_boxed(to, NULL);
return;
}
args.ary = rb_ary_to_ary(from);
args.n = RARRAY_LEN(args.ary);
args.result = g_value_array_new(args.n);
rb_rescue(value_array_from_ruby_body, (VALUE)&args,
value_array_from_ruby_rescue, (VALUE)&args);
g_value_set_boxed(to, args.result);
}
void
Init_gobject_value_array(void)
{
/* ValueArray is treated as Array */
rbgobj_register_g2r_func(G_TYPE_VALUE_ARRAY, value_array_to_ruby);
rbgobj_register_r2g_func(G_TYPE_VALUE_ARRAY, value_array_from_ruby);
}

View File

@ -0,0 +1,243 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#include "rbgobject.h"
VALUE
rbgobj_ptr_new(GType type, gpointer ptr)
{
return Data_Wrap_Struct(GTYPE2CLASS(type), NULL, NULL, ptr);
}
gpointer
rbgobj_ptr2cptr(VALUE ptr)
{
gpointer dest;
if (rb_obj_is_kind_of(ptr, GTYPE2CLASS(G_TYPE_POINTER))){
Data_Get_Struct(ptr, void, dest);
} else if (rb_obj_is_kind_of(ptr, rb_cObject)){
dest = (gpointer)ptr;
} else{
rb_raise(rb_eTypeError, "not a pointer object");
}
return dest;
}
static VALUE
ptr_s_gtype(VALUE klass)
{
return rbgobj_gtype_new(rbgobj_lookup_class(klass)->gtype);
}
static VALUE
ptr_gtype(VALUE self)
{
return ptr_s_gtype(CLASS_OF(self));
}
static void
Init_gtype_pointer(void)
{
VALUE cPtr = G_DEF_CLASS(G_TYPE_POINTER, "Pointer", mGLib);
rbg_define_singleton_method(cPtr, "gtype", ptr_s_gtype, 1);
rbg_define_method(cPtr, "gtype", ptr_gtype, 1);
}
/**********************************************************************/
static GHashTable* boxed_ruby_value_table;
static VALUE boxed_ruby_value_table_wrapper;
typedef struct {
VALUE obj;
guint ref_count;
} boxed_ruby_value_counter;
static void
boxed_ruby_value_counter_mark(G_GNUC_UNUSED gpointer key,
gpointer value,
G_GNUC_UNUSED gpointer user_data)
{
boxed_ruby_value_counter* counter = value;
if (counter->ref_count)
rb_gc_mark(counter->obj);
}
static void
boxed_ruby_value_table_mark(GHashTable* table)
{
g_hash_table_foreach(table, boxed_ruby_value_counter_mark, NULL);
}
static VALUE
boxed_ruby_value_ref(VALUE val)
{
if (!SPECIAL_CONST_P(val)){
boxed_ruby_value_counter* counter;
counter = g_hash_table_lookup(boxed_ruby_value_table, (gpointer)val);
if (!counter){
counter = g_new(boxed_ruby_value_counter, 1);
counter->obj = val;
counter->ref_count = 1;
g_hash_table_insert(boxed_ruby_value_table, (gpointer)val,
counter);
} else {
counter->ref_count += 1;
}
}
return val;
}
static void
boxed_ruby_value_unref(VALUE val)
{
if (!SPECIAL_CONST_P(val)){
boxed_ruby_value_counter* counter;
counter = g_hash_table_lookup(boxed_ruby_value_table, (gpointer)val);
counter->ref_count -= 1;
if (!counter->ref_count)
g_hash_table_remove(boxed_ruby_value_table, (gpointer)val);
}
}
struct transform_arg {
const GValue *src_value;
GValue *dest_value;
};
static VALUE
value_transform_ruby_any_impl(VALUE arg_)
{
struct transform_arg* arg = (struct transform_arg*)arg_;
rbgobj_rvalue_to_gvalue(g_value_get_ruby_value(arg->src_value),
arg->dest_value);
return Qnil;
}
static void
value_transform_ruby_any(const GValue *src_value,
GValue *dest_value)
{
int state;
struct transform_arg arg;
arg.src_value = src_value;
arg.dest_value = dest_value;
rb_protect(&value_transform_ruby_any_impl, (VALUE)&arg, &state);
}
static void
value_transform_any_ruby(const GValue *src_value,
GValue *dest_value)
{
g_value_set_ruby_value(dest_value, GVAL2RVAL(src_value));
}
GType
rbgobj_ruby_value_get_type(void)
{
static GType our_type = 0;
if (!our_type){
const GType table[] = {
G_TYPE_CHAR,
G_TYPE_UCHAR,
G_TYPE_BOOLEAN,
G_TYPE_INT,
G_TYPE_UINT,
G_TYPE_LONG,
G_TYPE_ULONG,
G_TYPE_INT64,
G_TYPE_UINT64,
G_TYPE_ENUM,
G_TYPE_FLAGS,
G_TYPE_FLOAT,
G_TYPE_DOUBLE,
G_TYPE_STRING,
G_TYPE_POINTER,
//G_TYPE_BOXED,
G_TYPE_PARAM,
G_TYPE_OBJECT,
};
size_t i;
our_type = g_boxed_type_register_static(
"VALUE",
(GBoxedCopyFunc)boxed_ruby_value_ref,
(GBoxedFreeFunc)boxed_ruby_value_unref);
for (i = 0; i < sizeof(table)/sizeof(table[0]); i++){
g_value_register_transform_func(table[i], our_type,
value_transform_any_ruby);
}
g_value_register_transform_func(our_type, G_TYPE_BOOLEAN,
value_transform_ruby_any);
}
return our_type;
}
VALUE
g_value_get_ruby_value(const GValue* value)
{
return (VALUE)g_value_get_boxed(value);
}
void
g_value_set_ruby_value(GValue* value, VALUE ruby)
{
g_value_set_boxed(value, (gconstpointer)ruby);
}
static void
ruby_value_r2g(VALUE from, GValue* to)
{
g_value_set_ruby_value(to, from);
}
static void
Init_boxed_ruby_value(void)
{
boxed_ruby_value_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
boxed_ruby_value_table_wrapper =
Data_Wrap_Struct(rb_cData,
boxed_ruby_value_table_mark, NULL,
boxed_ruby_value_table);
rb_global_variable(&boxed_ruby_value_table_wrapper);
rbgobj_register_g2r_func(RBGOBJ_TYPE_RUBY_VALUE, g_value_get_ruby_value);
rbgobj_register_r2g_func(RBGOBJ_TYPE_RUBY_VALUE, ruby_value_r2g);
}
/**********************************************************************/
void
Init_gobject_gvaluetypes(void)
{
Init_gtype_pointer();
Init_boxed_ruby_value();
}

View File

@ -0,0 +1,385 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2003-2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
* Copyright (C) 1998-2000 Yukihiro Matsumoto,
* Daisuke Kanda,
* Hiroshi Igarashi
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "ruby.h"
#include "rbgprivate.h"
#include <ctype.h>
#include "rbgprivate.h"
static ID id_relatives;
static ID id_delete;
static ID id_module_eval;
ID rbgobj_id_children;
/**********************************************************************/
void
rbgobj_initialize_object(VALUE obj, gpointer cobj)
{
GType type;
GType parent_type;
if (!cobj)
rb_raise(rb_eRuntimeError, "failed to initialize");
type = RVAL2GTYPE(obj);
for (parent_type = type;
parent_type != G_TYPE_INVALID;
parent_type = g_type_parent(parent_type)) {
if (rbgobj_convert_initialize(parent_type, obj, cobj))
return;
}
type = G_TYPE_FUNDAMENTAL(type);
switch (type){
case G_TYPE_OBJECT:
rbgobj_gobject_initialize(obj, cobj);
break;
case G_TYPE_PARAM:
rbgobj_param_spec_initialize(obj, cobj);
break;
case G_TYPE_BOXED:
rbgobj_boxed_initialize(obj, cobj);
break;
default:
rbgobj_convert_initialize(type, obj, cobj);
break;
}
}
gpointer
rbgobj_instance_from_ruby_object(VALUE obj)
{
GType type;
GType fundamental_type;
if (NIL_P(obj))
return NULL;
type = RVAL2GTYPE(obj);
if (rbgobj_convert_has_type(type)) {
gpointer instance;
if (rbgobj_convert_robj2instance(type, obj, &instance))
return instance;
}
fundamental_type = G_TYPE_FUNDAMENTAL(type);
switch (fundamental_type) {
case G_TYPE_OBJECT:
return rbgobj_get_gobject(obj);
case G_TYPE_BOXED:
return rbgobj_boxed_get(obj, type);
case G_TYPE_PARAM:
return rbgobj_get_param_spec(obj);
default:
{
gpointer instance;
if (!rbgobj_convert_robj2instance(fundamental_type, obj, &instance)) {
rb_raise(rb_eTypeError, "%s isn't supported",
rb_class2name(CLASS_OF(obj)));
}
return instance;
}
}
}
VALUE
rbgobj_ruby_object_from_instance(gpointer instance)
{
return rbgobj_ruby_object_from_instance2(instance, TRUE);
}
VALUE
rbgobj_ruby_object_from_instance2(gpointer instance, gboolean alloc)
{
VALUE object;
GType type;
if (!instance)
return Qnil;
type = G_TYPE_FROM_INSTANCE(instance);
if (alloc) {
GType parent_type;
for (parent_type = type;
parent_type != G_TYPE_INVALID;
parent_type = g_type_parent(parent_type)) {
if (rbgobj_convert_instance2robj(parent_type, instance, &object))
return object;
}
}
switch (G_TYPE_FUNDAMENTAL(type)) {
case G_TYPE_OBJECT:
return rbgobj_get_ruby_object_from_gobject(instance, alloc);
case G_TYPE_PARAM:
return rbgobj_get_ruby_object_from_param_spec(instance, alloc);
default:
if (alloc) {
rb_raise(rb_eTypeError, "%s isn't supported", g_type_name(type));
} else {
return Qnil;
}
}
}
VALUE
rbgobj_ruby_object_from_instance_with_unref(gpointer instance)
{
VALUE result = rbgobj_ruby_object_from_instance(instance);
if (!NIL_P(result)) {
GType type;
type = G_TYPE_FROM_INSTANCE(instance);
if (!rbgobj_convert_unref(type, instance)) {
type = G_TYPE_FUNDAMENTAL(type);
switch (type) {
case G_TYPE_OBJECT:
g_object_unref(instance);
break;
default:
rbgobj_convert_unref(type, instance);
break;
}
}
}
return result;
}
/**********************************************************************/
void
rbgobj_add_relative(VALUE obj, VALUE relative)
{
VALUE hash = Qnil;
if (RVAL2CBOOL(rb_ivar_defined(obj, id_relatives)))
hash = rb_ivar_get(obj, id_relatives);
if (NIL_P(hash) || TYPE(hash) != RUBY_T_HASH) {
hash = rb_hash_new();
rb_ivar_set(obj, id_relatives, hash);
}
rb_hash_aset(hash, relative, Qnil);
}
void
rbgobj_invalidate_relatives(VALUE obj)
{
if (RVAL2CBOOL(rb_ivar_defined(obj, id_relatives)))
rb_ivar_set(obj, id_relatives, Qnil);
if (RVAL2CBOOL(rb_ivar_defined(obj, rbgobj_id_children)))
rb_ivar_set(obj, rbgobj_id_children, Qnil);
}
void
rbgobj_add_relative_removable(VALUE obj, VALUE relative, ID obj_ivar_id, VALUE hash_key)
{
VALUE hash = Qnil;
if (RVAL2CBOOL(rb_ivar_defined(obj, obj_ivar_id)))
hash = rb_ivar_get(obj, obj_ivar_id);
if (NIL_P(hash) || TYPE(hash) != RUBY_T_HASH) {
hash = rb_hash_new();
rb_ivar_set(obj, obj_ivar_id, hash);
}
rb_hash_aset(hash, hash_key, relative);
}
VALUE
rbgobj_get_relative_removable(VALUE obj, ID obj_ivar_id, VALUE hash_key)
{
VALUE hash = Qnil;
if (RVAL2CBOOL(rb_ivar_defined(obj, obj_ivar_id)))
hash = rb_ivar_get(obj, obj_ivar_id);
if (NIL_P(hash) || TYPE(hash) != RUBY_T_HASH) {
return Qnil;
}
return rb_hash_aref(hash, hash_key);
}
void
rbgobj_remove_relative(VALUE obj, ID obj_ivar_id, VALUE hash_key)
{
VALUE hash = Qnil;
if (RVAL2CBOOL(rb_ivar_defined(obj, obj_ivar_id)))
hash = rb_ivar_get(obj, obj_ivar_id);
if (NIL_P(hash) || TYPE(hash) != RUBY_T_HASH) {
/* should not happen. */
} else {
rb_funcall(hash, id_delete, 1, hash_key);
}
}
void
rbgobj_remove_relative_all(VALUE obj, ID obj_ivar_id)
{
rb_ivar_set(obj, obj_ivar_id, Qnil);
}
/**********************************************************************/
static GHashTable* prop_exclude_list;
#define IS_FLAG(bitmask, flag) (((bitmask) & (flag)) == (flag))
void
rbgobj_define_property_accessors(VALUE klass)
{
GType gtype;
GParamSpec** pspecs = NULL;
guint i;
GString* source;
guint n_properties = 0;
gtype = CLASS2GTYPE(klass);
if (G_TYPE_IS_INTERFACE(gtype)){
#if GLIB_CHECK_VERSION(2,4,0)
gpointer iface = g_type_default_interface_ref(gtype);
pspecs = g_object_interface_list_properties(iface, &n_properties);
g_type_default_interface_unref(iface);
#endif
} else {
GObjectClass* oclass = G_OBJECT_CLASS(g_type_class_ref(gtype));
pspecs = g_object_class_list_properties(oclass, &n_properties);
g_type_class_unref(oclass);
}
if (n_properties == 0)
return;
source = g_string_new(NULL);
for (i = 0; i < n_properties; i++){
GParamSpec* pspec = pspecs[i];
char* buf;
char* prop_name;
char* p;
if (pspec->owner_type != gtype)
continue;
buf = g_strdup(pspec->name);
for (p = buf; *p; p++)
if (*p == '-')
*p = '_';
if (!strncmp(buf, "is_", 3))
prop_name = buf + 3;
else
prop_name = buf;
if (g_hash_table_lookup(prop_exclude_list, prop_name)){
g_free(buf);
continue;
}
if (pspec->flags & G_PARAM_READABLE){
g_string_append_printf(
source,
"def %s%s; get_property('%s'); end\n",
prop_name,
(G_PARAM_SPEC_VALUE_TYPE(pspec) == G_TYPE_BOOLEAN) ? "?" : "",
pspec->name);
}
if (IS_FLAG(pspec->flags, G_PARAM_WRITABLE) && !IS_FLAG(pspec->flags, G_PARAM_CONSTRUCT_ONLY)){
g_string_append_printf(source,
"def set_%s(val); set_property('%s', val); end\n",
prop_name, pspec->name);
#ifdef HAVE_NODE_ATTRASGN
g_string_append_printf(source, "alias %s= set_%s\n",
prop_name, prop_name);
#else
g_string_append_printf(source,
"def %s=(val); set_property('%s', val); val; end\n",
prop_name, pspec->name);
#endif
}
g_free(buf);
}
if (source->len > 0)
rb_funcall(klass, id_module_eval, 1, rb_str_new2(source->str));
g_string_free(source, TRUE);
}
/**********************************************************************/
void
Init_gobject(void)
{
/* Not defined properties. They are already used as methods of Object */
prop_exclude_list = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_insert(prop_exclude_list, (gpointer)"class", (gpointer)"class");
g_hash_table_insert(prop_exclude_list, (gpointer)"clone", (gpointer)"clone");
g_hash_table_insert(prop_exclude_list, (gpointer)"dup", (gpointer)"dup");
g_hash_table_insert(prop_exclude_list, (gpointer)"extend", (gpointer)"extend");
g_hash_table_insert(prop_exclude_list, (gpointer)"freeze", (gpointer)"freeze");
g_hash_table_insert(prop_exclude_list, (gpointer)"hash", (gpointer)"hash");
g_hash_table_insert(prop_exclude_list, (gpointer)"method", (gpointer)"method");
g_hash_table_insert(prop_exclude_list, (gpointer)"methods", (gpointer)"methods");
g_hash_table_insert(prop_exclude_list, (gpointer)"object_id", (gpointer)"object_id");
g_hash_table_insert(prop_exclude_list, (gpointer)"taint", (gpointer)"taint");
g_hash_table_insert(prop_exclude_list, (gpointer)"untaint", (gpointer)"untaint");
/* IDs */
id_relatives = rb_intern("__relatives__");
id_delete = rb_intern("delete");
id_module_eval = rb_intern("module_eval");
rbgobj_id_children = rb_intern("__stored_children__");
Init_gobject_convert();
Init_gobject_gtype();
Init_gobject_typeinterface();
Init_gobject_typeinstance();
Init_gobject_gvalue();
Init_gobject_gvaluetypes();
Init_gobject_gboxed();
#if GLIB_CHECK_VERSION(2,6,0)
Init_gobject_gstrv();
#endif
Init_gobject_value_array();
Init_gobject_genumflags();
Init_gobject_gparam();
Init_gobject_gparamspecs();
Init_gobject_gclosure();
Init_gobject_gobject();
Init_gobject_gsignal();
Init_gobject_gtypeplugin();
Init_gobject_gtypemodule();
}

View File

@ -0,0 +1,300 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2003,2006 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masahiro Sakai
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGOBJECT_H__
#define __RBGOBJECT_H__
#include <glib-object.h>
#include "ruby.h"
#include "rbglib.h"
#include "rbgutil.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* macros */
#define G_INITIALIZE(obj, cobj)\
(rbgobj_initialize_object(obj, (gpointer)cobj))
#define G_DEF_CLASS(gtype, name, module)\
(rbgobj_define_class(gtype, name, module, 0, 0, Qnil))
#define G_DEF_CLASS_WITH_GC_FUNC(gtype, name, module, mark, free) \
(rbgobj_define_class(gtype, name, module, mark, free, Qnil))
#define G_DEF_CLASS2(gtype, name, module, mark, free) \
G_DEF_CLASS_WITH_GC_FUNC(gtype, name, module, mark, free)
#define G_DEF_CLASS3(gtype_name, name, module)\
(rbgobj_define_class_dynamic(gtype_name, name, module, 0, 0))
#define G_DEF_CLASS_WITH_PARENT(gtype, name, module, parent) \
(rbgobj_define_class(gtype, name, module, 0, 0, parent))
#define G_DEF_CLASS4(gtype, name, module, parent) \
G_DEF_CLASS_WITH_PARENT(gtype, name, module, parent)
#define G_DEF_INTERFACE(gtype, name, module)\
(rbgobj_define_class(gtype, name, module, 0, 0, Qnil))
#define G_DEF_INTERFACE2(gtype, name, module, mark, free)\
(rbgobj_define_class(gtype, name, module, mark, free, Qnil))
#define RG_DEF_CONVERSION(table) (rbgobj_convert_define(table))
#define G_RELATIVE(obj, rel) (rbgobj_add_relative(obj, rel))
/* G_RELATIVE2 is useless now. Try G_CHILD_ADD/REMOVE first. */
#define G_RELATIVE2(obj, rel, id, hash_key)\
(rbgobj_add_relative_removable(obj, rel, id, hash_key))
#define G_GET_RELATIVE(obj, id, hash_key)\
(rbgobj_get_relative_removable(obj, id, hash_key))
#define G_REMOVE_RELATIVE(obj, id, hash_key)\
(rbgobj_remove_relative(obj, id, hash_key))
RUBY_GLIB2_VAR ID rbgobj_id_children;
#define G_CHILD_SET(self, id, child) (rb_ivar_set(self, id, child))
#define G_CHILD_UNSET(self, id) (rb_ivar_set(self, id, Qnil))
/* G_CHILD_ADD is same as G_RELATIVE, but the macro name is more obviously
to use than G_RELATIVE, and also support "remove" operation with the key
which is the object itself.
*/
#define G_CHILD_ADD(self, child) \
(rbgobj_add_relative_removable(self, Qnil, rbgobj_id_children, child))
#define G_CHILD_REMOVE(self, child) \
(rbgobj_remove_relative(self, rbgobj_id_children, child))
#define G_CHILD_REMOVE_ALL(self) \
(rbgobj_remove_relative_all(self, rbgobj_id_children))
#define G_DEF_SIGNAL_FUNC(klass, sig_name, func)\
(rbgobj_set_signal_func(klass, sig_name, func))
#define CLASS2CINFO(klass) (rbgobj_lookup_class(klass))
#define GTYPE2CINFO(gtype) (rbgobj_lookup_class_by_gtype(gtype, Qnil))
#define GTYPE2CINFO_NO_CREATE(gtype) (rbgobj_lookup_class_by_gtype_full(gtype, Qnil, FALSE))
#define RVAL2CINFO(obj) (rbgobj_lookup_class(CLASS_OF(obj)))
#define GTYPE2CLASS(gtype) (rbgobj_gtype_to_ruby_class(gtype))
#define CLASS2GTYPE(klass) (rbgobj_lookup_class(klass)->gtype)
#define RVAL2GTYPE(obj) (CLASS2GTYPE(CLASS_OF(obj)))
#define RVAL2GOBJ(obj) (rbgobj_instance_from_ruby_object(obj))
#define GOBJ2RVAL(gobj) (rbgobj_ruby_object_from_instance(gobj))
#define GOBJ2RVAL_UNREF(gobj) (rbgobj_ruby_object_from_instance_with_unref(gobj))
#define GOBJ2RVALU(gobj) GOBJ2RVAL_UNREF(gobj)
#define GVAL2RVAL(v) (rbgobj_gvalue_to_rvalue(v))
#define GVAL2RVAL_UNSET(v) (rbgobj_gvalue_to_rvalue(v))
#define RVAL2BOXED(obj, gtype) (rbgobj_boxed_get(obj, gtype))
#define BOXED2RVAL(cobj, gtype) (rbgobj_make_boxed(cobj, gtype))
#define RVAL2GENUM(obj, gtype) (rbgobj_get_enum(obj, gtype))
#define RVAL2GFLAGS(obj, gtype) (rbgobj_get_flags(obj, gtype))
#define GENUM2RVAL(n, gtype) (rbgobj_make_enum(n, gtype))
#define GFLAGS2RVAL(n, gtype) (rbgobj_make_flags(n, gtype))
#define RVAL2GPTR(object) (rbgobj_ptr2cptr(object))
#define GPTR2RVAL(ptr, gtype) (rbgobj_ptr_new(gtype, ptr))
#define G_DEF_CONSTANTS(mod, type, strip_prefix) \
rbgobj_add_constants(mod, type, strip_prefix)
#define G_RENAME_CONSTANT(orig, alt) \
rbgobj_constant_remap(orig, alt)
#define G_RENAME_NICK(orig, alt) \
rbgobj_constant_remap(orig, alt)
typedef enum
{
RBGOBJ_ABSTRACT_BUT_CREATABLE = 1 << 0, /* deprecated */
RBGOBJ_BOXED_NOT_COPY = 1 << 1,
RBGOBJ_DEFINED_BY_RUBY = 1 << 2,
} RGObjClassFlag;
typedef void (*RGMarkFunc)(gpointer object);
typedef void (*RGFreeFunc)(gpointer object);
typedef struct {
VALUE klass;
GType gtype;
RGMarkFunc mark;
RGFreeFunc free;
int flags; /* RGObjClassFlag */
} RGObjClassInfo;
/* rbgobject.c */
extern void rbgobj_initialize_object(VALUE obj, gpointer cobj);
extern gpointer rbgobj_instance_from_ruby_object(VALUE obj);
extern VALUE rbgobj_ruby_object_from_instance(gpointer instance);
extern VALUE rbgobj_ruby_object_from_instance2(gpointer instance, gboolean alloc);
extern VALUE rbgobj_ruby_object_from_instance_with_unref(gpointer instance);
extern void rbgobj_add_relative(VALUE obj, VALUE relative);
extern void rbgobj_invalidate_relatives(VALUE obj);
extern void rbgobj_add_relative_removable(VALUE obj, VALUE relative,
ID obj_ivar_id, VALUE hash_key);
extern VALUE rbgobj_get_relative_removable(VALUE obj, ID obj_ivar_id,
VALUE hash_key);
extern void rbgobj_remove_relative(VALUE obj, ID obj_ivar_id, VALUE hash_key);
extern void rbgobj_remove_relative_all(VALUE obj, ID obj_ivar_id);
extern GObject* rbgobj_gobject_new(GType type, VALUE params_hash);
extern VALUE rbgobj_create_object(VALUE klass); /* deprecated */
extern VALUE rbgobj_get_ruby_object_from_gobject(GObject* gobj, gboolean alloc);
/* For Ruby/Gstreamer */
extern void rbgobj_gobject_initialize(VALUE obj, gpointer cobj);
/* deprecated */
extern void rbgobj_add_abstract_but_create_instance_class(GType gtype);
/* rbgobj_typeinstance.c */
extern void rbgobj_gc_mark_instance(gpointer instance);
/* rbgobj_type.c */
extern const RGObjClassInfo *rbgobj_lookup_class(VALUE klass);
extern const RGObjClassInfo *rbgobj_lookup_class_by_gtype(GType gtype, VALUE parent);
extern const RGObjClassInfo *rbgobj_lookup_class_by_gtype_full(GType gtype,
VALUE parent,
gboolean create_object);
extern VALUE rbgobj_gtype_to_ruby_class(GType gtype);
extern VALUE rbgobj_define_class(GType gtype, const gchar* name, VALUE module,
RGMarkFunc mark, RGFreeFunc free, VALUE parent);
extern VALUE rbgobj_define_class_dynamic(const gchar* gtype_name,
const gchar* name, VALUE module,
RGMarkFunc mark, RGFreeFunc free);
extern void rbgobj_register_class(VALUE klass,
GType gtype,
gboolean klass2gtype,
gboolean gtype2klass);
extern void rbgobj_register_mark_func(GType gtype, RGMarkFunc mark);
extern void rbgobj_register_free_func(GType gtype, RGFreeFunc free);
extern VALUE rbgobj_cType;
extern VALUE rbgobj_gtype_new(GType gtype);
extern GType rbgobj_gtype_get(VALUE obj);
/* rbgobj_signal.c */
typedef VALUE (*GValToRValSignalFunc)(guint num,const GValue* values);
extern void rbgobj_set_signal_func(VALUE klass, const gchar *sig_name, GValToRValSignalFunc func);
extern GValToRValSignalFunc rbgobj_get_signal_func(guint signal_id);
extern VALUE rbgobj_signal_wrap(guint sig_id);
/* rbgobj_closure.c */
extern GClosure* g_rclosure_new(VALUE callback_proc, VALUE extra_args,
GValToRValSignalFunc func);
extern void g_rclosure_attach(GClosure *closure, VALUE object);
extern void g_rclosure_set_tag(GClosure *closure, const gchar *tag);
/* rbgobj_value.c */
extern VALUE rbgobj_gvalue_to_rvalue(const GValue* value);
extern VALUE rbgobj_gvalue_to_rvalue_unset(GValue *value);
extern void rbgobj_rvalue_to_gvalue(VALUE val, GValue* result);
extern void rbgobj_initialize_gvalue(GValue *result, VALUE value);
typedef void (*RValueToGValueFunc)(VALUE from, GValue* to);
typedef VALUE (*GValueToRValueFunc)(const GValue* from);
extern void rbgobj_register_r2g_func(GType gtype, RValueToGValueFunc func);
extern void rbgobj_register_g2r_func(GType gtype, GValueToRValueFunc func);
extern void rbgobj_gc_mark_gvalue(GValue* value);
/* rbgobj_valuetypes.c */
extern VALUE rbgobj_ptr_new(GType type, gpointer ptr);
extern gpointer rbgobj_ptr2cptr(VALUE ptr);
#define RBGOBJ_TYPE_RUBY_VALUE (rbgobj_ruby_value_get_type())
extern GType rbgobj_ruby_value_get_type(void);
extern VALUE g_value_get_ruby_value(const GValue* value);
extern void g_value_set_ruby_value(GValue* value, VALUE ruby);
/* rbgobj_object.c */
extern void rbgobj_register_property_setter(GType gtype, const char* prop_name, RValueToGValueFunc func);
extern void rbgobj_register_property_getter(GType gtype, const char* prop_name, GValueToRValueFunc func);
/* rbgobj_boxed.c */
extern VALUE rbgobj_boxed_create(VALUE klass); /* deprecated */
extern gpointer rbgobj_boxed_get(VALUE obj, GType gtype);
extern gpointer rbgobj_boxed_get_default(VALUE obj, GType gtype);
extern VALUE rbgobj_make_boxed(gpointer data, GType gtype);
extern VALUE rbgobj_make_boxed_raw(gpointer p, GType gtype,
VALUE klass, gint flags);
extern VALUE rbgobj_make_boxed_default(gpointer data, GType gtype);
extern void rbgobj_boxed_not_copy_obj(GType gtype);
extern void rbgobj_boxed_unown(VALUE boxed);
/* rbgobj_enums.c */
extern void rbgobj_constant_remap(const char *original, const char *replacement);
extern void rbgobj_add_constants(VALUE mod, GType type, const gchar *strip_prefix);
extern VALUE rbgobj_make_enum(gint n, GType gtype);
extern gint rbgobj_get_enum(VALUE obj, GType gtype);
extern VALUE rbgobj_make_flags(guint n, GType gtype);
extern guint rbgobj_get_flags(VALUE obj, GType gtype);
extern void rbgobj_define_const(VALUE mod, const char *name, VALUE value);
/* rbglib_mainloop.c */
#if !GLIB_CHECK_VERSION(2,30,0)
#define G_TYPE_MAIN_LOOP (g_main_loop_get_type())
extern GType g_main_loop_get_type(void);
#endif
/* rbglib_maincontext.c */
#if !GLIB_CHECK_VERSION(2,30,0)
#define G_TYPE_MAIN_CONTEXT (g_main_context_get_type())
#define G_TYPE_SOURCE (g_source_get_type())
extern GType g_main_context_get_type(void);
extern GType g_source_get_type(void);
#endif
#define G_TYPE_POLL_FD (g_poll_fd_get_type())
extern GType g_poll_fd_get_type(void);
/* rbglib_keyfile.c */
#if !GLIB_CHECK_VERSION(2,31,2)
#define G_TYPE_KEY_FILE (g_key_file_get_type())
extern GType g_key_file_get_type(void);
#endif
/* rbgobj_convert.c */
typedef struct {
GType type;
VALUE klass;
gpointer user_data;
GDestroyNotify notify;
VALUE (*get_superclass)(gpointer user_data);
void (*type_init_hook)(VALUE klass, gpointer user_data);
void (*rvalue2gvalue)(VALUE value, GValue *result, gpointer user_data);
VALUE (*gvalue2rvalue)(const GValue *value, gpointer user_data);
void (*initialize)(VALUE rb_instance, gpointer insntance, gpointer user_data);
gpointer (*robj2instance)(VALUE rb_instance, gpointer user_data);
VALUE (*instance2robj)(gpointer instance, gpointer user_data);
void (*unref)(gpointer instance, gpointer user_data);
} RGConvertTable;
extern void rbgobj_convert_define(const RGConvertTable *table);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __RBGOBJECT_H__ */
#include "rbgcompat.h"

View File

@ -0,0 +1,177 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2007 Ruby-GNOME2 Project Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGPRIVATE_H__
#define __RBGPRIVATE_H__
#include "rbgobject.h"
#include "glib-enum-types.h"
#ifndef HAVE_RB_ERRINFO
# define rb_errinfo() (ruby_errinfo)
#endif
#ifndef HAVE_RB_STR_NEW_CSTR
# define rb_str_new_cstr(c_string) rb_str_new2(c_string)
#endif
#ifndef G_VALUE_INIT
# define G_VALUE_INIT { 0, { { 0 } } }
#endif
G_BEGIN_DECLS
typedef struct {
VALUE self;
GObject* gobj;
const RGObjClassInfo* cinfo;
gboolean destroyed;
} gobj_holder;
typedef struct {
gpointer boxed;
gboolean own;
GType type;
} boxed_holder;
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
G_GNUC_INTERNAL extern GStaticPrivate rg_polling_key;
#endif
extern VALUE rbgobj_cEnum;
extern VALUE rbgobj_cFlags;
extern VALUE rbgobj_cBoxed;
extern VALUE rbgobj_cParam;
extern VALUE rbgobj_mInterface;
extern VALUE rbgobj_cObject;
extern VALUE rbgobj_cInstantiatable;
extern VALUE rbgobj_mMetaInterface;
#define cInstantiatable rbgobj_cInstantiatable
#define mMetaInterface rbgobj_mMetaInterface
extern void rbgobj_define_property_accessors(VALUE klass);
extern void rbgobj_define_action_methods(VALUE klass);
extern void rbgobj_param_spec_initialize(VALUE self, GParamSpec* pspec);
extern void rbgobj_boxed_initialize(VALUE obj, gpointer boxed);
extern GParamSpec* rbgobj_get_param_spec(VALUE obj);
extern GObject* rbgobj_get_gobject(VALUE obj);
extern VALUE rbgobj_get_ruby_object_from_param_spec(GParamSpec* pspec, gboolean alloc);
extern void rbgobj_init_object_class(VALUE klass);
extern void rbgobj_init_flags_class(VALUE klass);
extern void rbgobj_init_enum_class(VALUE klass);
extern void rbgobj_init_interface(VALUE interf);
/* FIXME: should have better name */
extern void rbgobj_instance_call_cinfo_mark(gpointer instance);
extern void rbgobj_instance_call_cinfo_free(gpointer instance);
VALUE rbgutil_generic_s_gtype(VALUE klass);
VALUE rbgutil_generic_gtype(VALUE self);
#define generic_s_gtype rbgutil_generic_s_gtype
#define generic_gtype rbgutil_generic_gtype
extern gboolean rbgobj_convert_has_type(GType type);
extern RGConvertTable *rbgobj_convert_lookup(GType type);
extern gboolean rbgobj_convert_get_superclass(GType type, VALUE *result);
extern gboolean rbgobj_convert_type_init_hook(GType type, VALUE klass);
extern gboolean rbgobj_convert_gvalue2rvalue(GType type, const GValue *value,
VALUE *result);
extern gboolean rbgobj_convert_rvalue2gvalue(GType type, VALUE val,
GValue *result);
extern GType rbgobj_convert_rvalue2gtype(VALUE val);
extern gboolean rbgobj_convert_initialize(GType type, VALUE obj, gpointer cobj);
extern gboolean rbgobj_convert_robj2instance(GType type, VALUE obj,
gpointer *result);
extern gboolean rbgobj_convert_instance2robj(GType type, gpointer instance,
VALUE *result);
extern gboolean rbgobj_convert_unref(GType type, gpointer instance);
#define RubyGObjectHookModule "RubyGObjectHook__"
G_GNUC_INTERNAL VALUE rg_enum_resolve_value(VALUE klass, VALUE nick);
G_GNUC_INTERNAL void rg_enum_add_constants(VALUE mod, GType enum_type, const gchar *strip_prefix);
G_GNUC_INTERNAL void rg_flags_add_constants(VALUE mod, GType flags_type, const gchar *strip_prefix);
G_GNUC_INTERNAL char *rg_obj_constant_lookup(const char *name);
G_GNUC_INTERNAL void Init_gutil(void);
G_GNUC_INTERNAL void Init_gutil_callback(void);
G_GNUC_INTERNAL void Init_glib_int64(void);
G_GNUC_INTERNAL void Init_glib_error(void);
G_GNUC_INTERNAL void Init_glib_threads(void);
G_GNUC_INTERNAL void Init_glib_convert(void);
G_GNUC_INTERNAL void Init_glib_messages(void);
G_GNUC_INTERNAL void Init_glib_spawn(void);
G_GNUC_INTERNAL void Init_glib_spawnerror(void);
G_GNUC_INTERNAL void Init_glib_fileutils(void);
G_GNUC_INTERNAL void Init_glib_utils(void);
G_GNUC_INTERNAL void Init_glib_i18n(void);
G_GNUC_INTERNAL void Init_glib_win32(void);
G_GNUC_INTERNAL void Init_gobject(void);
G_GNUC_INTERNAL void Init_glib_main_loop(void);
G_GNUC_INTERNAL void Init_glib_main_context(void);
G_GNUC_INTERNAL void Init_glib_source(void);
G_GNUC_INTERNAL void Init_glib_poll_fd(void);
G_GNUC_INTERNAL void Init_glib_io_constants(void);
G_GNUC_INTERNAL void Init_glib_io_channel(void);
G_GNUC_INTERNAL void Init_glib_io_channelerror(void);
G_GNUC_INTERNAL void Init_glib_io_channel_win32_socket(void);
G_GNUC_INTERNAL void Init_glib_shell(void);
G_GNUC_INTERNAL void Init_glib_shellerror(void);
G_GNUC_INTERNAL void Init_glib_timer(void);
G_GNUC_INTERNAL void Init_glib_unicode(void);
G_GNUC_INTERNAL void Init_glib_utf8(void);
G_GNUC_INTERNAL void Init_glib_utf16(void);
G_GNUC_INTERNAL void Init_glib_ucs4(void);
G_GNUC_INTERNAL void Init_glib_unichar(void);
G_GNUC_INTERNAL void Init_glib_keyfile(void);
G_GNUC_INTERNAL void Init_glib_bookmark_file(void);
G_GNUC_INTERNAL void Init_gobject_convert(void);
G_GNUC_INTERNAL void Init_gobject_gtype(void);
G_GNUC_INTERNAL void Init_gobject_typeinterface(void);
G_GNUC_INTERNAL void Init_gobject_typeinstance(void);
G_GNUC_INTERNAL void Init_gobject_gvalue(void);
G_GNUC_INTERNAL void Init_gobject_gvaluetypes(void);
G_GNUC_INTERNAL void Init_gobject_gboxed(void);
#if GLIB_CHECK_VERSION(2,6,0)
G_GNUC_INTERNAL void Init_gobject_gstrv(void);
#endif
G_GNUC_INTERNAL void Init_gobject_value_array(void);
G_GNUC_INTERNAL void Init_gobject_genumflags(void);
G_GNUC_INTERNAL void Init_gobject_genums(void);
G_GNUC_INTERNAL void Init_gobject_gflags(void);
G_GNUC_INTERNAL void Init_gobject_gparam(void);
G_GNUC_INTERNAL void Init_gobject_gparamspecs(void);
G_GNUC_INTERNAL void Init_gobject_gclosure(void);
G_GNUC_INTERNAL void Init_gobject_gobject(void);
G_GNUC_INTERNAL void Init_gobject_gsignal(void);
G_GNUC_INTERNAL void Init_gobject_gtypeplugin(void);
G_GNUC_INTERNAL void Init_gobject_gtypemodule(void);
G_END_DECLS
#endif

View File

@ -0,0 +1,145 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2004 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
ID rbgutil_id_module_eval;
static ID id_add_one_arg_setter;
static ID id_set_property;
static ID id_to_a;
static ID id_allocate;
static ID id_equal;
void
rbg_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_define_method(klass, name, func, argc);
if ((argc != 1) || strncmp(name, "set_", 4))
return;
name += 4;
rb_funcall(klass, rbgutil_id_module_eval, 1,
CSTR2RVAL_FREE(g_strdup_printf("def %s=(val); set_%s(val); val; end\n",
name, name)));
}
void
rbg_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
{
rb_define_singleton_method(obj, name, func, argc);
if ((argc != 1) || strncmp(name, "set_", 4))
return;
name += 4;
rb_funcall(obj, rbgutil_id_module_eval, 1,
CSTR2RVAL_FREE(g_strdup_printf("def self.%s=(val); set_%s(val); val; end\n",
name, name)));
}
void
rbgutil_set_properties(VALUE self, VALUE hash)
{
int i;
VALUE ary;
GObject* obj;
Check_Type(hash, RUBY_T_HASH);
ary = rb_funcall(hash, id_to_a, 0);
obj = RVAL2GOBJ(self);
g_object_freeze_notify(obj);
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_funcall(self, id_set_property, 2,
RARRAY_PTR(RARRAY_PTR(ary)[i])[0],
RARRAY_PTR(RARRAY_PTR(ary)[i])[1]);
}
g_object_thaw_notify(obj);
}
VALUE
rbgutil_def_setters(VALUE klass)
{
return rb_funcall(mGLib, id_add_one_arg_setter, 1, klass);
}
void
rbgutil_glibid_r2g_func(VALUE from, GValue* to)
{
VALUE buffer;
g_value_set_string(to, RVAL2GLIBID(from, buffer));
}
VALUE
rbgutil_sym_g2r_func(const GValue *from)
{
const gchar *str = g_value_get_string(from);
return str ? ID2SYM(rb_intern(str)) : Qnil;
}
VALUE
rbgutil_generic_s_gtype(VALUE klass)
{
return rbgobj_gtype_new(CLASS2GTYPE(klass));
}
VALUE
rbgutil_generic_gtype(VALUE self)
{
return generic_s_gtype(CLASS_OF(self));
}
VALUE
rbgutil_string_set_utf8_encoding(VALUE string)
{
#ifdef HAVE_RUBY_ENCODING_H
if (!NIL_P(string))
rb_enc_associate(string, rb_utf8_encoding());
#endif
return string;
}
gboolean
rbgutil_key_equal(VALUE rb_key, const char *key)
{
switch (TYPE(rb_key)) {
case RUBY_T_STRING:
return RVAL2CBOOL(rb_funcall(rb_key, id_equal, 1, rb_str_new_cstr(key)));
break;
case RUBY_T_SYMBOL:
return SYM2ID(rb_key) == rb_intern(key);
break;
default:
return FALSE;
break;
}
}
void
Init_gutil(void)
{
rbgutil_id_module_eval = rb_intern("module_eval");
id_set_property = rb_intern("set_property");
id_to_a = rb_intern("to_a");
id_add_one_arg_setter = rb_intern("__add_one_arg_setter");
id_allocate = rb_intern("allocate");
id_equal = rb_intern("==");
}

View File

@ -0,0 +1,110 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011-2013 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGUTIL_H__
#define __RBGUTIL_H__
#include <glib-object.h>
#include "ruby.h"
#ifdef HAVE_RUBY_ENCODING_H
# include <ruby/encoding.h>
#endif
#include "rbglib.h"
#include "rbgutil_list.h"
#include "rbgutildeprecated.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define RG_DEF_MODFUNC(method, argc) \
rb_define_module_function(RG_TARGET_NAMESPACE, #method, rg_m_ ## method, argc)
#define RG_DEF_MODFUNC_P(method, argc) \
rb_define_module_function(RG_TARGET_NAMESPACE, #method"?", rg_m_ ## method ## _p, argc)
#define RG_DEF_MODFUNC_OPERATOR(ope, func, argc) \
rb_define_module_function(RG_TARGET_NAMESPACE, ope, rg_m_operator_ ## func, argc)
#define RG_DEF_SMETHOD(method, argc) \
rbg_define_singleton_method(RG_TARGET_NAMESPACE, #method, rg_s_ ## method, argc)
#define RG_DEF_SMETHOD_P(method, argc) \
rb_define_singleton_method(RG_TARGET_NAMESPACE, #method"?", rg_s_ ## method ## _p, argc)
#define RG_DEF_SMETHOD_BANG(method, argc) \
rb_define_singleton_method(RG_TARGET_NAMESPACE, #method"!", rg_s_ ## method ## _bang, argc)
#define RG_DEF_SMETHOD_OPERATOR(ope, func, argc) \
rb_define_singleton_method(RG_TARGET_NAMESPACE, ope, rg_s_operator_ ## func, argc)
#define RG_DEF_METHOD(method, argc) \
rbg_define_method(RG_TARGET_NAMESPACE, #method, rg_ ## method, argc)
#define RG_DEF_METHOD_P(method, argc) \
rb_define_method(RG_TARGET_NAMESPACE, #method"?", rg_ ## method ## _p, argc)
#define RG_DEF_METHOD_BANG(method, argc) \
rb_define_method(RG_TARGET_NAMESPACE, #method"!", rg_ ## method ## _bang, argc)
#define RG_DEF_METHOD_OPERATOR(ope, func, argc) \
rb_define_method(RG_TARGET_NAMESPACE, ope, rg_operator_ ## func, argc)
#define RG_DEF_ATTR(attr, read, write, ex) \
rb_attr(RG_TARGET_NAMESPACE, rb_intern(attr), read, write, ex)
#define RG_DEF_ALIAS(new, old) rb_define_alias(RG_TARGET_NAMESPACE, new, old)
#define RG_REG_GLIBID_SETTER(name) \
rbgobj_register_property_setter(CLASS2GTYPE(RG_TARGET_NAMESPACE), name, rbgutil_glibid_r2g_func)
#define RG_REG_SYMBOL_GETTER(name) \
rbgobj_register_property_getter(CLASS2GTYPE(RG_TARGET_NAMESPACE), name, rbgutil_sym_g2r_func)
#define G_REPLACE_SET_PROPERTY(klass, name, function, args) \
rb_undef_method(klass, "set_" name); \
rb_define_method(klass, "set_" name, function, args); \
rb_undef_method(klass, name "="); \
G_DEF_SETTER(klass, name)
#define G_REPLACE_GET_PROPERTY(klass, name, function, args) \
rb_undef_method(klass, name); \
rb_define_method(klass, name, function, args)
#define G_REPLACE_ACTION(klass, name, function, args) \
rb_undef_method(klass, name); \
rb_define_method(klass, name, function, args)
#define G_SET_PROPERTIES(self, hash) (rbgutil_set_properties(self, hash))
#define G_PROTECT_CALLBACK(func, data) (rbgutil_invoke_callback((VALUE(*)(VALUE))func, (VALUE)data))
#define RBG_STRING_SET_UTF8_ENCODING(string) \
(rbgutil_string_set_utf8_encoding(string))
extern void rbg_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc);
extern void rbg_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc);
extern VALUE rbgutil_def_setters(VALUE klass);
extern void rbgutil_set_properties(VALUE self, VALUE hash);
extern VALUE rbgutil_protect(VALUE (*proc) (VALUE), VALUE data);
extern VALUE rbgutil_invoke_callback(VALUE (*func)(VALUE), VALUE arg);
extern void rbgutil_start_callback_dispatch_thread(void);
extern void rbgutil_stop_callback_dispatch_thread(void);
extern VALUE rbgutil_string_set_utf8_encoding(VALUE string);
extern gboolean rbgutil_key_equal(VALUE rb_string, const char *key);
/*< protected >*/
RUBY_GLIB2_VAR ID rbgutil_id_module_eval;
extern void rbgutil_glibid_r2g_func(VALUE from, GValue* to);
extern VALUE rbgutil_sym_g2r_func(const GValue *from);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __RBGUTIL_H__ */

View File

@ -0,0 +1,274 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2007 Ruby-GNOME2 Project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
#ifdef G_OS_WIN32
# ifdef HAVE_IO_H
# include <io.h>
# define pipe(phandles) _pipe(phandles, 128, _O_BINARY)
# endif
#else
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
#endif
#include <fcntl.h>
#include <errno.h>
#ifndef HAVE_RUBY_NATIVE_THREAD_P
# define ruby_native_thread_p() is_ruby_native_thread()
#endif
static VALUE rbgutil_eGLibCallbackNotInitializedError;
static ID id_exit_application;
/**********************************************************************/
VALUE
rbgutil_protect(VALUE (*func) (VALUE), VALUE data)
{
int state = 0;
VALUE ret = rb_protect(func, data, &state);
VALUE e = rb_errinfo();
if (state && !NIL_P(e))
rb_funcall(mGLib, id_exit_application, 2, e, INT2NUM(EXIT_FAILURE));
return ret;
}
/**********************************************************************/
#ifdef HAVE_NATIVETHREAD
typedef struct _CallbackRequest {
VALUE (*function)(VALUE);
VALUE argument;
VALUE result;
GMutex *done_mutex;
GCond *done_cond;
} CallbackRequest;
static GMutex *callback_dispatch_thread_mutex = NULL;
static GAsyncQueue *callback_request_queue = NULL;
static ID id_callback_dispatch_thread;
static gint callback_pipe_fds[2] = {-1, -1};
#define CALLBACK_PIPE_READY_MESSAGE "R"
#define CALLBACK_PIPE_READY_MESSAGE_SIZE 1
static VALUE
exec_callback(VALUE data)
{
CallbackRequest *request = (CallbackRequest *)data;
return request->function(request->argument);
}
static VALUE
process_request(CallbackRequest *request)
{
g_mutex_lock(request->done_mutex);
request->result = rbgutil_protect(exec_callback, (VALUE)request);
g_cond_signal(request->done_cond);
g_mutex_unlock(request->done_mutex);
return Qnil;
}
static VALUE
mainloop(void)
{
for (;;) {
CallbackRequest *request;
gchar ready_message_buffer[CALLBACK_PIPE_READY_MESSAGE_SIZE];
rb_thread_wait_fd(callback_pipe_fds[0]);
if (read(callback_pipe_fds[0], ready_message_buffer,
CALLBACK_PIPE_READY_MESSAGE_SIZE
) != CALLBACK_PIPE_READY_MESSAGE_SIZE ||
strncmp(ready_message_buffer,
CALLBACK_PIPE_READY_MESSAGE,
CALLBACK_PIPE_READY_MESSAGE_SIZE) != 0) {
g_error("failed to read valid callback dispatcher message");
continue;
}
request = g_async_queue_pop(callback_request_queue);
if (!request)
break;
rb_thread_create(process_request, request);
}
close(callback_pipe_fds[0]);
callback_pipe_fds[0] = -1;
close(callback_pipe_fds[1]);
callback_pipe_fds[1] = -1;
return Qnil;
}
static void
queue_callback_request(CallbackRequest *request)
{
ssize_t written;
g_async_queue_push(callback_request_queue, request);
written = write(callback_pipe_fds[1],
CALLBACK_PIPE_READY_MESSAGE,
CALLBACK_PIPE_READY_MESSAGE_SIZE);
if (written != CALLBACK_PIPE_READY_MESSAGE_SIZE) {
rb_warn("couldn't write all callback pipe ready message: "
"message-size: %d, written: %" G_GSSIZE_FORMAT,
CALLBACK_PIPE_READY_MESSAGE_SIZE,
written);
}
}
static VALUE
invoke_callback_in_ruby_thread(VALUE (*func)(VALUE), VALUE arg)
{
CallbackRequest request;
g_mutex_lock(callback_dispatch_thread_mutex);
if (callback_pipe_fds[0] == -1) {
g_error("Please call rbgutil_start_callback_dispatch_thread() "
"to dispatch a callback from non-ruby thread before "
"callbacks are requested from non-ruby thread.");
g_mutex_unlock(callback_dispatch_thread_mutex);
return Qnil;
}
request.function = func;
request.argument = arg;
request.result = Qnil;
request.done_mutex = g_mutex_new();
request.done_cond = g_cond_new();
g_mutex_lock(request.done_mutex);
queue_callback_request(&request);
g_mutex_unlock(callback_dispatch_thread_mutex);
g_cond_wait(request.done_cond, request.done_mutex);
g_mutex_unlock(request.done_mutex);
g_cond_free(request.done_cond);
g_mutex_free(request.done_mutex);
return request.result;
}
#ifdef HAVE_RB_THREAD_CALL_WITH_GVL
extern void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
static void *
invoke_callback_with_gvl(void *arg)
{
CallbackRequest *req = (CallbackRequest*)arg;
return (void *)rbgutil_protect(req->function, req->argument);
}
#endif
#endif
/**********************************************************************/
VALUE
rbgutil_invoke_callback(VALUE (*func)(VALUE), VALUE arg)
{
#ifdef HAVE_NATIVETHREAD
if (ruby_native_thread_p()) {
# ifdef HAVE_RB_THREAD_BLOCKING_REGION
if (!GPOINTER_TO_INT(g_static_private_get(&rg_polling_key))) {
return rbgutil_protect(func, arg);
}
# endif
# ifdef HAVE_RB_THREAD_CALL_WITH_GVL
{
CallbackRequest req;
req.function = func;
req.argument = arg;
return (VALUE)rb_thread_call_with_gvl(invoke_callback_with_gvl, &req);
}
# endif
} else {
return invoke_callback_in_ruby_thread(func, arg);
}
#endif
return rbgutil_protect(func, arg);
}
/**********************************************************************/
void
rbgutil_start_callback_dispatch_thread(void)
{
#ifdef HAVE_NATIVETHREAD
VALUE callback_dispatch_thread;
g_mutex_lock(callback_dispatch_thread_mutex);
callback_dispatch_thread = rb_ivar_get(mGLib, id_callback_dispatch_thread);
if (NIL_P(callback_dispatch_thread)) {
if (pipe(callback_pipe_fds) == -1)
rb_sys_fail("pipe()");
callback_dispatch_thread = rb_thread_create(mainloop, NULL);
rb_ivar_set(mGLib, id_callback_dispatch_thread,
callback_dispatch_thread);
}
g_mutex_unlock(callback_dispatch_thread_mutex);
#endif
}
void
rbgutil_stop_callback_dispatch_thread(void)
{
#ifdef HAVE_NATIVETHREAD
VALUE callback_dispatch_thread;
g_mutex_lock(callback_dispatch_thread_mutex);
callback_dispatch_thread = rb_ivar_get(mGLib, id_callback_dispatch_thread);
if (!NIL_P(callback_dispatch_thread)) {
queue_callback_request(NULL);
rb_ivar_set(mGLib, id_callback_dispatch_thread, Qnil);
}
g_mutex_unlock(callback_dispatch_thread_mutex);
#endif
}
void
Init_gutil_callback(void)
{
id_exit_application = rb_intern("exit_application");
rbgutil_eGLibCallbackNotInitializedError =
rb_define_class_under(mGLib, "CallbackNotInitializedError",
rb_eRuntimeError);
#ifdef HAVE_NATIVETHREAD
if (!g_thread_supported())
g_thread_init(NULL);
id_callback_dispatch_thread = rb_intern("callback_dispatch_thread");
rb_ivar_set(mGLib, id_callback_dispatch_thread, Qnil);
callback_request_queue = g_async_queue_new();
callback_dispatch_thread_mutex = g_mutex_new();
#endif
}

View File

@ -0,0 +1,173 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
struct list2rval_args {
gpointer list;
RBGRValueFunc conv;
GFreeFunc free_list;
GFreeFunc free_elem;
};
struct list2rval_with_type_args {
struct list2rval_args args;
RBGRValueFuncWithType conv_with_type;
GType gtype;
};
static VALUE
glist2rval_body(VALUE data)
{
struct list2rval_args *args = (struct list2rval_args *)data;
RBGRValueFunc conv = args->conv;
GList *node;
VALUE ary;
ary = rb_ary_new();
if (conv)
for (node = args->list; node; node = g_list_next(node))
rb_ary_push(ary, conv(node->data));
return ary;
}
static VALUE
gslist2rval_body(VALUE data)
{
struct list2rval_args *args = (struct list2rval_args *)data;
RBGRValueFunc conv = args->conv;
GSList *node;
VALUE ary;
ary = rb_ary_new();
if (conv)
for (node = args->list; node; node = g_slist_next(node))
rb_ary_push(ary, conv(node->data));
return ary;
}
static VALUE
glist2rval_with_type_body(VALUE data)
{
struct list2rval_with_type_args *args_with_type = (struct list2rval_with_type_args *)data;
struct list2rval_args *args = (struct list2rval_args *)data;
RBGRValueFuncWithType conv = args_with_type->conv_with_type;
GType gtype = args_with_type->gtype;
GList *node;
VALUE ary;
ary = rb_ary_new();
if (conv)
for (node = args->list; node; node = g_list_next(node))
rb_ary_push(ary, conv(node->data, gtype));
return ary;
}
static VALUE
gslist2rval_with_type_body(VALUE data)
{
struct list2rval_with_type_args *args_with_type = (struct list2rval_with_type_args *)data;
struct list2rval_args *args = (struct list2rval_args *)data;
RBGRValueFuncWithType conv = args_with_type->conv_with_type;
GType gtype = args_with_type->gtype;
GSList *node;
VALUE ary;
ary = rb_ary_new();
if (conv)
for (node = args->list; node; node = g_slist_next(node))
rb_ary_push(ary, conv(node->data, gtype));
return ary;
}
static VALUE
glist2rval_ensure(VALUE data)
{
struct list2rval_args *args = (struct list2rval_args *)data;
GList *node;
if (args->free_elem)
for (node = args->list; node; node = g_list_next(node))
args->free_elem(node->data);
if (args->free_list)
args->free_list(args->list);
return Qnil;
}
static VALUE
gslist2rval_ensure(VALUE data)
{
struct list2rval_args *args = (struct list2rval_args *)data;
GSList *node;
if (args->free_elem)
for (node = args->list; node; node = g_slist_next(node))
args->free_elem(node->data);
if (args->free_list)
args->free_list(args->list);
return Qnil;
}
VALUE
rbg_glist2rval(GList *const list, RBGRValueFunc conv,
GFreeFunc free_list, GFreeFunc free_elem)
{
struct list2rval_args args = {list, conv, free_list, free_elem};
return rb_ensure(glist2rval_body, (VALUE)&args,
glist2rval_ensure, (VALUE)&args);
}
VALUE
rbg_gslist2rval(GSList *const list, RBGRValueFunc conv,
GFreeFunc free_list, GFreeFunc free_elem)
{
struct list2rval_args args = {list, conv, free_list, free_elem};
return rb_ensure(gslist2rval_body, (VALUE)&args,
gslist2rval_ensure, (VALUE)&args);
}
VALUE
rbg_glist2rval_with_type(GList *const list, RBGRValueFuncWithType conv, GType gtype,
GFreeFunc free_list, GFreeFunc free_elem)
{
struct list2rval_with_type_args args = {{list, NULL, free_list, free_elem}, conv, gtype};
return rb_ensure(glist2rval_with_type_body, (VALUE)&args,
glist2rval_ensure, (VALUE)&args);
}
VALUE
rbg_gslist2rval_with_type(GSList *const list, RBGRValueFuncWithType conv, GType gtype,
GFreeFunc free_list, GFreeFunc free_elem)
{
struct list2rval_with_type_args args = {{list, NULL, free_list, free_elem}, conv, gtype};
return rb_ensure(gslist2rval_with_type_body, (VALUE)&args,
gslist2rval_ensure, (VALUE)&args);
}

View File

@ -0,0 +1,85 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGUTIL_LIST_H__
#define __RBGUTIL_LIST_H__
G_BEGIN_DECLS
#define CSTRGLIST2RVAL(list) \
CSTRGLIST2RVAL_FREE(list, NULL, NULL)
#define CSTRGLIST2RVAL_FREE(list, free_list, free_elem) \
rbg_glist2rval(list, (RBGRValueFunc)rbg_cstr2rval, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define CSTRGSLIST2RVAL(list) \
CSTRGSLIST2RVAL_FREE(list, NULL, NULL)
#define CSTRGSLIST2RVAL_FREE(list, free_list, free_elem) \
rbg_gslist2rval(list, (RBGRValueFunc)rbg_cstr2rval, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define FILENAMEGLIST2RVAL(list) \
FILENAMEGLIST2RVAL_FREE(list, NULL, NULL)
#define FILENAMEGLIST2RVAL_FREE(list, free_list, free_elem) \
rbg_glist2rval(list, (RBGRValueFunc)rbg_filename_to_ruby, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define FILENAMEGSLIST2RVAL(list) \
FILENAMEGSLIST2RVAL_FREE(list, NULL, NULL)
#define FILENAMEGSLIST2RVAL_FREE(list, free_list, free_elem) \
rbg_gslist2rval(list, (RBGRValueFunc)rbg_filename_to_ruby, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define GOBJGLIST2RVAL(list) \
GOBJGLIST2RVAL_FREE(list, NULL, NULL)
#define GOBJGLIST2RVAL_FREE(list, free_list, free_elem) \
rbg_glist2rval(list, (RBGRValueFunc)rbgobj_ruby_object_from_instance, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define GOBJGSLIST2RVAL(list) \
GOBJGSLIST2RVAL_FREE(list, NULL, NULL)
#define GOBJGSLIST2RVAL_FREE(list, free_list, free_elem) \
rbg_gslist2rval(list, (RBGRValueFunc)rbgobj_ruby_object_from_instance, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define BOXEDGLIST2RVAL(list, gtype) \
BOXEDGLIST2RVAL_FREE(list, gtype, NULL, NULL)
#define BOXEDGLIST2RVAL_FREE(list, gtype, free_list, free_elem) \
rbg_glist2rval_with_type(list, (RBGRValueFuncWithType)rbgobj_make_boxed, gtype, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
#define BOXEDGSLIST2RVAL(list, gtype) \
BOXEDGSLIST2RVAL_FREE(list, gtype, NULL, NULL)
#define BOXEDGSLIST2RVAL_FREE(list, gtype, free_list, free_elem) \
rbg_gslist2rval_with_type(list, (RBGRValueFuncWithType)rbgobj_make_boxed, gtype, \
(GFreeFunc)free_list, (GFreeFunc)free_elem)
typedef VALUE (*RBGRValueFunc)(gpointer obj);
typedef VALUE (*RBGRValueFuncWithType)(gpointer obj, GType gtype);
extern VALUE rbg_glist2rval(GList *const list, RBGRValueFunc conv,
GFreeFunc free_list, GFreeFunc free_elem);
extern VALUE rbg_gslist2rval(GSList *const list, RBGRValueFunc conv,
GFreeFunc free_list, GFreeFunc free_elem);
extern VALUE rbg_glist2rval_with_type(GList *const list, RBGRValueFuncWithType conv, GType gtype,
GFreeFunc free_list, GFreeFunc free_elem);
extern VALUE rbg_gslist2rval_with_type(GSList *const list, RBGRValueFuncWithType conv, GType gtype,
GFreeFunc free_list, GFreeFunc free_elem);
G_END_DECLS
#endif /* __RBGUTIL_LIST_H__ */

View File

@ -0,0 +1,252 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002-2004 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include "rbgprivate.h"
VALUE
rbgutil_glist2ary(const GList *const list)
{
VALUE ary;
const GList *i;
ary = rb_ary_new();
for (i = list; i != NULL; i = i->next)
rb_ary_push(ary, GOBJ2RVAL(i->data));
return ary;
}
static VALUE
rbgutil_glist2ary_and_free_body(VALUE data)
{
VALUE ary;
GList *i;
ary = rb_ary_new();
for (i = (GList *)data; i != NULL; i = i->next)
rb_ary_push(ary, GOBJ2RVAL(i->data));
return ary;
}
static VALUE
rbgutil_glist2ary_and_free_ensure(VALUE data)
{
g_list_free((GList *)data);
return Qnil;
}
VALUE
rbgutil_glist2ary_and_free(GList *const list)
{
return rb_ensure(rbgutil_glist2ary_and_free_body, (VALUE)list,
rbgutil_glist2ary_and_free_ensure, (VALUE)list);
}
VALUE
rbgutil_glist2ary_boxed(const GList *const list, GType gtype)
{
VALUE ary;
const GList *i;
ary = rb_ary_new();
for (i = list; i != NULL; i = i->next)
rb_ary_push(ary, BOXED2RVAL(i->data, gtype));
return ary;
}
struct rbgutil_glist2ary_boxed_and_free_data
{
GList *const list;
GType gtype;
};
static VALUE
rbgutil_glist2ary_boxed_and_free_body(VALUE data)
{
struct rbgutil_glist2ary_boxed_and_free_data *real;
VALUE ary;
GList *i;
real = (struct rbgutil_glist2ary_boxed_and_free_data *)data;
ary = rb_ary_new();
for (i = real->list; i != NULL; i = i->next)
rb_ary_push(ary, BOXED2RVAL(i->data, real->gtype));
return ary;
}
static VALUE
rbgutil_glist2ary_boxed_and_free_ensure(VALUE data)
{
g_list_free(((struct rbgutil_glist2ary_boxed_and_free_data *)data)->list);
return Qnil;
}
VALUE
rbgutil_glist2ary_boxed_and_free(GList *const list, GType gtype)
{
struct rbgutil_glist2ary_boxed_and_free_data data = { list, gtype };
return rb_ensure(rbgutil_glist2ary_boxed_and_free_body, (VALUE)&data,
rbgutil_glist2ary_boxed_and_free_ensure, (VALUE)&data);
}
VALUE
rbgutil_glist2ary_string(const GList *const list)
{
VALUE ary;
const GList *i;
ary = rb_ary_new();
for (i = list; i != NULL; i = i->next)
rb_ary_push(ary, CSTR2RVAL(i->data));
return ary;
}
static VALUE
rbgutil_glist2ary_string_and_free_body(VALUE data)
{
VALUE ary;
GList *i;
ary = rb_ary_new();
for (i = (GList *)data; i != NULL; i = i->next)
rb_ary_push(ary, CSTR2RVAL(i->data));
return ary;
}
static VALUE
rbgutil_glist2ary_string_and_free_ensure(VALUE data)
{
GList *i;
for (i = (GList *)data; i != NULL; i = i->next)
g_free(i->data);
g_list_free((GList *)data);
return Qnil;
}
VALUE
rbgutil_glist2ary_string_and_free(GList *const list)
{
return rb_ensure(rbgutil_glist2ary_string_and_free_body, (VALUE)list,
rbgutil_glist2ary_string_and_free_ensure, (VALUE)list);
}
VALUE
rbgutil_gslist2ary(const GSList *const list)
{
VALUE ary;
const GSList *i;
ary = rb_ary_new();
for (i = list; i != NULL; i = i->next)
rb_ary_push(ary, GOBJ2RVAL(i->data));
return ary;
}
static VALUE
rbgutil_gslist2ary_and_free_body(VALUE data)
{
VALUE ary;
GSList *i;
ary = rb_ary_new();
for (i = (GSList *)data; i != NULL; i = i->next)
rb_ary_push(ary, GOBJ2RVAL(i->data));
return ary;
}
static VALUE
rbgutil_gslist2ary_and_free_ensure(VALUE data)
{
g_slist_free((GSList *)data);
return Qnil;
}
VALUE
rbgutil_gslist2ary_and_free(GSList *const list)
{
return rb_ensure(rbgutil_gslist2ary_and_free_body, (VALUE)list,
rbgutil_gslist2ary_and_free_ensure, (VALUE)list);
}
VALUE
rbgutil_gslist2ary_boxed(const GSList *const list, GType gtype)
{
VALUE ary;
const GSList *i;
ary = rb_ary_new();
for (i = list; i != NULL; i = i->next)
rb_ary_push(ary, BOXED2RVAL(i->data, gtype));
return ary;
}
struct rbgutil_gslist2ary_boxed_and_free_data
{
GSList *const list;
GType gtype;
};
static VALUE
rbgutil_gslist2ary_boxed_and_free_body(VALUE data)
{
struct rbgutil_gslist2ary_boxed_and_free_data *real;
VALUE ary;
GSList *i;
real = (struct rbgutil_gslist2ary_boxed_and_free_data *)data;
ary = rb_ary_new();
for (i = real->list; i != NULL; i = i->next)
rb_ary_push(ary, BOXED2RVAL(i->data, real->gtype));
return ary;
}
static VALUE
rbgutil_gslist2ary_boxed_and_free_ensure(VALUE data)
{
g_slist_free(((struct rbgutil_gslist2ary_boxed_and_free_data *)data)->list);
return Qnil;
}
VALUE
rbgutil_gslist2ary_boxed_and_free(GSList *const list, GType gtype)
{
struct rbgutil_gslist2ary_boxed_and_free_data data = { list, gtype };
return rb_ensure(rbgutil_gslist2ary_boxed_and_free_body, (VALUE)&data,
rbgutil_gslist2ary_boxed_and_free_ensure, (VALUE)&data);
}

View File

@ -0,0 +1,63 @@
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
/*
* Copyright (C) 2011 Ruby-GNOME2 Project Team
* Copyright (C) 2002,2003 Masao Mutoh
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __RBGUTILDEPRECATED_H__
#define __RBGUTILDEPRECATED_H__
G_BEGIN_DECLS
#define G_DEF_SETTER(klass, name) \
rb_funcall(klass, rbgutil_id_module_eval, 1, rb_str_new2( \
"def " name "=(val); set_" name "(val); val; end\n"))
#define G_DEF_SETTERS(klass) rbgutil_def_setters(klass)
#define GLIST2ARY(list) (rbgutil_glist2ary(list))
#define GLIST2ARY_FREE(list) (rbgutil_glist2ary_and_free(list))
#define GLIST2ARYF(list) (GLIST2ARY_FREE(list))
#define GLIST2ARY2(list, gtype) (rbgutil_glist2ary_boxed(list, gtype))
#define GLIST2ARY2F(list, gtype) (rbgutil_glist2ary_boxed_and_free(list, gtype))
#define GLIST2ARY_STR(list) (rbgutil_glist2ary_string(list))
#define GLIST2ARY_STR_FREE(list) (rbgutil_glist2ary_string_and_free(list))
#define GSLIST2ARY(list) (rbgutil_gslist2ary(list))
#define GSLIST2ARY_FREE(list) (rbgutil_gslist2ary_and_free(list))
#define GSLIST2ARYF(list) (GSLIST2ARY_FREE(list))
#define GSLIST2ARY2(list, gtype) (rbgutil_gslist2ary_boxed(list, gtype))
#define GSLIST2ARY2F(list, gtype) (rbgutil_gslist2ary_boxed_and_free(list, gtype))
#define G_SET_SYMBOL_PROPERTY(gtype, name) \
rbgobj_register_property_getter(gtype, name, rbgutil_sym_g2r_func)
#define G_BLOCK_PROC rb_block_proc
extern VALUE rbgutil_glist2ary(const GList *list);
extern VALUE rbgutil_glist2ary_and_free(GList* list);
extern VALUE rbgutil_glist2ary_boxed(const GList *list, GType gtype);
extern VALUE rbgutil_glist2ary_boxed_and_free(GList *list, GType gtype);
extern VALUE rbgutil_glist2ary_string(const GList *list);
extern VALUE rbgutil_glist2ary_string_and_free(GList *list);
extern VALUE rbgutil_gslist2ary(const GSList *list);
extern VALUE rbgutil_gslist2ary_and_free(GSList *list);
extern VALUE rbgutil_gslist2ary_boxed(const GSList *list, GType gtype);
extern VALUE rbgutil_gslist2ary_boxed_and_free(GSList *list, GType gtype);
G_END_DECLS
#endif /* __RBGUTILDEPRECATED_H__ */