Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evince/ChangeLog,v
retrieving revision 1.795
diff -u -u -r1.795 ChangeLog
--- ChangeLog	1 Apr 2006 21:00:05 -0000	1.795
+++ ChangeLog	2 Apr 2006 17:54:15 -0000
@@ -1,3 +1,19 @@
+2006-04-02  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+	* backend/Makefile.am:
+	* data/evince-ui.xml:
+	* backend/ev-attachment.[ch]:
+	* backend/ev-document.[ch]: (ev_document_has_attachments),
+	(ev_document_get_attachments):
+	* pdf/ev-poppler.cc: (pdf_document_has_attachments),
+	(attachment_save_to_buffer), (pdf_document_get_attachments),
+	(pdf_document_document_iface_init):
+	* shell/Makefile.am:
+	* shell/ev-attachment-bar.[ch]:
+	* shell/ev-window.c:
+
+	Add support for PDF attachments. Fixes bug #325143
+	
 2006-04-02  Nickolay V. Shmyrev  <nshmyrev@yandex.ru>
 
 	* shell/ev-sidebar-thumbnails.c: (ev_sidebar_thumbnails_dispose):
Index: backend/Makefile.am
===================================================================
RCS file: /cvs/gnome/evince/backend/Makefile.am,v
retrieving revision 1.25
diff -u -u -r1.25 Makefile.am
--- backend/Makefile.am	21 Dec 2005 21:29:39 -0000	1.25
+++ backend/Makefile.am	2 Apr 2006 17:54:15 -0000
@@ -17,6 +17,8 @@
 libevbackend_la_SOURCES=			\
 	ev-async-renderer.c			\
 	ev-async-renderer.h			\
+	ev-attachment.c				\
+	ev-attachment.h				\
 	ev-backend-marshal.c			\
 	ev-link.c				\
 	ev-link.h				\
