balsa r8035 - in trunk: . libbalsa src



Author: pawels
Date: Fri Jan  2 18:05:59 2009
New Revision: 8035
URL: http://svn.gnome.org/viewvc/balsa?rev=8035&view=rev

Log:
* configure.in: prefer gio >= 2.16.0, fallback to gnome-vfs.
* libbalsa/gmime-stream-gnome-vfs.[hc]: build only if using gnome-vfs 
* libbalsa/files.[hc]: implement icon lookup for gio
* libbalsa/libbalsa-vfs.[hc]:  add support for GIO
* libbalsa/gmime-stream-gio.[hc]: gmime gio stream wrapper.
* libbalsa/misc.c: remove unnecessary #include of gnome-vfs.h
* libbalsa/Makefile.am: add gmime-stream-gio.[hc]
* src/balsa-print-object-default.c: use libbalsa-vfs instead of
  gnome-vfs, enabling in this way a clean GIO usage.
* src/sendmsg-window.c: call external editor through gio or gnome-vfs
  use libbalsa-vfs helper to open attachment with external app;
  show description in attachment list.
* src/balsa-mime-widget-callbacks.[ch]: use libbalsa-vfs to open parts
* src/balsa-mime-widget-text.c: use changed balsa-mime-widget-callbacks API.
* src/ab-window.c: launch app using glib
* src/balsa-message.c: use description instead of plain MIME type.
* src/balsa-mime-widget.c: create a mime button via libbalsa-vfs.


Added:
   trunk/libbalsa/gmime-stream-gio.c
   trunk/libbalsa/gmime-stream-gio.h
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/libbalsa/Makefile.am
   trunk/libbalsa/files.c
   trunk/libbalsa/files.h
   trunk/libbalsa/gmime-stream-gnome-vfs.c
   trunk/libbalsa/gmime-stream-gnome-vfs.h
   trunk/libbalsa/libbalsa-vfs.c
   trunk/libbalsa/libbalsa-vfs.h
   trunk/libbalsa/misc.c
   trunk/src/ab-main.c
   trunk/src/ab-window.c
   trunk/src/balsa-icons.c
   trunk/src/balsa-icons.h
   trunk/src/balsa-index.c
   trunk/src/balsa-mblist.c
   trunk/src/balsa-message.c
   trunk/src/balsa-mime-widget-callbacks.c
   trunk/src/balsa-mime-widget-callbacks.h
   trunk/src/balsa-mime-widget-text.c
   trunk/src/balsa-mime-widget.c
   trunk/src/balsa-print-object-default.c
   trunk/src/balsa-print-object-text.c
   trunk/src/filter-edit-dialog.c
   trunk/src/information-dialog.c
   trunk/src/mailbox-conf.c
   trunk/src/main-window.c
   trunk/src/quote-color.c
   trunk/src/save-restore.c
   trunk/src/sendmsg-window.c
   trunk/src/store-address.c
   trunk/src/toolbar-factory.c
   trunk/src/toolbar-prefs.c

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Fri Jan  2 18:05:59 2009
@@ -281,12 +281,33 @@
 		   [Path to sendmail program.])
 fi
 
+# GIO in glib 2.16.0 and above
+AC_MSG_CHECKING([for gio >= 2.16])
+if $PKG_CONFIG --atleast-version=2.16.0 gio-2.0 ; then
+   with_gio=yes
+   gio_extra=gio-2.0
+   AC_DEFINE(HAVE_GIO,1,[Defined when GIO can be used.])
+   giover=`$PKG_CONFIG --modversion gio-2.0`
+   AC_MSG_RESULT($giover)
+else
+   with_gio=no
+   AC_MSG_RESULT($with_gio)
+fi
+
 dnl #####################################################################
 dnl GNOME libs
 dnl #####################################################################
 if test x$with_gnome != xno; then
-   gnome_extras="libgnome-2.0 libgnomeui-2.0 
-   gnome-vfs-2.0 gnome-vfs-module-2.0 libbonobo-2.0"
+   gnome_extras="libgnome-2.0 libgnomeui-2.0 libbonobo-2.0"
+   if test x$with_gio != xyes ; then
+      gnome_extras="$gnome_extras gnome-vfs-2.0 >= 2.4.0 gnome-vfs-module-2.0"
+      AC_DEFINE(HAVE_GNOME_VFS,1,
+	        [Defined when gnome-vfs shall be used])
+      if $PKG_CONFIG --atleast-version=2.9.0 gnome-vfs-2.0 ; then
+         AC_DEFINE(HAVE_GNOME_VFS29,1,
+	           [Defined when gnome-vfs-2.0 version is at least 2.9.0])
+      fi
+   fi
    gnome_print_extras="libgnomeprint-2.2 >= 2.1.4 libgnomeprintui-2.2 >= 2.1.4"
    AC_MSG_CHECKING([whether we have gnome-keyring])
    if $PKG_CONFIG --atleast-version=1.0 gnome-keyring-1; then
@@ -351,6 +372,8 @@
 glib-2.0
 gtk+-2.0 >= 2.4
 gmime-2.0 >= 2.1.9
+gconf-2.0
+$gio_extra
 $gnome_extras
 $gnome_print_extras
 ])
@@ -366,13 +389,6 @@
 dnl Check versions
 dnl ##########################################################################
 
-if test x$with_gnome != xno; then
-  if $PKG_CONFIG --atleast-version=2.9.0 gnome-vfs-2.0 ; then
-    AC_DEFINE(HAVE_GNOME_VFS29,1,
-	      [Defined when gnome-vfs-2.0 version is at least 2.9.0])
-  fi
-fi
-
 # CORBA interface.
 #
                                                                         
@@ -977,6 +993,8 @@
 echo "   Enable compile warnings: $set_more_warnings"
 echo "                Use ESMTP : $with_esmtp"
 echo " Use WebKit (experimental): $use_webkit"
+echo "                 Use GNOME: $with_gnome"
+echo "                   Use GIO: $with_gio"
 echo "               Use GtkHTML: $use_gtkhtml"
 echo "                 Use GPGME: $gpgmecfg"
 echo "                  Use LDAP: $with_ldap"

Modified: trunk/libbalsa/Makefile.am
==============================================================================
--- trunk/libbalsa/Makefile.am	(original)
+++ trunk/libbalsa/Makefile.am	Fri Jan  2 18:05:59 2009
@@ -76,6 +76,8 @@
 	folder-scanners.h	\
 	gmime-stream-gnome-vfs.c\
 	gmime-stream-gnome-vfs.h\
+	gmime-stream-gio.c      \
+	gmime-stream-gio.h      \
 	html.c                  \
 	html.h                  \
 	identity.c		\

Modified: trunk/libbalsa/files.c
==============================================================================
--- trunk/libbalsa/files.c	(original)
+++ trunk/libbalsa/files.c	Fri Jan  2 18:05:59 2009
@@ -24,17 +24,22 @@
 #include <ctype.h>
 #include <string.h>
 
-#ifdef HAVE_GNOME
+#if HAVE_GIO
+#include <gio/gio.h>
+#endif
+
+#if HAVE_GNOME
 #include <gnome.h>
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#endif
+#if HAVE_GNOME_VFS
 #include <libgnomevfs/gnome-vfs-mime-info.h>
 #include <libgnomevfs/gnome-vfs.h>
 #endif
 
 #include "misc.h"
+#include "libbalsa.h"
 #include "files.h"
 #include <glib/gi18n.h>
-#include "libbalsa-vfs.h"
 
 static const gchar *permanent_prefixes[] = {
 /*	BALSA_DATA_PREFIX,
@@ -140,10 +145,12 @@
     gchar *icon = NULL;
     GdkPixbuf *pixbuf = NULL;
     gint width, height;
-#ifdef HAVE_GNOME
+    const gchar * filename = NULL;
+#if HAVE_GIO
+    GtkIconTheme *icon_theme;
+#elif HAVE_GNOME
     const char *icon_file;
     GtkIconTheme *icon_theme;
-    const gchar * filename = NULL;
 #endif
 
     if (!gtk_icon_size_lookup(size, &width, &height))
@@ -157,7 +164,47 @@
     } else
 	content_type = g_strdup("application/octet-stream");
 
-#ifdef HAVE_GNOME
+#if HAVE_GIO
+    /* ask GIO for the icon */
+    if ((icon_theme = gtk_icon_theme_get_default())) {
+        GIcon * icon = g_content_type_get_icon(content_type);
+
+        if (icon && G_IS_THEMED_ICON(icon)) {
+            int i = 0;
+            GStrv icon_names;
+
+            g_object_get(G_OBJECT(icon), "names", &icon_names, NULL);
+            while (!pixbuf && icon_names && icon_names[i]) {
+                pixbuf = gtk_icon_theme_load_icon(icon_theme, icon_names[i],
+                                                  width, 0, NULL);
+                i++;
+            }
+            g_strfreev(icon_names);
+            g_object_unref(icon);
+            
+            /* last resort: try gnome-mime-<base mime type> */
+            if (!pixbuf) {
+                gchar * base_type_icon = g_strdup_printf("gnome-mime-%s", content_type);
+                gchar * slash = strchr(base_type_icon, '/');
+
+                if (slash)
+                    *slash = '\0';
+                pixbuf = gtk_icon_theme_load_icon(icon_theme, base_type_icon,
+                                                   width, 0, NULL);
+                g_free(base_type_icon);
+            }
+
+            /* return if we found a proper pixbuf */
+	    if (pixbuf) {
+		if (used_type)
+		    *used_type = content_type;
+		else 
+		    g_free(content_type);
+		return pixbuf;
+	    }
+        }
+    }
+#elif HAVE_GNOME
     /* gtk+ 2.4.0 and above: use the default icon theme to get the icon */
     if ((icon_theme = gtk_icon_theme_get_default()))
 	if ((icon =
@@ -175,11 +222,8 @@
 	    }
 	}
 
-#if 0
-    icon_file = gnome_vfs_mime_get_icon(content_type);
-#else
+#if HAVE_GNOME_VFS
     icon_file = gnome_vfs_mime_get_value(content_type, "icon_filename");
-#endif
     
     /* check if the icon file is good and try harder otherwise */
     if (icon_file && g_file_test (icon_file, G_FILE_TEST_IS_REGULAR))
@@ -201,7 +245,9 @@
 	
 	g_free (gnome_icon);
     }
+#endif /* HAVE_GNOME_VFS */
 #endif /* HAVE_GNOME */
+
     /* load the pixbuf */
     if (icon == NULL)
 	pixbuf = libbalsa_default_attachment_pixbuf(width);
@@ -225,49 +271,3 @@
     
     return pixbuf;
 }
-
-#ifdef HAVE_GNOME
-static void 
-add_vfs_menu_item(GtkMenu * menu, const GnomeVFSMimeApplication *app,
-		  GCallback callback, gpointer data)
-{
-    gchar *menu_label = g_strdup_printf(_("Open with %s"), app->name);
-    GtkWidget *menu_item = gtk_menu_item_new_with_label (menu_label);
-    
-    g_object_set_data_full(G_OBJECT (menu_item), "mime_action", 
-			   g_strdup(app->id), g_free);
-    g_signal_connect(G_OBJECT (menu_item), "activate", callback, data);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
-    g_free (menu_label);
-}
-#endif /* HAVE_GNOME */
-/* helper: fill the passed menu with vfs items */
-void
-libbalsa_fill_vfs_menu_by_content_type(GtkMenu * menu,
-				       const gchar * content_type,
-				       GCallback callback, gpointer data)
-{
-#ifdef HAVE_GNOME
-    GList* list;
-    GnomeVFSMimeApplication *def_app;
-    GList *app_list;
-    
-    g_return_if_fail(data != NULL);
-
-    if((def_app=gnome_vfs_mime_get_default_application(content_type))) {
-        add_vfs_menu_item(menu, def_app, callback, data);
-    }
-    
-
-    app_list = gnome_vfs_mime_get_all_applications(content_type);
-    for (list = app_list; list; list = list->next) {
-        GnomeVFSMimeApplication *app = list->data;
-        if (app && (!def_app || strcmp(app->name, def_app->name) != 0))
-            add_vfs_menu_item(menu, app, callback, data);
-    }
-    gnome_vfs_mime_application_free(def_app);
-    
-    gnome_vfs_mime_application_list_free (app_list);
-#endif /* HAVE_GNOME */
-}
-

Modified: trunk/libbalsa/files.h
==============================================================================
--- trunk/libbalsa/files.h	(original)
+++ trunk/libbalsa/files.h	Fri Jan  2 18:05:59 2009
@@ -47,8 +47,4 @@
 GdkPixbuf *libbalsa_icon_finder(const char *mime_type, const LibbalsaVfs * for_file,
 				gchar** used_type, GtkIconSize size);
 
