changeset 18:836a064828e8

Implement FileDialog/DirectoryDialog with GTK and start a glib/gdk/gtk binding. Add invoke/invokeNow stubs to fix build on X.
author Jordan Miner <jminer7@gmail.com>
date Fri, 24 Jul 2009 00:35:42 -0500
parents ef81af74a306
children e4dabffaa784
files dynamin/all_gui.d dynamin/c/gdk.d dynamin/c/glib.d dynamin/c/gtk.d dynamin/gui/directory_dialog.d dynamin/gui/file_dialog.d dynamin/gui/screen.d dynamin/gui/windows_directory_dialog.d dynamin/gui/windows_file_dialog.d dynamin/gui/x_directory_dialog.d dynamin/gui/x_file_dialog.d dynamin/gui/x_window.d dynamin/gui_backend.d
diffstat 13 files changed, 1391 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/dynamin/all_gui.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/all_gui.d	Fri Jul 24 00:35:42 2009 -0500
@@ -36,8 +36,8 @@
 public import dynamin.gui.cursor;
 public import dynamin.gui.clipboard;
 public import dynamin.gui.screen;
-version(Windows) public import dynamin.gui.directory_dialog;
-version(Windows) public import dynamin.gui.file_dialog;
+public import dynamin.gui.directory_dialog;
+public import dynamin.gui.file_dialog;
 
 public import dynamin.gui.label;
 public import dynamin.gui.button;
@@ -52,6 +52,7 @@
 
 public import dynamin.gui.theme;
 public import dynamin.gui.basic_theme;