Index: backend/ev-attachment.c
===================================================================
RCS file: backend/ev-attachment.c
diff -N backend/ev-attachment.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ backend/ev-attachment.c	2 Apr 2006 17:54:16 -0000
@@ -0,0 +1,395 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince 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.
+ */
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomevfs/gnome-vfs-mime-handlers.h>
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+#include "ev-attachment.h"
+
+enum
+{
+	PROP_0,
+	PROP_NAME,
+	PROP_DESCRIPTION,
+	PROP_MTIME,
+	PROP_CTIME,
+	PROP_SIZE,
+	PROP_DATA
+};
+
+struct _EvAttachmentPrivate {
+	gchar                   *name;
+	gchar                   *description;
+	GTime                    mtime;
+	GTime                    ctime;
+	gsize                    size;
+	gchar                   *data;
+	gchar                   *mime_type;
+
+	GnomeVFSMimeApplication *app;
+	gchar                   *tmp_uri;
+};
+
+#define EV_ATTACHMENT_GET_PRIVATE(object) \
+                (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_ATTACHMENT, EvAttachmentPrivate))
+
+G_DEFINE_TYPE (EvAttachment, ev_attachment, G_TYPE_OBJECT)
+
+GQuark
+ev_attachment_error_quark (void)
+{
+	static GQuark error_quark = 0;
+	
+	if (error_quark == 0)
+		error_quark =
+			g_quark_from_static_string ("ev-attachment-error-quark");
+	
+	return error_quark;
+}
+
+static void
+ev_attachment_finalize (GObject *object)
+{
+	EvAttachment *attachment = EV_ATTACHMENT (object);
+
+	if (attachment->priv->name) {
+		g_free (attachment->priv->name);
+		attachment->priv->name = NULL;
+	}
+
+	if (attachment->priv->description) {
+		g_free (attachment->priv->description);
+		attachment->priv->description = NULL;
+	}
+
+	if (attachment->priv->data) {
+		g_free (attachment->priv->data);
+		attachment->priv->data = NULL;
+	}
+
+	if (attachment->priv->mime_type) {
+		g_free (attachment->priv->mime_type);
+		attachment->priv->mime_type = NULL;
+	}
+
+	if (attachment->priv->app) {
+		gnome_vfs_mime_application_free (attachment->priv->app);
+		attachment->priv->app = NULL;
+	}
+
+	if (attachment->priv->tmp_uri) {
+		g_unlink (attachment->priv->tmp_uri);
+		g_free (attachment->priv->tmp_uri);
+		attachment->priv->tmp_uri = NULL;
+	}
+
+	(* G_OBJECT_CLASS (ev_attachment_parent_class)->finalize) (object);
+}
+
+static void
+ev_attachment_set_property (GObject      *object,
+			    guint         prop_id,
+			    const GValue *value,
+			    GParamSpec   *param_spec)
+{
+	EvAttachment *attachment = EV_ATTACHMENT (object);
+
+	switch (prop_id) {
+	case PROP_NAME:
+		attachment->priv->name = g_value_dup_string (value);
+		break;
+	case PROP_DESCRIPTION:
+		attachment->priv->description = g_value_dup_string (value);
+		break;
+	case PROP_MTIME:
+		attachment->priv->mtime = g_value_get_ulong (value);
+		break;
+	case PROP_CTIME:
+		attachment->priv->ctime = g_value_get_ulong (value);
+		break;
+	case PROP_SIZE:
+		attachment->priv->size = g_value_get_uint (value);
+		break;
+	case PROP_DATA:
+		attachment->priv->data = g_value_get_pointer (value);
+		attachment->priv->mime_type =
+			g_strdup (gnome_vfs_get_mime_type_for_data (attachment->priv->data,
+								    attachment->priv->size));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+						   prop_id,
+						   param_spec);
+		break;
+	}
+}
+
+static void
+ev_attachment_class_init (EvAttachmentClass *klass)
+{
+	GObjectClass *g_object_class;
+
+	g_object_class = G_OBJECT_CLASS (klass);
+
+	g_object_class->set_property = ev_attachment_set_property;
+
+	g_type_class_add_private (g_object_class, sizeof (EvAttachmentPrivate));
+
+	/* Properties */
+	g_object_class_install_property (g_object_class,
+					 PROP_NAME,
+					 g_param_spec_string ("name",
+							      "Name",
+							      "The attachment name",
+							      NULL,
+							      G_PARAM_WRITABLE |
+							      G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (g_object_class,
+					 PROP_DESCRIPTION,
+					 g_param_spec_string ("description",
+							      "Description",
+							      "The attachment description",
+							      NULL,
+							      G_PARAM_WRITABLE |
+							      G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (g_object_class,
+					 PROP_MTIME,
+					 g_param_spec_ulong ("mtime",
+							     "ModifiedTime", 
+							     "The attachment modification date",
+							     0, G_MAXULONG, 0,
+							     G_PARAM_WRITABLE |
+							     G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (g_object_class,
+					 PROP_CTIME,
+					 g_param_spec_ulong ("ctime",
+							     "CreationTime",
+							     "The attachment creation date",
+							     0, G_MAXULONG, 0,
+							     G_PARAM_WRITABLE |
+							     G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (g_object_class,
+					 PROP_SIZE,
+					 g_param_spec_uint ("size",
+							    "Size",
+							    "The attachment size",
+							    0, G_MAXUINT, 0,
+							    G_PARAM_WRITABLE |
+							    G_PARAM_CONSTRUCT_ONLY));
+	g_object_class_install_property (g_object_class,
+					 PROP_DATA,
+					 g_param_spec_pointer ("data",
+							       "Data",
+							       "The attachment data",
+							       G_PARAM_WRITABLE |
+							       G_PARAM_CONSTRUCT_ONLY));
+	
+	g_object_class->finalize = ev_attachment_finalize;
+}
+
+static void
+ev_attachment_init (EvAttachment *attachment)
+{
+	attachment->priv = EV_ATTACHMENT_GET_PRIVATE (attachment);
+
+	attachment->priv->name = NULL;
+	attachment->priv->description = NULL;
+	attachment->priv->data = NULL;
+	attachment->priv->mime_type = NULL;
+
+	attachment->priv->tmp_uri = NULL;
+}
+
+EvAttachment *
+ev_attachment_new (const gchar *name,
+		   const gchar *description,
+		   GTime        mtime,
+		   GTime        ctime,
+		   gsize        size,
+		   gpointer     data)
+{
+	EvAttachment *attachment;
+
+	attachment = g_object_new (EV_TYPE_ATTACHMENT,
+				   "name", name,
+				   "description", description,
+				   "mtime", mtime,
+				   "ctime", ctime,
+				   "size", size,
+				   "data", data,
+				   NULL);
+
+	return attachment;
+}
+
+const gchar *
+ev_attachment_get_name (EvAttachment *attachment)
+{
+	g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
+
+	return attachment->priv->name;
+}
+
+const gchar *
+ev_attachment_get_description (EvAttachment *attachment)
+{
+	g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
+
+	return attachment->priv->description;
+}
+
+GTime
+ev_attachment_get_modification_date (EvAttachment *attachment)
+{
+	g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
+
+	return attachment->priv->mtime;
+}
+
+GTime
+ev_attachment_get_creation_date (EvAttachment *attachment)
+{
+	g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
+
+	return attachment->priv->ctime;
+}
+
+const gchar *
+ev_attachment_get_mime_type (EvAttachment *attachment)
+{
+	g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
+
+	return attachment->priv->mime_type;
+}
+
+gboolean
+ev_attachment_save (EvAttachment *attachment,
+		    const gchar  *uri,
+		    GError      **error)
+{
+	GnomeVFSHandle  *handle = NULL;
+	GnomeVFSFileSize written;
+	GnomeVFSResult   result;
+	
+	g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
+	g_return_val_if_fail (uri != NULL, FALSE);
+
+	result = gnome_vfs_create (&handle, uri,
+				   GNOME_VFS_OPEN_WRITE |
+				   GNOME_VFS_OPEN_TRUNCATE,
+				   FALSE, 0644);
+	if (result != GNOME_VFS_OK) {
+		g_set_error (error,
+			     EV_ATTACHMENT_ERROR, 
+			     (gint) result,
+			     _("Couldn't save attachment '%s': %s"),
+			     uri, 
+			     gnome_vfs_result_to_string (result));
+		
+		return FALSE;
+	}
+
+	result = gnome_vfs_write (handle, attachment->priv->data,
+				  attachment->priv->size, &written);
+	if (result != GNOME_VFS_OK || written < attachment->priv->size){
+		g_set_error (error,
+			     EV_ATTACHMENT_ERROR,
+			     (gint) result,
+			     _("Couldn't save attachment '%s': %s"),
+			     uri,
+			     gnome_vfs_result_to_string (result));
+		
+		gnome_vfs_close (handle);
+
+		return FALSE;
+	}
+
+	gnome_vfs_close (handle);
+
+	return TRUE;
+}
+
+static gboolean
+ev_attachment_launch_app (EvAttachment *attachment,
+			  GError      **error)
+{
+	GnomeVFSResult result;
+	GList         *uris = NULL;
+
+	g_assert (attachment->priv->tmp_uri != NULL);
+	g_assert (attachment->priv->app != NULL);
+
+	uris = g_list_prepend (uris, attachment->priv->tmp_uri);
+	result = gnome_vfs_mime_application_launch (attachment->priv->app,
+						    uris);
+
+	if (result != GNOME_VFS_OK) {
+		g_set_error (error,
+			     EV_ATTACHMENT_ERROR,
+			     (gint) result,
+			     _("Couldn't open attachment '%s': %s"),
+			     attachment->priv->name,
+			     gnome_vfs_result_to_string (result));
+
+		g_list_free (uris);
+		
+		return FALSE;
+	}
+
+	g_list_free (uris);
+	
+	return TRUE;
+}
+
+gboolean
+ev_attachment_open (EvAttachment *attachment,
+		    GError      **error)
+{
+
+	gboolean retval = FALSE;
+
+	if (!attachment->priv->app)
+		attachment->priv->app =
+			gnome_vfs_mime_get_default_application (attachment->priv->mime_type);
+
+	if (attachment->priv->tmp_uri &&
+	    g_file_test (attachment->priv->tmp_uri, G_FILE_TEST_EXISTS)) {
+		retval = ev_attachment_launch_app (attachment, error);
+	} else {
+		gchar *uri, *filename;
+		
+		filename = g_build_filename (g_get_tmp_dir (), attachment->priv->name, NULL);
+		uri = g_filename_to_uri (filename, NULL, NULL);
+
+		if (ev_attachment_save (attachment, uri, error)) {
+			if (attachment->priv->tmp_uri)
+				g_free (attachment->priv->tmp_uri);
+			attachment->priv->tmp_uri = g_strdup (filename);
+
+			retval = ev_attachment_launch_app (attachment, error);
+		}
+
+		g_free (filename);
+		g_free (uri);
+	}
+
+	return retval;
+}
Index: backend/ev-attachment.h
===================================================================
RCS file: backend/ev-attachment.h
diff -N backend/ev-attachment.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ backend/ev-attachment.h	2 Apr 2006 17:54:16 -0000
@@ -0,0 +1,72 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince 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 __EV_ATTACHMENT_H__
+#define __EV_ATTACHMENT_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _EvAttachment        EvAttachment;
+typedef struct _EvAttachmentClass   EvAttachmentClass;
+typedef struct _EvAttachmentPrivate EvAttachmentPrivate;
+
+#define EV_TYPE_ATTACHMENT              (ev_attachment_get_type())
+#define EV_ATTACHMENT(object)           (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_ATTACHMENT, EvAttachment))
+#define EV_ATTACHMENT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_ATTACHMENT, EvAttachmentClass))
+#define EV_IS_ATTACHMENT(object)        (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_ATTACHMENT))
+#define EV_IS_ATTACHMENT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_ATTACHMENT))
+#define EV_ATTACHMENT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_ATTACHMENT, EvAttachmentClass))
+
+#define EV_ATTACHMENT_ERROR (ev_attachment_error_quark ())
+
+struct _EvAttachment {
+	GObject base_instance;
+	
+	EvAttachmentPrivate *priv;
+};
+
+struct _EvAttachmentClass {
+	GObjectClass base_class;
+};
+
+GType         ev_attachment_get_type             (void) G_GNUC_CONST;
+GQuark        ev_attachment_error_quark          (void) G_GNUC_CONST;
+EvAttachment *ev_attachment_new                  (const gchar  *name,
+						  const gchar  *description,
+						  GTime         mtime,
+						  GTime         ctime,
+						  gsize         size,
+						  gpointer      data);
+
+const gchar *ev_attachment_get_name              (EvAttachment *attachment);
+const gchar *ev_attachment_get_description       (EvAttachment *attachment);
+GTime        ev_attachment_get_modification_date (EvAttachment *attachment);
+GTime        ev_attachment_get_creation_date     (EvAttachment *attachment);
+const gchar *ev_attachment_get_mime_type         (EvAttachment *attachment);
+gboolean     ev_attachment_save                  (EvAttachment *attachment,
+						  const gchar  *uri,
+						  GError      **error);
+gboolean     ev_attachment_open                  (EvAttachment *attachment,
+						  GError      **error);
+
+G_END_DECLS
+
+#endif /* __EV_ATTACHMENT_H__ */
Index: backend/ev-document.c
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-document.c,v
retrieving revision 1.33
diff -u -u -r1.33 ev-document.c
--- backend/ev-document.c	29 Jul 2005 16:02:26 -0000	1.33
+++ backend/ev-document.c	2 Apr 2006 17:54:16 -0000
@@ -200,7 +200,30 @@
 	return retval;
 }
 
+gboolean
+ev_document_has_attachments (EvDocument *document)
+{
+	EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
 
+	if (iface->has_attachments == NULL)
+		return FALSE;
+	
+	return iface->has_attachments (document);
+}
+
+GList *
+ev_document_get_attachments (EvDocument *document)
+{
+	EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
+	GList *retval;
+
+	LOG ("ev_document_get_attachments");
+	if (iface->get_attachments == NULL)
+		return NULL;
+	retval = iface->get_attachments (document);
+
+	return retval;
+}
 
 GdkPixbuf *
 ev_document_render_pixbuf (EvDocument      *document,
Index: backend/ev-document.h
===================================================================
RCS file: /cvs/gnome/evince/backend/ev-document.h,v
retrieving revision 1.32
diff -u -u -r1.32 ev-document.h
--- backend/ev-document.h	7 Sep 2005 12:36:53 -0000	1.32
+++ backend/ev-document.h	2 Apr 2006 17:54:16 -0000
@@ -92,6 +92,8 @@
 					      EvRectangle  *rect);
 	GList          * (* get_links)	     (EvDocument   *document,
 					      int           page);
+	gboolean         (* has_attachments) (EvDocument   *document);
+	GList          * (* get_attachments) (EvDocument   *document);
 	GdkPixbuf      * (* render_pixbuf)   (EvDocument      *document,
 					      EvRenderContext *rc);
 	EvDocumentInfo * (* get_info)        (EvDocument   *document);
@@ -123,6 +125,8 @@
 					     EvRectangle    *rect);
 GList	       *ev_document_get_links       (EvDocument     *document,
 				             int             page);
+gboolean        ev_document_has_attachments (EvDocument     *document);
+GList          *ev_document_get_attachments (EvDocument     *document);
 GdkPixbuf      *ev_document_render_pixbuf   (EvDocument     *document,
 					     EvRenderContext *rc);
 
Index: data/evince-ui.xml
===================================================================
RCS file: /cvs/gnome/evince/data/evince-ui.xml,v
retrieving revision 1.41
diff -u -u -r1.41 evince-ui.xml
--- data/evince-ui.xml	27 Dec 2005 23:21:06 -0000	1.41
+++ data/evince-ui.xml	2 Apr 2006 17:54:16 -0000
@@ -58,7 +58,7 @@
     </menu>
   </menubar>
 
-  <popup name="DocumentPopup" action="PopupAction">
+  <popup name="DocumentPopup" action="DocumentPopupAction">
     <menuitem name="OpenLink" action="OpenLink"/>
     <menuitem name="CopyLinkAddress" action="CopyLinkAddress"/>
     <menuitem name="GoLink" action="GoLink"/>
@@ -69,6 +69,12 @@
     <separator/>
     <menuitem name="EditCopy" action="EditCopy"/>
     <menuitem name="EditSelectAllPopup" action="EditSelectAll"/>
+  </popup>
+
+  <popup name="AttachmentPopup" action="AttachmentPopupAction">
+    <menuitem name="OpenAttachment" action="OpenAttachment"/>
+    <separator/>
+    <menuitem name="SaveAttachmentAs" action="SaveAttachmentAs"/>
   </popup>
 
   <accelerator name="PageDownAccel" action="PageDown"/>
Index: pdf/ev-poppler.cc
===================================================================
RCS file: /cvs/gnome/evince/pdf/ev-poppler.cc,v
retrieving revision 1.65
diff -u -u -r1.65 ev-poppler.cc
--- pdf/ev-poppler.cc	25 Dec 2005 16:49:47 -0000	1.65
+++ pdf/ev-poppler.cc	2 Apr 2006 17:54:16 -0000
@@ -34,6 +34,7 @@
 #include "ev-document-security.h"
 #include "ev-document-thumbnails.h"
 #include "ev-selection.h"
+#include "ev-attachment.h"
 
 typedef struct {
 	PdfDocument *document;
@@ -313,7 +314,122 @@
 
 	return g_list_reverse (retval);
 }
+
+static gboolean
+pdf_document_has_attachments (EvDocument *document)
+{
+	PdfDocument *pdf_document;
+
+	pdf_document = PDF_DOCUMENT (document);
+
+	return poppler_document_has_attachments (pdf_document->document);
+}
+
+struct SaveToBufferData {
+	gchar *buffer;
+	gsize len, max;
+};
+
+static gboolean
+attachment_save_to_buffer_callback (const gchar  *buf,
+				    gsize         count,
+				    gpointer      user_data,
+				    GError      **error)
+{
+	struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
+	gchar *new_buffer;
+	gsize new_max;
+
+	if (sdata->len + count > sdata->max) {
+		new_max = MAX (sdata->max * 2, sdata->len + count);
+		new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
+
+		sdata->buffer = new_buffer;
+		sdata->max = new_max;
+	}
+	
+	memcpy (sdata->buffer + sdata->len, buf, count);
+	sdata->len += count;
+	
+	return TRUE;
+}
+
+static gboolean
+attachment_save_to_buffer (PopplerAttachment  *attachment,
+			   gchar             **buffer,
+			   gsize              *buffer_size,
+			   GError            **error)
+{
+	static const gint initial_max = 1024;
+	struct SaveToBufferData sdata;
+
+	*buffer = NULL;
+	*buffer_size = 0;
+
+	sdata.buffer = (gchar *) g_malloc (initial_max);
+	sdata.max = initial_max;
+	sdata.len = 0;
+
+	if (! poppler_attachment_save_to_callback (attachment,
+						   attachment_save_to_buffer_callback,
+						   &sdata,
+						   error)) {
+		g_free (sdata.buffer);
+		return FALSE;
+	}
+
+	*buffer = sdata.buffer;
+	*buffer_size = sdata.len;
+	
+	return TRUE;
+}
+
+static GList *
+pdf_document_get_attachments (EvDocument *document)
+{
+	PdfDocument *pdf_document;
+	GList *attachments;
+	GList *list;
+	GList *retval = NULL;
+
+	pdf_document = PDF_DOCUMENT (document);
+
+	if (!pdf_document_has_attachments (document))
+		return NULL;
+
+	attachments = poppler_document_get_attachments (pdf_document->document);
+	
+	for (list = attachments; list; list = list->next) {
+		PopplerAttachment *attachment;
+		EvAttachment *ev_attachment;
+		gchar *data = NULL;
+		gsize size;
+		GError *error = NULL;
+
+		attachment = (PopplerAttachment *) list->data;
+
+		if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
+			ev_attachment = ev_attachment_new (attachment->name,
+							   attachment->description,
+							   attachment->mtime,
+							   attachment->ctime,
+							   size, data);
 			
+			retval = g_list_prepend (retval, ev_attachment);
+		} else {
+			if (error) {
+				g_warning ("%s", error->message);
+				g_error_free (error);
+
+				g_free (data);
+			}
+		}
+
+		g_object_unref (attachment);
+	}
+
+	return g_list_reverse (retval);
+}
 
 static GdkPixbuf *
 pdf_document_render_pixbuf (EvDocument   *document,
@@ -551,6 +667,8 @@
 	iface->get_page_size = pdf_document_get_page_size;
 	iface->get_page_label = pdf_document_get_page_label;
 	iface->get_links = pdf_document_get_links;
+	iface->has_attachments = pdf_document_has_attachments;
+	iface->get_attachments = pdf_document_get_attachments;
 	iface->render_pixbuf = pdf_document_render_pixbuf;
 	iface->get_text = pdf_document_get_text;
 	iface->can_get_text = pdf_document_can_get_text;
Index: shell/Makefile.am
===================================================================
RCS file: /cvs/gnome/evince/shell/Makefile.am,v
retrieving revision 1.62
diff -u -u -r1.62 Makefile.am
--- shell/Makefile.am	30 Mar 2006 22:20:34 -0000	1.62
+++ shell/Makefile.am	2 Apr 2006 17:54:16 -0000
@@ -63,6 +63,8 @@
 	ev-sidebar-page.h		\
 	ev-sidebar-thumbnails.c		\
 	ev-sidebar-thumbnails.h		\
+	ev-attachment-bar.c		\
+	ev-attachment-bar.h		\
 	ev-stock-icons.c		\
 	ev-stock-icons.h		\
 	main.c
Index: shell/ev-attachment-bar.c
===================================================================
RCS file: shell/ev-attachment-bar.c
diff -N shell/ev-attachment-bar.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ shell/ev-attachment-bar.c	2 Apr 2006 17:54:16 -0000
@@ -0,0 +1,592 @@
+/* ev-attachment-bar.c
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2006 Carlos Garcia Campos
+ *
+ * Author:
+ *   Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince 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.
+ */
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <string.h>
+#include <libgnomeui/gnome-icon-lookup.h>
+
+#include "ev-attachment-bar.h"
+
+#define MIN_HEIGHT 92
+
+enum {
+	COLUMN_ICON,
+	COLUMN_NAME,
+	COLUMN_DESCRIPTION,
+	COLUMN_ATTACHMENT,
+	N_COLS
+};
+
+enum {
+	SIGNAL_POPUP_MENU,
+	N_SIGNALS
+};
+
+static const GtkTargetEntry drag_targets[] = {
+	{ "text/uri-list", 0, 0 }
+};
+
+static guint signals[N_SIGNALS];
+
+struct _EvAttachmentBarPrivate {
+	GtkWidget      *label;
+	GtkWidget      *icon_view;
+	GtkListStore   *model;
+
+	/* Icons */
+	GtkIconTheme   *icon_theme;
+	GHashTable     *icon_cache;
+};
+
+G_DEFINE_TYPE (EvAttachmentBar, ev_attachment_bar, GTK_TYPE_EXPANDER)
+
+#define EV_ATTACHMENT_BAR_GET_PRIVATE(object) \
+                (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_ATTACHMENT_BAR, EvAttachmentBarPrivate))
+
+/* Icon cache */
+static void
+ev_attachment_bar_icon_cache_add (EvAttachmentBar *ev_attachbar,
+				  const gchar     *mime_type,
+				  const GdkPixbuf *pixbuf)
+{
+	g_assert (mime_type != NULL);
+	g_assert (GDK_IS_PIXBUF (pixbuf));
+
+	g_hash_table_insert (ev_attachbar->priv->icon_cache,
+			     (gpointer)g_strdup (mime_type),
+			     (gpointer)pixbuf);
+			     
+}
+
+static GdkPixbuf *
+icon_theme_get_pixbuf_from_mime_type (GtkIconTheme *icon_theme,
+				      const gchar  *mime_type)
+{
+	GdkPixbuf *pixbuf = NULL;
+	gchar     *icon;
+
+	icon = gnome_icon_lookup (icon_theme,
+				  NULL, NULL,
+				  NULL, NULL,
+				  mime_type,
+				  GNOME_ICON_LOOKUP_FLAGS_NONE,
+				  NULL);
+
+	pixbuf = gtk_icon_theme_load_icon (icon_theme,
+					   icon, 48, 0, NULL);
+	g_free (icon);
+
+	return pixbuf;
+}
+
+static GdkPixbuf *
+ev_attachment_bar_icon_cache_get (EvAttachmentBar *ev_attachbar,
+				  const gchar     *mime_type)
+{
+	GdkPixbuf *pixbuf = NULL;
+	
+	g_assert (mime_type != NULL);
+
+	pixbuf = g_hash_table_lookup (ev_attachbar->priv->icon_cache,
+				      mime_type);
+
+	if (GDK_IS_PIXBUF (pixbuf))
+		return pixbuf;
+
+	pixbuf = icon_theme_get_pixbuf_from_mime_type (ev_attachbar->priv->icon_theme,
+						       mime_type);
+
+	if (GDK_IS_PIXBUF (pixbuf))
+		ev_attachment_bar_icon_cache_add (ev_attachbar,
+						  mime_type,
+						  pixbuf);
+
+	return pixbuf;
+}
+
+static gboolean
+icon_cache_update_icon (gchar           *key,
+			GdkPixbuf       *value,
+			EvAttachmentBar *ev_attachbar)
+{
+	GdkPixbuf *pixbuf = NULL;
+
+	pixbuf = icon_theme_get_pixbuf_from_mime_type (ev_attachbar->priv->icon_theme,
+						       key);
+
+	ev_attachment_bar_icon_cache_add (ev_attachbar,
+					  key,
+					  pixbuf);
+	
+	return FALSE;
+}
+
+static void
+ev_attachment_bar_icon_cache_refresh (EvAttachmentBar *ev_attachbar)
+{
+	g_hash_table_foreach_remove (ev_attachbar->priv->icon_cache,
+				     (GHRFunc) icon_cache_update_icon,
+				     ev_attachbar);
+}
+
+static void
+ev_attachment_bar_toggled (GObject    *object,
+			   GParamSpec *param_spec,
+			   gpointer    user_data)
+{
+	EvAttachmentBar *attachbar = EV_ATTACHMENT_BAR (object);
+	GtkExpander     *expander = GTK_EXPANDER (object);
+
+	if (!attachbar->priv->label)
+		return;
+	
+	if (gtk_expander_get_expanded (expander)) {
+		gtk_label_set_text (GTK_LABEL (attachbar->priv->label),
+				    _("Hide attachments bar"));
+	} else {
+		gtk_label_set_text (GTK_LABEL (attachbar->priv->label),
+				    _("Show attachments bar"));
+	}
+}
+
+static EvAttachment *
+ev_attachment_bar_get_attachment_at_pos (EvAttachmentBar *ev_attachbar,
+					 gint             x,
+					 gint             y)
+{
+	GtkTreePath  *path = NULL;
+	GtkTreeIter   iter;
+	EvAttachment *attachment = NULL;
+
+	path = gtk_icon_view_get_path_at_pos (GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
+					      x, y);
+	if (!path) {
+		return NULL;
+	}
+
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
+				 &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
+			    COLUMN_ATTACHMENT, &attachment,
+			    -1);
+
+	gtk_icon_view_select_path (GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
+				   path);
+	
+	gtk_tree_path_free (path);
+
+	return attachment;
+}
+
+static gboolean
+ev_attachment_bar_button_press (EvAttachmentBar *ev_attachbar,
+				GdkEventButton  *event,
+				GtkWidget       *icon_view)
+{
+	EvAttachment *attachment;
+	gboolean      handled = FALSE;
+
+	if (!GTK_WIDGET_HAS_FOCUS (icon_view)) {
+		gtk_widget_grab_focus (icon_view);
+	}
+	
+	if (event->button == 2)
+		return FALSE;
+
+	attachment = ev_attachment_bar_get_attachment_at_pos (ev_attachbar,
+							      event->x,
+							      event->y);
+	if (!attachment)
+		return FALSE;
+
+	switch (event->button) {
+	case 1:
+		if (event->type == GDK_2BUTTON_PRESS) {
+			GError *error = NULL;
+
+			ev_attachment_open (attachment, &error);
+
+			if (error) {
+				g_warning (error->message);
+				g_error_free (error);
+			}
+					    
+			handled = TRUE;
+		}
+		break;
+	case 3:
+		g_signal_emit (ev_attachbar, signals[SIGNAL_POPUP_MENU], 0, attachment);
+		handled = TRUE;
+		
+		break;
+	}
+
+	g_object_unref (attachment);
+
+	return handled;
+}
+
+static gboolean
+ev_attachment_bar_focus_in (GtkWidget     *widget,
+			    GdkEventFocus *event)
+{
+	EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (widget);
+
+	if (gtk_expander_get_expanded (GTK_EXPANDER (ev_attachbar)))
+		gtk_widget_grab_focus (ev_attachbar->priv->icon_view);
+
+	return TRUE;
+}
+
+static gboolean
+ev_attachment_bar_popup_menu (GtkWidget *widget)
+{
+	EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (widget);
+	EvAttachment    *attachment;
+	gint             x, y;
+
+	gtk_widget_get_pointer (widget, &x, &y);
+	attachment = ev_attachment_bar_get_attachment_at_pos (ev_attachbar,
+							      x, y);
+	if (!attachment)
+		return FALSE;
+
+	g_signal_emit (ev_attachbar, signals[SIGNAL_POPUP_MENU], 0, attachment);
+
+	return TRUE;
+}
+
+static void
+ev_attachment_bar_update_icons (EvAttachmentBar *ev_attachbar,
+				gpointer         user_data)
+{
+	GtkTreeIter iter;
+	gboolean    valid;
+
+	ev_attachment_bar_icon_cache_refresh (ev_attachbar);
+	
+	valid = gtk_tree_model_get_iter_first (
+		GTK_TREE_MODEL (ev_attachbar->priv->model),
+		&iter);
+
+	while (valid) {
+		EvAttachment *attachment = NULL;
+		GdkPixbuf    *pixbuf = NULL;
+		const gchar  *mime_type;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
+				    COLUMN_ATTACHMENT, &attachment,
+				    -1);
+
+		mime_type = ev_attachment_get_mime_type (attachment);
+
+		if (attachment)
+			g_object_unref (attachment);
+
+		pixbuf = ev_attachment_bar_icon_cache_get (ev_attachbar,
+							   mime_type);
+
+		gtk_list_store_set (ev_attachbar->priv->model, &iter,
+				    COLUMN_ICON, pixbuf,
+				    -1);
+
+		valid = gtk_tree_model_iter_next (
+			GTK_TREE_MODEL (ev_attachbar->priv->model),
+			&iter);
+	}
+}
+
+static void
+ev_attachment_bar_drag_data_get (GtkWidget        *widget,
+				 GdkDragContext   *drag_context,
+				 GtkSelectionData *data,
+				 guint             info,
+				 guint             time,
+				 gpointer          user_data)
+{
+	EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (user_data);
+	EvAttachment    *attachment;
+	GtkTreePath     *path;
+	GtkTreeIter      iter;
+	GList           *selected = NULL;
+	gchar           *uri, *filename;
+	GError          *error = NULL;
+
+	selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (ev_attachbar->priv->icon_view));
+	if (!selected)
+		return;
+
+	path = (GtkTreePath *) selected->data;
+
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
+				 &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
+			    COLUMN_ATTACHMENT, &attachment,
+			    -1);
+
+	filename = g_build_filename (g_get_tmp_dir (),
+				     ev_attachment_get_name (attachment),
+				     NULL);
+	uri = g_filename_to_uri (filename, NULL, NULL);
+
+	g_object_set_data_full (G_OBJECT (drag_context),
+				"tmp-filename", filename,
+				g_free);
+	
+	
+	if (ev_attachment_save (attachment, uri, &error)) {
+		gtk_selection_data_set (data,
+					data->target,
+					8,
+					(guchar *)uri,
+					strlen (uri));
+	}
+	
+	if (error) {
+		g_warning (error->message);
+		g_error_free (error);
+	}
+
+	g_free (uri);
+	g_object_unref (attachment);
+	g_list_foreach (selected,
+			(GFunc) gtk_tree_path_free,
+			NULL);
+	g_list_free (selected);
+}
+
+static void
+ev_attachment_bar_drag_data_delete (GtkWidget      *widget,
+				    GdkDragContext *drag_context,
+				    gpointer        user_data)
+{
+	gchar *filename;
+
+	filename = g_object_get_data (G_OBJECT (drag_context), "tmp-filename");
+	
+	if (filename && g_file_test (filename, G_FILE_TEST_EXISTS))
+		g_unlink (filename);
+}
+
+static void
+ev_attachment_bar_destroy (GtkObject *object)
+{
+	EvAttachmentBar *ev_attachbar = EV_ATTACHMENT_BAR (object);
+
+	if (ev_attachbar->priv->model) {
+		g_object_unref (ev_attachbar->priv->model);
+		ev_attachbar->priv->model = NULL;
+	}
+
+	if (ev_attachbar->priv->icon_cache) {
+		g_hash_table_destroy (ev_attachbar->priv->icon_cache);
+		ev_attachbar->priv->icon_cache = NULL;
+	}
+
+	(* GTK_OBJECT_CLASS (ev_attachment_bar_parent_class)->destroy) (object);
+}
+
+static void
+ev_attachment_bar_class_init (EvAttachmentBarClass *ev_attachbar_class)
+{
+	GObjectClass   *g_object_class;
+	GtkObjectClass *gtk_object_class;
+	GtkWidgetClass *gtk_widget_class;
+
+	g_object_class = G_OBJECT_CLASS (ev_attachbar_class);
+	gtk_object_class = GTK_OBJECT_CLASS (ev_attachbar_class);
+	gtk_widget_class = GTK_WIDGET_CLASS (ev_attachbar_class);
+
+	gtk_object_class->destroy = ev_attachment_bar_destroy;
+	gtk_widget_class->popup_menu = ev_attachment_bar_popup_menu;
+	gtk_widget_class->focus_in_event = ev_attachment_bar_focus_in;
+
+	g_type_class_add_private (g_object_class, sizeof (EvAttachmentBarPrivate));
+
+	/* Signals */
+	signals[SIGNAL_POPUP_MENU] =
+		g_signal_new ("popup",
+			      G_TYPE_FROM_CLASS (g_object_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+			      G_STRUCT_OFFSET (EvAttachmentBarClass, popup_menu),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1,
+			      G_TYPE_OBJECT);
+}
+
+static void
+ev_attachment_bar_init (EvAttachmentBar *ev_attachbar)
+{
+	GtkWidget *swindow;
+	
+	ev_attachbar->priv = EV_ATTACHMENT_BAR_GET_PRIVATE (ev_attachbar);
+
+	swindow = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
+					GTK_POLICY_NEVER,
+					GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
+					     GTK_SHADOW_IN);
+	gtk_widget_set_size_request (swindow, -1, MIN_HEIGHT);
+
+	/* Data Model */
+	ev_attachbar->priv->model = gtk_list_store_new (N_COLS,
+							GDK_TYPE_PIXBUF, 
+							G_TYPE_STRING,  
+							G_TYPE_STRING,
+							EV_TYPE_ATTACHMENT);
+
+	/* Icon View */
+	ev_attachbar->priv->icon_view =
+		gtk_icon_view_new_with_model (GTK_TREE_MODEL (ev_attachbar->priv->model));
+	gtk_icon_view_set_columns (GTK_ICON_VIEW (ev_attachbar->priv->icon_view), -1);
+	g_object_set (G_OBJECT (ev_attachbar->priv->icon_view),
+		      "text-column", COLUMN_NAME,
+		      "pixbuf-column", COLUMN_ICON,
+		      NULL);
+	g_signal_connect_swapped (G_OBJECT (ev_attachbar->priv->icon_view),
+				  "button-press-event",
+				  G_CALLBACK (ev_attachment_bar_button_press),
+				  (gpointer) ev_attachbar);
+
+	gtk_container_add (GTK_CONTAINER (swindow),
+			   ev_attachbar->priv->icon_view);
+	gtk_widget_show (ev_attachbar->priv->icon_view);
+
+	gtk_container_add (GTK_CONTAINER (ev_attachbar),
+			   swindow);
+	gtk_widget_show (swindow);
+
+	/* Icon Theme */
+	ev_attachbar->priv->icon_theme = gtk_icon_theme_get_default ();
+	g_signal_connect_swapped (G_OBJECT (ev_attachbar->priv->icon_theme),
+				  "changed",
+				  G_CALLBACK (ev_attachment_bar_update_icons),
+				  (gpointer) ev_attachbar);
+
+	/* Icon Cache */
+	ev_attachbar->priv->icon_cache = g_hash_table_new_full (g_str_hash,
+								g_str_equal,
+								g_free,
+								g_object_unref);
+
+	/* Drag and Drop */
+	gtk_icon_view_enable_model_drag_source (
+		GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
+			       GDK_BUTTON1_MASK,
+			       drag_targets,
+			       G_N_ELEMENTS (drag_targets),
+			       GDK_ACTION_MOVE);
+	g_signal_connect (G_OBJECT (ev_attachbar->priv->icon_view),
+			  "drag-data-get",
+			  G_CALLBACK (ev_attachment_bar_drag_data_get),
+			  (gpointer) ev_attachbar);
+	g_signal_connect (G_OBJECT (ev_attachbar->priv->icon_view),
+			  "drag-data-delete",
+			  G_CALLBACK (ev_attachment_bar_drag_data_delete),
+			  (gpointer) ev_attachbar);
+
+	g_signal_connect (G_OBJECT (ev_attachbar),
+			  "notify::expanded",
+			  G_CALLBACK (ev_attachment_bar_toggled),
+			  NULL);
+	
+}
+
+static void
+ev_attachment_bar_setup (EvAttachmentBar *ev_attachbar)
+{
+	GtkWidget *hbox;
+	GtkWidget *image;
+
+	hbox = gtk_hbox_new (FALSE, 6);
+	image = gtk_image_new_from_stock ("gnome-stock-attach",
+					  GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    image,
+			    FALSE, FALSE, 0);
+	gtk_widget_show (image);
+
+	ev_attachbar->priv->label = gtk_label_new (_("Show attachments bar"));
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    ev_attachbar->priv->label,
+			    FALSE, FALSE, 0);
+	gtk_widget_show (ev_attachbar->priv->label);
+
+	gtk_expander_set_label_widget (GTK_EXPANDER (ev_attachbar), hbox);
+	gtk_widget_show (hbox);
+}
+
+GtkWidget *
+ev_attachment_bar_new (void)
+{
+	GtkWidget *ev_attachbar;
+
+	ev_attachbar = g_object_new (EV_TYPE_ATTACHMENT_BAR, NULL);
+
+	ev_attachment_bar_setup (EV_ATTACHMENT_BAR (ev_attachbar));
+
+	return ev_attachbar;
+}
+
+void
+ev_attachment_bar_set_document (EvAttachmentBar *ev_attachbar,
+				EvDocument      *document)
+{
+	GList *attachments = NULL;
+	GList *l;
+	
+	if (!ev_document_has_attachments (document))
+		return;
+
+	attachments = ev_document_get_attachments (document);
+
+	gtk_list_store_clear (ev_attachbar->priv->model);
+					   
+	for (l = attachments; l && l->data; l = g_list_next (l)) {
+		EvAttachment *attachment;
+		GtkTreeIter   iter;
+		GdkPixbuf    *pixbuf = NULL;
+		const gchar  *mime_type;
+
+		attachment = EV_ATTACHMENT (l->data);
+
+		mime_type = ev_attachment_get_mime_type (attachment);
+		pixbuf = ev_attachment_bar_icon_cache_get (ev_attachbar,
+							   mime_type);
+
+		gtk_list_store_append (ev_attachbar->priv->model, &iter);
+		gtk_list_store_set (ev_attachbar->priv->model, &iter,
+				    COLUMN_NAME, ev_attachment_get_name (attachment),
+				    COLUMN_ICON, pixbuf,
+				    COLUMN_ATTACHMENT, attachment, 
+				    -1);
+
+		g_object_unref (attachment);
+	}
+
+	g_list_free (attachments);
+}
Index: shell/ev-attachment-bar.h
===================================================================
RCS file: shell/ev-attachment-bar.h
diff -N shell/ev-attachment-bar.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ shell/ev-attachment-bar.h	2 Apr 2006 17:54:16 -0000
@@ -0,0 +1,66 @@
+/* ev-attachment-bar.h
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2006 Carlos Garcia Campos
+ *
+ * Author:
+ *   Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince 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 __EV_ATTACHMENT_BAR_H__
+#define __EV_ATTACHMENT_BAR_H__
+
+#include <gtk/gtkexpander.h>
+#include "ev-attachment.h"
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+typedef struct _EvAttachmentBar        EvAttachmentBar;
+typedef struct _EvAttachmentBarClass   EvAttachmentBarClass;
+typedef struct _EvAttachmentBarPrivate EvAttachmentBarPrivate;
+
+#define EV_TYPE_ATTACHMENT_BAR              (ev_attachment_bar_get_type())
+#define EV_ATTACHMENT_BAR(object)           (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_ATTACHMENT_BAR, EvAttachmentBar))
+#define EV_ATTACHMENT_BAR_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_ATTACHMENT_BAR, EvAttachmentBarClass))
+#define EV_IS_ATTACHMENT_BAR(object)        (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_ATTACHMENT_BAR))
+#define EV_IS_ATTACHMENT_BAR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_ATTACHMENT_BAR))
+#define EV_ATTACHMENT_BAR_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_ATTACHMENT_BAR, EvAttachmentBarClass))
+
+struct _EvAttachmentBar {
+	GtkExpander base_instance;
+
+	EvAttachmentBarPrivate *priv;
+};
+
+struct _EvAttachmentBarClass {
+	GtkExpanderClass base_class;
+
+	/* Signals */
+	void (*popup_menu) (EvAttachmentBar *ev_attachbar,
+			    EvAttachment    *attachment);
+};
+
+GType      ev_attachment_bar_get_type     (void) G_GNUC_CONST;
+GtkWidget *ev_attachment_bar_new          (void);
+
+void       ev_attachment_bar_set_document (EvAttachmentBar *ev_attachbar,
+					   EvDocument      *document);
+
+G_END_DECLS
+
+#endif /* __EV_ATTACHMENT_BAR_H__ */
Index: shell/ev-window.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-window.c,v
retrieving revision 1.266
diff -u -u -r1.266 ev-window.c
--- shell/ev-window.c	30 Mar 2006 22:20:34 -0000	1.266
+++ shell/ev-window.c	2 Apr 2006 17:54:18 -0000
@@ -37,6 +37,7 @@
 #include "ev-view.h"
 #include "ev-password.h"
 #include "ev-password-view.h"