-void libbalsa_fill_vfs_menu_by_content_type(GtkMenu * menu,
-					    const gchar * content_type,
-					    GCallback callback, gpointer data);
-
 #endif

Added: trunk/libbalsa/gmime-stream-gio.c
==============================================================================
--- (empty file)
+++ trunk/libbalsa/gmime-stream-gio.c	Fri Jan  2 18:05:59 2009
@@ -0,0 +1,486 @@
+/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
+/*  GMime GIO stream module
+ *  Written/Copyright (c) by Albrecht Dreß<albrecht dress arcor de>
+ *  The basic structure of this file has been shamelessly stolen from the
+ *  gmime-stream-fs module, written by Jeffrey Stedfast.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "config.h"
+
+/* note: this module will be compiled only if GIO is available */
+#if HAVE_GIO
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "gmime-stream-gio.h"
+
+
+static void g_mime_stream_gio_class_init(GMimeStreamGioClass *klass);
+static void g_mime_stream_gio_init(GMimeStreamGio *stream,
+				   GMimeStreamGioClass *klass);
+static void g_mime_stream_gio_finalize(GObject *object);
+
+static ssize_t stream_read(GMimeStream *stream,
+			   char *buf,
+			   size_t len);
+static ssize_t stream_write(GMimeStream *stream,
+			    const char *buf,
+			    size_t len);
+static int stream_flush(GMimeStream *stream);
+static int stream_close(GMimeStream *stream);
+static gboolean stream_eos(GMimeStream *stream);
+static int stream_reset(GMimeStream *stream);
+static gint64 stream_seek(GMimeStream *stream,
+			  gint64 offset,
+			  GMimeSeekWhence whence);
+static gint64 stream_tell(GMimeStream *stream);
+static ssize_t stream_length(GMimeStream *stream);
+static GMimeStream *stream_substream(GMimeStream *stream,
+				     gint64 start,
+				     gint64 end);
+
+
+static GMimeStreamClass *parent_class = NULL;
+
+#define GIO_DEBUG  1
+
+#ifdef GIO_DEBUG
+#define GIO_DEBUG_INIT   GError * gioerr = NULL
+#define GIO_DEBUG_OUT    &gioerr
+#define GIO_DEBUG_MSG(textmsg)						\
+    do {								\
+	if (gioerr) {							\
+	    g_debug("%s::%s::%d " textmsg ": err %d: %s\n",		\
+		    __FILE__, __FUNCTION__, __LINE__,			\
+		    gioerr->code, gioerr->message);			\
+	    g_error_free(gioerr);					\
+	    gioerr = NULL;						\
+	}								\
+    } while(0)
+#else
+#define GIO_DEBUG_INIT
+#define GIO_DEBUG_OUT    NULL
+#define GIO_DEBUG_MSG    
+#endif
+
+
+GType
+g_mime_stream_gio_get_type(void)
+{
+    static GType type = 0;
+	
+    if (!type) {
+	static const GTypeInfo info = {
+	    sizeof (GMimeStreamGioClass),
+	    NULL, /* base_class_init */
+	    NULL, /* base_class_finalize */
+	    (GClassInitFunc) g_mime_stream_gio_class_init,
+	    NULL, /* class_finalize */
+	    NULL, /* class_data */
+	    sizeof (GMimeStreamGio),
+	    0,    /* n_preallocs */
+	    (GInstanceInitFunc) g_mime_stream_gio_init,
+	};
+		
+	type = g_type_register_static(GMIME_TYPE_STREAM, "GMimeStreamGio", &info, 0);
+    }
+	
+    return type;
+}
+
+
+static void
+g_mime_stream_gio_class_init(GMimeStreamGioClass *klass)
+{
+    GMimeStreamClass *stream_class = GMIME_STREAM_CLASS(klass);
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+	
+    parent_class = g_type_class_ref(GMIME_TYPE_STREAM);
+	
+    object_class->finalize = g_mime_stream_gio_finalize;
+	
+    stream_class->read = stream_read;
+    stream_class->write = stream_write;
+    stream_class->flush = stream_flush;
+    stream_class->close = stream_close;
+    stream_class->eos = stream_eos;
+    stream_class->reset = stream_reset;
+    stream_class->seek = stream_seek;
+    stream_class->tell = stream_tell;
+    stream_class->length = stream_length;
+    stream_class->substream = stream_substream;
+}
+
+static void
+g_mime_stream_gio_init(GMimeStreamGio *stream,
+		       GMimeStreamGioClass *klass)
+{
+    stream->eos = FALSE;
+    stream->gfile = NULL;
+    stream->stream = NULL;
+}
+
+static void
+g_mime_stream_gio_finalize(GObject *object)
+{
+    GMimeStreamGio *stream = (GMimeStreamGio *) object;
+    
+    g_return_if_fail(stream);
+    if (stream->stream) {
+	g_object_unref(stream->stream);  // will also call g_(input|output)_stream_close
+	stream->stream = NULL;
+    }
+    
+    if (stream->gfile)
+	g_object_unref(G_OBJECT(stream->gfile));
+
+    G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static ssize_t
+stream_read(GMimeStream *stream, char *buf, size_t len)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+    gsize nread;
+    gboolean result;
+    GIO_DEBUG_INIT;
+	
+    g_return_val_if_fail(stream, -1);
+    if (stream->bound_end != -1 && stream->position >= stream->bound_end)
+	return -1;
+	
+    if (stream->bound_end != -1)
+	len = MIN (stream->bound_end - stream->position, (gint64) len);
+    
+    /* try to create the stream if necessary */
+    if (!gios->stream) {
+	gios->stream = G_OBJECT(g_file_read(gios->gfile, NULL, GIO_DEBUG_OUT));
+	GIO_DEBUG_MSG("g_file_read");
+	if (!gios->stream)
+	    return -1;
+    }
+
+    /* make sure we are at the right position */
+    g_seekable_seek(G_SEEKABLE(gios->stream), (goffset) stream->position,
+		    G_SEEK_SET, NULL, NULL);
+
+    result = g_input_stream_read_all(G_INPUT_STREAM(gios->stream), buf, len, 
+				     &nread, NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_input_stream_read_all");
+	
+    if (result)
+	stream->position += nread;
+    if (nread == 0)
+	gios->eos = TRUE;
+	
+    return nread;
+}
+
+static ssize_t
+stream_write(GMimeStream *stream, const char *buf, size_t len)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+    gsize nwritten;
+    gboolean result;
+    GIO_DEBUG_INIT;
+	
+    g_return_val_if_fail(stream, -1);
+    if (stream->bound_end != -1 && stream->position >= stream->bound_end)
+	return -1;
+	
+    if (stream->bound_end != -1)
+	len = MIN (stream->bound_end - stream->position, (gint64) len);
+    
+    /* try to create the stream if necessary */
+    if (!gios->stream) {
+	gios->stream = G_OBJECT(g_file_append_to(gios->gfile, G_FILE_CREATE_NONE, NULL, GIO_DEBUG_OUT));
+	GIO_DEBUG_MSG("g_file_append_to");
+	if (!gios->stream)
+	    return -1;
+    }
+	
+    /* make sure we are at the right position */
+    g_seekable_seek(G_SEEKABLE(gios->stream), (goffset) stream->position,
+		    G_SEEK_SET, NULL, NULL);
+    
+    result = g_output_stream_write_all(G_OUTPUT_STREAM(gios->stream), buf, len,
+				       &nwritten, NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_output_stream_write_all");
+	
+    if (result)
+	stream->position += nwritten;
+    else 
+	return -1;
+	
+    return nwritten;
+}
+
+static int
+stream_flush(GMimeStream *stream)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+    gboolean result;
+    GIO_DEBUG_INIT;
+    
+    g_return_val_if_fail(stream, -1);
+    g_return_val_if_fail(G_IS_OUTPUT_STREAM(gios->stream), -1);
+    result = g_output_stream_flush(G_OUTPUT_STREAM(gios->stream), NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_output_stream_flush");
+    return result ? 0 : -1;
+}
+
+static int
+stream_close(GMimeStream *stream)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+
+    g_return_val_if_fail(stream, -1);
+    if (gios->stream) {
+	g_object_unref(gios->stream);
+	gios->stream = NULL;
+    }
+    
+    return 0;
+}
+
+static gboolean
+stream_eos(GMimeStream *stream)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+	
+    g_return_val_if_fail(stream, TRUE);
+    if (gios->stream)
+        g_return_val_if_fail(G_IS_INPUT_STREAM(gios->stream), TRUE);
+	
+    return gios->eos;
+}
+
+static int
+stream_reset(GMimeStream *stream)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+    gboolean result;
+    GIO_DEBUG_INIT;
+
+    g_return_val_if_fail(stream, -1);
+    if (!gios->stream)
+	return -1;
+	
+    if (stream->position == stream->bound_start) {
+	gios->eos = FALSE;
+	return 0;
+    }
+    
+    result = g_seekable_seek(G_SEEKABLE(gios->stream), (goffset)stream->bound_start,
+			     G_SEEK_SET, NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_seekable_seek");
+
+    if (!result)
+	return -1;
+	
+    gios->eos = FALSE;
+    return 0;
+}
+
+static gint64
+stream_seek(GMimeStream *stream, gint64 offset, GMimeSeekWhence whence)
+{
+    GMimeStreamGio *gios = (GMimeStreamGio *) stream;
+    goffset real;
+    gboolean result;
+    GIO_DEBUG_INIT;
+	
+    g_return_val_if_fail(stream, -1);
+    g_return_val_if_fail(gios->stream, -1);
+	
+    switch (whence) {
+    case GMIME_STREAM_SEEK_SET:
+	real = offset;
+	break;
+    case GMIME_STREAM_SEEK_CUR:
+	real = stream->position + offset;
+	break;
+    case GMIME_STREAM_SEEK_END:
+	if (offset > 0 || (stream->bound_end == -1 && !gios->eos)) {
+	    /* need to do an actual lseek() here because
+	     * we either don't know the offset of the end
+	     * of the stream and/or don't know if we can
+	     * seek past the end */
+	    result = g_seekable_seek(G_SEEKABLE(gios->stream), (goffset)offset,
+				     G_SEEK_END, NULL, GIO_DEBUG_OUT);
+	    GIO_DEBUG_MSG("g_seekable_seek");
+	    if (!result)
+		return -1;
+	    else
+		real = g_seekable_tell(G_SEEKABLE(gios->stream));
+	} else if (gios->eos && stream->bound_end == -1) {
+	    /* seeking backwards from eos (which happens
+	     * to be our current position) */
+	    real = stream->position + offset;
+	} else {
+	    /* seeking backwards from a known position */
+	    real = stream->bound_end + offset;
+	}
+		
+	break;
+    default:
+	g_assert_not_reached ();
+	return -1;
+    }
+	
+    /* sanity check the resultant offset */
+    if (real < stream->bound_start)
+	return -1;
+	
+    /* short-cut if we are seeking to our current position */
+    if (real == stream->position)
+	return real;
+	
+    if (stream->bound_end != -1 && real > stream->bound_end)
+	return -1;
+    
+    result = g_seekable_seek(G_SEEKABLE(gios->stream), (goffset) real,
+			     G_SEEK_SET, NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_seekable_seek");
+    if (!result)
+	return -1;
+    real = g_seekable_tell(G_SEEKABLE(gios->stream));
+	
+    /* reset eos if appropriate */
+    if ((stream->bound_end != -1 && real < stream->bound_end) ||
+	(gios->eos && real < stream->position))
+	gios->eos = FALSE;
+	
+    stream->position = real;
+	
+    return real;
+}
+
+static gint64
+stream_tell (GMimeStream *stream)
+{
+    g_return_val_if_fail(stream, -1);
+    return stream->position;
+}
+
+static ssize_t
+stream_length(GMimeStream *stream)
+{
+    goffset bound_end;
+    GFileInputStream *istream;
+    gboolean sres;
+    GIO_DEBUG_INIT;
+	
+    g_return_val_if_fail(stream, -1);
+    if (stream->bound_end != -1)
+	return stream->bound_end - stream->bound_start;
+    
+    istream = g_file_read(GMIME_STREAM_GIO(stream)->gfile, NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_file_read");
+    if (!istream)
+	return -1;
+
+    sres = g_seekable_seek(G_SEEKABLE(istream), (goffset) 0, G_SEEK_END, NULL, GIO_DEBUG_OUT);
+    GIO_DEBUG_MSG("g_seekable_seek");
+    if (!sres) {
+	g_object_unref(istream);
+	return -1;
+    }
+    bound_end = g_seekable_tell(G_SEEKABLE(istream));
+    g_object_unref(istream);
+	
+    if (bound_end < stream->bound_start)
+	return -1;
+	
+    return bound_end - stream->bound_start;
+}
+
+static GMimeStream *
+stream_substream(GMimeStream *stream, gint64 start, gint64 end)
+{
+    GMimeStreamGio *gios;
+	
+    g_return_val_if_fail(stream, NULL);
+    gios = g_object_newv(GMIME_TYPE_STREAM_GIO, 0, NULL);
+    g_mime_stream_construct (GMIME_STREAM(gios), start, end);
+    gios->gfile = GMIME_STREAM_GIO(stream)->gfile;
+    g_object_ref(G_OBJECT(gios->gfile));
+    gios->eos = FALSE;
+    gios->stream = NULL;
+	
+    return (GMimeStream *) gios;
+}
+
+
+/**
+ * g_mime_stream_gio_new:
+ * @gfile: GIO File
+ *
+ * Creates a new #GMimeStreamGio object around @gfile.
+ *
+ * Returns: a stream using @fd.
+ **/
+GMimeStream *
+g_mime_stream_gio_new(GFile * gfile)
+{
+    GMimeStreamGio *gios;
+	
+    g_return_val_if_fail(gfile, NULL);
+    gios = g_object_newv (GMIME_TYPE_STREAM_GIO, 0, NULL);
+    g_mime_stream_construct(GMIME_STREAM (gios), 0, -1);
+    gios->eos = FALSE;
+    gios->gfile = gfile;
+    g_object_ref(G_OBJECT(gios->gfile));
+    gios->stream = NULL;
+	
+    return (GMimeStream *) gios;
+}
+
+
+/**
+ * g_mime_stream_gio_new_with_bounds:
+ * @fd: file descriptor
+ * @start: start boundary
+ * @end: end boundary
+ *
+ * Creates a new #GMimeStreamGio object around @fd with bounds @start
+ * and @end.
+ *
+ * Returns: a stream using @fd with bounds @start and @end.
+ **/
+GMimeStream *
+g_mime_stream_gio_new_with_bounds(GFile * gfile, gint64 start, gint64 end)
+{
+    GMimeStreamGio *gios;
+	
+    g_return_val_if_fail(gfile, NULL);
+    gios = g_object_newv (GMIME_TYPE_STREAM_GIO, 0, NULL);
+    g_mime_stream_construct (GMIME_STREAM (gios), start, end);
+    gios->eos = FALSE;
+    gios->gfile = gfile;
+    g_object_ref(G_OBJECT(gios->gfile));
+    gios->stream = NULL;
+	
+    return (GMimeStream *) gios;
+}
+
+
+#endif  /* HAVE_GIO */

Added: trunk/libbalsa/gmime-stream-gio.h
==============================================================================
--- (empty file)
+++ trunk/libbalsa/gmime-stream-gio.h	Fri Jan  2 18:05:59 2009
@@ -0,0 +1,71 @@
+/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
+/*  GMime GIO stream module
+ *  Written/Copyright (c) by Albrecht Dreß<albrecht dress arcor de>
+ *  The basic structure of this file has been shamelessly stolen from the
+ *  gmime-stream-fs module, written by Jeffrey Stedfast.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#ifndef __GMIME_STREAM_GIO_H__
+#define __GMIME_STREAM_GIO_H__
+
+#include "config.h"
+
+/* note: this module will be compiled only if GIO is available */
+#if HAVE_GIO
+
+#include <gio/gio.h>
+#include <gmime/gmime-stream.h>
+
+G_BEGIN_DECLS
+
+#define GMIME_TYPE_STREAM_GIO            (g_mime_stream_gio_get_type())
+#define GMIME_STREAM_GIO(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GMIME_TYPE_STREAM_GIO, GMimeStreamGio))
+#define GMIME_STREAM_GIO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GMIME_TYPE_STREAM_GIO, GMimeStreamGioClass))
+#define GMIME_IS_STREAM_GIO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GMIME_TYPE_STREAM_GIO))
+#define GMIME_IS_STREAM_GIO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GMIME_TYPE_STREAM_GIO))
+#define GMIME_STREAM_GIO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GMIME_TYPE_STREAM_GIO, GMimeStreamGioClass))
+
+typedef struct _GMimeStreamGio GMimeStreamGio;
+typedef struct _GMimeStreamGioClass GMimeStreamGioClass;
+
+struct _GMimeStreamGio {
+    GMimeStream parent_object;
+	
+    gboolean eos;
+    GFile *gfile;
+    GObject *stream;
+};
+
+struct _GMimeStreamGioClass {
+    GMimeStreamClass parent_class;
+};
+
+
+GType g_mime_stream_gio_get_type(void);
+
+GMimeStream *g_mime_stream_gio_new(GFile * gfile);
+GMimeStream *g_mime_stream_gio_new_with_bounds(GFile * gfile,
+					       gint64 start,
+					       gint64 end);
+
+G_END_DECLS
+
+#endif /* HAVE_GIO */
+
+#endif /* __GMIME_STREAM_GIO_H__ */

Modified: trunk/libbalsa/gmime-stream-gnome-vfs.c
==============================================================================
--- trunk/libbalsa/gmime-stream-gnome-vfs.c	(original)
+++ trunk/libbalsa/gmime-stream-gnome-vfs.c	Fri Jan  2 18:05:59 2009
@@ -22,8 +22,8 @@
 
 #include "config.h"
 
-/* note: this module will be compiled only if Gnome is available */
-#ifdef HAVE_GNOME
+/* note: this module will be compiled only if Gnome-Vfs is available */
+#ifdef HAVE_GNOME_VFS
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -463,4 +463,4 @@
     stream->owner = owner;
 }
 
-#endif				/* HAVE_GNOME */
+#endif				/* HAVE_GNOME_VFS */

Modified: trunk/libbalsa/gmime-stream-gnome-vfs.h
==============================================================================
--- trunk/libbalsa/gmime-stream-gnome-vfs.h	(original)
+++ trunk/libbalsa/gmime-stream-gnome-vfs.h	Fri Jan  2 18:05:59 2009
@@ -26,8 +26,8 @@
 
 #include "config.h"
 
-/* note: this module will be compiled only if Gnome is available */
-#ifdef HAVE_GNOME
+/* note: this module will be compiled only if Gnome-Vfs is available */
+#ifdef HAVE_GNOME_VFS
 
 #include <libgnomevfs/gnome-vfs.h>
 #include <gmime/gmime-stream.h>
@@ -70,156 +70,6 @@
 
 G_END_DECLS
 
-#endif				/* HAVE_GNOME */
-
-#endif				/* __GMIME_STREAM_GVFS_H__ */
-/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
-/*  GMime Gnome VFS stream module
- *  Written/Copyright (c) by Albrecht Dreß<albrecht dress arcor de>
- *  The basic structure of this file has been shamelessly stolen from the
- *  gmime-stream-fs module, written by Jeffrey Stedfast.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1
- *  of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#ifndef __GMIME_STREAM_GVFS_H__
-#define __GMIME_STREAM_GVFS_H__
-
-#include "config.h"
-
-/* note: this module will be compiled only if Gnome is available */
-#ifdef HAVE_GNOME
-
-#include <libgnomevfs/gnome-vfs.h>
-#include <gmime/gmime-stream.h>
-
-G_BEGIN_DECLS
-
-#define GMIME_TYPE_STREAM_GVFS            (g_mime_stream_gvfs_get_type ())
-#define GMIME_STREAM_GVFS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_STREAM_GVFS, GMimeStreamGvfs))
-#define GMIME_STREAM_GVFS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_STREAM_GVFS, GMimeStreamGvfsClass))
-#define GMIME_IS_STREAM_GVFS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_STREAM_GVFS))
-#define GMIME_IS_STREAM_GVFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_STREAM_GVFS))
-#define GMIME_STREAM_GVFS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_STREAM_GVFS, GMimeStreamGvfsClass))
-
-typedef struct _GMimeStreamGvfs GMimeStreamGvfs;
-typedef struct _GMimeStreamGvfsClass GMimeStreamGvfsClass;
-
-struct _GMimeStreamGvfs {
-    GMimeStream parent_object;
-
-    gboolean owner;
-    gboolean eos;
-    GnomeVFSHandle *handle;
-};
-
-struct _GMimeStreamGvfsClass {
-    GMimeStreamClass parent_class;
-};
-
-
-GType g_mime_stream_gvfs_get_type(void);
-
-GMimeStream *g_mime_stream_gvfs_new(GnomeVFSHandle * handle);
-GMimeStream *g_mime_stream_gvfs_new_with_bounds(GnomeVFSHandle * handle,
-                                                off_t start,
-						off_t end);
-
-gboolean g_mime_stream_gvfs_get_owner(GMimeStreamGvfs * stream);
-void g_mime_stream_gvfs_set_owner(GMimeStreamGvfs * stream,
-				  gboolean owner);
-
-G_END_DECLS
-
-#endif				/* HAVE_GNOME */
-
-#endif				/* __GMIME_STREAM_GVFS_H__ */
-/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
-/*  GMime Gnome VFS stream module
- *  Written/Copyright (c) by Albrecht Dreß<albrecht dress arcor de>
- *  The basic structure of this file has been shamelessly stolen from the
- *  gmime-stream-fs module, written by Jeffrey Stedfast.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1
- *  of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free
- *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#ifndef __GMIME_STREAM_GVFS_H__
-#define __GMIME_STREAM_GVFS_H__
-
-#include "config.h"
-
-/* note: this module will be compiled only if Gnome is available */
-#ifdef HAVE_GNOME
-
-#include <libgnomevfs/gnome-vfs.h>
-#include <gmime/gmime-stream.h>
-
-G_BEGIN_DECLS
-
-#define GMIME_TYPE_STREAM_GVFS            (g_mime_stream_gvfs_get_type ())
-#define GMIME_STREAM_GVFS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_STREAM_GVFS, GMimeStreamGvfs))
-#define GMIME_STREAM_GVFS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_STREAM_GVFS, GMimeStreamGvfsClass))
-#define GMIME_IS_STREAM_GVFS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_STREAM_GVFS))
-#define GMIME_IS_STREAM_GVFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_STREAM_GVFS))
-#define GMIME_STREAM_GVFS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_STREAM_GVFS, GMimeStreamGvfsClass))
-
-typedef struct _GMimeStreamGvfs GMimeStreamGvfs;
-typedef struct _GMimeStreamGvfsClass GMimeStreamGvfsClass;
-
-struct _GMimeStreamGvfs {
-    GMimeStream parent_object;
-
-    gboolean owner;
-    gboolean eos;
-    GnomeVFSHandle *handle;
-};
-
-struct _GMimeStreamGvfsClass {
-    GMimeStreamClass parent_class;
-};
-
-
-GType g_mime_stream_gvfs_get_type(void);
-
-GMimeStream *g_mime_stream_gvfs_new(GnomeVFSHandle * handle);
-GMimeStream *g_mime_stream_gvfs_new_with_bounds(GnomeVFSHandle * handle,
-                                                off_t start,
-						off_t end);
-
-gboolean g_mime_stream_gvfs_get_owner(GMimeStreamGvfs * stream);
-void g_mime_stream_gvfs_set_owner(GMimeStreamGvfs * stream,
-				  gboolean owner);
-
-G_END_DECLS
-
-#endif				/* HAVE_GNOME */
+#endif				/* HAVE_GNOME_VFS */
 
 #endif				/* __GMIME_STREAM_GVFS_H__ */

Modified: trunk/libbalsa/libbalsa-vfs.c
==============================================================================
--- trunk/libbalsa/libbalsa-vfs.c	(original)
+++ trunk/libbalsa/libbalsa-vfs.c	Fri Jan  2 18:05:59 2009
@@ -30,22 +30,34 @@
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <gmime/gmime.h>
-#include "gmime-stream-gnome-vfs.h"
+#include "libbalsa.h"
 #include "misc.h"
 #include "libbalsa-vfs.h"
 
-
-#ifdef HAVE_GNOME
+#if HAVE_GIO
+#  include <gio/gio.h>
+#  include "gmime-stream-gio.h"
+#elif HAVE_GNOME_VFS
 #  include <libgnomevfs/gnome-vfs.h>
-#  define USE_GNOME_VFS  1
-#else
-#  undef USE_GNOME_VFS
+#  include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#  include "gmime-stream-gnome-vfs.h"
 #endif
 
 
 #define LIBBALSA_VFS_ERROR_QUARK (g_quark_from_static_string("libbalsa-vfs"))
 
 
+#define LIBBALSA_VFS_MIME_ACTION "mime_action"
+
+#if HAVE_GIO
+#define GIO_INFO_ATTS                           \
+    G_FILE_ATTRIBUTE_STANDARD_TYPE ","          \
+    G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","  \
+    G_FILE_ATTRIBUTE_STANDARD_SIZE ","          \
+    "access::*"
+#endif
+
+
 struct _LibbalsaVfsPriv {
     gchar * file_uri;
     gchar * file_utf8;
@@ -53,7 +65,10 @@
     gchar * mime_type;
     gchar * charset;
     LibBalsaTextAttribute text_attr;
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+    GFile * gio_gfile;
+    GFileInfo * info;
+#elif HAVE_GNOME_VFS
     GnomeVFSURI * gvfs_uri;
     GnomeVFSFileInfo * info;
 #else
@@ -73,7 +88,7 @@
 gboolean
 libbalsa_vfs_local_only(void)
 {
-#ifdef USE_GNOME_VFS
+#if (HAVE_GIO || HAVE_GNOME_VFS)
     return FALSE;
 #else
     return TRUE;
@@ -141,7 +156,12 @@
         g_free(priv->folder_uri);
         g_free(priv->mime_type);
         g_free(priv->charset);
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+        if (priv->gio_gfile)
+            g_object_unref(priv->gio_gfile);
+        if (priv->info)
+            g_object_unref(priv->info);
+#elif HAVE_GNOME_VFS
         if (priv->gvfs_uri)
             gnome_vfs_uri_unref(priv->gvfs_uri);
         if (priv->info)
@@ -179,7 +199,9 @@
     retval->priv->text_attr = (LibBalsaTextAttribute) -1;
 
     retval->priv->file_uri = g_strdup(uri);
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+    retval->priv->gio_gfile = g_file_new_for_uri(uri);
+#elif HAVE_GNOME_VFS
     retval->priv->gvfs_uri = gnome_vfs_uri_new(uri);
     if (!retval->priv->gvfs_uri)
         g_message(_("Failed to convert %s to a Gnome VFS URI"), uri);
@@ -349,7 +371,19 @@
     g_return_val_if_fail(priv->file_uri, NULL);
 
     if (!priv->mime_type) {
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+        /* use GIO to determine the mime type of the file */
+        g_return_val_if_fail(priv->gio_gfile, FALSE);
+
+        if (!priv->info)
+            priv->info = 
+                g_file_query_info(priv->gio_gfile, GIO_INFO_ATTS,
+                                  G_FILE_QUERY_INFO_NONE, NULL, NULL);
+        if (priv->info)
+            priv->mime_type =
+                g_strdup(g_file_info_get_attribute_string(priv->info,
+                                                          G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE));
+#elif HAVE_GNOME_VFS
         /* use GnomeVFS to determine the mime type of the file */
         g_return_val_if_fail(priv->gvfs_uri, FALSE);
 
@@ -367,10 +401,10 @@
                  GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) != 0)
                 priv->mime_type = g_strdup(gnome_vfs_file_info_get_mime_type(priv->info));
         }
+#endif
 
         /* always fall back to application/octet-stream */
         if (!priv->mime_type)
-#endif
             priv->mime_type = g_strdup("application/octet-stream");
     }
 