+public import dynamin.gui.silver_theme;
 public import dynamin.gui.windows_theme;
 
 void aHack() { Theme.current; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/c/gdk.d	Fri Jul 24 00:35:42 2009 -0500
@@ -0,0 +1,126 @@
+module dynamin.c.gdk;
+
+/*
+ * A binding to at least the part of GDK that Dynamin uses.
+ */
+
+import dynamin.c.glib;
+import tango.sys.SharedLib;
+
+extern(C):
+
+//{{{ gdktypes
+enum {
+	GDK_CURRENT_TIME     = 0L,
+	GDK_PARENT_RELATIVE  = 1L
+}
+
+alias guint32 GdkWChar;
+
+/*alias struct _GdkAtom* GdkAtom;*/
+alias void* GdkAtom;
+
+gpointer GDK_ATOM_TO_POINTER(GdkAtom atom) { return atom; }
+GdkAtom GDK_POINTER_TO_ATOM(gpointer ptr) { return ptr; }
+
+GdkAtom _GDK_MAKE_ATOM(guint64 val) { return cast(GdkAtom)val; }
+GdkAtom GDK_NONE() { return _GDK_MAKE_ATOM(0); }
+
+alias guint32 GdkNativeWindow;
+
+enum {
+	GDK_LSB_FIRST,
+	GDK_MSB_FIRST
+}
+alias uint GdkByteOrder;
+
+enum {
+	GDK_SHIFT_MASK    = 1 << 0,
+	GDK_LOCK_MASK     = 1 << 1,
+	GDK_CONTROL_MASK  = 1 << 2,
+	GDK_MOD1_MASK     = 1 << 3,
+	GDK_MOD2_MASK     = 1 << 4,
+	GDK_MOD3_MASK     = 1 << 5,
+	GDK_MOD4_MASK     = 1 << 6,
+	GDK_MOD5_MASK     = 1 << 7,
+	GDK_BUTTON1_MASK  = 1 << 8,
+	GDK_BUTTON2_MASK  = 1 << 9,
+	GDK_BUTTON3_MASK  = 1 << 10,
+	GDK_BUTTON4_MASK  = 1 << 11,
+	GDK_BUTTON5_MASK  = 1 << 12,
+
+	GDK_SUPER_MASK    = 1 << 26,
+	GDK_HYPER_MASK    = 1 << 27,
+	GDK_META_MASK     = 1 << 28,
+
+	GDK_RELEASE_MASK  = 1 << 30,
+
+	GDK_MODIFIER_MASK = 0x5c001fff
+}
+alias uint GdkModifierType;
+
+enum {
+	GDK_INPUT_READ       = 1 << 0,
+	GDK_INPUT_WRITE      = 1 << 1,
+	GDK_INPUT_EXCEPTION  = 1 << 2
+}
+alias uint GdkInputCondition;
+
+enum {
+	GDK_OK          = 0,
+	GDK_ERROR          = -1,
+	GDK_ERROR_PARAM = -2,
+	GDK_ERROR_FILE  = -3,
+	GDK_ERROR_MEM          = -4
+}
+alias uint GdkStatus;
+
+enum {
+	GDK_GRAB_SUCCESS         = 0,
+	GDK_GRAB_ALREADY_GRABBED = 1,
+	GDK_GRAB_INVALID_TIME    = 2,
+	GDK_GRAB_NOT_VIEWABLE    = 3,
+	GDK_GRAB_FROZEN          = 4
+}
+alias uint GdkGrabStatus;
+
+alias void function(gpointer data,
+	gint source,
+	GdkInputCondition condition) GdkInputFunction;
+
+struct GdkPoint {
+	gint x;
+	gint y;
+}
+
+struct GdkRectangle {
+	gint x;
+	gint y;
+	gint width;
+	gint height;
+}
+
+struct GdkSegment {
+	gint x1;
+	gint y1;
+	gint x2;
+	gint y2;
+}
+
+struct GdkSpan {
+	gint x;
+	gint y;
+	gint width;
+}
+//}}}
+
+//{{{ gdkwindow
+//}}}
+
+static this() {
+	auto lib = SharedLib.load("libgdk-x11-2.0.so.0");
+
+	//{{{ gdkwindow
+	//}}}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/c/glib.d	Fri Jul 24 00:35:42 2009 -0500
@@ -0,0 +1,397 @@
+module dynamin.c.glib;
+
+/*
+ * A binding to at least the part of Glib that Dynamin uses.
+ */
+
+import tango.sys.SharedLib;
+
+extern(C):
+
+//{{{ gtypes
+static if((void*).sizeof == 4) {
+	alias uint gsize;
+} else static if((void*).sizeof == 8) {
+	alias ulong gsize;
+}
+alias char gchar;
+alias short gshort;
+alias int glong;
+alias int gint;
+alias gint gboolean;
+
+alias ubyte guchar;
+alias ushort gushort;
+alias uint gulong;
+alias uint guint;
+
+alias float gfloat;
+alias double gdouble;
+
+alias byte gint8;
+alias ubyte guint8;
+alias short gint16;
+alias ushort guint16;
+alias int gint32;
+alias uint guint32;
+alias long gint64;
+alias ulong guint64;
+
+enum : gint8 {
+	G_MININT8 = cast(gint8)0x80,
+	G_MAXINT8 = 0x7f
+}
+enum : guint8 {
+	G_MAXUINT8 = 0xff
+}
+enum : gint16 {
+	G_MININT16 = cast(gint16)0x8000,
+	G_MAXINT16 = 0x7fff
+}
+enum : guint16 {
+	G_MAXUINT16 = 0xffff
+}
+
+enum : gint32 {
+	G_MININT32 = 0x80000000,
+	G_MAXINT32 = 0x7fffffff
+}
+enum : guint32 {
+	G_MAXUINT32 = 0xffffffff
+}
+
+enum : gint64 {
+	G_MININT64 = 0x8000000000000000,
+	G_MAXINT64 = 0x7fffffffffffffff
+}
+enum : guint64 {
+	G_MAXUINT64 = 0xffffffffffffffffU
+}
+
+
+alias void* gpointer;
+alias /*const*/ void* gconstpointer;
+
+alias gint function(gconstpointer a, gconstpointer b) GCompareFunc;
+alias gint function(gconstpointer a, gconstpointer b,
+	gpointer user_data) GCompareDataFunc;
+alias gboolean function(gconstpointer a, gconstpointer b) GEqualFunc;
+alias void function(gpointer data) GDestroyNotify;
+alias void function(gpointer data, gpointer user_data) GFunc;
+alias guint function(gconstpointer key) GHashFunc;
+alias void function(gpointer key, gpointer value,
+	gpointer user_data) GHFunc;
+alias void function(gpointer data) GFreeFunc;
+alias /*const*/ gchar* function(/*const*/ gchar* str,
+	gpointer data) GTranslateFunc;
+
+const real G_E     = 2.7182818284590452353602874713526624977572470937000;
+const real G_LN2   = 0.69314718055994530941723212145817656807550013436026;
+const real G_LN10  = 2.3025850929940456840179914546843642076011014886288;
+const real G_PI    = 3.1415926535897932384626433832795028841971693993751;
+const real G_PI_2  = 1.5707963267948966192313216916397514420985846996876;
+const real G_PI_4  = 0.78539816339744830961566084581987572104929234984378;
+const real G_SQRT2 = 1.4142135623730950488016887242096980785696718753769;
+
+version(LittleEndian) {
+	enum {
+		G_BYTE_ORDER = 1234
+	}
+} else {
+	enum {
+		G_BYTE_ORDER = 4321
+	}
+}
+enum {
+	G_LITTLE_ENDIAN = 1234,
+	G_BIG_ENDIAN    = 4321
+}
+//}}}
+
+//{{{ gtype
+const G_TYPE_FUNDAMENTAL_SHIFT = 2;
+const G_TYPE_FUNDAMENTAL_MAX = 255 << G_TYPE_FUNDAMENTAL_SHIFT;
+GType G_TYPE_MAKE_FUNDAMENTAL(uint x) {
+	return x << G_TYPE_FUNDAMENTAL_SHIFT;
+}
+enum {
+	G_TYPE_INVALID         = 0  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_NONE            = 1  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_INTERFACE       = 2  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_CHAR            = 3  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_UCHAR           = 4  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_BOOLEAN         = 5  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_INT             = 6  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_UINT            = 7  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_LONG            = 8  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_ULONG           = 9  << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_INT64           = 10 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_UINT64          = 11 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_ENUM            = 12 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_FLAGS           = 13 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_FLOAT           = 14 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_DOUBLE          = 15 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_STRING          = 16 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_POINTER         = 17 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_BOXED           = 18 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_PARAM           = 19 << G_TYPE_FUNDAMENTAL_SHIFT,
+	G_TYPE_OBJECT          = 20 << G_TYPE_FUNDAMENTAL_SHIFT,
+}
+const G_TYPE_RESERVED_GLIB_FIRST = 21;
+const G_TYPE_RESERVED_GLIB_LAST  = 31;
+const G_TYPE_RESERVED_BSE_FIRST  = 32;
+const G_TYPE_RESERVED_BSE_LAST   = 48;
+const G_TYPE_RESERVED_USER_FIRST = 49;
+
+bool G_TYPE_IS_FUNDAMENTAL(GType type) {
+	return type <= G_TYPE_FUNDAMENTAL_MAX;
+}
+bool G_TYPE_IS_DERIVED(GType type) {
+	return type > G_TYPE_FUNDAMENTAL_MAX;
+}
+/*bool G_TYPE_IS_INTERFACE(GType type) {
+	return G_TYPE_FUNDAMENTAL(type) == G_TYPE_INTERFACE;
+}
+bool G_TYPE_IS_CLASSED(GType type) {
+	return g_type_test_flags(type, G_TYPE_FLAG_CLASSED);
+}
+bool G_TYPE_IS_INSTANTIATABLE(GType type) {
+	return g_type_test_flags(type, G_TYPE_FLAG_INSTANTIATABLE);
+}
+bool G_TYPE_IS_DERIVABLE(GType type) {
+	return g_type_test_flags(type, G_TYPE_FLAG_DERIVABLE);
+}
+bool G_TYPE_IS_DEEP_DERIVABLE(GType type) {
+	return g_type_test_flags(type, G_TYPE_FLAG_DEEP_DERIVABLE);
+}
+bool G_TYPE_IS_ABSTRACT(GType type) {
+	return g_type_test_flags(type, G_TYPE_FLAG_ABSTRACT);
+}
+bool G_TYPE_IS_VALUE_ABSTRACT(GType type) {
+	return g_type_test_flags(type, G_TYPE_FLAG_VALUE_ABSTRACT);
+}
+bool G_TYPE_IS_VALUE_TYPE(GType type) {
+	return g_type_check_is_value_type(type);
+}
+bool G_TYPE_HAS_VALUE_TABLE(GType type) {
+	return g_type_value_table_peek(type) != NULL;
+}
+*/
+alias gsize GType;
+
+struct GTypeClass {
+	GType g_type;
+}
+struct GTypeInstance {
+	GTypeClass* g_class;
+}
+struct GTypeInterface {
+	GType g_type;
+	GType g_instance_type;
+}
+struct GTypeQuery {
+	GType type;
+	/*const*/ gchar* type_name;
+	guint class_size;
+	guint instance_size;
+}
+
+// plus a lot more
+//GType function(GType type_id) g_type_fundamental;
+//alias g_type_fundamental G_TYPE_FUNDAMENTAL;
+gboolean function(GType type, guint flags) g_type_test_flags;
+//}}}
+
+//{{{ gquark
+typedef guint32 GQuark;
+
+GQuark function(/*const*/ gchar* string) g_quark_try_string;
+GQuark function(/*const*/ gchar* string) g_quark_from_static_string;
+GQuark function(/*const*/ gchar* string) g_quark_from_string;
+gchar* function(GQuark quark) g_quark_to_string;
+
+gchar* function(/*const*/ gchar* string) g_intern_string;
+gchar* function(/*const*/ gchar* string) g_intern_static_string;
+//}}}
+
+//{{{ gerror
+struct GError {
+	GQuark domain;
+	gint code;
+	gchar* message;
+}
+
+GError* function(GQuark domain,
+	gint code,
+	/*const*/ gchar* format,
+	...) g_error_new;
+
+GError* function(GQuark domain,
+	gint code,
+	/*const*/ gchar* message) g_error_new_literal;
+
+void function(GError* error) g_error_free;
+GError* function(/*const*/ GError* error) g_error_copy;
+
+gboolean function(/*const*/ GError* error,
+	GQuark domain,
+	gint code) g_error_matches;
+
+void function(GError** err,
+	GQuark domain,
+	gint code,
+	/*const*/ gchar* format,
+	...) g_set_error;
+
+void function(GError** err,
+	GQuark domain,
+	gint code,
+	/*const*/ gchar* message) g_set_error_literal;
+
+void function(GError** dest,
+	GError* src) g_propagate_error;
+
+void function(GError** err) g_clear_error;
+
+void function(GError** err,
+	/*const*/ gchar* format,
+	...) g_prefix_error;
+
+void function(GError** dest,
+	GError* src,
+	/*const*/ gchar* format,
+	...) g_propagate_prefixed_error;
+//}}}
+
+//{{{ gslist
+struct GSList {
+	gpointer data;
+	GSList* next;
+}
+
+GSList* function() g_slist_alloc;
+void function(GSList* list) g_slist_free;
+void function(GSList* list) g_slist_free_1;
+alias g_slist_free_1 g_slist_free1;
+GSList* function(GSList* list, gpointer data) g_slist_append;
+GSList* function(GSList* list, gpointer data) g_slist_prepend;
+GSList* function(GSList* list, gpointer data, gint position) g_slist_insert;
+GSList* function(GSList* list, gpointer data, GCompareFunc func) g_slist_insert_sorted;
+GSList* function(
+	GSList* list,
+	gpointer data,
+	GCompareDataFunc func,
+	gpointer user_data) g_slist_insert_sorted_with_data;
+GSList* function(GSList* slist, GSList* sibling, gpointer data) g_slist_insert_before;
+GSList* function(GSList* list1, GSList* list2) g_slist_concat;
+GSList* function(GSList* list, gconstpointer data) g_slist_remove;
+GSList* function(GSList* list, gconstpointer data) g_slist_remove_all;
+GSList* function(GSList* list, GSList* link_) g_slist_remove_link;
+GSList* function(GSList* list, GSList* link_) g_slist_delete_link;
+GSList* function(GSList* list) g_slist_reverse;
+GSList* function(GSList* list) g_slist_copy;
+GSList* function(GSList* list, guint n) g_slist_nth;
+GSList* function(GSList* list, gconstpointer data) g_slist_find;
+GSList* function(
+	GSList* list,
+	gconstpointer data,
+	GCompareFunc func) g_slist_find_custom;
+gint function(GSList* list, GSList* llink) g_slist_position;
+gint function(GSList* list, gconstpointer data) g_slist_index;
+GSList* function(GSList* list) g_slist_last;
+guint function(GSList* list) g_slist_length;
+void function(GSList* list, GFunc func, gpointer user_data) g_slist_foreach;
+GSList* function(GSList* list, GCompareFunc compare_func) g_slist_sort;
+GSList* function(GSList* list,
+	GCompareDataFunc compare_func,
+	gpointer user_data) g_slist_sort_with_data;
+gpointer function(GSList* list, guint n) g_slist_nth_data;
+
+GSList* g_slist_next(GSList* slist) {
+	return slist ? slist.next : null;
+}
+//}}}
+
+//{{{ gmem
+gpointer function(gsize n_bytes) g_malloc;
+gpointer function(gsize n_bytes) g_malloc0;
+gpointer function(gpointer mem,
+	gsize n_bytes) g_realloc;
+void function(gpointer mem) g_free;
+gpointer function(gsize n_bytes) g_try_malloc;
+gpointer function(gsize n_bytes) g_try_malloc0;
+gpointer function(gpointer mem,
+	gsize n_bytes) g_try_realloc;
+//}}}
+
+static this() {
+	auto lib = SharedLib.load("libglib-2.0.so.0");
+
+	//{{{ gtype
+	//g_type_fundamental = cast(typeof(g_type_fundamental))lib.getSymbol("g_type_fundamental");
+	//g_type_test_flags = cast(typeof(g_type_test_flags))lib.getSymbol("g_type_test_flags");
+	//}}}
+
+	//{{{ gquark
+	g_quark_try_string = cast(typeof(g_quark_try_string))lib.getSymbol("g_quark_try_string");
+	g_quark_from_static_string = cast(typeof(g_quark_from_static_string))lib.getSymbol("g_quark_from_static_string");
+	g_quark_from_string = cast(typeof(g_quark_from_string))lib.getSymbol("g_quark_from_string");
+	g_quark_to_string = cast(typeof(g_quark_to_string))lib.getSymbol("g_quark_to_string");
+	g_intern_string = cast(typeof(g_intern_string))lib.getSymbol("g_intern_string");
+	g_intern_static_string = cast(typeof(g_intern_static_string))lib.getSymbol("g_intern_static_string");
+	//}}}
+
+	//{{{ gerror
+	g_error_new = cast(typeof(g_error_new))lib.getSymbol("g_error_new");
+	g_error_new_literal = cast(typeof(g_error_new_literal))lib.getSymbol("g_error_new_literal");
+	g_error_free = cast(typeof(g_error_free))lib.getSymbol("g_error_free");
+	g_error_copy = cast(typeof(g_error_copy))lib.getSymbol("g_error_copy");
+	g_error_matches = cast(typeof(g_error_matches))lib.getSymbol("g_error_matches");
+	g_set_error = cast(typeof(g_set_error))lib.getSymbol("g_set_error");
+	//g_set_error_literal = cast(typeof(g_set_error_literal))lib.getSymbol("g_set_error_literal");
+	g_propagate_error = cast(typeof(g_propagate_error))lib.getSymbol("g_propagate_error");
+	g_clear_error = cast(typeof(g_clear_error))lib.getSymbol("g_clear_error");
+	//g_prefix_error = cast(typeof(g_prefix_error))lib.getSymbol("g_prefix_error");
+	//g_propagate_prefixed_error = cast(typeof(g_propagate_prefixed_error))lib.getSymbol("g_propagate_prefixed_error");
+	//}}}
+
+	//{{{ gslist
+	g_slist_alloc = cast(typeof(g_slist_alloc))lib.getSymbol("g_slist_alloc");
+	g_slist_free = cast(typeof(g_slist_free))lib.getSymbol("g_slist_free");
+	g_slist_free_1 = cast(typeof(g_slist_free_1))lib.getSymbol("g_slist_free_1");
+	g_slist_append = cast(typeof(g_slist_append))lib.getSymbol("g_slist_append");
+	g_slist_prepend = cast(typeof(g_slist_prepend))lib.getSymbol("g_slist_prepend");
+	g_slist_insert = cast(typeof(g_slist_insert))lib.getSymbol("g_slist_insert");
+	g_slist_insert_sorted = cast(typeof(g_slist_insert_sorted))lib.getSymbol("g_slist_insert_sorted");
+	g_slist_insert_sorted_with_data = cast(typeof(g_slist_insert_sorted_with_data))lib.getSymbol("g_slist_insert_sorted_with_data");
+	g_slist_insert_before = cast(typeof(g_slist_insert_before))lib.getSymbol("g_slist_insert_before");
+	g_slist_concat = cast(typeof(g_slist_concat))lib.getSymbol("g_slist_concat");
+	g_slist_remove = cast(typeof(g_slist_remove))lib.getSymbol("g_slist_remove");
+	g_slist_remove_all = cast(typeof(g_slist_remove_all))lib.getSymbol("g_slist_remove_all");
+	g_slist_remove_link = cast(typeof(g_slist_remove_link))lib.getSymbol("g_slist_remove_link");
+	g_slist_delete_link = cast(typeof(g_slist_delete_link))lib.getSymbol("g_slist_delete_link");
+	g_slist_reverse = cast(typeof(g_slist_reverse))lib.getSymbol("g_slist_reverse");
+	g_slist_copy = cast(typeof(g_slist_copy))lib.getSymbol("g_slist_copy");
+	g_slist_nth = cast(typeof(g_slist_nth))lib.getSymbol("g_slist_nth");
+	g_slist_find = cast(typeof(g_slist_find))lib.getSymbol("g_slist_find");
+	g_slist_find_custom = cast(typeof(g_slist_find_custom))lib.getSymbol("g_slist_find_custom");
+	g_slist_position = cast(typeof(g_slist_position))lib.getSymbol("g_slist_position");
+	g_slist_index = cast(typeof(g_slist_index))lib.getSymbol("g_slist_index");
+	g_slist_last = cast(typeof(g_slist_last))lib.getSymbol("g_slist_last");
+	g_slist_length = cast(typeof(g_slist_length))lib.getSymbol("g_slist_length");
+	g_slist_foreach = cast(typeof(g_slist_foreach))lib.getSymbol("g_slist_foreach");
+	g_slist_sort = cast(typeof(g_slist_sort))lib.getSymbol("g_slist_sort");
+	g_slist_sort_with_data = cast(typeof(g_slist_sort_with_data))lib.getSymbol("g_slist_sort_with_data");
+	g_slist_nth_data = cast(typeof(g_slist_nth_data))lib.getSymbol("g_slist_nth_data");
+	//}}}
+
+	//{{{ gmem
+	g_malloc = cast(typeof(g_malloc))lib.getSymbol("g_malloc");
+	g_malloc0 = cast(typeof(g_malloc0))lib.getSymbol("g_malloc0");
+	g_realloc = cast(typeof(g_realloc))lib.getSymbol("g_realloc");
+	g_free = cast(typeof(g_free))lib.getSymbol("g_free");
+	g_try_malloc = cast(typeof(g_try_malloc))lib.getSymbol("g_try_malloc");
+	g_try_malloc0 = cast(typeof(g_try_malloc0))lib.getSymbol("g_try_malloc0");
+	g_try_realloc = cast(typeof(g_try_realloc))lib.getSymbol("g_try_realloc");
+	//}}}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/c/gtk.d	Fri Jul 24 00:35:42 2009 -0500
@@ -0,0 +1,592 @@
+module dynamin.c.gtk;
+
+/*
+ * A binding to at least the part of GTK that Dynamin uses.
+ */
+
+import dynamin.c.glib;
+import dynamin.c.gdk;
+import tango.sys.SharedLib;
+
+extern(C):
+
+alias void GtkWidget;
+alias void GtkWindow;
+
+//{{{ gtkmain
+/*const*/ gchar* function(guint required_major,
+	guint required_minor,
+	guint required_micro) gtk_check_version;
+
+gboolean function(int* argc,
+	char*** argv) gtk_parse_args;
+
+void function(int* argc,
+	char*** argv) gtk_init;
+
+gboolean function(int* argc,
+	char*** argv) gtk_init_check;
+
+// leaving some out
+
+gboolean function() gtk_events_pending;
+//void function(GdkEvent* event) gtk_main_do_event;
+void function() gtk_main;
+guint function() gtk_main_level;
+void function() gtk_main_quit;
+gboolean function() gtk_main_iteration;
+gboolean function(gboolean blocking) gtk_main_iteration_do;
+//}}}
+
+//{{{ gtkwidget
+void function(GtkWidget* widget) gtk_widget_destroy;
+//}}}
+
+//{{{ gtkdialog
+enum {
+	GTK_DIALOG_MODAL               = 1 << 0,
+	GTK_DIALOG_DESTROY_WITH_PARENT = 1 << 1,
+	GTK_DIALOG_NO_SEPARATOR        = 1 << 2
+}
+alias uint GtkDialogFlags;
+
+enum {
+	GTK_RESPONSE_NONE = -1,
+
+	GTK_RESPONSE_REJECT = -2,
+	GTK_RESPONSE_ACCEPT = -3,
+
+	GTK_RESPONSE_DELETE_EVENT = -4,
+
+	GTK_RESPONSE_OK     = -5,
+	GTK_RESPONSE_CANCEL = -6,
+	GTK_RESPONSE_CLOSE  = -7,
+	GTK_RESPONSE_YES    = -8,
+	GTK_RESPONSE_NO     = -9,
+	GTK_RESPONSE_APPLY  = -10,
+	GTK_RESPONSE_HELP   = -11
+}
+alias uint GtkResponseType;
+
+alias void GtkDialog;
+
+GType function() gtk_dialog_get_type;
+alias gtk_dialog_get_type GTK_TYPE_DIALOG;
+GtkWidget* function() gtk_dialog_new;
+
+GtkWidget* function(/*const*/ gchar* title,
+	GtkWindow* parent,
+	GtkDialogFlags flags,
+	/*const*/ gchar* first_button_text,
+	...) gtk_dialog_new_with_buttons;
+
+void function(GtkDialog* dialog,
+	GtkWidget* child,
+	gint response_id) gtk_dialog_add_action_widget;
+GtkWidget* function(GtkDialog* dialog,
+	/*const*/ gchar* button_text,
+	gint response_id) gtk_dialog_add_button;
+void function(GtkDialog* dialog,
+	/*const*/ gchar* first_button_text,
+	...) gtk_dialog_add_buttons;
+
+void function(GtkDialog* dialog,
+	gint response_id,
+	gboolean setting) gtk_dialog_set_response_sensitive;
+void function(GtkDialog* dialog,
+	gint response_id) gtk_dialog_set_default_response;
+gint function(GtkDialog* dialog,
+	GtkWidget* widget) gtk_dialog_get_response_for_widget;
+
+void function(GtkDialog* dialog,
+	gboolean setting) gtk_dialog_set_has_separator;
+gboolean function(GtkDialog* dialog) gtk_dialog_get_has_separator;
+
+//gboolean function(GdkScreen* screen) gtk_alternative_dialog_button_order;
+void function(GtkDialog* dialog,
+	gint first_response_id,
+	...) gtk_dialog_set_alternative_button_order;
+void function(GtkDialog* dialog,
+	gint n_params,
+	gint* new_order) gtk_dialog_set_alternative_button_order_from_array;
+
+void function(GtkDialog* dialog,
+	gint response_id) gtk_dialog_response;
+
+gint function(GtkDialog* dialog) gtk_dialog_run;
+
+GtkWidget*  function(GtkDialog* dialog) gtk_dialog_get_action_area;
+GtkWidget*  function(GtkDialog* dialog) gtk_dialog_get_content_area;
+//}}}
+
+//{{{ gtkfilefilter
+alias void GtkFileFilter;
+
+enum {
+	GTK_FILE_FILTER_FILENAME     = 1 << 0,
+	GTK_FILE_FILTER_URI          = 1 << 1,
+	GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
+	GTK_FILE_FILTER_MIME_TYPE    = 1 << 3
+}
+alias uint GtkFileFilterFlags;
+
+alias gboolean function(/*const*/ GtkFileFilterInfo* filter_info,
+	gpointer data) GtkFileFilterFunc;
+
+struct GtkFileFilterInfo {
+	GtkFileFilterFlags contains;
+
+	/*const*/ gchar* filename;
+	/*const*/ gchar* uri;
+	/*const*/ gchar* display_name;
+	/*const*/ gchar* mime_type;
+}
+
+GType function() gtk_file_filter_get_type;
+
+alias gtk_file_filter_get_type GTK_TYPE_FILE_FILTER;
+
+GtkFileFilter*  function() gtk_file_filter_new;
+void function(GtkFileFilter* filter,
+	/*const*/ gchar* name) gtk_file_filter_set_name;
+gchar* function(GtkFileFilter* filter) gtk_file_filter_get_name;
+
+void function(GtkFileFilter* filter,
+	/*const*/ gchar* mime_type) gtk_file_filter_add_mime_type;
+void function(GtkFileFilter* filter,
+	/*const*/ gchar* pattern) gtk_file_filter_add_pattern;
+void function(GtkFileFilter* filter) gtk_file_filter_add_pixbuf_formats;
+void function(GtkFileFilter* filter,
+	GtkFileFilterFlags needed,
+	GtkFileFilterFunc func,
+	gpointer data,
+	GDestroyNotify notify) gtk_file_filter_add_custom;
+
+GtkFileFilterFlags function(GtkFileFilter* filter) gtk_file_filter_get_needed;
+gboolean function(GtkFileFilter* filter,
+	/*const*/ GtkFileFilterInfo* filter_info) gtk_file_filter_filter;
+//}}}
+
+//{{{ gtkfilechooser
+alias void GtkFileChooser;
+
+enum {
+	GTK_FILE_CHOOSER_ACTION_OPEN,
+	GTK_FILE_CHOOSER_ACTION_SAVE,
+	GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+	GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+}
+alias uint GtkFileChooserAction;
+
+enum {
+	GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM,
+	GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME,
+	GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN
+}
+alias uint GtkFileChooserConfirmation;
+
+GType function() gtk_file_chooser_get_type;
+
+alias gtk_file_chooser_get_type GTK_TYPE_FILE_CHOOSER;
+
+enum {
+	GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
+	GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
+	GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
+	GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME
+}
+alias uint GtkFileChooserError;
+
+GQuark function() gtk_file_chooser_error_quark;
+
+alias gtk_file_chooser_error_quark GTK_FILE_CHOOSER_ERROR;
+
+void function(GtkFileChooser* chooser,
+	GtkFileChooserAction action) gtk_file_chooser_set_action;
+GtkFileChooserAction function(GtkFileChooser* chooser) gtk_file_chooser_get_action;
+void function(GtkFileChooser* chooser,
+	gboolean local_only) gtk_file_chooser_set_local_only;
+gboolean function(GtkFileChooser* chooser) gtk_file_chooser_get_local_only;
+void function(GtkFileChooser* chooser,
+	gboolean select_multiple) gtk_file_chooser_set_select_multiple;
+gboolean function(GtkFileChooser* chooser) gtk_file_chooser_get_select_multiple;
+void function(GtkFileChooser* chooser,
+	gboolean show_hidden) gtk_file_chooser_set_show_hidden;
+gboolean function(GtkFileChooser* chooser) gtk_file_chooser_get_show_hidden;
+void function(GtkFileChooser* chooser,
+	gboolean do_overwrite_confirmation) gtk_file_chooser_set_do_overwrite_confirmation;
+gboolean function(GtkFileChooser* chooser) gtk_file_chooser_get_do_overwrite_confirmation;
+
+void function(GtkFileChooser* chooser,
+	/*const*/ gchar* name) gtk_file_chooser_set_current_name;
+
+gchar* function(GtkFileChooser* chooser) gtk_file_chooser_get_filename;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* filename) gtk_file_chooser_set_filename;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* filename) gtk_file_chooser_select_filename;
+void function(GtkFileChooser* chooser,
+	/*const*/ char* filename) gtk_file_chooser_unselect_filename;
+void function(GtkFileChooser* chooser) gtk_file_chooser_select_all;
+void function(GtkFileChooser* chooser) gtk_file_chooser_unselect_all;
+GSList* function(GtkFileChooser* chooser) gtk_file_chooser_get_filenames;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ gchar* filename) gtk_file_chooser_set_current_folder;
+gchar* function(GtkFileChooser* chooser) gtk_file_chooser_get_current_folder;
+
+gchar* function(GtkFileChooser* chooser) gtk_file_chooser_get_uri;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* uri) gtk_file_chooser_set_uri;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* uri) gtk_file_chooser_select_uri;
+void function(GtkFileChooser* chooser,
+	/*const*/ char* uri) gtk_file_chooser_unselect_uri;
+GSList* function(GtkFileChooser* chooser) gtk_file_chooser_get_uris;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ gchar* uri) gtk_file_chooser_set_current_folder_uri;
+gchar* function(GtkFileChooser* chooser) gtk_file_chooser_get_current_folder_uri;
+/*
+GFile* function(GtkFileChooser* chooser) gtk_file_chooser_get_file;
+gboolean function(GtkFileChooser* chooser,
+	GFile* file,
+	GError** error) gtk_file_chooser_set_file;
+gboolean function(GtkFileChooser* chooser,
+	GFile* file,
+	GError** error) gtk_file_chooser_select_file;
+void function(GtkFileChooser* chooser,
+	GFile* file) gtk_file_chooser_unselect_file;
+GSList* function(GtkFileChooser* chooser) gtk_file_chooser_get_files;
+gboolean function(GtkFileChooser* chooser,
+	GFile* file,
+	GError** error) gtk_file_chooser_set_current_folder_file;
+GFile* function(GtkFileChooser* chooser) gtk_file_chooser_get_current_folder_file;
+*/
+/*
+void function(GtkFileChooser* chooser,
+	GtkWidget* preview_widget) gtk_file_chooser_set_preview_widget;
+GtkWidget* function(GtkFileChooser* chooser) gtk_file_chooser_get_preview_widget;
+void function(GtkFileChooser* chooser,
+	gboolean active) gtk_file_chooser_set_preview_widget_active;
+gboolean function(GtkFileChooser* chooser) gtk_file_chooser_get_preview_widget_active;
+void function(GtkFileChooser* chooser,
+	gboolean use_label) gtk_file_chooser_set_use_preview_label;
+gboolean function(GtkFileChooser* chooser) gtk_file_chooser_get_use_preview_label;
+
+char* function(GtkFileChooser* chooser) gtk_file_chooser_get_preview_filename;
+char* function(GtkFileChooser* chooser) gtk_file_chooser_get_preview_uri;
+GFile* function(GtkFileChooser* chooser) gtk_file_chooser_get_preview_file;
+
+void function(GtkFileChooser* chooser,
+	GtkWidget* extra_widget) gtk_file_chooser_set_extra_widget;
+GtkWidget* function(GtkFileChooser* chooser) gtk_file_chooser_get_extra_widget;
+*/
+void function(GtkFileChooser* chooser,
+	GtkFileFilter* filter) gtk_file_chooser_add_filter;
+void function(GtkFileChooser* chooser,
+	GtkFileFilter* filter) gtk_file_chooser_remove_filter;
+GSList* function(GtkFileChooser* chooser) gtk_file_chooser_list_filters;
+
+void function(GtkFileChooser* chooser,
+	GtkFileFilter* filter) gtk_file_chooser_set_filter;
+GtkFileFilter* function(GtkFileChooser* chooser) gtk_file_chooser_get_filter;
+
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* folder,
+	GError** error) gtk_file_chooser_add_shortcut_folder;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* folder,
+	GError** error) gtk_file_chooser_remove_shortcut_folder;
+GSList* function(GtkFileChooser* chooser) gtk_file_chooser_list_shortcut_folders;
+
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* uri,
+	GError** error) gtk_file_chooser_add_shortcut_folder_uri;
+gboolean function(GtkFileChooser* chooser,
+	/*const*/ char* uri,
+	GError** error) gtk_file_chooser_remove_shortcut_folder_uri;
+GSList* function(GtkFileChooser* chooser) gtk_file_chooser_list_shortcut_folder_uris;
+//}}}
+
+//{{{ gtkfilechooserdialog
+alias void GtkFileChooserDialog;
+
+GType function() gtk_file_chooser_dialog_get_type;
+alias gtk_file_chooser_dialog_get_type GTK_TYPE_FILE_CHOOSER_DIALOG;
+GtkWidget* function(/*const*/ gchar* title,
+	GtkWindow* parent,
+	GtkFileChooserAction action,
+	/*const*/ gchar* first_button_text,
+	...) gtk_file_chooser_dialog_new;
+//}}}
+
+//{{{ gtkstock
+struct GtkStockItem {
+	gchar* stock_id;
+	gchar* label;
+	GdkModifierType modifier;
+	guint keyval;
+	gchar* translation_domain;
+}
+
+void function(/*const*/ GtkStockItem* items,
+	guint n_items) gtk_stock_add;
+void function(/*const*/ GtkStockItem* items,
+	guint n_items) gtk_stock_add_static;
+gboolean function(/*const*/ gchar* stock_id,
+	GtkStockItem* item) gtk_stock_lookup;
+
+GSList* function() gtk_stock_list_ids;
+
+GtkStockItem* function(/*const*/ GtkStockItem* item) gtk_stock_item_copy;
+void function(GtkStockItem* item) gtk_stock_item_free;
+
+//void function(/*const*/ gchar* domain,
+//	GtkTranslateFunc func,
+//	gpointer data,
+//	GDestroyNotify notify) gtk_stock_set_translate_func;
+
+const gchar* GTK_STOCK_DIALOG_AUTHENTICATION = "gtk-dialog-authentication";
+const gchar* GTK_STOCK_DIALOG_INFO      = "gtk-dialog-info";
+const gchar* GTK_STOCK_DIALOG_WARNING   = "gtk-dialog-warning";
+const gchar* GTK_STOCK_DIALOG_ERROR     = "gtk-dialog-error";
+const gchar* GTK_STOCK_DIALOG_QUESTION  = "gtk-dialog-question";
+
+const gchar* GTK_STOCK_DND              = "gtk-dnd";
+const gchar* GTK_STOCK_DND_MULTIPLE     = "gtk-dnd-multiple";
+
+const gchar* GTK_STOCK_ABOUT            = "gtk-about";
+const gchar* GTK_STOCK_ADD              = "gtk-add";
+const gchar* GTK_STOCK_APPLY            = "gtk-apply";
+const gchar* GTK_STOCK_BOLD             = "gtk-bold";
+const gchar* GTK_STOCK_CANCEL           = "gtk-cancel";
+const gchar* GTK_STOCK_CAPS_LOCK_WARNING = "gtk-caps-lock-warning";
+const gchar* GTK_STOCK_CDROM            = "gtk-cdrom";
+const gchar* GTK_STOCK_CLEAR            = "gtk-clear";
+const gchar* GTK_STOCK_CLOSE            = "gtk-close";
+const gchar* GTK_STOCK_COLOR_PICKER     = "gtk-color-picker";
+const gchar* GTK_STOCK_CONVERT          = "gtk-convert";
+const gchar* GTK_STOCK_CONNECT          = "gtk-connect";
+const gchar* GTK_STOCK_COPY             = "gtk-copy";
+const gchar* GTK_STOCK_CUT              = "gtk-cut";
+const gchar* GTK_STOCK_DELETE           = "gtk-delete";
+const gchar* GTK_STOCK_DIRECTORY        = "gtk-directory";
+const gchar* GTK_STOCK_DISCARD          = "gtk-discard";
+const gchar* GTK_STOCK_DISCONNECT       = "gtk-disconnect";
+const gchar* GTK_STOCK_EDIT             = "gtk-edit";
+const gchar* GTK_STOCK_EXECUTE          = "gtk-execute";
+const gchar* GTK_STOCK_FILE             = "gtk-file";
+const gchar* GTK_STOCK_FIND             = "gtk-find";
+const gchar* GTK_STOCK_FIND_AND_REPLACE = "gtk-find-and-replace";
+const gchar* GTK_STOCK_FLOPPY           = "gtk-floppy";
+const gchar* GTK_STOCK_FULLSCREEN       = "gtk-fullscreen";
+const gchar* GTK_STOCK_GOTO_BOTTOM      = "gtk-goto-bottom";
+const gchar* GTK_STOCK_GOTO_FIRST       = "gtk-goto-first";
+const gchar* GTK_STOCK_GOTO_LAST        = "gtk-goto-last";
+const gchar* GTK_STOCK_GOTO_TOP         = "gtk-goto-top";
+const gchar* GTK_STOCK_GO_BACK          = "gtk-go-back";
+const gchar* GTK_STOCK_GO_DOWN          = "gtk-go-down";
+const gchar* GTK_STOCK_GO_FORWARD       = "gtk-go-forward";
+const gchar* GTK_STOCK_GO_UP            = "gtk-go-up";
+const gchar* GTK_STOCK_HARDDISK         = "gtk-harddisk";
+const gchar* GTK_STOCK_HELP             = "gtk-help";
+const gchar* GTK_STOCK_HOME             = "gtk-home";
+const gchar* GTK_STOCK_INDEX            = "gtk-index";
+const gchar* GTK_STOCK_INDENT           = "gtk-indent";
+const gchar* GTK_STOCK_INFO             = "gtk-info";
+const gchar* GTK_STOCK_UNINDENT         = "gtk-unindent";
+const gchar* GTK_STOCK_ITALIC           = "gtk-italic";
+const gchar* GTK_STOCK_JUMP_TO          = "gtk-jump-to";
+const gchar* GTK_STOCK_JUSTIFY_CENTER   = "gtk-justify-center";
+const gchar* GTK_STOCK_JUSTIFY_FILL     = "gtk-justify-fill";
+const gchar* GTK_STOCK_JUSTIFY_LEFT     = "gtk-justify-left";
+const gchar* GTK_STOCK_JUSTIFY_RIGHT    = "gtk-justify-right";
+const gchar* GTK_STOCK_LEAVE_FULLSCREEN = "gtk-leave-fullscreen";
+const gchar* GTK_STOCK_MISSING_IMAGE    = "gtk-missing-image";
+const gchar* GTK_STOCK_MEDIA_FORWARD    = "gtk-media-forward";
+const gchar* GTK_STOCK_MEDIA_NEXT       = "gtk-media-next";
+const gchar* GTK_STOCK_MEDIA_PAUSE      = "gtk-media-pause";
+const gchar* GTK_STOCK_MEDIA_PLAY       = "gtk-media-play";
+const gchar* GTK_STOCK_MEDIA_PREVIOUS   = "gtk-media-previous";
+const gchar* GTK_STOCK_MEDIA_RECORD     = "gtk-media-record";
+const gchar* GTK_STOCK_MEDIA_REWIND     = "gtk-media-rewind";
+const gchar* GTK_STOCK_MEDIA_STOP       = "gtk-media-stop";
+const gchar* GTK_STOCK_NETWORK          = "gtk-network";
+const gchar* GTK_STOCK_NEW              = "gtk-new";
+const gchar* GTK_STOCK_NO               = "gtk-no";
+const gchar* GTK_STOCK_OK               = "gtk-ok";
+const gchar* GTK_STOCK_OPEN             = "gtk-open";
+const gchar* GTK_STOCK_ORIENTATION_PORTRAIT = "gtk-orientation-portrait";
+const gchar* GTK_STOCK_ORIENTATION_LANDSCAPE = "gtk-orientation-landscape";
+const gchar* GTK_STOCK_ORIENTATION_REVERSE_LANDSCAPE = "gtk-orientation-reverse-landscape";
+const gchar* GTK_STOCK_ORIENTATION_REVERSE_PORTRAIT = "gtk-orientation-reverse-portrait";
+const gchar* GTK_STOCK_PAGE_SETUP       = "gtk-page-setup";
+const gchar* GTK_STOCK_PASTE            = "gtk-paste";
+const gchar* GTK_STOCK_PREFERENCES      = "gtk-preferences";
+const gchar* GTK_STOCK_PRINT            = "gtk-print";
+const gchar* GTK_STOCK_PRINT_ERROR      = "gtk-print-error";
+const gchar* GTK_STOCK_PRINT_PAUSED     = "gtk-print-paused";
+const gchar* GTK_STOCK_PRINT_PREVIEW    = "gtk-print-preview";
+const gchar* GTK_STOCK_PRINT_REPORT     = "gtk-print-report";
+const gchar* GTK_STOCK_PRINT_WARNING    = "gtk-print-warning";
+const gchar* GTK_STOCK_PROPERTIES       = "gtk-properties";
+const gchar* GTK_STOCK_QUIT             = "gtk-quit";
+const gchar* GTK_STOCK_REDO             = "gtk-redo";
+const gchar* GTK_STOCK_REFRESH          = "gtk-refresh";
+const gchar* GTK_STOCK_REMOVE           = "gtk-remove";
+const gchar* GTK_STOCK_REVERT_TO_SAVED  = "gtk-revert-to-saved";
+const gchar* GTK_STOCK_SAVE             = "gtk-save";
+const gchar* GTK_STOCK_SAVE_AS          = "gtk-save-as";
+const gchar* GTK_STOCK_SELECT_ALL       = "gtk-select-all";
+const gchar* GTK_STOCK_SELECT_COLOR     = "gtk-select-color";
+const gchar* GTK_STOCK_SELECT_FONT      = "gtk-select-font";
+const gchar* GTK_STOCK_SORT_ASCENDING   = "gtk-sort-ascending";
+const gchar* GTK_STOCK_SORT_DESCENDING  = "gtk-sort-descending";
+const gchar* GTK_STOCK_SPELL_CHECK      = "gtk-spell-check";
+const gchar* GTK_STOCK_STOP             = "gtk-stop";
+const gchar* GTK_STOCK_STRIKETHROUGH    = "gtk-strikethrough";
+const gchar* GTK_STOCK_UNDELETE         = "gtk-undelete";
+const gchar* GTK_STOCK_UNDERLINE        = "gtk-underline";
+const gchar* GTK_STOCK_UNDO             = "gtk-undo";
+const gchar* GTK_STOCK_YES              = "gtk-yes";
+const gchar* GTK_STOCK_ZOOM_100         = "gtk-zoom-100";
+const gchar* GTK_STOCK_ZOOM_FIT         = "gtk-zoom-fit";
+const gchar* GTK_STOCK_ZOOM_IN          = "gtk-zoom-in";
+const gchar* GTK_STOCK_ZOOM_OUT         = "gtk-zoom-out";
+//}}}
+
+static this() {
+	auto lib = SharedLib.load("libgtk-x11-2.0.so.0");
+
+	//{{{ gtkmain
+	gtk_check_version = cast(typeof(gtk_check_version))lib.getSymbol("gtk_check_version");
+	gtk_parse_args = cast(typeof(gtk_parse_args))lib.getSymbol("gtk_parse_args");
+	gtk_init = cast(typeof(gtk_init))lib.getSymbol("gtk_init");
+	gtk_init_check = cast(typeof(gtk_init_check))lib.getSymbol("gtk_init_check");
+
+	gtk_events_pending = cast(typeof(gtk_events_pending))lib.getSymbol("gtk_events_pending");
+	//gtk_main_do_event = cast(typeof(gtk_main_do_event))lib.getSymbol("gtk_main_do_event");
+	gtk_main = cast(typeof(gtk_main))lib.getSymbol("gtk_main");
+	gtk_main_level = cast(typeof(gtk_main_level))lib.getSymbol("gtk_main_level");
+	gtk_main_quit = cast(typeof(gtk_main_quit))lib.getSymbol("gtk_main_quit");
+	gtk_main_iteration = cast(typeof(gtk_main_iteration))lib.getSymbol("gtk_main_iteration");
+	gtk_main_iteration_do = cast(typeof(gtk_main_iteration_do))lib.getSymbol("gtk_main_iteration_do");
+	//}}}
+
+	//{{{ gtkwidget
+	gtk_widget_destroy = cast(typeof(gtk_widget_destroy))lib.getSymbol("gtk_widget_destroy");
+	//}}}
+
+	//{{{ gtkdialog
+	gtk_dialog_get_type = cast(typeof(gtk_dialog_get_type))lib.getSymbol("gtk_dialog_get_type");
+	gtk_dialog_new = cast(typeof(gtk_dialog_new))lib.getSymbol("gtk_dialog_new");
+	gtk_dialog_new_with_buttons = cast(typeof(gtk_dialog_new_with_buttons))lib.getSymbol("gtk_dialog_new_with_buttons");
+	gtk_dialog_add_action_widget = cast(typeof(gtk_dialog_add_action_widget))lib.getSymbol("gtk_dialog_add_action_widget");
+	gtk_dialog_add_button = cast(typeof(gtk_dialog_add_button))lib.getSymbol("gtk_dialog_add_button");
+	gtk_dialog_add_buttons = cast(typeof(gtk_dialog_add_buttons))lib.getSymbol("gtk_dialog_add_buttons");
+	gtk_dialog_set_response_sensitive = cast(typeof(gtk_dialog_set_response_sensitive))lib.getSymbol("gtk_dialog_set_response_sensitive");
+	gtk_dialog_set_default_response = cast(typeof(gtk_dialog_set_default_response))lib.getSymbol("gtk_dialog_set_default_response");
+	gtk_dialog_get_response_for_widget = cast(typeof(gtk_dialog_get_response_for_widget))lib.getSymbol("gtk_dialog_get_response_for_widget");
+	gtk_dialog_set_has_separator = cast(typeof(gtk_dialog_set_has_separator))lib.getSymbol("gtk_dialog_set_has_separator");
+	gtk_dialog_get_has_separator = cast(typeof(gtk_dialog_get_has_separator))lib.getSymbol("gtk_dialog_get_has_separator");
+	//gtk_alternative_dialog_button_order = cast(typeof(gtk_alternative_dialog_button_order))lib.getSymbol("gtk_alternative_dialog_button_order");
+	gtk_dialog_set_alternative_button_order = cast(typeof(gtk_dialog_set_alternative_button_order))lib.getSymbol("gtk_dialog_set_alternative_button_order");
+	gtk_dialog_set_alternative_button_order_from_array = cast(typeof(gtk_dialog_set_alternative_button_order_from_array))lib.getSymbol("gtk_dialog_set_alternative_button_order_from_array");
+	gtk_dialog_response = cast(typeof(gtk_dialog_response))lib.getSymbol("gtk_dialog_response");
+	gtk_dialog_run = cast(typeof(gtk_dialog_run))lib.getSymbol("gtk_dialog_run");
+	//gtk_dialog_get_action_area = cast(typeof(gtk_dialog_get_action_area))lib.getSymbol("gtk_dialog_get_action_area");
+	//gtk_dialog_get_content_area = cast(typeof(gtk_dialog_get_content_area))lib.getSymbol("gtk_dialog_get_content_area");
+	//}}}
+
+	//{{{ gtkfilefilter
+	gtk_file_filter_get_type = cast(typeof(gtk_file_filter_get_type))lib.getSymbol("gtk_file_filter_get_type");
+	gtk_file_filter_new = cast(typeof(gtk_file_filter_new))lib.getSymbol("gtk_file_filter_new");
+	gtk_file_filter_set_name = cast(typeof(gtk_file_filter_set_name))lib.getSymbol("gtk_file_filter_set_name");
+	gtk_file_filter_get_name = cast(typeof(gtk_file_filter_get_name))lib.getSymbol("gtk_file_filter_get_name");
+	gtk_file_filter_add_mime_type = cast(typeof(gtk_file_filter_add_mime_type))lib.getSymbol("gtk_file_filter_add_mime_type");
+	gtk_file_filter_add_pattern = cast(typeof(gtk_file_filter_add_pattern))lib.getSymbol("gtk_file_filter_add_pattern");
+	gtk_file_filter_add_pixbuf_formats = cast(typeof(gtk_file_filter_add_pixbuf_formats))lib.getSymbol("gtk_file_filter_add_pixbuf_formats");
+	gtk_file_filter_add_custom = cast(typeof(gtk_file_filter_add_custom))lib.getSymbol("gtk_file_filter_add_custom");
+	gtk_file_filter_get_needed = cast(typeof(gtk_file_filter_get_needed))lib.getSymbol("gtk_file_filter_get_needed");
+	gtk_file_filter_filter = cast(typeof(gtk_file_filter_filter))lib.getSymbol("gtk_file_filter_filter");
+	//}}}
+
+	//{{{ gtkfilechooser
+	gtk_file_chooser_get_type = cast(typeof(gtk_file_chooser_get_type))lib.getSymbol("gtk_file_chooser_get_type");
+	gtk_file_chooser_error_quark = cast(typeof(gtk_file_chooser_error_quark))lib.getSymbol("gtk_file_chooser_error_quark");
+	gtk_file_chooser_set_action = cast(typeof(gtk_file_chooser_set_action))lib.getSymbol("gtk_file_chooser_set_action");
+	gtk_file_chooser_get_action = cast(typeof(gtk_file_chooser_get_action))lib.getSymbol("gtk_file_chooser_get_action");
+	gtk_file_chooser_set_local_only = cast(typeof(gtk_file_chooser_set_local_only))lib.getSymbol("gtk_file_chooser_set_local_only");
+	gtk_file_chooser_get_local_only = cast(typeof(gtk_file_chooser_get_local_only))lib.getSymbol("gtk_file_chooser_get_local_only");
+	gtk_file_chooser_set_select_multiple = cast(typeof(gtk_file_chooser_set_select_multiple))lib.getSymbol("gtk_file_chooser_set_select_multiple");
+	gtk_file_chooser_get_select_multiple = cast(typeof(gtk_file_chooser_get_select_multiple))lib.getSymbol("gtk_file_chooser_get_select_multiple");
+	gtk_file_chooser_set_show_hidden = cast(typeof(gtk_file_chooser_set_show_hidden))lib.getSymbol("gtk_file_chooser_set_show_hidden");
+	gtk_file_chooser_get_show_hidden = cast(typeof(gtk_file_chooser_get_show_hidden))lib.getSymbol("gtk_file_chooser_get_show_hidden");
+	gtk_file_chooser_set_do_overwrite_confirmation = cast(typeof(gtk_file_chooser_set_do_overwrite_confirmation))lib.getSymbol("gtk_file_chooser_set_do_overwrite_confirmation");
+	gtk_file_chooser_get_do_overwrite_confirmation = cast(typeof(gtk_file_chooser_get_do_overwrite_confirmation))lib.getSymbol("gtk_file_chooser_get_do_overwrite_confirmation");
+	gtk_file_chooser_set_current_name = cast(typeof(gtk_file_chooser_set_current_name))lib.getSymbol("gtk_file_chooser_set_current_name");
+	gtk_file_chooser_get_filename = cast(typeof(gtk_file_chooser_get_filename))lib.getSymbol("gtk_file_chooser_get_filename");
+	gtk_file_chooser_set_filename = cast(typeof(gtk_file_chooser_set_filename))lib.getSymbol("gtk_file_chooser_set_filename");
+	gtk_file_chooser_select_filename = cast(typeof(gtk_file_chooser_select_filename))lib.getSymbol("gtk_file_chooser_select_filename");
+	gtk_file_chooser_unselect_filename = cast(typeof(gtk_file_chooser_unselect_filename))lib.getSymbol("gtk_file_chooser_unselect_filename");
+	gtk_file_chooser_select_all = cast(typeof(gtk_file_chooser_select_all))lib.getSymbol("gtk_file_chooser_select_all");
+	gtk_file_chooser_unselect_all = cast(typeof(gtk_file_chooser_unselect_all))lib.getSymbol("gtk_file_chooser_unselect_all");
+	gtk_file_chooser_get_filenames = cast(typeof(gtk_file_chooser_get_filenames))lib.getSymbol("gtk_file_chooser_get_filenames");
+	gtk_file_chooser_set_current_folder = cast(typeof(gtk_file_chooser_set_current_folder))lib.getSymbol("gtk_file_chooser_set_current_folder");
+	gtk_file_chooser_get_current_folder = cast(typeof(gtk_file_chooser_get_current_folder))lib.getSymbol("gtk_file_chooser_get_current_folder");
+	gtk_file_chooser_get_uri = cast(typeof(gtk_file_chooser_get_uri))lib.getSymbol("gtk_file_chooser_get_uri");
+	gtk_file_chooser_set_uri = cast(typeof(gtk_file_chooser_set_uri))lib.getSymbol("gtk_file_chooser_set_uri");
+	gtk_file_chooser_select_uri = cast(typeof(gtk_file_chooser_select_uri))lib.getSymbol("gtk_file_chooser_select_uri");
+	gtk_file_chooser_unselect_uri = cast(typeof(gtk_file_chooser_unselect_uri))lib.getSymbol("gtk_file_chooser_unselect_uri");
+	gtk_file_chooser_get_uris = cast(typeof(gtk_file_chooser_get_uris))lib.getSymbol("gtk_file_chooser_get_uris");
+	gtk_file_chooser_set_current_folder_uri = cast(typeof(gtk_file_chooser_set_current_folder_uri))lib.getSymbol("gtk_file_chooser_set_current_folder_uri");
+	gtk_file_chooser_get_current_folder_uri = cast(typeof(gtk_file_chooser_get_current_folder_uri))lib.getSymbol("gtk_file_chooser_get_current_folder_uri");
+	/*
+	gtk_file_chooser_get_file = cast(typeof(gtk_file_chooser_get_file))lib.getSymbol("gtk_file_chooser_get_file");
+	gtk_file_chooser_set_file = cast(typeof(gtk_file_chooser_set_file))lib.getSymbol("gtk_file_chooser_set_file");
+	gtk_file_chooser_select_file = cast(typeof(gtk_file_chooser_select_file))lib.getSymbol("gtk_file_chooser_select_file");
+	gtk_file_chooser_unselect_file = cast(typeof(gtk_file_chooser_unselect_file))lib.getSymbol("gtk_file_chooser_unselect_file");
+	gtk_file_chooser_get_files = cast(typeof(gtk_file_chooser_get_files))lib.getSymbol("gtk_file_chooser_get_files");
+	gtk_file_chooser_set_current_folder_file = cast(typeof(gtk_file_chooser_set_current_folder_file))lib.getSymbol("gtk_file_chooser_set_current_folder_file");
+	gtk_file_chooser_get_current_folder_file = cast(typeof(gtk_file_chooser_get_current_folder_file))lib.getSymbol("gtk_file_chooser_get_current_folder_file");
+	gtk_file_chooser_set_preview_widget = cast(typeof(gtk_file_chooser_set_preview_widget))lib.getSymbol("gtk_file_chooser_set_preview_widget");
+	gtk_file_chooser_get_preview_widget = cast(typeof(gtk_file_chooser_get_preview_widget))lib.getSymbol("gtk_file_chooser_get_preview_widget");
+	gtk_file_chooser_set_preview_widget_active = cast(typeof(gtk_file_chooser_set_preview_widget_active))lib.getSymbol("gtk_file_chooser_set_preview_widget_active");
+	gtk_file_chooser_get_preview_widget_active = cast(typeof(gtk_file_chooser_get_preview_widget_active))lib.getSymbol("gtk_file_chooser_get_preview_widget_active");
+	gtk_file_chooser_set_use_preview_label = cast(typeof(gtk_file_chooser_set_use_preview_label))lib.getSymbol("gtk_file_chooser_set_use_preview_label");
+	gtk_file_chooser_get_use_preview_label = cast(typeof(gtk_file_chooser_get_use_preview_label))lib.getSymbol("gtk_file_chooser_get_use_preview_label");
+	gtk_file_chooser_get_preview_filename = cast(typeof(gtk_file_chooser_get_preview_filename))lib.getSymbol("gtk_file_chooser_get_preview_filename");
+	gtk_file_chooser_get_preview_uri = cast(typeof(gtk_file_chooser_get_preview_uri))lib.getSymbol("gtk_file_chooser_get_preview_uri");
+	gtk_file_chooser_get_preview_file = cast(typeof(gtk_file_chooser_get_preview_file))lib.getSymbol("gtk_file_chooser_get_preview_file");
+	gtk_file_chooser_set_extra_widget = cast(typeof(gtk_file_chooser_set_extra_widget))lib.getSymbol("gtk_file_chooser_set_extra_widget");
+	gtk_file_chooser_get_extra_widget = cast(typeof(gtk_file_chooser_get_extra_widget))lib.getSymbol("gtk_file_chooser_get_extra_widget");
+	*/
+	gtk_file_chooser_add_filter = cast(typeof(gtk_file_chooser_add_filter))lib.getSymbol("gtk_file_chooser_add_filter");
+	gtk_file_chooser_remove_filter = cast(typeof(gtk_file_chooser_remove_filter))lib.getSymbol("gtk_file_chooser_remove_filter");
+	gtk_file_chooser_list_filters = cast(typeof(gtk_file_chooser_list_filters))lib.getSymbol("gtk_file_chooser_list_filters");
+	gtk_file_chooser_set_filter = cast(typeof(gtk_file_chooser_set_filter))lib.getSymbol("gtk_file_chooser_set_filter");
+	gtk_file_chooser_get_filter = cast(typeof(gtk_file_chooser_get_filter))lib.getSymbol("gtk_file_chooser_get_filter");
+	gtk_file_chooser_add_shortcut_folder = cast(typeof(gtk_file_chooser_add_shortcut_folder))lib.getSymbol("gtk_file_chooser_add_shortcut_folder");
+	gtk_file_chooser_remove_shortcut_folder = cast(typeof(gtk_file_chooser_remove_shortcut_folder))lib.getSymbol("gtk_file_chooser_remove_shortcut_folder");
+	gtk_file_chooser_list_shortcut_folders = cast(typeof(gtk_file_chooser_list_shortcut_folders))lib.getSymbol("gtk_file_chooser_list_shortcut_folders");
+	gtk_file_chooser_add_shortcut_folder_uri = cast(typeof(gtk_file_chooser_add_shortcut_folder_uri))lib.getSymbol("gtk_file_chooser_add_shortcut_folder_uri");
+	gtk_file_chooser_remove_shortcut_folder_uri = cast(typeof(gtk_file_chooser_remove_shortcut_folder_uri))lib.getSymbol("gtk_file_chooser_remove_shortcut_folder_uri");
+	gtk_file_chooser_list_shortcut_folder_uris = cast(typeof(gtk_file_chooser_list_shortcut_folder_uris))lib.getSymbol("gtk_file_chooser_list_shortcut_folder_uris");
+	//}}}
+
+	//{{{ gtkfilechooserdialog
+	gtk_file_chooser_dialog_get_type = cast(typeof(gtk_file_chooser_dialog_get_type))lib.getSymbol("gtk_file_chooser_dialog_get_type");
+	gtk_file_chooser_dialog_new = cast(typeof(gtk_file_chooser_dialog_new))lib.getSymbol("gtk_file_chooser_dialog_new");
+	//}}}
+
+	//{{{ gtkstock
+	gtk_stock_add = cast(typeof(gtk_stock_add))lib.getSymbol("gtk_stock_add");
+	gtk_stock_add_static = cast(typeof(gtk_stock_add_static))lib.getSymbol("gtk_stock_add_static");
+	gtk_stock_lookup = cast(typeof(gtk_stock_lookup))lib.getSymbol("gtk_stock_lookup");
+	gtk_stock_list_ids = cast(typeof(gtk_stock_list_ids))lib.getSymbol("gtk_stock_list_ids");
+	gtk_stock_item_copy = cast(typeof(gtk_stock_item_copy))lib.getSymbol("gtk_stock_item_copy");
+	gtk_stock_item_free = cast(typeof(gtk_stock_item_free))lib.getSymbol("gtk_stock_item_free");
+	//gtk_stock_set_translate_func = cast(typeof(gtk_stock_set_translate_func))lib.getSymbol("gtk_stock_set_translate_func");
+	//}}}
+
+	gtk_init(null, null);
+}
--- a/dynamin/gui/directory_dialog.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/gui/directory_dialog.d	Fri Jul 24 00:35:42 2009 -0500
@@ -25,12 +25,8 @@
 
 module dynamin.gui.directory_dialog;
 