+#include "ev-attachment-bar.h"
 #include "ev-properties-dialog.h"
 #include "ev-ps-exporter.h"
 #include "ev-document-thumbnails.h"
@@ -108,6 +109,7 @@
 	GtkWidget *password_view;
 	GtkWidget *sidebar_thumbs;
 	GtkWidget *sidebar_links;
+	GtkWidget *attachment_bar;
 
 	/* Dialogs */
 	GtkWidget *properties;
@@ -118,7 +120,8 @@
 
 	/* UI Builders */
 	GtkActionGroup *action_group;
-	GtkActionGroup *popups_action_group;
+	GtkActionGroup *view_popup_action_group;
+	GtkActionGroup *attachment_popup_action_group;
 	GtkUIManager   *ui_manager;
 
 	/* Fullscreen mode */
@@ -127,9 +130,13 @@
 	GSource   *fullscreen_timeout_source;
 	
 	/* Popup link */
-	GtkWidget *popup;
+	GtkWidget *view_popup;
 	EvLink    *link;
 
+	/* Popup attachment */
+	GtkWidget    *attachment_popup;
+	EvAttachment *attachment;
+
 	/* Document */
 	char *uri;
 	char *local_uri;
@@ -170,42 +177,46 @@
 #define LINKS_SIDEBAR_ID "links"
 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
 