@@ -412,7 +446,72 @@
     g_return_val_if_fail(priv->file_uri, 0);
 
     if (priv->text_attr == (LibBalsaTextAttribute) -1) {
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+        GInputStream * stream;
+
+        /* use GIO to determine the text attributes of the file */
+        g_return_val_if_fail(priv->gio_gfile, 0);
+        priv->text_attr = 0;
+
+        /* read and check - see libbalsa_text_attr_file() */
+        if ((stream = G_INPUT_STREAM(g_file_read(priv->gio_gfile, NULL, NULL))) != NULL) {
+            gchar buf[1024];
+            gchar *new_chars = buf;
+            gboolean has_esc = FALSE;
+            gboolean has_hi_bit = FALSE;
+            gboolean has_hi_ctrl = FALSE;
+            gboolean is_utf8 = TRUE;
+            gssize bytes_read;
+
+            while ((is_utf8 || (!has_esc || !has_hi_bit || !has_hi_ctrl)) &&
+                   ((bytes_read = g_input_stream_read(stream,
+                                                      new_chars,
+                                                      (sizeof buf) - (new_chars - buf) - 1,
+                                                      NULL,
+                                                      NULL)) > 0)) {
+                new_chars[bytes_read] = '\0';
+                
+                if (!has_esc || !has_hi_bit || !has_hi_ctrl) {
+                    guchar * p;
+
+                    for (p = (guchar *) new_chars; *p; p++)
+                        if (*p == 0x1b)
+                            has_esc = TRUE;
+                        else if (*p >= 0x80) {
+                            has_hi_bit = TRUE;
+                            if (*p <= 0x9f)
+                                has_hi_ctrl = TRUE;
+                        }
+                }
+
+                if (is_utf8) {
+                    const gchar *end;
+
+                    new_chars = buf;
+                    if (!g_utf8_validate(buf, -1, &end)) {
+                        if (g_utf8_get_char_validated(end, -1) == (gunichar) (-1))
+                            is_utf8 = FALSE;
+                        else
+                            /* copy any remaining bytes, including the
+                             * terminating '\0', to start of buffer */
+                            while ((*new_chars = *end++) != '\0')
+                                new_chars++;
+                    }
+                }
+            }
+
+            g_object_unref(stream);
+
+            if (has_esc)
+                priv->text_attr |= LIBBALSA_TEXT_ESC;
+            if (has_hi_bit)
+                priv->text_attr |= LIBBALSA_TEXT_HI_BIT;
+            if (has_hi_ctrl)
+                priv->text_attr |= LIBBALSA_TEXT_HI_CTRL;
+            if (is_utf8 && has_hi_bit)
+                priv->text_attr |= LIBBALSA_TEXT_HI_UTF8;
+        }
+#elif HAVE_GNOME_VFS
         GnomeVFSHandle *handle;
 
         /* use GnomeVFS to determine the text attributes of the file */
@@ -490,7 +589,7 @@
 gsize
 libbalsa_vfs_get_size(const LibbalsaVfs * file)
 {
-#ifndef USE_GNOME_VFS
+#if (!defined(HAVE_GIO) && !defined(HAVE_GNOME_VFS))
     struct stat s;
 #endif
     gsize retval = 0;
@@ -501,7 +600,19 @@
     priv = file->priv;
     g_return_val_if_fail(priv->file_uri, 0);
 
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+    /* use GIO to determine the size of the file */
+    g_return_val_if_fail(priv->gio_gfile, 0);
+
+    if (!priv->info)
+        priv->info = 
+            g_file_query_info(priv->gio_gfile, GIO_INFO_ATTS,
+                              G_FILE_QUERY_INFO_NONE, NULL, NULL);
+    if (priv->info)
+        retval =
+            (gsize) g_file_info_get_attribute_uint64(priv->info,
+                                                     G_FILE_ATTRIBUTE_STANDARD_SIZE);
+#elif HAVE_GNOME_VFS
     /* use GnomeVFS to determine the size of the file */
     g_return_val_if_fail(priv->gvfs_uri, 0);
 
@@ -513,7 +624,7 @@
              GNOME_VFS_FILE_INFO_FIELDS_SIZE) == 0)
             gnome_vfs_get_file_info_uri(priv->gvfs_uri, priv->info,
                                         GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS |
-                                       GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
+                                        GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
         if ((priv->info->valid_fields &
              GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0)
             retval = (gsize) priv->info->size;
@@ -536,7 +647,8 @@
 libbalsa_vfs_create_stream(const LibbalsaVfs * file, mode_t mode, 
                            gboolean rdwr, GError ** err)
 {
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+#elif HAVE_GNOME_VFS
     GnomeVFSOpenMode openmode = GNOME_VFS_OPEN_RANDOM | GNOME_VFS_OPEN_READ;
     GnomeVFSHandle * handle;
     GnomeVFSResult result;
@@ -551,8 +663,13 @@
     priv = file->priv;
     g_return_val_if_fail(priv->file_uri, NULL);
 
-#ifdef USE_GNOME_VFS
-    /* use GnomeVFS to create a GMime Gnome VFS stream */
+#if HAVE_GIO
+    /* use GIO to create a GMime stream */
+    g_return_val_if_fail(priv->gio_gfile, NULL);
+
+    return g_mime_stream_gio_new(priv->gio_gfile);
+#elif HAVE_GNOME_VFS
+    /* use GnomeVFS to create a GMime stream */
     g_return_val_if_fail(priv->gvfs_uri, NULL);
 
     if (rdwr) {
@@ -562,7 +679,7 @@
     } else
         result = gnome_vfs_open_uri(&handle, priv->gvfs_uri, openmode);
     if (result != GNOME_VFS_OK) {
-        g_set_error(err, LIBBALSA_ERROR_QUARK, result,
+        g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, result,
                     "%s", gnome_vfs_result_to_string(result));
         return NULL;
     }
@@ -598,7 +715,16 @@
     priv = file->priv;
     g_return_val_if_fail(priv->file_uri, FALSE);
 
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+    /* use GIO to get the file's attributes - fails if the file does not exist */
+    g_return_val_if_fail(priv->gio_gfile, 0);
+
+    if (!priv->info)
+        priv->info = 
+            g_file_query_info(priv->gio_gfile, GIO_INFO_ATTS,
+                              G_FILE_QUERY_INFO_NONE, NULL, NULL);
+    result = priv->info != NULL;
+#elif HAVE_GNOME_VFS
     /* use GnomeVFS to check if the file exists */
     g_return_val_if_fail(priv->gvfs_uri, FALSE);
 
@@ -629,7 +755,7 @@
 gboolean
 libbalsa_vfs_is_regular_file(const LibbalsaVfs * file, GError **err)
 {
-#ifndef USE_GNOME_VFS
+#if (!defined(HAVE_GIO) && !defined(HAVE_GNOME_VFS))
     struct stat s;
 #endif
     gboolean result = FALSE;
@@ -640,7 +766,31 @@
     priv = file->priv;
     g_return_val_if_fail(priv->file_uri, FALSE);
 
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+    /* use GIO to check if the file is a regular one which can be read */
+    g_return_val_if_fail(priv->gio_gfile, 0);
+
+    if (!priv->info)
+        priv->info = 
+            g_file_query_info(priv->gio_gfile, GIO_INFO_ATTS,
+                              G_FILE_QUERY_INFO_NONE, NULL, err);
+    if (priv->info) {
+        if (g_file_info_get_file_type(priv->info) != G_FILE_TYPE_REGULAR)
+            g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1,
+                        _("not a regular file"));
+        else if (!g_file_info_get_attribute_boolean(priv->info,
+                                                    G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) {
+            /* the read flag may not be set for some remote file systems (like smb),
+             * so try to actually open the file... */
+            GFileInputStream * stream = g_file_read(priv->gio_gfile, NULL, err);
+            if (stream) {
+                g_object_unref(stream);
+                result = TRUE;
+            }
+        } else
+            result = TRUE;
+    }
+#elif HAVE_GNOME_VFS
     /* use GnomeVFS to check if the file is a regular one which can be read */
     g_return_val_if_fail(priv->gvfs_uri, FALSE);
 
@@ -654,7 +804,6 @@
             gnome_vfs_get_file_info_uri(priv->gvfs_uri, priv->info,
                                         GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS |
                                         GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
-        g_message("fields = %x", priv->info->valid_fields);
         if ((priv->info->valid_fields &
              (GNOME_VFS_FILE_INFO_FIELDS_TYPE |
               GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS)) !=
@@ -670,7 +819,8 @@
             g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1, _("cannot read"));
         else
             result = TRUE;
-    }
+    } else
+        g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1, _("cannot access file"));
 #else
     /* use libc to check if the file is a regular one which can be read */
     g_return_val_if_fail(priv->local_name, FALSE);
@@ -694,7 +844,7 @@
 gint
 libbalsa_vfs_file_unlink(const LibbalsaVfs * file, GError **err)
 {
-#ifdef USE_GNOME_VFS
+#ifdef HAVE_GNOME_VFS
     GnomeVFSResult vfs_res;
 #endif
     gint result = -1;
@@ -705,7 +855,12 @@
     priv = file->priv;
     g_return_val_if_fail(priv->file_uri, -1);
 
-#ifdef USE_GNOME_VFS
+#if HAVE_GIO
+    /* use GIO to delete the file */
+    g_return_val_if_fail(priv->gio_gfile, -1);
+    if (g_file_delete(priv->gio_gfile, NULL, err))
+        result = 0;
+#elif HAVE_GNOME_VFS
     /* use GnomeVFS to unlink the file */
     g_return_val_if_fail(priv->gvfs_uri, -1);
 
@@ -726,3 +881,262 @@
 
     return result;
 }
+
+
+gboolean
+libbalsa_vfs_launch_app(const LibbalsaVfs * file, GObject * object, GError **err)
+{
+#if HAVE_GIO
+    GAppInfo *app;
+    GList * args;
+    gboolean result;
+#elif HAVE_GNOME_VFS
+    gchar *id;
+    GnomeVFSMimeApplication *app;
+    GnomeVFSResult gvfs_result;
+    GList *uris;
+#endif
+
+    g_return_val_if_fail(file != NULL, FALSE);
+    g_return_val_if_fail(object != NULL, FALSE);
+
+#if HAVE_GIO /* -- launch the requested application using GIO */
+
+    app = G_APP_INFO(g_object_get_data(object, LIBBALSA_VFS_MIME_ACTION));
+    if (!app) {
+        g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1,
+                    _("Cannot launch, missing application"));
+        return FALSE;
+    }
+    args = g_list_prepend(NULL, file->priv->gio_gfile);
+    result = g_app_info_launch(app, args, NULL, err);
+    g_list_free(args);
+    return result;
+
+#elif HAVE_GNOME_VFS /* -- launch the requested application using Gnome-VFS -- */
+
+    id = (gchar *) g_object_get_data(object, LIBBALSA_VFS_MIME_ACTION);
+    if (!id) {
+        g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1,
+                    _("Cannot launch, missing application"));
+        return FALSE;
+    }
+#if HAVE_GNOME_VFS29
+    app = gnome_vfs_mime_application_new_from_desktop_id(id);
+#else				/* HAVE_GNOME_VFS29 */
+    app = gnome_vfs_mime_application_new_from_id(id);
+#endif				/* HAVE_GNOME_VFS29 */
+    if (!app) {
+        g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1,
+                    _("Cannot find application for id %s"), id);
+        return FALSE;
+    }
+
+    uris = g_list_prepend(NULL, file->priv->file_uri);
+    gvfs_result = gnome_vfs_mime_application_launch(app, uris);
+    g_list_free(uris);
+    if (gvfs_result != GNOME_VFS_OK)
+        g_set_error(err, LIBBALSA_VFS_ERROR_QUARK, -1,
+                    _("Cannot launch %s: %s"), app->name,
+                    gnome_vfs_result_to_string(gvfs_result));
+    return gvfs_result == GNOME_VFS_OK;
+    
+#else /* -- no GIO or Gnome-VFS support -- */
+
+    return FALSE;
+
+#endif
+}
+
+
+gboolean
+libbalsa_vfs_launch_app_for_body(LibBalsaMessageBody * mime_body,
+                                 GObject * object, GError **err)
+{
+    gchar *uri;
+    LibbalsaVfs * file;
+    gboolean result;
+
+    g_return_val_if_fail(mime_body != NULL, FALSE);
+    g_return_val_if_fail(object != NULL, FALSE);
+
+    if (!libbalsa_message_body_save_temporary(mime_body, err))
+        return FALSE;
+
+    uri = g_filename_to_uri(mime_body->temp_filename, NULL, NULL);
+    file = libbalsa_vfs_new_from_uri(uri);
+    g_free(uri);
+    result = libbalsa_vfs_launch_app(file,object , err);
+    g_object_unref(file);
+
+    return result;
+}
+
+
+gchar *
+libbalsa_vfs_content_description(const gchar * mime_type)
+{
+    g_return_val_if_fail(mime_type != NULL, NULL);
+
+#if HAVE_GIO
+    return g_content_type_get_description(mime_type);
+#elif HAVE_GNOME_VFS
+    return g_strdup(gnome_vfs_mime_get_description(mime_type));
+#else
+    return NULL;
+#endif
+}
+
+gchar *
+libbalsa_vfs_content_type_of_buffer(const guchar * buffer,
+                                    gsize length)
+{
+#if HAVE_GIO
+    gchar * retval;
+    gboolean content_uncertain;
+#endif
+
+    g_return_val_if_fail(buffer != NULL, NULL);
+    g_return_val_if_fail(length > 0, NULL);
+
+#if HAVE_GIO
+    retval = g_content_type_guess(NULL, buffer, length, &content_uncertain);
+    if (content_uncertain) {
+        g_free(retval);
+        retval = g_strdup("application/octet-stream");
+    }
+    return retval;
+#elif HAVE_GNOME_VFS
+    return g_strdup(gnome_vfs_get_mime_type_for_data(buffer, length));
+#else
+    return g_strdup("application/octet-stream");
+#endif
+}
+
+
+#ifdef HAVE_GIO
+static void 
+gio_add_vfs_menu_item(GtkMenu * menu, GAppInfo *app, GCallback callback,
+                      gpointer data)
+{
+    gchar *menu_label =
+        g_strdup_printf(_("Open with %s"), g_app_info_get_name(app));
+    GtkWidget *menu_item = gtk_menu_item_new_with_label (menu_label);
+    
+    g_object_ref(G_OBJECT(app));
+    g_object_set_data_full(G_OBJECT(menu_item), LIBBALSA_VFS_MIME_ACTION,
+			   app, g_object_unref);
+    g_signal_connect(G_OBJECT (menu_item), "activate", callback, data);
+    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+    g_free(menu_label);
+}
+#elif HAVE_GNOME_VFS
+static void 
+gvfs_add_vfs_menu_item(GtkMenu * menu, const GnomeVFSMimeApplication *app,
+                       GCallback callback, gpointer data)
+{
+    gchar *menu_label = g_strdup_printf(_("Open with %s"), app->name);
+    GtkWidget *menu_item = gtk_menu_item_new_with_label (menu_label);
+    
+    g_object_set_data_full(G_OBJECT (menu_item), LIBBALSA_VFS_MIME_ACTION, 
+			   g_strdup(app->id), g_free);
+    g_signal_connect(G_OBJECT (menu_item), "activate", callback, data);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+    g_free (menu_label);
+}
+#endif
+
+
+/* fill the passed menu with vfs items */
+void
+libbalsa_vfs_fill_menu_by_content_type(GtkMenu * menu,
+				       const gchar * content_type,
+				       GCallback callback, gpointer data)
+{
+#if HAVE_GIO
+    GList* list;
+    GAppInfo *def_app;
+    GList *app_list;
+    
+    g_return_if_fail(data != NULL);
+
+    if ((def_app = g_app_info_get_default_for_type(content_type, FALSE)))
+        gio_add_vfs_menu_item(menu, def_app, callback, data);
+
+    app_list = g_app_info_get_all_for_type(content_type);
+    for (list = app_list; list; list = g_list_next(list)) {
+        GAppInfo *app = G_APP_INFO(list->data);
+
+        if (app && g_app_info_should_show(app) &&
+            (!def_app || !g_app_info_equal(app, def_app)))
+            gio_add_vfs_menu_item(menu, app, callback, data);
+    }
+    if (def_app)
+        g_object_unref(def_app);
+    if (app_list) {
+        g_list_foreach(app_list, (GFunc) g_object_unref, NULL);
+        g_list_free(app_list);
+    }
+#elif HAVE_GNOME_VFS
+    GList* list;
+    GnomeVFSMimeApplication *def_app;
+    GList *app_list;
+    
+    g_return_if_fail(data != NULL);
+
+    if((def_app=gnome_vfs_mime_get_default_application(content_type)))
+        gvfs_add_vfs_menu_item(menu, def_app, callback, data);
+
+    app_list = gnome_vfs_mime_get_all_applications(content_type);
+    for (list = app_list; list; list = g_list_next(list)) {
+        GnomeVFSMimeApplication *app = (GnomeVFSMimeApplication *) list->data;
+
+        if (app && (!def_app || strcmp(app->name, def_app->name) != 0))
+            gvfs_add_vfs_menu_item(menu, app, callback, data);
+    }
+    gnome_vfs_mime_application_free(def_app);
+    
+    gnome_vfs_mime_application_list_free (app_list);
+#endif /* HAVE_GNOME_VFS */
+}
+
+GtkWidget *
+libbalsa_vfs_mime_button(LibBalsaMessageBody * mime_body,
+                         const gchar * content_type,
+                         GCallback callback, gpointer data)
+{
+    GtkWidget *button = NULL;
+#if HAVE_GIO
+    gchar *msg;
+    GAppInfo *app = g_app_info_get_default_for_type(content_type, FALSE);
+
+    if (app) {
+	msg = g_strdup_printf(_("Open _part with %s"), g_app_info_get_name(app));
+	button = gtk_button_new_with_mnemonic(msg);
+	g_object_set_data_full(G_OBJECT(button), LIBBALSA_VFS_MIME_ACTION,
+			       (gpointer) app, g_object_unref);
+	g_free(msg);
+
+	g_signal_connect(G_OBJECT(button), "clicked",
+                         callback, data);
+    }
+#elif HAVE_GNOME_VFS
+    gchar *msg;
+    GnomeVFSMimeApplication *app =
+	gnome_vfs_mime_get_default_application(content_type);
+
+    if (app) {
+	msg = g_strdup_printf(_("Open _part with %s"), app->name);
+	button = gtk_button_new_with_mnemonic(msg);
+	g_object_set_data_full(G_OBJECT(button), LIBBALSA_VFS_MIME_ACTION,
+			       (gpointer) g_strdup(app->id), g_free);
+	g_free(msg);
+	gnome_vfs_mime_application_free(app);
+
+	g_signal_connect(G_OBJECT(button), "clicked",
+                         callback, data);
+    }
+#endif
+
+    return button;
+}