-import dynamin.c.windows;
 import dynamin.all_core;
-import dynamin.gui.window;
-import tango.io.Stdout;
-import Utf = tango.text.convert.Utf;
-//import std.c.windows.com;
+import dynamin.gui_backend;
 
 /**
  *
@@ -39,54 +35,27 @@
  *
  * $(IMAGE ../web/example_directory_dialog.png)
  */
-class DirectoryDialog { // use FILE_CHOOSER_ACTION_SELECT_FOLDER
+class DirectoryDialog { // TODO: rename to FolderDialog
 private:
+	mixin DirectoryDialogBackend;
+	string _text;
 	string _directory;
 public:
+	/// Gets or sets the text that is displayed in the dialog's title bar.
+	string text() { return _text; }
+	/// ditto
+	void text(string str) { _text = str; }
+
+	/// Gets or sets the selected directory.
 	string directory() {
 		return _directory;
 	}
+	/// ditto
 	void directory(string str) {
-		throw new Exception("Sorry, DirectoryDialog.directory(string) not yet working");
 		_directory = str;
 	}
 
 	DialogResult showDialog() {
-		BROWSEINFO bi;
-		//bi.hwndOwner = ;
-		bi.lpszTitle = "Choose a folder:";
-		bi.ulFlags |= BIF_RETURNONLYFSDIRS;
-		bi.ulFlags |= BIF_USENEWUI;
-
-		// TODO: I can't get this #!@#! COM stuff working...
-		//IShellFolder* shf;
-		//SHGetDesktopFolder(&shf);
-		//ITEMIDLIST* pidlInit;
-		//shf.ParseDisplayName(null, null, toWcharPointer(directory), null, &pidlInit, null);
-		//shf.Release();
-		//bi.pidlRoot = pidlInit;
-
-		ITEMIDLIST* pidl = SHBrowseForFolder(&bi);
-		//CoTaskMemFree(pidlInit);
-		if(!pidl)
-			return DialogResult.Cancel;
-		wchar[MAX_PATH+1] dirBuffer; // MAX_PATH is 260
-		if(!SHGetPathFromIDList(pidl, dirBuffer.ptr)) {
-			Stdout("GetPathFromIDList() failed").newline;
-			return DialogResult.Cancel;
-		}
-		CoTaskMemFree(pidl);
-		int index = MAX_PATH;
-		foreach(i, c; dirBuffer)
-			if(c == 0) { // find first null
-				index = i;
-				if(dirBuffer[i-1] != '\\') {
-					dirBuffer[i] = '\\';
-					index++;
-				}
-				break;
-			}
-		_directory = Utf.toString(dirBuffer[0..index]);
-		return DialogResult.OK;
+		return backend_showDialog();
 	}
 }
--- a/dynamin/gui/file_dialog.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/gui/file_dialog.d	Fri Jul 24 00:35:42 2009 -0500
@@ -143,7 +143,7 @@
 	void directory(string str) {
 		_directory = str;
 	}
-	/// TODO: Should this be SelectedDirectory ?
+	/// TODO: Should this be selectedDirectory ?
 	string directory() {
 		return _directory;
 	}
@@ -165,6 +165,26 @@
 	DialogResult showDialog() {
 		return backend_showDialog();
 	}
+	private void ensureAllFilesFilter() {
+		foreach(filter; _filters)
+			if(filter.extensions.length == 0)
+				return;
+		addFilter("All Files (*.*)");
+	}
+	private void maybeAddExt(ref string file) {
+		auto selFilter = _filters[selectedFilter];
+
+		// return if the "All Files (*.*)" filter is selected
+		if(selFilter.extensions.length == 0)
+			return;
+
+		// return if the file already has an extension from the selected filter
+		foreach(ext; selFilter.extensions)
+			if(file.downcase().endsWith(ext.downcase()))
+				return;
+
+		file ~= "." ~ selFilter.extensions[0].downcase();
+	}
 }
 
 ///