-static void	ev_window_update_actions	 	(EvWindow *ev_window);
-static void     ev_window_update_fullscreen_popup       (EvWindow         *window);
-static void     ev_window_sidebar_visibility_changed_cb (EvSidebar        *ev_sidebar,
-							 GParamSpec       *pspec,
-							 EvWindow         *ev_window);
-static void     ev_window_set_page_mode                 (EvWindow         *window,
-							 EvWindowPageMode  page_mode);
-static void	ev_window_load_job_cb  			(EvJobLoad *job,
-							 gpointer data);
-static void	ev_window_xfer_job_cb  			(EvJobXfer *job,
-							 gpointer data);
-static void     ev_window_sizing_mode_changed_cb        (EvView           *view,
-							 GParamSpec       *pspec,
-							 EvWindow         *ev_window);
-static void     ev_window_zoom_changed_cb 	        (EvView           *view,
-							 GParamSpec       *pspec,
-							 EvWindow         *ev_window);
-static void     ev_window_add_recent                    (EvWindow         *window,
-							 const char       *filename);
-static void     ev_window_run_fullscreen                (EvWindow         *window);
-static void     ev_window_stop_fullscreen               (EvWindow         *window);
-static void     ev_window_cmd_view_fullscreen           (GtkAction        *action,
-							 EvWindow         *window);
-static void     ev_window_run_presentation              (EvWindow         *window);
-static void     ev_window_stop_presentation             (EvWindow         *window);
-static void     ev_window_cmd_view_presentation         (GtkAction        *action,
-							 EvWindow         *window);
-static void     show_fullscreen_popup                   (EvWindow         *window);
-static void     ev_popup_cmd_open_link                  (GtkAction        *action,
-							 EvWindow         *window);
-static void     ev_popup_cmd_copy_link_address          (GtkAction        *action,
-							 EvWindow         *window);
-static void	ev_window_cmd_view_best_fit 		(GtkAction 	  *action, 
-							 EvWindow 	  *ev_window);
-static void	ev_window_cmd_view_page_width 		(GtkAction 	  *action, 
-							 EvWindow 	  *ev_window);
+static void     ev_window_update_actions                   (EvWindow         *ev_window);
+static void     ev_window_update_fullscreen_popup          (EvWindow         *window);
+static void     ev_window_sidebar_visibility_changed_cb    (EvSidebar        *ev_sidebar,
+							    GParamSpec       *pspec,
+							    EvWindow         *ev_window);
+static void     ev_window_set_page_mode                    (EvWindow         *window,
+							    EvWindowPageMode  page_mode);
+static void	ev_window_load_job_cb  			   (EvJobLoad        *job,
+							    gpointer          data);
+static void	ev_window_xfer_job_cb  			   (EvJobXfer        *job,
+							    gpointer          data);
+static void     ev_window_sizing_mode_changed_cb           (EvView           *view,
+							    GParamSpec       *pspec,
+							    EvWindow         *ev_window);
+static void     ev_window_zoom_changed_cb 	           (EvView           *view,
+							    GParamSpec       *pspec,
+							    EvWindow         *ev_window);
+static void     ev_window_add_recent                       (EvWindow         *window,
+							    const char       *filename);
+static void     ev_window_run_fullscreen                   (EvWindow         *window);
+static void     ev_window_stop_fullscreen                  (EvWindow         *window);
+static void     ev_window_cmd_view_fullscreen              (GtkAction        *action,
+							    EvWindow         *window);
+static void     ev_window_run_presentation                 (EvWindow         *window);
+static void     ev_window_stop_presentation                (EvWindow         *window);
+static void     ev_window_cmd_view_presentation            (GtkAction        *action,
+							    EvWindow         *window);
+static void     show_fullscreen_popup                      (EvWindow         *window);
+static void     ev_view_popup_cmd_open_link                (GtkAction        *action,
+							    EvWindow         *window);
+static void     ev_view_popup_cmd_copy_link_address        (GtkAction        *action,
+							    EvWindow         *window);
+static void     ev_attachment_popup_cmd_open_attachment    (GtkAction        *action,
+							    EvWindow         *window);
+static void     ev_attachment_popup_cmd_save_attachment_as (GtkAction        *action,
+							    EvWindow         *window);
+static void	ev_window_cmd_view_best_fit 		   (GtkAction 	     *action, 
+							    EvWindow 	     *ev_window);
+static void	ev_window_cmd_view_page_width 		   (GtkAction 	     *action, 
+							    EvWindow 	     *ev_window);
 
 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
 
