[f-spot] replace our Core by App, on top of unique#



commit 576066e03f7322c3310bbf62ca6abbe17266f903
Author: Stephane Delcroix <stephane delcroix org>
Date:   Thu Nov 5 12:50:58 2009 +0100

    replace our Core by App, on top of unique#
    
    replace the dbus based single instance detection and communication between
    extra instance by unique#. It allows having alternate backends (on systems
    with no dbus) and certainly clean the code of the startup process.

 Makefile.include                                   |    2 +
 configure.ac                                       |    6 +
 extensions/Exporters/FacebookExport/Makefile.am    |   17 +-
 .../Exporters/FlickrExport/FlickrExport.addin.xml  |    4 +-
 extensions/Exporters/FlickrExport/FlickrExport.cs  |    4 +-
 extensions/Exporters/FlickrExport/FlickrRemote.cs  |    4 +-
 extensions/Exporters/FlickrExport/Makefile.am      |    9 +-
 extensions/Exporters/FolderExport/FolderExport.cs  |    4 +-
 extensions/Exporters/FolderExport/Makefile.am      |    1 +
 .../GalleryExport/GalleryExport.addin.xml          |    4 +-
 .../Exporters/GalleryExport/GalleryExport.cs       |    4 +-
 extensions/Exporters/GalleryExport/Makefile.am     |    9 +-
 extensions/Exporters/PicasaWebExport/Makefile.am   |   17 +-
 .../PicasaWebExport/PicasaWebExport.addin.xml      |    4 +-
 .../Exporters/PicasaWebExport/PicasaWebExport.cs   |    4 +-
 extensions/Exporters/SmugMugExport/Makefile.am     |   13 +-
 .../SmugMugExport/SmugMugExport.addin.xml          |    4 +-
 .../Exporters/SmugMugExport/SmugMugExport.cs       |    4 +-
 extensions/Exporters/TabbloExport/Makefile.am      |    1 +
 .../Exporters/TabbloExport/TabbloExport.addin.xml  |    4 +-
 extensions/Exporters/TabbloExport/TabbloExport.cs  |    4 +-
 .../Exporters/TabbloExport/TabbloExportModel.cs    |    2 +-
 extensions/Exporters/ZipExport/Makefile.am         |   13 +-
 .../Services/BeagleService/BeagleService.addin.xml |    4 +-
 extensions/Services/BeagleService/BeagleService.cs |    2 +-
 extensions/Services/DBusService/DBusProxy.cs       |    2 +-
 .../Services/DBusService/DBusService.addin.xml     |    4 +-
 extensions/Services/DBusService/DBusService.cs     |    2 +-
 .../ChangePhotoPath/ChangePhotoPath.addin.xml      |    4 +-
 .../ChangePhotoPath/ChangePhotoPathController.cs   |    2 +-
 .../Tools/DevelopInUFraw/DevelopInUFRaw.addin.xml  |    4 +-
 extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs  |    2 +-
 extensions/Tools/HashJob/HashJob.addin.xml         |    4 +-
 extensions/Tools/HashJob/HashJob.cs                |   14 +-
 .../Tools/LiveWebGallery/GalleryRequestHandler.cs  |    6 +-
 .../Tools/LiveWebGallery/LiveWebGallery.addin.xml  |    4 +-
 .../Tools/LiveWebGallery/LiveWebGalleryDialog.cs   |    8 +-
 .../Tools/LiveWebGallery/PhotoRequestHandler.cs    |    2 +-
 extensions/Tools/MergeDb/MergeDb.addin.xml         |    4 +-
 extensions/Tools/MergeDb/MergeDb.cs                |    2 +-
 extensions/Tools/RawPlusJpeg/RawPlusJpeg.addin.xml |    4 +-
 extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs        |    6 +-
 .../ScreensaverConfig/ScreensaverConfig.addin.xml  |    4 +-
 .../CoverTransition/CoverTransition.addin.xml      |    4 +-
 lib/Makefile.am                                    |    3 +-
 lib/unique-sharp/Makefile.am                       |   17 +
 lib/unique-sharp/generator/AliasGen.cs             |   30 +
 lib/unique-sharp/generator/BoxedGen.cs             |   82 +++
 lib/unique-sharp/generator/ByRefGen.cs             |   63 ++
 lib/unique-sharp/generator/CallbackGen.cs          |  306 ++++++++
 lib/unique-sharp/generator/ChildProperty.cs        |   45 ++
 lib/unique-sharp/generator/ClassBase.cs            |  480 +++++++++++++
 lib/unique-sharp/generator/ClassGen.cs             |   94 +++
 lib/unique-sharp/generator/CodeGenerator.cs        |  122 ++++
 lib/unique-sharp/generator/ConstFilenameGen.cs     |   52 ++
 lib/unique-sharp/generator/ConstStringGen.cs       |   59 ++
 lib/unique-sharp/generator/Ctor.cs                 |  165 +++++
 lib/unique-sharp/generator/EnumGen.cs              |  127 ++++
 lib/unique-sharp/generator/FieldBase.cs            |  270 ++++++++
 lib/unique-sharp/generator/GenBase.cs              |  142 ++++
 lib/unique-sharp/generator/GenerationInfo.cs       |  188 +++++
 lib/unique-sharp/generator/HandleBase.cs           |   81 +++
 lib/unique-sharp/generator/IAccessor.cs            |   29 +
 lib/unique-sharp/generator/IGeneratable.cs         |   71 ++
 lib/unique-sharp/generator/IManualMarshaler.cs     |   32 +
 lib/unique-sharp/generator/InterfaceGen.cs         |  384 +++++++++++
 lib/unique-sharp/generator/LPGen.cs                |   58 ++
 lib/unique-sharp/generator/LPUGen.cs               |   58 ++
 lib/unique-sharp/generator/ManagedCallString.cs    |  152 ++++
 lib/unique-sharp/generator/ManualGen.cs            |   58 ++
 lib/unique-sharp/generator/MarshalGen.cs           |   56 ++
 lib/unique-sharp/generator/Method.cs               |  304 ++++++++
 lib/unique-sharp/generator/MethodBase.cs           |  184 +++++
 lib/unique-sharp/generator/MethodBody.cs           |  177 +++++
 lib/unique-sharp/generator/ObjectBase.cs           |   36 +
 lib/unique-sharp/generator/ObjectField.cs          |   48 ++
 lib/unique-sharp/generator/ObjectGen.cs            |  425 ++++++++++++
 lib/unique-sharp/generator/OpaqueGen.cs            |  237 +++++++
 lib/unique-sharp/generator/Parameters.cs           |  728 ++++++++++++++++++++
 lib/unique-sharp/generator/Parser.cs               |  170 +++++
 lib/unique-sharp/generator/Property.cs             |  193 ++++++
 lib/unique-sharp/generator/PropertyBase.cs         |  122 ++++
 lib/unique-sharp/generator/ReturnValue.cs          |  170 +++++
 lib/unique-sharp/generator/Signal.cs               |  587 ++++++++++++++++
 lib/unique-sharp/generator/Signature.cs            |  123 ++++
 lib/unique-sharp/generator/SimpleBase.cs           |  121 ++++
 lib/unique-sharp/generator/SimpleGen.cs            |   31 +
 lib/unique-sharp/generator/Statistics.cs           |  197 ++++++
 lib/unique-sharp/generator/StructBase.cs           |  230 ++++++
 lib/unique-sharp/generator/StructField.cs          |  149 ++++
 lib/unique-sharp/generator/StructGen.cs            |   53 ++
 lib/unique-sharp/generator/SymbolTable.cs          |  412 +++++++++++
 lib/unique-sharp/generator/VMSignature.cs          |   75 ++
 lib/unique-sharp/generator/VirtualMethod.cs        |  168 +++++
 lib/unique-sharp/unique/App.custom                 |  104 +++
 lib/unique-sharp/unique/AssemblyInfo.cs            |    7 +
 lib/unique-sharp/unique/Makefile.am                |   62 ++
 lib/unique-sharp/unique/MessageData.custom         |   54 ++
 lib/unique-sharp/unique/MessageReceivedHandler.cs  |   37 +
 lib/unique-sharp/unique/Unique.metadata            |   18 +
 lib/unique-sharp/unique/snk                        |  Bin 0 -> 596 bytes
 lib/unique-sharp/unique/unique-api.raw             |  143 ++++
 lib/unique-sharp/unique/unique-sharp.dll.config    |    4 +
 src/.gitignore                                     |    2 +
 src/Core.cs                                        |  287 --------
 src/Core/App.cs                                    |  340 +++++++++
 src/Editors/Editor.cs                              |    2 +-
 src/FSpot.addin.xml                                |    4 +-
 src/FileImportBackend.cs                           |    4 +-
 src/Jobs/CalculateHashJob.cs                       |    4 +-
 src/Jobs/SyncMetadataJob.cs                        |    2 +-
 src/MainWindow.cs                                  |   45 ++-
 src/Makefile.am                                    |    3 +-
 src/PhotoStore.cs                                  |   10 +-
 src/Query/HiddenTag.cs                             |    2 +-
 src/Sharpener.cs                                   |    2 +-
 src/SingleView.cs                                  |   26 +-
 src/TagStore.cs                                    |   12 +-
 src/Term.cs                                        |    2 +-
 src/Widgets/IconView.cs                            |    2 +-
 src/f-spot.in                                      |    2 +-
 src/main.cs                                        |  201 ++----
 122 files changed, 9178 insertions(+), 593 deletions(-)
---
diff --git a/Makefile.include b/Makefile.include
index f7cd9a4..e41ff8f 100644
--- a/Makefile.include
+++ b/Makefile.include
@@ -17,6 +17,7 @@ DIR_SEMWEB = $(top_builddir)/lib/semweb
 DIR_SRC = $(top_builddir)/src
 DIR_GIOSHARP = $(top_builddir)/lib/gio-sharp/gio
 DIR_GTKSHARPBEANS = $(top_builddir)/lib/gtk-sharp-beans
+DIR_UNIQUESHARP = $(top_builddir)/lib/unique-sharp/unique
 
 ## Links
 
@@ -29,6 +30,7 @@ LINK_MONO_ADDINS =					\
 LINK_SEMWEB = -r:$(DIR_SEMWEB)/SemWeb.dll
 LINK_GIOSHARP = -r:$(DIR_GIOSHARP)/gio-sharp.dll
 LINK_GTKSHARPBEANS = -r:$(DIR_GTKSHARPBEANS)/gtk-sharp-beans.dll
+LINK_UNIQUESHARP = -r:$(DIR_UNIQUESHARP)/unique-sharp.dll
 
 ## Build
 
diff --git a/configure.ac b/configure.ac
index e5ef001..75acfd6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -219,6 +219,9 @@ AC_SUBST(EXIF_LIBS)
 PKG_CHECK_MODULES(LIBEXIF_VERSION_CHECK, libexif >= 0.6.12, EXIF_SOVERSION=12, EXIF_SOVERSION=10)
 AC_SUBST(EXIF_SOVERSION)
 
+dnl --- libunique check
+PKG_CHECK_MODULES(UNIQUE, unique-1.0 >= 1.0)
+
 dnl --- Set up paths
 
 AC_ARG_WITH(turtle, [ --with-turtle=DIR                set path to source directory for turtle])
@@ -307,6 +310,9 @@ lib/mono-addins/Mono.Addins.Gui/Makefile
 lib/mono-addins/Mono.Addins/Makefile
 lib/mono-addins/Mono.Addins.Setup/Makefile
 lib/semweb/Makefile
+lib/unique-sharp/Makefile
+lib/unique-sharp/generator/Makefile
+lib/unique-sharp/unique/Makefile
 docs/Makefile
 icons/Makefile
 tools/Makefile
diff --git a/extensions/Exporters/FacebookExport/Makefile.am b/extensions/Exporters/FacebookExport/Makefile.am
index 2544555..a9aa972 100644
--- a/extensions/Exporters/FacebookExport/Makefile.am
+++ b/extensions/Exporters/FacebookExport/Makefile.am
@@ -30,18 +30,19 @@ PLUGIN_SOURCES =			\
 	$(srcdir)/Mono.Facebook/User.cs			\
 	$(srcdir)/Mono.Facebook/Util.cs
 
-REFS =					\
+REFS =							\
 	-r:$(top_builddir)/src/f-spot.exe		\
-	-r:$(top_builddir)/src/FSpot.Core.dll	\
-	-r:$(top_builddir)/src/FSpot.Utils.dll	\
+	-r:$(top_builddir)/src/FSpot.Core.dll		\
+	-r:$(top_builddir)/src/FSpot.Utils.dll		\
 	-r:$(top_builddir)/src/FSpot.Platform.dll	\
 	-r:$(top_builddir)/src/FSpot.Widgets.dll	\
 	$(LINK_GTKSHARPBEANS)				\
-	$(LINK_KEYRING)                     \
-	$(LINK_MONO_ADDINS)					\
-	$(LINK_SEMWEB)						\
-	$(LINK_GPHOTO2)						\
-	$(LINK_GIOSHARP)						\
+	$(LINK_KEYRING)                     		\
+	$(LINK_MONO_ADDINS)				\
+	$(LINK_SEMWEB)					\
+	$(LINK_GPHOTO2)					\
+	$(LINK_GIOSHARP)				\
+	$(LINK_UNIQUESHARP)				\
 	-r:Mono.Posix
 
 PKGS =					\
diff --git a/extensions/Exporters/FlickrExport/FlickrExport.addin.xml b/extensions/Exporters/FlickrExport/FlickrExport.addin.xml
index 5a3447a..192f120 100644
--- a/extensions/Exporters/FlickrExport/FlickrExport.addin.xml
+++ b/extensions/Exporters/FlickrExport/FlickrExport.addin.xml
@@ -1,5 +1,5 @@
 <Addin namespace="FSpot"
-	version="0.6.0.1"
+	version="0.7.0.0"
 	name="Flickr Export"
 	description="This extension allows you to export your photos to Flickr and 23hq."
 	author="F-Spot team"
@@ -8,7 +8,7 @@
 	category="Export">
 
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 
 	<Extension path = "/FSpot/Menus/Exports">
diff --git a/extensions/Exporters/FlickrExport/FlickrExport.cs b/extensions/Exporters/FlickrExport/FlickrExport.cs
index a677505..6bb4727 100644
--- a/extensions/Exporters/FlickrExport/FlickrExport.cs
+++ b/extensions/Exporters/FlickrExport/FlickrExport.cs
@@ -357,8 +357,8 @@ namespace FSpotFlickrExport {
 					string id = fr.Upload (photo, stack, is_public, is_family, is_friend);
 					ids.Add (id);
 
-					if (Core.Database != null && photo is FSpot.Photo)
-						Core.Database.Exports.Create ((photo as FSpot.Photo).Id,
+					if (App.Instance.Database != null && photo is FSpot.Photo)
+						App.Instance.Database.Exports.Create ((photo as FSpot.Photo).Id,
 									      (photo as FSpot.Photo).DefaultVersionId,
 									      ExportStore.FlickrExportType,
 									      auth.User.UserId + ":" + auth.User.Username + ":" + current_service.Name + ":" + id);
diff --git a/extensions/Exporters/FlickrExport/FlickrRemote.cs b/extensions/Exporters/FlickrExport/FlickrRemote.cs
index fbe42c1..bb84d6e 100644
--- a/extensions/Exporters/FlickrExport/FlickrRemote.cs
+++ b/extensions/Exporters/FlickrExport/FlickrRemote.cs
@@ -159,9 +159,9 @@ public class FlickrRemote {
 						// Go through the tag parents
 						if (ExportTagHierarchy) {
 							tag_iter = t[i].Category;
-							while (tag_iter != Core.Database.Tags.RootCategory && tag_iter != null) {
+							while (tag_iter != App.Instance.Database.Tags.RootCategory && tag_iter != null) {
 								// Skip top level tags because they have no meaning in a linear tag database
-								if (ExportIgnoreTopLevel && tag_iter.Category == Core.Database.Tags.RootCategory) {
+								if (ExportIgnoreTopLevel && tag_iter.Category == App.Instance.Database.Tags.RootCategory) {
 									break;
 								}
 
diff --git a/extensions/Exporters/FlickrExport/Makefile.am b/extensions/Exporters/FlickrExport/Makefile.am
index 4942570..ec40c02 100644
--- a/extensions/Exporters/FlickrExport/Makefile.am
+++ b/extensions/Exporters/FlickrExport/Makefile.am
@@ -10,15 +10,16 @@ PLUGIN_SOURCES =			\
 	$(srcdir)/FlickrExport.cs	\
 	$(srcdir)/FlickrRemote.cs
 
-REFS =					\
-	-r:$(top_builddir)/src/f-spot.exe		\
+REFS =						\
+	-r:$(top_builddir)/src/f-spot.exe	\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
 	$(LINK_SEMWEB)				\
 	$(LINK_MONO_ADDINS)			\
 	$(LINK_GPHOTO2)				\
-	$(LINK_GIOSHARP)				\
-	$(LINK_GTKSHARPBEANS)		\
+	$(LINK_GIOSHARP)			\
+	$(LINK_GTKSHARPBEANS)			\
+	$(LINK_UNIQUESHARP)			\
 	-r:FlickrNet/FlickrNet.dll	\
 	-r:Mono.Posix
 
diff --git a/extensions/Exporters/FolderExport/FolderExport.cs b/extensions/Exporters/FolderExport/FolderExport.cs
index 4bdc338..b280644 100644
--- a/extensions/Exporters/FolderExport/FolderExport.cs
+++ b/extensions/Exporters/FolderExport/FolderExport.cs
@@ -532,8 +532,8 @@ namespace FSpotFolderExport {
 				else
 					File.Copy (request.Current.LocalPath, path, true);
 
-				if (photo != null && photo is Photo && Core.Database != null) {
-					Core.Database.Exports.Create ((photo as Photo).Id, (photo as Photo).DefaultVersionId,
+				if (photo != null && photo is Photo && App.Instance.Database != null) {
+					App.Instance.Database.Exports.Create ((photo as Photo).Id, (photo as Photo).DefaultVersionId,
 								      ExportStore.FolderExportType,
 								      // FIXME this is wrong, the final path is the one
 								      // after the Xfer.
diff --git a/extensions/Exporters/FolderExport/Makefile.am b/extensions/Exporters/FolderExport/Makefile.am
index 704a481..9a51e13 100644
--- a/extensions/Exporters/FolderExport/Makefile.am
+++ b/extensions/Exporters/FolderExport/Makefile.am
@@ -18,6 +18,7 @@ REFS =					\
 	$(LINK_GPHOTO2)				\
 	$(LINK_GIOSHARP)				\
 	$(LINK_GTKSHARPBEANS)		\
+	$(LINK_UNIQUESHARP)		\
 	-r:System.Web			\
 	-r:ICSharpCode.SharpZipLib	\
 	-r:Mono.Posix
diff --git a/extensions/Exporters/GalleryExport/GalleryExport.addin.xml b/extensions/Exporters/GalleryExport/GalleryExport.addin.xml
index 744a5b4..d1998e4 100644
--- a/extensions/Exporters/GalleryExport/GalleryExport.addin.xml
+++ b/extensions/Exporters/GalleryExport/GalleryExport.addin.xml
@@ -1,5 +1,5 @@
 <Addin namespace="FSpot"
-	version="0.6.0.1"
+	version="0.7.0.0"
 	name="Gallery Export"
 	description="This extension allows you to export your photos to PHP Gallery (http://gallery.menalto.com)."
 	author="F-Spot team"
@@ -8,7 +8,7 @@
 	category="Export">
 
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 
 	<Extension path = "/FSpot/Menus/Exports">
diff --git a/extensions/Exporters/GalleryExport/GalleryExport.cs b/extensions/Exporters/GalleryExport/GalleryExport.cs
index 48474b5..01ef34e 100644
--- a/extensions/Exporters/GalleryExport/GalleryExport.cs
+++ b/extensions/Exporters/GalleryExport/GalleryExport.cs
@@ -787,8 +787,8 @@ namespace G2Export {
 					try {
 						int id = album.Add (item, req.Current.LocalPath);
 
-						if (item != null && item is Photo && Core.Database != null && id != 0) {
-							Core.Database.Exports.Create ((item as Photo).Id, (item as Photo).DefaultVersionId,
+						if (item != null && item is Photo && App.Instance.Database != null && id != 0) {
+							App.Instance.Database.Exports.Create ((item as Photo).Id, (item as Photo).DefaultVersionId,
 										      ExportStore.Gallery2ExportType,
 										      String.Format("{0}:{1}",album.Gallery.Uri.ToString (), id.ToString ()));
 						}
diff --git a/extensions/Exporters/GalleryExport/Makefile.am b/extensions/Exporters/GalleryExport/Makefile.am
index 55bfdfa..ee31a30 100644
--- a/extensions/Exporters/GalleryExport/Makefile.am
+++ b/extensions/Exporters/GalleryExport/Makefile.am
@@ -10,15 +10,16 @@ PLUGIN_SOURCES =			\
 	$(srcdir)/GalleryExport.cs	\
 	$(srcdir)/GalleryRemote.cs
 
-REFS =					\
-	-r:$(top_builddir)/src/f-spot.exe		\
+REFS =						\
+	-r:$(top_builddir)/src/f-spot.exe	\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
 	$(LINK_SEMWEB)				\
 	$(LINK_MONO_ADDINS)			\
 	$(LINK_GPHOTO2)				\
-	$(LINK_GIOSHARP)				\
-	$(LINK_GTKSHARPBEANS)		\
+	$(LINK_GIOSHARP)			\
+	$(LINK_GTKSHARPBEANS)			\
+	$(LINK_UNIQUESHARP)			\
 	-r:Mono.Posix
 
 PKGS =					\
diff --git a/extensions/Exporters/PicasaWebExport/Makefile.am b/extensions/Exporters/PicasaWebExport/Makefile.am
index 4f7732f..e28fcb3 100644
--- a/extensions/Exporters/PicasaWebExport/Makefile.am
+++ b/extensions/Exporters/PicasaWebExport/Makefile.am
@@ -9,17 +9,18 @@ PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
 PLUGIN_SOURCES =			\
 	$(srcdir)/PicasaWebExport.cs
 
-REFS =					\
-	-r:$(top_builddir)/src/f-spot.exe		\
+REFS =						\
+	-r:$(top_builddir)/src/f-spot.exe	\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
-	$(LINK_SEMWEB)			\
-	-r:google-sharp/Mono.Google.dll	\
-	$(LINK_KEYRING)			\
-	$(LINK_MONO_ADDINS)		\
+	$(LINK_SEMWEB)				\
+	-r:google-sharp/Mono.Google.dll		\
+	$(LINK_KEYRING)				\
+	$(LINK_MONO_ADDINS)			\
 	$(LINK_GIOSHARP)			\
-	$(LINK_GPHOTO2)			\
-	-r:System.Web			\
+	$(LINK_GPHOTO2)				\
+	$(LINK_UNIQUESHARP)			\
+	-r:System.Web				\
 	-r:Mono.Posix
 
 PKGS =					\
diff --git a/extensions/Exporters/PicasaWebExport/PicasaWebExport.addin.xml b/extensions/Exporters/PicasaWebExport/PicasaWebExport.addin.xml
index dea05ec..880cedf 100644
--- a/extensions/Exporters/PicasaWebExport/PicasaWebExport.addin.xml
+++ b/extensions/Exporters/PicasaWebExport/PicasaWebExport.addin.xml
@@ -1,5 +1,5 @@
 <Addin namespace="FSpot"
-	version="0.6.0.3"
+	version="0.7.0.0"
 	name="PicasaWeb Export"
 	description="This extension allows you to export your photos to PicasaWeb."
 	author="F-Spot team"
@@ -8,7 +8,7 @@
 	category="Export">
 
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 
 	<Extension path = "/FSpot/Menus/Exports">
diff --git a/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs b/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs
index 000144b..4c12a69 100644
--- a/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs
+++ b/extensions/Exporters/PicasaWebExport/PicasaWebExport.cs
@@ -674,8 +674,8 @@ namespace FSpotGoogleExport {
 						picture = album.UploadPicture (request.Current.LocalPath, Path.ChangeExtension (item.Name, "jpg"), item.Description);
 						sent_bytes += file_info.Length;
 					}
-					if (Core.Database != null && item is Photo)
-						Core.Database.Exports.Create ((item as Photo).Id,
+					if (App.Instance.Database != null && item is Photo)
+						App.Instance.Database.Exports.Create ((item as Photo).Id,
 									      (item as Photo).DefaultVersionId,
 									      ExportStore.PicasaExportType,
 									      picture.Link);
diff --git a/extensions/Exporters/SmugMugExport/Makefile.am b/extensions/Exporters/SmugMugExport/Makefile.am
index 39f0fc7..6537aae 100644
--- a/extensions/Exporters/SmugMugExport/Makefile.am
+++ b/extensions/Exporters/SmugMugExport/Makefile.am
@@ -9,17 +9,18 @@ PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
 PLUGIN_SOURCES =			\
 	$(srcdir)/SmugMugExport.cs
 
-REFS =					\
-	-r:$(top_builddir)/src/f-spot.exe		\
+REFS =						\
+	-r:$(top_builddir)/src/f-spot.exe	\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
-	-r:SmugMugNet/SmugMugNet.dll	\
+	-r:SmugMugNet/SmugMugNet.dll		\
 	$(LINK_SEMWEB)				\
 	$(LINK_MONO_ADDINS)			\
-	$(LINK_GIOSHARP)		\
+	$(LINK_GIOSHARP)			\
 	$(LINK_GPHOTO2)				\
-	$(LINK_GTKSHARPBEANS)		\
-	$(LINK_KEYRING)			\
+	$(LINK_GTKSHARPBEANS)			\
+	$(LINK_KEYRING)				\
+	$(LINK_UNIQUESHARP)			\
 	-r:Mono.Posix
 
 PKGS =					\
diff --git a/extensions/Exporters/SmugMugExport/SmugMugExport.addin.xml b/extensions/Exporters/SmugMugExport/SmugMugExport.addin.xml
index e7a2c09..3b624d9 100644
--- a/extensions/Exporters/SmugMugExport/SmugMugExport.addin.xml
+++ b/extensions/Exporters/SmugMugExport/SmugMugExport.addin.xml
@@ -1,5 +1,5 @@
 <Addin namespace="FSpot"
-	version="0.6.0.2"
+	version="0.7.0.0"
 	name="SmugMug Export"
 	description="This extension allows you to export your photos to SmugMug."
 	author="F-Spot team"
@@ -8,7 +8,7 @@
 	category="Export">
 
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 
 	<Extension path = "/FSpot/Menus/Exports">
diff --git a/extensions/Exporters/SmugMugExport/SmugMugExport.cs b/extensions/Exporters/SmugMugExport/SmugMugExport.cs
index c0987ea..7c935ea 100644
--- a/extensions/Exporters/SmugMugExport/SmugMugExport.cs
+++ b/extensions/Exporters/SmugMugExport/SmugMugExport.cs
@@ -580,8 +580,8 @@ namespace FSpotSmugMugExport {
 						approx_size = sent_bytes * items.Length / (photo_index - 1);
 
 					int image_id = account.SmugMug.Upload (request.Current.LocalPath, album.AlbumID);
-					if (Core.Database != null && item is Photo && image_id >= 0)
-						Core.Database.Exports.Create ((item as Photo).Id,
+					if (App.Instance.Database != null && item is Photo && image_id >= 0)
+						App.Instance.Database.Exports.Create ((item as Photo).Id,
 									      (item as Photo).DefaultVersionId,
 									      ExportStore.SmugMugExportType,
 									      account.SmugMug.GetAlbumUrl (image_id).ToString ());
diff --git a/extensions/Exporters/TabbloExport/Makefile.am b/extensions/Exporters/TabbloExport/Makefile.am
index 99b300b..abce7f5 100644
--- a/extensions/Exporters/TabbloExport/Makefile.am
+++ b/extensions/Exporters/TabbloExport/Makefile.am
@@ -35,6 +35,7 @@ REFS = \
 	$(LINK_GIOSHARP)	\
 	$(LINK_GTKSHARPBEANS)	\	
 	$(LINK_GPHOTO2)		\
+	$(LINK_UNIQUESHARP)	\
 	-r:Mono.Posix.dll
 
 PKGS = \
diff --git a/extensions/Exporters/TabbloExport/TabbloExport.addin.xml b/extensions/Exporters/TabbloExport/TabbloExport.addin.xml
index d78cc17..04e3307 100644
--- a/extensions/Exporters/TabbloExport/TabbloExport.addin.xml
+++ b/extensions/Exporters/TabbloExport/TabbloExport.addin.xml
@@ -1,5 +1,5 @@
 <Addin namespace="FSpot"
-	version="0.6.1.3"
+	version="0.7.0.0"
 	name="Tabblo Export"
 	description="This extension allows you to export your photos to Tabblo."
  	author="Wojciech Dzierżanowski"
@@ -7,7 +7,7 @@
 	category="Export">
 
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 
 	<Extension path = "/FSpot/Menus/Exports">
diff --git a/extensions/Exporters/TabbloExport/TabbloExport.cs b/extensions/Exporters/TabbloExport/TabbloExport.cs
index a5ea18e..6d05ba8 100644
--- a/extensions/Exporters/TabbloExport/TabbloExport.cs
+++ b/extensions/Exporters/TabbloExport/TabbloExport.cs
@@ -252,7 +252,7 @@ namespace FSpotTabbloExport {
 
 		private FSpot.Tag [] SelectTags ()
 		{
-			TagStore tag_store = FSpot.Core.Database.Tags;
+			TagStore tag_store = FSpot.App.Instance.Database.Tags;
 			TagSelectionDialog tagDialog =
 					new TagSelectionDialog (tag_store);
 			FSpot.Tag [] tags = tagDialog.Run ();
@@ -371,7 +371,7 @@ namespace FSpotTabbloExport {
 				return;
 			}
 
-			PhotoStore photo_store = FSpot.Core.Database.Photos;
+			PhotoStore photo_store = FSpot.App.Instance.Database.Photos;
 			FSpot.Photo photo = photo_store.GetByUri (
 					item.DefaultVersionUri);
 			Debug.Assert (null != photo);
diff --git a/extensions/Exporters/TabbloExport/TabbloExportModel.cs b/extensions/Exporters/TabbloExport/TabbloExportModel.cs
index 6c0eab7..aca8abf 100644
--- a/extensions/Exporters/TabbloExport/TabbloExportModel.cs
+++ b/extensions/Exporters/TabbloExport/TabbloExportModel.cs
@@ -362,7 +362,7 @@ namespace FSpotTabbloExport {
 			List <FSpot.Tag> tags =
 					new List <FSpot.Tag> (ids.Length);
 			foreach (int id in ids) {
-				FSpot.Tag tag = FSpot.Core.Database.Tags
+				FSpot.Tag tag = FSpot.App.Instance.Database.Tags
 						.GetTagById (id);
 				if (null != tag) {
 					tags.Add (tag);
diff --git a/extensions/Exporters/ZipExport/Makefile.am b/extensions/Exporters/ZipExport/Makefile.am
index 32deeab..7149e14 100644
--- a/extensions/Exporters/ZipExport/Makefile.am
+++ b/extensions/Exporters/ZipExport/Makefile.am
@@ -9,17 +9,18 @@ PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
 PLUGIN_SOURCES =			\
 	$(srcdir)/ZipExport.cs
 
-REFS =					\
-	-r:$(top_builddir)/src/f-spot.exe		\
+REFS =						\
+	-r:$(top_builddir)/src/f-spot.exe	\
 	-r:$(top_builddir)/src/FSpot.Core.dll	\
 	-r:$(top_builddir)/src/FSpot.Utils.dll	\
 	$(LINK_SEMWEB)				\
 	$(LINK_MONO_ADDINS)			\
 	$(LINK_GPHOTO2)				\
-	$(LINK_GTKSHARPBEANS)		\
-	$(LINK_GIOSHARP)		\
-	-r:System.Web			\
-	-r:ICSharpCode.SharpZipLib	\
+	$(LINK_GTKSHARPBEANS)			\
+	$(LINK_GIOSHARP)			\
+	$(LINK_UNIQUESHARP)			\
+	-r:System.Web				\
+	-r:ICSharpCode.SharpZipLib		\
 	-r:Mono.Posix
 
 PKGS =					\
diff --git a/extensions/Services/BeagleService/BeagleService.addin.xml b/extensions/Services/BeagleService/BeagleService.addin.xml
index 3349c25..9a2a29c 100644
--- a/extensions/Services/BeagleService/BeagleService.addin.xml
+++ b/extensions/Services/BeagleService/BeagleService.addin.xml
@@ -1,13 +1,13 @@
 <Addin namespace="FSpot"
 	id="BeagleService"
-	version="0.6.1"
+	version="0.7.0.0"
 	name="Beagle Service"
 	description="Notify Beagle on image changes"
 	author="Stephane Delcroix"
 	url="http://f-spot.org/Extensions";
 	category="Services">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Services">
 		<Service class="BeagleService.BeagleService"/>
diff --git a/extensions/Services/BeagleService/BeagleService.cs b/extensions/Services/BeagleService/BeagleService.cs
index c858cfb..a8c19a6 100644
--- a/extensions/Services/BeagleService/BeagleService.cs
+++ b/extensions/Services/BeagleService/BeagleService.cs
@@ -20,7 +20,7 @@ namespace BeagleService {
 		{
 			uint timer = Log.InformationTimerStart ("Starting BeagleService");
 			try {
-				Core.Database.Photos.ItemsChanged += HandleDbItemsChanged;
+				App.Instance.Database.Photos.ItemsChanged += HandleDbItemsChanged;
 			} catch {
 				Log.Warning ("unable to hook the BeagleNotifier. are you running --view mode?");
 			}
diff --git a/extensions/Services/DBusService/DBusProxy.cs b/extensions/Services/DBusService/DBusProxy.cs
index 549c5f8..d8036c0 100644
--- a/extensions/Services/DBusService/DBusProxy.cs
+++ b/extensions/Services/DBusService/DBusProxy.cs
@@ -241,7 +241,7 @@ namespace DBusService {
 
 			try {
 				// remove tags from photos first
-				Core.Database.Photos.Remove (new Tag [] { t });
+				App.Instance.Database.Photos.Remove (new Tag [] { t });
 				// then remove tag
 				tag_store.Remove (t);
 				return true;
diff --git a/extensions/Services/DBusService/DBusService.addin.xml b/extensions/Services/DBusService/DBusService.addin.xml
index 919b5c7..73ca21f 100644
--- a/extensions/Services/DBusService/DBusService.addin.xml
+++ b/extensions/Services/DBusService/DBusService.addin.xml
@@ -1,6 +1,6 @@
 <Addin namespace="FSpot"
 	id="DBusService"
-	version="0.6"
+	version="0.7"
 	name="DBus Service"
 	description="Expose F-Spot Photos over DBus"
 	author="Thomas Van Machelen"
@@ -8,7 +8,7 @@
 	defaultEnabled="false"
 	category="Services">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Services">
 		<Service class="DBusService.DBusService"/>
diff --git a/extensions/Services/DBusService/DBusService.cs b/extensions/Services/DBusService/DBusService.cs
index 3d333a4..b7374db 100644
--- a/extensions/Services/DBusService/DBusService.cs
+++ b/extensions/Services/DBusService/DBusService.cs
@@ -20,7 +20,7 @@ namespace DBusService {
 		{
 			uint timer = Log.InformationTimerStart ("Starting DBusService");
 			try {
-				DBusProxyFactory.Load (Core.Database);
+				DBusProxyFactory.Load (App.Instance.Database);
 			} catch {
 				Log.Warning ("unable init DBus service");
 			}
diff --git a/extensions/Tools/ChangePhotoPath/ChangePhotoPath.addin.xml b/extensions/Tools/ChangePhotoPath/ChangePhotoPath.addin.xml
index a0127bf..f8e134b 100644
--- a/extensions/Tools/ChangePhotoPath/ChangePhotoPath.addin.xml
+++ b/extensions/Tools/ChangePhotoPath/ChangePhotoPath.addin.xml
@@ -1,6 +1,6 @@
 <Addin namespace="FSpot"
         id="ChangePath"
-        version="0.6"
+        version="0.7"
         name="ChangePath"
         description="UNSTABLE - Please ensure you have a backup of your photos.db before you test this extension. This extension will allow you to change the base path to the your photos. It is very handy if you move your photos from ~/Photos to /OurPhotos for instance. Just ensure you let SqLite continue to process the changes for up to a few hours after f-spot reports finished. It will only change the path to photos which are located under the Photo directory."
         author="Bengt Thuree"
@@ -8,7 +8,7 @@
         category="Tools"
 	defaultEnabled="false">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/Tools">
 		<Command id="FileList" _label = "Change path to photos" command_type = "ChangePhotoPath.Dump" />
diff --git a/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs b/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs
index 093671f..01d78be 100644
--- a/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs
+++ b/extensions/Tools/ChangePhotoPath/ChangePhotoPathController.cs
@@ -39,7 +39,7 @@ namespace ChangePhotoPath
 
 	public class ChangePathController
 	{
-		PhotoStore photo_store = FSpot.Core.Database.Photos;
+		PhotoStore photo_store = FSpot.App.Instance.Database.Photos;
 		ArrayList photo_id_array, version_id_array;
 		StringCollection old_path_array, new_path_array;
 		int total_photos;
diff --git a/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.addin.xml b/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.addin.xml
index 4881868..56381aa 100644
--- a/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.addin.xml
+++ b/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.addin.xml
@@ -1,6 +1,6 @@
 <Addin namespace="FSpot"
 	id="DevelopInUFraw"
-	version="0.6.0.2"
+	version="0.7.0.0"
 	name="DevelopInUFRaw"
 	description="Develop the image in UFRaw, saves the result as a new version\n\nNote: Require ufraw 0.13 or CVS version newer than 2007-09-06 !!!"
 	author="Stephane Delcroix"
@@ -8,7 +8,7 @@
 	category="Tools"
 	defaultEnabled="false">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/PhotoPopup">
 		<Command id = "DevelopInUFRaw" _label = "Develop in UFRaw" command_type = "DevelopInUFRawExtension.DevelopInUFRaw" insertbefore="OpenWith"/>
diff --git a/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs b/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs
index e7d350c..97ad4da 100644
--- a/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs
+++ b/extensions/Tools/DevelopInUFraw/DevelopInUFRaw.cs
@@ -150,7 +150,7 @@ namespace DevelopInUFRawExtension
 
 			p.DefaultVersionId = p.AddVersion (developed, name, true);
 			p.Changes.DataChanged = true;
-			Core.Database.Photos.Commit (p);
+			App.Instance.Database.Photos.Commit (p);
 		}
 
 		private static string GetVersionName (Photo p)
diff --git a/extensions/Tools/HashJob/HashJob.addin.xml b/extensions/Tools/HashJob/HashJob.addin.xml
index afa6be7..a31ff56 100644
--- a/extensions/Tools/HashJob/HashJob.addin.xml
+++ b/extensions/Tools/HashJob/HashJob.addin.xml
@@ -1,13 +1,13 @@
 <Addin namespace="FSpot"
 	id="HashJob"
-	version="0.6"
+	version="0.7"
 	description="Process your photo collection for duplicate detection"
 	author="Stephane Delcroix"
 	url="http://f-spot.org/Extensions";
 	name="Hash for Duplicates"
 	category="Tools">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/Tools">
 		<Command id = "HashDupes" _label = "Hash for Duplicates" command_type = "HashJobExtension.HashJob" />
diff --git a/extensions/Tools/HashJob/HashJob.cs b/extensions/Tools/HashJob/HashJob.cs
index 613b140..477aa0b 100644
--- a/extensions/Tools/HashJob/HashJob.cs
+++ b/extensions/Tools/HashJob/HashJob.cs
@@ -35,7 +35,7 @@ namespace HashJobExtension {
 		public void ShowDialog ()
 		{ 			
 			// This query is not very fast, but it's a 'one-time' so don't care much...
-			SqliteDataReader reader = FSpot.Core.Database.Database.Query (
+			SqliteDataReader reader = FSpot.App.Instance.Database.Database.Query (
 				"SELECT COUNT(*) FROM photos p WHERE md5_sum IS NULL OR md5_sum = '' OR EXISTS " +
 					"(SELECT * FROM photo_versions pv WHERE p.id=pv.photo_id AND version_id <> '1' AND " +
 					"(pv.md5_sum IS NULL OR pv.md5_sum = ''))");
@@ -43,7 +43,7 @@ namespace HashJobExtension {
 			uint missing_md5 = Convert.ToUInt32 (reader[0]);
 			reader.Close ();
 
-			reader = FSpot.Core.Database.Database.Query (String.Format (
+			reader = FSpot.App.Instance.Database.Database.Query (String.Format (
 				"SELECT COUNT(*) FROM jobs WHERE job_type = '{0}' ", typeof(FSpot.Jobs.CalculateHashJob).ToString ()));
 			reader.Read ();
 			uint active_jobs = Convert.ToUInt32 (reader[0]);
@@ -90,21 +90,21 @@ namespace HashJobExtension {
 
 		void HandleExecuteClicked (object o, EventArgs e)
 		{
-			SqliteDataReader reader = FSpot.Core.Database.Database.Query (
+			SqliteDataReader reader = FSpot.App.Instance.Database.Database.Query (
 				"SELECT id FROM photos p WHERE md5_sum IS NULL OR md5_sum = '' OR EXISTS " +
 					"(SELECT * FROM photo_versions pv WHERE p.id=pv.photo_id AND version_id <> '1' AND " +
 					"(pv.md5_sum IS NULL OR pv.md5_sum = '') )");
-			FSpot.Core.Database.Database.BeginTransaction ();
+			FSpot.App.Instance.Database.Database.BeginTransaction ();
 			while (reader.Read ())
-				FSpot.Jobs.CalculateHashJob.Create (FSpot.Core.Database.Jobs, Convert.ToUInt32 (reader[0]));
+				FSpot.Jobs.CalculateHashJob.Create (FSpot.App.Instance.Database.Jobs, Convert.ToUInt32 (reader[0]));
 			reader.Close ();
-			FSpot.Core.Database.Database.CommitTransaction ();
+			FSpot.App.Instance.Database.Database.CommitTransaction ();
 			status_label.Text = Catalog.GetString ("Processing images...");
 		}
 
 		void HandleStopClicked (object o, EventArgs e)
 		{
-			FSpot.Core.Database.Database.ExecuteNonQuery (String.Format ("DELETE FROM jobs WHERE job_type = '{0}'", typeof(FSpot.Jobs.CalculateHashJob).ToString ()));
+			FSpot.App.Instance.Database.Database.ExecuteNonQuery (String.Format ("DELETE FROM jobs WHERE job_type = '{0}'", typeof(FSpot.Jobs.CalculateHashJob).ToString ()));
 			status_label.Text = Catalog.GetString ("Stopped");
 		}
 
diff --git a/extensions/Tools/LiveWebGallery/GalleryRequestHandler.cs b/extensions/Tools/LiveWebGallery/GalleryRequestHandler.cs
index c0778b8..40f77d0 100644
--- a/extensions/Tools/LiveWebGallery/GalleryRequestHandler.cs
+++ b/extensions/Tools/LiveWebGallery/GalleryRequestHandler.cs
@@ -143,7 +143,7 @@ namespace LiveWebGalleryExtension
 		{
 			switch (query_type) {
 			case QueryType.ByTag:
-				return Core.Database.Photos.Query (new Tag[] {query_tag});
+				return App.Instance.Database.Photos.Query (new Tag[] {query_tag});
 			case QueryType.CurrentView:
 				return MainWindow.Toplevel.Query.Photos;
 			case QueryType.Selected:
@@ -213,12 +213,12 @@ namespace LiveWebGalleryExtension
 				return;
 			}
 			
-			Photo photo = Core.Database.Photos.Get (photo_id);
+			Photo photo = App.Instance.Database.Photos.Get (photo_id);
 			if (addTag)
 				photo.AddTag (options.EditableTag);
 			else
 				photo.RemoveTag (options.EditableTag);
-			Core.Database.Photos.Commit (photo);
+			App.Instance.Database.Photos.Commit (photo);
 			
 			SendHeadersAndStartContent (stream, "Content-type: text/plain;charset=UTF-8");
 			SendLine (stream, TagsToString (photo));
diff --git a/extensions/Tools/LiveWebGallery/LiveWebGallery.addin.xml b/extensions/Tools/LiveWebGallery/LiveWebGallery.addin.xml
index f760b56..aa254c7 100644
--- a/extensions/Tools/LiveWebGallery/LiveWebGallery.addin.xml
+++ b/extensions/Tools/LiveWebGallery/LiveWebGallery.addin.xml
@@ -1,14 +1,14 @@
 <Addin namespace="FSpot"
 	id="LiveWebGallery"
 	name="LiveWebGallery"
-	version="0.6.0.3"
+	version="0.7.0.0"
 	description="Share photos with other people on the same network via Web Browser"
 	author="Anton Keks"
 	url="http://blog.azib.net/2009/08/announcing-f-spot-live-web-gallery.html";
 	category="Tools"
 	defaultEnabled="false">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/Tools">
 		<Command id = "LiveWebGallery" _label = "Live Web Gallery" command_type = "LiveWebGalleryExtension.LiveWebGallery" />
diff --git a/extensions/Tools/LiveWebGallery/LiveWebGalleryDialog.cs b/extensions/Tools/LiveWebGallery/LiveWebGalleryDialog.cs
index 0c6a4e3..6244757 100644
--- a/extensions/Tools/LiveWebGallery/LiveWebGalleryDialog.cs
+++ b/extensions/Tools/LiveWebGallery/LiveWebGalleryDialog.cs
@@ -53,10 +53,10 @@ namespace LiveWebGalleryExtension
 			limit_spin.Sensitive = options.LimitMaxPhotos;
 			limit_spin.Value = options.MaxPhotos;
 			UpdateQueryRadios ();
-			HandleQueryTagSelected (options.QueryTag != null ? options.QueryTag : Core.Database.Tags.GetTagById(1));
+			HandleQueryTagSelected (options.QueryTag != null ? options.QueryTag : App.Instance.Database.Tags.GetTagById(1));
 			allow_tagging_checkbox.Active = options.TaggingAllowed;
 			tag_edit_button.Sensitive = options.TaggingAllowed;			
-			HandleEditableTagSelected (options.EditableTag != null ? options.EditableTag : Core.Database.Tags.GetTagById(3));
+			HandleEditableTagSelected (options.EditableTag != null ? options.EditableTag : App.Instance.Database.Tags.GetTagById(3));
 			HandleStatsChanged (null, null);
 						
 			activate_button.Toggled += HandleActivated;
@@ -159,7 +159,7 @@ namespace LiveWebGalleryExtension
 		
 		void ShowTagMenuFor (Widget widget, TagMenu.TagSelectedHandler handler) 
 		{
-			TagMenu tag_menu = new TagMenu (null, Core.Database.Tags);
+			TagMenu tag_menu = new TagMenu (null, App.Instance.Database.Tags);
 			tag_menu.TagSelected += handler;
 			tag_menu.Populate ();
 			int x, y;
@@ -198,4 +198,4 @@ namespace LiveWebGalleryExtension
 			tag_edit_button.Image = tag.Icon != null ? new Gtk.Image (PixbufUtils.ScaleDown (tag.Icon, 16, 16)) : null;
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/extensions/Tools/LiveWebGallery/PhotoRequestHandler.cs b/extensions/Tools/LiveWebGallery/PhotoRequestHandler.cs
index d0c6106..0885a60 100644
--- a/extensions/Tools/LiveWebGallery/PhotoRequestHandler.cs
+++ b/extensions/Tools/LiveWebGallery/PhotoRequestHandler.cs
@@ -29,7 +29,7 @@ namespace LiveWebGalleryExtension
 		public override void Handle (string requested, Stream stream)
 		{
 			uint photo_id = uint.Parse (requested);
-			Photo photo = Core.Database.Photos.Get (photo_id);
+			Photo photo = App.Instance.Database.Photos.Get (photo_id);
 			
 			SendImage (photo, stream);
 					}
diff --git a/extensions/Tools/MergeDb/MergeDb.addin.xml b/extensions/Tools/MergeDb/MergeDb.addin.xml
index 23d4c18..3cd7fd0 100644
--- a/extensions/Tools/MergeDb/MergeDb.addin.xml
+++ b/extensions/Tools/MergeDb/MergeDb.addin.xml
@@ -1,14 +1,14 @@
 <Addin namespace="FSpot"
 	id="MergeDb"
 	name="MergeDb"
-	version="0.6"
+	version="0.7"
 	description="Merge another db back to the main one"
 	author="Stephane Delcroix"
 	url="http://f-spot.org/Extensions";
 	category="Tools"
 	defaultEnabled="false">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/Tools">
 		<Command id = "MergeDb" _label = "Merge Db" command_type = "MergeDbExtension.MergeDb" />
diff --git a/extensions/Tools/MergeDb/MergeDb.cs b/extensions/Tools/MergeDb/MergeDb.cs
index 3f43cbb..043885e 100644
--- a/extensions/Tools/MergeDb/MergeDb.cs
+++ b/extensions/Tools/MergeDb/MergeDb.cs
@@ -37,7 +37,7 @@ namespace MergeDbExtension
 		{
 			from_db = new Db ();
 			from_db.ExceptionThrown += HandleDbException;
-			to_db = Core.Database;
+			to_db = App.Instance.Database;
 
 			//ShowDialog ();
 			mdd = new MergeDbDialog (this);
diff --git a/extensions/Tools/RawPlusJpeg/RawPlusJpeg.addin.xml b/extensions/Tools/RawPlusJpeg/RawPlusJpeg.addin.xml
index 55563c5..cba8b57 100644
--- a/extensions/Tools/RawPlusJpeg/RawPlusJpeg.addin.xml
+++ b/extensions/Tools/RawPlusJpeg/RawPlusJpeg.addin.xml
@@ -1,14 +1,14 @@
 <Addin namespace="FSpot"
 	id="RawPlusJpeg"
 	name="RawPlusJpeg"
-	version="0.6"
+	version="0.7"
 	description="Merge RAW+Jpeg as multiple versions of the same photo"
 	author="Stephane Delcroix"
 	url="http://f-spot.org/Extensions";
 	category="Tools"
 	defaultEnabled="false">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/Tools">
 		<Command id = "MergeRawJpeg" _label = "Merge Raw" command_type = "RawPlusJpegExtension.RawPlusJpeg" />
diff --git a/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs b/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs
index ec04628..e348a49 100644
--- a/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs
+++ b/extensions/Tools/RawPlusJpeg/RawPlusJpeg.cs
@@ -33,7 +33,7 @@ namespace RawPlusJpegExtension
 				"Do it now"))
 				return;
 
-			Photo [] photos = Core.Database.Photos.Query ((Tag [])null, null, null, null);
+			Photo [] photos = App.Instance.Database.Photos.Query ((Tag [])null, null, null, null);
 			Array.Sort (photos, new Photo.CompareDirectory ());
 
 			Photo raw = null;
@@ -115,8 +115,8 @@ namespace RawPlusJpegExtension
 					}
 				}
 				raw.Changes.DataChanged = true;
-				Core.Database.Photos.Commit (raw);
-				Core.Database.Photos.Remove (jpeg);
+				App.Instance.Database.Photos.Commit (raw);
+				App.Instance.Database.Photos.Remove (jpeg);
 			}
 		}
 	}
diff --git a/extensions/Tools/ScreensaverConfig/ScreensaverConfig.addin.xml b/extensions/Tools/ScreensaverConfig/ScreensaverConfig.addin.xml
index ab78012..4f77fb7 100644
--- a/extensions/Tools/ScreensaverConfig/ScreensaverConfig.addin.xml
+++ b/extensions/Tools/ScreensaverConfig/ScreensaverConfig.addin.xml
@@ -1,14 +1,14 @@
 <Addin namespace="FSpot"
 	id="ScreensaverConfig"
 	name="Screensaver Configuration"
-	version="0.6"
+	version="0.7.0.0"
 	description="Screensaver options"
 	author="Stephane Delcroix"
 	url="http://f-spot.org/Extensions";
 	category="Tools"
 	defaultEnabled="true">
 	<Dependencies>
-		<Addin id="Core" version="0.6"/>
+		<Addin id="Core" version="0.7.0.0"/>
 	</Dependencies>
 	<Extension path = "/FSpot/Menus/Tools">
 		<Command id = "ScreensaverConfig" _label = "Configure Screensaver" command_type = "ScreensaverConfig.ScreensaverConfig" />
diff --git a/extensions/Transitions/CoverTransition/CoverTransition.addin.xml b/extensions/Transitions/CoverTransition/CoverTransition.addin.xml
index 18594e7..330d4c4 100644
--- a/extensions/Transitions/CoverTransition/CoverTransition.addin.xml
+++ b/extensions/Transitions/CoverTransition/CoverTransition.addin.xml
@@ -1,13 +1,13 @@
 <Addin namespace="FSpot"
 	id="CoverTransition"
-	version="0.6.0.1"
+	version="0.7.0.0"
 	name="Cover Transition"
 	description="A Slideshow transition that covers images"
 	author="Stephane Delcroix"
 	url="http://f-spot.org/Extensions";
 	category="Transitions">
 	<Dependencies>
-		<Addin id="Core" version="0.6.0.1"/>
+		<Addin id="Core" version="0.7.0.0"/>
 	</Dependencies>
 	<Extension path = "/FSpot/SlideShow">
 		<Transition transition_type="CoverTransition.CoverTransition"/>
diff --git a/lib/Makefile.am b/lib/Makefile.am
index abe2bd5..df912a7 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -10,7 +10,8 @@ UNCONDITIONAL_SUBDIRS = \
 	libfspot			\
 	libgphoto2-sharp	\
 	mono-addins			\
-	semweb
+	semweb				\
+	unique-sharp
 
 # dpap-sharp isn't built, but it is shipped.
 
diff --git a/lib/unique-sharp/Makefile.am b/lib/unique-sharp/Makefile.am
new file mode 100644
index 0000000..8899ef1
--- /dev/null
+++ b/lib/unique-sharp/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS =					\
+	generator				\
+	unique
+
+fetch:
+	rm -rf fetch
+	git clone git://gitorious.org/unique-sharp/unique-sharp.git fetch
+
+update:
+	cp fetch/generator/*.cs generator/
+	cp	fetch/unique/*.custom 		\
+		fetch/unique/*.cs			\
+		fetch/unique/unique-api.raw		\
+		fetch/unique/Unique.metadata		\
+		unique
+
+.PHONY: fetch update
diff --git a/lib/unique-sharp/generator/AliasGen.cs b/lib/unique-sharp/generator/AliasGen.cs
new file mode 100644
index 0000000..19911d6
--- /dev/null
+++ b/lib/unique-sharp/generator/AliasGen.cs
@@ -0,0 +1,30 @@
+// GtkSharp.Generation.AliasGen.cs - The Alias type Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2003 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class AliasGen : SimpleBase {
+		
+		public AliasGen (string ctype, string type) : base (ctype, type, String.Empty) {}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/BoxedGen.cs b/lib/unique-sharp/generator/BoxedGen.cs
new file mode 100644
index 0000000..759868c
--- /dev/null
+++ b/lib/unique-sharp/generator/BoxedGen.cs
@@ -0,0 +1,82 @@
+// GtkSharp.Generation.BoxedGen.cs - The Boxed Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+	using System.Xml;
+
+	public class BoxedGen : StructBase {
+		
+		public BoxedGen (XmlElement ns, XmlElement elem) : base (ns, elem) {}
+		
+		public override void Generate (GenerationInfo gen_info)
+		{
+			Method copy = methods["Copy"] as Method;
+			methods.Remove ("Copy");
+			methods.Remove ("Free");
+
+			gen_info.CurrentType = Name;
+
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
+			base.Generate (gen_info);
+			sw.WriteLine ("\t\t[DllImport(\"glibsharpglue-2\")]");
+			sw.WriteLine ("\t\tstatic extern IntPtr glibsharp_value_get_boxed (ref GLib.Value val);");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\t[DllImport(\"glibsharpglue-2\")]");
+			sw.WriteLine ("\t\tstatic extern void glibsharp_value_set_boxed (ref GLib.Value val, ref " + QualifiedName + " boxed);");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic static explicit operator GLib.Value (" + QualifiedName + " boxed)");
+			sw.WriteLine ("\t\t{");
+
+			sw.WriteLine ("\t\t\tGLib.Value val = GLib.Value.Empty;");
+			sw.WriteLine ("\t\t\tval.Init (" + QualifiedName + ".GType);");
+			sw.WriteLine ("\t\t\tglibsharp_value_set_boxed (ref val, ref boxed);");
+			sw.WriteLine ("\t\t\treturn val;");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic static explicit operator " + QualifiedName + " (GLib.Value val)");
+			sw.WriteLine ("\t\t{");
+
+			sw.WriteLine ("\t\t\tIntPtr boxed_ptr = glibsharp_value_get_boxed (ref val);");
+			sw.WriteLine ("\t\t\treturn New (boxed_ptr);");
+			sw.WriteLine ("\t\t}");
+
+			if (copy != null && copy.IsDeprecated) {
+				sw.WriteLine ();
+				sw.WriteLine ("\t\t[Obsolete(\"This is a no-op\")]");
+				sw.WriteLine ("\t\tpublic " + QualifiedName + " Copy() {");
+				sw.WriteLine ("\t\t\treturn this;");
+				sw.WriteLine ("\t\t}");
+			}
+
+			sw.WriteLine ("#endregion");
+                        AppendCustom(sw, gen_info.CustomDir);
+                        sw.WriteLine ("\t}");
+                        sw.WriteLine ("}");
+			sw.Close ();
+			gen_info.Writer = null;
+			Statistics.BoxedCount++;
+		}		
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ByRefGen.cs b/lib/unique-sharp/generator/ByRefGen.cs
new file mode 100644
index 0000000..7a2641e
--- /dev/null
+++ b/lib/unique-sharp/generator/ByRefGen.cs
@@ -0,0 +1,63 @@
+// GtkSharp.Generation.ByRefGen.cs - The ByRef type Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2003 Mike Kestner
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class ByRefGen : SimpleBase, IManualMarshaler {
+		
+		public ByRefGen (string ctype, string type) : base (ctype, type, type + ".Empty") {}
+		
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+
+		public override string CallByName (string var_name)
+		{
+			return "native_" + var_name;
+		}
+		
+		public string AllocNative ()
+		{
+			return "Marshal.AllocHGlobal (Marshal.SizeOf (typeof (" + QualifiedName + ")))";
+		}
+
+		public string AllocNative (string var_name)
+		{
+			return "GLib.Marshaller.StructureToPtrAlloc (" + var_name + ")";
+		}
+
+		public override string FromNative (string var_name)
+		{
+			return String.Format ("({0}) Marshal.PtrToStructure ({1}, typeof ({0}))", QualifiedName, var_name);
+		}
+
+		public string ReleaseNative (string var_name)
+		{
+			return "Marshal.FreeHGlobal (" + var_name + ")";
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/CallbackGen.cs b/lib/unique-sharp/generator/CallbackGen.cs
new file mode 100644
index 0000000..a30cfa5
--- /dev/null
+++ b/lib/unique-sharp/generator/CallbackGen.cs
@@ -0,0 +1,306 @@
+// GtkSharp.Generation.CallbackGen.cs - The Callback Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2002-2003 Mike Kestner
+// Copyright (c) 2007 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+	using System.Xml;
+
+	public class CallbackGen : GenBase, IAccessor {
+
+		private Parameters parms;
+		private Signature sig = null;
+		private ReturnValue retval;
+		private bool valid = true;
+
+		public CallbackGen (XmlElement ns, XmlElement elem) : base (ns, elem) 
+		{
+			retval = new ReturnValue (elem ["return-type"]);
+			parms = new Parameters (elem ["parameters"]);
+			parms.HideData = true;
+		}
+
+		public override string DefaultValue {
+			get { return "null"; }
+		}
+
+		public override bool Validate ()
+		{
+			if (!retval.Validate ()) {
+				Console.WriteLine ("rettype: " + retval.CType + " in callback " + CName);
+				Statistics.ThrottledCount++;
+				valid = false;
+				return false;
+			}
+
+			if (!parms.Validate ()) {
+				Console.WriteLine (" in callback " + CName);
+				Statistics.ThrottledCount++;
+				valid = false;
+				return false;
+			}
+
+			valid = true;
+			return true;
+		}
+
+		public string InvokerName {
+			get {
+				if (!valid)
+					return String.Empty;
+				return NS + "Sharp." + Name + "Invoker";
+			}
+		}
+
+		public override string MarshalType {
+			get {
+				if (valid)
+					return NS + "Sharp." + Name + "Native";
+				else
+					return "";
+			}
+		}
+
+		public override string CallByName (string var_name)
+		{
+			return var_name + ".NativeDelegate";
+		}
+
+		public override string FromNative (string var)
+		{
+			return NS + "Sharp." + Name + "Wrapper.GetManagedDelegate (" + var + ")";
+		}
+
+		public void WriteAccessors (StreamWriter sw, string indent, string var)
+		{
+			sw.WriteLine (indent + "get {");
+			sw.WriteLine (indent + "\treturn " + FromNative (var) + ";");
+			sw.WriteLine (indent + "}");
+		}
+
+		string CastFromInt (string type)
+		{
+			return type != "int" ? "(" + type + ") " : "";
+		}
+
+		string InvokeString {
+			get {
+				if (parms.Count == 0)
+					return String.Empty;
+
+				string[] result = new string [parms.Count];
+				for (int i = 0; i < parms.Count; i++) {
+					Parameter p = parms [i];
+					IGeneratable igen = p.Generatable;
+
+					if (i > 0 && parms [i - 1].IsString && p.IsLength) {
+						string string_name = parms [i - 1].Name;
+						result[i] = igen.CallByName (CastFromInt (p.CSType) + "System.Text.Encoding.UTF8.GetByteCount (" +  string_name + ")");
+						continue;
+					}
+
+					p.CallName = p.Name;
+					result [i] = p.CallString;
+					if (p.IsUserData)
+						result [i] = "__data"; 
+				}
+
+				return String.Join (", ", result);
+			}
+		}
+
+		MethodBody body;
+
+		void GenInvoker (GenerationInfo gen_info, StreamWriter sw)
+		{
+			if (sig == null)
+				sig = new Signature (parms);
+
+			sw.WriteLine ("\tinternal class " + Name + "Invoker {");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\t" + Name + "Native native_cb;");
+			sw.WriteLine ("\t\tIntPtr __data;");
+			sw.WriteLine ("\t\tGLib.DestroyNotify __notify;");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\t~" + Name + "Invoker ()");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tif (__notify == null)");
+			sw.WriteLine ("\t\t\t\treturn;");
+			sw.WriteLine ("\t\t\t__notify (__data);");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb) : this (native_cb, IntPtr.Zero, null) {}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb, IntPtr data) : this (native_cb, data, null) {}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb, IntPtr data, GLib.DestroyNotify notify)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tthis.native_cb = native_cb;");
+			sw.WriteLine ("\t\t\t__data = data;");
+			sw.WriteLine ("\t\t\t__notify = notify;");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tinternal " + QualifiedName + " Handler {");
+			sw.WriteLine ("\t\t\tget {");
+			sw.WriteLine ("\t\t\t\treturn new " + QualifiedName + "(InvokeNative);");
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\t" + retval.CSType + " InvokeNative (" + sig + ")");
+			sw.WriteLine ("\t\t{");
+			body.Initialize (gen_info);
+			string call = "native_cb (" + InvokeString + ")";
+			if (retval.IsVoid)
+				sw.WriteLine ("\t\t\t" + call + ";");
+			else
+				sw.WriteLine ("\t\t\t" + retval.CSType + " result = " + retval.FromNative (call) + ";");
+			body.Finish (sw, String.Empty);
+			if (!retval.IsVoid)
+				sw.WriteLine ("\t\t\treturn result;");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ("\t}");
+			sw.WriteLine ();
+		}
+
+		public string GenWrapper (GenerationInfo gen_info)
+		{
+			string wrapper = Name + "Native";
+			string qualname = MarshalType;
+
+			if (!Validate ())
+				return String.Empty;
+
+			body = new MethodBody (parms);
+
+			StreamWriter save_sw = gen_info.Writer;
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (qualname);
+
+			sw.WriteLine ("namespace " + NS + "Sharp {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+			sw.WriteLine ("#region Autogenerated code");
+			sw.WriteLine ("\t[GLib.CDeclCallback]");
+			sw.WriteLine ("\tinternal delegate " + retval.MarshalType + " " + wrapper + "(" + parms.ImportSignature + ");");
+			sw.WriteLine ();
+			GenInvoker (gen_info, sw);
+			sw.WriteLine ("\tinternal class " + Name + "Wrapper {");
+			sw.WriteLine ();
+			ManagedCallString call = new ManagedCallString (parms, false);
+			sw.WriteLine ("\t\tpublic " + retval.MarshalType + " NativeCallback (" + parms.ImportSignature + ")");
+			sw.WriteLine ("\t\t{");
+			string unconditional = call.Unconditional ("\t\t\t");
+			if (unconditional.Length > 0)
+				sw.WriteLine (unconditional);
+			sw.WriteLine ("\t\t\ttry {");
+			string call_setup = call.Setup ("\t\t\t\t");
+			if (call_setup.Length > 0)
+				sw.WriteLine (call_setup);
+			if (retval.CSType == "void")
+				sw.WriteLine ("\t\t\t\tmanaged ({0});", call);
+			else
+				sw.WriteLine ("\t\t\t\t{0} __ret = managed ({1});", retval.CSType, call);
+			string finish = call.Finish ("\t\t\t\t");
+			if (finish.Length > 0)
+				sw.WriteLine (finish);
+			sw.WriteLine ("\t\t\t\tif (release_on_call)\n\t\t\t\t\tgch.Free ();");
+			if (retval.CSType != "void")
+				sw.WriteLine ("\t\t\t\treturn {0};", retval.ToNative ("__ret"));
+
+			/* If the function expects one or more "out" parameters(error parameters are excluded) or has a return value different from void and bool, exceptions
+			*  thrown in the managed function have to be considered fatal meaning that an exception is to be thrown and the function call cannot not return
+			*/
+			bool fatal = (retval.MarshalType != "void" && retval.MarshalType != "bool") || call.HasOutParam;
+			sw.WriteLine ("\t\t\t} catch (Exception e) {");
+			sw.WriteLine ("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, " + (fatal ? "true" : "false") + ");");
+			if (fatal) {
+				sw.WriteLine ("\t\t\t\t// NOTREACHED: Above call does not return.");
+				sw.WriteLine ("\t\t\t\tthrow e;");
+			} else if (retval.MarshalType == "bool") {
+				sw.WriteLine ("\t\t\t\treturn false;");
+			}
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tbool release_on_call = false;");
+			sw.WriteLine ("\t\tGCHandle gch;");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic void PersistUntilCalled ()");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\trelease_on_call = true;");
+			sw.WriteLine ("\t\t\tgch = GCHandle.Alloc (this);");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tinternal " + wrapper + " NativeDelegate;");
+			sw.WriteLine ("\t\t" + NS + "." + Name + " managed;");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic " + Name + "Wrapper (" + NS + "." + Name + " managed)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tthis.managed = managed;");
+			sw.WriteLine ("\t\t\tif (managed != null)");
+			sw.WriteLine ("\t\t\t\tNativeDelegate = new " + wrapper + " (NativeCallback);");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic static " + NS + "." + Name + " GetManagedDelegate (" + wrapper + " native)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tif (native == null)");
+			sw.WriteLine ("\t\t\t\treturn null;");
+			sw.WriteLine ("\t\t\t" + Name + "Wrapper wrapper = (" + Name + "Wrapper) native.Target;");
+			sw.WriteLine ("\t\t\tif (wrapper == null)");
+			sw.WriteLine ("\t\t\t\treturn null;");
+			sw.WriteLine ("\t\t\treturn wrapper.managed;");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("#endregion");
+			sw.WriteLine ("}");
+			sw.Close ();
+			gen_info.Writer = save_sw;
+			return NS + "Sharp." + Name + "Wrapper";
+		}
+		
+		public override void Generate (GenerationInfo gen_info)
+		{
+			gen_info.CurrentType = Name;
+
+			sig = new Signature (parms);
+
+			StreamWriter sw = gen_info.OpenStream (Name);
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ();
+			sw.WriteLine ("\t{0} delegate " + retval.CSType + " " + Name + "(" + sig.ToString() + ");", IsInternal ? "internal" : "public");
+			sw.WriteLine ();
+			sw.WriteLine ("}");
+
+			sw.Close ();
+			
+			GenWrapper (gen_info);
+
+			Statistics.CBCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ChildProperty.cs b/lib/unique-sharp/generator/ChildProperty.cs
new file mode 100644
index 0000000..fe361ed
--- /dev/null
+++ b/lib/unique-sharp/generator/ChildProperty.cs
@@ -0,0 +1,45 @@
+// GtkSharp.Generation.ChildProperty.cs - GtkContainer child properties
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class ChildProperty : Property {
+
+		public ChildProperty (XmlElement elem, ClassBase container_type) : base (elem, container_type) {}
+
+		protected override string PropertyAttribute (string qpname) {
+			return "[Gtk.ChildProperty (" + qpname + ")]";
+		}
+
+		protected override string RawGetter (string qpname) {
+			return "parent.ChildGetProperty (child, " + qpname + ")";
+		}
+
+		protected override string RawSetter (string qpname) {
+			return "parent.ChildSetProperty(child, " + qpname + ", val)";
+		}
+
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ClassBase.cs b/lib/unique-sharp/generator/ClassBase.cs
new file mode 100644
index 0000000..68b16df
--- /dev/null
+++ b/lib/unique-sharp/generator/ClassBase.cs
@@ -0,0 +1,480 @@
+// GtkSharp.Generation.ClassBase.cs - Common code between object
+// and interface wrappers
+//
+// Authors: Rachel Hestilow <hestilow ximian com>
+//          Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2002 Rachel Hestilow
+// Copyright (c) 2001-2003 Mike Kestner 
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public abstract class ClassBase : GenBase {
+		protected Hashtable props = new Hashtable();
+		protected Hashtable fields = new Hashtable();
+		protected Hashtable sigs = new Hashtable();
+		protected Hashtable methods = new Hashtable();
+		protected ArrayList interfaces = new ArrayList();
+		protected ArrayList managed_interfaces = new ArrayList();
+		protected ArrayList ctors = new ArrayList();
+
+		private bool ctors_initted = false;
+		private Hashtable clash_map;
+		private bool deprecated = false;
+		private bool isabstract = false;
+
+		public Hashtable Methods {
+			get {
+				return methods;
+			}
+		}	
+
+		public Hashtable Signals {
+			get {
+				return sigs;
+			}
+		}	
+
+		public ClassBase Parent {
+			get {
+				string parent = Elem.GetAttribute("parent");
+
+				if (parent == "")
+					return null;
+				else
+					return SymbolTable.Table.GetClassGen(parent);
+			}
+		}
+
+		protected ClassBase (XmlElement ns, XmlElement elem) : base (ns, elem) {
+					
+			if (elem.HasAttribute ("deprecated")) {
+				string attr = elem.GetAttribute ("deprecated");
+				deprecated = attr == "1" || attr == "true";
+			}
+			
+			if (elem.HasAttribute ("abstract")) {
+				string attr = elem.GetAttribute ("abstract");
+				isabstract = attr == "1" || attr == "true";
+			}
+
+			foreach (XmlNode node in elem.ChildNodes) {
+				if (!(node is XmlElement)) continue;
+				XmlElement member = (XmlElement) node;
+				if (member.HasAttribute ("hidden"))
+					continue;
+				
+				string name;
+				switch (node.Name) {
+				case "method":
+					name = member.GetAttribute("name");
+					while (methods.ContainsKey(name))
+						name += "mangled";
+					methods.Add (name, new Method (member, this));
+					break;
+
+				case "property":
+					name = member.GetAttribute("name");
+					while (props.ContainsKey(name))
+						name += "mangled";
+					props.Add (name, new Property (member, this));
+					break;
+
+				case "field":
+					name = member.GetAttribute("name");
+					while (fields.ContainsKey (name))
+						name += "mangled";
+					fields.Add (name, new ObjectField (member, this));
+					break;
+
+				case "signal":
+					name = member.GetAttribute("name");
+					while (sigs.ContainsKey(name))
+						name += "mangled";
+					sigs.Add (name, new Signal (member, this));
+					break;
+
+				case "implements":
+					ParseImplements (member);
+					break;
+
+				case "constructor":
+					ctors.Add (new Ctor (member, this));
+					break;
+
+				default:
+					break;
+				}
+			}
+		}
+
+		public override bool Validate ()
+		{
+			if (Parent != null && !Parent.ValidateForSubclass ())
+				return false;
+			foreach (string iface in interfaces) {
+				InterfaceGen igen = SymbolTable.Table[iface] as InterfaceGen;
+				if (igen == null) {
+					Console.WriteLine (QualifiedName + " implements unknown GInterface " + iface);
+					return false;
+				}
+				if (!igen.ValidateForSubclass ()) {
+					Console.WriteLine (QualifiedName + " implements invalid GInterface " + iface);
+					return false;
+				}
+			}
+
+			ArrayList invalids = new ArrayList ();
+
+			foreach (Property prop in props.Values) {
+				if (!prop.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (prop);
+				}
+			}
+			foreach (Property prop in invalids)
+				props.Remove (prop.Name);
+			invalids.Clear ();
+
+			foreach (Signal sig in sigs.Values) {
+				if (!sig.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (sig);
+				}
+			}
+			foreach (Signal sig in invalids)
+				sigs.Remove (sig.Name);
+			invalids.Clear ();
+
+			foreach (ObjectField field in fields.Values) {
+				if (!field.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (field);
+				}
+			}
+			foreach (ObjectField field in invalids)
+				fields.Remove (field.Name);
+			invalids.Clear ();
+
+			foreach (Method method in methods.Values) {
+				if (!method.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (method);
+				}
+			}
+			foreach (Method method in invalids)
+				methods.Remove (method.Name);
+			invalids.Clear ();
+
+			foreach (Ctor ctor in ctors) {
+				if (!ctor.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (ctor);
+				}
+			}
+			foreach (Ctor ctor in invalids)
+				ctors.Remove (ctor);
+			invalids.Clear ();
+
+			return true;
+		}
+
+		public virtual bool ValidateForSubclass ()
+		{
+			ArrayList invalids = new ArrayList ();
+
+			foreach (Signal sig in sigs.Values) {
+				if (!sig.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (sig);
+				}
+			}
+			foreach (Signal sig in invalids)
+				sigs.Remove (sig.Name);
+			invalids.Clear ();
+
+			return true;
+		}
+
+		public bool IsDeprecated {
+			get {
+				return deprecated;
+			}
+		}
+
+		public bool IsAbstract {
+			get {
+				return isabstract;
+			}
+		}
+
+		public abstract string AssignToName { get; }
+
+		public abstract string CallByName ();
+
+		public override string DefaultValue {
+			get {
+				return "null";
+			}
+		}
+
+		protected bool IsNodeNameHandled (string name)
+		{
+			switch (name) {
+			case "method":
+			case "property":
+			case "field":
+			case "signal":
+			case "implements":
+			case "constructor":
+			case "disabledefaultconstructor":
+				return true;
+				
+			default:
+				return false;
+			}
+		}
+
+		public void GenProperties (GenerationInfo gen_info, ClassBase implementor)
+		{		
+			if (props.Count == 0)
+				return;
+
+			foreach (Property prop in props.Values)
+				prop.Generate (gen_info, "\t\t", implementor);
+		}
+
+		public void GenSignals (GenerationInfo gen_info, ClassBase implementor)
+		{		
+			if (sigs == null)
+				return;
+
+			foreach (Signal sig in sigs.Values)
+				sig.Generate (gen_info, implementor);
+		}
+
+		protected void GenFields (GenerationInfo gen_info)
+		{
+			foreach (ObjectField field in fields.Values)
+				field.Generate (gen_info, "\t\t");
+		}
+
+		private void ParseImplements (XmlElement member)
+		{
+			foreach (XmlNode node in member.ChildNodes) {
+				if (node.Name != "interface")
+					continue;
+				XmlElement element = (XmlElement) node;
+				if (element.HasAttribute ("hidden"))
+					continue;
+				if (element.HasAttribute ("cname"))
+					interfaces.Add (element.GetAttribute ("cname"));
+				else if (element.HasAttribute ("name"))
+					managed_interfaces.Add (element.GetAttribute ("name"));
+			}
+		}
+		
+		protected bool IgnoreMethod (Method method, ClassBase implementor)
+		{	
+			if (implementor != null && implementor.QualifiedName != this.QualifiedName && method.IsStatic)
+				return true;
+
+			string mname = method.Name;
+			return ((method.IsSetter || (method.IsGetter && mname.StartsWith("Get"))) &&
+				((props != null) && props.ContainsKey(mname.Substring(3)) ||
+				 (fields != null) && fields.ContainsKey(mname.Substring(3))));
+		}
+
+		public void GenMethods (GenerationInfo gen_info, Hashtable collisions, ClassBase implementor)
+		{		
+			if (methods == null)
+				return;
+
+			foreach (Method method in methods.Values) {
+				if (IgnoreMethod (method, implementor))
+					continue;
+
+				string oname = null, oprotection = null;
+				if (collisions != null && collisions.Contains (method.Name)) {
+					oname = method.Name;
+					oprotection = method.Protection;
+					method.Name = QualifiedName + "." + method.Name;
+					method.Protection = "";
+				}
+				method.Generate (gen_info, implementor);
+				if (oname != null) {
+					method.Name = oname;
+					method.Protection = oprotection;
+				}
+			}
+		}
+
+		public Method GetMethod (string name)
+		{
+			return (Method) methods[name];
+		}
+
+		public Property GetProperty (string name)
+		{
+			return (Property) props[name];
+		}
+
+		public Signal GetSignal (string name)
+		{
+			return (Signal) sigs[name];
+		}
+
+		public Method GetMethodRecursively (string name)
+		{
+			return GetMethodRecursively (name, false);
+		}
+		
+		public virtual Method GetMethodRecursively (string name, bool check_self)
+		{
+			Method p = null;
+			if (check_self)
+				p = GetMethod (name);
+			if (p == null && Parent != null) 
+				p = Parent.GetMethodRecursively (name, true);
+			
+			if (check_self && p == null) {
+				foreach (string iface in interfaces) {
+					ClassBase igen = SymbolTable.Table.GetClassGen (iface);
+					if (igen == null)
+						continue;
+					p = igen.GetMethodRecursively (name, true);
+					if (p != null)
+						break;
+				}
+			}
+
+			return p;
+		}
+
+		public virtual Property GetPropertyRecursively (string name)
+		{
+			ClassBase klass = this;
+			Property p = null;
+			while (klass != null && p == null) {
+				p = (Property) klass.GetProperty (name);
+				klass = klass.Parent;
+			}
+
+			return p;
+		}
+
+		public Signal GetSignalRecursively (string name)
+		{
+			return GetSignalRecursively (name, false);
+		}
+		
+		public virtual Signal GetSignalRecursively (string name, bool check_self)
+		{
+			Signal p = null;
+			if (check_self)
+				p = GetSignal (name);
+			if (p == null && Parent != null) 
+				p = Parent.GetSignalRecursively (name, true);
+			
+			if (check_self && p == null) {
+				foreach (string iface in interfaces) {
+					ClassBase igen = SymbolTable.Table.GetClassGen (iface);
+					if (igen == null)
+						continue;
+					p = igen.GetSignalRecursively (name, true);
+					if (p != null)
+						break;
+				}
+			}
+
+			return p;
+		}
+
+		public bool Implements (string iface)
+		{
+			if (interfaces.Contains (iface))
+				return true;
+			else if (Parent != null)
+				return Parent.Implements (iface);
+			else
+				return false;
+		}
+
+		public ArrayList Ctors { get { return ctors; } }
+
+		bool HasStaticCtor (string name) 
+		{
+			if (Parent != null && Parent.HasStaticCtor (name))
+				return true;
+
+			foreach (Ctor ctor in Ctors)
+				if (ctor.StaticName == name)
+					return true;
+
+			return false;
+		}
+
+		private void InitializeCtors ()
+		{
+			if (ctors_initted)
+				return;
+
+			if (Parent != null)
+				Parent.InitializeCtors ();
+
+			ArrayList valid_ctors = new ArrayList();
+			clash_map = new Hashtable();
+
+			foreach (Ctor ctor in ctors) {
+				if (clash_map.Contains (ctor.Signature.Types)) {
+					Ctor clash = clash_map [ctor.Signature.Types] as Ctor;
+					Ctor alter = ctor.Preferred ? clash : ctor;
+					alter.IsStatic = true;
+					if (Parent != null && Parent.HasStaticCtor (alter.StaticName))
+						alter.Modifiers = "new ";
+				} else
+					clash_map [ctor.Signature.Types] = ctor;
+
+				valid_ctors.Add (ctor);
+			}
+
+			ctors = valid_ctors;
+			ctors_initted = true;
+		}
+
+		protected virtual void GenCtors (GenerationInfo gen_info)
+		{
+			InitializeCtors ();
+			foreach (Ctor ctor in ctors)
+				ctor.Generate (gen_info);
+		}
+
+		public virtual void Finish (StreamWriter sw, string indent)
+		{
+		}
+
+		public virtual void Prepare (StreamWriter sw, string indent)
+		{
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/ClassGen.cs b/lib/unique-sharp/generator/ClassGen.cs
new file mode 100644
index 0000000..700a27a
--- /dev/null
+++ b/lib/unique-sharp/generator/ClassGen.cs
@@ -0,0 +1,94 @@
+// GtkSharp.Generation.ClassGen.cs - The Class Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Text;
+	using System.Xml;
+
+	public class ClassGen : ClassBase  {
+
+		public ClassGen (XmlElement ns, XmlElement elem) : base (ns, elem) {}
+
+		public override string AssignToName {
+			get {
+				return String.Empty;
+			}
+		}
+
+		public override string MarshalType {
+			get {
+				return String.Empty;
+			}
+		}
+
+		public override string CallByName () 
+		{
+			return String.Empty;
+		}
+
+		public override string CallByName (string var) 
+		{
+			return String.Empty;
+		}
+
+		public override string FromNative (string var) 
+		{
+			return String.Empty;
+		}
+
+		public override void Generate (GenerationInfo gen_info)
+		{
+			gen_info.CurrentType = Name;
+
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream(Name);
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+
+			sw.WriteLine ("#region Autogenerated code");
+			if (IsDeprecated)
+				sw.WriteLine ("\t[Obsolete]");
+			sw.Write ("\t{0} class " + Name, IsInternal ? "internal" : "public");
+			sw.WriteLine (" {");
+			sw.WriteLine ();
+
+			GenProperties (gen_info, null);
+			GenMethods (gen_info, null, null);
+			
+			sw.WriteLine ("#endregion");
+			AppendCustom(sw, gen_info.CustomDir);
+
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+
+			sw.Close ();
+			gen_info.Writer = null;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/CodeGenerator.cs b/lib/unique-sharp/generator/CodeGenerator.cs
new file mode 100644
index 0000000..f45c7a0
--- /dev/null
+++ b/lib/unique-sharp/generator/CodeGenerator.cs
@@ -0,0 +1,122 @@
+// GtkSharp.Generation.CodeGenerator.cs - The main code generation engine.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner 
+// Copyright (c) 2003-2004 Novell Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.Xml;
+
+	public class CodeGenerator  {
+
+		public static int Main (string[] args)
+		{
+			if (args.Length < 2) {
+				Console.WriteLine ("Usage: codegen --generate <filename1...>");
+				return 0;
+			}
+
+			bool generate = false;
+			string dir = "";
+			string custom_dir = "";
+			string assembly_name = "";
+			string glue_filename = "";
+			string glue_includes = "";
+			string gluelib_name = "";
+
+			SymbolTable table = SymbolTable.Table;
+			ArrayList gens = new ArrayList ();
+			foreach (string arg in args) {
+				string filename = arg;
+				if (arg == "--generate") {
+					generate = true;
+					continue;
+				} else if (arg == "--include") {
+					generate = false;
+					continue;
+				} else if (arg.StartsWith ("-I:")) {
+					generate = false;
+					filename = filename.Substring (3);
+				} else if (arg.StartsWith ("--outdir=")) {
+					generate = false;
+					dir = arg.Substring (9);
+					continue;
+				} else if (arg.StartsWith ("--customdir=")) {
+					generate = false;
+					custom_dir = arg.Substring (12);
+					continue;
+				} else if (arg.StartsWith ("--assembly-name=")) {
+					generate = false;
+					assembly_name = arg.Substring (16);
+					continue;
+				} else if (arg.StartsWith ("--glue-filename=")) {
+					generate = false;
+					glue_filename = arg.Substring (16);
+					continue;
+				} else if (arg.StartsWith ("--glue-includes=")) {
+					generate = false;
+					glue_includes = arg.Substring (16);
+					continue;
+				} else if (arg.StartsWith ("--gluelib-name=")) {
+					generate = false;
+					gluelib_name = arg.Substring (15);
+					continue;
+				}
+
+				Parser p = new Parser ();
+				IGeneratable[] curr_gens = p.Parse (filename);
+				table.AddTypes (curr_gens);
+				if (generate)
+					gens.AddRange (curr_gens);
+			}
+
+			// Now that everything is loaded, validate all the to-be-
+			// generated generatables and then remove the invalid ones.
+			ArrayList invalids = new ArrayList ();
+			foreach (IGeneratable gen in gens) {
+				if (!gen.Validate ())
+					invalids.Add (gen);
+			}
+			foreach (IGeneratable gen in invalids)
+				gens.Remove (gen);
+
+			GenerationInfo gen_info = null;
+			if (dir != "" || assembly_name != "" || glue_filename != "" || glue_includes != "" || gluelib_name != "")
+				gen_info = new GenerationInfo (dir, custom_dir, assembly_name, glue_filename, glue_includes, gluelib_name);
+			
+			foreach (IGeneratable gen in gens) {
+				if (gen_info == null)
+					gen.Generate ();
+				else
+					gen.Generate (gen_info);
+			}
+
+			ObjectGen.GenerateMappers ();
+
+			if (gen_info != null)
+				gen_info.CloseGlueWriter ();
+
+			Statistics.Report();
+			return 0;
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/ConstFilenameGen.cs b/lib/unique-sharp/generator/ConstFilenameGen.cs
new file mode 100644
index 0000000..562ab9c
--- /dev/null
+++ b/lib/unique-sharp/generator/ConstFilenameGen.cs
@@ -0,0 +1,52 @@
+// ConstFilenameGen.cs - The Const Filename type Generatable.
+//
+// Author:  Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class ConstFilenameGen : SimpleBase, IManualMarshaler {
+		
+		public ConstFilenameGen (string ctype) : base (ctype, "string", "null") {}
+
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+		
+		public override string FromNative (string var)
+		{
+			return "GLib.Marshaller.FilenamePtrToString (" + var + ")";
+		}
+
+		public string AllocNative (string managed_var)
+		{
+			return "GLib.Marshaller.StringToFilenamePtr (" + managed_var + ")";
+		}
+
+		public string ReleaseNative (string native_var)
+		{
+			return "GLib.Marshaller.Free (" + native_var + ")";
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ConstStringGen.cs b/lib/unique-sharp/generator/ConstStringGen.cs
new file mode 100644
index 0000000..70f882e
--- /dev/null
+++ b/lib/unique-sharp/generator/ConstStringGen.cs
@@ -0,0 +1,59 @@
+// GtkSharp.Generation.ConstStringGen.cs - The Const String type Generatable.
+//
+// Author: Rachel Hestilow <rachel nullenvoid com>
+//         Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2003 Rachel Hestilow
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class ConstStringGen : SimpleBase, IManualMarshaler {
+		
+		public ConstStringGen (string ctype) : base (ctype, "string", "null") {}
+
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+		
+		public override string FromNative (string var)
+		{
+			return "GLib.Marshaller.Utf8PtrToString (" + var + ")";
+		}
+
+		public override string ToNativeReturn (string var)
+		{
+			return "GLib.Marshaller.StringToPtrGStrdup (" + var + ")";
+		}
+
+		public string AllocNative (string managed_var)
+		{
+			return "GLib.Marshaller.StringToPtrGStrdup (" + managed_var + ")";
+		}
+
+		public string ReleaseNative (string native_var)
+		{
+			return "GLib.Marshaller.Free (" + native_var + ")";
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Ctor.cs b/lib/unique-sharp/generator/Ctor.cs
new file mode 100644
index 0000000..9d57043
--- /dev/null
+++ b/lib/unique-sharp/generator/Ctor.cs
@@ -0,0 +1,165 @@
+// GtkSharp.Generation.Ctor.cs - The Constructor Generation Class.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2004-2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class Ctor : MethodBase  {
+
+		private bool preferred;
+		private string name;
+		private bool needs_chaining = false;
+
+		public Ctor (XmlElement elem, ClassBase implementor) : base (elem, implementor) 
+		{
+			if (elem.HasAttribute ("preferred"))
+				preferred = true;
+			if (implementor is ObjectGen)
+				needs_chaining = true;
+			name = implementor.Name;
+		}
+
+		public bool Preferred {
+			get { return preferred; }
+			set { preferred = value; }
+		}
+
+		public string StaticName {
+			get {
+				if (!IsStatic)
+					return String.Empty;
+
+				string[] toks = CName.Substring(CName.IndexOf("new")).Split ('_');
+				string result = String.Empty;
+
+				foreach (string tok in toks)
+					result += tok.Substring(0,1).ToUpper() + tok.Substring(1);
+				return result;
+			}
+		}
+
+		void GenerateImport (StreamWriter sw)
+		{
+			sw.WriteLine("\t\t[DllImport(\"" + LibraryName + "\")]");
+			sw.WriteLine("\t\tstatic extern " + Safety + "IntPtr " + CName + "(" + Parameters.ImportSignature + ");");
+			sw.WriteLine();
+		}
+
+		void GenerateStatic (GenerationInfo gen_info)
+		{
+			StreamWriter sw = gen_info.Writer;
+			sw.WriteLine("\t\t" + Protection + " static " + Safety + Modifiers +  name + " " + StaticName + "(" + Signature + ")");
+			sw.WriteLine("\t\t{");
+
+			Body.Initialize(gen_info, false, false, ""); 
+
+			sw.Write("\t\t\t" + name + " result = ");
+			if (container_type is StructBase)
+				sw.Write ("{0}.New (", name);
+			else
+				sw.Write ("new {0} (", name);
+			sw.WriteLine (CName + "(" + Body.GetCallString (false) + "));");
+			Body.Finish (sw, ""); 
+			Body.HandleException (sw, ""); 
+			sw.WriteLine ("\t\t\treturn result;");
+		}
+
+		public void Generate (GenerationInfo gen_info)
+		{
+			if (!Validate ())
+				return;
+
+			StreamWriter sw = gen_info.Writer;
+			gen_info.CurrentMember = CName;
+
+			GenerateImport (sw);
+			
+			if (IsStatic)
+				GenerateStatic (gen_info);
+			else {
+				sw.WriteLine("\t\t{0} {1}{2} ({3}) {4}", Protection, Safety, name, Signature.ToString(), needs_chaining ? ": base (IntPtr.Zero)" : "");
+				sw.WriteLine("\t\t{");
+
+				if (needs_chaining) {
+					sw.WriteLine ("\t\t\tif (GetType () != typeof (" + name + ")) {");
+					
+					if (Parameters.Count == 0) {
+						sw.WriteLine ("\t\t\t\tCreateNativeObject (new string [0], new GLib.Value[0]);");
+						sw.WriteLine ("\t\t\t\treturn;");
+					} else {
+						ArrayList names = new ArrayList ();
+						ArrayList values = new ArrayList ();
+						for (int i = 0; i < Parameters.Count; i++) {
+							Parameter p = Parameters[i];
+							if (container_type.GetPropertyRecursively (p.StudlyName) != null) {
+								names.Add (p.Name);
+								values.Add (p.Name);
+							} else if (p.PropertyName != String.Empty) {
+								names.Add (p.PropertyName);
+								values.Add (p.Name);
+							}
+						}
+
+						if (names.Count == Parameters.Count) {
+							sw.WriteLine ("\t\t\t\tArrayList vals = new ArrayList();");
+							sw.WriteLine ("\t\t\t\tArrayList names = new ArrayList();");
+							for (int i = 0; i < names.Count; i++) {
+								Parameter p = Parameters [i];
+								string indent = "\t\t\t\t";
+								if (p.Generatable is ClassBase && !(p.Generatable is StructBase)) {
+									sw.WriteLine (indent + "if (" + p.Name + " != null) {");
+									indent += "\t";
+								}
+								sw.WriteLine (indent + "names.Add (\"" + names [i] + "\");");
+								sw.WriteLine (indent + "vals.Add (new GLib.Value (" + values[i] + "));");
+
+								if (p.Generatable is ClassBase && !(p.Generatable is StructBase))
+									sw.WriteLine ("\t\t\t\t}");
+							}
+
+							sw.WriteLine ("\t\t\t\tCreateNativeObject ((string[])names.ToArray (typeof (string)), (GLib.Value[])vals.ToArray (typeof (GLib.Value)));");
+							sw.WriteLine ("\t\t\t\treturn;");
+						} else
+							sw.WriteLine ("\t\t\t\tthrow new InvalidOperationException (\"Can't override this constructor.\");");
+					}
+					
+					sw.WriteLine ("\t\t\t}");
+				}
+	
+				Body.Initialize(gen_info, false, false, ""); 
+				sw.WriteLine("\t\t\t{0} = {1}({2});", container_type.AssignToName, CName, Body.GetCallString (false));
+				Body.Finish (sw, "");
+				Body.HandleException (sw, "");
+			}
+			
+			sw.WriteLine("\t\t}");
+			sw.WriteLine();
+			
+			Statistics.CtorCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/EnumGen.cs b/lib/unique-sharp/generator/EnumGen.cs
new file mode 100644
index 0000000..fa66af5
--- /dev/null
+++ b/lib/unique-sharp/generator/EnumGen.cs
@@ -0,0 +1,127 @@
+// GtkSharp.Generation.EnumGen.cs - The Enumeration Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class EnumGen : GenBase {
+		
+		string enum_type = String.Empty;
+		ArrayList members = new ArrayList ();
+
+		public EnumGen (XmlElement ns, XmlElement elem) : base (ns, elem) 
+		{
+			foreach (XmlElement member in elem.ChildNodes) {
+				if (member.Name != "member")
+					continue;
+
+				string result = "\t\t" + member.GetAttribute("name");
+				if (member.HasAttribute("value")) {
+					string value = member.GetAttribute("value");
+					if (value.EndsWith("U")) {
+						enum_type = " : uint";
+						value = value.TrimEnd('U');
+					}
+					result += " = " + value;
+				}
+				members.Add (result + ",");
+			}
+		}
+
+		public override bool Validate ()
+		{
+			return true;
+		}
+
+		public override string DefaultValue {
+			get {
+				return "(" + QualifiedName + ") 0";
+			}
+		}
+
+		public override string MarshalType {
+			get {
+				return "int";
+			}
+		}
+
+		public override string CallByName (string var_name)
+		{
+			return "(int) " + var_name;
+		}
+		
+		public override string FromNative(string var)
+		{
+			return "(" + QualifiedName + ") " + var;
+		}
+		
+		public override void Generate (GenerationInfo gen_info)
+		{
+			StreamWriter sw = gen_info.OpenStream (Name);
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+
+			sw.WriteLine ("#region Autogenerated code");
+					
+			if (Elem.GetAttribute("type") == "flags")
+				sw.WriteLine ("\t[Flags]");
+			if (Elem.HasAttribute("gtype"))
+				sw.WriteLine ("\t[GLib.GType (typeof (" + NS + "." + Name + "GType))]");
+
+			string access = IsInternal ? "internal" : "public";
+			sw.WriteLine ("\t" + access + " enum " + Name + enum_type + " {");
+			sw.WriteLine ();
+				
+			foreach (string member in members)
+				sw.WriteLine (member);
+
+			sw.WriteLine ("\t}");
+
+			if (Elem.HasAttribute ("gtype")) {
+				sw.WriteLine ();
+				sw.WriteLine ("\tinternal class " + Name + "GType {");
+				sw.WriteLine ("\t\t[DllImport (\"" + LibraryName + "\")]");
+				sw.WriteLine ("\t\tstatic extern IntPtr " + Elem.GetAttribute ("gtype") + " ();");
+				sw.WriteLine ();
+				sw.WriteLine ("\t\tpublic static GLib.GType GType {");
+				sw.WriteLine ("\t\t\tget {");
+				sw.WriteLine ("\t\t\t\treturn new GLib.GType (" + Elem.GetAttribute ("gtype") + " ());");
+				sw.WriteLine ("\t\t\t}");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ("\t}");
+			}
+
+			sw.WriteLine ("#endregion");
+			sw.WriteLine ("}");
+			sw.Close ();
+			Statistics.EnumCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/FieldBase.cs b/lib/unique-sharp/generator/FieldBase.cs
new file mode 100644
index 0000000..9fac0cd
--- /dev/null
+++ b/lib/unique-sharp/generator/FieldBase.cs
@@ -0,0 +1,270 @@
+// GtkSharp.Generation.FieldBase.cs - base class for struct and object
+// fields
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public abstract class FieldBase : PropertyBase {
+		public FieldBase (XmlElement elem, ClassBase container_type) : base (elem, container_type) {}
+
+		public bool Validate ()
+		{
+			if (!Ignored && !Hidden && CSType == "") {
+				Console.Write("Field {0} has unknown Type {1} ", Name, CType);
+				Statistics.ThrottledCount++;
+				return false;
+			}
+
+			return true;
+		}
+
+		protected virtual bool Readable {
+			get {
+				return elem.GetAttribute ("readable") != "false";
+			}
+		}
+
+		protected virtual bool Writable {
+			get {
+				return elem.GetAttribute ("writeable") != "false";
+			}
+		}
+
+		protected abstract string DefaultAccess { get; }
+
+		protected string Access {
+			get {
+				return elem.HasAttribute ("access") ? elem.GetAttribute ("access") : DefaultAccess;
+			}
+		}
+
+		public bool IsArray {
+			get {
+				return elem.HasAttribute("array_len") || elem.HasAttribute("array");
+			}
+		}
+
+		public bool IsBitfield {
+			get {
+				return elem.HasAttribute("bits");
+			}
+		}
+
+		public bool Ignored {
+			get {
+				if (container_type.GetProperty (Name) != null)
+					return true;
+				if (IsArray)
+					return true;
+				if (Access == "private" && (Getter == null) && (Setter == null))
+					return true;
+				return false;
+			}
+		}
+
+		string getterName, setterName;
+		string getOffsetName, offsetName;
+
+		void CheckGlue ()
+		{
+			getterName = setterName = getOffsetName = null;
+			if (Access != "public")
+				return;
+
+			string prefix = (container_type.NS + "Sharp_" + container_type.NS + "_" + container_type.Name).ToLower ();
+
+			if (IsBitfield) {
+				if (Readable && Getter == null)
+					getterName = prefix + "_get_" + CName;
+				if (Writable && Setter == null)
+					setterName = prefix + "_set_" + CName;
+			} else {
+				if ((Readable && Getter == null) || (Writable && Setter == null)) {
+					offsetName = CName + "_offset";
+					getOffsetName = prefix + "_get_" + offsetName;
+				}
+			}
+		}
+
+		protected override void GenerateImports (GenerationInfo gen_info, string indent)
+		{
+			StreamWriter sw = gen_info.Writer;
+			SymbolTable table = SymbolTable.Table;
+
+			if (getterName != null) {
+				sw.WriteLine (indent + "[DllImport (\"{0}\")]", gen_info.GluelibName);
+				sw.WriteLine (indent + "extern static {0} {1} ({2} raw);",
+					      table.GetMarshalReturnType (CType), getterName,
+					      container_type.MarshalType);
+			}
+
+			if (setterName != null) {
+				sw.WriteLine (indent + "[DllImport (\"{0}\")]", gen_info.GluelibName);
+				sw.WriteLine (indent + "extern static void {0} ({1} raw, {2} value);",
+					      setterName, container_type.MarshalType, table.GetMarshalType (CType));
+			}
+
+			if (getOffsetName != null) {
+				sw.WriteLine (indent + "[DllImport (\"{0}\")]", gen_info.GluelibName);
+				sw.WriteLine (indent + "extern static uint {0} ();", getOffsetName);
+				sw.WriteLine ();
+				sw.WriteLine (indent + "static uint " + offsetName + " = " + getOffsetName + " ();");
+			}
+
+			base.GenerateImports (gen_info, indent);
+		}
+
+		public virtual void Generate (GenerationInfo gen_info, string indent)
+		{
+			if (Ignored || Hidden)
+				return;
+
+			CheckGlue ();
+			if ((getterName != null || setterName != null || getOffsetName != null) &&
+			    gen_info.GlueWriter == null) {
+				Console.WriteLine ("No glue-filename specified, can't create glue for {0}.{1}",
+						   container_type.Name, Name);
+				return;
+			}
+
+			GenerateImports (gen_info, indent);
+
+			SymbolTable table = SymbolTable.Table;
+			StreamWriter sw = gen_info.Writer;
+			string modifiers = elem.HasAttribute ("new_flag") ? "new " : "";
+			bool is_struct = table.IsStruct (CType) || table.IsBoxed (CType);
+
+			sw.WriteLine (indent + "public " + modifiers + CSType + " " + Name + " {");
+
+			if (Getter != null) {
+				sw.Write (indent + "\tget ");
+				Getter.GenerateBody (gen_info, container_type, "\t");
+				sw.WriteLine ("");
+			} else if (getterName != null) {
+				sw.WriteLine (indent + "\tget {");
+				container_type.Prepare (sw, indent + "\t\t");
+				sw.WriteLine (indent + "\t\t" + CSType + " result = " + table.FromNativeReturn (ctype, getterName + " (" + container_type.CallByName () + ")") + ";");
+				container_type.Finish (sw, indent + "\t\t");
+				sw.WriteLine (indent + "\t\treturn result;");
+				sw.WriteLine (indent + "\t}");
+			} else if (Readable && offsetName != null) {
+				sw.WriteLine (indent + "\tget {");
+				sw.WriteLine (indent + "\t\tunsafe {");
+				if (is_struct) {
+					sw.WriteLine (indent + "\t\t\t" + CSType + "* raw_ptr = (" + CSType + "*)(((byte*)" + container_type.CallByName () + ") + " + offsetName + ");");
+					sw.WriteLine (indent + "\t\t\treturn *raw_ptr;");
+				} else {
+					sw.WriteLine (indent + "\t\t\t" + table.GetMarshalReturnType (CType) + "* raw_ptr = (" + table.GetMarshalReturnType (CType) + "*)(((byte*)" + container_type.CallByName () + ") + " + offsetName + ");");
+					sw.WriteLine (indent + "\t\t\treturn " + table.FromNativeReturn (ctype, "(*raw_ptr)") + ";");
+				}
+				sw.WriteLine (indent + "\t\t}");
+				sw.WriteLine (indent + "\t}");
+			}
+
+			if (Setter != null) {
+				sw.Write (indent + "\tset ");
+				Setter.GenerateBody (gen_info, container_type, "\t");
+				sw.WriteLine ("");
+			} else if (setterName != null) {
+				sw.WriteLine (indent + "\tset {");
+				container_type.Prepare (sw, indent + "\t\t");
+				sw.WriteLine (indent + "\t\t" + setterName + " (" + container_type.CallByName () + ", " + table.CallByName (ctype, "value") + ");");
+				container_type.Finish (sw, indent + "\t\t");
+				sw.WriteLine (indent + "\t}");
+			} else if (Writable && offsetName != null) {
+				sw.WriteLine (indent + "\tset {");
+				sw.WriteLine (indent + "\t\tunsafe {");
+				if (is_struct) {
+					sw.WriteLine (indent + "\t\t\t" + CSType + "* raw_ptr = (" + CSType + "*)(((byte*)" + container_type.CallByName () + ") + " + offsetName + ");");
+					sw.WriteLine (indent + "\t\t\t*raw_ptr = value;");
+				} else {
+					sw.WriteLine (indent + "\t\t\t" + table.GetMarshalReturnType (CType) + "* raw_ptr = (" + table.GetMarshalReturnType (CType) + "*)(((byte*)" + container_type.CallByName () + ") + " + offsetName + ");");
+					sw.WriteLine (indent + "\t\t\t*raw_ptr = " + table.ToNativeReturn (ctype, "value") + ";");
+				}
+				sw.WriteLine (indent + "\t\t}");
+				sw.WriteLine (indent + "\t}");
+			}
+
+			sw.WriteLine (indent + "}");
+			sw.WriteLine ("");
+
+			if (getterName != null || setterName != null || getOffsetName != null)
+				GenerateGlue (gen_info);
+		}
+
+		protected void GenerateGlue (GenerationInfo gen_info)
+		{
+			StreamWriter sw = gen_info.GlueWriter;
+			SymbolTable table = SymbolTable.Table;
+
+			string FieldCType = CType.Replace ("-", " ");
+			bool byref = table[CType] is ByRefGen || table[CType] is StructGen;
+			string GlueCType = byref ? FieldCType + " *" : FieldCType;
+			string ContainerCType = container_type.CName;
+			string ContainerCName = container_type.Name.ToLower ();
+
+			if (getterName != null) {
+				sw.WriteLine ("{0} {1} ({2} *{3});",
+					      GlueCType, getterName, ContainerCType, ContainerCName);
+			}
+			if (setterName != null) {
+				sw.WriteLine ("void {0} ({1} *{2}, {3} value);",
+					      setterName, ContainerCType, ContainerCName, GlueCType);
+			}
+			if (getOffsetName != null)
+				sw.WriteLine ("guint {0} (void);", getOffsetName);
+			sw.WriteLine ("");
+
+			if (getterName != null) {
+				sw.WriteLine (GlueCType);
+				sw.WriteLine ("{0} ({1} *{2})", getterName, ContainerCType, ContainerCName);
+				sw.WriteLine ("{");
+				sw.WriteLine ("\treturn ({0}){1}{2}->{3};", GlueCType,
+					      byref ? "&" : "", ContainerCName, CName);
+				sw.WriteLine ("}");
+				sw.WriteLine ("");
+			}
+			if (setterName != null) {
+				sw.WriteLine ("void");
+				sw.WriteLine ("{0} ({1} *{2}, {3} value)",
+					      setterName, ContainerCType, ContainerCName, GlueCType);
+				sw.WriteLine ("{");
+				sw.WriteLine ("\t{0}->{1} = ({2}){3}value;", ContainerCName, CName,
+					      FieldCType, byref ? "*" : "");
+				sw.WriteLine ("}");
+				sw.WriteLine ("");
+			}
+			if (getOffsetName != null) {
+				sw.WriteLine ("guint");
+				sw.WriteLine ("{0} (void)", getOffsetName);
+				sw.WriteLine ("{");
+				sw.WriteLine ("\treturn (guint)G_STRUCT_OFFSET ({0}, {1});",
+					      ContainerCType, CName);
+				sw.WriteLine ("}");
+				sw.WriteLine ("");
+			}
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/GenBase.cs b/lib/unique-sharp/generator/GenBase.cs
new file mode 100644
index 0000000..db0a004
--- /dev/null
+++ b/lib/unique-sharp/generator/GenBase.cs
@@ -0,0 +1,142 @@
+// GtkSharp.Generation.GenBase.cs - The Generatable base class.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2001-2002 Mike Kestner
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+	using System.Xml;
+
+	public abstract class GenBase : IGeneratable {
+		
+		private XmlElement ns;
+		private XmlElement elem;
+
+		protected GenBase (XmlElement ns, XmlElement elem)
+		{
+			this.ns = ns;
+			this.elem = elem;
+		}
+
+		public string CName {
+			get {
+				return elem.GetAttribute ("cname");
+			}
+		}
+
+		public XmlElement Elem {
+			get {
+				return elem;
+			}
+		}
+
+		public bool IsInternal {
+			get {
+				if (elem.HasAttribute ("internal")) {
+					string attr = elem.GetAttribute ("internal");
+					return attr == "1" || attr == "true";
+				}
+				return false;
+			}
+		}
+
+		public string LibraryName {
+			get {
+				return ns.GetAttribute ("library");
+			}
+		}
+
+		public virtual string MarshalReturnType { 
+			get {
+				return MarshalType;
+			}
+		}
+
+		public abstract string MarshalType { get; }
+
+		public string Name {
+			get {
+				return elem.GetAttribute ("name");
+			}
+		}
+
+		public string NS {
+			get {
+				return ns.GetAttribute ("name");
+			}
+		}
+
+		public abstract string DefaultValue { get; }
+
+		public string QualifiedName {
+			get {
+				return NS + "." + Name;
+			}
+		}
+
+		public virtual string ToNativeReturnType { 
+			get {
+				return MarshalType;
+			}
+		}
+
+		protected void AppendCustom (StreamWriter sw, string custom_dir)
+		{
+			char sep = Path.DirectorySeparatorChar;
+			string custom = custom_dir + sep + Name + ".custom";
+			if (File.Exists(custom)) {
+				sw.WriteLine ("#region Customized extensions");
+				sw.WriteLine ("#line 1 \"" + Name + ".custom\"");
+				FileStream custstream = new FileStream(custom, FileMode.Open, FileAccess.Read);
+				StreamReader sr = new StreamReader(custstream);
+				sw.WriteLine (sr.ReadToEnd ());
+				sw.WriteLine ("#endregion");
+				sr.Close ();
+			}
+		}
+
+		public abstract string CallByName (string var);
+
+		public abstract string FromNative (string var);
+
+		public virtual string FromNativeReturn (string var)
+		{
+			return FromNative (var);
+		}
+
+		public virtual string ToNativeReturn (string var)
+		{
+			return CallByName (var);
+		}
+
+		public abstract bool Validate ();
+
+		public void Generate ()
+		{
+			GenerationInfo geninfo = new GenerationInfo (ns);
+			Generate (geninfo);
+		}
+
+		public abstract void Generate (GenerationInfo geninfo);
+	}
+}
+
diff --git a/lib/unique-sharp/generator/GenerationInfo.cs b/lib/unique-sharp/generator/GenerationInfo.cs
new file mode 100644
index 0000000..7b7619a
--- /dev/null
+++ b/lib/unique-sharp/generator/GenerationInfo.cs
@@ -0,0 +1,188 @@
+// GtkSharp.Generation.GenerationInfo.cs - Generation information class.
+//
+// Author: Mike Kestner <mkestner ximian com>
+//
+// Copyright (c) 2003-2008 Novell Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class GenerationInfo {
+		
+		string dir;
+		string custom_dir;
+		string assembly_name;
+		string gluelib_name;
+		bool glue_enabled;
+		StreamWriter sw;
+		StreamWriter glue_sw;
+
+		public GenerationInfo (XmlElement ns)
+		{
+			string ns_name = ns.GetAttribute ("name");
+			char sep = Path.DirectorySeparatorChar;
+			dir = ".." + sep + ns_name.ToLower () + sep + "generated";
+			custom_dir = ".." + sep + ns_name.ToLower ();
+			assembly_name = ns_name.ToLower () + "-sharp";
+		}
+
+		public GenerationInfo (string dir, string assembly_name) : this (dir, dir, assembly_name, "", "", "") {}
+
+		public GenerationInfo (string dir, string custom_dir, string assembly_name, string glue_filename, string glue_includes, string gluelib_name)
+		{
+			this.dir = dir;
+			this.custom_dir = custom_dir;
+			this.assembly_name = assembly_name;
+			this.gluelib_name = gluelib_name;
+			InitializeGlue (glue_filename, glue_includes, gluelib_name);
+		}
+
+		void InitializeGlue (string glue_filename, string glue_includes, string gluelib_name)
+		{
+			if (gluelib_name != String.Empty && glue_filename != String.Empty) {
+				FileStream stream;
+				try {
+					stream = new FileStream (glue_filename, FileMode.Create, FileAccess.Write);
+				} catch (Exception) {
+					Console.Error.WriteLine ("Unable to create specified glue file.  Glue will not be generated.");
+					return;
+				}
+
+				glue_sw = new StreamWriter (stream);
+			
+				glue_sw.WriteLine ("// This file was generated by the Gtk# code generator.");
+				glue_sw.WriteLine ("// Any changes made will be lost if regenerated.");
+				glue_sw.WriteLine ();
+
+				if (glue_includes != "") {
+					foreach (string header in glue_includes.Split (new char[] {',', ' '})) {
+						if (header != "")
+							glue_sw.WriteLine ("#include <{0}>", header);
+					}
+					glue_sw.WriteLine ("");
+				}
+				glue_sw.WriteLine ("const gchar *__prefix = \"__gtksharp_\";\n");
+				glue_sw.WriteLine ("#define HAS_PREFIX(a) (*((guint64 *)(a)) == *((guint64 *) __prefix))\n");
+				glue_sw.WriteLine ("static GObjectClass *");
+				glue_sw.WriteLine ("get_threshold_class (GObject *obj)");
+				glue_sw.WriteLine ("{");
+				glue_sw.WriteLine ("\tGType gtype = G_TYPE_FROM_INSTANCE (obj);");
+				glue_sw.WriteLine ("\twhile (HAS_PREFIX (g_type_name (gtype)))");
+				glue_sw.WriteLine ("\t\tgtype = g_type_parent (gtype);");
+				glue_sw.WriteLine ("\tGObjectClass *klass = g_type_class_peek (gtype);");
+				glue_sw.WriteLine ("\tif (klass == NULL) klass = g_type_class_ref (gtype);");
+				glue_sw.WriteLine ("\treturn klass;");
+				glue_sw.WriteLine ("}\n");
+				glue_enabled = true;
+			}
+		}
+
+		public string AssemblyName {
+			get {
+				return assembly_name;
+			}
+		}
+
+		public string CustomDir {
+			get {
+				return custom_dir;
+			}
+		}
+
+		public string Dir {
+			get {
+				return dir;
+			}
+		}
+
+		public string GluelibName {
+			get {
+				return gluelib_name;
+			}
+		}
+
+		public bool GlueEnabled {
+			get {
+				return glue_enabled;
+			}
+		}
+
+		public StreamWriter GlueWriter {
+			get {
+				return glue_sw;
+			}
+		}
+
+		public StreamWriter Writer {
+			get {
+				return sw;
+			}
+			set {
+				sw = value;
+			}
+		}
+
+		public void CloseGlueWriter ()
+		{
+			if (glue_sw != null)
+				glue_sw.Close ();
+		}
+
+		string member;
+		public string CurrentMember {
+			get {
+				return typename + "." + member;
+			}
+			set {
+				member = value;
+			}
+		}
+
+		string typename;
+		public string CurrentType {
+			get {
+				return typename;
+			}
+			set {
+				typename = value;
+			}
+		}
+
+		public StreamWriter OpenStream (string name) 
+		{
+			char sep = Path.DirectorySeparatorChar;
+			if (!Directory.Exists(dir))
+				Directory.CreateDirectory(dir);
+			string filename = dir + sep + name + ".cs";
+			
+			FileStream stream = new FileStream (filename, FileMode.Create, FileAccess.Write);
+			StreamWriter sw = new StreamWriter (stream);
+			
+			sw.WriteLine ("// This file was generated by the Gtk# code generator.");
+			sw.WriteLine ("// Any changes made will be lost if regenerated.");
+			sw.WriteLine ();
+
+			return sw;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/HandleBase.cs b/lib/unique-sharp/generator/HandleBase.cs
new file mode 100644
index 0000000..08f7805
--- /dev/null
+++ b/lib/unique-sharp/generator/HandleBase.cs
@@ -0,0 +1,81 @@
+// HandleBase.cs - Base class for Handle types
+//
+// Authors:  Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+	using System.Xml;
+
+	public abstract class HandleBase : ClassBase, IAccessor {
+
+		protected HandleBase (XmlElement ns, XmlElement elem) : base (ns, elem) {}
+					
+		public override string AssignToName {
+			get {
+				return "Raw";
+			}
+		}
+
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+
+		public override string CallByName (string name)
+		{
+			return name + " == null ? IntPtr.Zero : " + name + ".Handle";
+		}
+
+		public override string CallByName ()
+		{
+			return "Handle";
+		}
+
+		public abstract string FromNative (string var, bool owned);
+
+		public override string FromNative (string var)
+		{
+			return FromNative (var, false);
+		}
+
+		public string FromNativeReturn (string var, bool owned)
+		{
+			return FromNative (var, owned);
+		}
+
+		public override string FromNativeReturn (string var)
+		{
+			return FromNativeReturn (var, false);
+		}
+
+		public void WriteAccessors (StreamWriter sw, string indent, string var)
+		{
+			sw.WriteLine (indent + "get {");
+			sw.WriteLine (indent + "\treturn " + FromNative (var, false) + ";");
+			sw.WriteLine (indent + "}");
+			sw.WriteLine (indent + "set {");
+			sw.WriteLine (indent + "\t" + var + " = " + CallByName ("value") + ";");
+			sw.WriteLine (indent + "}");
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/IAccessor.cs b/lib/unique-sharp/generator/IAccessor.cs
new file mode 100644
index 0000000..3cfcfc0
--- /dev/null
+++ b/lib/unique-sharp/generator/IAccessor.cs
@@ -0,0 +1,29 @@
+// IAccessor.cs - Interface to generate property accessors.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	public interface IAccessor  {
+
+		void WriteAccessors (System.IO.StreamWriter sw, string indentation, string field_name);
+
+	}
+}
diff --git a/lib/unique-sharp/generator/IGeneratable.cs b/lib/unique-sharp/generator/IGeneratable.cs
new file mode 100644
index 0000000..1608fd7
--- /dev/null
+++ b/lib/unique-sharp/generator/IGeneratable.cs
@@ -0,0 +1,71 @@
+// GtkSharp.Generation.IGeneratable.cs - Interface to generate code for a type.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2001 Mike Kestner
+// Copyright (c) 2007 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	public interface IGeneratable  {
+
+		// The C name of the generatable
+		string CName {get;}
+
+		// The (short) C# name of the generatable
+		string Name {get;}
+
+		// The fully-qualified C# name of the generatable
+		string QualifiedName {get;}
+
+		// The type (possibly including "ref" or "out") to use in the import
+		// signature when passing this generatable to unmanaged code
+		string MarshalType {get;}
+
+		// The type to use as the return type in an import signature when
+		// receiving this generatable back from unmanaged code
+		string MarshalReturnType {get;}
+
+		// The type to use in a managed callback signature when returning this
+		// generatable to unmanaged code
+		string ToNativeReturnType {get;}
+
+		// The value returned by callbacks that are interrupted prematurely
+		// by managed exceptions or other conditions where an appropriate
+		// value can't be otherwise obtained.
+		string DefaultValue {get;}
+
+		// Generates an expression to convert var_name to MarshalType
+		string CallByName (string var_name);
+
+		// Generates an expression to convert var from MarshalType
+		string FromNative (string var);
+
+		// Generates an expression to convert var from MarshalReturnType
+		string FromNativeReturn (string var);
+
+		// Generates an expression to convert var to ToNativeReturnType
+		string ToNativeReturn (string var);
+
+		bool Validate ();
+
+		void Generate ();
+
+		void Generate (GenerationInfo gen_info);
+	}
+}
diff --git a/lib/unique-sharp/generator/IManualMarshaler.cs b/lib/unique-sharp/generator/IManualMarshaler.cs
new file mode 100644
index 0000000..e9e7eaf
--- /dev/null
+++ b/lib/unique-sharp/generator/IManualMarshaler.cs
@@ -0,0 +1,32 @@
+// GtkSharp.Generation.IManualMarshaler.cs - Interface for manual marshaling.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	public interface IManualMarshaler  {
+
+		string AllocNative (string managed_var);
+
+		string ReleaseNative (string native_var);
+
+	}
+}
+
diff --git a/lib/unique-sharp/generator/InterfaceGen.cs b/lib/unique-sharp/generator/InterfaceGen.cs
new file mode 100644
index 0000000..00cd892
--- /dev/null
+++ b/lib/unique-sharp/generator/InterfaceGen.cs
@@ -0,0 +1,384 @@
+// GtkSharp.Generation.InterfaceGen.cs - The Interface Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2004, 2007 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class InterfaceGen : ObjectBase {
+
+		bool consume_only;
+		ArrayList vms = new ArrayList ();
+		ArrayList members = new ArrayList ();
+
+		public InterfaceGen (XmlElement ns, XmlElement elem) : base (ns, elem) 
+		{
+			consume_only = elem.HasAttribute ("consume_only");
+			foreach (XmlNode node in elem.ChildNodes) {
+				switch (node.Name) {
+				case "virtual_method":
+					VirtualMethod vm = new VirtualMethod (node as XmlElement, this);
+					vms.Add (vm);
+					members.Add (vm);
+					break;
+				case "signal":
+					object sig = sigs [(node as XmlElement).GetAttribute ("name")];
+					if (sig == null)
+						sig = new Signal (node as XmlElement, this);
+					members.Add (sig);
+					break;
+				default:
+					if (!IsNodeNameHandled (node.Name))
+						Console.WriteLine ("Unexpected node " + node.Name + " in " + CName);
+					break;
+				}
+			}
+		}
+
+		public bool IsConsumeOnly {
+			get {
+				return consume_only;
+			}
+		}
+
+		public override string FromNative (string var, bool owned)
+		{
+			return QualifiedName + "Adapter.GetObject (" + var + ", " + (owned ? "true" : "false") + ")";
+		}
+
+		public override bool ValidateForSubclass ()
+		{
+			ArrayList invalids = new ArrayList ();
+
+			foreach (Method method in methods.Values) {
+				if (!method.Validate ()) {
+					Console.WriteLine ("in type " + QualifiedName);
+					invalids.Add (method);
+				}
+			}
+			foreach (Method method in invalids)
+				methods.Remove (method.Name);
+			invalids.Clear ();
+
+			return base.ValidateForSubclass ();
+		}
+
+		string IfaceName {
+			get {
+				return Name + "Iface";
+			}
+		}
+
+		void GenerateIfaceStruct (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tstatic " + IfaceName + " iface;");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tstruct " + IfaceName + " {");
+			sw.WriteLine ("\t\t\tpublic IntPtr gtype;");
+			sw.WriteLine ("\t\t\tpublic IntPtr itype;");
+			sw.WriteLine ();
+
+			foreach (object member in members) {
+				if (member is Signal) {
+					Signal sig = member as Signal;
+					sw.WriteLine ("\t\t\tpublic IntPtr {0};", sig.CName.Replace ("\"", "").Replace ("-", "_"));
+				} else if (member is VirtualMethod) {
+					VirtualMethod vm = member as VirtualMethod;
+					bool has_target = methods [vm.Name] != null;
+					if (!has_target)
+						Console.WriteLine ("Interface " + QualifiedName + " virtual method " + vm.Name + " has no matching method to invoke.");
+					string type = has_target && vm.IsValid ? vm.Name + "Delegate" : "IntPtr";
+					sw.WriteLine ("\t\t\tpublic " + type + " " + vm.CName + ";");
+				}
+			}
+
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateStaticCtor (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tstatic " + Name + "Adapter ()");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tGLib.GType.Register (_gtype, typeof({0}Adapter));", Name);
+			foreach (VirtualMethod vm in vms) {
+				bool has_target = methods [vm.Name] != null;
+				if (has_target && vm.IsValid)
+					sw.WriteLine ("\t\t\tiface.{0} = new {1}Delegate ({1}Callback);", vm.CName, vm.Name);
+			}
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateInitialize (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tstatic void Initialize (IntPtr ifaceptr, IntPtr data)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\t" + IfaceName + " native_iface = (" + IfaceName + ") Marshal.PtrToStructure (ifaceptr, typeof (" + IfaceName + "));");
+			foreach (VirtualMethod vm in vms)
+				sw.WriteLine ("\t\t\tnative_iface." + vm.CName + " = iface." + vm.CName + ";");
+			sw.WriteLine ("\t\t\tMarshal.StructureToPtr (native_iface, ifaceptr, false);");
+			sw.WriteLine ("\t\t\tGCHandle gch = (GCHandle) data;");
+			sw.WriteLine ("\t\t\tgch.Free ();");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateCallbacks (StreamWriter sw)
+		{
+			foreach (VirtualMethod vm in vms) {
+				if (methods [vm.Name] != null) {
+					sw.WriteLine ();
+					vm.GenerateCallback (sw);
+				}
+			}
+		}
+
+		void GenerateCtors (StreamWriter sw)
+		{
+			if (!IsConsumeOnly) {
+				sw.WriteLine ("\t\tpublic " + Name + "Adapter ()");
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tInitHandler = new GLib.GInterfaceInitHandler (Initialize);");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+				sw.WriteLine ("\t\t{0}Implementor implementor;", Name);
+				sw.WriteLine ();
+				sw.WriteLine ("\t\tpublic {0}Adapter ({0}Implementor implementor)", Name);
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tif (implementor == null)");
+				sw.WriteLine ("\t\t\t\tthrow new ArgumentNullException (\"implementor\");");
+				sw.WriteLine ("\t\t\tthis.implementor = implementor;");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+			}
+			sw.WriteLine ("\t\tpublic " + Name + "Adapter (IntPtr handle)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tthis.handle = handle;");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateGType (StreamWriter sw)
+		{
+			Method m = GetMethod ("GetType");
+			m.GenerateImport (sw);
+			sw.WriteLine ("\t\tprivate static GLib.GType _gtype = new GLib.GType ({0} ());", m.CName);
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic override GLib.GType GType {");
+			sw.WriteLine ("\t\t\tget {");
+			sw.WriteLine ("\t\t\t\treturn _gtype;");
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateHandleProp (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tIntPtr handle;");
+			sw.WriteLine ("\t\tpublic override IntPtr Handle {");
+			sw.WriteLine ("\t\t\tget {");
+			if (IsConsumeOnly) {
+				sw.WriteLine ("\t\t\t\treturn handle;");
+			} else {
+				sw.WriteLine ("\t\t\t\tif (handle != IntPtr.Zero)");
+				sw.WriteLine ("\t\t\t\t\treturn handle;");
+				sw.WriteLine ("\t\t\t\treturn implementor == null ? IntPtr.Zero : implementor.Handle;");
+			}
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateGetObject (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tpublic static " + Name + " GetObject (IntPtr handle, bool owned)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tGLib.Object obj = GLib.Object.GetObject (handle, owned);");
+			sw.WriteLine ("\t\t\treturn GetObject (obj);");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tpublic static " + Name + " GetObject (GLib.Object obj)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tif (obj == null)");
+			sw.WriteLine ("\t\t\t\treturn null;");
+			if (!IsConsumeOnly) {
+				sw.WriteLine ("\t\t\telse if (obj is " + Name + "Implementor)");
+				sw.WriteLine ("\t\t\t\treturn new {0}Adapter (obj as {0}Implementor);", Name);
+			}
+			sw.WriteLine ("\t\t\telse if (obj as " + Name + " == null)");
+			sw.WriteLine ("\t\t\t\treturn new {0}Adapter (obj.Handle);", Name);
+			sw.WriteLine ("\t\t\telse");
+			sw.WriteLine ("\t\t\t\treturn obj as {0};", Name);
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateImplementorProp (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tpublic " + Name + "Implementor Implementor {");
+			sw.WriteLine ("\t\t\tget {");
+			sw.WriteLine ("\t\t\t\treturn implementor;");
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		void GenerateAdapter (GenerationInfo gen_info)
+		{
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name + "Adapter");
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+			sw.WriteLine ("#region Autogenerated code");
+			sw.WriteLine ("\tpublic class " + Name + "Adapter : GLib.GInterfaceAdapter, " + QualifiedName + " {");
+			sw.WriteLine ();
+
+			if (!IsConsumeOnly) {
+				GenerateIfaceStruct (sw);
+				GenerateStaticCtor (sw);
+				GenerateCallbacks (sw);
+				GenerateInitialize (sw);
+			}
+			GenerateCtors (sw);
+			GenerateGType (sw);
+			GenerateHandleProp (sw);
+			GenerateGetObject (sw);
+			if (!IsConsumeOnly)
+				GenerateImplementorProp (sw);
+
+			GenProperties (gen_info, null);
+
+			foreach (Signal sig in sigs.Values)
+				sig.GenEvent (sw, null, "GLib.Object.GetObject (Handle)");
+
+			Method temp = methods ["GetType"] as Method;
+			if (temp != null)
+				methods.Remove ("GetType");
+			GenMethods (gen_info, new Hashtable (), this);
+			if (temp != null)
+				methods ["GetType"] = temp;
+
+			sw.WriteLine ("#endregion");
+
+			string custom = Path.Combine (gen_info.CustomDir, Name + "Adapter.custom");
+			if (File.Exists (custom)) {
+				sw.WriteLine ("#region Customized extensions");
+				sw.WriteLine ("#line 1 \"" + Name + "Adapter.custom\"");
+				using (StreamReader sr = new StreamReader(new FileStream (custom, FileMode.Open, FileAccess.Read)))
+					sw.WriteLine (sr.ReadToEnd ());
+				
+				sw.WriteLine ("#endregion");
+			}
+
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+			sw.Close ();
+			gen_info.Writer = null;
+		}
+
+		void GenerateImplementorIface (StreamWriter sw)
+		{
+			if (IsConsumeOnly)
+				return;
+
+			sw.WriteLine ();
+			sw.WriteLine ("\t[GLib.GInterface (typeof (" + Name + "Adapter))]");
+			string access = IsInternal ? "internal" : "public";
+			sw.WriteLine ("\t" + access + " interface " + Name + "Implementor : GLib.IWrapper {");
+			sw.WriteLine ();
+			Hashtable vm_table = new Hashtable ();
+			foreach (VirtualMethod vm in vms)
+				vm_table [vm.Name] = vm;
+			foreach (VirtualMethod vm in vms) {
+				if (vm_table [vm.Name] == null)
+					continue;
+				else if (!vm.IsValid) {
+					vm_table.Remove (vm.Name);
+					continue;
+				} else if (vm.IsGetter || vm.IsSetter) {
+					string cmp_name = (vm.IsGetter ? "Set" : "Get") + vm.Name.Substring (3);
+					VirtualMethod cmp = vm_table [cmp_name] as VirtualMethod;
+					if (cmp != null && (cmp.IsGetter || cmp.IsSetter)) {
+						if (vm.IsSetter)
+							cmp.GenerateDeclaration (sw, vm);
+						else
+							vm.GenerateDeclaration (sw, cmp);
+						vm_table.Remove (cmp.Name);
+					} else 
+						vm.GenerateDeclaration (sw, null);
+					vm_table.Remove (vm.Name);
+				} else {
+					vm.GenerateDeclaration (sw, null);
+					vm_table.Remove (vm.Name);
+				}
+			}
+			sw.WriteLine ("\t}");
+		}
+
+		public override void Generate (GenerationInfo gen_info)
+		{
+			GenerateAdapter (gen_info);
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ();
+			sw.WriteLine ("#region Autogenerated code");
+			string access = IsInternal ? "internal" : "public";
+			sw.WriteLine ("\t" + access + " interface " + Name + " : GLib.IWrapper {");
+			sw.WriteLine ();
+			
+			foreach (Signal sig in sigs.Values) {
+				sig.GenerateDecl (sw);
+				sig.GenEventHandler (gen_info);
+			}
+
+			foreach (Method method in methods.Values) {
+				if (IgnoreMethod (method, this))
+					continue;
+				method.GenerateDecl (sw);
+			}
+
+			foreach (Property prop in props.Values)
+				prop.GenerateDecl (sw, "\t\t");
+
+			AppendCustom (sw, gen_info.CustomDir);
+
+			sw.WriteLine ("\t}");
+			GenerateImplementorIface (sw);
+			sw.WriteLine ("#endregion");
+			sw.WriteLine ("}");
+			sw.Close ();
+			gen_info.Writer = null;
+			Statistics.IFaceCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/LPGen.cs b/lib/unique-sharp/generator/LPGen.cs
new file mode 100644
index 0000000..3fb774e
--- /dev/null
+++ b/lib/unique-sharp/generator/LPGen.cs
@@ -0,0 +1,58 @@
+// GtkSharp.Generation.LPGen.cs - long/pointer Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+
+	public class LPGen : SimpleGen, IAccessor {
+		
+		public LPGen (string ctype) : base (ctype, "long", "0L") {}
+
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+
+		public override string CallByName (string var_name)
+		{
+			return "new IntPtr (" + var_name + ")";
+		}
+		
+		public override string FromNative(string var)
+		{
+			return "(long) " + var;
+		}
+
+		public void WriteAccessors (StreamWriter sw, string indent, string var)
+		{
+			sw.WriteLine (indent + "get {");
+			sw.WriteLine (indent + "\treturn " + FromNative (var) + ";");
+			sw.WriteLine (indent + "}");
+			sw.WriteLine (indent + "set {");
+			sw.WriteLine (indent + "\t" + var + " = " + CallByName ("value") + ";");
+			sw.WriteLine (indent + "}");
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/LPUGen.cs b/lib/unique-sharp/generator/LPUGen.cs
new file mode 100644
index 0000000..331b25f
--- /dev/null
+++ b/lib/unique-sharp/generator/LPUGen.cs
@@ -0,0 +1,58 @@
+// GtkSharp.Generation.LPUGen.cs - unsugned long/pointer generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+
+	public class LPUGen : SimpleGen, IAccessor {
+		
+		public LPUGen (string ctype) : base (ctype, "ulong", "0") {}
+
+		public override string MarshalType {
+			get {
+				return "UIntPtr";
+			}
+		}
+
+		public override string CallByName (string var_name)
+		{
+			return "new UIntPtr (" + var_name + ")";
+		}
+		
+		public override string FromNative(string var)
+		{
+			return "(ulong) " + var;
+		}
+
+		public void WriteAccessors (StreamWriter sw, string indent, string var)
+		{
+			sw.WriteLine (indent + "get {");
+			sw.WriteLine (indent + "\treturn " + FromNative (var) + ";");
+			sw.WriteLine (indent + "}");
+			sw.WriteLine (indent + "set {");
+			sw.WriteLine (indent + "\t" + var + " = " + CallByName ("value") + ";");
+			sw.WriteLine (indent + "}");
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ManagedCallString.cs b/lib/unique-sharp/generator/ManagedCallString.cs
new file mode 100644
index 0000000..409eb36
--- /dev/null
+++ b/lib/unique-sharp/generator/ManagedCallString.cs
@@ -0,0 +1,152 @@
+// GtkSharp.Generation.ManagedCallString.cs - The ManagedCallString Class.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2003 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+
+	public class ManagedCallString {
+		
+		ArrayList parms = new ArrayList ();
+		ArrayList special = new ArrayList ();
+		string error_param = null;
+		string user_data_param = null;
+		string destroy_param = null;
+
+		public ManagedCallString (Parameters parms, bool drop_first)
+		{
+			for (int i = drop_first ? 1 : 0; i < parms.Count; i ++) {
+				Parameter p = parms [i];
+				if (p.IsLength && i > 0 && parms [i-1].IsString) 
+					continue;
+				else if (p.Scope == "notified") {
+					user_data_param = parms[i+1].Name;
+					destroy_param = parms[i+2].Name;
+					i += 2;
+				} else if (p.IsUserData && parms.IsHidden (p)) {
+					user_data_param = p.Name;
+					continue;
+				} else if (p is ErrorParameter) {
+					error_param = p.Name;
+					continue;
+				}
+				this.parms.Add (p);
+
+				if (p.PassAs != String.Empty && (p.Name != p.FromNative (p.Name)))
+					this.special.Add (true);
+				else if (p.Generatable is CallbackGen)
+					this.special.Add (true);
+				else
+					this.special.Add (false);
+			}
+		}
+
+		public bool HasOutParam {
+			get {
+				foreach (Parameter p in parms) {
+					if (p.PassAs == "out")
+						return true;
+				}
+				return false;
+			}
+		}
+
+		public string Unconditional (string indent) {
+			string ret = "";
+			if (error_param != null)
+				ret = indent + error_param + " = IntPtr.Zero;\n";
+			return ret;
+		}
+
+		public string Setup (string indent)
+		{
+			string ret = "";
+
+			for (int i = 0; i < parms.Count; i ++) {
+				if ((bool)special[i] == false)
+					continue;
+
+				Parameter p = parms [i] as Parameter;
+				IGeneratable igen = p.Generatable;
+
+				if (igen is CallbackGen) {
+					if (user_data_param == null)
+						ret += indent + String.Format ("{0} {1}_invoker = new {0} ({1});\n", (igen as CallbackGen).InvokerName, p.Name);
+					else if (destroy_param == null)
+						ret += indent + String.Format ("{0} {1}_invoker = new {0} ({1}, {2});\n", (igen as CallbackGen).InvokerName, p.Name, user_data_param);
+					else
+						ret += indent + String.Format ("{0} {1}_invoker = new {0} ({1}, {2}, {3});\n", (igen as CallbackGen).InvokerName, p.Name, user_data_param, destroy_param);
+				} else {
+					ret += indent + igen.QualifiedName + " my" + p.Name;
+					if (p.PassAs == "ref")
+						ret += " = " + p.FromNative (p.Name);
+					ret += ";\n";
+				}
+			}
+
+			return ret;
+		}
+
+		public override string ToString ()
+		{
+			if (parms.Count < 1)
+				return "";
+
+			string[] result = new string [parms.Count];
+
+			for (int i = 0; i < parms.Count; i ++) {
+				Parameter p = parms [i] as Parameter;
+				result [i] = p.PassAs == "" ? "" : p.PassAs + " ";
+				if (p.Generatable is CallbackGen)
+					result [i] += p.Name + "_invoker.Handler";
+				else
+					result [i] += ((bool)special[i]) ? "my" + p.Name : p.FromNative (p.Name);
+			}
+
+			return String.Join (", ", result);
+		}
+
+		public string Finish (string indent)
+		{
+			string ret = "";
+
+			for (int i = 0; i < parms.Count; i ++) {
+				if ((bool)special[i] == false)
+					continue;
+
+				Parameter p = parms [i] as Parameter;
+				IGeneratable igen = p.Generatable;
+
+				if (igen is CallbackGen)
+					continue;
+				else if (igen is StructBase || igen is ByRefGen)
+					ret += indent + String.Format ("if ({0} != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (my{0}, {0}, false);\n", p.Name);
+				else
+					ret += indent + p.Name + " = " + igen.ToNativeReturn ("my" + p.Name) + ";\n";
+			}
+
+			return ret;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ManualGen.cs b/lib/unique-sharp/generator/ManualGen.cs
new file mode 100644
index 0000000..1d94916
--- /dev/null
+++ b/lib/unique-sharp/generator/ManualGen.cs
@@ -0,0 +1,58 @@
+// GtkSharp.Generation.ManualGen.cs - Ungenerated handle type Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2003 Mike Kestner
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class ManualGen : SimpleBase {
+		
+		string from_fmt;
+
+		public ManualGen (string ctype, string type) : base (ctype, type, "null") 
+		{
+			from_fmt = "new " + QualifiedName + "({0})";
+		}
+
+		public ManualGen (string ctype, string type, string from_fmt) : base (ctype, type, "null")
+		{
+			this.from_fmt = from_fmt;
+		}
+		
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+
+		public override string CallByName (string var_name)
+		{
+			return var_name + " == null ? IntPtr.Zero : " + var_name + ".Handle";
+		}
+		
+		public override string FromNative(string var)
+		{
+			return String.Format (from_fmt, var);
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/MarshalGen.cs b/lib/unique-sharp/generator/MarshalGen.cs
new file mode 100644
index 0000000..820961c
--- /dev/null
+++ b/lib/unique-sharp/generator/MarshalGen.cs
@@ -0,0 +1,56 @@
+// GtkSharp.Generation.MarshalGen.cs - Simple marshaling Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class MarshalGen : SimpleBase {
+		
+		string mtype;
+		string call_fmt;
+		string from_fmt;
+
+		public MarshalGen (string ctype, string type, string mtype, string call_fmt, string from_fmt) : base (ctype, type, "null")
+		{
+			this.mtype = mtype;
+			this.call_fmt = call_fmt;
+			this.from_fmt = from_fmt;
+		}
+		
+		public override string MarshalType {
+			get {
+				return mtype;
+			}
+		}
+
+		public override string CallByName (string var)
+		{
+			return String.Format (call_fmt, var);
+		}
+		
+		public override string FromNative (string var)
+		{
+			return String.Format (from_fmt, var);
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Method.cs b/lib/unique-sharp/generator/Method.cs
new file mode 100644
index 0000000..76cd721
--- /dev/null
+++ b/lib/unique-sharp/generator/Method.cs
@@ -0,0 +1,304 @@
+// GtkSharp.Generation.Method.cs - The Method Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class Method : MethodBase  {
+		
+		private ReturnValue retval;
+
+		private string call;
+		private bool is_get, is_set;
+		private bool deprecated = false;
+
+		public Method (XmlElement elem, ClassBase container_type) : base (elem, container_type)
+		{
+			this.retval = new ReturnValue (elem["return-type"]);
+			
+			if (!container_type.IsDeprecated && elem.HasAttribute ("deprecated")) {
+				string attr = elem.GetAttribute ("deprecated");
+				deprecated = attr == "1" || attr == "true";
+			}
+			
+			if (Name == "GetType")
+				Name = "GetGType";
+		}
+
+		public bool IsDeprecated {
+			get {
+				return deprecated;
+			}
+		}
+
+		public bool IsGetter {
+			get {
+				return is_get;
+			}
+		}
+
+		public bool IsSetter {
+			get {
+				return is_set;
+			}
+		}
+
+		public string ReturnType {
+			get {
+				return retval.CSType;
+			}
+		}
+
+		public override bool Validate ()
+		{
+			if (!retval.Validate () || !base.Validate ()) {
+				Console.Write(" in method " + Name + " ");
+				return false;
+			}
+
+			Parameters parms = Parameters;
+			is_get = ((((parms.IsAccessor && retval.IsVoid) || (parms.Count == 0 && !retval.IsVoid)) || (parms.Count == 0 && !retval.IsVoid)) && HasGetterName);
+			is_set = ((parms.IsAccessor || (parms.VisibleCount == 1 && retval.IsVoid)) && HasSetterName);
+
+			call = "(" + (IsStatic ? "" : container_type.CallByName () + (parms.Count > 0 ? ", " : "")) + Body.GetCallString (is_set) + ")";
+
+			return true;
+		}
+		
+		private Method GetComplement ()
+		{
+			char complement;
+			if (is_get)
+				complement = 'S';
+			else
+				complement = 'G';
+			
+			return container_type.GetMethod (complement + BaseName.Substring (1));
+		}
+		
+		public string Declaration {
+			get {
+				return retval.CSType + " " + Name + " (" + (Signature != null ? Signature.ToString() : "") + ");";
+			}
+		}
+
+		private void GenerateDeclCommon (StreamWriter sw, ClassBase implementor)
+		{
+			if (IsStatic)
+				sw.Write("static ");
+			sw.Write (Safety);
+			Method dup = null;
+			if (container_type != null)
+				dup = container_type.GetMethodRecursively (Name);
+			if (implementor != null)
+				dup = implementor.GetMethodRecursively (Name);
+
+			if (Name == "ToString" && Parameters.Count == 0)
+				sw.Write("override ");
+			else if (Name == "GetGType" && container_type is ObjectGen)
+				sw.Write("new ");
+			else if (Modifiers == "new " || (dup != null && ((dup.Signature != null && Signature != null && dup.Signature.ToString() == Signature.ToString()) || (dup.Signature == null && Signature == null))))
+				sw.Write("new ");
+
+			if (is_get || is_set) {
+				if (retval.IsVoid)
+					sw.Write (Parameters.AccessorReturnType);
+				else
+					sw.Write(retval.CSType);
+				sw.Write(" ");
+				if (Name.StartsWith ("Get") || Name.StartsWith ("Set"))
+					sw.Write (Name.Substring (3));
+				else {
+					int dot = Name.LastIndexOf ('.');
+					if (dot != -1 && (Name.Substring (dot + 1, 3) == "Get" || Name.Substring (dot + 1, 3) == "Set"))
+						sw.Write (Name.Substring (0, dot + 1) + Name.Substring (dot + 4));
+					else
+						sw.Write (Name);
+				}
+				sw.WriteLine(" { ");
+			} else if (IsAccessor) {
+				sw.Write (Signature.AccessorType + " " + Name + "(" + Signature.AsAccessor + ")");
+			} else {
+				sw.Write(retval.CSType + " " + Name + "(" + (Signature != null ? Signature.ToString() : "") + ")");
+			}
+		}
+
+		public void GenerateDecl (StreamWriter sw)
+		{
+			if (IsStatic)
+				return;
+
+			if (is_get || is_set)
+			{
+				Method comp = GetComplement ();
+				if (comp != null && is_set)
+					return;
+			
+				sw.Write("\t\t");
+				GenerateDeclCommon (sw, null);
+
+				sw.Write("\t\t\t");
+				sw.Write ((is_get) ? "get;" : "set;");
+
+				if (comp != null && comp.is_set)
+					sw.WriteLine (" set;");
+				else
+					sw.WriteLine ();
+
+				sw.WriteLine ("\t\t}");
+			}
+			else
+			{
+				sw.Write("\t\t");
+				GenerateDeclCommon (sw, null);
+				sw.WriteLine (";");
+			}
+
+			Statistics.MethodCount++;
+		}
+
+		public void GenerateImport (StreamWriter sw)
+		{
+			string import_sig = IsStatic ? "" : container_type.MarshalType + " raw";
+			import_sig += !IsStatic && Parameters.Count > 0 ? ", " : "";
+			import_sig += Parameters.ImportSignature.ToString();
+			sw.WriteLine("\t\t[DllImport(\"" + LibraryName + "\")]");
+			if (retval.MarshalType.StartsWith ("[return:"))
+				sw.WriteLine("\t\t" + retval.MarshalType + " static extern " + Safety + retval.CSType + " " + CName + "(" + import_sig + ");");
+			else
+				sw.WriteLine("\t\tstatic extern " + Safety + retval.MarshalType + " " + CName + "(" + import_sig + ");");
+			sw.WriteLine();
+		}
+
+		public void Generate (GenerationInfo gen_info, ClassBase implementor)
+		{
+			if (!Validate ())
+				return;
+
+			Method comp = null;
+
+			gen_info.CurrentMember = Name;
+
+			/* we are generated by the get Method, if there is one */
+			if (is_set || is_get)
+			{
+				if (Modifiers != "new " && container_type.GetPropertyRecursively (Name.Substring (3)) != null)
+					return;
+				comp = GetComplement ();
+				if (comp != null && is_set) {
+					if (Parameters.AccessorReturnType == comp.ReturnType)
+						return;
+					else {
+						is_set = false;
+						call = "(Handle, " + Body.GetCallString (false) + ")";
+						comp = null;
+					}
+				}
+				/* some setters take more than one arg */
+				if (comp != null && !comp.is_set)
+					comp = null;
+			}
+			
+			GenerateImport (gen_info.Writer);
+			if (comp != null && retval.CSType == comp.Parameters.AccessorReturnType)
+				comp.GenerateImport (gen_info.Writer);
+
+			if (IsDeprecated)
+				gen_info.Writer.WriteLine("\t\t[Obsolete]");
+			gen_info.Writer.Write("\t\t");
+			if (Protection != "")
+				gen_info.Writer.Write("{0} ", Protection);
+			GenerateDeclCommon (gen_info.Writer, implementor);
+
+			if (is_get || is_set)
+			{
+				gen_info.Writer.Write ("\t\t\t");
+				gen_info.Writer.Write ((is_get) ? "get" : "set");
+				GenerateBody (gen_info, implementor, "\t");
+			}
+			else
+				GenerateBody (gen_info, implementor, "");
+			
+			if (is_get || is_set)
+			{
+				if (comp != null && retval.CSType == comp.Parameters.AccessorReturnType)
+				{
+					gen_info.Writer.WriteLine ();
+					gen_info.Writer.Write ("\t\t\tset");
+					comp.GenerateBody (gen_info, implementor, "\t");
+				}
+				gen_info.Writer.WriteLine ();
+				gen_info.Writer.WriteLine ("\t\t}");
+			}
+			else
+				gen_info.Writer.WriteLine();
+			
+			gen_info.Writer.WriteLine();
+
+			Statistics.MethodCount++;
+		}
+
+		public void GenerateBody (GenerationInfo gen_info, ClassBase implementor, string indent)
+		{
+			StreamWriter sw = gen_info.Writer;
+			sw.WriteLine(" {");
+			if (!IsStatic && implementor != null)
+				implementor.Prepare (sw, indent + "\t\t\t");
+			if (IsAccessor)
+				Body.InitAccessor (sw, Signature, indent);
+			Body.Initialize(gen_info, is_get, is_set, indent);
+
+			sw.Write(indent + "\t\t\t");
+			if (retval.IsVoid)
+				sw.WriteLine(CName + call + ";");
+			else {
+				sw.WriteLine(retval.MarshalType + " raw_ret = " + CName + call + ";");
+				sw.WriteLine(indent + "\t\t\t" + retval.CSType + " ret = " + retval.FromNative ("raw_ret") + ";");
+			}
+
+			if (!IsStatic && implementor != null)
+				implementor.Finish (sw, indent + "\t\t\t");
+			Body.Finish (sw, indent);
+			Body.HandleException (sw, indent);
+
+			if (is_get && Parameters.Count > 0) 
+				sw.WriteLine (indent + "\t\t\treturn " + Parameters.AccessorName + ";");
+			else if (!retval.IsVoid)
+				sw.WriteLine (indent + "\t\t\treturn ret;");
+			else if (IsAccessor)
+				Body.FinishAccessor (sw, Signature, indent);
+
+			sw.Write(indent + "\t\t}");
+		}
+
+		bool IsAccessor { 
+			get { 
+				return retval.IsVoid && Signature.IsAccessor; 
+			} 
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/MethodBase.cs b/lib/unique-sharp/generator/MethodBase.cs
new file mode 100644
index 0000000..9a25fa0
--- /dev/null
+++ b/lib/unique-sharp/generator/MethodBase.cs
@@ -0,0 +1,184 @@
+// GtkSharp.Generation.MethodBase.cs - function element base class.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2004-2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Xml;
+
+	public abstract class MethodBase  {
+
+		XmlElement elem;
+		protected ClassBase container_type;
+		Parameters parms;
+		bool is_static = false;
+		string mods = String.Empty;
+		string name;
+		private string protection = "public";
+
+		protected MethodBase (XmlElement elem, ClassBase container_type) 
+		{
+			this.elem = elem;
+			this.container_type = container_type;
+			this.name = elem.GetAttribute ("name");
+			parms = new Parameters (elem ["parameters"]);
+			IsStatic = elem.GetAttribute ("shared") == "true";
+			if (elem.HasAttribute ("new_flag"))
+				mods = "new ";
+			if (elem.HasAttribute ("accessibility")) {
+				string attr = elem.GetAttribute ("accessibility");
+				switch (attr) {
+					case "public":
+					case "protected":
+					case "internal":
+					case "private":
+					case "protected internal":
+						protection = attr;
+						break;
+				}
+			}
+		}
+
+		protected string BaseName {
+			get {
+				string name = Name;
+				int idx = Name.LastIndexOf (".");
+				if (idx > 0)
+					name = Name.Substring (idx + 1);
+				return name;
+			}
+		}
+
+		MethodBody body;
+		public MethodBody Body {
+			get {
+				if (body == null)
+					body = new MethodBody (parms);
+				return body;
+			}
+		}
+
+		public string CName {
+			get {
+				return SymbolTable.Table.MangleName (elem.GetAttribute ("cname"));
+			}
+		}
+
+		protected bool HasGetterName {
+			get {
+				string name = BaseName;
+				if (name.Length <= 3)
+					return false;
+				if (name.StartsWith ("Get") || name.StartsWith ("Has"))
+					return Char.IsUpper (name [3]);
+				else if (name.StartsWith ("Is"))
+					return Char.IsUpper (name [2]);
+				else
+					return false;
+			}
+		}
+
+		protected bool HasSetterName {
+			get {
+				string name = BaseName;
+				if (name.Length <= 3)
+					return false;
+
+				return name.StartsWith ("Set") && Char.IsUpper (name [3]);
+			}
+		}
+
+		public bool IsStatic {
+			get {
+				return is_static;
+			}
+			set {
+				is_static = value;
+				parms.Static = value;
+			}
+		}
+
+		public string LibraryName {
+			get {
+				if (elem.HasAttribute ("library"))
+					return elem.GetAttribute ("library");
+				return container_type.LibraryName;
+			}
+		}
+
+		public string Modifiers {
+			get {
+				return mods;
+			}
+			set {
+				mods = value;
+			}
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+			set {
+				name = value;
+			}
+		}
+
+		public Parameters Parameters {
+			get {
+				return parms;
+			}
+		}
+	
+		public string Protection {
+			get { return protection; }
+			set { protection = value; }
+		}
+
+		protected string Safety {
+			get {
+				return Body.ThrowsException && !(container_type is InterfaceGen) ? "unsafe " : "";
+			}
+		}
+
+		Signature sig;
+		public Signature Signature {
+			get {
+				if (sig == null)
+					sig = new Signature (parms);
+				return sig;
+			}
+		}
+
+		public virtual bool Validate ()
+		{
+			if (!parms.Validate ()) {
+				Console.Write("in " + CName + " ");
+				Statistics.ThrottledCount++;
+				return false;
+			}
+
+			return true;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/MethodBody.cs b/lib/unique-sharp/generator/MethodBody.cs
new file mode 100644
index 0000000..cee7079
--- /dev/null
+++ b/lib/unique-sharp/generator/MethodBody.cs
@@ -0,0 +1,177 @@
+// GtkSharp.Generation.MethodBody.cs - The MethodBody Generation Class.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+
+	public class MethodBody  {
+		
+		Parameters parameters;
+
+		public MethodBody (Parameters parms) 
+		{
+			parameters = parms;
+		}
+
+		private string CastFromInt (string type)
+		{
+			return type != "int" ? "(" + type + ") " : "";
+		}
+
+		public string GetCallString (bool is_set)
+		{
+			if (parameters.Count == 0)
+				return String.Empty;
+
+			string[] result = new string [parameters.Count];
+			for (int i = 0; i < parameters.Count; i++) {
+				Parameter p = parameters [i];
+				IGeneratable igen = p.Generatable;
+
+				bool is_prop = is_set && i == 0;
+
+				if (i > 0 && parameters [i - 1].IsString && p.IsLength && p.PassAs == String.Empty) {
+					string string_name = (i == 1 && is_set) ? "value" : parameters [i - 1].Name;
+					result[i] = igen.CallByName (CastFromInt (p.CSType) + "System.Text.Encoding.UTF8.GetByteCount (" +  string_name + ")");
+					continue;
+				}
+
+				if (is_prop)
+					p.CallName = "value";
+				else
+					p.CallName = p.Name;
+				string call_parm = p.CallString;
+
+				if (p.IsUserData && parameters.IsHidden (p) && !parameters.HideData &&
+					   (i == 0 || parameters [i - 1].Scope != "notified")) {
+					call_parm = "IntPtr.Zero"; 
+				}
+
+				result [i] += call_parm;
+			}
+
+			return String.Join (", ", result);
+		}
+
+		public void Initialize (GenerationInfo gen_info)
+		{
+			Initialize (gen_info, false, false, String.Empty);
+		}
+
+		public void Initialize (GenerationInfo gen_info, bool is_get, bool is_set, string indent)
+		{
+			if (parameters.Count == 0)
+				return;
+
+			StreamWriter sw = gen_info.Writer;
+			for (int i = 0; i < parameters.Count; i++) {
+				Parameter p = parameters [i];
+
+				IGeneratable gen = p.Generatable;
+				string name = p.Name;
+				if (is_set)
+					name = "value";
+
+				p.CallName = name;
+				foreach (string prep in p.Prepare)
+					sw.WriteLine (indent + "\t\t\t" + prep);
+
+				if (gen is CallbackGen) {
+					CallbackGen cbgen = gen as CallbackGen;
+					string wrapper = cbgen.GenWrapper(gen_info);
+					switch (p.Scope) {
+					case "notified":
+						sw.WriteLine (indent + "\t\t\t{0} {1}_wrapper = new {0} ({1});", wrapper, name);
+						sw.WriteLine (indent + "\t\t\tIntPtr {0};", parameters [i + 1].Name);
+						sw.WriteLine (indent + "\t\t\t{0} {1};", parameters [i + 2].CSType, parameters [i + 2].Name);
+						sw.WriteLine (indent + "\t\t\tif ({0} == null) {{", name);
+						sw.WriteLine (indent + "\t\t\t\t{0} = IntPtr.Zero;", parameters [i + 1].Name);
+						sw.WriteLine (indent + "\t\t\t\t{0} = null;", parameters [i + 2].Name);
+						sw.WriteLine (indent + "\t\t\t} else {");
+						sw.WriteLine (indent + "\t\t\t\t{0} = (IntPtr) GCHandle.Alloc ({1}_wrapper);", parameters [i + 1].Name, name);
+						sw.WriteLine (indent + "\t\t\t\t{0} = GLib.DestroyHelper.NotifyHandler;", parameters [i + 2].Name, parameters [i + 2].CSType);
+						sw.WriteLine (indent + "\t\t\t}");
+						break;
+
+					case "async":
+						sw.WriteLine (indent + "\t\t\t{0} {1}_wrapper = new {0} ({1});", wrapper, name);
+						sw.WriteLine (indent + "\t\t\t{0}_wrapper.PersistUntilCalled ();", name);
+						break;
+					case "call":
+					default:
+						if (p.Scope == String.Empty)
+							Console.WriteLine ("Defaulting " + gen.Name + " param to 'call' scope in method " + gen_info.CurrentMember);
+						sw.WriteLine (indent + "\t\t\t{0} {1}_wrapper = new {0} ({1});", wrapper, name);
+						break;
+					}
+				}
+			}
+
+			if (ThrowsException)
+				sw.WriteLine (indent + "\t\t\tIntPtr error = IntPtr.Zero;");
+		}
+
+		public void InitAccessor (StreamWriter sw, Signature sig, string indent)
+		{
+			sw.WriteLine (indent + "\t\t\t" + sig.AccessorType + " " + sig.AccessorName + ";");
+		}
+
+		public void Finish (StreamWriter sw, string indent)
+		{
+			foreach (Parameter p in parameters)
+				foreach (string s in p.Finish)
+					sw.WriteLine(indent + "\t\t\t" + s);
+		}
+
+		public void FinishAccessor (StreamWriter sw, Signature sig, string indent)
+		{
+			sw.WriteLine (indent + "\t\t\treturn " + sig.AccessorName + ";");
+		}
+
+		public void HandleException (StreamWriter sw, string indent)
+		{
+			if (!ThrowsException)
+				return;
+			sw.WriteLine (indent + "\t\t\tif (error != IntPtr.Zero) throw new GLib.GException (error);");
+		}
+		
+		public bool ThrowsException {
+			get {
+				int idx = parameters.Count - 1;
+
+				while (idx >= 0) {
+					if (parameters [idx].IsUserData)
+						idx--;
+					else if (parameters [idx].CType == "GError**")
+						return true;
+					else
+						break;
+				}
+				return false;
+			}
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ObjectBase.cs b/lib/unique-sharp/generator/ObjectBase.cs
new file mode 100644
index 0000000..2f00e9b
--- /dev/null
+++ b/lib/unique-sharp/generator/ObjectBase.cs
@@ -0,0 +1,36 @@
+// ObjectBase.cs - Base class for Object types
+//
+// Authors:  Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Xml;
+
+	public abstract class ObjectBase : HandleBase {
+
+		protected ObjectBase (XmlElement ns, XmlElement elem) : base (ns, elem) {}
+					
+		public override string FromNative (string var, bool owned)
+		{
+			return "GLib.Object.GetObject(" + var + (owned ? ", true" : "") + ") as " + QualifiedName;
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/ObjectField.cs b/lib/unique-sharp/generator/ObjectField.cs
new file mode 100644
index 0000000..47e0156
--- /dev/null
+++ b/lib/unique-sharp/generator/ObjectField.cs
@@ -0,0 +1,48 @@
+// GtkSharp.Generation.ObjectField.cs - autogenerated field glue
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class ObjectField : FieldBase {
+
+		public ObjectField (XmlElement elem, ClassBase container_type) : base (elem, container_type)
+		{
+			if (CType == "char*" || CType == "gchar*")
+				ctype = "const-" + CType;
+		}
+
+		protected override bool Writable {
+			get {
+				return elem.GetAttribute ("writeable") == "true";
+			}
+		}
+
+		protected override string DefaultAccess {
+			get {
+				return "private";
+			}
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ObjectGen.cs b/lib/unique-sharp/generator/ObjectGen.cs
new file mode 100644
index 0000000..58d2c17
--- /dev/null
+++ b/lib/unique-sharp/generator/ObjectGen.cs
@@ -0,0 +1,425 @@
+// GtkSharp.Generation.ObjectGen.cs - The Object Generatable.
+//
+// Author: Mike Kestner <mkestner ximian com>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Text;
+	using System.Xml;
+
+	public class ObjectGen : ObjectBase  {
+
+		private ArrayList custom_attrs = new ArrayList();
+		private ArrayList strings = new ArrayList();
+		private ArrayList vm_nodes = new ArrayList();
+		private Hashtable childprops = new Hashtable();
+		private static Hashtable dirs = new Hashtable ();
+
+		public ObjectGen (XmlElement ns, XmlElement elem) : base (ns, elem) 
+		{
+			foreach (XmlNode node in elem.ChildNodes) {
+				string name;
+
+				if (!(node is XmlElement)) continue;
+				XmlElement member = (XmlElement) node;
+
+				switch (node.Name) {
+				case "callback":
+					Statistics.IgnoreCount++;
+					break;
+
+				case "custom-attribute":
+					custom_attrs.Add (member.InnerXml);
+					break;
+
+				case "virtual_method":
+					Statistics.IgnoreCount++;
+					break;
+
+				case "static-string":
+					strings.Add (node);
+					break;
+
+				case "childprop":
+					name = member.GetAttribute ("name");
+					while (childprops.ContainsKey (name))
+						name += "mangled";
+					childprops.Add (name, new ChildProperty (member, this));
+					break;
+
+				default:
+					if (!IsNodeNameHandled (node.Name))
+						Console.WriteLine ("Unexpected node " + node.Name + " in " + CName);
+					break;
+				}
+			}
+		}
+
+		public override bool Validate ()
+		{
+			ArrayList invalids = new ArrayList ();
+
+			foreach (ChildProperty prop in childprops.Values) {
+				if (!prop.Validate ()) {
+					Console.WriteLine ("in Object " + QualifiedName);
+					invalids.Add (prop);
+				}
+			}
+			foreach (ChildProperty prop in invalids)
+				childprops.Remove (prop);
+
+			return base.Validate ();
+		}
+
+		private bool DisableVoidCtor {
+			get {
+				return Elem.HasAttribute ("disable_void_ctor");
+			}
+		}
+
+		private bool DisableGTypeCtor {
+			get {
+				return Elem.HasAttribute ("disable_gtype_ctor");
+			}
+		}
+
+		private class DirectoryInfo {
+			public string assembly_name;
+			public Hashtable objects;
+
+			public DirectoryInfo (string assembly_name) {
+				this.assembly_name = assembly_name;
+				objects = new Hashtable ();
+			}
+		}
+
+		private static DirectoryInfo GetDirectoryInfo (string dir, string assembly_name)
+		{
+			DirectoryInfo result;
+
+			if (dirs.ContainsKey (dir)) {
+				result = dirs [dir] as DirectoryInfo;
+				if  (result.assembly_name != assembly_name) {
+					Console.WriteLine ("Can't put multiple assemblies in one directory.");
+					return null;
+				}
+
+				return result;
+			}
+
+			result = new DirectoryInfo (assembly_name);
+			dirs.Add (dir, result);
+			
+			return result;
+		}
+
+		public override void Generate (GenerationInfo gen_info)
+		{
+			gen_info.CurrentType = Name;
+
+			string asm_name = gen_info.AssemblyName.Length == 0 ? NS.ToLower () + "-sharp" : gen_info.AssemblyName;
+			DirectoryInfo di = GetDirectoryInfo (gen_info.Dir, asm_name);
+
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Collections;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+
+			SymbolTable table = SymbolTable.Table;
+
+			sw.WriteLine ("#region Autogenerated code");
+			if (IsDeprecated)
+				sw.WriteLine ("\t[Obsolete]");
+			foreach (string attr in custom_attrs)
+				sw.WriteLine ("\t" + attr);
+			sw.Write ("\t{0} {1}class " + Name, IsInternal ? "internal" : "public", IsAbstract ? "abstract " : "");
+			string cs_parent = table.GetCSType(Elem.GetAttribute("parent"));
+			if (cs_parent != "") {
+				di.objects.Add (CName, QualifiedName);
+				sw.Write (" : " + cs_parent);
+			}
+			foreach (string iface in interfaces) {
+				if (Parent != null && Parent.Implements (iface))
+					continue;
+				sw.Write (", " + table.GetCSType (iface));
+			}
+			foreach (string iface in managed_interfaces) {
+				if (Parent != null && Parent.Implements (iface))
+					continue;
+				sw.Write (", " + iface);
+			}
+			sw.WriteLine (" {");
+			sw.WriteLine ();
+
+			GenCtors (gen_info);
+			GenProperties (gen_info, null);
+			GenFields (gen_info);
+			GenChildProperties (gen_info);
+			
+			bool has_sigs = (sigs != null && sigs.Count > 0);
+			if (!has_sigs) {
+				foreach (string iface in interfaces) {
+					ClassBase igen = table.GetClassGen (iface);
+					if (igen != null && igen.Signals != null) {
+						has_sigs = true;
+						break;
+					}
+				}
+			}
+
+			if (has_sigs && Elem.HasAttribute("parent")) {
+				GenSignals (gen_info, null);
+			}
+
+			if (vm_nodes.Count > 0) {
+				if (gen_info.GlueEnabled) {
+					GenVirtualMethods (gen_info);
+				} else {
+					Statistics.VMIgnored = true;
+					Statistics.ThrottledCount += vm_nodes.Count;
+				}
+			}
+
+			GenMethods (gen_info, null, null);
+			
+			if (interfaces.Count != 0) {
+				Hashtable all_methods = new Hashtable ();
+				foreach (Method m in Methods.Values)
+					all_methods[m.Name] = m;
+				Hashtable collisions = new Hashtable ();
+				foreach (string iface in interfaces) {
+					ClassBase igen = table.GetClassGen (iface);
+					foreach (Method m in igen.Methods.Values) {
+						Method collision = all_methods[m.Name] as Method;
+						if (collision != null && collision.Signature.Types == m.Signature.Types)
+							collisions[m.Name] = true;
+						else
+							all_methods[m.Name] = m;
+					}
+				}
+					
+				foreach (string iface in interfaces) {
+					if (Parent != null && Parent.Implements (iface))
+						continue;
+					ClassBase igen = table.GetClassGen (iface);
+					igen.GenMethods (gen_info, collisions, this);
+					igen.GenProperties (gen_info, this);
+					igen.GenSignals (gen_info, this);
+				}
+			}
+
+			foreach (XmlElement str in strings) {
+				sw.Write ("\t\tpublic static string " + str.GetAttribute ("name"));
+				sw.WriteLine (" {\n\t\t\t get { return \"" + str.GetAttribute ("value") + "\"; }\n\t\t}");
+			}
+
+			if (cs_parent != String.Empty && GetExpected (CName) != QualifiedName) {
+				sw.WriteLine ();
+				sw.WriteLine ("\t\tstatic " + Name + " ()");
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tGtkSharp." + Studlify (asm_name) + ".ObjectManager.Initialize ();");
+				sw.WriteLine ("\t\t}");
+			}
+
+			sw.WriteLine ("#endregion");
+			AppendCustom (sw, gen_info.CustomDir);
+
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+
+			sw.Close ();
+			gen_info.Writer = null;
+			Statistics.ObjectCount++;
+		}
+
+		protected override void GenCtors (GenerationInfo gen_info)
+		{
+			if (!Elem.HasAttribute("parent"))
+				return;
+
+			if (!DisableGTypeCtor) {
+				gen_info.Writer.WriteLine("\t\t[Obsolete]");
+				gen_info.Writer.WriteLine("\t\tprotected " + Name + "(GLib.GType gtype) : base(gtype) {}");
+			}
+			gen_info.Writer.WriteLine("\t\tpublic " + Name + "(IntPtr raw) : base(raw) {}");
+			if (ctors.Count == 0 && !DisableVoidCtor) {
+				gen_info.Writer.WriteLine();
+				gen_info.Writer.WriteLine("\t\tprotected " + Name + "() : base(IntPtr.Zero)");
+				gen_info.Writer.WriteLine("\t\t{");
+				gen_info.Writer.WriteLine("\t\t\tCreateNativeObject (new string [0], new GLib.Value [0]);");
+				gen_info.Writer.WriteLine("\t\t}");
+			}
+			gen_info.Writer.WriteLine();
+
+			base.GenCtors (gen_info);
+		}
+
+		protected void GenChildProperties (GenerationInfo gen_info)
+		{
+			if (childprops.Count == 0)
+				return;
+
+			StreamWriter sw = gen_info.Writer;
+
+			ObjectGen child_ancestor = Parent as ObjectGen;
+			while (child_ancestor.CName != "GtkContainer" &&
+			       child_ancestor.childprops.Count == 0)
+				child_ancestor = child_ancestor.Parent as ObjectGen;
+
+			sw.WriteLine ("\t\tpublic class " + Name + "Child : " + child_ancestor.NS + "." + child_ancestor.Name + "." + child_ancestor.Name + "Child {");
+			sw.WriteLine ("\t\t\tprotected internal " + Name + "Child (Gtk.Container parent, Gtk.Widget child) : base (parent, child) {}");
+			sw.WriteLine ("");
+
+			foreach (ChildProperty prop in childprops.Values)
+				prop.Generate (gen_info, "\t\t\t", null);
+
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ("");
+
+			sw.WriteLine ("\t\tpublic override Gtk.Container.ContainerChild this [Gtk.Widget child] {");
+			sw.WriteLine ("\t\t\tget {");
+			sw.WriteLine ("\t\t\t\treturn new " + Name + "Child (this, child);");
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ("");
+			
+		}
+
+		private void GenVMGlue (GenerationInfo gen_info, XmlElement elem)
+		{
+			StreamWriter sw = gen_info.GlueWriter;
+
+			string vm_name = elem.GetAttribute ("cname");
+			string method = gen_info.GluelibName + "_" + NS + Name + "_override_" + vm_name;
+			sw.WriteLine ();
+			sw.WriteLine ("void " + method + " (GType type, gpointer cb);");
+			sw.WriteLine ();
+			sw.WriteLine ("void");
+			sw.WriteLine (method + " (GType type, gpointer cb)");
+			sw.WriteLine ("{");
+			sw.WriteLine ("\t{0} *klass = ({0} *) g_type_class_peek (type);", NS + Name + "Class");
+			sw.WriteLine ("\tklass->" + vm_name + " = cb;");
+			sw.WriteLine ("}");
+		}
+
+		static bool vmhdrs_needed = true;
+
+		private void GenVirtualMethods (GenerationInfo gen_info)
+		{
+			if (vmhdrs_needed) {
+				gen_info.GlueWriter.WriteLine ("#include <glib-object.h>");
+				gen_info.GlueWriter.WriteLine ("#include \"vmglueheaders.h\"");
+				gen_info.GlueWriter.WriteLine ();
+				vmhdrs_needed = false;
+			}
+
+			foreach (XmlElement elem in vm_nodes) {
+				GenVMGlue (gen_info, elem);
+			}
+		}
+
+		/* Keep this in sync with the one in glib/GType.cs */
+		private static string GetExpected (string cname)
+		{
+			for (int i = 1; i < cname.Length; i++) {
+				if (Char.IsUpper (cname[i])) {
+					if (i == 1 && cname[0] == 'G')
+						return "GLib." + cname.Substring (1);
+					else
+						return cname.Substring (0, i) + "." + cname.Substring (i);
+				}
+			}
+
+			throw new ArgumentException ("cname doesn't follow the NamespaceType capitalization style: " + cname);
+		}
+
+		private static bool NeedsMap (Hashtable objs, string assembly_name)
+		{
+			foreach (string key in objs.Keys)
+				if (GetExpected (key) != ((string) objs[key]))
+					return true;
+			
+			return false;
+		}
+
+		private static string Studlify (string name)
+		{
+			string result = "";
+
+			string[] subs = name.Split ('-');
+			foreach (string sub in subs)
+				result += Char.ToUpper (sub[0]) + sub.Substring (1);
+				
+			return result;
+		}
+				
+		public static void GenerateMappers ()
+		{
+			foreach (string dir in dirs.Keys) {
+
+				DirectoryInfo di = dirs[dir] as DirectoryInfo;
+
+				if (!NeedsMap (di.objects, di.assembly_name))
+					continue;
+	
+				GenerationInfo gen_info = new GenerationInfo (dir, di.assembly_name);
+
+				GenerateMapper (di, gen_info);
+			}
+		}
+
+		private static void GenerateMapper (DirectoryInfo dir_info, GenerationInfo gen_info)
+		{
+			StreamWriter sw = gen_info.OpenStream ("ObjectManager");
+
+			sw.WriteLine ("namespace GtkSharp." + Studlify (dir_info.assembly_name) + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tpublic class ObjectManager {");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tstatic bool initialized = false;");
+			sw.WriteLine ("\t\t// Call this method from the appropriate module init function.");
+			sw.WriteLine ("\t\tpublic static void Initialize ()");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tif (initialized)");
+			sw.WriteLine ("\t\t\t\treturn;");
+			sw.WriteLine ("");
+			sw.WriteLine ("\t\t\tinitialized = true;");
+	
+			foreach (string key in dir_info.objects.Keys) {
+				if (GetExpected(key) != ((string) dir_info.objects[key]))
+					sw.WriteLine ("\t\t\tGLib.GType.Register ({0}.GType, typeof ({0}));", dir_info.objects [key]);
+			}
+					
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+			sw.Close ();
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/OpaqueGen.cs b/lib/unique-sharp/generator/OpaqueGen.cs
new file mode 100644
index 0000000..2f77e62
--- /dev/null
+++ b/lib/unique-sharp/generator/OpaqueGen.cs
@@ -0,0 +1,237 @@
+// GtkSharp.Generation.OpaqueGen.cs - The Opaque Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class OpaqueGen : HandleBase {
+
+		public OpaqueGen (XmlElement ns, XmlElement elem) : base (ns, elem) {}
+	
+		public override string FromNative(string var, bool owned)
+		{
+			return var + " == IntPtr.Zero ? null : (" + QualifiedName + ") GLib.Opaque.GetOpaque (" + var + ", typeof (" + QualifiedName + "), " + (owned ? "true" : "false") + ")";
+		}
+
+		private bool DisableRawCtor {
+			get {
+				return Elem.HasAttribute ("disable_raw_ctor");
+			}
+		}
+
+		public override void Generate (GenerationInfo gen_info)
+		{
+			gen_info.CurrentType = Name;
+
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
+
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Collections;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+
+			sw.WriteLine ("#region Autogenerated code");
+
+			SymbolTable table = SymbolTable.Table;
+
+			Method ref_, unref, dispose;
+			GetSpecialMethods (out ref_, out unref, out dispose);
+
+			if (IsDeprecated)
+				sw.WriteLine ("\t[Obsolete]");
+			sw.Write ("\t{0} class " + Name, IsInternal ? "internal" : "public");
+			string cs_parent = table.GetCSType(Elem.GetAttribute("parent"));
+			if (cs_parent != "")
+				sw.Write (" : " + cs_parent);
+			else
+				sw.Write (" : GLib.Opaque");
+
+			foreach (string iface in managed_interfaces) {
+				if (Parent != null && Parent.Implements (iface))
+					continue;
+				sw.Write (", " + iface);
+			}
+
+			sw.WriteLine (" {");
+			sw.WriteLine ();
+            
+			GenFields (gen_info);
+			GenMethods (gen_info, null, null);
+			GenCtors (gen_info);
+
+			if (ref_ != null) {
+				ref_.GenerateImport (sw);
+				sw.WriteLine ("\t\tprotected override void Ref (IntPtr raw)");
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tif (!Owned) {");
+				sw.WriteLine ("\t\t\t\t" + ref_.CName + " (raw);");
+				sw.WriteLine ("\t\t\t\tOwned = true;");
+				sw.WriteLine ("\t\t\t}");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+
+				if (ref_.IsDeprecated) {
+					sw.WriteLine ("\t\t[Obsolete(\"" + QualifiedName + " is now refcounted automatically\")]");
+					if (ref_.ReturnType == "void")
+						sw.WriteLine ("\t\tpublic void Ref () {}");
+					else
+						sw.WriteLine ("\t\tpublic " + Name + " Ref () { return this; }");
+					sw.WriteLine ();
+				}
+			}
+
+			bool finalizer_needed = false;
+
+			if (unref != null) {
+				unref.GenerateImport (sw);
+				sw.WriteLine ("\t\tprotected override void Unref (IntPtr raw)");
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tif (Owned) {");
+				sw.WriteLine ("\t\t\t\t" + unref.CName + " (raw);");
+				sw.WriteLine ("\t\t\t\tOwned = false;");
+				sw.WriteLine ("\t\t\t}");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+
+				if (unref.IsDeprecated) {
+					sw.WriteLine ("\t\t[Obsolete(\"" + QualifiedName + " is now refcounted automatically\")]");
+					sw.WriteLine ("\t\tpublic void Unref () {}");
+					sw.WriteLine ();
+				}	
+				finalizer_needed = true;
+			}
+
+			if (dispose != null) {
+				dispose.GenerateImport (sw);
+				sw.WriteLine ("\t\tprotected override void Free (IntPtr raw)");
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\t" + dispose.CName + " (raw);");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+
+				if (dispose.IsDeprecated) {
+					sw.WriteLine ("\t\t[Obsolete(\"" + QualifiedName + " is now freed automatically\")]");
+					sw.WriteLine ("\t\tpublic void " + dispose.Name + " () {}");
+					sw.WriteLine ();
+				}	
+				finalizer_needed = true;
+			}
+
+			if (finalizer_needed) {
+				sw.WriteLine ("\t\tclass FinalizerInfo {");
+				sw.WriteLine ("\t\t\tIntPtr handle;");
+				sw.WriteLine ();
+				sw.WriteLine ("\t\t\tpublic FinalizerInfo (IntPtr handle)");
+				sw.WriteLine ("\t\t\t{");
+				sw.WriteLine ("\t\t\t\tthis.handle = handle;");
+				sw.WriteLine ("\t\t\t}");
+				sw.WriteLine ();
+				sw.WriteLine ("\t\t\tpublic bool Handler ()");
+				sw.WriteLine ("\t\t\t{");
+				if (dispose != null)
+					sw.WriteLine ("\t\t\t\t{0} (handle);", dispose.CName);
+				else if (unref != null)
+					sw.WriteLine ("\t\t\t\t{0} (handle);", unref.CName);
+				sw.WriteLine ("\t\t\t\treturn false;");
+				sw.WriteLine ("\t\t\t}");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+				sw.WriteLine ("\t\t~{0} ()", Name);
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tif (!Owned)");
+				sw.WriteLine ("\t\t\t\treturn;");
+				sw.WriteLine ("\t\t\tFinalizerInfo info = new FinalizerInfo (Handle);");
+				sw.WriteLine ("\t\t\tGLib.Timeout.Add (50, new GLib.TimeoutHandler (info.Handler));");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+			}
+
+#if false
+			Method copy = Methods ["Copy"] as Method;
+			if (copy != null && copy.Parameters.Count == 0) {
+				sw.WriteLine ("\t\tprotected override GLib.Opaque Copy (IntPtr raw)");
+				sw.WriteLine ("\t\t{");
+				sw.WriteLine ("\t\t\tGLib.Opaque result = new " + QualifiedName + " (" + copy.CName + " (raw));");
+				sw.WriteLine ("\t\t\tresult.Owned = true;");
+				sw.WriteLine ("\t\t\treturn result;");
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+			}
+#endif
+			sw.WriteLine ("#endregion");
+			
+			AppendCustom(sw, gen_info.CustomDir);
+
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+
+			sw.Close ();
+			gen_info.Writer = null;
+			Statistics.OpaqueCount++;
+		}
+
+		void GetSpecialMethods (out Method ref_, out Method unref, out Method dispose)
+		{
+			ref_ = CheckSpecialMethod (GetMethod ("Ref"));
+			unref = CheckSpecialMethod (GetMethod ("Unref"));
+
+			dispose = GetMethod ("Free");
+			if (dispose == null) {
+				dispose = GetMethod ("Destroy");
+				if (dispose == null)
+					dispose = GetMethod ("Dispose");
+			}
+			dispose = CheckSpecialMethod (dispose);
+		}
+
+		Method CheckSpecialMethod (Method method)
+		{
+			if (method == null)
+				return null;
+			if (method.ReturnType != "void" &&
+			    method.ReturnType != QualifiedName)
+				return null;
+			if (method.Signature.ToString () != "")
+				return null;
+
+			methods.Remove (method.Name);
+			return method;
+		}
+
+		protected override void GenCtors (GenerationInfo gen_info)
+		{
+			if (!DisableRawCtor) {
+				gen_info.Writer.WriteLine("\t\tpublic " + Name + "(IntPtr raw) : base(raw) {}");
+				gen_info.Writer.WriteLine();
+			}
+
+			base.GenCtors (gen_info);
+		}
+
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Parameters.cs b/lib/unique-sharp/generator/Parameters.cs
new file mode 100644
index 0000000..75dd68f
--- /dev/null
+++ b/lib/unique-sharp/generator/Parameters.cs
@@ -0,0 +1,728 @@
+// GtkSharp.Generation.Parameters.cs - The Parameters Generation Class.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class Parameter {
+
+		private XmlElement elem;
+
+		public Parameter (XmlElement e)
+		{
+			elem = e;
+		}
+
+		string call_name;
+		public string CallName {
+			get {
+				if (call_name == null)
+					return Name;
+				else
+					return call_name;
+			}
+			set {
+				call_name = value;
+			}
+		}
+
+		public string CType {
+			get {
+				string type = elem.GetAttribute("type");
+				if (type == "void*")
+					type = "gpointer";
+				return type;
+			}
+		}
+
+		public string CSType {
+			get {
+				string cstype = SymbolTable.Table.GetCSType( elem.GetAttribute("type"));
+				if (cstype == "void")
+					cstype = "System.IntPtr";
+				if (IsArray) {
+					if (IsParams)
+						cstype = "params " + cstype;
+					cstype += "[]";
+					cstype = cstype.Replace ("ref ", "");
+				}
+				return cstype;
+			}
+		}
+
+		public IGeneratable Generatable {
+			get {
+				return SymbolTable.Table[CType];
+			}
+		}
+
+		public bool IsArray {
+			get {
+				return elem.HasAttribute("array") || elem.HasAttribute("null_term_array");
+			}
+		}
+
+		public bool IsEllipsis {
+			get {
+				return elem.HasAttribute("ellipsis");
+			}
+		}
+
+		public bool IsCount {
+			get {
+				
+				if (Name.StartsWith("n_"))
+					switch (CSType) {
+					case "int":
+					case "uint":
+					case "long":
+					case "ulong":
+					case "short":
+					case "ushort": 
+						return true;
+					default:
+						return false;
+					}
+				else
+					return false;
+			}
+		}
+
+		public bool IsDestroyNotify {
+			get {
+				return CType == "GDestroyNotify";
+			}
+		}
+
+		public bool IsLength {
+			get {
+				
+				if (Name.EndsWith("len") || Name.EndsWith("length"))
+					switch (CSType) {
+					case "int":
+					case "uint":
+					case "long":
+					case "ulong":
+					case "short":
+					case "ushort": 
+						return true;
+					default:
+						return false;
+					}
+				else
+					return false;
+			}
+		}
+
+		public bool IsParams {
+			get {
+				return elem.HasAttribute("params");
+			}
+		}
+
+		public bool IsString {
+			get {
+				return (CSType == "string");
+			}
+		}
+
+		public bool IsUserData {
+			get {
+				return CSType == "IntPtr" && (Name.EndsWith ("data") || Name.EndsWith ("data_or_owner"));
+			}
+		}
+
+		public virtual string MarshalType {
+			get {
+				string type = SymbolTable.Table.GetMarshalType( elem.GetAttribute("type"));
+				if (type == "void" || Generatable is IManualMarshaler)
+					type = "IntPtr";
+				if (IsArray) {
+					type += "[]";
+					type = type.Replace ("ref ", "");
+				}
+				return type;
+			}
+		}
+
+		public string Name {
+			get {
+				return SymbolTable.Table.MangleName (elem.GetAttribute("name"));
+			}
+		}
+
+		public bool Owned {
+			get {
+				return elem.GetAttribute ("owned") == "true";
+			}
+		}
+
+		public virtual string NativeSignature {
+			get {
+				string sig = MarshalType + " " + Name;
+				if (PassAs != String.Empty)
+					sig = PassAs + " " + sig;
+				return sig;
+			}
+		}
+
+		public string PropertyName {
+			get {
+				return elem.GetAttribute("property_name");
+			}
+		}
+
+		string pass_as;
+
+		public string PassAs {
+			get {
+				if (pass_as != null)
+					return pass_as;
+
+				if (elem.HasAttribute ("pass_as"))
+					return elem.GetAttribute ("pass_as");
+
+				if (IsArray || CSType.EndsWith ("IntPtr"))
+					return "";
+
+				if (CType.EndsWith ("*") && (Generatable is SimpleGen || Generatable is EnumGen))
+					return "out";
+
+				return "";
+			}
+			set {
+				pass_as = value;
+			}
+		}
+
+		string scope;
+		public string Scope {
+			get {
+				if (scope == null)
+					scope = elem.GetAttribute ("scope");
+				return scope;
+			}
+			set {
+				scope = value;
+			}
+		}
+
+		public virtual string[] Prepare {
+			get {
+				IGeneratable gen = Generatable;
+				if (gen is IManualMarshaler) {
+					string result = "IntPtr native_" + CallName;
+					if (PassAs != "out")
+						result += " = " + (gen as IManualMarshaler).AllocNative (CallName);
+					return new string [] { result + ";" }; 
+				} else if (PassAs == "out" && CSType != MarshalType)
+					return new string [] { gen.MarshalType + " native_" + CallName + ";" };
+
+				return new string [0];
+			}
+		}
+
+		public virtual string CallString {
+			get {
+				string call_parm;
+
+				IGeneratable gen = Generatable;
+				if (gen is CallbackGen)
+					return SymbolTable.Table.CallByName (CType, CallName + "_wrapper");
+				else if (PassAs != String.Empty) {
+					call_parm = PassAs + " ";
+					if (CSType != MarshalType)
+						call_parm += "native_";
+					call_parm += CallName;
+				} else if (gen is IManualMarshaler)
+					call_parm = "native_" + CallName;
+				else
+					call_parm = SymbolTable.Table.CallByName(CType, CallName);
+			
+				return call_parm;
+			}
+		}
+
+		public virtual string[] Finish {
+			get {
+				IGeneratable gen = Generatable;
+				if (gen is IManualMarshaler) {
+					string[] result = new string [PassAs == "ref" ? 2 : 1];
+					int i = 0;
+					if (PassAs != String.Empty)
+						result [i++] = CallName + " = " + Generatable.FromNative ("native_" + CallName) + ";";
+					if (PassAs != "out")
+						result [i] = (gen as IManualMarshaler).ReleaseNative ("native_" + CallName) + ";";
+					return result;
+				} else if (PassAs != String.Empty && MarshalType != CSType)
+					return new string [] { CallName + " = " + gen.FromNative ("native_" + CallName) + ";" };
+				return new string [0];
+			}
+		}
+
+		public string FromNative (string var)
+		{
+			if (Generatable == null)
+				return String.Empty;
+			else if (Generatable is HandleBase)
+				return ((HandleBase)Generatable).FromNative (var, Owned);
+			else
+				return Generatable.FromNative (var);
+		}
+
+		public string StudlyName {
+			get {
+				string name = elem.GetAttribute("name");
+				string[] segs = name.Split('_');
+				string studly = "";
+				foreach (string s in segs) {
+					if (s.Trim () == "")
+						continue;
+					studly += (s.Substring(0,1).ToUpper() + s.Substring(1));
+				}
+				return studly;
+				
+			}
+		}
+	}
+
+	public class ArrayParameter : Parameter {
+
+		bool null_terminated;
+
+		public ArrayParameter (XmlElement elem) : base (elem) 
+		{
+			null_terminated = elem.HasAttribute ("null_term_array");
+		}
+
+		public override string MarshalType {
+			get {
+				if (Generatable is StructBase)
+					return CSType;
+				else
+					return base.MarshalType;
+			}
+		}
+
+		bool NullTerminated {
+			get {
+				return null_terminated;
+			}
+		}
+
+		public override string[] Prepare {
+			get {
+				if (CSType == MarshalType)
+					return new string [0];
+
+				ArrayList result = new ArrayList ();
+				result.Add (String.Format ("int cnt_{0} = {0} == null ? 0 : {0}.Length;", CallName));
+				result.Add (String.Format ("{0}[] native_{1} = new {0} [cnt_{1}" + (NullTerminated ? " + 1" : "") + "];", MarshalType.TrimEnd('[', ']'), CallName));
+				result.Add (String.Format ("for (int i = 0; i < cnt_{0}; i++)", CallName));
+				IGeneratable gen = Generatable;
+				if (gen is IManualMarshaler)
+					result.Add (String.Format ("\tnative_{0} [i] = {1};", CallName, (gen as IManualMarshaler).AllocNative (CallName + "[i]")));
+				else
+					result.Add (String.Format ("\tnative_{0} [i] = {1};", CallName, gen.CallByName (CallName + "[i]")));
+
+				if (NullTerminated)
+					result.Add (String.Format ("native_{0} [cnt_{0}] = IntPtr.Zero;", CallName));
+				return (string[]) result.ToArray (typeof (string));
+			}
+		}
+
+		public override string CallString {
+			get {
+				if (CSType != MarshalType)
+					return "native_" + CallName;
+				else
+					return CallName;
+			}
+		}
+
+		public override string[] Finish {
+			get {
+				if (CSType == MarshalType)
+					return new string [0];
+
+				IGeneratable gen = Generatable;
+				if (gen is IManualMarshaler) {
+					string [] result = new string [4];
+					result [0] = "for (int i = 0; i < native_" + CallName + ".Length" + (NullTerminated ? " - 1" : "") + "; i++) {";
+					result [1] = "\t" + CallName + " [i] = " + Generatable.FromNative ("native_" + CallName + "[i]") + ";";
+					result [2] = "\t" + (gen as IManualMarshaler).ReleaseNative ("native_" + CallName + "[i]") + ";";
+					result [3] = "}";
+					return result;
+				}
+
+				return new string [0];
+			}
+		}
+	}
+
+	public class ArrayCountPair : ArrayParameter {
+
+		XmlElement count_elem;
+		bool invert;
+
+		public ArrayCountPair (XmlElement array_elem, XmlElement count_elem, bool invert) : base (array_elem)
+		{
+			this.count_elem = count_elem;
+			this.invert = invert;
+		}
+
+		string CountNativeType {
+			get {
+				return SymbolTable.Table.GetMarshalType(count_elem.GetAttribute("type"));
+			}
+		}
+
+		string CountType {
+			get {
+				return SymbolTable.Table.GetCSType(count_elem.GetAttribute("type"));
+			}
+		}
+
+		string CountCast {
+			get {
+				if (CountType == "int")
+					return String.Empty;
+				else
+					return "(" + CountType + ") ";
+			}
+		}
+
+		string CountName {
+			get {
+				return SymbolTable.Table.MangleName (count_elem.GetAttribute("name"));
+			}
+		}
+
+		string CallCount (string name)
+		{
+			string result = CountCast + "(" + name + " == null ? 0 : " + name + ".Length)";
+			IGeneratable gen = SymbolTable.Table[count_elem.GetAttribute("type")];
+			return gen.CallByName (result);
+		}
+
+		public override string CallString {
+			get {
+				if (invert)
+					return CallCount (CallName) + ", " + base.CallString;
+				else
+					return base.CallString + ", " + CallCount (CallName);
+			}
+		}
+
+		public override string NativeSignature {
+			get {
+				if (invert)
+					return CountNativeType + " " + CountName + ", " + MarshalType + " " + Name;
+				else
+					return MarshalType + " " + Name + ", " + CountNativeType + " " + CountName;
+			}
+		}
+	}
+
+	public class ErrorParameter : Parameter {
+
+		public ErrorParameter (XmlElement elem) : base (elem) 
+		{
+			PassAs = "out";
+		}
+
+		public override string CallString {
+			get {
+				return "out error";
+			}
+		}
+	}
+
+	public class StructParameter : Parameter {
+
+		public StructParameter (XmlElement elem) : base (elem) {}
+
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+
+		public override string[] Prepare {
+			get {
+				if (PassAs == "out")
+					return new string [] { "IntPtr native_" + CallName + " = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (" + Generatable.QualifiedName + ")));"};
+				else
+					return new string [] { "IntPtr native_" + CallName + " = " + (Generatable as IManualMarshaler).AllocNative (CallName) + ";"};
+			}
+		}
+
+		public override string CallString {
+			get {
+				return "native_" + CallName;
+			}
+		}
+
+		public override string[] Finish {
+			get {
+				string[] result = new string [2];
+				result [0] = CallName + " = " + FromNative ("native_" + CallName) + ";";
+				result [1] = (Generatable as IManualMarshaler).ReleaseNative ("native_" + CallName) + ";";
+				return result;
+			}
+		}
+
+		public override string NativeSignature {
+			get {
+				return "IntPtr " + CallName;
+			}
+		}
+	}
+
+	public class Parameters : IEnumerable {
+		
+		ArrayList param_list = new ArrayList ();
+		XmlElement elem;
+
+		public Parameters (XmlElement elem) 
+		{
+			if (elem == null)
+				valid = true;
+			this.elem = elem;
+		}
+
+		public int Count {
+			get {
+				return param_list.Count;
+			}
+		}
+
+		public int VisibleCount {
+			get {
+				int visible = 0;
+				foreach (Parameter p in this) {
+					if (!IsHidden (p))
+						visible++;
+				}
+				return visible;
+			}
+		}
+
+		public Parameter this [int idx] {
+			get {
+				return param_list [idx] as Parameter;
+			}
+		}
+
+		public bool IsHidden (Parameter p)
+		{
+			int idx = param_list.IndexOf (p);
+
+			if (idx > 0 && p.IsLength && p.PassAs == String.Empty && this [idx - 1].IsString)
+				return true;
+
+			if (p.IsCount && ((idx > 0 && this [idx - 1].IsArray) ||
+					  (idx < Count - 1 && this [idx + 1].IsArray)))
+				return true;
+
+			if (p.CType == "GError**")
+				return true;
+
+			if (HasCB || HideData) {
+				if (p.IsUserData && (idx == Count - 1))
+                                        return true;
+				if (p.IsUserData && (idx == Count - 2) && this [Count - 1] is ErrorParameter)
+                                        return true;
+				if (p.IsUserData && idx > 0 &&
+				    this [idx - 1].Generatable is CallbackGen)
+					return true;
+				if (p.IsDestroyNotify && (idx == Count - 1) &&
+				    this [idx - 1].IsUserData)
+					return true;
+			}
+
+			return false;
+		}
+
+		bool has_cb;
+		public bool HasCB {
+			get { return has_cb; }
+			set { has_cb = value; }
+		}
+
+		public bool HasOutParam {
+			get {
+				foreach (Parameter p in this)
+					if (p.PassAs == "out")
+						return true;
+				return false;
+			}
+		}
+
+		bool hide_data;
+		public bool HideData {
+			get { return hide_data; }
+			set { hide_data = value; }
+		}
+
+		bool is_static;
+		public bool Static {
+			get { return is_static; }
+			set { is_static = value; }
+		}
+
+		void Clear ()
+		{
+			elem = null;
+			param_list.Clear ();
+			param_list = null;
+		}
+
+		public IEnumerator GetEnumerator ()
+		{
+			return param_list.GetEnumerator ();
+		}
+
+		bool valid = false;
+
+		public bool Validate ()
+		{
+			if (valid)
+				return true;
+
+			if (elem == null)
+				return false;
+
+			for (int i = 0; i < elem.ChildNodes.Count; i++) {
+				XmlElement parm = elem.ChildNodes [i] as XmlElement;
+				if (parm == null || parm.Name != "parameter")
+					continue;
+				Parameter p = new Parameter (parm);
+				
+				if (p.IsEllipsis) {
+					Console.Write("Ellipsis parameter ");
+					Clear ();
+					return false;
+				}
+
+				if ((p.CSType == "") || (p.Name == "") || 
+				    (p.MarshalType == "") || (SymbolTable.Table.CallByName(p.CType, p.Name) == "")) {
+					Console.Write("Name: " + p.Name + " Type: " + p.CType + " ");
+					Clear ();
+					return false;
+				}
+
+				IGeneratable gen = p.Generatable;
+
+				if (p.IsArray) {
+					p = new ArrayParameter (parm);
+					if (i < elem.ChildNodes.Count - 1) {
+						XmlElement next = elem.ChildNodes [i + 1] as XmlElement;
+						if (next != null || next.Name == "parameter") {
+							Parameter c = new Parameter (next);
+							if (c.IsCount) {
+								p = new ArrayCountPair (parm, next, false);
+								i++;
+							} 
+						}
+					}
+				} else if (p.IsCount && i < elem.ChildNodes.Count - 1) {
+					XmlElement next = elem.ChildNodes [i + 1] as XmlElement;
+					if (next != null || next.Name == "parameter") {
+						Parameter a = new Parameter (next);
+						if (a.IsArray) {
+							p = new ArrayCountPair (next, parm, true);
+							i++;
+						}
+					}
+				} else if (p.CType == "GError**")
+					p = new ErrorParameter (parm);
+				else if (gen is StructBase || gen is ByRefGen) {
+					p = new StructParameter (parm);
+				} else if (gen is CallbackGen) {
+					has_cb = true;
+				}
+				param_list.Add (p);
+			}
+			
+			if (has_cb && Count > 2 && this [Count - 3].Generatable is CallbackGen && this [Count - 2].IsUserData && this [Count - 1].IsDestroyNotify)
+				this [Count - 3].Scope = "notified";
+
+			valid = true;
+			return true;
+		}
+
+		public bool IsAccessor {
+			get {
+				return VisibleCount == 1 && AccessorParam.PassAs == "out";
+			}
+		}
+
+		public Parameter AccessorParam {
+			get {
+				foreach (Parameter p in this) {
+					if (!IsHidden (p))
+						return p;
+				}
+				return null;
+			}
+		}
+
+		public string AccessorReturnType {
+			get {
+				Parameter p = AccessorParam;
+				if (p != null)
+					return p.CSType;
+				else
+					return null;
+			}
+		}
+
+		public string AccessorName {
+			get {
+				Parameter p = AccessorParam;
+				if (p != null)
+					return p.Name;
+				else
+					return null;
+			}
+		}
+
+		public string ImportSignature {
+			get {
+				if (Count == 0)
+					return String.Empty;
+
+				string[] result = new string [Count];
+				for (int i = 0; i < Count; i++)
+					result [i] = this [i].NativeSignature;
+
+				return String.Join (", ", result);
+			}
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Parser.cs b/lib/unique-sharp/generator/Parser.cs
new file mode 100644
index 0000000..61e3714
--- /dev/null
+++ b/lib/unique-sharp/generator/Parser.cs
@@ -0,0 +1,170 @@
+// GtkSharp.Generation.Parser.cs - The XML Parsing engine.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2003 Ximian Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class Parser  {
+		
+		private XmlDocument Load (string filename)
+		{
+			XmlDocument doc = new XmlDocument ();
+
+			try {
+				Stream stream = File.OpenRead (filename);
+				doc.Load (stream);
+				stream.Close ();
+			} catch (XmlException e) {
+				Console.WriteLine ("Invalid XML file.");
+				Console.WriteLine (e);
+				doc = null;
+			}
+
+			return doc;
+		}
+
+		public IGeneratable[] Parse (string filename)
+		{
+			XmlDocument doc = Load (filename);
+			if (doc == null)
+				return null;
+
+			XmlElement root = doc.DocumentElement;
+
+			if ((root == null) || !root.HasChildNodes) {
+				Console.WriteLine ("No Namespaces found.");
+				return null;
+			}
+
+			ArrayList gens = new ArrayList ();
+
+			foreach (XmlNode child in root.ChildNodes) {
+				XmlElement elem = child as XmlElement;
+				if (elem == null)
+					continue;
+
+				switch (child.Name) {
+				case "namespace":
+					gens.AddRange (ParseNamespace (elem));
+					break;
+				case "symbol":
+					gens.Add (ParseSymbol (elem));
+					break;
+				default:
+					Console.WriteLine ("Parser::Parse - Unexpected child node: " + child.Name);
+					break;
+				}
+			}
+
+			return (IGeneratable[]) gens.ToArray (typeof (IGeneratable));
+		}
+
+		private ArrayList ParseNamespace (XmlElement ns)
+		{
+			ArrayList result = new ArrayList ();
+
+			foreach (XmlNode def in ns.ChildNodes) {
+
+				XmlElement elem = def as XmlElement;
+				if (elem == null)
+					continue;
+
+				if (elem.HasAttribute("hidden"))
+					continue;
+
+				bool is_opaque = false;
+				if (elem.GetAttribute ("opaque") == "true" ||
+				    elem.GetAttribute ("opaque") == "1")
+					is_opaque = true;
+
+				switch (def.Name) {
+				case "alias":
+					string aname = elem.GetAttribute("cname");
+					string atype = elem.GetAttribute("type");
+					if ((aname == "") || (atype == ""))
+						continue;
+					result.Add (new AliasGen (aname, atype));
+					break;
+				case "boxed":
+					result.Add (is_opaque ? new OpaqueGen (ns, elem) as object : new BoxedGen (ns, elem) as object);
+					break;
+				case "callback":
+					result.Add (new CallbackGen (ns, elem));
+					break;
+				case "enum":
+					result.Add (new EnumGen (ns, elem));
+					break;
+				case "interface":
+					result.Add (new InterfaceGen (ns, elem));
+					break;
+				case "object":
+					result.Add (new ObjectGen (ns, elem));
+					break;
+				case "class":
+					result.Add (new ClassGen (ns, elem));
+					break;
+				case "struct":
+					result.Add (is_opaque ? new OpaqueGen (ns, elem) as object : new StructGen (ns, elem) as object);
+					break;
+				default:
+					Console.WriteLine ("Parser::ParseNamespace - Unexpected node: " + def.Name);
+					break;
+				}
+			}
+
+			return result;
+		}
+
+		private IGeneratable ParseSymbol (XmlElement symbol)
+		{
+			string type = symbol.GetAttribute ("type");
+			string cname = symbol.GetAttribute ("cname");
+			string name = symbol.GetAttribute ("name");
+			IGeneratable result = null;
+
+			if (type == "simple") {
+				if (symbol.HasAttribute ("default_value"))
+					result = new SimpleGen (cname, name, symbol.GetAttribute ("default_value"));
+				else {
+					Console.WriteLine ("Simple type element " + cname + " has no specified default value");
+					result = new SimpleGen (cname, name, String.Empty);
+				}
+			} else if (type == "manual")
+				result = new ManualGen (cname, name);
+			else if (type == "alias")
+				result = new AliasGen (cname, name);
+			else if (type == "marshal") {
+				string mtype = symbol.GetAttribute ("marshal_type");
+				string call = symbol.GetAttribute ("call_fmt");
+				string from = symbol.GetAttribute ("from_fmt");
+				result = new MarshalGen (cname, name, mtype, call, from);
+			} else
+				Console.WriteLine ("Parser::ParseSymbol - Unexpected symbol type " + type);
+
+			return result;
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/Property.cs b/lib/unique-sharp/generator/Property.cs
new file mode 100644
index 0000000..fbf940b
--- /dev/null
+++ b/lib/unique-sharp/generator/Property.cs
@@ -0,0 +1,193 @@
+// GtkSharp.Generation.Property.cs - The Property Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class Property : PropertyBase {
+
+		public Property (XmlElement elem, ClassBase container_type) : base (elem, container_type) {}
+
+		public bool Validate ()
+		{
+			if (CSType == "" && !Hidden) {
+				Console.Write("Property has unknown Type {0} ", CType);
+				Statistics.ThrottledCount++;
+				return false;
+			}
+
+			return true;
+		}
+
+		bool Readable {
+			get {
+				return elem.GetAttribute ("readable") == "true";
+			}
+		}
+
+		bool Writable {
+			get {
+				return elem.GetAttribute ("writeable") == "true" &&
+					!elem.HasAttribute ("construct-only");
+			}
+		}
+
+		bool IsDeprecated {
+			get {
+				return !container_type.IsDeprecated &&
+					(elem.GetAttribute ("deprecated") == "1" ||
+					 elem.GetAttribute ("deprecated") == "true");
+			}
+		}
+
+		protected virtual string PropertyAttribute (string qpname) {
+			return "[GLib.Property (" + qpname + ")]";
+		}
+
+		protected virtual string RawGetter (string qpname) {
+			return "GetProperty (" + qpname + ")";
+		}
+
+		protected virtual string RawSetter (string qpname) {
+			return "SetProperty(" + qpname + ", val)";
+		}
+
+		public void GenerateDecl (StreamWriter sw, string indent)
+		{
+			if (Hidden || (!Readable && !Writable))
+				return;
+
+			string name = Name;
+			if (name == container_type.Name)
+				name += "Prop";
+
+			sw.WriteLine (indent + CSType + " " + name + " {");
+			sw.Write (indent + "\t");
+			if (Readable || Getter != null)
+				sw.Write ("get; ");
+			if (Writable || Setter != null)
+				sw.Write ("set;");
+			sw.WriteLine ();
+			sw.WriteLine (indent + "}");
+		}
+
+		public void Generate (GenerationInfo gen_info, string indent, ClassBase implementor)
+		{
+			SymbolTable table = SymbolTable.Table;
+			StreamWriter sw = gen_info.Writer;
+
+			if (Hidden || (!Readable && !Writable))
+				return;
+
+			string modifiers = "";
+
+			if (IsNew || (container_type.Parent != null && container_type.Parent.GetPropertyRecursively (Name) != null))
+				modifiers = "new ";
+			else if (implementor != null && implementor.Parent != null && implementor.Parent.GetPropertyRecursively (Name) != null)
+				modifiers = "new ";
+
+			string name = Name;
+			if (name == container_type.Name) {
+				name += "Prop";
+			}
+			string qpname = "\"" + CName + "\"";
+
+			string v_type = "";
+			if (table.IsInterface (CType)) {
+				v_type = "(GLib.Object)";
+			} else if (table.IsOpaque (CType)) {
+				v_type = "(GLib.Opaque)";
+			} else if (table.IsEnum (CType)) {
+				v_type = "(Enum)";
+			}
+
+			GenerateImports (gen_info, indent);
+
+			if (IsDeprecated ||
+			    (Getter != null && Getter.IsDeprecated) ||
+			    (Setter != null && Setter.IsDeprecated))
+				sw.WriteLine (indent + "[Obsolete]");
+			sw.WriteLine (indent + PropertyAttribute (qpname));
+			sw.WriteLine (indent + "public " + modifiers + CSType + " " + name + " {");
+			indent += "\t";
+
+			if (Getter != null) {
+				sw.Write(indent + "get ");
+				Getter.GenerateBody(gen_info, implementor, "\t");
+				sw.WriteLine();
+			} else if (Readable) {
+				sw.WriteLine(indent + "get {");
+				sw.WriteLine(indent + "\tGLib.Value val = " + RawGetter (qpname) + ";");
+				if (table.IsOpaque (CType) || table.IsBoxed (CType)) {
+					sw.WriteLine(indent + "\t" + CSType + " ret = (" + CSType + ") val;");
+				} else if (table.IsInterface (CType)) {
+					// Do we have to dispose the GLib.Object from the GLib.Value?
+					sw.WriteLine (indent + "\t{0} ret = {0}Adapter.GetObject ((GLib.Object) val);", CSType);
+				} else {
+					sw.Write(indent + "\t" + CSType + " ret = ");
+					sw.Write ("(" + CSType + ") ");
+					if (v_type != "") {
+						sw.Write(v_type + " ");
+					}
+					sw.WriteLine("val;");
+				}
+
+				sw.WriteLine(indent + "\tval.Dispose ();");
+				sw.WriteLine(indent + "\treturn ret;");
+				sw.WriteLine(indent + "}");
+			}
+
+			if (Setter != null) {
+				sw.Write(indent + "set ");
+				Setter.GenerateBody(gen_info, implementor, "\t");
+				sw.WriteLine();
+			} else if (Writable) {
+				sw.WriteLine(indent + "set {");
+				sw.Write(indent + "\tGLib.Value val = ");
+				if (table.IsBoxed (CType)) {
+					sw.WriteLine("(GLib.Value) value;");
+				} else if (table.IsOpaque (CType)) {
+					sw.WriteLine("new GLib.Value(value, \"{0}\");", CType);
+				} else {
+					sw.Write("new GLib.Value(");
+					if (v_type != "" && !(table.IsObject (CType) || table.IsInterface (CType) || table.IsOpaque (CType))) {
+						sw.Write(v_type + " ");
+					}
+					sw.WriteLine("value);");
+				}
+				sw.WriteLine(indent + "\t" + RawSetter (qpname) + ";");
+				sw.WriteLine(indent + "\tval.Dispose ();");
+				sw.WriteLine(indent + "}");
+			}
+
+			sw.WriteLine(indent.Substring (1) + "}");
+			sw.WriteLine();
+
+			Statistics.PropCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/PropertyBase.cs b/lib/unique-sharp/generator/PropertyBase.cs
new file mode 100644
index 0000000..d031bd8
--- /dev/null
+++ b/lib/unique-sharp/generator/PropertyBase.cs
@@ -0,0 +1,122 @@
+// GtkSharp.Generation.PropertyBase.cs - base class for properties and
+// fields
+//
+// Copyright (c) 2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Xml;
+
+	public abstract class PropertyBase {
+
+		protected XmlElement elem;
+		protected ClassBase container_type;
+
+		public PropertyBase (XmlElement elem, ClassBase container_type)
+		{
+			this.elem = elem;
+			this.container_type = container_type;
+		}
+
+		public string Name {
+			get {
+				return elem.GetAttribute ("name");
+			}
+		}
+
+		public string CName {
+			get {
+				return elem.GetAttribute ("cname");
+			}
+		}
+
+		protected string ctype;
+		public string CType {
+			get {
+				if (ctype == null) {
+					if (elem.GetAttribute("bits") == "1")
+						ctype = "gboolean";
+					else
+						ctype = elem.GetAttribute("type");
+				}
+				return ctype;
+			}
+		}
+
+		protected string cstype;
+		public string CSType {
+			get {
+				if (cstype == null)
+					cstype = SymbolTable.Table.GetCSType (CType);
+				return cstype;
+			}
+		}
+
+		public bool Hidden {
+			get {
+				return elem.HasAttribute("hidden");
+			}
+		}
+
+		protected bool IsNew {
+			get {
+				return elem.HasAttribute("new_flag");
+			}
+		}
+
+		Method getter;
+		protected Method Getter {
+			get {
+				if (getter == null) {
+					getter = container_type.GetMethod ("Get" + Name);
+					if (getter != null && getter.Name == "Get" + Name &&
+					    getter.IsGetter)
+						cstype = getter.ReturnType;
+					else
+						getter = null;
+				}
+				return getter;
+			}
+		}
+
+		Method setter;
+		protected Method Setter {
+			get {
+				if (setter == null) {
+					setter = container_type.GetMethod ("Set" + Name);
+					if (setter != null && setter.Name == "Set" + Name &&
+					    setter.IsSetter)
+						cstype = setter.Signature.Types;
+					else
+						setter = null;
+				}
+				return setter;
+			}
+		}
+
+		protected virtual void GenerateImports (GenerationInfo gen_info, string indent)
+		{
+			if (Getter != null)
+				Getter.GenerateImport (gen_info.Writer);
+			if (Setter != null)
+				Setter.GenerateImport (gen_info.Writer);
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/ReturnValue.cs b/lib/unique-sharp/generator/ReturnValue.cs
new file mode 100644
index 0000000..4ace994
--- /dev/null
+++ b/lib/unique-sharp/generator/ReturnValue.cs
@@ -0,0 +1,170 @@
+// GtkSharp.Generation.ReturnValue.cs - The ReturnValue Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2004-2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Xml;
+
+	public class ReturnValue  {
+
+		
+		bool is_null_term;
+		bool is_array;
+		bool elements_owned;
+		bool owned;
+		string ctype = String.Empty;
+		string element_ctype = String.Empty;
+
+		public ReturnValue (XmlElement elem) 
+		{
+			if (elem != null) {
+				is_null_term = elem.HasAttribute ("null_term_array");
+				is_array = elem.HasAttribute ("array");
+				elements_owned = elem.GetAttribute ("elements_owned") == "true";
+				owned = elem.GetAttribute ("owned") == "true";
+				ctype = elem.GetAttribute("type");
+				element_ctype = elem.GetAttribute ("element_type");
+			}
+		}
+
+		public string CType {
+			get {
+				return ctype;
+			}
+		}
+
+		public string CSType {
+			get {
+				if (IGen == null)
+					return String.Empty;
+
+				if (ElementType != String.Empty)
+					return ElementType + "[]";
+
+				return IGen.QualifiedName + (is_array || is_null_term ? "[]" : String.Empty);
+			}
+		}
+
+		public string DefaultValue {
+			get {
+				if (IGen == null)
+					return String.Empty;
+				return IGen.DefaultValue;
+			}
+		}
+
+		string ElementType {
+			get {
+				if (element_ctype.Length > 0)
+					return SymbolTable.Table.GetCSType (element_ctype);
+
+				return String.Empty;
+			}
+		}
+
+		IGeneratable igen;
+		IGeneratable IGen {
+			get {
+				if (igen == null)
+					igen = SymbolTable.Table [CType];
+				return igen;
+			}
+		}
+
+		public bool IsVoid {
+			get {
+				return CSType == "void";
+			}
+		}
+
+		public string MarshalType {
+			get {
+				if (IGen == null)
+					return String.Empty;
+				else if (is_null_term)
+					return "IntPtr";
+				return IGen.MarshalReturnType + (is_array ? "[]" : String.Empty);
+			}
+		}
+
+		public string ToNativeType {
+			get {
+				if (IGen == null)
+					return String.Empty;
+				else if (is_null_term)
+					return "IntPtr"; //FIXME
+				return IGen.ToNativeReturnType + (is_array ? "[]" : String.Empty);
+			}
+		}
+
+		public string FromNative (string var)
+		{
+			if (IGen == null)
+				return String.Empty;
+
+			if (ElementType != String.Empty) {
+				string args = (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false");
+				if (IGen.QualifiedName == "GLib.PtrArray")
+					return String.Format ("({0}[]) GLib.Marshaller.PtrArrayToArray ({1}, {2}, typeof({0}))", ElementType, var, args);
+				else
+					return String.Format ("({0}[]) GLib.Marshaller.ListPtrToArray ({1}, typeof({2}), {3}, typeof({0}))", ElementType, var, IGen.QualifiedName, args);
+			} else if (IGen is HandleBase)
+				return ((HandleBase)IGen).FromNative (var, owned);
+			else if (is_null_term)
+				return String.Format ("GLib.Marshaller.NullTermPtrToStringArray ({0}, {1})", var, owned ? "true" : "false");
+			else
+				return IGen.FromNativeReturn (var);
+		}
+			
+		public string ToNative (string var)
+		{
+			if (IGen == null)
+				return String.Empty;
+
+			if (ElementType.Length > 0) {
+				string args = ", typeof (" + ElementType + "), " + (owned ? "true" : "false") + ", " + (elements_owned ? "true" : "false");
+				var = "new " + IGen.QualifiedName + "(" + var + args + ")";
+			} else if (is_null_term)
+				return String.Format ("GLib.Marshaller.StringArrayToNullTermPtr ({0})", var);
+
+			if (IGen is IManualMarshaler)
+				return (IGen as IManualMarshaler).AllocNative (var);
+			else if (IGen is ObjectGen && owned)
+				return var + " == null ? IntPtr.Zero : " + var + ".OwnedHandle";
+			else if (IGen is OpaqueGen && owned)
+				return var + " == null ? IntPtr.Zero : " + var + ".OwnedCopy";
+			else
+				return IGen.ToNativeReturn (var);
+		}
+
+		public bool Validate ()
+		{
+			if (MarshalType == "" || CSType == "") {
+				Console.Write("rettype: " + CType);
+				return false;
+			}
+
+			return true;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Signal.cs b/lib/unique-sharp/generator/Signal.cs
new file mode 100644
index 0000000..32901c0
--- /dev/null
+++ b/lib/unique-sharp/generator/Signal.cs
@@ -0,0 +1,587 @@
+// GtkSharp.Generation.Signal.cs - The Signal Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner 
+// Copyright (c) 2003-2005 Novell, Inc.
+// Copyright (c) 2007 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	public class Signal {
+
+		bool marshaled;
+		string name;
+		XmlElement elem;
+		ReturnValue retval;
+		Parameters parms;
+		ClassBase container_type;
+
+		public Signal (XmlElement elem, ClassBase container_type)
+		{
+			this.elem = elem;
+			name = elem.GetAttribute ("name");
+			marshaled = elem.GetAttribute ("manual") == "true";
+			retval = new ReturnValue (elem ["return-type"]);
+			parms = new Parameters (elem["parameters"]);
+			this.container_type = container_type;
+		}
+
+		bool Marshaled {
+			get { return marshaled; }
+		}
+
+		public string Name {
+			get {
+				return name; 
+			}
+			set {
+				name = value;
+			}
+		}
+
+		public bool Validate ()
+		{
+			if (Name == "") {
+				Console.Write ("Nameless signal ");
+				Statistics.ThrottledCount++;
+				return false;
+			}
+			
+			if (!parms.Validate () || !retval.Validate ()) {
+				Console.Write (" in signal " + Name + " ");
+				Statistics.ThrottledCount++;
+				return false;
+			}
+
+			return true;
+		}
+
+		public void GenerateDecl (StreamWriter sw)
+		{
+			if (elem.HasAttribute("new_flag") || (container_type != null && container_type.GetSignalRecursively (Name) != null))
+				sw.Write("new ");
+
+			sw.WriteLine ("\t\tevent " + EventHandlerQualifiedName + " " + Name + ";");
+		}
+
+		public string CName {
+			get {
+				return "\"" + elem.GetAttribute("cname") + "\"";
+			}
+		}
+
+		string CallbackSig {
+			get {
+				string result = "";
+				for (int i = 0; i < parms.Count; i++) {
+					if (i > 0)
+						result += ", ";
+
+					Parameter p = parms [i];
+					if (p.PassAs != "" && !(p.Generatable is StructBase))
+						result += p.PassAs + " ";
+					result += (p.MarshalType + " arg" + i);
+				}
+
+				return result;
+			}
+		}
+
+		string CallbackName {
+			get { return Name + "SignalCallback"; }
+		}
+
+		string DelegateName {
+			get { return Name + "SignalDelegate"; }
+		}
+
+                private string EventArgsName {
+                        get {
+                                if (IsEventHandler)
+                                        return "EventArgs";
+                                else
+                                        return Name + "Args";
+                        }
+                }
+                                                                                                                        
+                private string EventArgsQualifiedName {
+                        get {
+                                if (IsEventHandler)
+                                        return "System.EventArgs";
+                                else
+                                        return container_type.NS + "." + Name + "Args";
+                        }
+                }
+                                                                                                                        
+                private string EventHandlerName {
+                        get {
+                                if (IsEventHandler)
+                                        return "EventHandler";
+                                else if (SymbolTable.Table [container_type.NS + Name + "Handler"] != null)
+                                        return Name + "EventHandler";
+				else
+                                        return Name + "Handler";
+                        }
+                }
+                                                                                                                        
+                private string EventHandlerQualifiedName {
+                        get {
+                                if (IsEventHandler)
+                                        return "System.EventHandler";
+                                else
+                                        return container_type.NS + "." + EventHandlerName;
+                        }
+                }
+
+		string ClassFieldName {
+			get {
+				return elem.HasAttribute ("field_name") ? elem.GetAttribute("field_name") : String.Empty;
+			}
+		}
+
+		private bool HasOutParams {
+			get {
+				foreach (Parameter p in parms) {
+					if (p.PassAs == "out")
+						return true;
+				}
+				return false;
+			}
+		}
+
+		private bool IsEventHandler {
+			get {
+				return retval.CSType == "void" && parms.Count == 1 && (parms [0].Generatable is ObjectGen || parms [0].Generatable is InterfaceGen);
+			}
+		}
+
+		private bool IsVoid {
+			get {
+				return retval.CSType == "void";
+			}
+		}
+
+		private string ReturnGType {
+			get {
+				IGeneratable igen = SymbolTable.Table [retval.CType];
+
+				if (igen is ObjectGen)
+					return "GLib.GType.Object";
+				if (igen is BoxedGen)
+					return retval.CSType + ".GType";
+				if (igen is EnumGen)
+					return retval.CSType + "GType.GType";
+
+				switch (retval.CSType) {
+				case "bool":
+					return "GLib.GType.Boolean";
+				case "string":
+					return "GLib.GType.String";
+				case "int":
+					return "GLib.GType.Int";
+				default:
+					throw new Exception (retval.CSType);
+				}
+			}
+		}
+
+		public string GenArgsInitialization (StreamWriter sw)
+		{
+			if (parms.Count > 1)
+				sw.WriteLine("\t\t\t\targs.Args = new object[" + (parms.Count - 1) + "];");
+			string finish = "";
+			for (int idx = 1; idx < parms.Count; idx++) {
+				Parameter p = parms [idx];
+				IGeneratable igen = p.Generatable;
+				if (p.PassAs != "out") {
+					if (igen is ManualGen) {
+						sw.WriteLine("\t\t\t\tif (arg{0} == IntPtr.Zero)", idx);
+						sw.WriteLine("\t\t\t\t\targs.Args[{0}] = null;", idx - 1);
+						sw.WriteLine("\t\t\t\telse {");
+						sw.WriteLine("\t\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx)  + ";");
+						sw.WriteLine("\t\t\t\t}");
+					} else
+						sw.WriteLine("\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx)  + ";");
+				}
+				if (igen is StructBase && p.PassAs == "ref")
+					finish += "\t\t\t\tif (arg" + idx + " != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (args.Args[" + (idx-1) + "], arg" + idx + ", false);\n";
+				else if (p.PassAs != "")
+					finish += "\t\t\t\targ" + idx + " = " + igen.ToNativeReturn ("((" + p.CSType + ")args.Args[" + (idx - 1) + "])") + ";\n";
+			}
+			return finish;
+		}
+
+		public void GenArgsCleanup (StreamWriter sw, string finish)
+		{
+			if (IsVoid && finish.Length == 0)
+				return;
+
+			sw.WriteLine("\n\t\t\ttry {");
+			sw.Write (finish);
+			if (!IsVoid) {
+				if (retval.CSType == "bool") {
+					sw.WriteLine ("\t\t\t\tif (args.RetVal == null)");
+					sw.WriteLine ("\t\t\t\t\treturn false;");
+				}
+				sw.WriteLine("\t\t\t\treturn " + SymbolTable.Table.ToNativeReturn (retval.CType, "((" + retval.CSType + ")args.RetVal)") + ";");
+			}
+			sw.WriteLine("\t\t\t} catch (Exception) {");
+			sw.WriteLine ("\t\t\t\tException ex = new Exception (\"args.RetVal or 'out' property unset or set to incorrect type in " + EventHandlerQualifiedName + " callback\");");
+			sw.WriteLine("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (ex, true);");
+			
+			sw.WriteLine ("\t\t\t\t// NOTREACHED: above call doesn't return.");
+			sw.WriteLine ("\t\t\t\tthrow ex;");
+			sw.WriteLine("\t\t\t}");
+		}
+
+		public void GenCallback (StreamWriter sw)
+		{
+			if (IsEventHandler)
+				return;
+
+			sw.WriteLine ("\t\t[GLib.CDeclCallback]");
+			sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + DelegateName + " (" + CallbackSig + ", IntPtr gch);");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + CallbackName + " (" + CallbackSig + ", IntPtr gch)");
+			sw.WriteLine("\t\t{");
+			sw.WriteLine("\t\t\t{0} args = new {0} ();", EventArgsQualifiedName);
+			sw.WriteLine("\t\t\ttry {");
+			sw.WriteLine("\t\t\t\tGLib.Signal sig = ((GCHandle) gch).Target as GLib.Signal;");
+			sw.WriteLine("\t\t\t\tif (sig == null)");
+			sw.WriteLine("\t\t\t\t\tthrow new Exception(\"Unknown signal GC handle received \" + gch);");
+			sw.WriteLine();
+			string finish = GenArgsInitialization (sw);
+			sw.WriteLine("\t\t\t\t{0} handler = ({0}) sig.Handler;", EventHandlerQualifiedName);
+			sw.WriteLine("\t\t\t\thandler (GLib.Object.GetObject (arg0), args);");
+			sw.WriteLine("\t\t\t} catch (Exception e) {");
+			sw.WriteLine("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, false);");
+			sw.WriteLine("\t\t\t}");
+			GenArgsCleanup (sw, finish);
+			sw.WriteLine("\t\t}");
+			sw.WriteLine();
+		}
+
+		private bool NeedNew (ClassBase implementor)
+		{
+			return elem.HasAttribute ("new_flag") ||
+				(container_type != null && container_type.GetSignalRecursively (Name) != null) ||
+				(implementor != null && implementor.GetSignalRecursively (Name) != null);
+		}
+
+		public void GenEventHandler (GenerationInfo gen_info)
+		{
+			if (IsEventHandler)
+				return;
+
+			string ns = container_type.NS;
+
+			StreamWriter sw = gen_info.OpenStream (EventHandlerName);
+			
+			sw.WriteLine ("namespace " + ns + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+
+			sw.WriteLine ();
+			sw.WriteLine ("\tpublic delegate void " + EventHandlerName + "(object o, " + EventArgsName + " args);");
+			sw.WriteLine ();
+			sw.WriteLine ("\tpublic class " + EventArgsName + " : GLib.SignalArgs {");
+			for (int i = 1; i < parms.Count; i++) {
+				sw.WriteLine ("\t\tpublic " + parms[i].CSType + " " + parms[i].StudlyName + "{");
+				if (parms[i].PassAs != "out") {
+					sw.WriteLine ("\t\t\tget {");
+					sw.WriteLine ("\t\t\t\treturn (" + parms[i].CSType + ") Args[" + (i - 1) + "];");
+					sw.WriteLine ("\t\t\t}");
+				}
+				if (parms[i].PassAs != "") {
+					sw.WriteLine ("\t\t\tset {");
+					sw.WriteLine ("\t\t\t\tArgs[" + (i - 1) + "] = (" + parms[i].CSType + ")value;");
+					sw.WriteLine ("\t\t\t}");
+				}
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+			}
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+			sw.Close ();
+		}
+
+		private void GenVMDeclaration (StreamWriter sw, ClassBase implementor)
+		{
+			VMSignature vmsig = new VMSignature (parms);
+			sw.WriteLine ("\t\t[GLib.DefaultSignalHandler(Type=typeof(" + (implementor != null ? implementor.QualifiedName : container_type.QualifiedName) + "), ConnectionMethod=\"Override" + Name +"\")]");
+			sw.Write ("\t\tprotected ");
+			if (NeedNew (implementor))
+				sw.Write ("new ");
+			sw.WriteLine ("virtual {0} {1} ({2})", retval.CSType, "On" + Name, vmsig.ToString ());
+		}
+
+		private string CastFromInt (string type)
+		{
+			return type != "int" ? "(" + type + ") " : "";
+		}
+
+		private string GlueCallString {
+			get {
+				string result = "Handle";
+
+				for (int i = 1; i < parms.Count; i++) {
+					Parameter p = parms [i];
+					IGeneratable igen = p.Generatable;
+
+					if (i > 1 && parms [i - 1].IsString && p.IsLength && p.PassAs == String.Empty) {
+						string string_name = parms [i - 1].Name;
+						result += ", " + igen.CallByName (CastFromInt (p.CSType) + "System.Text.Encoding.UTF8.GetByteCount (" +  string_name + ")");
+						continue;
+					}
+
+					p.CallName = p.Name;
+					string call_parm = p.CallString;
+
+					if (p.IsUserData && parms.IsHidden (p) && !parms.HideData && (i == 1 || parms [i - 1].Scope != "notified")) {
+						call_parm = "IntPtr.Zero"; 
+					}
+
+					result += ", " + call_parm;
+				}
+				return result;
+			}
+		}
+
+		private string GlueSignature {
+			get {
+				string result = String.Empty;
+				for (int i = 0; i < parms.Count; i++)
+					result += parms[i].CType.Replace ("const-", "const ") + " " + parms[i].Name + (i == parms.Count-1 ? "" : ", ");
+				return result;
+			}
+		}
+
+		private string DefaultGlueValue {
+			get {
+				string val = retval.DefaultValue;
+				switch (val) {
+				case "null":
+					return "NULL";
+				case "false":
+					return "FALSE";
+				case "true":
+					return "TRUE";
+				default:
+					return val;
+				}
+			}
+		}
+
+		private void GenGlueVirtualMethod (GenerationInfo gen_info)
+		{
+			StreamWriter glue = gen_info.GlueWriter;
+			string glue_name = String.Format ("{0}sharp_{1}_base_{2}", container_type.NS.ToLower ().Replace (".", "_"), container_type.Name.ToLower (), ClassFieldName);
+			glue.WriteLine ("{0} {1} ({2});\n", retval.CType, glue_name, GlueSignature);
+			glue.WriteLine ("{0}\n{1} ({2})", retval.CType, glue_name, GlueSignature);
+			glue.WriteLine ("{");
+			glue.WriteLine ("\t{0}Class *klass = ({0}Class *) get_threshold_class (G_OBJECT ({1}));", container_type.CName, parms[0].Name);
+			glue.Write ("\tif (klass->{0})\n\t\t", ClassFieldName);
+			if (!IsVoid)
+				glue.Write ("return ");
+			glue.Write ("(* klass->{0}) (", ClassFieldName);
+			for (int i = 0; i < parms.Count; i++)
+				glue.Write (parms[i].Name + (i == parms.Count - 1 ? "" : ", "));
+			glue.WriteLine (");");
+			if (!IsVoid)
+				glue.WriteLine ("\treturn " + DefaultGlueValue + ";");
+			glue.WriteLine ("}");
+
+			StreamWriter sw = gen_info.Writer;
+			sw.WriteLine ("\t\t[DllImport (\"{0}\")]", gen_info.GluelibName);
+			sw.WriteLine ("\t\tstatic extern {0} {1} ({2});\n", retval.MarshalType, glue_name, parms.ImportSignature);
+			GenVMDeclaration (sw, null);
+			sw.WriteLine ("\t\t{");
+			MethodBody body = new MethodBody (parms);
+			body.Initialize (gen_info, false, false, String.Empty);
+			sw.WriteLine ("\t\t\t{0}{1} ({2});", IsVoid ? "" : retval.MarshalType + " __ret = ", glue_name, GlueCallString);
+			body.Finish (sw, "");
+			if (!IsVoid)
+				sw.WriteLine ("\t\t\treturn {0};", retval.FromNative ("__ret"));
+			sw.WriteLine ("\t\t}\n");
+		}
+
+		private void GenChainVirtualMethod (StreamWriter sw, ClassBase implementor)
+		{
+			GenVMDeclaration (sw, implementor);
+			sw.WriteLine ("\t\t{");
+			if (IsVoid)
+				sw.WriteLine ("\t\t\tGLib.Value ret = GLib.Value.Empty;");
+			else
+				sw.WriteLine ("\t\t\tGLib.Value ret = new GLib.Value (" + ReturnGType + ");");
+
+			sw.WriteLine ("\t\t\tGLib.ValueArray inst_and_params = new GLib.ValueArray (" + parms.Count + ");");
+			sw.WriteLine ("\t\t\tGLib.Value[] vals = new GLib.Value [" + parms.Count + "];");
+			sw.WriteLine ("\t\t\tvals [0] = new GLib.Value (this);");
+			sw.WriteLine ("\t\t\tinst_and_params.Append (vals [0]);");
+			string cleanup = "";
+			for (int i = 1; i < parms.Count; i++) {
+				Parameter p = parms [i];
+				if (p.PassAs != "") {
+					if (SymbolTable.Table.IsBoxed (p.CType)) {
+						if (p.PassAs == "ref")
+							sw.WriteLine ("\t\t\tvals [" + i + "] = new GLib.Value (" + p.Name + ");");
+						else
+							sw.WriteLine ("\t\t\tvals [" + i + "] = new GLib.Value ((GLib.GType)typeof (" + p.CSType + "));");
+						cleanup += "\t\t\t" + p.Name + " = (" + p.CSType + ") vals [" + i + "];\n";
+					} else {
+						if (p.PassAs == "ref")
+							sw.WriteLine ("\t\t\tIntPtr " + p.Name + "_ptr = GLib.Marshaller.StructureToPtrAlloc (" + p.Generatable.CallByName (p.Name) + ");");
+						else
+							sw.WriteLine ("\t\t\tIntPtr " + p.Name + "_ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (" + p.MarshalType + ")));");
+
+						sw.WriteLine ("\t\t\tvals [" + i + "] = new GLib.Value (" + p.Name + "_ptr);");
+						cleanup += "\t\t\t" + p.Name + " = " + p.FromNative ("(" + p.MarshalType + ") Marshal.PtrToStructure (" + p.Name + "_ptr, typeof (" + p.MarshalType + "))") + ";\n";
+						cleanup += "\t\t\tMarshal.FreeHGlobal (" + p.Name + "_ptr);\n";
+					}
+				} else if (p.IsLength && parms [i - 1].IsString)
+					sw.WriteLine ("\t\t\tvals [" + i + "] = new GLib.Value (System.Text.Encoding.UTF8.GetByteCount (" + parms [i-1].Name + "));");
+				else
+					sw.WriteLine ("\t\t\tvals [" + i + "] = new GLib.Value (" + p.Name + ");");
+
+				sw.WriteLine ("\t\t\tinst_and_params.Append (vals [" + i + "]);");
+			}
+
+			sw.WriteLine ("\t\t\tg_signal_chain_from_overridden (inst_and_params.ArrayPtr, ref ret);");
+			if (cleanup != "")
+				sw.WriteLine (cleanup);
+			sw.WriteLine ("\t\t\tforeach (GLib.Value v in vals)");
+			sw.WriteLine ("\t\t\t\tv.Dispose ();");
+			if (!IsVoid) {
+				IGeneratable igen = SymbolTable.Table [retval.CType];
+				sw.WriteLine ("\t\t\t" + retval.CSType + " result = (" + (igen is EnumGen ? retval.CSType + ") (Enum" : retval.CSType) + ") ret;");
+				sw.WriteLine ("\t\t\tret.Dispose ();");
+				sw.WriteLine ("\t\t\treturn result;");
+			}
+			sw.WriteLine ("\t\t}\n");
+		}
+
+		private void GenDefaultHandlerDelegate (GenerationInfo gen_info, ClassBase implementor)
+		{
+			StreamWriter sw = gen_info.Writer;
+			StreamWriter glue;
+			bool use_glue = gen_info.GlueEnabled && implementor == null && ClassFieldName.Length > 0;
+			string glue_name = String.Empty;
+			ManagedCallString call = new ManagedCallString (parms, true);
+			sw.WriteLine ("\t\t[GLib.CDeclCallback]");
+			sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + Name + "VMDelegate (" + parms.ImportSignature + ");\n");
+
+			if (use_glue) {
+				glue = gen_info.GlueWriter;
+				glue_name = String.Format ("{0}sharp_{1}_override_{2}", container_type.NS.ToLower ().Replace (".", "_"), container_type.Name.ToLower (), ClassFieldName);
+				sw.WriteLine ("\t\t[DllImport (\"{0}\")]", gen_info.GluelibName);
+				sw.WriteLine ("\t\tstatic extern void {0} (IntPtr gtype, {1}VMDelegate cb);\n", glue_name, Name);
+				glue.WriteLine ("void {0} (GType gtype, gpointer cb);\n", glue_name);
+				glue.WriteLine ("void\n{0} (GType gtype, gpointer cb)", glue_name);
+				glue.WriteLine ("{");
+				glue.WriteLine ("\tGObjectClass *klass = g_type_class_peek (gtype);");
+				glue.WriteLine ("\tif (klass == NULL)");
+				glue.WriteLine ("\t\tklass = g_type_class_ref (gtype);");
+				glue.WriteLine ("\t(({0} *)klass)->{1} = cb;", container_type.CName + "Class", ClassFieldName);
+				glue.WriteLine ("}\n");
+			}
+
+			sw.WriteLine ("\t\tstatic {0} {1};\n", Name + "VMDelegate", Name + "VMCallback");
+			sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + parms.ImportSignature + ")");
+			sw.WriteLine ("\t\t{");
+			string unconditional = call.Unconditional ("\t\t\t");
+			if (unconditional.Length > 0)
+				sw.WriteLine (unconditional);
+			sw.WriteLine ("\t\t\ttry {");
+			sw.WriteLine ("\t\t\t\t{0} {1}_managed = GLib.Object.GetObject ({1}, false) as {0};", implementor != null ? implementor.Name : container_type.Name, parms[0].Name);
+			sw.Write (call.Setup ("\t\t\t\t"));
+			sw.Write ("\t\t\t\t{0}", IsVoid ? "" : retval.CSType == retval.ToNativeType ? "return " : retval.CSType + " raw_ret = ");
+			sw.WriteLine ("{2}_managed.{0} ({1});", "On" + Name, call.ToString (), parms[0].Name);
+			sw.Write (call.Finish ("\t\t\t\t"));
+			if (!IsVoid && retval.CSType != retval.ToNativeType)
+				sw.WriteLine ("\t\t\t\treturn {0};", SymbolTable.Table.ToNativeReturn (retval.CType, "raw_ret"));
+			sw.WriteLine ("\t\t\t} catch (Exception e) {");
+			bool fatal = HasOutParams || !IsVoid;
+			sw.WriteLine ("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, " + (fatal ? "true" : "false") + ");");
+			if (fatal) {
+				sw.WriteLine ("\t\t\t\t// NOTREACHED: above call doesn't return");
+				sw.WriteLine ("\t\t\t\tthrow e;");
+			}
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}\n");
+			sw.WriteLine ("\t\tprivate static void Override" + Name + " (GLib.GType gtype)");
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\tif (" + Name + "VMCallback == null)");
+			sw.WriteLine ("\t\t\t\t" + Name + "VMCallback = new " + Name + "VMDelegate (" + Name.ToLower() + "_cb);");
+			if (use_glue)
+				sw.WriteLine ("\t\t\t{0} (gtype.Val, {1}VMCallback);", glue_name, Name);
+			else
+				sw.WriteLine ("\t\t\tOverrideVirtualMethod (gtype, " + CName + ", " + Name + "VMCallback);");
+			sw.WriteLine ("\t\t}\n");
+		}
+
+		public void GenEvent (StreamWriter sw, ClassBase implementor, string target)
+		{
+			string args_type = IsEventHandler ? "" : ", typeof (" + EventArgsQualifiedName + ")";
+			
+			if (Marshaled) {
+				GenCallback (sw);
+				args_type = ", new " + DelegateName + "(" + CallbackName + ")";
+			}
+
+			sw.WriteLine("\t\t[GLib.Signal("+ CName + ")]");
+			sw.Write("\t\tpublic ");
+			if (NeedNew (implementor))
+				sw.Write("new ");
+			sw.WriteLine("event " + EventHandlerQualifiedName + " " + Name + " {");
+			sw.WriteLine("\t\t\tadd {");
+			sw.WriteLine("\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (" + target + ", " + CName + args_type + ");");
+			sw.WriteLine("\t\t\t\tsig.AddDelegate (value);");
+			sw.WriteLine("\t\t\t}");
+			sw.WriteLine("\t\t\tremove {");
+			sw.WriteLine("\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (" + target + ", " + CName + args_type + ");");
+			sw.WriteLine("\t\t\t\tsig.RemoveDelegate (value);");
+			sw.WriteLine("\t\t\t}");
+			sw.WriteLine("\t\t}");
+			sw.WriteLine();
+		}
+
+		public void Generate (GenerationInfo gen_info, ClassBase implementor)
+		{
+			StreamWriter sw = gen_info.Writer;
+
+			if (implementor == null)
+				GenEventHandler (gen_info);
+
+			GenDefaultHandlerDelegate (gen_info, implementor);
+			if (gen_info.GlueEnabled && implementor == null && ClassFieldName.Length > 0)
+				GenGlueVirtualMethod (gen_info);
+			else
+				GenChainVirtualMethod (sw, implementor);
+			GenEvent (sw, implementor, "this");
+			
+			Statistics.SignalCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Signature.cs b/lib/unique-sharp/generator/Signature.cs
new file mode 100644
index 0000000..1b01234
--- /dev/null
+++ b/lib/unique-sharp/generator/Signature.cs
@@ -0,0 +1,123 @@
+// GtkSharp.Generation.Signature.cs - The Signature Generation Class.
+//
+// Author: Mike Kestner <mkestner ximian com>
+//
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.Xml;
+
+	public class Signature  {
+		
+		private ArrayList parms = new ArrayList ();
+
+		public Signature (Parameters parms) 
+		{
+			foreach (Parameter p in parms) {
+				if (!parms.IsHidden (p))
+					this.parms.Add (p);
+			}
+		}
+
+		public override string ToString ()
+		{
+			if (parms.Count == 0)
+				return "";
+
+			string[] result = new string [parms.Count];
+			int i = 0;
+
+			foreach (Parameter p in parms) {
+				result [i] = p.PassAs != "" ? p.PassAs + " " : "";
+				result [i++] += p.CSType + " " + p.Name;
+			}
+
+			return String.Join (", ", result);
+		}
+
+		public string Types {
+			get {
+				if (parms.Count == 0)
+					return "";
+
+				string[] result = new string [parms.Count];
+				int i = 0;
+
+				foreach (Parameter p in parms)
+					result [i++] = p.CSType;
+
+				return String.Join (":", result);
+			}
+		}
+
+		public bool IsAccessor {
+			get {
+				int count = 0;
+				foreach (Parameter p in parms) {
+					if (p.PassAs == "out")
+						count++;
+					
+					if (count > 1)
+						return false;
+				}
+				return count == 1;
+			}
+		}
+
+		public string AccessorType {
+			get {
+				foreach (Parameter p in parms) 
+					if (p.PassAs == "out")
+						return p.CSType;
+				
+				return null;
+			}
+		}
+
+		public string AccessorName {
+			get {
+				foreach (Parameter p in parms) 
+					if (p.PassAs == "out")
+						return p.Name;
+				
+				return null;
+			}
+		}
+
+		public string AsAccessor {
+			get {
+				string[] result = new string [parms.Count - 1];
+				int i = 0;
+
+				foreach (Parameter p in parms) {
+					if (p.PassAs == "out")
+						continue;
+
+					result [i] = p.PassAs != "" ? p.PassAs + " " : "";
+					result [i++] += p.CSType + " " + p.Name;
+				}
+				
+				return String.Join (", ", result);
+			}
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/SimpleBase.cs b/lib/unique-sharp/generator/SimpleBase.cs
new file mode 100644
index 0000000..38bfbe3
--- /dev/null
+++ b/lib/unique-sharp/generator/SimpleBase.cs
@@ -0,0 +1,121 @@
+// GtkSharp.Generation.SimpleBase.cs - base class for marshaling non-generated types.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public abstract class SimpleBase : IGeneratable  {
+		
+		string type;
+		string ctype;
+		string ns = String.Empty;
+		string default_value = String.Empty;
+
+		public SimpleBase (string ctype, string type, string default_value)
+		{
+			string[] toks = type.Split('.');
+			this.ctype = ctype;
+			this.type = toks[toks.Length - 1];
+			if (toks.Length > 2)
+				this.ns = String.Join (".", toks, 0, toks.Length - 1);
+			else if (toks.Length == 2)
+				this.ns = toks[0];
+			this.default_value = default_value;
+		}
+		
+		public string CName {
+			get {
+				return ctype;
+			}
+		}
+
+		public string Name {
+			get {
+				return type;
+			}
+		}
+
+		public string QualifiedName {
+			get {
+				return ns == String.Empty ? type : ns + "." + type;
+			}
+		}
+
+		public virtual string MarshalType {
+			get {
+				return QualifiedName;
+			}
+		}
+
+		public virtual string MarshalReturnType {
+			get {
+				return MarshalType;
+			}
+		}
+
+		public virtual string DefaultValue {
+			get {
+				return default_value;
+			}
+		}
+
+		public virtual string ToNativeReturnType {
+			get {
+				return MarshalType;
+			}
+		}
+
+		public virtual string CallByName (string var)
+		{
+			return var;
+		}
+		
+		public virtual string FromNative(string var)
+		{
+			return var;
+		}
+		
+		public virtual string FromNativeReturn(string var)
+		{
+			return FromNative (var);
+		}
+
+		public virtual string ToNativeReturn(string var)
+		{
+			return CallByName (var);
+		}
+
+		public bool Validate ()
+		{
+			return true;
+		}
+
+		public void Generate ()
+		{
+		}
+		
+		public void Generate (GenerationInfo gen_info)
+		{
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/SimpleGen.cs b/lib/unique-sharp/generator/SimpleGen.cs
new file mode 100644
index 0000000..b382135
--- /dev/null
+++ b/lib/unique-sharp/generator/SimpleGen.cs
@@ -0,0 +1,31 @@
+// GtkSharp.Generation.SimpleGen.cs - The Simple type Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2003 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+
+	public class SimpleGen : SimpleBase {
+		public SimpleGen (string ctype, string type, string default_value) : base (ctype, type, default_value) {}
+
+	}
+}
+
diff --git a/lib/unique-sharp/generator/Statistics.cs b/lib/unique-sharp/generator/Statistics.cs
new file mode 100644
index 0000000..4545765
--- /dev/null
+++ b/lib/unique-sharp/generator/Statistics.cs
@@ -0,0 +1,197 @@
+// Statistics.cs : Generation statistics class implementation
+//
+// Author: Mike Kestner  <mkestner ximian com>
+//
+// Copyright (c) 2002 Mike Kestner
+// Copyright (c) 2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+	
+	using System;
+	using System.Collections;
+	
+	public class Statistics {
+		
+		static int cbs = 0;
+		static int enums = 0;
+		static int objects = 0;
+		static int structs = 0;
+		static int boxed = 0;
+		static int opaques = 0;
+		static int interfaces = 0;
+		static int methods = 0;
+		static int ctors = 0;
+		static int props = 0;
+		static int sigs = 0;
+		static int throttled = 0;
+		static int ignored = 0;
+		static bool vm_ignored = false;
+		
+		public static int CBCount {
+			get {
+				return cbs;
+			}
+			set {
+				cbs = value;
+			}
+		}
+
+		public static int EnumCount {
+			get {
+				return enums;
+			}
+			set {
+				enums = value;
+			}
+		}
+
+		public static int ObjectCount {
+			get {
+				return objects;
+			}
+			set {
+				objects = value;
+			}
+		}
+
+		public static int StructCount {
+			get {
+				return structs;
+			}
+			set {
+				structs = value;
+			}
+		}
+
+		public static int BoxedCount {
+			get {
+				return boxed;
+			}
+			set {
+				boxed = value;
+			}
+		}
+
+		public static int OpaqueCount {
+			get {
+				return opaques;
+			}
+			set {
+				opaques = value;
+			}
+		}
+
+		public static int CtorCount {
+			get {
+				return ctors;
+			}
+			set {
+				ctors = value;
+			}
+		}
+		
+		public static int MethodCount {
+			get {
+				return methods;
+			}
+			set {
+				methods = value;
+			}
+		}
+
+		public static int PropCount {
+			get {
+				return props;
+			}
+			set {
+				props = value;
+			}
+		}
+
+		public static int SignalCount {
+			get {
+				return sigs;
+			}
+			set {
+				sigs = value;
+			}
+		}
+
+		public static int IFaceCount {
+			get {
+				return interfaces;
+			}
+			set {
+				interfaces = value;
+			}
+		}
+
+		public static int ThrottledCount {
+			get {
+				return throttled;
+			}
+			set {
+				throttled = value;
+			}
+		}
+		
+		public static int IgnoreCount {
+			get {
+				return ignored;
+			}
+			set {
+				ignored = value;
+			}
+		}
+		
+		public static bool VMIgnored {
+			get {
+				return vm_ignored;
+			}
+			set {
+				if (value)
+					vm_ignored = value;
+			}
+		}
+		
+		public static void Report()
+		{
+			if (VMIgnored) {
+				Console.WriteLine();
+				Console.WriteLine("Warning: Generation throttled for Virtual Methods.");
+				Console.WriteLine("  Consider regenerating with --gluelib-name and --glue-filename.");
+			}
+			Console.WriteLine();
+			Console.WriteLine("Generation Summary:");
+			Console.Write("  Enums: " + enums);
+			Console.Write("  Structs: " + structs);
+			Console.Write("  Boxed: " + boxed);
+			Console.Write("  Opaques: " + opaques);
+			Console.Write("  Interfaces: " + interfaces);
+			Console.Write("  Objects: " + objects);
+			Console.WriteLine("  Callbacks: " + cbs);
+			Console.Write("  Properties: " + props);
+			Console.Write("  Signals: " + sigs);
+			Console.Write("  Methods: " + methods);
+			Console.Write("  Constructors: " + ctors);
+			Console.WriteLine("  Throttled: " + throttled);
+			Console.WriteLine("Total Nodes: " + (enums+structs+boxed+opaques+interfaces+cbs+objects+props+sigs+methods+ctors+throttled));
+			Console.WriteLine();
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/StructBase.cs b/lib/unique-sharp/generator/StructBase.cs
new file mode 100644
index 0000000..7e1b87a
--- /dev/null
+++ b/lib/unique-sharp/generator/StructBase.cs
@@ -0,0 +1,230 @@
+// GtkSharp.Generation.StructBase.cs - The Structure/Boxed Base Class.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Text.RegularExpressions;
+	using System.Xml;
+
+	public abstract class StructBase : ClassBase, IManualMarshaler {
+	
+		new ArrayList fields = new ArrayList ();
+		bool need_read_native = false;
+
+		protected StructBase (XmlElement ns, XmlElement elem) : base (ns, elem)
+		{
+			foreach (XmlNode node in elem.ChildNodes) {
+
+				if (!(node is XmlElement)) continue;
+				XmlElement member = (XmlElement) node;
+
+				switch (node.Name) {
+				case "field":
+					fields.Add (new StructField (member, this));
+					break;
+
+				case "callback":
+					Statistics.IgnoreCount++;
+					break;
+
+				default:
+					if (!IsNodeNameHandled (node.Name))
+						Console.WriteLine ("Unexpected node " + node.Name + " in " + CName);
+					break;
+				}
+			}
+		}
+
+		public override string DefaultValue {
+			get {
+				return QualifiedName + ".Zero";
+			}
+		}
+
+		public override string MarshalType {
+			get {
+				return "IntPtr";
+			}
+		}
+
+		public override string AssignToName {
+			get { throw new NotImplementedException (); }
+		}
+
+		public override string CallByName ()
+		{
+			return "this_as_native";
+		}
+
+		public override string CallByName (string var)
+		{
+			return var + "_as_native";
+		}
+
+		public override string FromNative (string var)
+		{
+			if (DisableNew)
+				return var + " == IntPtr.Zero ? " + QualifiedName + ".Zero : (" + QualifiedName + ") System.Runtime.InteropServices.Marshal.PtrToStructure (" + var + ", typeof (" + QualifiedName + "))";
+			else
+				return QualifiedName + ".New (" + var + ")";
+		}
+		
+		public string AllocNative (string var)
+		{
+			return "GLib.Marshaller.StructureToPtrAlloc (" + var + ")";
+		}
+
+		public string ReleaseNative (string var)
+		{
+			return "Marshal.FreeHGlobal (" +var + ")";
+		}
+
+		private bool DisableNew {
+			get {
+				return Elem.HasAttribute ("disable_new");
+			}
+		}
+
+		protected new void GenFields (GenerationInfo gen_info)
+		{
+			int bitfields = 0;
+			bool need_field = true;
+
+			foreach (StructField field in fields) {
+				if (field.IsBitfield) {
+					if (need_field) {
+						StreamWriter sw = gen_info.Writer;
+
+						sw.WriteLine ("\t\tprivate uint _bitfield{0};\n", bitfields++);
+						need_field = false;
+					}
+				} else
+					need_field = true;
+				field.Generate (gen_info, "\t\t");
+			}
+		}
+
+		public override bool Validate ()
+		{
+			foreach (StructField field in fields) {
+				if (!field.Validate ()) {
+					Console.WriteLine ("in Struct " + QualifiedName);
+					if (!field.IsPointer)
+						return false;
+				}
+			}
+
+			return base.Validate ();
+		}
+
+		public override void Generate (GenerationInfo gen_info)
+		{
+			bool need_close = false;
+			if (gen_info.Writer == null) {
+				gen_info.Writer = gen_info.OpenStream (Name);
+				need_close = true;
+			}
+
+			StreamWriter sw = gen_info.Writer;
+			
+			sw.WriteLine ("namespace " + NS + " {");
+			sw.WriteLine ();
+			sw.WriteLine ("\tusing System;");
+			sw.WriteLine ("\tusing System.Collections;");
+			sw.WriteLine ("\tusing System.Runtime.InteropServices;");
+			sw.WriteLine ();
+			
+			sw.WriteLine ("#region Autogenerated code");
+			if (IsDeprecated)
+				sw.WriteLine ("\t[Obsolete]");
+			sw.WriteLine ("\t[StructLayout(LayoutKind.Sequential)]");
+			string access = IsInternal ? "internal" : "public";
+			sw.WriteLine ("\t" + access + " struct " + Name + " {");
+			sw.WriteLine ();
+
+			need_read_native = false;
+			GenFields (gen_info);
+			sw.WriteLine ();
+			GenCtors (gen_info);
+			GenMethods (gen_info, null, this);
+			if (need_read_native)
+				GenReadNative (sw);
+
+			if (!need_close)
+				return;
+
+			sw.WriteLine ("#endregion");
+			AppendCustom(sw, gen_info.CustomDir);
+			
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+			sw.Close ();
+			gen_info.Writer = null;
+		}
+		
+		protected override void GenCtors (GenerationInfo gen_info)
+		{
+			StreamWriter sw = gen_info.Writer;
+
+			sw.WriteLine ("\t\tpublic static {0} Zero = new {0} ();", QualifiedName);
+			sw.WriteLine();
+			if (!DisableNew) {
+				sw.WriteLine ("\t\tpublic static " + QualifiedName + " New(IntPtr raw) {");
+				sw.WriteLine ("\t\t\tif (raw == IntPtr.Zero)");
+				sw.WriteLine ("\t\t\t\treturn {0}.Zero;", QualifiedName);
+				sw.WriteLine ("\t\t\treturn ({0}) Marshal.PtrToStructure (raw, typeof ({0}));", QualifiedName);
+				sw.WriteLine ("\t\t}");
+				sw.WriteLine ();
+			}
+
+			foreach (Ctor ctor in Ctors)
+				ctor.IsStatic = true;
+
+			base.GenCtors (gen_info);
+		}
+
+		void GenReadNative (StreamWriter sw)
+		{
+			sw.WriteLine ("\t\tstatic void ReadNative (IntPtr native, ref {0} target)", QualifiedName);
+			sw.WriteLine ("\t\t{");
+			sw.WriteLine ("\t\t\ttarget = New (native);");
+			sw.WriteLine ("\t\t}");
+			sw.WriteLine ();
+		}
+
+		public override void Prepare (StreamWriter sw, string indent)
+		{
+			sw.WriteLine (indent + "IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf (this));");
+			sw.WriteLine (indent + "System.Runtime.InteropServices.Marshal.StructureToPtr (this, this_as_native, false);");
+		}
+
+		public override void Finish (StreamWriter sw, string indent)
+		{
+			need_read_native = true;
+			sw.WriteLine (indent + "ReadNative (this_as_native, ref this);");
+			sw.WriteLine (indent + "System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);");
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/StructField.cs b/lib/unique-sharp/generator/StructField.cs
new file mode 100644
index 0000000..58f92d4
--- /dev/null
+++ b/lib/unique-sharp/generator/StructField.cs
@@ -0,0 +1,149 @@
+// GtkSharp.Generation.StructField.cs - The Structure Field generation
+// Class.
+//
+// Author: Mike Kestner <mkestner ximian com>
+//
+// Copyright (c) 2004-2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+	using System.Xml;
+
+	public class StructField : FieldBase {
+
+		public static int bitfields;
+
+		public StructField (XmlElement elem, ClassBase container_type) : base (elem, container_type) {}
+
+		protected override string DefaultAccess {
+			get {
+				if (IsPadding)
+					return "private";
+
+				return "public";
+			}
+		}
+
+		int ArrayLength {
+			get {
+				if (!IsArray)
+					return 0;
+				
+				int result;
+				try {
+					result = Int32.Parse (elem.GetAttribute("array_len"));
+				} catch (Exception) {
+					Console.Write ("Non-numeric array_len: " + elem.GetAttribute("array_len"));
+					Console.WriteLine (" warning: array field {0} incorrectly generated", Name);
+					result = 0;
+				}
+				return result;
+			}
+		}
+
+		public new string CSType {
+			get {
+				string type = base.CSType;
+				if (IsArray)
+					type += "[]";
+				else if ((IsPointer || SymbolTable.Table.IsOpaque (CType)) && type != "string")
+					type = "IntPtr";
+
+				return type;
+			}
+		}
+
+		bool IsPadding {
+			get {
+				return (CName.StartsWith ("dummy") || CName.StartsWith ("padding"));
+			}
+		}
+
+		public bool IsPointer {
+			get {
+				return (CType.EndsWith ("*") || CType.EndsWith ("pointer"));
+			}
+		}
+
+		public new string Name {
+			get {
+				string result = "";
+				if ((IsPointer || SymbolTable.Table.IsOpaque (CType)) && CSType != "string")
+					result = "_";
+				result += SymbolTable.Table.MangleName (CName);
+
+				return result;
+			}
+		}
+
+		string StudlyName {
+			get {
+				string studly = base.Name;
+				if (studly == "")
+					throw new Exception ("API file must be regenerated with a current version of the GAPI parser. It is incompatible with this version of the GAPI code generator.");
+
+				return studly;
+			}
+		}
+
+		public override void Generate (GenerationInfo gen_info, string indent)
+		{
+			if (Hidden)
+				return;
+
+			StreamWriter sw = gen_info.Writer;
+			SymbolTable table = SymbolTable.Table;
+
+			string wrapped = table.GetCSType (CType);
+			string wrapped_name = SymbolTable.Table.MangleName (CName);
+			IGeneratable gen = table [CType];
+
+			if (IsArray) {
+				sw.WriteLine (indent + "[MarshalAs (UnmanagedType.ByValArray, SizeConst=" + ArrayLength + ")]");
+				sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, StudlyName);
+			} else if (IsBitfield) {
+				base.Generate (gen_info, indent);
+			} else if (gen is IAccessor) {
+				sw.WriteLine (indent + "private {0} {1};", gen.MarshalType, Name);
+
+				if (Access != "private") {
+					IAccessor acc = table [CType] as IAccessor;
+					sw.WriteLine (indent + Access + " " + wrapped + " " + StudlyName + " {");
+					acc.WriteAccessors (sw, indent + "\t", Name);
+					sw.WriteLine (indent + "}");
+				}
+			} else if (IsPointer && (gen is StructGen || gen is BoxedGen)) {
+				sw.WriteLine (indent + "private {0} {1};", CSType, Name);
+				sw.WriteLine ();
+				if (Access != "private") {
+					sw.WriteLine (indent + Access + " " + wrapped + " " + wrapped_name + " {");
+					sw.WriteLine (indent + "\tget { return " + table.FromNativeReturn (CType, Name) + "; }");
+					sw.WriteLine (indent + "}");
+				}
+			} else if (IsPointer && CSType != "string") {
+				// FIXME: probably some fields here which should be visible.
+				sw.WriteLine (indent + "private {0} {1};", CSType, Name);
+			} else {
+				sw.WriteLine (indent + "{0} {1} {2};", Access, CSType, Access == "public" ? StudlyName : Name);
+			}
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/StructGen.cs b/lib/unique-sharp/generator/StructGen.cs
new file mode 100644
index 0000000..4d615ad
--- /dev/null
+++ b/lib/unique-sharp/generator/StructGen.cs
@@ -0,0 +1,53 @@
+// GtkSharp.Generation.StructGen.cs - The Structure Generatable.
+//
+// Author: Mike Kestner <mkestner speakeasy net>
+//
+// Copyright (c) 2001 Mike Kestner
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.IO;
+	using System.Xml;
+
+	public class StructGen : StructBase {
+		
+		public StructGen (XmlElement ns, XmlElement elem) : base (ns, elem) {}
+		
+		public override void Generate (GenerationInfo gen_info)
+		{
+			gen_info.CurrentType = Name;
+
+			StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
+			base.Generate (gen_info);
+			if (GetMethod ("GetType") == null && GetMethod ("GetGType") == null) {
+				sw.WriteLine ("\t\tprivate static GLib.GType GType {");
+				sw.WriteLine ("\t\t\tget { return GLib.GType.Pointer; }");
+				sw.WriteLine ("\t\t}");
+			}
+			sw.WriteLine ("#endregion");
+			AppendCustom (sw, gen_info.CustomDir);
+			sw.WriteLine ("\t}");
+			sw.WriteLine ("}");
+			sw.Close ();
+			gen_info.Writer = null;
+			Statistics.StructCount++;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/SymbolTable.cs b/lib/unique-sharp/generator/SymbolTable.cs
new file mode 100644
index 0000000..e10b51f
--- /dev/null
+++ b/lib/unique-sharp/generator/SymbolTable.cs
@@ -0,0 +1,412 @@
+// GtkSharp.Generation.SymbolTable.cs - The Symbol Table Class.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2001-2003 Mike Kestner
+// Copyright (c) 2004-2005 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+
+	public class SymbolTable {
+		
+		static SymbolTable table = null;
+
+		Hashtable types = new Hashtable ();
+		
+		public static SymbolTable Table {
+			get {
+				if (table == null)
+					table = new SymbolTable ();
+
+				return table;
+			}
+		}
+
+		public SymbolTable ()
+		{
+			// Simple easily mapped types
+			AddType (new SimpleGen ("void", "void", String.Empty));
+			AddType (new SimpleGen ("gpointer", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("gboolean", "bool", "false"));
+			AddType (new SimpleGen ("gint", "int", "0"));
+			AddType (new SimpleGen ("guint", "uint", "0"));
+			AddType (new SimpleGen ("int", "int", "0"));
+			AddType (new SimpleGen ("unsigned", "uint", "0"));
+			AddType (new SimpleGen ("unsigned int", "uint", "0"));
+			AddType (new SimpleGen ("unsigned-int", "uint", "0"));
+			AddType (new SimpleGen ("gshort", "short", "0"));
+			AddType (new SimpleGen ("gushort", "ushort", "0"));
+			AddType (new SimpleGen ("short", "short", "0"));
+			AddType (new SimpleGen ("guchar", "byte", "0"));
+			AddType (new SimpleGen ("unsigned char", "byte", "0"));
+			AddType (new SimpleGen ("unsigned-char", "byte", "0"));
+			AddType (new SimpleGen ("guint1", "bool", "false"));
+			AddType (new SimpleGen ("uint1", "bool", "false"));
+			AddType (new SimpleGen ("gint8", "sbyte", "0"));
+			AddType (new SimpleGen ("guint8", "byte", "0"));
+			AddType (new SimpleGen ("gint16", "short", "0"));
+			AddType (new SimpleGen ("guint16", "ushort", "0"));
+			AddType (new SimpleGen ("gint32", "int", "0"));
+			AddType (new SimpleGen ("guint32", "uint", "0"));
+			AddType (new SimpleGen ("gint64", "long", "0"));
+			AddType (new SimpleGen ("guint64", "ulong", "0"));
+			AddType (new SimpleGen ("long long", "long", "0"));
+			AddType (new SimpleGen ("gfloat", "float", "0.0"));
+			AddType (new SimpleGen ("float", "float", "0.0"));
+			AddType (new SimpleGen ("gdouble", "double", "0.0"));
+			AddType (new SimpleGen ("double", "double", "0.0"));
+			AddType (new SimpleGen ("goffset", "long", "0"));
+			AddType (new SimpleGen ("GQuark", "int", "0"));
+
+			// platform specific integer types.
+#if WIN64LONGS
+			AddType (new SimpleGen ("long", "int", "0"));
+			AddType (new SimpleGen ("glong", "int", "0"));
+			AddType (new SimpleGen ("ulong", "uint", "0"));
+			AddType (new SimpleGen ("gulong", "uint", "0"));
+			AddType (new SimpleGen ("unsigned long", "uint", "0"));
+#else
+			AddType (new LPGen ("long"));
+			AddType (new LPGen ("glong"));
+			AddType (new LPUGen ("ulong"));
+			AddType (new LPUGen ("gulong"));
+			AddType (new LPUGen ("unsigned long"));
+#endif
+
+			AddType (new LPGen ("ssize_t"));
+			AddType (new LPGen ("gssize"));
+			AddType (new LPUGen ("size_t"));
+			AddType (new LPUGen ("gsize"));
+
+#if OFF_T_8
+			AddType (new AliasGen ("off_t", "long"));
+#else
+			AddType (new LPGen ("off_t"));
+#endif
+
+			// string types
+			AddType (new ConstStringGen ("const-gchar"));
+			AddType (new ConstStringGen ("const-xmlChar"));
+			AddType (new ConstStringGen ("const-char"));
+			AddType (new ConstFilenameGen ("const-gfilename"));
+			AddType (new MarshalGen ("gfilename", "string", "IntPtr", "GLib.Marshaller.StringToFilenamePtr({0})", "GLib.Marshaller.FilenamePtrToStringGFree({0})"));
+			AddType (new MarshalGen ("gchar", "string", "IntPtr", "GLib.Marshaller.StringToPtrGStrdup({0})", "GLib.Marshaller.PtrToStringGFree({0})"));
+			AddType (new MarshalGen ("char", "string", "IntPtr", "GLib.Marshaller.StringToPtrGStrdup({0})", "GLib.Marshaller.PtrToStringGFree({0})"));
+			AddType (new SimpleGen ("GStrv", "string[]", "null"));
+
+			// manually wrapped types requiring more complex marshaling
+			AddType (new ManualGen ("GInitiallyUnowned", "GLib.InitiallyUnowned", "GLib.Object.GetObject ({0})"));
+			AddType (new ManualGen ("GObject", "GLib.Object", "GLib.Object.GetObject ({0})"));
+			AddType (new ManualGen ("GList", "GLib.List"));
+			AddType (new ManualGen ("GPtrArray", "GLib.PtrArray"));
+			AddType (new ManualGen ("GSList", "GLib.SList"));
+			AddType (new MarshalGen ("gunichar", "char", "uint", "GLib.Marshaller.CharToGUnichar ({0})", "GLib.Marshaller.GUnicharToChar ({0})"));
+			AddType (new MarshalGen ("time_t", "System.DateTime", "IntPtr", "GLib.Marshaller.DateTimeTotime_t ({0})", "GLib.Marshaller.time_tToDateTime ({0})"));
+			AddType (new MarshalGen ("GString", "string", "IntPtr", "new GLib.GString ({0}).Handle", "GLib.GString.PtrToString ({0})"));
+			AddType (new MarshalGen ("GType", "GLib.GType", "IntPtr", "{0}.Val", "new GLib.GType({0})"));
+			AddType (new ByRefGen ("GValue", "GLib.Value"));
+			AddType (new SimpleGen ("GDestroyNotify", "GLib.DestroyNotify", "null"));
+
+			// FIXME: These ought to be handled properly.
+			AddType (new SimpleGen ("GC", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GError", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GMemChunk", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GTimeVal", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GClosure", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GArray", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GByteArray", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GData", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GIOChannel", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GTypeModule", "GLib.Object", "null"));
+			AddType (new SimpleGen ("GHashTable", "System.IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("va_list", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("GParamSpec", "IntPtr", "IntPtr.Zero"));
+			AddType (new SimpleGen ("gconstpointer", "IntPtr", "IntPtr.Zero"));
+		}
+		
+		public void AddType (IGeneratable gen)
+		{
+			types [gen.CName] = gen;
+		}
+		
+		public void AddTypes (IGeneratable[] gens)
+		{
+			foreach (IGeneratable gen in gens)
+				types [gen.CName] = gen;
+		}
+		
+		public int Count {
+			get
+			{
+				return types.Count;
+			}
+		}
+		
+		public IEnumerable Generatables {
+			get {
+				return types.Values;
+			}
+		}
+		
+		public IGeneratable this [string ctype] {
+			get {
+				return DeAlias (ctype) as IGeneratable;
+			}
+		}
+
+		private bool IsConstString (string type)
+		{
+			switch (type) {
+			case "const-gchar":
+			case "const-char":
+			case "const-xmlChar":
+			case "const-gfilename":
+				return true;
+			default:
+				return false;
+			}
+		}
+
+		private string Trim(string type)
+		{
+			// HACK: If we don't detect this here, there is no
+			// way of indicating it in the symbol table
+			if (type == "void*" || type == "const-void*") return "gpointer";
+
+			string trim_type = type.TrimEnd('*');
+
+			if (IsConstString (trim_type))
+				return trim_type;
+			
+			if (trim_type.StartsWith("const-")) return trim_type.Substring(6);
+			return trim_type;
+		}
+
+		private object DeAlias (string type)
+		{
+			type = Trim (type);
+			while (types [type] is AliasGen) {
+				IGeneratable igen = types [type] as AliasGen;
+				types [type] = types [igen.Name];
+				type = igen.Name;
+			}
+
+			return types [type];
+		}
+
+		public string FromNativeReturn(string c_type, string val)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.FromNativeReturn (val);
+		}
+		
+		public string ToNativeReturn(string c_type, string val)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.ToNativeReturn (val);
+		}
+
+		public string FromNative(string c_type, string val)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.FromNative (val);
+		}
+
+		public string GetCSType(string c_type)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.QualifiedName;
+		}
+		
+		public string GetName(string c_type)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.Name;
+		}
+		
+		public string GetMarshalReturnType(string c_type)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.MarshalReturnType;
+		}
+		
+		public string GetToNativeReturnType(string c_type)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.ToNativeReturnType;
+		}
+		
+		public string GetMarshalType(string c_type)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.MarshalType;
+		}
+		
+		public string CallByName(string c_type, string var_name)
+		{
+			IGeneratable gen = this[c_type];
+			if (gen == null)
+				return "";
+			return gen.CallByName(var_name);
+		}
+	
+		public bool IsOpaque(string c_type)
+		{
+			if (this[c_type] is OpaqueGen)
+				return true;
+
+			return false;
+		}
+	
+		public bool IsBoxed(string c_type)
+		{
+			if (this[c_type] is BoxedGen)
+				return true;
+
+			return false;
+		}
+		
+		public bool IsStruct(string c_type)
+		{
+			if (this[c_type] is StructGen)
+				return true;
+
+			return false;
+		}
+	
+		public bool IsEnum(string c_type)
+		{
+			if (this[c_type] is EnumGen)
+				return true;
+
+			return false;
+		}
+	
+		public bool IsEnumFlags(string c_type)
+		{
+			EnumGen gen = this [c_type] as EnumGen;
+			return (gen != null && gen.Elem.GetAttribute ("type") == "flags");
+		}
+	
+		public bool IsInterface(string c_type)
+		{
+			if (this[c_type] is InterfaceGen)
+				return true;
+
+			return false;
+		}
+		
+		public ClassBase GetClassGen(string c_type)
+		{
+			return this[c_type] as ClassBase;
+		}
+			
+		public bool IsObject(string c_type)
+		{
+			if (this[c_type] is ObjectGen)
+				return true;
+
+			return false;
+		}
+
+		public bool IsCallback(string c_type)
+		{
+			if (this[c_type] is CallbackGen)
+				return true;
+
+			return false;
+		}
+
+		public bool IsManuallyWrapped(string c_type)
+		{
+			if (this[c_type] is ManualGen)
+				return true;
+
+			return false;
+		}
+
+		public string MangleName(string name)
+		{
+			switch (name) {
+			case "string":
+				return "str1ng";
+			case "event":
+				return "evnt";
+			case "null":
+				return "is_null";
+			case "object":
+				return "objekt";
+			case "params":
+				return "parms";
+			case "ref":
+				return "reference";
+			case "in":
+				return "in_param";
+			case "out":
+				return "out_param";
+			case "fixed":
+				return "mfixed";
+			case "byte":
+				return "_byte";
+			case "new":
+				return "_new";
+			case "base":
+				return "_base";
+			case "lock":
+				return "_lock";
+			case "callback":
+				return "cb";
+			case "readonly":
+				return "read_only";
+			case "interface":
+				return "iface";
+			case "internal":
+				return "_internal";
+			case "where":
+				return "wh3r3";
+			case "foreach":
+				return "for_each";
+			case "remove":
+				return "_remove";
+			default:
+				break;
+			}
+
+			return name;
+		}
+	}
+}
diff --git a/lib/unique-sharp/generator/VMSignature.cs b/lib/unique-sharp/generator/VMSignature.cs
new file mode 100644
index 0000000..fe0ebf1
--- /dev/null
+++ b/lib/unique-sharp/generator/VMSignature.cs
@@ -0,0 +1,75 @@
+// GtkSharp.Generation.VMSignature.cs - The Virtual Method Signature Generation Class.
+//
+// Author: Mike Kestner <mkestner ximian com>
+//
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.Xml;
+
+	public class VMSignature  {
+		
+		private ArrayList parms = new ArrayList ();
+
+		public VMSignature (Parameters parms) 
+		{
+			bool has_cb = parms.HideData;
+			for (int i = 1; i < parms.Count; i++) {
+				Parameter p = parms [i];
+
+				if (i > 1 && p.IsLength && parms [i - 1].IsString)
+					continue;
+
+				if (p.IsCount && ((i > 1 && parms [i - 1].IsArray) || (i < parms.Count - 1 && parms [i + 1].IsArray)))
+					continue;
+
+				has_cb = has_cb || p.Generatable is CallbackGen;
+				if (p.IsUserData && has_cb) 
+					continue;
+
+				if (p.CType == "GError**")
+					continue;
+
+				if (p.Scope == "notified")
+					i += 2;
+
+				this.parms.Add (p);
+			}
+		}
+
+		public override string ToString ()
+		{
+			if (parms.Count == 0)
+				return "";
+
+			string[] result = new string [parms.Count];
+			int i = 0;
+
+			foreach (Parameter p in parms) {
+				result [i] = p.PassAs != "" ? p.PassAs + " " : "";
+				result [i++] += p.CSType + " " + p.Name;
+			}
+
+			return String.Join (", ", result);
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/generator/VirtualMethod.cs b/lib/unique-sharp/generator/VirtualMethod.cs
new file mode 100644
index 0000000..8c09704
--- /dev/null
+++ b/lib/unique-sharp/generator/VirtualMethod.cs
@@ -0,0 +1,168 @@
+// GtkSharp.Generation.VirtualMethod.cs - The VirtualMethod Generatable.
+//
+// Author: Mike Kestner <mkestner novell com>
+//
+// Copyright (c) 2003-2004 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of version 2 of the GNU General Public
+// License as published by the Free Software Foundation.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+
+namespace GtkSharp.Generation {
+
+	using System;
+	using System.Collections;
+	using System.IO;
+	using System.Xml;
+
+	// FIXME: handle static VMs
+	public class VirtualMethod : MethodBase  {
+		
+		XmlElement elem;
+		ReturnValue retval;
+		Parameters parms;
+
+		public VirtualMethod (XmlElement elem, ClassBase container_type) : base (elem, container_type)
+		{
+			this.elem = elem;
+			retval = new ReturnValue (elem ["return-type"]);
+			parms = new Parameters (elem["parameters"]);
+			parms.HideData = true;
+		}
+
+		public bool IsGetter {
+			get {
+				return HasGetterName && ((!retval.IsVoid && parms.Count == 1) || (retval.IsVoid && parms.Count == 2 && parms [1].PassAs == "out"));
+			}
+		}
+	
+		public bool IsSetter {
+			get {
+				if (!HasSetterName || !retval.IsVoid)
+					return false;
+
+				if (parms.Count == 2 || (parms.Count == 4 && parms [1].Scope == "notified"))
+					return true;
+				else
+					return false;
+			}
+		}
+ 
+		public string MarshalReturnType {
+			get {
+				return SymbolTable.Table.GetToNativeReturnType (elem["return-type"].GetAttribute("type"));
+			}
+		}
+
+		public void GenerateCallback (StreamWriter sw)
+		{
+			if (!Validate ())
+				return;
+
+			ManagedCallString call = new ManagedCallString (parms, true);
+			string type = parms [0].CSType + "Implementor";
+			string name = parms [0].Name;
+			string call_string = "__obj." + Name + " (" + call + ")";
+			if (IsGetter)
+				call_string = "__obj." + (Name.StartsWith ("Get") ? Name.Substring (3) : Name);
+			else if (IsSetter)
+				call_string = "__obj." + Name.Substring (3) + " = " + call;
+
+			sw.WriteLine ("\t\t[GLib.CDeclCallback]");
+			sw.WriteLine ("\t\tdelegate " + MarshalReturnType + " " + Name + "Delegate (" + parms.ImportSignature + ");");
+			sw.WriteLine ();
+			sw.WriteLine ("\t\tstatic " + MarshalReturnType + " " + Name + "Callback (" + parms.ImportSignature + ")");
+			sw.WriteLine ("\t\t{");
+			string unconditional = call.Unconditional ("\t\t\t");
+			if (unconditional.Length > 0)
+				sw.WriteLine (unconditional);
+			sw.WriteLine ("\t\t\ttry {");
+			sw.WriteLine ("\t\t\t\t" + type + " __obj = GLib.Object.GetObject (" + name + ", false) as " + type + ";");
+			sw.Write (call.Setup ("\t\t\t\t"));
+			if (retval.IsVoid) { 
+				if (IsGetter) {
+					Parameter p = parms [1];
+					string out_name = p.Name;
+					if (p.MarshalType != p.CSType)
+						out_name = "my" + out_name;
+					sw.WriteLine ("\t\t\t\t" + out_name + " = " + call_string + ";");
+				} else
+					sw.WriteLine ("\t\t\t\t" + call_string + ";");
+			} else
+				sw.WriteLine ("\t\t\t\t" + retval.CSType + " __result = " + call_string + ";");
+			bool fatal = parms.HasOutParam || !retval.IsVoid;
+			sw.Write (call.Finish ("\t\t\t\t"));
+			if (!retval.IsVoid)
+				sw.WriteLine ("\t\t\t\treturn " + retval.ToNative ("__result") + ";");
+
+			sw.WriteLine ("\t\t\t} catch (Exception e) {");
+			sw.WriteLine ("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, " + (fatal ? "true" : "false") + ");");
+			if (fatal) {
+				sw.WriteLine ("\t\t\t\t// NOTREACHED: above call does not return.");
+				sw.WriteLine ("\t\t\t\tthrow e;");
+			}
+			sw.WriteLine ("\t\t\t}");
+			sw.WriteLine ("\t\t}");
+		}
+
+		public void GenerateDeclaration (StreamWriter sw, VirtualMethod complement)
+		{
+			VMSignature vmsig = new VMSignature (parms);
+			if (IsGetter) {
+				string name = Name.StartsWith ("Get") ? Name.Substring (3) : Name;
+				string type = retval.IsVoid ? parms [1].CSType : retval.CSType;
+				if (complement != null && complement.parms [1].CSType == type)
+					sw.WriteLine ("\t\t" + type + " " + name + " { get; set; }");
+				else {
+					sw.WriteLine ("\t\t" + type + " " + name + " { get; }");
+					if (complement != null)
+						sw.WriteLine ("\t\t" + complement.retval.CSType + " " + complement.Name + " (" + (new VMSignature (complement.parms)) + ");");
+				}
+			} else if (IsSetter) 
+				sw.WriteLine ("\t\t" + parms[1].CSType + " " + Name.Substring (3) + " { set; }");
+			else
+				sw.WriteLine ("\t\t" + retval.CSType + " " + Name + " (" + vmsig + ");");
+		}
+
+		enum ValidState {
+			Unvalidated,
+			Invalid,
+			Valid
+		}
+
+		ValidState vstate = ValidState.Unvalidated;
+
+		public bool IsValid {
+			get { 
+				if (vstate == ValidState.Unvalidated)
+					return Validate ();
+				else
+					return vstate == ValidState.Valid; 
+			}
+		}
+
+		public override bool Validate ()
+		{
+			if (!parms.Validate () || !retval.Validate ()) {
+				Console.Write ("in virtual method " + Name + " ");
+				vstate = ValidState.Invalid;
+				return false;
+			}
+
+			vstate = ValidState.Valid;
+			return true;
+		}
+	}
+}
+
diff --git a/lib/unique-sharp/unique/App.custom b/lib/unique-sharp/unique/App.custom
new file mode 100644
index 0000000..1a17457
--- /dev/null
+++ b/lib/unique-sharp/unique/App.custom
@@ -0,0 +1,104 @@
+// App.custom - customization for App.cs
+//
+// Author(s):
+//	Stephane Delcroix  <stephane delcroix org>
+//
+// Copyright (c) 2009 Stephane Delcroix
+//
+// This is open source software. See COPYING for details.
+//
+
+		public App (string name, string startup_id, params object [] commands) : this (name, startup_id)
+		{
+			for (int i = 0; i < commands.Length; i+=2)
+				AddCommand (commands[i] as string, (int)commands[i+1]);
+		}
+
+		[GLib.CDeclCallback]
+		delegate int MessageReceivedVMDelegate (IntPtr app, int command, IntPtr message_data, uint time_);
+
+		static MessageReceivedVMDelegate MessageReceivedVMCallback;
+
+		static int messagereceived_cb (IntPtr app, int command, IntPtr message_data, uint time_)
+		{
+			try {
+				App app_managed = GLib.Object.GetObject (app, false) as App;
+				Unique.Response raw_ret = app_managed.OnMessageReceived (command, message_data == IntPtr.Zero ? null : (Unique.MessageData) GLib.Opaque.GetOpaque (message_data, typeof (Unique.MessageData), false), time_);
+				return (int) raw_ret;
+			} catch (Exception e) {
+				GLib.ExceptionManager.RaiseUnhandledException (e, true);
+				// NOTREACHED: above call doesn't return
+				throw e;
+			}
+		}
+
+		static void OverrideMessageReceived (GLib.GType gtype)
+		{
+			if (MessageReceivedVMCallback == null)
+				MessageReceivedVMCallback = new MessageReceivedVMDelegate (messagereceived_cb);
+			OverrideVirtualMethod (gtype, "message-received", MessageReceivedVMCallback);
+		}
+
+		[GLib.DefaultSignalHandler(Type=typeof(Unique.App), ConnectionMethod="OverrideMessageReceived")]
+		protected virtual Unique.Response OnMessageReceived (int command, Unique.MessageData message_data, uint time_)
+		{
+			GLib.Value ret = new GLib.Value (Unique.ResponseGType.GType);
+			GLib.ValueArray inst_and_params = new GLib.ValueArray (4);
+			GLib.Value[] vals = new GLib.Value [4];
+			vals [0] = new GLib.Value (this);
+			inst_and_params.Append (vals [0]);
+			vals [1] = new GLib.Value (command);
+			inst_and_params.Append (vals [1]);
+			vals [2] = new GLib.Value (message_data);
+			inst_and_params.Append (vals [2]);
+			vals [3] = new GLib.Value (time_);
+			inst_and_params.Append (vals [3]);
+			g_signal_chain_from_overridden (inst_and_params.ArrayPtr, ref ret);
+			foreach (GLib.Value v in vals)
+				v.Dispose ();
+			Unique.Response result = (Unique.Response) (Enum) ret;
+			ret.Dispose ();
+			return result;
+		}
+
+		[GLib.Signal("message-received")]
+		event Unique.MessageReceivedHandler InternalMessageReceived {
+			add {
+				GLib.Signal sig = GLib.Signal.Lookup (this, "message-received", typeof (Unique.MessageReceivedArgs));
+				sig.AddDelegate (value);
+			}
+			remove {
+				GLib.Signal sig = GLib.Signal.Lookup (this, "message-received", typeof (Unique.MessageReceivedArgs));
+				sig.RemoveDelegate (value);
+			}
+		}
+
+		MessageReceivedHandler received_handler;
+
+		public event MessageReceivedHandler MessageReceived {
+			add {
+				if (received_handler == null)
+					InternalMessageReceived += MessageReceivedWrapper;
+				received_handler = (MessageReceivedHandler)Delegate.Combine (received_handler, value);
+			}
+			remove {
+				received_handler = (MessageReceivedHandler)Delegate.Remove (received_handler, value);
+				if (received_handler == null)
+					InternalMessageReceived -= MessageReceivedWrapper;
+			}
+		}
+
+		[GLib.ConnectBefore]
+		void MessageReceivedWrapper (object sender, MessageReceivedArgs e)
+		{
+			MessageReceivedHandler eh = received_handler;
+			if (eh == null)
+				return;
+			foreach (MessageReceivedHandler d in eh.GetInvocationList ()) {
+				if (e.RetVal != null && (Response)e.RetVal != Response.Passthrough)
+					break;
+				d (sender, e);
+			}
+		}
+
+
diff --git a/lib/unique-sharp/unique/AssemblyInfo.cs b/lib/unique-sharp/unique/AssemblyInfo.cs
new file mode 100644
index 0000000..68bf32a
--- /dev/null
+++ b/lib/unique-sharp/unique/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly:AssemblyVersion("1.0.0.0")]
+[assembly:AssemblyDelaySign(false)]
+[assembly:AssemblyKeyFile("unique-sharp.snk")]
+[assembly:GLib.IgnoreClassInitializers]
diff --git a/lib/unique-sharp/unique/Makefile.am b/lib/unique-sharp/unique/Makefile.am
new file mode 100644
index 0000000..ac9b104
--- /dev/null
+++ b/lib/unique-sharp/unique/Makefile.am
@@ -0,0 +1,62 @@
+include $(top_srcdir)/Makefile.include
+
+UNSAFE = -unsafe
+DEBUG = -debug
+
+SRCS =								\
+	$(srcdir)/AssemblyInfo.cs				\
+	$(srcdir)/MessageReceivedHandler.cs
+
+CUSTOMS =							\
+	$(srcdir)/App.custom					\
+	$(srcdir)/MessageData.custom	
+
+SNK = 	$(srcdir)/snk
+
+ASSEMBLIES =					\
+	-pkg:glib-sharp-2.0
+
+all: unique-sharp.dll
+
+unique-api.xml: $(srcdir)/unique-api.raw $(srcdir)/Unique.metadata
+	@echo -e "\n*** Massaging the raw api into $@"
+	cp $(srcdir)/unique-api.raw unique-api.xml
+	chmod +w unique-api.xml
+	$(GAPI2FIXUP) --api=unique-api.xml --metadata=$(srcdir)/Unique.metadata
+
+$(top_builddir)/unique-sharp/generator/gapi_codegen.exe:
+	$(MAKE) -C $(top_builddir)/lib/unique-sharp/generator
+
+generated/File.cs: unique-api.xml $(CUSTOMS) $(top_builddir)/unique-sharp/generator/gapi_codegen.exe
+	@echo -e "\n*** Generating C# code"
+	$(MONO) $(top_builddir)/lib/unique-sharp/generator/gapi_codegen.exe $(GLIBSHARP_CFLAGS) --outdir=generated --customdir=$(srcdir) --generate unique-api.xml
+
+unique-sharp.snk: $(SNK)
+	cp $< $@
+
+unique-sharp.dll: generated/File.cs $(SRCS) gtk-sharp.snk
+	@echo -e "\n*** Building $@"
+	$(CSC) -target:library -out:$@ $(UNSAFE) $(DEBUG) $(ASSEMBLIES) $(SRCS) generated/*.cs
+
+assemblydir = $(pkglibdir)
+assembly_DATA =			\
+	unique-sharp.dll	\
+	unique-sharp.dll.config
+
+
+CLEANFILES = 			\
+	unique-sharp.dll 	\
+	unique-sharp.dll.mdb \
+	unique-api.xml
+
+DISTCLEANFILES =		\
+	generated/*.cs		\
+	gtk-sharp.snk
+
+EXTRA_DIST =			\
+	$(SRCS)			\
+	$(CUSTOMS)		\
+	Unique.metadata		\
+	$(SNK)			\
+	unique-sharp.dll.config	\
+	unique-api.raw
diff --git a/lib/unique-sharp/unique/MessageData.custom b/lib/unique-sharp/unique/MessageData.custom
new file mode 100644
index 0000000..55939cf
--- /dev/null
+++ b/lib/unique-sharp/unique/MessageData.custom
@@ -0,0 +1,54 @@
+//
+// MessageData.custom
+//
+// Author(s):
+//	Stephane Delcroix  <stephane delcroix org>
+//
+// Copyright (c) 2009 Stephane Delcroix
+//
+// This is open source software.
+//
+
+		public object Clone ()
+		{
+			return (object)Copy ();
+		}
+		
+		[DllImport("libunique-1.0-0.dll")]
+		static extern bool unique_message_data_set_text(IntPtr raw, IntPtr str, IntPtr length);
+
+		[DllImport("libunique-1.0-0.dll")]
+		static extern IntPtr unique_message_data_get_text(IntPtr raw);
+
+		public string Text {
+			set {
+				IntPtr native_str = GLib.Marshaller.StringToPtrGStrdup (value);
+				bool raw_ret = unique_message_data_set_text(Handle, native_str, new IntPtr ((long) System.Text.Encoding.UTF8.GetByteCount (value)));
+				bool ret = raw_ret;
+				GLib.Marshaller.Free (native_str);
+				if (!ret)
+					throw new Exception ("Failed to convert the text to UTF-8");
+			}
+			get {
+				IntPtr raw_ret = unique_message_data_get_text(Handle);
+				string ret = GLib.Marshaller.PtrToStringGFree(raw_ret);
+				return ret;
+			}
+		}
+
+		[DllImport("libunique-1.0-0.dll")]
+		static extern byte[] unique_message_data_get(IntPtr raw, out UIntPtr length);
+
+		[DllImport("libunique-1.0-0.dll")]
+		static extern void unique_message_data_set(IntPtr raw, byte[] data, UIntPtr n_data);
+
+		public byte[] Data { 
+			set { unique_message_data_set(Handle, value, new UIntPtr ((ulong) (value == null ? -1 : value.Length))); }
+			get {
+				UIntPtr native_length;
+				return unique_message_data_get(Handle, out native_length);
+			}
+		}
+
+
+
diff --git a/lib/unique-sharp/unique/MessageReceivedHandler.cs b/lib/unique-sharp/unique/MessageReceivedHandler.cs
new file mode 100644
index 0000000..4bac8a9
--- /dev/null
+++ b/lib/unique-sharp/unique/MessageReceivedHandler.cs
@@ -0,0 +1,37 @@
+// MessageReceivedHandler.cs
+//
+// Author(s):
+//	Stephane Delcroix  <stephane delcroix org>
+//
+// Copyright (c) 2009 Stephane Delcroix
+//
+// This is open source software. See COPYING for details.
+//
+
+namespace Unique {
+
+	using System;
+
+	public delegate void MessageReceivedHandler(object o, MessageReceivedArgs args);
+
+	public class MessageReceivedArgs : GLib.SignalArgs {
+		public int Command{
+			get {
+				return (int) Args[0];
+			}
+		}
+
+		public Unique.MessageData MessageData{
+			get {
+				return (Unique.MessageData) Args[1];
+			}
+		}
+
+		public uint Time{
+			get {
+				return (uint) Args[2];
+			}
+		}
+
+	}
+}
diff --git a/lib/unique-sharp/unique/Unique.metadata b/lib/unique-sharp/unique/Unique.metadata
new file mode 100644
index 0000000..5cce804
--- /dev/null
+++ b/lib/unique-sharp/unique/Unique.metadata
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<metadata>
+  <attr path="/api/namespace/object[ cname='UniqueApp']/constructor[ cname='unique_app_new_with_commands']" name="hidden">1</attr>
+  <attr path="/api/namespace/object[ cname='UniqueApp']/method[ cname='unique_app_is_running']" name="name">GetIsRunning</attr>
+  <attr path="/api/namespace/object[ cname='UniqueApp']/method[ cname='unique_app_send_message']/parameters/parameter[ name='command_id']" name="type">UniqueCommand</attr>
+  <attr path="/api/namespace/object[ cname='UniqueApp']/signal[ cname='message-received']" name="hidden">1</attr>
+
+  <add-node path="/api/namespace/boxed[ cname='UniqueMessageData']"><implements><interface name="ICloneable" /></implements></add-node>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_copy']" name="accessibility">private</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_get_text']" name="hidden">1</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_set_text']" name="hidden">1</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_get']" name="hidden">1</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_set']" name="hidden">1</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_set_uris']/*/*[ name='uris']" name="null_term_array">1</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_set_uris']/return-type" name="type">void</attr>
+  <attr path="/api/namespace/boxed[ cname='UniqueMessageData']/method[ cname='unique_message_data_get_uris']/return-type"  name="null_term_array">1</attr>
+</metadata>
+
diff --git a/lib/unique-sharp/unique/snk b/lib/unique-sharp/unique/snk
new file mode 100644
index 0000000..a651450
Binary files /dev/null and b/lib/unique-sharp/unique/snk differ
diff --git a/lib/unique-sharp/unique/unique-api.raw b/lib/unique-sharp/unique/unique-api.raw
new file mode 100644
index 0000000..8072a4f
--- /dev/null
+++ b/lib/unique-sharp/unique/unique-api.raw
@@ -0,0 +1,143 @@
+<?xml version="1.0"?>
+<api>
+  <!--
+
+        This file was automatically generated.
+        Please DO NOT MODIFY THIS FILE, modify .metadata files instead.
+
+-->
+  <namespace name="Unique" library="libunique-1.0-0.dll">
+    <enum name="Command" cname="UniqueCommand" gtype="unique_command_get_type" type="enum">
+      <member cname="UNIQUE_INVALID" name="Invalid" />
+      <member cname="UNIQUE_ACTIVATE" name="Activate" value="-1" />
+      <member cname="UNIQUE_NEW" name="New" value="-2" />
+      <member cname="UNIQUE_OPEN" name="Open" value="-3" />
+      <member cname="UNIQUE_CLOSE" name="Close" value="-4" />
+    </enum>
+    <enum name="Response" cname="UniqueResponse" gtype="unique_response_get_type" type="enum">
+      <member cname="UNIQUE_RESPONSE_INVALID" name="Invalid" />
+      <member cname="UNIQUE_RESPONSE_OK" name="Ok" />
+      <member cname="UNIQUE_RESPONSE_CANCEL" name="Cancel" />
+      <member cname="UNIQUE_RESPONSE_FAIL" name="Fail" />
+      <member cname="UNIQUE_RESPONSE_PASSTHROUGH" name="Passthrough" />
+    </enum>
+    <object name="App" cname="UniqueApp" parent="GObject">
+      <field name="Priv" cname="priv" type="UniqueAppPrivate*" />
+      <property name="Name" cname="name" type="gchar*" readable="true" writeable="true" construct-only="true" />
+      <property name="StartupId" cname="startup-id" type="gchar*" readable="true" writeable="true" construct-only="true" />
+      <property name="Screen" cname="screen" type="GdkScreen" readable="true" writeable="true" construct="true" />
+      <property name="IsRunning" cname="is-running" type="gboolean" readable="true" />
+      <signal name="MessageReceived" cname="message-received" when="LAST" field_name="message_received">
+        <return-type type="UniqueResponse" />
+        <parameters>
+          <parameter type="UniqueApp*" name="app" />
+          <parameter type="gint" name="command" />
+          <parameter type="UniqueMessageData*" name="message_data" />
+          <parameter type="guint" name="time_" />
+        </parameters>
+      </signal>
+      <method name="AddCommand" cname="unique_app_add_command">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="const-gchar*" name="command_name" />
+          <parameter type="gint" name="command_id" />
+        </parameters>
+      </method>
+      <method name="GetType" cname="unique_app_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="IsRunning" cname="unique_app_is_running">
+        <return-type type="gboolean" />
+      </method>
+      <constructor cname="unique_app_new">
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+          <parameter type="const-gchar*" name="startup_id" />
+        </parameters>
+      </constructor>
+      <constructor cname="unique_app_new_with_commands">
+        <parameters>
+          <parameter type="const-gchar*" name="name" />
+          <parameter type="const-gchar*" name="startup_id" />
+          <parameter type="const-gchar*" name="first_command_name" />
+          <parameter ellipsis="true" />
+        </parameters>
+      </constructor>
+      <method name="SendMessage" cname="unique_app_send_message">
+        <return-type type="UniqueResponse" />
+        <parameters>
+          <parameter type="gint" name="command_id" />
+          <parameter type="UniqueMessageData*" name="message_data" />
+        </parameters>
+      </method>
+      <method name="WatchWindow" cname="unique_app_watch_window">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="GtkWindow*" name="window" />
+        </parameters>
+      </method>
+    </object>
+    <boxed name="MessageData" cname="UniqueMessageData" opaque="true">
+      <method name="Copy" cname="unique_message_data_copy">
+        <return-type type="UniqueMessageData*" owned="true" />
+      </method>
+      <method name="Free" cname="unique_message_data_free">
+        <return-type type="void" />
+      </method>
+      <method name="Get" cname="unique_message_data_get">
+        <return-type type="const-guchar*" />
+        <parameters>
+          <parameter type="gsize*" name="length" />
+        </parameters>
+      </method>
+      <method name="GetFilename" cname="unique_message_data_get_filename">
+        <return-type type="gchar*" />
+      </method>
+      <method name="GetScreen" cname="unique_message_data_get_screen">
+        <return-type type="GdkScreen*" />
+      </method>
+      <method name="GetStartupId" cname="unique_message_data_get_startup_id">
+        <return-type type="const-gchar*" />
+      </method>
+      <method name="GetText" cname="unique_message_data_get_text">
+        <return-type type="gchar*" />
+      </method>
+      <method name="GetType" cname="unique_message_data_get_type" shared="true">
+        <return-type type="GType" />
+      </method>
+      <method name="GetUris" cname="unique_message_data_get_uris">
+        <return-type type="gchar**" />
+      </method>
+      <method name="GetWorkspace" cname="unique_message_data_get_workspace">
+        <return-type type="guint" />
+      </method>
+      <constructor cname="unique_message_data_new" />
+      <method name="Set" cname="unique_message_data_set">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="const-guchar*" name="data" />
+          <parameter type="gsize" name="length" />
+        </parameters>
+      </method>
+      <method name="SetFilename" cname="unique_message_data_set_filename">
+        <return-type type="void" />
+        <parameters>
+          <parameter type="const-gchar*" name="filename" />
+        </parameters>
+      </method>
+      <method name="SetText" cname="unique_message_data_set_text">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="const-gchar*" name="str" />
+          <parameter type="gssize" name="length" />
+        </parameters>
+      </method>
+      <method name="SetUris" cname="unique_message_data_set_uris">
+        <return-type type="gboolean" />
+        <parameters>
+          <parameter type="gchar**" name="uris" />
+        </parameters>
+      </method>
+    </boxed>
+  </namespace>
+</api>
\ No newline at end of file
diff --git a/lib/unique-sharp/unique/unique-sharp.dll.config b/lib/unique-sharp/unique/unique-sharp.dll.config
new file mode 100644
index 0000000..02e103f
--- /dev/null
+++ b/lib/unique-sharp/unique/unique-sharp.dll.config
@@ -0,0 +1,4 @@
+<configuration>
+  <dllmap dll="libunique-1.0-0.dll" target="libunique-1.0.so.0"/>
+</configuration>
+
diff --git a/src/.gitignore b/src/.gitignore
index c227bc5..f4fcdfe 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -24,3 +24,5 @@
 /f-spot.exe
 /f-spot.exe.config
 /f-spot.exe.mdb
+/xdb.*
+/photos-*.db
diff --git a/src/Core/App.cs b/src/Core/App.cs
new file mode 100644
index 0000000..3391502
--- /dev/null
+++ b/src/Core/App.cs
@@ -0,0 +1,340 @@
+/*
+ * FSpot.Application.cs
+ *
+ * Author(s):
+ *	Stephane Delcroix  <stephane delcroix org>
+ *
+ * Copyright (c) 2009 Stephane Delcroix.
+ *
+ * This is open source software. See COPYING fro details.
+ */
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+
+using Unique;
+
+using Mono.Posix;
+
+using FSpot.Utils;
+
+namespace FSpot
+{
+	public class App : Unique.App
+	{
+#region public API
+		static App app;
+		public static App Instance {
+			get {
+				if (app == null)
+					app = new App ();
+				return app;
+			}
+		}
+
+		public MainWindow Organizer {
+			get {
+				if (organizer == null) {
+					organizer = new MainWindow (Database);
+					Register (organizer.Window);
+				}
+				return organizer;
+			}
+		}
+
+		public Db Database {
+			get {
+				if (db == null) {
+					if (!File.Exists (FSpot.Global.BaseDirectory))
+						Directory.CreateDirectory (FSpot.Global.BaseDirectory);
+
+					db = new Db ();
+
+					try {
+						db.Init (Path.Combine (FSpot.Global.BaseDirectory, "photos.db"), true);
+					} catch (Exception e) {
+						new FSpot.UI.Dialog.RepairDbDialog (e, db.Repair (), null);
+						db.Init (Path.Combine (FSpot.Global.BaseDirectory, "photos.db"), true);
+					}
+				}
+				return db;
+			}
+		}
+
+		public void Import (string path)
+		{
+			if (IsRunning) {
+				var md = new MessageData ();
+				md.Text = path;
+				SendMessage (Command.Import, md);
+				return;
+			}
+			HandleImport (path);
+		}
+
+		public void Organize ()
+		{
+			if (IsRunning) {
+				SendMessage (Command.Organize, null);
+				return;
+			}
+			HandleOrganize ();
+		}
+
+		public void Shutdown ()
+		{
+			if (IsRunning) {
+				SendMessage (Command.Shutdown, null);
+				return;
+			}
+			HandleShutdown ();
+		}
+
+		public void Slideshow (string tagname)
+		{
+			if (IsRunning) {
+				var md = new MessageData ();
+				md.Text = tagname ?? String.Empty;
+				SendMessage (Command.Slideshow, md);
+
+				return;
+			}
+			HandleSlideshow (tagname);
+		}
+
+		public void View (string uri)
+		{
+			View (new string[] {uri});
+		}
+
+		public void View (string[] uris)
+		{
+			if (IsRunning) {
+				var md = new MessageData ();
+				md.Uris = uris;
+				SendMessage (Command.View, md);
+				return;
+			}
+			HandleView (uris);
+		}
+#endregion
+
+#region private ctor and stuffs
+		enum Command {
+			Invalid,
+			Import,
+			View,
+			Organize,
+			Shutdown,
+			Version,
+			Slideshow,
+		}
+
+		List<Gtk.Window> toplevels;
+		MainWindow organizer;
+		Db db;
+
+		App (): base ("org.gnome.FSpot.Core", null,
+				  "Invalid", Command.Invalid,
+				  "Import", Command.Import,
+				  "View", Command.View,
+				  "Organize", Command.Organize,
+				  "Shutdown", Command.Shutdown,
+				  "Slideshow", Command.Slideshow)
+		{
+			toplevels = new List<Gtk.Window> ();
+			if (IsRunning) {
+				Log.Information ("Found active FSpot process");
+			} else {
+				MessageReceived += HandleMessageReceived;
+			}
+		}
+
+		void SendMessage (Command command, MessageData md)
+		{
+			SendMessage ((Unique.Command)command, md);
+		}
+#endregion
+
+#region Command Handlers
+		void HandleMessageReceived (object sender, MessageReceivedArgs e)
+		{
+			switch ((Command)e.Command) {
+			case Command.Import:
+				HandleImport (e.MessageData.Text);
+				e.RetVal = Response.Ok;
+				break;
+			case Command.Organize:
+				HandleOrganize ();
+				e.RetVal = Response.Ok;
+				break;
+			case Command.Shutdown:
+				HandleShutdown ();
+				e.RetVal = Response.Ok;
+				break;
+			case Command.Slideshow:
+				HandleSlideshow (e.MessageData.Text);
+				e.RetVal = Response.Ok;
+				break;
+			case Command.View:
+				HandleView (e.MessageData.Uris);
+				e.RetVal = Response.Ok;
+				break;
+			case Command.Invalid:
+			default:
+				Log.Debug ("Wrong command received");
+				break;
+			}
+		}
+
+		void HandleImport (string path)
+		{
+			Organizer.Window.Present ();
+			if (path != null && path.StartsWith ("gphoto2:"))
+				Organizer.ImportCamera (path);
+			else if (path != null && path.StartsWith ("file:"))
+				Organizer.ImportFile (Uri.UnescapeDataString ((new Uri(path)).AbsolutePath));
+			else
+				Organizer.ImportFile (path);
+		}
+
+		void HandleOrganize ()
+		{
+			if (Database.Empty)
+				HandleImport (null);
+			else
+				Organizer.Window.Present ();
+		}
+
+		void HandleShutdown ()
+		{
+			try {
+				MainWindow.Toplevel.Close ();
+			} catch {
+				System.Environment.Exit (0);
+			}
+		}
+
+		//FIXME move all this in a standalone class
+		void HandleSlideshow (string tagname)
+		{
+			Tag tag;
+			SlideView slideview = null;
+
+			if (!String.IsNullOrEmpty (tagname))
+				tag = Database.Tags.GetTagByName (tagname);
+			else
+				tag = Database.Tags.GetTagById (Preferences.Get<int> (Preferences.SCREENSAVER_TAG));
+
+			Photo[] photos;
+			if (tag != null)
+				photos = Database.Photos.Query (new Tag[] {tag});
+			else if (Preferences.Get<int> (Preferences.SCREENSAVER_TAG) == 0)
+				photos = Database.Photos.Query (new Tag [] {});
+			else
+				photos = new Photo [0];
+
+			var delay = Math.Max (1.0, Preferences.Get<double> (Preferences.APP_FSPOT + "screensaver/delay"));
+			var window = new XScreenSaverSlide ();
+			window.ModifyFg (Gtk.StateType.Normal, new Gdk.Color (127, 127, 127));
+			window.ModifyBg (Gtk.StateType.Normal, new Gdk.Color (0, 0, 0));
+
+			if (photos.Length > 0) {
+				Array.Sort (photos, new Photo.RandomSort ());
+				Gdk.Pixbuf black = new Gdk.Pixbuf (Gdk.Colorspace.Rgb, false, 8, 1, 1);
+				black.Fill (0x00000000);
+				slideview = new SlideView (black, photos, delay);
+				window.Add (slideview);
+			} else {
+				Gtk.HBox outer = new Gtk.HBox ();
+				Gtk.HBox hbox = new Gtk.HBox ();
+				Gtk.VBox vbox = new Gtk.VBox ();
+
+				outer.PackStart (new Gtk.Label (String.Empty));
+				outer.PackStart (vbox, false, false, 0);
+				vbox.PackStart (new Gtk.Label (String.Empty));
+				vbox.PackStart (hbox, false, false, 0);
+				hbox.PackStart (new Gtk.Image (Gtk.Stock.DialogWarning, Gtk.IconSize.Dialog),
+						false, false, 0);
+				outer.PackStart (new Gtk.Label (String.Empty));
+
+				string msg;
+				string long_msg;
+
+				if (tag != null) {
+					msg = String.Format (Catalog.GetString ("No photos matching {0} found"), tag.Name);
+					long_msg = String.Format (Catalog.GetString ("The tag \"{0}\" is not applied to any photos. Try adding\n" +
+										     "the tag to some photos or selecting a different tag in the\n" +
+										     "F-Spot preference dialog."), tag.Name);
+				} else {
+					msg = Catalog.GetString ("Search returned no results");
+					long_msg = Catalog.GetString ("The tag F-Spot is looking for does not exist. Try\n" + 
+								      "selecting a different tag in the F-Spot preference\n" + 
+								      "dialog.");
+				}
+
+				Gtk.Label label = new Gtk.Label (msg);
+				hbox.PackStart (label, false, false, 0);
+
+				Gtk.Label long_label = new Gtk.Label (long_msg);
+				long_label.Markup  = String.Format ("<small>{0}</small>", long_msg);
+
+				vbox.PackStart (long_label, false, false, 0);
+				vbox.PackStart (new Gtk.Label (String.Empty));
+
+				window.Add (outer);
+				label.ModifyFg (Gtk.StateType.Normal, new Gdk.Color (127, 127, 127));
+				label.ModifyBg (Gtk.StateType.Normal, new Gdk.Color (0, 0, 0));
+				long_label.ModifyFg (Gtk.StateType.Normal, new Gdk.Color (127, 127, 127));
+				long_label.ModifyBg (Gtk.StateType.Normal, new Gdk.Color (0, 0, 0));
+			}
+			window.ShowAll ();
+
+			Register (window);
+			GLib.Idle.Add (delegate {
+				if (slideview != null)
+					slideview.Play ();
+				return false;
+			});
+		}
+
+		void HandleView (string[] uris)
+		{
+			List<Uri> ul = new List<Uri> ();
+			foreach (var u in uris)
+				ul.Add (new Uri (u));
+			try {
+				Register (new FSpot.SingleView (ul.ToArray ()).Window);
+			} catch (System.Exception e) {
+				System.Console.WriteLine (e.ToString ());
+				System.Console.WriteLine ("no real valid path to view from");
+			} 
+		}
+
+#endregion
+
+#region Track toplevel windows
+		void Register (Gtk.Window window)
+		{
+			toplevels.Add (window);
+			window.Destroyed += HandleDestroyed;
+		}
+
+		void HandleDestroyed (object sender, EventArgs e)
+		{
+			toplevels.Remove (sender as Gtk.Window);
+			if (toplevels.Count == 0) {
+				Log.Information ("Exiting...");
+				Banshee.Kernel.Scheduler.Dispose ();
+				Database.Dispose ();
+				ImageLoaderThread.Cleanup ();
+				Gtk.Application.Quit ();
+				System.Environment.Exit (0);
+			}
+			if (organizer != null && organizer.Window == sender)
+				organizer = null;
+		}
+#endregion
+	}
+}
diff --git a/src/Editors/Editor.cs b/src/Editors/Editor.cs
index 9542419..ef5a4db 100644
--- a/src/Editors/Editor.cs
+++ b/src/Editors/Editor.cs
@@ -154,7 +154,7 @@ namespace FSpot.Editors {
 				bool create_version = photo.DefaultVersion.IsProtected;
 				photo.SaveVersion (edited, create_version);
 				photo.Changes.DataChanged = true;
-				Core.Database.Photos.Commit (photo);
+				App.Instance.Database.Photos.Commit (photo);
 
 				done++;
 				if (ProcessingStep != null) {
diff --git a/src/FSpot.addin.xml b/src/FSpot.addin.xml
index e75b561..053c7bf 100644
--- a/src/FSpot.addin.xml
+++ b/src/FSpot.addin.xml
@@ -1,7 +1,7 @@
 <Addin namespace = "FSpot" 
        id = "Core" 
-       version = "0.6.1.5"
-       compatVersion = "0.6"
+       version = "0.7.0.0"
+       compatVersion = "0.7"
        isroot="true">
 
 	<Runtime>
diff --git a/src/FileImportBackend.cs b/src/FileImportBackend.cs
index 8588b28..a83e7b4 100644
--- a/src/FileImportBackend.cs
+++ b/src/FileImportBackend.cs
@@ -18,8 +18,8 @@ public class ImportException : System.Exception {
 
 public class FileImportBackend : ImportBackend {
 	PhotoStore store;
- 	RollStore rolls = FSpot.Core.Database.Rolls;
-	TagStore tag_store = FSpot.Core.Database.Tags;
+	RollStore rolls = FSpot.App.Instance.Database.Rolls;
+	TagStore tag_store = FSpot.App.Instance.Database.Tags;
 	bool recurse;
 	bool copy;
 	bool detect_duplicates;
diff --git a/src/Jobs/CalculateHashJob.cs b/src/Jobs/CalculateHashJob.cs
index 46cbe11..4c93505 100644
--- a/src/Jobs/CalculateHashJob.cs
+++ b/src/Jobs/CalculateHashJob.cs
@@ -38,8 +38,8 @@ namespace FSpot.Jobs {
 			Log.Debug ("Calculating Hash {0}...", photo_id);
 
 			try {
-			 	Photo photo = FSpot.Core.Database.Photos.Get (Convert.ToUInt32 (photo_id)) as Photo;
-				FSpot.Core.Database.Photos.UpdateMD5Sum (photo);
+				Photo photo = FSpot.App.Instance.Database.Photos.Get (Convert.ToUInt32 (photo_id)) as Photo;
+				FSpot.App.Instance.Database.Photos.UpdateMD5Sum (photo);
 				return true;
 			} catch (System.Exception e) {
 			 	Log.Debug ("Error Calculating Hash for photo {0}: {1}", JobOptions, e.Message);
diff --git a/src/Jobs/SyncMetadataJob.cs b/src/Jobs/SyncMetadataJob.cs
index 5edffa5..76825b0 100644
--- a/src/Jobs/SyncMetadataJob.cs
+++ b/src/Jobs/SyncMetadataJob.cs
@@ -34,7 +34,7 @@ namespace FSpot.Jobs {
 			System.Threading.Thread.Sleep (500);
 			Console.WriteLine ("Syncing metadata to file...");
 			try {
-				Photo photo = FSpot.Core.Database.Photos.Get (Convert.ToUInt32 (JobOptions)) as Photo;
+				Photo photo = FSpot.App.Instance.Database.Photos.Get (Convert.ToUInt32 (JobOptions)) as Photo;
 				WriteMetadataToImage (photo);
 				return true;
 			} catch (System.Exception e) {
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index 640abe4..5e7c1fb 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -228,6 +228,46 @@ namespace FSpot
 		//
 		public MainWindow (Db db)
 		{
+			foreach (ServiceNode service in AddinManager.GetExtensionNodes ("/FSpot/Services")) {
+				try {
+					service.Initialize ();
+					service.Start ();
+				} catch (Exception e) {
+					Log.Warning ("Something went wrong while starting the {0} extension.", service.Id);
+					Log.DebugException (e);
+				}
+			}
+		
+#if GSD_2_24
+			Log.Information ("Hack for gnome-settings-daemon engaged");
+			int max_age, max_size;
+			if (Preferences.TryGet<int> (Preferences.GSD_THUMBS_MAX_AGE, out max_age)) {
+				if (max_age < 0)
+					Log.Debug ("maximum_age check already disabled, good");
+				else if (max_age == 0)
+					Log.Warning ("maximum_age is 0 (tin-hat mode), not overriding");
+				else if (max_age < 180) {
+					Log.Debug ("Setting maximum_age to a saner value");
+					Preferences.Set (Preferences.GSD_THUMBS_MAX_AGE, 180);
+				}
+			}
+
+			if (Preferences.TryGet<int> (Preferences.GSD_THUMBS_MAX_SIZE, out max_size)) {
+				int count = App.Instance.Database.Photos.Count ("photos");
+				// average thumbs are taking 70K, so this will push the threshold
+				//if f-spot takes more than 70% of the thumbs space
+				int size = count / 10;
+				if (max_size < 0)
+					Log.Debug ("maximum_size check already disabled, good");
+				else if (max_size == 0)
+					Log.Warning ("maximum_size is 0 (tin-hat mode), not overriding");
+				else if (max_size < size) {
+					Log.Debug ("Setting maximum_size to a saner value ({0}MB), according to your db size", size);
+					Preferences.Set (Preferences.GSD_THUMBS_MAX_SIZE, size);
+				}
+			}
+
+#endif
 			Database = db;
 	
 			if (Toplevel == null)
@@ -1447,11 +1487,6 @@ namespace FSpot
 		// Main menu commands
 		//
 	
-		void HandleOpenCommand (object sender, EventArgs e)
-		{
-			new FSpot.SingleView ();
-		}
-	
 		void HandleImportCommand (object sender, EventArgs e)
 		{
 			Database.Sync = false;
diff --git a/src/Makefile.am b/src/Makefile.am
index 4badc83..c107224 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -130,7 +130,7 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/ColorAdjustment/FullColorAdjustment.cs		\
 	$(srcdir)/ColorAdjustment/SepiaTone.cs		\
 	$(srcdir)/ControlOverlay.cs		\
-	$(srcdir)/Core.cs			\
+	$(srcdir)/Core/App.cs			\
 	$(srcdir)/Core/ColorManagement.cs	\
 	$(srcdir)/Core/Photo.cs			\
 	$(srcdir)/Core/PhotoVersion.cs		\
@@ -385,6 +385,7 @@ F_SPOT_ASSEMBLIES = 				\
 	$(LINK_SEMWEB)				\
 	$(LINK_GTKSHARPBEANS)			\
 	$(LINK_GIOSHARP)			\
+	$(LINK_UNIQUESHARP)			\
 	-r:System.Data				\
 	-r:System.Web				\
 	-r:Mono.Data.SqliteClient		\
diff --git a/src/PhotoStore.cs b/src/PhotoStore.cs
index f5b4210..690b018 100644
--- a/src/PhotoStore.cs
+++ b/src/PhotoStore.cs
@@ -229,7 +229,7 @@ public class PhotoStore : DbStore<Photo> {
 
 		while (reader.Read ()) {
 			uint tag_id = Convert.ToUInt32 (reader ["tag_id"]);
-			Tag tag = Core.Database.Tags.Get (tag_id) as Tag;
+			Tag tag = App.Instance.Database.Tags.Get (tag_id) as Tag;
 			photo.AddTagUnsafely (tag);
 		}
 		reader.Close();
@@ -291,7 +291,7 @@ public class PhotoStore : DbStore<Photo> {
 
 		        if (reader [1] != null) {
 				uint tag_id = Convert.ToUInt32 (reader ["tag_id"]);
-				Tag tag = Core.Database.Tags.Get (tag_id) as Tag;
+				Tag tag = App.Instance.Database.Tags.Get (tag_id) as Tag;
 				photo.AddTagUnsafely (tag);
 			}
 		}
@@ -443,7 +443,7 @@ public class PhotoStore : DbStore<Photo> {
 		Commit (photos);
 
 		foreach (Tag tag in tags)
-			Core.Database.Tags.Remove (tag);
+			App.Instance.Database.Tags.Remove (tag);
 		
 	}
 
@@ -1015,9 +1015,9 @@ public class PhotoStore : DbStore<Photo> {
 			where_clauses.Add (importidrange.SqlClause ());
 		}		
 		
-		if (hide && Core.Database.Tags.Hidden != null) {
+		if (hide && App.Instance.Database.Tags.Hidden != null) {
 			where_clauses.Add (String.Format ("id NOT IN (SELECT photo_id FROM photo_tags WHERE tag_id = {0})", 
-							  FSpot.Core.Database.Tags.Hidden.Id));
+							  App.Instance.Database.Tags.Hidden.Id));
 		}
 		
 		if (searchexpression != null) {
diff --git a/src/Query/HiddenTag.cs b/src/Query/HiddenTag.cs
index 901417b..0990b47 100644
--- a/src/Query/HiddenTag.cs
+++ b/src/Query/HiddenTag.cs
@@ -50,7 +50,7 @@ namespace FSpot.Query
 		
 		public string SqlClause ()
 		{
-			Tag hidden = Core.Database.Tags.Hidden;
+			Tag hidden = App.Instance.Database.Tags.Hidden;
 			
 			if ( ! show_hidden && hidden != null)
 				return String.Format (" photos.id NOT IN (SELECT photo_id FROM photo_tags WHERE tag_id = {0}) ",
diff --git a/src/Sharpener.cs b/src/Sharpener.cs
index fe978dd..d38b435 100644
--- a/src/Sharpener.cs
+++ b/src/Sharpener.cs
@@ -67,7 +67,7 @@ namespace FSpot.Widgets {
 
 				photo.SaveVersion (final, create_version);
 				photo.Changes.DataChanged = true;
-				Core.Database.Photos.Commit (photo);
+				App.Instance.Database.Photos.Commit (photo);
 			} catch (System.Exception e) {
 				string msg = Catalog.GetString ("Error saving sharpened photo");
 				string desc = String.Format (Catalog.GetString ("Received exception \"{0}\". Unable to save photo {1}"),
diff --git a/src/SingleView.cs b/src/SingleView.cs
index 0f0a6db..70d1c60 100644
--- a/src/SingleView.cs
+++ b/src/SingleView.cs
@@ -1,6 +1,8 @@
 using Gtk;
 using Gdk;
 using System;
+using System.Collections.Generic;
+
 using Mono.Addins;
 using Mono.Unix;
 
@@ -51,21 +53,6 @@ namespace FSpot {
 
 		private static Gtk.Tooltips toolTips = new Gtk.Tooltips ();
 
-		public SingleView () : this (FSpot.Global.HomeDirectory) {}
-
-
-		public SingleView (string path) : this (UriUtils.PathToFileUri (path)) 
-		{
-		}
-
-		public SingleView (Uri uri) : this (new Uri [] { uri })
-		{
-		}
-
-		public SingleView (UriList list) : this (list.ToArray ())
-		{
-		}
-
 		public SingleView (Uri [] uris) 
 		{
 			string glade_name = "single_view";
@@ -331,7 +318,7 @@ namespace FSpot {
 		private void HandleNewWindow (object sender, System.EventArgs args)
 		{
 			/* FIXME this needs to register witth the core */
-			new SingleView (uri);
+			new SingleView (new Uri[] {uri});
 		}
 
 		private void HandlePreferences (object sender, System.EventArgs args)
@@ -529,9 +516,12 @@ namespace FSpot {
 			int response = file_selector.Run ();
 			
 			if ((Gtk.ResponseType) response == Gtk.ResponseType.Ok) {
-				open = file_selector.Filename;
-				new FSpot.SingleView (open);
+				var l = new List<Uri> ();
+				foreach (var s in file_selector.Uris)
+					l.Add (new Uri (s));
+				new FSpot.SingleView (l.ToArray ());
 			}
+
 			
 			file_selector.Destroy ();
 		}
diff --git a/src/TagStore.cs b/src/TagStore.cs
index ab0ecd3..3adb4c1 100644
--- a/src/TagStore.cs
+++ b/src/TagStore.cs
@@ -180,8 +180,8 @@ public class TagStore : DbStore<Tag> {
 		}
 		reader.Close ();
 
-		if (FSpot.Core.Database.Meta.HiddenTagId.Value != null)
-			hidden = LookupInCache ((uint) FSpot.Core.Database.Meta.HiddenTagId.ValueAsInt) as Tag;
+		if (FSpot.App.Instance.Database.Meta.HiddenTagId.Value != null)
+			hidden = LookupInCache ((uint) FSpot.App.Instance.Database.Meta.HiddenTagId.ValueAsInt) as Tag;
 	}
 
 
@@ -210,8 +210,8 @@ public class TagStore : DbStore<Tag> {
 		hidden_tag.SortPriority = -9;
 		this.hidden = hidden_tag;
 		Commit (hidden_tag);
-		FSpot.Core.Database.Meta.HiddenTagId.ValueAsInt = (int) hidden_tag.Id;
-		FSpot.Core.Database.Meta.Commit (FSpot.Core.Database.Meta.HiddenTagId);
+		FSpot.App.Instance.Database.Meta.HiddenTagId.ValueAsInt = (int) hidden_tag.Id;
+		FSpot.App.Instance.Database.Meta.Commit (FSpot.App.Instance.Database.Meta.HiddenTagId);
 
 		Tag people_category = CreateCategory (RootCategory, Catalog.GetString ("People"), false);
 		people_category.ThemeIconName = "emblem-people";
@@ -364,10 +364,10 @@ public class TagStore : DbStore<Tag> {
 							  "id", tag.Id));
 			
 			if (update_xmp && Preferences.Get<bool> (Preferences.METADATA_EMBED_IN_IMAGE)) {
-				Photo [] photos = Core.Database.Photos.Query (new Tag [] { tag });
+				Photo [] photos = App.Instance.Database.Photos.Query (new Tag [] { tag });
 				foreach (Photo p in photos)
 					if (p.HasTag (tag)) // the query returns all the pics of the tag and all its child. this avoids updating child tags
-						SyncMetadataJob.Create (Core.Database.Jobs, p);
+						SyncMetadataJob.Create (App.Instance.Database.Jobs, p);
 			}
 		}
 
diff --git a/src/Term.cs b/src/Term.cs
index 2c9bffb..c015ee4 100644
--- a/src/Term.cs
+++ b/src/Term.cs
@@ -330,7 +330,7 @@ namespace FSpot {
 
 			condition.Append (base.SqlCondition());
 
-			Tag hidden = Core.Database.Tags.Hidden;
+			Tag hidden = App.Instance.Database.Tags.Hidden;
 			if (hidden != null) {
 				if (FindByTag (hidden, true).Count == 0) {
 					condition.Append (String.Format (
diff --git a/src/Widgets/IconView.cs b/src/Widgets/IconView.cs
index c126dc7..3d1a976 100644
--- a/src/Widgets/IconView.cs
+++ b/src/Widgets/IconView.cs
@@ -975,7 +975,7 @@ namespace FSpot.Widgets
 					Pixbuf icon = t.Icon;
 
 					Tag tag_iter = t.Category;
-					while (icon == null && tag_iter != Core.Database.Tags.RootCategory && tag_iter != null) {
+					while (icon == null && tag_iter != App.Instance.Database.Tags.RootCategory && tag_iter != null) {
 						icon = tag_iter.Icon;
 						tag_iter = tag_iter.Category;
 					}
diff --git a/src/f-spot.in b/src/f-spot.in
index 8a26d51..fc7d296 100644
--- a/src/f-spot.in
+++ b/src/f-spot.in
@@ -60,7 +60,7 @@ for arg in "$@"; do
 	x--uninstalled)
 	    echo "*** Running uninstalled f-spot ***"
 	    EXE_TO_RUN="./f-spot.exe"
-	    export MONO_PATH=../lib/gnome-keyring-sharp:../lib/libgphoto2-sharp:../lib/semweb:../lib/mono-addins/Mono.Addins:../lib/mono-addins/Mono.Addins.Setup:../lib/mono-addins/Mono.Addins.Gui:../lib/gio-sharp/gio:../lib/gtk-sharp-beans:$MONO_PATH
+	    export MONO_PATH=../lib/gnome-keyring-sharp:../lib/libgphoto2-sharp:../lib/semweb:../lib/mono-addins/Mono.Addins:../lib/mono-addins/Mono.Addins.Setup:../lib/mono-addins/Mono.Addins.Gui:../lib/gio-sharp/gio:../lib/gtk-sharp-beans:../lib/unique-sharp/unique:$MONO_PATH
 	    ;;
     esac
 done
diff --git a/src/main.cs b/src/main.cs
index 9f52676..771498f 100644
--- a/src/main.cs
+++ b/src/main.cs
@@ -19,7 +19,9 @@ namespace FSpot
 		static void Version ()
 		{
 			Console.WriteLine (
-				"F-Spot  {0} - (c)2003-2009, Novell Inc" + Environment.NewLine +
+				"F-Spot  {0}" + Environment.NewLine +
+				"\t(c)2003-2009, Novell Inc" + Environment.NewLine +
+				"\t(c)2009 Stephane Delcroix" + Environment.NewLine +
 				"Personal photo management for the GNOME Desktop" + Environment.NewLine,
 				FSpot.Defines.VERSION);
 		}
@@ -57,7 +59,6 @@ namespace FSpot
 		static int Main (string [] args)
 		{
 			bool empty = false;
-			ICore control = null;
 			List<string> uris = new List<string> ();
 			Unix.SetProcessName (Defines.PACKAGE);
 
@@ -174,177 +175,73 @@ namespace FSpot
 				return 1;
 			}
 
-			Application.Init (Defines.PACKAGE, ref args);
-
-			if (slideshow == true) {
-				Gnome.Vfs.Vfs.Initialize ();
-				Core core = new Core ();
-				core.ShowSlides (null);
-				Application.Run ();
-				return 0;
-			}
-			
-			try {
-				uint timer = Log.InformationTimerStart ("Initializing DBus");
-				try {
-					NDesk.DBus.BusG.Init();
-				} catch (Exception e) {
-					throw new ApplicationException ("F-Spot cannot find the Dbus session bus. " +
-					"Make sure dbus is configured properly or start a new session for f-spot using \"dbus-launch f-spot\"", e);
-				}
-				Log.DebugTimerPrint (timer, "DBusInitialization took {0}");
-
-				timer = Log.InformationTimerStart ("Initializing Mono.Addins");
-				AddinManager.Initialize (FSpot.Global.BaseDirectory);
-				AddinManager.Registry.Update (null);
-				SetupService setupService = new SetupService (AddinManager.Registry);
-				string maj_version = String.Join (".", Defines.VERSION.Split ('.'), 0, 3);
-				foreach (AddinRepository repo in setupService.Repositories.GetRepositories ())
-					if (repo.Url.StartsWith ("http://addins.f-spot.org/";) && !repo.Url.StartsWith ("http://addins.f-spot.org/"; + maj_version)) {
-						Log.Information ("Unregistering {0}", repo.Url);
-						setupService.Repositories.RemoveRepository (repo.Url);
-					}
-				setupService.Repositories.RegisterRepository (null, "http://addins.f-spot.org/"; + maj_version, false);
-				Log.DebugTimerPrint (timer, "Mono.Addins Initialization took {0}");
-
-				bool is_main = true;
-
-				try {
-					control = Core.FindInstance ();
-					is_main = false;
-				} catch (System.Exception) { 
+			//Initialize Mono.Addins
+			uint timer = Log.InformationTimerStart ("Initializing Mono.Addins");
+			AddinManager.Initialize (FSpot.Global.BaseDirectory);
+			AddinManager.Registry.Update (null);
+			SetupService setupService = new SetupService (AddinManager.Registry);
+			string maj_version = String.Join (".", Defines.VERSION.Split ('.'), 0, 3);
+			foreach (AddinRepository repo in setupService.Repositories.GetRepositories ())
+				if (repo.Url.StartsWith ("http://addins.f-spot.org/";) && !repo.Url.StartsWith ("http://addins.f-spot.org/"; + maj_version)) {
+					Log.Information ("Unregistering {0}", repo.Url);
+					setupService.Repositories.RemoveRepository (repo.Url);
 				}
+			setupService.Repositories.RegisterRepository (null, "http://addins.f-spot.org/"; + maj_version, false);
+			Log.DebugTimerPrint (timer, "Mono.Addins Initialization took {0}");
 
-				if (control == null) {
-					if (!shutdown)
-						Log.Information ("Starting new FSpot server (f-spot {0})", FSpot.Defines.VERSION);
-				} else
-					Log.Information ("Found active FSpot server: {0}", control);
-
-				Core core = null;
-				try {
-					if (control == null) {
-						Gnome.Vfs.Vfs.Initialize ();
-
-						if (File.Exists (Preferences.Get<string> (Preferences.GTK_RC))) {
-							if (File.Exists (Path.Combine (Global.BaseDirectory, "gtkrc")))
-								Gtk.Rc.AddDefaultFile (Path.Combine (Global.BaseDirectory, "gtkrc"));
-
-							Global.DefaultRcFiles = Gtk.Rc.DefaultFiles;
-							Gtk.Rc.AddDefaultFile (Preferences.Get<string> (Preferences.GTK_RC));
-							Gtk.Rc.ReparseAllForSettings (Gtk.Settings.Default, true);
-						}
-
-						try {
-							Gtk.Window.DefaultIconList = new Gdk.Pixbuf [] {
-								GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 16, (Gtk.IconLookupFlags)0),
-								GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 22, (Gtk.IconLookupFlags)0),
-								GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 32, (Gtk.IconLookupFlags)0),
-								GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 48, (Gtk.IconLookupFlags)0)
-							};
-						} catch {}
 
-						core = new Core ();
-						core.RegisterServer ();
-
-						empty = view || Core.Database.Empty;
-						control = core;
-					}
-				} catch (System.Exception e) {
-					Log.Exception (e);
-					control = null;
+			//Gtk initialization
+			Application.Init (Defines.PACKAGE, ref args);
+			Gnome.Vfs.Vfs.Initialize ();
 
-					if (core != null)
-						core.UnregisterServer ();
+			// init web proxy globally
+			Platform.WebProxy.Init ();
 
-					// if there is a problem with the DB, so is no way we can survive
-					if (e is DbException) {
-						throw;
-					}
-				}
+			if (File.Exists (Preferences.Get<string> (Preferences.GTK_RC))) {
+				if (File.Exists (Path.Combine (Global.BaseDirectory, "gtkrc")))
+					Gtk.Rc.AddDefaultFile (Path.Combine (Global.BaseDirectory, "gtkrc"));
 
-				if (control == null)
-					throw new ApplicationException ("Sorry, couldn't start F-Spot.");
+				Global.DefaultRcFiles = Gtk.Rc.DefaultFiles;
+				Gtk.Rc.AddDefaultFile (Preferences.Get<string> (Preferences.GTK_RC));
+				Gtk.Rc.ReparseAllForSettings (Gtk.Settings.Default, true);
+			}
 
-				UriList list = new UriList ();
+			try {
+				Gtk.Window.DefaultIconList = new Gdk.Pixbuf [] {
+					GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 16, (Gtk.IconLookupFlags)0),
+					GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 22, (Gtk.IconLookupFlags)0),
+					GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 32, (Gtk.IconLookupFlags)0),
+					GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 48, (Gtk.IconLookupFlags)0)
+				};
+			} catch {}
 
-				if (shutdown) {
+			try {
+				if (slideshow == true) {
+					App.Instance.Slideshow (null);
+				} else if (shutdown) {
 					try {
-						control.Shutdown ();
+						App.Instance.Shutdown ();
 					} catch (System.Exception) { // trap errors
 					}
 					System.Environment.Exit (0);
-				}
-
-				if (import_uri != null) {
-					control.Import (import_uri);
-				}
-
-				if (view) {
+				} else if (view) {
+					UriList list = new UriList ();
 					foreach (string s in uris)
 						list.AddUnknown (s);
 					if (list.Count == 0) {
 						Help ();
 						return 1;
 					}
-					control.View (list.ToString ());
-				}
-
-				if (empty && import_uri == null && !view)
-					control.Import (null);
-
-				if (is_main && import_uri != null || !view) {
-					control.Organize ();
-					Gdk.Global.NotifyStartupComplete ();
-					foreach (ServiceNode service in AddinManager.GetExtensionNodes ("/FSpot/Services")) {
-						try {
-							service.Initialize ();
-							service.Start ();
-						} catch (Exception e) {
-							Log.Warning ("Something went wrong while starting the {0} extension.", service.Id);
-							Log.DebugException (e);
-						}
-					}
+					App.Instance.View (list.ToString ());
+				} else if (import_uri != null) {
+					App.Instance.Import (import_uri);
+				} else {
+					App.Instance.Organize ();
 				}
-
-				if (!is_main)
+	
+				if (App.Instance.IsRunning)
 					return 0;
-
-				// init web proxy globally
-				Platform.WebProxy.Init ();
-
-#if GSD_2_24
-				Log.Information ("Hack for gnome-settings-daemon engaged");
-				int max_age, max_size;
-				if (Preferences.TryGet<int> (Preferences.GSD_THUMBS_MAX_AGE, out max_age)) {
-					if (max_age < 0)
-						Log.Debug ("maximum_age check already disabled, good");
-					else if (max_age == 0)
-						Log.Warning ("maximum_age is 0 (tin-hat mode), not overriding");
-					else if (max_age < 180) {
-						Log.Debug ("Setting maximum_age to a saner value");
-						Preferences.Set (Preferences.GSD_THUMBS_MAX_AGE, 180);
-					}
-				}
-
-				if (Preferences.TryGet<int> (Preferences.GSD_THUMBS_MAX_SIZE, out max_size)) {
-					int count = Core.Database.Photos.Count ("photos");
-					// average thumbs are taking 70K, so this will push the threshold
-					//if f-spot takes more than 70% of the thumbs space
-					int size = count / 10;
-					if (max_size < 0)
-						Log.Debug ("maximum_size check already disabled, good");
-					else if (max_size == 0)
-						Log.Warning ("maximum_size is 0 (tin-hat mode), not overriding");
-					else if (max_size < size) {
-						Log.Debug ("Setting maximum_size to a saner value ({0}MB), according to your db size", size);
-						Preferences.Set (Preferences.GSD_THUMBS_MAX_SIZE, size);
-					}
-				}
-
-#endif
 				Application.Run ();
-				Log.Information ("exiting");
 			} catch (System.Exception e) {
 				Log.Exception (e);
 				ExceptionDialog dlg = new ExceptionDialog(e);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]