Modified: trunk/libbalsa/libbalsa-vfs.h
==============================================================================
--- trunk/libbalsa/libbalsa-vfs.h	(original)
+++ trunk/libbalsa/libbalsa-vfs.h	Fri Jan  2 18:05:59 2009
@@ -26,6 +26,8 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <gmime/gmime.h>
+#include <gtk/gtk.h>
+#include "libbalsa.h"
 #include "misc.h"
 
 
@@ -76,181 +78,31 @@
                                          gboolean rdwr,
                                          GError ** err);
 gboolean libbalsa_vfs_file_exists(const LibbalsaVfs * file);
-gboolean libbalsa_vfs_is_regular_file(const LibbalsaVfs * file, GError **err);
-gint libbalsa_vfs_file_unlink(const LibbalsaVfs * file, GError **err);
-
-
-G_END_DECLS
-
-
-#endif				/* __LIBBALSA_VFS_H__ */
-/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
-/*
- * libbalsa vfs glue layer library
- * Copyright (C) 2008 Albrecht Dreß<albrecht dress arcor de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version.
- *  
- * 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.
- */
-
-#ifndef __LIBBALSA_VFS_H__
-#define __LIBBALSA_VFS_H__
-
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gmime/gmime.h>
-#include "misc.h"
-
-
-G_BEGIN_DECLS
-
-
-/* a vfs file description as GObject */
-#define LIBBALSA_TYPE_VFS            (libbalsa_vfs_get_type())
-#define LIBBALSA_VFS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), LIBBALSA_TYPE_VFS, LibbalsaVfs))
-#define LIBBALSA_VFS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), LIBBALSA_TYPE_VFS, LibbalsaVfsClass))
-#define LIBBALSA_IS_VFS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), LIBBALSA_TYPE_VFS))
-#define LIBBALSA_IS_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), LIBBALSA_TYPE_VFS))
-#define LIBBALSA_VFS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), LIBBALSA_TYPE_VFS, LibbalsaVfsClass))
-
-typedef struct _LibbalsaVfs LibbalsaVfs;
-typedef struct _LibbalsaVfsClass LibbalsaVfsClass;
-
-
-struct _LibbalsaVfs {
-    GObject parent;
-
-    struct _LibbalsaVfsPriv * priv;
-};
-
-struct _LibbalsaVfsClass {
-    GObjectClass parent;
-};
-
-gboolean libbalsa_vfs_local_only(void);
-
-GType libbalsa_vfs_get_type(void);
-LibbalsaVfs * libbalsa_vfs_new(void);
-LibbalsaVfs * libbalsa_vfs_new_from_uri(const gchar * uri);
-LibbalsaVfs * libbalsa_vfs_append(const LibbalsaVfs * file,
-                                  const gchar * text);
-LibbalsaVfs * libbalsa_vfs_dir_append(const LibbalsaVfs * dir,
-                                      const gchar * filename);
-const gchar * libbalsa_vfs_get_folder(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_uri(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_uri_utf8(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_basename_utf8(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_mime_type(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_charset(const LibbalsaVfs * file);
-LibBalsaTextAttribute libbalsa_vfs_get_text_attr(const LibbalsaVfs * file);
-gsize libbalsa_vfs_get_size(const LibbalsaVfs * file);
-GMimeStream * libbalsa_vfs_create_stream(const LibbalsaVfs * file,
-                                         mode_t mode, 
-                                         gboolean rdwr,
-                                         GError ** err);
-gboolean libbalsa_vfs_file_exists(const LibbalsaVfs * file);
-gboolean libbalsa_vfs_is_regular_file(const LibbalsaVfs * file, GError **err);
-gint libbalsa_vfs_file_unlink(const LibbalsaVfs * file, GError **err);
-
-
-G_END_DECLS
-
-
-#endif				/* __LIBBALSA_VFS_H__ */
-/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */
-/*
- * libbalsa vfs glue layer library
- * Copyright (C) 2008 Albrecht Dreß<albrecht dress arcor de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version.
- *  
- * 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.
- */
-
-#ifndef __LIBBALSA_VFS_H__
-#define __LIBBALSA_VFS_H__
-
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gmime/gmime.h>
-#include "misc.h"
-
-
-G_BEGIN_DECLS
-
-
-/* a vfs file description as GObject */
-#define LIBBALSA_TYPE_VFS            (libbalsa_vfs_get_type())
-#define LIBBALSA_VFS(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), LIBBALSA_TYPE_VFS, LibbalsaVfs))
-#define LIBBALSA_VFS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), LIBBALSA_TYPE_VFS, LibbalsaVfsClass))
-#define LIBBALSA_IS_VFS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), LIBBALSA_TYPE_VFS))
-#define LIBBALSA_IS_VFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), LIBBALSA_TYPE_VFS))
-#define LIBBALSA_VFS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), LIBBALSA_TYPE_VFS, LibbalsaVfsClass))
-
-typedef struct _LibbalsaVfs LibbalsaVfs;
-typedef struct _LibbalsaVfsClass LibbalsaVfsClass;
-
-
-struct _LibbalsaVfs {
-    GObject parent;
-
-    struct _LibbalsaVfsPriv * priv;
-};
-
-struct _LibbalsaVfsClass {
-    GObjectClass parent;
-};
-
-gboolean libbalsa_vfs_local_only(void);
-
-GType libbalsa_vfs_get_type(void);
-LibbalsaVfs * libbalsa_vfs_new(void);
-LibbalsaVfs * libbalsa_vfs_new_from_uri(const gchar * uri);
-LibbalsaVfs * libbalsa_vfs_append(const LibbalsaVfs * file,
-                                  const gchar * text);
-LibbalsaVfs * libbalsa_vfs_dir_append(const LibbalsaVfs * dir,
-                                      const gchar * filename);
-const gchar * libbalsa_vfs_get_folder(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_uri(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_uri_utf8(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_basename_utf8(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_mime_type(const LibbalsaVfs * file);
-const gchar * libbalsa_vfs_get_charset(const LibbalsaVfs * file);
-LibBalsaTextAttribute libbalsa_vfs_get_text_attr(const LibbalsaVfs * file);
-gsize libbalsa_vfs_get_size(const LibbalsaVfs * file);
-GMimeStream * libbalsa_vfs_create_stream(const LibbalsaVfs * file,
-                                         mode_t mode, 
-                                         gboolean rdwr,
-                                         GError ** err);
-gboolean libbalsa_vfs_file_exists(const LibbalsaVfs * file);
-gboolean libbalsa_vfs_is_regular_file(const LibbalsaVfs * file, GError **err);
-gint libbalsa_vfs_file_unlink(const LibbalsaVfs * file, GError **err);
-
+gboolean libbalsa_vfs_is_regular_file(const LibbalsaVfs * file,
+                                      GError **err);
+gint libbalsa_vfs_file_unlink(const LibbalsaVfs * file,
+                              GError **err);
+
+/* application launch helpers */
+gboolean libbalsa_vfs_launch_app(const LibbalsaVfs * file,
+                                 GObject * object,
+                                 GError **err);
+gboolean libbalsa_vfs_launch_app_for_body(LibBalsaMessageBody * mime_body,
+                                          GObject * object,
+                                          GError **err);
+void libbalsa_vfs_fill_menu_by_content_type(GtkMenu * menu,
+                                            const gchar * content_type,
+                                            GCallback callback,
+                                            gpointer data);
+GtkWidget * libbalsa_vfs_mime_button(LibBalsaMessageBody * mime_body,
+                                     const gchar * content_type,
+                                     GCallback callback,
+                                     gpointer data);
+
+/* content type helpers */
+gchar * libbalsa_vfs_content_description(const gchar * mime_type);
+gchar * libbalsa_vfs_content_type_of_buffer(const guchar * buffer,
+                                            gsize length);
 
 G_END_DECLS
 

Modified: trunk/libbalsa/misc.c
==============================================================================
--- trunk/libbalsa/misc.c	(original)
+++ trunk/libbalsa/misc.c	Fri Jan  2 18:05:59 2009
@@ -39,10 +39,6 @@
 #include <sys/types.h>
 #include <sys/utsname.h>
 
-#ifdef HAVE_GNOME
-#include <libgnomevfs/gnome-vfs.h>
-#endif
-
 #include "libbalsa.h"
 #include "libbalsa_private.h"
 #include "misc.h"

Modified: trunk/src/ab-main.c
==============================================================================
--- trunk/src/ab-main.c	(original)
+++ trunk/src/ab-main.c	Fri Jan  2 18:05:59 2009
@@ -22,7 +22,10 @@
 #include "config.h"
 
 #include <string.h>
+#include <gtk/gtk.h>
+#if HAVE_GNOME
 #include <gnome.h>
+#endif
 #ifdef GTKHTML_HAVE_GCONF
 # include <gconf/gconf.h>
 #endif
@@ -1177,7 +1180,9 @@
 static void
 bab_cleanup(void)
 {
+#if HAVE_GNOME
     gnome_sound_shutdown();
+#endif
     gtk_main_quit();
 }
 

Modified: trunk/src/ab-window.c
==============================================================================
--- trunk/src/ab-window.c	(original)
+++ trunk/src/ab-window.c	Fri Jan  2 18:05:59 2009
@@ -21,7 +21,6 @@
 
 #include "config.h"
 
-#include <gnome.h>
 #include <string.h>
 #include <glib/gi18n.h>
 #include "address-view.h"
@@ -412,9 +411,15 @@
 static void
 balsa_ab_window_run_editor(GtkWidget * widget, gpointer data)
 {
-    char *argv[] = { "balsa-ab" };
+    char *argv[] = { "balsa-ab", NULL };
+    GError * err = NULL;
 
-    gnome_execute_async(NULL, 1, argv);
+    if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
+                       NULL, NULL, NULL, &err))
+        balsa_information(LIBBALSA_INFORMATION_WARNING,
+                          _("Could not launch %s: %s"), argv[0],
+                          err ? err->message : "Unknown error");
+    g_clear_error(&err);
 }
 
 /*

Modified: trunk/src/balsa-icons.c
==============================================================================
--- trunk/src/balsa-icons.c	(original)
+++ trunk/src/balsa-icons.c	Fri Jan  2 18:05:59 2009
@@ -20,7 +20,6 @@
  */
 
 #include <string.h>
-#include <gnome.h>
 #include <gdk/gdkx.h>
 
 #include "config.h"

Modified: trunk/src/balsa-icons.h
==============================================================================
--- trunk/src/balsa-icons.h	(original)
+++ trunk/src/balsa-icons.h	Fri Jan  2 18:05:59 2009
@@ -22,6 +22,7 @@
 #ifndef __BALSA_ICONS_H__
 #define __BALSA_ICONS_H__
 
+#include <gtk/gtk.h>
 #include "config.h"
 
 #define BALSA_PIXMAP_ATTACHMENT			"balsa_attachment"

Modified: trunk/src/balsa-index.c
==============================================================================
--- trunk/src/balsa-index.c	(original)
+++ trunk/src/balsa-index.c	Fri Jan  2 18:05:59 2009
@@ -34,7 +34,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <gnome.h>
 #include <glib.h>
 
 #include "balsa-app.h"

Modified: trunk/src/balsa-mblist.c
==============================================================================
--- trunk/src/balsa-mblist.c	(original)
+++ trunk/src/balsa-mblist.c	Fri Jan  2 18:05:59 2009
@@ -21,7 +21,6 @@
 
 #include "config.h"
 
-#include <gnome.h>
 /* #include <gtk/gtkfeatures.h> */
 #include <string.h>
 #include <gdk/gdkfont.h>

Modified: trunk/src/balsa-message.c
==============================================================================
--- trunk/src/balsa-message.c	(original)
+++ trunk/src/balsa-message.c	Fri Jan  2 18:05:59 2009
@@ -26,7 +26,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <iconv.h>
-#include <libgnomevfs/gnome-vfs-mime-info.h>
 #include <sys/utsname.h>
 
 #include "balsa-app.h"
@@ -50,8 +49,6 @@
 #include "sendmsg-window.h"
 #include "libbalsa-vfs.h"
 
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
-
 #ifdef HAVE_GPGME
 #  include "gmime-part-rfc2440.h"
 #endif
@@ -1340,6 +1337,9 @@
     gchar *icon_title = NULL;
     gboolean is_multipart=libbalsa_message_body_is_multipart(body);
     GdkPixbuf *content_icon;
+    gchar *content_desc;
+
+    content_desc = libbalsa_vfs_content_description(content_type);
 
     if(!is_multipart ||
        g_ascii_strcasecmp(content_type, "message/rfc822")==0 ||
@@ -1382,13 +1382,13 @@
             libbalsa_utf8_sanitize(&filename, balsa_app.convert_unknown_8bit, 
                                    NULL);
             icon_title =
-                g_strdup_printf("%s (%s)", filename, content_type);
+                g_strdup_printf("%s (%s)", filename, content_desc);
 	    
 	    /* this should neither be a message nor multipart, so add it to the
 	       attachments popup */
 	    menu_label =
 		g_strdup_printf(_("part %s: %s (file %s)"), part_id,
-				content_type, filename);
+				content_desc, filename);
 	    add_to_attachments_popup(GTK_MENU_SHELL(bm->parts_popup),
 				     menu_label, bm, info);
 	    g_free(menu_label);
@@ -1396,9 +1396,9 @@
         } else {
 	    gchar * menu_label;
 
-            icon_title = g_strdup_printf("%s", content_type);
+            icon_title = g_strdup_printf("%s", content_desc);
 	    menu_label =
-		g_strdup_printf(_("part %s: %s"), part_id, content_type);
+		g_strdup_printf(_("part %s: %s"), part_id, content_desc);
 	    add_to_attachments_popup(GTK_MENU_SHELL(bm->parts_popup),
 				     menu_label, bm, info);
 	    g_free(menu_label);
@@ -1440,11 +1440,12 @@
                             PART_INFO_COLUMN, NULL,
 			    PART_NUM_COLUMN, part_id,
                             MIME_ICON_COLUMN, content_icon,
-                            MIME_TYPE_COLUMN, content_type, -1);
+                            MIME_TYPE_COLUMN, content_desc, -1);
     }
         
     if (content_icon)
 	g_object_unref(G_OBJECT(content_icon));
+    g_free(content_desc);
     g_free(content_type);
 }
 
@@ -1591,9 +1592,9 @@
 #endif                          /* GLIB_CHECK_VERSION(2, 10, 0) */
     
     content_type = libbalsa_message_body_get_mime_type (info->body);
-    libbalsa_fill_vfs_menu_by_content_type(GTK_MENU(info->popup_menu),
+    libbalsa_vfs_fill_menu_by_content_type(GTK_MENU(info->popup_menu),
 					   content_type,
-					   G_CALLBACK (balsa_mime_widget_ctx_menu_vfs_cb),
+					   G_CALLBACK (balsa_mime_widget_ctx_menu_cb),
 					   (gpointer)info->body);
 
     menu_item = gtk_menu_item_new_with_mnemonic (_("_Save..."));

Modified: trunk/src/balsa-mime-widget-callbacks.c
==============================================================================
--- trunk/src/balsa-mime-widget-callbacks.c	(original)
+++ trunk/src/balsa-mime-widget-callbacks.c	Fri Jan  2 18:05:59 2009
@@ -20,8 +20,6 @@
  */
 
 #include <string.h>
-#include <libgnomevfs/gnome-vfs-mime-info.h>
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
 #include "config.h"
 #include "balsa-app.h"
 #include <glib/gi18n.h>
@@ -30,99 +28,25 @@
 #include "balsa-mime-widget.h"
 #include "balsa-mime-widget-callbacks.h"
 
-#include <gnome.h> /* for gnome_execute_shell() */
 #include <gdk/gdkkeysyms.h>
 
+
 void
 balsa_mime_widget_ctx_menu_cb(GtkWidget * menu_item,
 			      LibBalsaMessageBody * mime_body)
 {
-    gchar *content_type, *fpos;
-    const gchar *cmd;
-    gchar *key;
     GError *err = NULL;
-    g_return_if_fail(mime_body != NULL);
-
-    content_type = libbalsa_message_body_get_mime_type(mime_body);
-    key = g_object_get_data(G_OBJECT(menu_item), "mime_action");
-
-    if (key != NULL
-	&& (cmd = gnome_vfs_mime_get_value(content_type, key)) != NULL) {
-	if (!libbalsa_message_body_save_temporary(mime_body, &err)) {
-	    balsa_information(LIBBALSA_INFORMATION_WARNING,
-			      _("Could not create temporary file %s: %s"),
-			      mime_body->temp_filename,
-                              err ? err->message : "Unknown error");
-            g_clear_error(&err);
-	    g_free(content_type);
-	    return;
-	}
-
-	if ((fpos = strstr(cmd, "%f")) != NULL) {
-	    gchar *exe_str, *cps = g_strdup(cmd);
-	    cps[fpos - cmd + 1] = 's';
-	    exe_str = g_strdup_printf(cps, mime_body->temp_filename);
-	    gnome_execute_shell(NULL, exe_str);
-	    fprintf(stderr, "Executed: %s\n", exe_str);
-	    g_free(cps);
-	    g_free(exe_str);
-	}
-    } else
-	fprintf(stderr, "view for %s returned NULL\n", content_type);
-
-    g_free(content_type);
-}
+    gboolean result;
 
-
-void
-balsa_mime_widget_ctx_menu_vfs_cb(GtkWidget * menu_item,
-				  LibBalsaMessageBody * mime_body)
-{
-    gchar *id;
-
-    if ((id = g_object_get_data(G_OBJECT(menu_item), "mime_action"))) {
-        GError *err = NULL;
-#if HAVE_GNOME_VFS29
-	GnomeVFSMimeApplication *app =
-	    gnome_vfs_mime_application_new_from_desktop_id(id);
-#else				/* HAVE_GNOME_VFS29 */
-	GnomeVFSMimeApplication *app =
-	    gnome_vfs_mime_application_new_from_id(id);
-#endif				/* HAVE_GNOME_VFS29 */
-	if (app) {
-	    if (libbalsa_message_body_save_temporary(mime_body, &err)) {
-#if HAVE_GNOME_VFS29
-		gchar *uri = g_filename_to_uri(mime_body->temp_filename, NULL, NULL);
-		GList *uris = g_list_prepend(NULL, uri);
-		gnome_vfs_mime_application_launch(app, uris);
-		g_free(uri);
-		g_list_free(uris);
-#else				/* HAVE_GNOME_VFS29 */
-		gboolean tmp =
-		    (app->expects_uris ==
-		     GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS);
-		gchar *uri = g_filename_to_uri(mime_body->temp_filename, NULL, NULL);
-		gchar *exe_str =
-		    g_strdup_printf("%s \"%s\"", app->command,
-				    tmp ? uri : mime_body->temp_filename);
-
-		gnome_execute_shell(NULL, exe_str);
-		fprintf(stderr, "Executed: %s\n", exe_str);
-		g_free(uri);
-		g_free(exe_str);
-#endif				/* HAVE_GNOME_VFS29 */
-	    } else {
-		balsa_information(LIBBALSA_INFORMATION_WARNING,
-				  _("Could not create temporary file %s: %s"),
-				  mime_body->temp_filename,
-                                  err ? err->message : "Unknown error");
-	    }
-	    gnome_vfs_mime_application_free(app);
-	} else {
-	    fprintf(stderr, "lookup for application %s returned NULL\n",
-		    id);
-	}
-    }
+    g_return_if_fail(mime_body != NULL);
+    result = libbalsa_vfs_launch_app_for_body(mime_body,
+                                              G_OBJECT(menu_item),
+                                              &err);
+    if (!result)
+        balsa_information(LIBBALSA_INFORMATION_WARNING,
+                          _("Could not launch application: %s"),
+                          err ? err->message : "Unknown error");
+    g_clear_error(&err);
 }
 
 

Modified: trunk/src/balsa-mime-widget-callbacks.h
==============================================================================
--- trunk/src/balsa-mime-widget-callbacks.h	(original)
+++ trunk/src/balsa-mime-widget-callbacks.h	Fri Jan  2 18:05:59 2009
@@ -33,7 +33,6 @@
 
 
 void balsa_mime_widget_ctx_menu_cb(GtkWidget * menu_item, LibBalsaMessageBody * mime_body);
-void balsa_mime_widget_ctx_menu_vfs_cb(GtkWidget * menu_item, LibBalsaMessageBody * mime_body);
 void balsa_mime_widget_ctx_menu_save(GtkWidget * parent_widget,
                                      LibBalsaMessageBody * mime_body);
 gint balsa_mime_widget_key_press_event(GtkWidget * widget, GdkEventKey * event,

Modified: trunk/src/balsa-mime-widget-text.c
==============================================================================
--- trunk/src/balsa-mime-widget-text.c	(original)
+++ trunk/src/balsa-mime-widget-text.c	Fri Jan  2 18:05:59 2009
@@ -678,8 +678,8 @@
                           (GtkCallback)gtk_widget_destroy_insensitive, NULL);
     gtk_menu_shell_append(GTK_MENU_SHELL(menu),
 			  gtk_separator_menu_item_new ());
-    libbalsa_fill_vfs_menu_by_content_type(menu, "text/plain",
-					   G_CALLBACK (balsa_mime_widget_ctx_menu_vfs_cb),
+    libbalsa_vfs_fill_menu_by_content_type(menu, "text/plain",
+					   G_CALLBACK (balsa_mime_widget_ctx_menu_cb),
 					   (gpointer)mime_body);
 
     menu_item = gtk_menu_item_new_with_label (_("Save..."));
@@ -1168,8 +1168,8 @@
     menuitem = gtk_separator_menu_item_new ();
     gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 
-    libbalsa_fill_vfs_menu_by_content_type(GTK_MENU(menu), "text/html",
-					   G_CALLBACK (balsa_mime_widget_ctx_menu_vfs_cb),
+    libbalsa_vfs_fill_menu_by_content_type(GTK_MENU(menu), "text/html",
+					   G_CALLBACK (balsa_mime_widget_ctx_menu_cb),
 					   mime_body);
 
     menuitem = gtk_menu_item_new_with_label (_("Save..."));

Modified: trunk/src/balsa-mime-widget.c
==============================================================================
--- trunk/src/balsa-mime-widget.c	(original)
+++ trunk/src/balsa-mime-widget.c	Fri Jan  2 18:05:59 2009
@@ -20,9 +20,8 @@
  */
 
 #include <string.h>
-#include <libgnomevfs/gnome-vfs-mime-info.h>
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
 #include "config.h"
+#include "libbalsa.h"
 #include "balsa-app.h"
 #include "balsa-icons.h"
 #include "mime-stream-shared.h"
@@ -48,14 +47,6 @@
 						      const gchar *
 						      content_type);
 
-/* buttons to handle unknown mime types */
-static GtkWidget *part_info_mime_button(LibBalsaMessageBody * mime_body,
-					const gchar * content_type,
-					const gchar * key);
-static GtkWidget *part_info_mime_button_vfs(LibBalsaMessageBody *
-					    mime_body,
-					    const gchar * content_type);
-
 static void vadj_change_cb(GtkAdjustment *vadj, GtkWidget *widget);
 
 
@@ -226,7 +217,7 @@
     GtkWidget *hbox;
     GtkWidget *button = NULL;
     gchar *msg;
-    const gchar *content_desc;
+    gchar *content_desc;
     BalsaMimeWidget *mw;
     gchar *use_content_type;
 
@@ -267,8 +258,7 @@
             size = g_mime_stream_read(stream, buffer, length);
             libbalsa_mime_stream_shared_unlock(stream);
             g_object_unref(stream);
-            use_content_type =
-                g_strdup(gnome_vfs_get_mime_type_for_data(buffer, size));
+            use_content_type = libbalsa_vfs_content_type_of_buffer(buffer, size);
             if (g_ascii_strncasecmp(use_content_type, "text", 4) == 0
                 && libbalsa_text_attr_string(buffer) & LIBBALSA_TEXT_HI_BIT) {
                 /* Hmmm...better stick with application/octet-stream. */
@@ -280,27 +270,26 @@
     } else
 	use_content_type = g_strdup(content_type);
 
-    if ((content_desc = gnome_vfs_mime_get_description(use_content_type)))
+    content_desc = libbalsa_vfs_content_description(use_content_type);
+    if (content_desc) {
 	msg = g_strdup_printf(_("Type: %s (%s)"), content_desc,
 			      use_content_type);
-    else
+        g_free(content_desc);
+    } else
 	msg = g_strdup_printf(_("Content Type: %s"), use_content_type);
     gtk_box_pack_start(GTK_BOX(mw->widget), gtk_label_new(msg), FALSE,
 		       FALSE, 0);
     g_free(msg);
 
     hbox = gtk_hbox_new(TRUE, BMW_HBOX_SPACE);
-    if ((button = part_info_mime_button_vfs(mime_body, use_content_type))
-	|| (button =
-	    part_info_mime_button(mime_body, use_content_type, "view"))
-	|| (button =
-	    part_info_mime_button(mime_body, use_content_type, "open")))
+    if ((button = libbalsa_vfs_mime_button(mime_body, use_content_type,
+                                           G_CALLBACK(balsa_mime_widget_ctx_menu_cb),
+                                           (gpointer) mime_body)))
 	gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
     else
 	gtk_box_pack_start(GTK_BOX(mw->widget),
 			   gtk_label_new(_("No open or view action "
-					   "defined in GNOME MIME "
-					   "for this content type")),
+					   "defined for this content type")),
 			   FALSE, FALSE, 0);
     g_free(use_content_type);
 
@@ -316,57 +305,6 @@
 }
 
 
-static GtkWidget *
-part_info_mime_button(LibBalsaMessageBody * mime_body,
-		      const gchar * content_type, const gchar * key)
-{
-    GtkWidget *button = NULL;
-    gchar *msg;
-    const gchar *cmd =
-	gnome_vfs_mime_get_value(content_type, (char *) key);
-
-    if (cmd) {
-	msg = g_strdup_printf(_("View _part with %s"), cmd);
-	button = gtk_button_new_with_mnemonic(msg);
-	g_object_set_data(G_OBJECT(button), "mime_action", (gpointer) key);
-	g_free(msg);
-
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(balsa_mime_widget_ctx_menu_cb),
-			 (gpointer) mime_body);
-    }
-
-    return button;
-}
-
-
-static GtkWidget *
-part_info_mime_button_vfs(LibBalsaMessageBody * mime_body,
-			  const gchar * content_type)
-{
-    GtkWidget *button = NULL;
-    gchar *msg;
-    GnomeVFSMimeApplication *app =
-	gnome_vfs_mime_get_default_application(content_type);
-
-    if (app) {
-	msg = g_strdup_printf(_("View _part with %s"), app->name);
-	button = gtk_button_new_with_mnemonic(msg);
-	g_object_set_data_full(G_OBJECT(button), "mime_action",
-			       (gpointer) g_strdup(app->id), g_free);
-	g_free(msg);
-
-	g_signal_connect(G_OBJECT(button), "clicked",
-			 G_CALLBACK(balsa_mime_widget_ctx_menu_vfs_cb),
-			 (gpointer) mime_body);
-
-	gnome_vfs_mime_application_free(app);
-
-    }
-    return button;
-}
-
-
 static gint resize_idle_id;
 
 static GtkWidget *old_widget, *new_widget;

Modified: trunk/src/balsa-print-object-default.c
==============================================================================
--- trunk/src/balsa-print-object-default.c	(original)
+++ trunk/src/balsa-print-object-default.c	Fri Jan  2 18:05:59 2009
@@ -23,9 +23,7 @@
 #include "config.h"
 #include <glib/gi18n.h>
 #include "balsa-print-object.h"
-#ifdef HAVE_GNOME
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
-#endif
+#include "libbalsa-vfs.h"
 #include "balsa-print-object-default.h"
 
 
@@ -120,9 +118,7 @@
     PangoTabArray *tabs;
     GString *desc_buf;
     gdouble c_max_height;
-#ifdef HAVE_GNOME
-    const gchar *part_desc;
-#endif
+    gchar *part_desc;
 
     pod = g_object_new(BALSA_TYPE_PRINT_OBJECT_DEFAULT, NULL);
     g_assert(pod != NULL);
@@ -152,13 +148,12 @@
     /* add type and filename (if available) */
     pod->p_label_width =
 	p_string_width_from_layout(test_layout, _("Type:"));
-#ifdef HAVE_GNOME
-    if ((part_desc = gnome_vfs_mime_get_description(conttype)))
+    if ((part_desc = libbalsa_vfs_content_description(conttype)))
 	g_string_append_printf(desc_buf, "%s\t%s (%s)", _("Type:"),
 			       part_desc, conttype);
     else
-#endif
 	g_string_append_printf(desc_buf, "%s\t%s", _("Type:"), conttype);
+    g_free(part_desc);
     g_free(conttype);
     if (body->filename) {
 	gint p_fnwidth =

Modified: trunk/src/balsa-print-object-text.c
==============================================================================
--- trunk/src/balsa-print-object-text.c	(original)
+++ trunk/src/balsa-print-object-text.c	Fri Jan  2 18:05:59 2009
@@ -423,9 +423,6 @@
 
 /* note: a vcard is an icon plus a series of labels/text, so this function actually
  * returns a BalsaPrintObjectDefault... */
-#ifdef HAVE_GNOME
-#include <libgnomevfs/gnome-vfs-mime-handlers.h>
-#endif
 
 #define ADD_VCARD_FIELD(buf, labwidth, layout, field, descr)		\
     do {								\

Modified: trunk/src/filter-edit-dialog.c
==============================================================================
--- trunk/src/filter-edit-dialog.c	(original)
+++ trunk/src/filter-edit-dialog.c	Fri Jan  2 18:05:59 2009
@@ -21,7 +21,6 @@
 
 #include "config.h"
 
-#include <gnome.h>
 #include "balsa-app.h"
 #include "filter-edit.h"
 #include "filter-funcs.h"

Modified: trunk/src/information-dialog.c
==============================================================================
--- trunk/src/information-dialog.c	(original)
+++ trunk/src/information-dialog.c	Fri Jan  2 18:05:59 2009
@@ -26,7 +26,6 @@
 
 #include "config.h"
 
-#include <gnome.h>
 #include <string.h>
 
 #include "libbalsa.h"

Modified: trunk/src/mailbox-conf.c
==============================================================================
--- trunk/src/mailbox-conf.c	(original)
+++ trunk/src/mailbox-conf.c	Fri Jan  2 18:05:59 2009
@@ -41,7 +41,10 @@
 */
 #include "config.h"
 
-#include <gnome.h>
+#include <gtk/gtk.h>
+#if !GTK_CHECK_VERSION(2, 6, 0) && HAVE_GNOME
+#include <gnome.h>  /* needed by GnomeFileEntry */
+#endif
 #include <string.h>
 
 #include "balsa-app.h"
@@ -80,7 +83,7 @@
     gboolean ok_sensitive;
 
     union {
-#if !GTK_CHECK_VERSION(2, 6, 0)
+#if !GTK_CHECK_VERSION(2, 6, 0) && HAVE_GNOME
 	/* for local mailboxes */
 	struct local { 
 	    GnomeFileEntry *path;

Modified: trunk/src/main-window.c
==============================================================================
--- trunk/src/main-window.c	(original)
+++ trunk/src/main-window.c	Fri Jan  2 18:05:59 2009
@@ -66,7 +66,9 @@
 #endif
 #endif                          /* GTK_CHECK_VERSION(2, 14, 0) */
 
+#if HAVE_GNOME
 #include <gnome.h> /* for gnome_triggers_do() */
+#endif
 
 #ifdef BALSA_USE_THREADS
 #include "threads.h"
@@ -3261,9 +3263,11 @@
     if (num_new <= 0 && has_new <= 0)
         return;
 
+#if HAVE_GNOME
     if (balsa_app.notify_new_mail_sound)
         gnome_triggers_do("New mail has arrived", "email",
                           "balsa", "newmail", NULL);
+#endif
 
 #if GTK_CHECK_VERSION(2, 10, 0)
     if (balsa_app.notify_new_mail_icon) {

Modified: trunk/src/quote-color.c
==============================================================================
--- trunk/src/quote-color.c	(original)
+++ trunk/src/quote-color.c	Fri Jan  2 18:05:59 2009
@@ -21,8 +21,6 @@
 
 #include "config.h"
 
-#include <gnome.h>
-
 #include "balsa-app.h"
 #include "quote-color.h"
 

Modified: trunk/src/save-restore.c
==============================================================================
--- trunk/src/save-restore.c	(original)
+++ trunk/src/save-restore.c	Fri Jan  2 18:05:59 2009
@@ -24,7 +24,6 @@
 
 #include <string.h>
 #include <gconf/gconf-client.h>
-#include <gnome.h>
 #include <glib/gi18n.h>
 #include "balsa-app.h"
 #include "save-restore.h"

Modified: trunk/src/sendmsg-window.c
==============================================================================
--- trunk/src/sendmsg-window.c	(original)
+++ trunk/src/sendmsg-window.c	Fri Jan  2 18:05:59 2009
@@ -30,9 +30,17 @@
 
 #include <stdio.h>
 #include <string.h>
+#if HAVE_GNOME
 #include <gnome.h>
-#include <libgnomevfs/gnome-vfs-uri.h>
+#else
+#define GNOME_PAD_SMALL    4
+#endif
+#if HAVE_GIO
+#include <gio/gio.h>
+#elif HAVE_GNOME_VFS
+#include <libgnomevfs/gnome-vfs.h>
 #include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#endif
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <ctype.h>
@@ -1178,14 +1186,32 @@
         gtk_text_view_get_buffer(GTK_TEXT_VIEW(bsmsg->text));
     GtkTextIter start, end;
     gchar *p;
+#if HAVE_GIO
+    GAppInfo *app;
+#elif HAVE_GNOME_VFS
     GnomeVFSMimeApplication *app;
+#endif
     char **argv;
     int argc;
 
     strcpy(filename, TMP_PATTERN);
     tmpfd = mkstemp(filename);
+#if HAVE_GIO
+    app = g_app_info_get_default_for_type("text/plain", FALSE);
+#elif HAVE_GNOME_VFS
     app = gnome_vfs_mime_get_default_application ("text/plain");
+#endif
     if (app) {
+#if HAVE_GIO
+        argc = 2;
+        argv = g_new0 (char *, argc + 1);
+
+        argv[0] = g_strdup(g_app_info_get_executable(app));
+        argv[1] = g_strdup_printf("%s%s",
+                                  g_app_info_supports_uris(app) ? "file://" : "", filename);
+        // FIXME: how can I detect if the called application needs the terminal???
+        g_object_unref(app);
+#elif HAVE_GNOME_VFS
 #if HAVE_GNOME_VFS29
         gboolean adduri = gnome_vfs_mime_application_supports_uris(app);
 	const gchar *exec, *pct;
@@ -1224,6 +1250,7 @@
             }
         }
         gnome_vfs_mime_application_free (app);
+#endif
     } else {
         balsa_information_parented(GTK_WINDOW(bsmsg->window),
                                    LIBBALSA_INFORMATION_ERROR,
@@ -1760,42 +1787,19 @@
 static void
 attachment_menu_vfs_cb(GtkWidget * menu_item, BalsaAttachInfo * info)
 {
-    gchar *id;
-    
+    GError *err = NULL;
+    gboolean result;
+
     g_return_if_fail(info != NULL);
 
-    if ((id = g_object_get_data (G_OBJECT (menu_item), "mime_action"))) {
-#if HAVE_GNOME_VFS29
-        GnomeVFSMimeApplication *app=
-            gnome_vfs_mime_application_new_from_desktop_id(id);
-#else /* HAVE_GNOME_VFS29 */
-        GnomeVFSMimeApplication *app=
-            gnome_vfs_mime_application_new_from_id(id);
-#endif /* HAVE_GNOME_VFS29 */
-        if (app) {
-#if HAVE_GNOME_VFS29
-            gchar *uri = g_strdup(libbalsa_vfs_get_uri(info->file_uri));
-            GList *uris = g_list_prepend(NULL, uri);
-            gnome_vfs_mime_application_launch(app, uris);
-            g_free(uri);
-            g_list_free(uris);
-#else /* HAVE_GNOME_VFS29 */
-	    gboolean tmp =
-		(app->expects_uris ==
-		 GNOME_VFS_MIME_APPLICATION_ARGUMENT_TYPE_URIS);
-	    gchar *exe_str =
-		g_strdup_printf("%s \"%s%s\"", app->command,
-				tmp ? "file://" : "", info->filename);
-                
-	    gnome_execute_shell(NULL, exe_str);
-	    fprintf(stderr, "Executed: %s\n", exe_str);
-	    g_free (exe_str);
-#endif /* HAVE_GNOME_VFS29 */
-	    gnome_vfs_mime_application_free(app);    
-        } else {
-            fprintf(stderr, "lookup for application %s returned NULL\n", id);
-        }
-    }
+    result = libbalsa_vfs_launch_app(info->file_uri,
+                                     G_OBJECT(menu_item),
+                                     &err);
+    if (!result)
+        balsa_information(LIBBALSA_INFORMATION_WARNING,
+                          _("Could not launch application: %s"),
+                          err ? err->message : "Unknown error");
+    g_clear_error(&err);
 }
 
 
@@ -2016,6 +2020,7 @@
     GError *err = NULL;
     GdkPixbuf *pixbuf;
     GtkWidget *menu_item;
+    gchar *content_desc;
 
     if (balsa_app.debug)
 	fprintf(stderr, "Trying to attach '%s'\n", filename);
@@ -2168,17 +2173,18 @@
     /* add the usual vfs menu so the user can inspect what (s)he actually
        attached... (only for non-message attachments) */
     if (!is_fwd_message)
-	libbalsa_fill_vfs_menu_by_content_type(GTK_MENU(attach_data->popup_menu),
+	libbalsa_vfs_fill_menu_by_content_type(GTK_MENU(attach_data->popup_menu),
 					       content_type, 
 					       G_CALLBACK(attachment_menu_vfs_cb),
 					       (gpointer)attach_data);
     gtk_widget_show_all(attach_data->popup_menu);
 
     /* append to the list store */
+    content_desc =libbalsa_vfs_content_description(content_type);
     gtk_list_store_set(GTK_LIST_STORE(model), &iter,
 		       ATTACH_INFO_COLUMN, attach_data,
 		       ATTACH_ICON_COLUMN, pixbuf,
-		       ATTACH_TYPE_COLUMN, content_type,
+		       ATTACH_TYPE_COLUMN, content_desc,
 		       ATTACH_MODE_COLUMN, attach_data->mode,
 		       ATTACH_SIZE_COLUMN, (gfloat) libbalsa_vfs_get_size(file_uri),
 		       ATTACH_DESC_COLUMN, utf8name,
@@ -2187,6 +2193,7 @@
     g_object_unref(pixbuf);
     g_free(utf8name);
     g_free(content_type);
+    g_free(content_desc);
     
     show_attachment_widget(bsmsg);
 

Modified: trunk/src/store-address.c
==============================================================================
--- trunk/src/store-address.c	(original)
+++ trunk/src/store-address.c	Fri Jan  2 18:05:59 2009
@@ -21,7 +21,6 @@
 
 #include "config.h"
 
-#include <gnome.h>
 #include <string.h>
 #include <glib/gi18n.h>
 

Modified: trunk/src/toolbar-factory.c
==============================================================================
--- trunk/src/toolbar-factory.c	(original)
+++ trunk/src/toolbar-factory.c	Fri Jan  2 18:05:59 2009
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <gnome.h>
 #include <gconf/gconf-client.h>
 
 #include <glib/gi18n.h>

Modified: trunk/src/toolbar-prefs.c
==============================================================================
--- trunk/src/toolbar-prefs.c	(original)
+++ trunk/src/toolbar-prefs.c	Fri Jan  2 18:05:59 2009
@@ -42,7 +42,9 @@
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 #endif
 
+#ifdef HAVE_GNOME
 #define OLD_BALSA_COMPATIBILITY_TRANSLATION
+#endif
 #ifdef OLD_BALSA_COMPATIBILITY_TRANSLATION
 #include <gnome.h> /* for GNOME_STOCK_* pixmaps */
 #endif



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