@@ -388,7 +399,7 @@
 static void
 set_widget_visibility (GtkWidget *widget, gboolean visible)
 {
-	g_return_if_fail (GTK_IS_WIDGET (widget));
+	g_assert (GTK_IS_WIDGET (widget));
 	
 	if (visible)
 		gtk_widget_show (widget);
@@ -666,6 +677,14 @@
 }
 
 static void
+update_attachment_bar_visibility (EvWindow *window)
+{
+	set_widget_visibility (window->priv->attachment_bar,
+			       (window->priv->document &&
+			       ev_document_has_attachments (window->priv->document)));
+}
+
+static void
 setup_document_from_metadata (EvWindow *window)
 {
 	char *uri = window->priv->uri;
@@ -835,6 +854,7 @@
 	EvDocument *document;
 	EvView *view = EV_VIEW (ev_window->priv->view);
 	EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
+	EvAttachmentBar *attachbar = EV_ATTACHMENT_BAR (ev_window->priv->attachment_bar);
 	GtkAction *action;
 
 	document = ev_window->priv->document;
@@ -855,6 +875,9 @@
 	}
 	ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
 
+	ev_attachment_bar_set_document (attachbar, document);
+	update_attachment_bar_visibility (ev_window);
+
 	ev_window_title_set_document (ev_window->priv->title, document);
 	ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
 