--- a/dynamin/gui/screen.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/gui/screen.d	Fri Jul 24 00:35:42 2009 -0500
@@ -62,7 +62,7 @@
 }
 
 } else {
-import dynamin.gui.backend;
+import dynamin.gui_backend;
 Rect desktopRect() { // TODO: move
 	int* data = cast(int*)getXWindowProperty(display,
 		XRootWindow(display, XDefaultScreen(display)), XA._NET_WORKAREA);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/gui/windows_directory_dialog.d	Fri Jul 24 00:35:42 2009 -0500
@@ -0,0 +1,70 @@
+// Written in the D programming language
+// www.digitalmars.com/d/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Dynamin library.
+ *
+ * The Initial Developer of the Original Code is Jordan Miner.
+ * Portions created by the Initial Developer are Copyright (C) 2006-2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jordan Miner <jminer7@gmail.com>
+ *
+ */
+
+module dynamin.gui.windows_directory_dialog;
+
+public import Utf = tango.text.convert.Utf;
+
+template DirectoryDialogBackend() {
+	DialogResult backend_showDialog() {
+		BROWSEINFO bi;
+		//bi.hwndOwner = ;
+		bi.lpszTitle = "Choose a folder:";
+		bi.ulFlags |= BIF_RETURNONLYFSDIRS;
+		bi.ulFlags |= BIF_USENEWUI;
+
+		// TODO: I can't get this #!@#! COM stuff working...
+		//IShellFolder* shf;
+		//SHGetDesktopFolder(&shf);
+		//ITEMIDLIST* pidlInit;
+		//shf.ParseDisplayName(null, null, toWcharPointer(directory), null, &pidlInit, null);
+		//shf.Release();
+		//bi.pidlRoot = pidlInit;
+
+		ITEMIDLIST* pidl = SHBrowseForFolder(&bi);
+		//CoTaskMemFree(pidlInit);
+		if(!pidl)
+			return DialogResult.Cancel;
+		wchar[MAX_PATH+1] dirBuffer; // MAX_PATH is 260
+		if(!SHGetPathFromIDList(pidl, dirBuffer.ptr)) {
+			Stdout("GetPathFromIDList() failed").newline;
+			return DialogResult.Cancel;
+		}
+		CoTaskMemFree(pidl);
+		int index = MAX_PATH;
+		foreach(i, c; dirBuffer)
+			if(c == 0) { // find first null
+				index = i;
+				if(dirBuffer[i-1] != '\\') {
+					dirBuffer[i] = '\\';
+					index++;
+				}
+				break;
+			}
+		_directory = Utf.toString(dirBuffer[0..index]);
+		return DialogResult.OK;
+	}
+}
+
--- a/dynamin/gui/windows_file_dialog.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/gui/windows_file_dialog.d	Fri Jul 24 00:35:42 2009 -0500
@@ -34,12 +34,7 @@
 		ofn.lStructSize = OPENFILENAME.sizeof;
 		//ofn.hwndOwner = ;
 
-		bool allFilesFilter = false;
-		foreach(filter; _filters)
-			if(filter.extensions.length == 0)
-				allFilesFilter = true;
-		if(!allFilesFilter) addFilter("All Files (*.*)");
-
+		ensureAllFilesFilter();
 		string filterStr;
 		foreach(filter; _filters) {
 			if(filter.shouldShow)
@@ -70,7 +65,7 @@
 		ofn.Flags |= OFN_FILEMUSTEXIST;
 		ofn.Flags |= OFN_HIDEREADONLY;
 		ofn.Flags |= OFN_OVERWRITEPROMPT;
-		if(_multipleSelection)
+		if(_multipleSelection && fileDialogType == Open)
 			ofn.Flags |= OFN_ALLOWMULTISELECT;
 
 		auto GetFileName = fileDialogType == Open ?
@@ -106,25 +101,13 @@
 					_files[i-1] = arr[i];
 				else
 					_files[i-1] = _directory ~ arr[i];
+				maybeAddExt(_files[i-1]);
 			}
 		} else { //single file
 			assert(filesBuffer.contains('\\'));
 			_directory = filesBuffer[0..filesBuffer.findLast("\\")].dup;
 			_files = [filesBuffer.dup];
-		}
-
-		// if "All Files (*.*)" filter is not selected
-		if(_filters[selectedFilter].extensions.length > 0) {
-			// go over every chosen file and add the selected filter's
-			// extension if the file doesn't already have one from the selected filter
-			for(int i = 0; i < _files.length; ++i) {
-				bool validExt = false;
-				foreach(ext; _filters[selectedFilter].extensions)
-					if(_files[i].downcase().endsWith(ext.downcase()))
-						validExt = true;
-				if(!validExt)
-					_files[i] ~= "." ~ _filters[selectedFilter].extensions[0].downcase();
-			}
+			maybeAddExt(_files[0]);
 		}
 
 		return DialogResult.OK;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/gui/x_directory_dialog.d	Fri Jul 24 00:35:42 2009 -0500
@@ -0,0 +1,55 @@
+// Written in the D programming language
+// www.digitalmars.com/d/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Dynamin library.
+ *
+ * The Initial Developer of the Original Code is Jordan Miner.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jordan Miner <jminer7@gmail.com>
+ *
+ */
+
+module dynamin.gui.x_directory_dialog;
+
+public import Utf = tango.text.convert.Utf;
+public import dynamin.c.glib;
+public import dynamin.c.gtk;
+
+template DirectoryDialogBackend() {
+	DialogResult backend_showDialog() {
+		string title = text ? text : "Select Folder";
+		auto dialog = gtk_file_chooser_dialog_new(toCharPtr(title), null,
+			GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+			GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, null);
+		if(_directory)
+			gtk_file_chooser_set_current_folder(dialog, toCharPtr(_directory));
+		scope(exit) {
+			gtk_widget_destroy(dialog);
+			while(gtk_events_pending())
+				gtk_main_iteration();
+		}
+		if(gtk_dialog_run(dialog) == GTK_RESPONSE_ACCEPT) {
+			char* folder = gtk_file_chooser_get_filename(dialog);
+			_directory = folder[0..strlen(folder)].dup;
+			g_free(folder);
+			return DialogResult.OK;
+		}
+		return DialogResult.Cancel;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dynamin/gui/x_file_dialog.d	Fri Jul 24 00:35:42 2009 -0500
@@ -0,0 +1,100 @@
+// Written in the D programming language
+// www.digitalmars.com/d/
+
+/*
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Dynamin library.
+ *
+ * The Initial Developer of the Original Code is Jordan Miner.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jordan Miner <jminer7@gmail.com>
+ *
+ */
+
+module dynamin.gui.x_file_dialog;
+
+public import Utf = tango.text.convert.Utf;
+public import dynamin.c.glib;
+public import dynamin.c.gtk;
+
+template FileDialogBackend() {
+	DialogResult backend_showDialog() {
+		// gdk_x11_get_server_time             (GdkWindow *window)
+		// could be used in clipboard
+
+		string title = text ? text : (fileDialogType == Open ? "Open" : "Save");
+		auto dialog = gtk_file_chooser_dialog_new(toCharPtr(title), null,
+			fileDialogType == Open ?
+			GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE,
+			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+			fileDialogType == Open ? GTK_STOCK_OPEN : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, null);
+
+		ensureAllFilesFilter();
+		foreach(i, filter; _filters) {
+			if(filter.shouldShow) // TODO:
+				continue;
+			auto gfilter = gtk_file_filter_new();
+			gtk_file_filter_set_name(gfilter, toCharPtr(filter.name));
+
+			if(filter.extensions.length == 0)
+				gtk_file_filter_add_pattern(gfilter, "*");
+			else foreach(ext; filter.extensions)
+				gtk_file_filter_add_pattern(gfilter, toCharPtr("*."~ext));
+
+			gtk_file_chooser_add_filter(dialog, gfilter);
+			if(selectedFilter == i)
+				gtk_file_chooser_set_filter(dialog, gfilter);
+		}
+
+		if(fileDialogType == Open)
+			gtk_file_chooser_set_select_multiple(dialog, multipleSelection);
+		gtk_file_chooser_set_do_overwrite_confirmation(dialog, true);
+		if(_directory)
+			gtk_file_chooser_set_current_folder(dialog, toCharPtr(_directory));
+		if(_initialFileName)
+			gtk_file_chooser_set_current_name(dialog, toCharPtr(_initialFileName));
+
+		scope(exit) {
+			gtk_widget_destroy(dialog);
+			while(gtk_events_pending())
+				gtk_main_iteration();
+		}
+		if(gtk_dialog_run(dialog) == GTK_RESPONSE_ACCEPT) {
+			auto gfilters = gtk_file_chooser_list_filters(dialog);
+			_selectedFilter = g_slist_index(gfilters,
+				gtk_file_chooser_get_filter(dialog));
+			g_slist_free(gfilters);
+
+			auto list = gtk_file_chooser_get_filenames(dialog);
+			_files = new string[g_slist_length(list)];
+			for(int i = 0; i < _files.length; ++i) {
+				auto d = cast(char*)list.data;
+				_files[i] = d[0..strlen(d)].dup;
+				maybeAddExt(_files[i]);
+				g_free(list.data);
+				list = g_slist_next(list);
+			}
+			g_slist_free(list);
+
+			char* fold = gtk_file_chooser_get_current_folder(dialog);
+			_directory = fold[0..strlen(fold)].dup;
+			g_free(fold);
+
+			return DialogResult.OK;
+		}
+		return DialogResult.Cancel;
+	}
+}
+
--- a/dynamin/gui/x_window.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/gui/x_window.d	Fri Jul 24 00:35:42 2009 -0500
@@ -436,6 +436,13 @@
 			}
 		}
 	}
+	void backend_invoke(void delegate() dg) {
+		// TODO:
+	}
+	void backend_invokeNow(void delegate() dg) {
+		// TODO:
+	}
+
 }
 //}}}
 
--- a/dynamin/gui_backend.d	Sat Jul 18 21:32:19 2009 -0500
+++ b/dynamin/gui_backend.d	Fri Jul 24 00:35:42 2009 -0500
@@ -28,15 +28,15 @@
 version(Windows) {
 	public import dynamin.gui.windows_clipboard;
 	public import dynamin.gui.windows_cursor;
-	//public import dynamin.gui.windows_directory_dialog;
+	public import dynamin.gui.windows_directory_dialog;
 	public import dynamin.gui.windows_file_dialog;
 	//public import dynamin.gui.windows_screen;
 	public import dynamin.gui.windows_window;
 } else {
 	public import dynamin.gui.x_clipboard;
 	public import dynamin.gui.x_cursor;
-	//public import dynamin.gui.x_directory_dialog;
-	//public import dynamin.gui.x_file_dialog;
+	public import dynamin.gui.x_directory_dialog;
+	public import dynamin.gui.x_file_dialog;
 	//public import dynamin.gui.x_screen;
 	public import dynamin.gui.x_window;
 }