@@ -1748,6 +1771,7 @@
 
 	update_chrome_visibility (window);
 	gtk_widget_hide (window->priv->sidebar);
+	gtk_widget_hide (window->priv->attachment_bar);
 
 	g_object_set (G_OBJECT (window->priv->scrolled_window),
 		      "shadow-type", GTK_SHADOW_NONE,
@@ -1797,6 +1821,7 @@
 	gtk_window_unfullscreen (GTK_WINDOW (window));
 	update_chrome_visibility (window);
 	update_sidebar_visibility (window);
+	update_attachment_bar_visibility (window);
 
 	if (!ev_window_is_empty (window))
 		ev_metadata_manager_set_boolean (window->priv->uri, "fullscreen", FALSE);
@@ -1845,6 +1870,7 @@
 	ev_window_update_presentation_action (window);
 	update_chrome_visibility (window);
 	gtk_widget_hide (window->priv->sidebar);
+	gtk_widget_hide (window->priv->attachment_bar);
 
 	if (!ev_window_is_empty (window))
 		ev_metadata_manager_set_boolean (window->priv->uri, "presentation", TRUE);
@@ -1864,6 +1890,7 @@
 	ev_window_update_presentation_action (window);
 	update_chrome_visibility (window);
 	update_sidebar_visibility (window);
+	update_attachment_bar_visibility (window);
 
 	if (!ev_window_is_empty (window))
 		ev_metadata_manager_set_boolean (window->priv->uri, "presentation", FALSE);
@@ -2519,6 +2546,18 @@
 	}
 }
 
+static void
+ev_window_attachment_bar_toggled_cb (EvAttachmentBar *ev_attachbar,
+				     GParamSpec      *param_spec,
+				     EvWindow        *ev_window)
+{
+	if (gtk_expander_get_expanded (GTK_EXPANDER (ev_attachbar))) {
+		gtk_widget_grab_focus (GTK_WIDGET (ev_attachbar));
+	} else {
+		gtk_widget_grab_focus (ev_window->priv->view);
+	}
+}
+
 static gboolean
 view_menu_popup_cb (EvView         *view,
 		    EvLink         *link,
@@ -2539,7 +2578,7 @@
 	else	
 		ev_window->priv->link = NULL;
 
-	popup = ev_window->priv->popup;
+	popup = ev_window->priv->view_popup;
 
 	if (ev_window->priv->link) 
 		switch (ev_link_get_link_type (ev_window->priv->link)) {
@@ -2559,15 +2598,15 @@
 				break;
 		}
 	
-	action = gtk_action_group_get_action (ev_window->priv->popups_action_group,
+	action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
 					      "OpenLink");
 	gtk_action_set_visible (action, show_external);
 
-	action = gtk_action_group_get_action (ev_window->priv->popups_action_group,
+	action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
 					      "CopyLinkAddress");
 	gtk_action_set_visible (action, show_external);
 
-	action = gtk_action_group_get_action (ev_window->priv->popups_action_group,
+	action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
 					      "GoLink");
 	gtk_action_set_visible (action, show_internal);
 
@@ -2578,6 +2617,27 @@
 }
 
 static void
+attachment_bar_menu_popup_cb (EvAttachmentBar *attachbar,
+			      EvAttachment    *attachment,
+			      EvWindow        *ev_window)
+{
+	GtkWidget *popup;
+
+	if (ev_window->priv->attachment)
+		g_object_unref (ev_window->priv->attachment);
+	if (attachment)
+		ev_window->priv->attachment = g_object_ref (attachment);
+	else
+		ev_window->priv->attachment = NULL;
+	
+	popup = ev_window->priv->attachment_popup;
+
+	gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
+			NULL, NULL,
+			3, gtk_get_current_event_time ());
+}
+
+static void
 view_find_status_changed_cb (EvView     *view,
 			     GParamSpec *pspec,
 			     EvWindow   *ev_window)
@@ -2725,9 +2785,14 @@
 		priv->action_group = NULL;
 	}
 
-	if (priv->popups_action_group) {
-		g_object_unref (priv->popups_action_group);
-		priv->popups_action_group = NULL;
+	if (priv->view_popup_action_group) {
+		g_object_unref (priv->view_popup_action_group);
+		priv->view_popup_action_group = NULL;
+	}
+
+	if (priv->attachment_popup_action_group) {
+		g_object_unref (priv->attachment_popup_action_group);
+		priv->attachment_popup_action_group = NULL;
 	}
 
 	if (priv->page_cache) {
@@ -2765,6 +2830,11 @@
 		priv->link = NULL;
 	}
 
+	if (priv->attachment) {
+		g_object_unref (priv->attachment);
+		priv->attachment = NULL;
+	}
+
 	if (priv->find_bar) {
 		g_signal_handlers_disconnect_by_func
 			(window->priv->find_bar,
@@ -2956,18 +3026,46 @@
 };
 
 /* Popups specific items */
-static const GtkActionEntry popups_entries [] = {
+static const GtkActionEntry view_popup_entries [] = {
 	/* Links */
 	{ "OpenLink", GTK_STOCK_OPEN, N_("_Open Link"), NULL,
-	  NULL, G_CALLBACK (ev_popup_cmd_open_link) },
+	  NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
 	{ "GoLink", GTK_STOCK_GO_FORWARD, N_("_Go To"), NULL,
-	  NULL, G_CALLBACK (ev_popup_cmd_open_link) },
+	  NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
 	{ "CopyLinkAddress", NULL, N_("_Copy Link Address"), NULL,
 	  NULL,
-	  G_CALLBACK (ev_popup_cmd_copy_link_address) },
+	  G_CALLBACK (ev_view_popup_cmd_copy_link_address) },
+};
+
+static const GtkActionEntry attachment_popup_entries [] = {
+	{ "OpenAttachment", GTK_STOCK_OPEN, N_("_Open..."), NULL,
+	  NULL, G_CALLBACK (ev_attachment_popup_cmd_open_attachment) },
+	{ "SaveAttachmentAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy..."), NULL,
+	  NULL, G_CALLBACK (ev_attachment_popup_cmd_save_attachment_as) },
 };
 
 static void
+drag_motion_cb (GtkWidget      *widget,
+		GdkDragContext *context,
+		gint            x,
+		gint            y,
+		guint           time,
+		gpointer        user_data)
+{
+	/* Only accept 'move' from myself, but we don't
+	 * want to remove the file, since we need it in order to
+	 * be able to reload it. We avoid it by changing
+	 * the action to 'copy'. The file will always be in /tmp
+	 */
+	if (context->suggested_action == GDK_ACTION_MOVE) {
+		if (gtk_drag_get_source_widget (context))
+			context->action = GDK_ACTION_COPY;
+		else	
+			gdk_drag_abort (context, time);
+	}
+}
+
+static void
 drag_data_received_cb (GtkWidget *widget, GdkDragContext *context,
 		       gint x, gint y, GtkSelectionData *selection_data,
 		       guint info, guint time, gpointer gdata)
@@ -2991,8 +3089,6 @@
 		ev_application_open_uri_list (EV_APP, uris, 0);
 		
 		g_slist_free (uris);
-
-		gtk_drag_finish (context, TRUE, FALSE, time);
 	}
 }
 
@@ -3264,13 +3360,13 @@
 }
 
 static void
-ev_popup_cmd_open_link (GtkAction *action, EvWindow *window)
+ev_view_popup_cmd_open_link (GtkAction *action, EvWindow *window)
 {
 	ev_view_goto_link (EV_VIEW (window->priv->view), window->priv->link);
 }
 
 static void
-ev_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
+ev_view_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
 {
 	GtkClipboard *clipboard;
 	const gchar *uri;
@@ -3283,6 +3379,95 @@
 }
 
 static void
+ev_error_dialog (GtkWindow *window, const gchar *msg, GError *error)
+{
+	GtkWidget *dialog;
+
+	dialog = gtk_message_dialog_new (window,
+					 GTK_DIALOG_DESTROY_WITH_PARENT,
+					 GTK_MESSAGE_ERROR,
+					 GTK_BUTTONS_CLOSE,
+					 msg);
+
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+						  "%s", error->message);
+
+	gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+}
+
+static void
+ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window)
+{
+	GError *error = NULL;
+	
+	if (!window->priv->attachment)
+		return;
+	
+	ev_attachment_open (window->priv->attachment, &error);
+
+	if (error) {
+		ev_error_dialog (GTK_WINDOW (window),
+				 _("Unable to open attachment"),
+				 error);
+		g_error_free (error);
+	}
+}
+
+static void
+attachment_save_dialog_response_cb (GtkWidget *fc,
+				    gint       response_id,
+				    EvWindow  *ev_window)
+{
+	if (response_id == GTK_RESPONSE_OK) {
+		const char *uri;
+		GError     *error = NULL;
+
+		uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
+
+		ev_attachment_save (ev_window->priv->attachment, uri, &error);
+
+		if (error) {
+			ev_error_dialog (GTK_WINDOW (fc),
+					 _("The attachment could not be saved."),
+					 error);
+			g_error_free (error);
+		}
+	}
+
+	gtk_widget_destroy (fc);
+}
+
+static void
+ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
+{
+	GtkWidget *fc;
+
+	fc = gtk_file_chooser_dialog_new (_("Save a Copy"),
+					  GTK_WINDOW (window),
+					  GTK_FILE_CHOOSER_ACTION_SAVE,
+					  GTK_STOCK_CANCEL,
+					  GTK_RESPONSE_CANCEL,
+					  GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+					  NULL);
+
+	gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
+
+#ifdef HAVE_GTK_FILE_CHOOSER_SET_DO_OVERWRITE_CONFIRMATION
+	gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
+#endif
+
+	gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
+					   ev_attachment_get_name (window->priv->attachment));
+
+	g_signal_connect (fc, "response",
+			  G_CALLBACK (attachment_save_dialog_response_cb),
+			  window);
+
+	gtk_widget_show (fc);
+}
+
+static void
 ev_window_init (EvWindow *ev_window)
 {
 	GtkActionGroup *action_group;
@@ -3325,11 +3510,21 @@
 
 	ev_window_set_view_accels_sensitivity (ev_window, FALSE);
 
-	action_group = gtk_action_group_new ("PopupsActions");
-	ev_window->priv->popups_action_group = action_group;
+	action_group = gtk_action_group_new ("ViewPopupActions");
+	ev_window->priv->view_popup_action_group = action_group;
+	gtk_action_group_set_translation_domain (action_group, NULL);
+	gtk_action_group_add_actions (action_group, view_popup_entries,
+				      G_N_ELEMENTS (view_popup_entries),
+				      ev_window);
+	gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
+					    action_group, 0);
+
+	action_group = gtk_action_group_new ("AttachmentPopupActions");
+	ev_window->priv->attachment_popup_action_group = action_group;
 	gtk_action_group_set_translation_domain (action_group, NULL);
-	gtk_action_group_add_actions (action_group, popups_entries,
-				      G_N_ELEMENTS (popups_entries), ev_window);
+	gtk_action_group_add_actions (action_group, attachment_popup_entries,
+				      G_N_ELEMENTS (attachment_popup_entries),
+				      ev_window);
 	gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
 					    action_group, 0);
 
@@ -3440,6 +3635,17 @@
 	gtk_widget_show (ev_window->priv->view);
 	gtk_widget_show (ev_window->priv->password_view);
 
+	/* Attachments Bar */
+	ev_window->priv->attachment_bar = ev_attachment_bar_new ();
+	gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
+			  ev_window->priv->attachment_bar,
+			  FALSE, TRUE, 0);
+	g_signal_connect_object (ev_window->priv->attachment_bar,
+				 "popup",
+				 G_CALLBACK (attachment_bar_menu_popup_cb),
+				 ev_window, 0);
+
+	/* Find Bar */
 	ev_window->priv->find_bar = egg_find_bar_new ();
 	gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
 			  ev_window->priv->find_bar,
@@ -3491,6 +3697,12 @@
 			  G_CALLBACK (ev_window_sidebar_current_page_changed_cb),
 			  ev_window);
 
+	/* Connect attachment bar sgignals */
+	g_signal_connect (G_OBJECT (ev_window->priv->attachment_bar),
+			  "notify::expanded",
+			  G_CALLBACK (ev_window_attachment_bar_toggled_cb),
+			  ev_window);
+
 	/* Connect to find bar signals */
 	g_signal_connect (ev_window->priv->find_bar,
 			  "previous",
@@ -3522,19 +3734,26 @@
 			  ev_window);
 
 	/* Popups */
-	ev_window->priv->popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
-				    	    		   "/DocumentPopup");
+	ev_window->priv->view_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
+								 "/DocumentPopup");
 	ev_window->priv->link = NULL;
 
+	ev_window->priv->attachment_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
+								       "/AttachmentPopup");
+	ev_window->priv->attachment = NULL;
+
 	/* Give focus to the document view */
 	gtk_widget_grab_focus (ev_window->priv->view);
 
 	/* Drag and Drop */
 	gtk_drag_dest_unset (GTK_WIDGET (ev_window));
-	gtk_drag_dest_set (GTK_WIDGET (ev_window), GTK_DEST_DEFAULT_ALL, ev_drop_types,
+	gtk_drag_dest_set (GTK_WIDGET (ev_window), GTK_DEST_DEFAULT_ALL,
+			   ev_drop_types,
 			   sizeof (ev_drop_types) / sizeof (ev_drop_types[0]),
-			   GDK_ACTION_COPY);
-	g_signal_connect (G_OBJECT (ev_window), "drag_data_received",
+			   GDK_ACTION_COPY | GDK_ACTION_MOVE);
+	g_signal_connect (G_OBJECT (ev_window), "drag-motion",
+			  G_CALLBACK (drag_motion_cb), NULL);
+	g_signal_connect (G_OBJECT (ev_window), "drag-data-received",
 			  G_CALLBACK (drag_data_received_cb), NULL);
 
 	/* Set it user interface params */
@@ -3544,6 +3763,7 @@
 	set_chrome_actions (ev_window);
 	update_chrome_visibility (ev_window);
 	update_sidebar_visibility (ev_window);
+	update_attachment_bar_visibility (ev_window);
 
 	gtk_window_set_default_size (GTK_WINDOW (ev_window),
 			             600, 600);
