]> www.fi.muni.cz Git - evince.git/commitdiff
Add initial support for password-supported dialogs. This could be a lot
authorJonathan Blandford <jrb@redhat.com>
Wed, 19 Jan 2005 06:12:27 +0000 (06:12 +0000)
committerJonathan Blandford <jrb@src.gnome.org>
Wed, 19 Jan 2005 06:12:27 +0000 (06:12 +0000)
Wed Jan 19 01:10:57 2005  Jonathan Blandford  <jrb@redhat.com>

        * backend/Makefile.am:
        * backend/ev-document-links.h:
        * backend/ev-document-security.c: (ev_document_security_get_type),
        (ev_document_security_has_document_security),
        (ev_document_security_set_password):
        * backend/ev-document-security.h:
        * backend/ev-document.c: (ev_document_error_quark):
        * backend/ev-document.h:
        * data/Makefile.am:
        * data/evince-password.glade:
        * pdf/xpdf/pdf-document.cc:
        * shell/Makefile.am:
        * shell/ev-password.c: (ev_password_set_bad_password_label),
        (ev_window_password_entry_changed_cb), (ev_password_dialog_new),
        (ev_password_dialog_get_password),
        (ev_password_dialog_set_bad_pass):
        * shell/ev-password.h:
        * shell/ev-window.c: (ev_window_get_attribute),
        (ev_window_set_property), (update_action_sensitivity),
        (ev_window_is_empty), (mime_type_supported_by_gdk_pixbuf),
        (ev_window_setup_document), (ev_window_get_password),
        (ev_window_open), (ev_window_cmd_save_as),
        (using_postscript_printer), (ev_window_print),
        (find_not_supported_dialog), (ev_window_cmd_edit_find),
        (update_fullscreen_popup), (ev_window_fullscreen),
        (ev_window_unfullscreen), (ev_window_cmd_view_fullscreen),
        (ev_window_focus_out_cb), (ev_window_cmd_help_about),
        (menu_item_select_cb), (find_bar_search_changed_cb),
        (ev_window_dispose), (ev_window_init):

        Add initial support for password-supported dialogs.  This could be
        a lot cooler, but it'll do for now.

14 files changed:
ChangeLog
backend/Makefile.am
backend/ev-document-links.h
backend/ev-document-security.c [new file with mode: 0644]
backend/ev-document-security.h [new file with mode: 0644]
backend/ev-document.c
backend/ev-document.h
data/Makefile.am
data/evince-password.glade [new file with mode: 0644]
pdf/xpdf/pdf-document.cc
shell/Makefile.am
shell/ev-password.c [new file with mode: 0644]
shell/ev-password.h [new file with mode: 0644]
shell/ev-window.c

index 7e3ed84d0ce34dbd7f18f6b36a431b8d6067bf9e..be6b69c41c18c951ab65b9dccf3c14553be4256f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+Wed Jan 19 01:10:57 2005  Jonathan Blandford  <jrb@redhat.com>
+
+       * backend/Makefile.am:
+       * backend/ev-document-links.h:
+       * backend/ev-document-security.c: (ev_document_security_get_type),
+       (ev_document_security_has_document_security),
+       (ev_document_security_set_password):
+       * backend/ev-document-security.h:
+       * backend/ev-document.c: (ev_document_error_quark):
+       * backend/ev-document.h:
+       * data/Makefile.am:
+       * data/evince-password.glade:
+       * pdf/xpdf/pdf-document.cc:
+       * shell/Makefile.am:
+       * shell/ev-password.c: (ev_password_set_bad_password_label),
+       (ev_window_password_entry_changed_cb), (ev_password_dialog_new),
+       (ev_password_dialog_get_password),
+       (ev_password_dialog_set_bad_pass):
+       * shell/ev-password.h:
+       * shell/ev-window.c: (ev_window_get_attribute),
+       (ev_window_set_property), (update_action_sensitivity),
+       (ev_window_is_empty), (mime_type_supported_by_gdk_pixbuf),
+       (ev_window_setup_document), (ev_window_get_password),
+       (ev_window_open), (ev_window_cmd_save_as),
+       (using_postscript_printer), (ev_window_print),
+       (find_not_supported_dialog), (ev_window_cmd_edit_find),
+       (update_fullscreen_popup), (ev_window_fullscreen),
+       (ev_window_unfullscreen), (ev_window_cmd_view_fullscreen),
+       (ev_window_focus_out_cb), (ev_window_cmd_help_about),
+       (menu_item_select_cb), (find_bar_search_changed_cb),
+       (ev_window_dispose), (ev_window_init):
+
+       Add initial support for password-supported dialogs.  This could be
+       a lot cooler, but it'll do for now.
+
 2005-01-18  Marco Pesenti Gritti  <marco@gnome.org>
 
        * pdf/xpdf/pdf-document.cc:
index ea599fd3d5c01b435da6e3bb5e338bc7cc545377..90303332880c1531f38fae1574ebff184ca39b40 100644 (file)
@@ -19,6 +19,8 @@ libevbackend_la_SOURCES=                      \
        ev-document-thumbnails.h                \
        ev-document-links.c                     \
        ev-document-links.h                     \
+       ev-document-security.c                  \
+       ev-document-security.h                  \
        ev-document-find.c                      \
        ev-document-find.h                      \
        ev-ps-exporter.c                        \
index 4576e8c22eeb9d347f73331bae4687ad1fbe638e..59e638b24ca9f99bf90022047215d0f68851700d 100644 (file)
@@ -1,5 +1,5 @@
 /* ev-document-links.h
- *  this file is part of evince, a gnome document_links viewer
+ *  this file is part of evince, a gnome document viewer
  * 
  * Copyright (C) 2004 Red Hat, Inc.
  *
diff --git a/backend/ev-document-security.c b/backend/ev-document-security.c
new file mode 100644 (file)
index 0000000..5458ccc
--- /dev/null
@@ -0,0 +1,63 @@
+/* ev-document-links.h
+ *  this file is part of evince, a gnome document_links viewer
+ * 
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * Author:
+ *   Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * 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 "config.h"
+
+#include "ev-document-security.h"
+
+GType
+ev_document_security_get_type (void)
+{
+       static GType type = 0;
+       
+       if (G_UNLIKELY (type == 0))
+       {
+               static const GTypeInfo our_info =
+               {
+                       sizeof (EvDocumentSecurityIface),
+                       NULL,
+                       NULL,
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                                              "EvDocumentSecurity",
+                                              &our_info, (GTypeFlags)0);
+       }
+
+       return type;
+}
+
+gboolean
+ev_document_security_has_document_security (EvDocumentSecurity *document_security)
+{
+       EvDocumentSecurityIface *iface = EV_DOCUMENT_SECURITY_GET_IFACE (document_security);
+       return iface->has_document_security (document_security);
+}
+
+void
+ev_document_security_set_password (EvDocumentSecurity *document_security,
+                                  const char         *password)
+{
+       EvDocumentSecurityIface *iface = EV_DOCUMENT_SECURITY_GET_IFACE (document_security);
+       iface->set_password (document_security, password);
+}
diff --git a/backend/ev-document-security.h b/backend/ev-document-security.h
new file mode 100644 (file)
index 0000000..154a3b1
--- /dev/null
@@ -0,0 +1,63 @@
+/* ev-document-security.h
+ *  this file is part of evince, a gnome pdf viewer
+ * 
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Author:
+ *   Jonathan Blandford <jrb@alum.mit.edu>
+ *
+ * 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_DOCUMENT_SECURITY_H
+#define EV_DOCUMENT_SECURITY_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+
+#define EV_TYPE_DOCUMENT_SECURITY                (ev_document_security_get_type ())
+#define EV_DOCUMENT_SECURITY(o)                          (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurity))
+#define EV_DOCUMENT_SECURITY_IFACE(k)            (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurityIface))
+#define EV_IS_DOCUMENT_SECURITY(o)               (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_DOCUMENT_SECURITY))
+#define EV_IS_DOCUMENT_SECURITY_IFACE(k)         (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT_SECURITY))
+#define EV_DOCUMENT_SECURITY_GET_IFACE(inst)     (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_DOCUMENT_SECURITY, EvDocumentSecurityIface))
+
+typedef struct _EvDocumentSecurity      EvDocumentSecurity;
+typedef struct _EvDocumentSecurityIface EvDocumentSecurityIface;
+
+struct _EvDocumentSecurityIface
+{
+       GTypeInterface base_iface;
+
+       /* Methods  */
+       gboolean             (* has_document_security) (EvDocumentSecurity *document_security);
+       void                 (* set_password)          (EvDocumentSecurity *document_security,
+                                                       const char         *password);
+};
+
+GType    ev_document_security_get_type              (void);
+gboolean ev_document_security_has_document_security (EvDocumentSecurity *document_security);
+void     ev_document_security_set_password          (EvDocumentSecurity *document_security,
+                                                    const char         *password);
+
+G_END_DECLS
+
+#endif
index a8de9a5326c47a7d15cb2deeb2e5482b74678f79..6f6a687eef0686f4345e88b9661b079f9e70423c 100644 (file)
@@ -56,6 +56,16 @@ ev_document_get_type (void)
        return type;
 }
 
+GQuark
+ev_document_error_quark (void)
+{
+  static GQuark q = 0;
+  if (q == 0)
+    q = g_quark_from_static_string ("ev-document-error-quark");
+
+  return q;
+}
+
 static void
 ev_document_class_init (gpointer g_class)
 {
index 3616e4307b465988e0a74025527e0ca98d26bc3b..5581cd713825df9385bc75f1e8cf7a3f9262b570 100644 (file)
@@ -40,6 +40,14 @@ G_BEGIN_DECLS
 typedef struct _EvDocument     EvDocument;
 typedef struct _EvDocumentIface        EvDocumentIface;
 
+#define EV_DOCUMENT_ERROR ev_document_error_quark ()
+
+typedef enum
+{
+       EV_DOCUMENT_ERROR_INVALID,
+       EV_DOCUMENT_ERROR_ENCRYPTED
+} EvDocumentError;
+
 struct _EvDocumentIface
 {
        GTypeInterface base_iface;
@@ -78,9 +86,12 @@ struct _EvDocumentIface
                                         int           clip_y,
                                         int           clip_width,
                                         int           clip_height);
+
+
 };
 
-GType ev_document_get_type (void);
+GType    ev_document_get_type    (void);
+GQuark   ev_document_error_quark (void);
 
 gboolean ev_document_load            (EvDocument   *document,
                                      const char   *uri,
index e543c3bee23356d0de93a7a815f2b2de47737c47..f1ca4b939677ac87db96be37d690ecee1bb90f4c 100644 (file)
@@ -5,6 +5,11 @@ ui_DATA =                              \
        evince-ui.xml                   \
        $(NULL)
 
+gladedir = $(pkgdatadir)
+glade_DATA =                           \
+       evince-password.glade           \
+       $(NULL)
+
 stockdir = $(datadir)/pixmaps/evince
 stock_DATA =                           \
         ev-stock-zoom-fit-width.png    \
@@ -12,5 +17,6 @@ stock_DATA =                          \
 
 EXTRA_DIST =                           \
        $(stock_DATA)                   \
+       $(glade_DATA)                   \
        $(ui_DATA)                      \
        $(NULL)
diff --git a/data/evince-password.glade b/data/evince-password.glade
new file mode 100644 (file)
index 0000000..dc1364c
--- /dev/null
@@ -0,0 +1,211 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkDialog" id="password_dialog">
+  <property name="border_width">6</property>
+  <property name="title" translatable="yes"></property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">False</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="has_separator">False</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">12</property>
+
+      <child internal-child="action_area">
+       <widget class="GtkHButtonBox" id="dialog-action_area1">
+         <property name="visible">True</property>
+         <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+         <child>
+           <widget class="GtkButton" id="cancelbutton1">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-cancel</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="focus_on_click">True</property>
+             <property name="response_id">-6</property>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="ok_button">
+             <property name="visible">True</property>
+             <property name="sensitive">False</property>
+             <property name="can_default">True</property>
+             <property name="has_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-ok</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="focus_on_click">True</property>
+             <property name="response_id">-5</property>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+         <property name="pack_type">GTK_PACK_END</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkHBox" id="hbox1">
+         <property name="border_width">6</property>
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">12</property>
+
+         <child>
+           <widget class="GtkImage" id="image1">
+             <property name="visible">True</property>
+             <property name="stock">gtk-dialog-authentication</property>
+             <property name="icon_size">6</property>
+             <property name="xalign">0.5</property>
+             <property name="yalign">0</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkVBox" id="vbox1">
+             <property name="visible">True</property>
+             <property name="homogeneous">False</property>
+             <property name="spacing">12</property>
+
+             <child>
+               <widget class="GtkLabel" id="password_label">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes"></property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">True</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">True</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0</property>
+                 <property name="yalign">0</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">False</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkHBox" id="hbox2">
+                 <property name="visible">True</property>
+                 <property name="homogeneous">False</property>
+                 <property name="spacing">3</property>
+
+                 <child>
+                   <widget class="GtkLabel" id="label2">
+                     <property name="visible">True</property>
+                     <property name="label" translatable="yes">_Password:</property>
+                     <property name="use_underline">True</property>
+                     <property name="use_markup">False</property>
+                     <property name="justify">GTK_JUSTIFY_LEFT</property>
+                     <property name="wrap">False</property>
+                     <property name="selectable">False</property>
+                     <property name="xalign">0.5</property>
+                     <property name="yalign">0.5</property>
+                     <property name="xpad">0</property>
+                     <property name="ypad">0</property>
+                     <property name="mnemonic_widget">password_entry</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkEntry" id="password_entry">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="editable">True</property>
+                     <property name="visibility">False</property>
+                     <property name="max_length">0</property>
+                     <property name="text" translatable="yes"></property>
+                     <property name="has_frame">True</property>
+                     <property name="invisible_char" translatable="yes">*</property>
+                     <property name="activates_default">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">True</property>
+                     <property name="fill">True</property>
+                   </packing>
+                 </child>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">True</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkLabel" id="bad_password_label">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">&lt;span size=&quot;smaller&quot;&gt; &lt;/span&gt;</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">True</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">1</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">False</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
index 36ad37436a2e40626510fdf0792bc5b689829a29..0a70edbdf2c0bc71e2c63eac6a2c8d0e0ea75fad 100644 (file)
@@ -26,6 +26,7 @@
 #include "gpdf-g-switch.h"
 #include "ev-document-links.h"
 #include "ev-document-misc.h"
+#include "ev-document-security.h"
 #include "ev-document-thumbnails.h"
 
 #include "GlobalParams.h"
@@ -33,6 +34,7 @@
 #include "SplashBitmap.h"
 #include "PDFDoc.h"
 #include "Outline.h"
+#include "ErrorCodes.h"
 #include "UnicodeMap.h"
 #include "GlobalParams.h"
 #include "GfxState.h"
@@ -87,18 +89,21 @@ struct _PdfDocument
        Links *links;
        UnicodeMap *umap;
 
+       gchar *password;
        gboolean page_valid;
 
        PdfDocumentSearch *search;
 };
 
-static void pdf_document_document_links_iface_init      (EvDocumentLinksIface  *iface);
+static void pdf_document_document_links_iface_init      (EvDocumentLinksIface      *iface);
 static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
 static void pdf_document_document_iface_init            (EvDocumentIface           *iface);
-static void pdf_document_ps_exporter_iface_init (EvPSExporterIface   *iface);
-static void pdf_document_find_iface_init        (EvDocumentFindIface *iface);
-static void pdf_document_search_free            (PdfDocumentSearch   *search);
-static void pdf_document_search_page_changed    (PdfDocumentSearch   *search);
+static void pdf_document_ps_exporter_iface_init         (EvPSExporterIface         *iface);
+static void pdf_document_find_iface_init                (EvDocumentFindIface       *iface);
+static void pdf_document_security_iface_init            (EvDocumentSecurityIface   *iface);
+static void pdf_document_search_free                    (PdfDocumentSearch         *search);
+static void pdf_document_search_page_changed            (PdfDocumentSearch         *search);
+
 
 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
                          {
@@ -112,6 +117,8 @@ G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
                                                        pdf_document_ps_exporter_iface_init);
                                 G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
                                                        pdf_document_find_iface_init);
+                                G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
+                                                       pdf_document_security_iface_init);
                         });
 
 static void
@@ -184,18 +191,27 @@ pdf_document_load (EvDocument  *document,
        g_free (filename);
 
        // open the PDF file, assumes ownership of filename_g
-       newDoc = new PDFDoc(filename_g, 0, 0);
+       GString *password = NULL;
+       if (pdf_document->password)
+               password = new GString (pdf_document->password);
+       newDoc = new PDFDoc(filename_g, password, password);
+       if (password)
+               delete password;
 
        if (!newDoc->isOk()) {
                err = newDoc->getErrorCode();
                delete newDoc;
-
-               /* FIXME: Add a real error enum to EvDocument */
-               g_set_error (error, G_FILE_ERROR,
-                            G_FILE_ERROR_FAILED,
-                            "Failed to load document (error %d) '%s'\n",
-                            err,
-                            uri);
+               if (err == errEncrypted) {
+                       g_set_error (error, EV_DOCUMENT_ERROR,
+                                    EV_DOCUMENT_ERROR_ENCRYPTED,
+                                    "Document is encrypted.");
+               } else {
+                       g_set_error (error, G_FILE_ERROR,
+                                    G_FILE_ERROR_FAILED,
+                                    "Failed to load document (error %d) '%s'\n",
+                                    err,
+                                    uri);
+               }
 
                return FALSE;
        }
@@ -660,6 +676,25 @@ pdf_document_search_free (PdfDocumentSearch   *search)
        g_free (search);
 }
 
+static gboolean
+pdf_document_has_document_security (EvDocumentSecurity *document_security)
+{
+       /* FIXME: do we really need to have this? */
+       return FALSE;
+}
+
+static void
+pdf_document_set_password (EvDocumentSecurity *document_security,
+                          const char         *password)
+{
+       PdfDocument *document = PDF_DOCUMENT (document_security);
+
+       if (document->password)
+               g_free (document->password);
+
+       document->password = g_strdup (password);
+}
+
 static void
 pdf_document_ps_export_begin (EvPSExporter *exporter, const char *filename)
 {
@@ -1081,6 +1116,13 @@ pdf_document_find_iface_init (EvDocumentFindIface *iface)
         iface->cancel = pdf_document_find_cancel;
 }
 
+static void
+pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
+{
+       iface->has_document_security = pdf_document_has_document_security;
+       iface->set_password = pdf_document_set_password;
+}
+
 static void
 pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
 {
@@ -1285,5 +1327,6 @@ pdf_document_init (PdfDocument *pdf_document)
        pdf_document->scale = 1.;
 
        pdf_document->page_valid = FALSE;
+       pdf_document->password = NULL;
 }
 
index 5fb0bdbb6d78db96b98471a116a1f43c3c13d950..8e76518b38d7e23fa5c9d5aabd99d31d863bd2c9 100644 (file)
@@ -29,6 +29,8 @@ evince_SOURCES=                               \
        ev-navigation-action.h          \
        ev-page-action.c                \
        ev-page-action.h                \
+       ev-password.h                   \
+       ev-password.c                   \
        ev-print-job.c                  \
        ev-print-job.h                  \
        ev-utils.c                      \
diff --git a/shell/ev-password.c b/shell/ev-password.c
new file mode 100644 (file)
index 0000000..9ea1df2
--- /dev/null
@@ -0,0 +1,143 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2005 Red Hat, Inc
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ev-password.h"
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+
+#define EV_PASSWORD_DATA "ev-password-data"
+
+static void
+ev_password_set_bad_password_label (GtkWidget *password,
+                                   gchar     *message)
+{
+       GladeXML *xml;
+       GtkWidget *label;
+       gchar *markup;
+
+       xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA);
+       g_assert (xml);
+
+       label = glade_xml_get_widget (xml, "bad_password_label");
+       markup = g_strdup_printf ("<span color=\"red\" size=\"smaller\">%s</span>",
+                                 message);
+       gtk_label_set_markup (GTK_LABEL (label), markup);
+       g_free (markup);
+}
+
+static void
+ev_window_password_entry_changed_cb (GtkEditable *editable,
+                                    GtkWidget   *password)
+{
+       const char *text;
+       GtkWidget *button;
+       GladeXML *xml;
+
+       xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA);
+       g_assert (xml);
+
+       text = gtk_entry_get_text (GTK_ENTRY (editable));
+       button = glade_xml_get_widget (xml, "ok_button");
+
+       if (text == NULL || *text == '\0')
+               gtk_widget_set_sensitive (button, FALSE);
+       else
+               gtk_widget_set_sensitive (button, TRUE);
+
+       ev_password_set_bad_password_label (password, " ");
+}
+
+GtkWidget *
+ev_password_dialog_new (GtkWidget  *toplevel,
+                       const char *uri)
+{
+       const char *glade_file = DATADIR "/evince-password.glade";
+       GladeXML *xml;
+       GtkWidget *dialog, *label;
+       GtkWidget *entry;
+       char *format;
+       char *markup;
+
+       xml = glade_xml_new (glade_file, NULL, NULL);
+       if (xml == NULL) {
+               dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
+                                                GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                GTK_MESSAGE_ERROR,
+                                                GTK_BUTTONS_CLOSE,
+                                                _("Unable to find glade file"));
+               gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                                         _("The glade file, %s, cannot be found.  Please check that your installation is complete."),
+                                                         glade_file);
+               gtk_dialog_run (GTK_DIALOG (dialog));
+               gtk_widget_destroy (dialog);
+               return NULL;
+       }
+       
+       dialog = glade_xml_get_widget (xml, "password_dialog");
+       label = glade_xml_get_widget (xml, "password_label");
+       entry = glade_xml_get_widget (xml, "password_entry");
+
+       gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
+       g_signal_connect (entry, "changed", G_CALLBACK (ev_window_password_entry_changed_cb), dialog);
+       format = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n%s",
+                                 _("Password required"),
+                                 _("The document '%s' requires a password before it can be opened."));
+       markup = g_markup_printf_escaped (format, uri);
+       gtk_label_set_markup (GTK_LABEL (label), markup);
+       g_free (format);
+       g_free (markup);
+
+       g_object_set_data_full (G_OBJECT (dialog), EV_PASSWORD_DATA, xml, g_object_unref);
+       ev_password_set_bad_password_label (dialog, " ");
+
+       return dialog;
+}
+
+char *
+ev_password_dialog_get_password (GtkWidget *password)
+{
+       GladeXML *xml;
+       GtkWidget *entry;
+
+       xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA);
+       g_assert (xml);
+
+       entry = glade_xml_get_widget (xml, "password_entry");
+
+       return g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+}
+
+void
+ev_password_dialog_set_bad_pass (GtkWidget *password)
+{
+       GladeXML *xml;
+       GtkWidget *entry;
+
+       xml = g_object_get_data (G_OBJECT (password), EV_PASSWORD_DATA);
+       g_assert (xml);
+
+       entry = glade_xml_get_widget (xml, "password_entry");
+       gtk_entry_set_text (GTK_ENTRY (entry), "");
+       ev_password_set_bad_password_label (password, _("Incorrect password"));
+}
diff --git a/shell/ev-password.h b/shell/ev-password.h
new file mode 100644 (file)
index 0000000..0c725a8
--- /dev/null
@@ -0,0 +1,34 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2005 Red Hat, Inc
+ *
+ * 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_PASSWORD_H__
+#define __EV_PASSWORD_H__
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *ev_password_dialog_new          (GtkWidget   *toplevel,
+                                           const gchar *uri);
+char      *ev_password_dialog_get_password (GtkWidget *password);
+void       ev_password_dialog_set_bad_pass (GtkWidget *password);
+
+G_END_DECLS
+
+#endif /* __EV_PASSWORD_H__ */
index 54effcd24e9b124180088b89ddbe5e4adb625783..532efae1fd6c13dc3223cf807fba0ea6907e9f95 100644 (file)
 #include "ev-sidebar-links.h"
 #include "ev-sidebar-thumbnails.h"
 #include "ev-view.h"
+#include "ev-password.h"
 #include "ev-print-job.h"
 #include "ev-document-find.h"
+#include "ev-document-security.h"
 #include "eggfindbar.h"
 
 #include "pdf-document.h"
@@ -45,6 +47,7 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+
 #include <libgnomevfs/gnome-vfs-mime-utils.h>
 #include <libgnomeprintui/gnome-print-dialog.h>
 
@@ -105,7 +108,7 @@ const char *
 ev_window_get_attribute (EvWindow *self)
 {
        g_return_val_if_fail (self != NULL && EV_IS_WINDOW (self), NULL);
-       
+
        return self->priv->attribute;
 }
 
@@ -149,9 +152,9 @@ ev_window_set_property (GObject *object, guint prop_id, const GValue *value,
                        GParamSpec *param_spec)
 {
        EvWindow *self;
-       
+
        self = EV_WINDOW (object);
-       
+
        switch (prop_id) {
        case PROP_ATTRIBUTE:
                ev_window_set_attribute (self, g_value_get_string (value));
@@ -235,7 +238,7 @@ update_action_sensitivity (EvWindow *ev_window)
                set_action_sensitive (ev_window, "GoPageUp", FALSE);
                set_action_sensitive (ev_window, "GoLastPage", FALSE);
        }
-        
+
        /* Help menu */
        /* "HelpContents": always sensitive */
        /* "HelpAbout": always sensitive */
@@ -256,7 +259,7 @@ gboolean
 ev_window_is_empty (const EvWindow *ev_window)
 {
        g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
-       
+
        return ev_window->priv->document == NULL;
 }
 
@@ -283,33 +286,33 @@ mime_type_supported_by_gdk_pixbuf (const gchar *mime_type)
 {
        GSList *formats, *list;
        gboolean retval = FALSE;
-       
+
        formats = gdk_pixbuf_get_formats ();
-       
+
        list = formats;
        while (list) {
                GdkPixbufFormat *format = list->data;
                int i;
                gchar **mime_types;
-               
+
                if (gdk_pixbuf_format_is_disabled (format))
                        continue;
 
                mime_types = gdk_pixbuf_format_get_mime_types (format);
-               
+
                for (i = 0; mime_types[i] != NULL; i++) {
                        if (strcmp (mime_types[i], mime_type) == 0) {
                                retval = TRUE;
                                break;
                        }
                }
-               
+
                if (retval)
                        break;
-               
+
                list = list->next;
        }
-       
+
        g_slist_free (formats);
 
        return retval;
@@ -347,12 +350,58 @@ update_total_pages (EvWindow *ev_window)
        ev_page_action_set_total_pages (EV_PAGE_ACTION (action), pages);
 }
 
+/* This function assumes that ev_window just had ev_window->document set.
+ */
+static void
+ev_window_setup_document (EvWindow *ev_window)
+{
+       EvDocument *document;
+       EvHistory *history;
+       EvView *view = EV_VIEW (ev_window->priv->view);
+       EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
+       GtkAction *action;
+
+       document = ev_window->priv->document;
+
+       ev_view_set_document (view, document);
+       ev_sidebar_set_document (sidebar, document);
+
+       history = ev_history_new ();
+       ev_view_set_history (view, history);
+       g_object_unref (history);
+
+       action = gtk_action_group_get_action
+               (ev_window->priv->action_group, NAVIGATION_BACK_ACTION);
+       ev_navigation_action_set_history
+               (EV_NAVIGATION_ACTION (action), history);
+
+       action = gtk_action_group_get_action
+               (ev_window->priv->action_group, NAVIGATION_FORWARD_ACTION);
+       ev_navigation_action_set_history
+               (EV_NAVIGATION_ACTION (action), history);
+
+       update_total_pages (ev_window);
+       update_action_sensitivity (ev_window);
+}
+
+
+static gchar *
+ev_window_get_password (GtkWidget *password_dialog)
+{
+       gchar *password = NULL;
+
+       if (gtk_dialog_run (GTK_DIALOG (password_dialog)) == GTK_RESPONSE_OK)
+               password = ev_password_dialog_get_password (password_dialog);
+
+       return password;
+}
+
 void
 ev_window_open (EvWindow *ev_window, const char *uri)
 {
        EvDocument *document = NULL;
        char *mime_type;
-       
+
        g_free (ev_window->priv->uri);
        ev_window->priv->uri = g_strdup (uri);
 
@@ -366,49 +415,62 @@ ev_window_open (EvWindow *ev_window, const char *uri)
                document = g_object_new (PS_TYPE_DOCUMENT, NULL);
        else if (mime_type_supported_by_gdk_pixbuf (mime_type))
                document = g_object_new (PIXBUF_TYPE_DOCUMENT, NULL);
-       
+
        if (document) {
                GError *error = NULL;
+               GtkWidget *password_dialog = NULL;
 
                g_signal_connect_object (G_OBJECT (document),
                                         "notify::title",
                                         G_CALLBACK (update_window_title),
                                         ev_window, 0);
 
-               if (ev_document_load (document, uri, &error)) {
-                       EvHistory *history;
-                       EvView *view = EV_VIEW (ev_window->priv->view);
-                       EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
-                       GtkAction *action;
-
-                       if (ev_window->priv->document)
-                               g_object_unref (ev_window->priv->document);
-                       ev_window->priv->document = document;
+               /* If we get an error while loading the document, we try to fix
+                * it and try again. This is an ugly loop that could do with
+                * some refactoring.*/
+               while (TRUE) {
+                       gboolean result;
 
-                       ev_view_set_document (view, document);
-                       ev_sidebar_set_document (sidebar, document);
+                       result = ev_document_load (document, uri, &error);
 
-                       history = ev_history_new ();
-                       ev_view_set_history (view, history);
-                       g_object_unref (history);
+                       if (result) {
+                               if (ev_window->priv->document)
+                                       g_object_unref (ev_window->priv->document);
+                               ev_window->priv->document = document;
+                               ev_window_setup_document (ev_window);
 
-                       action = gtk_action_group_get_action
-                               (ev_window->priv->action_group, NAVIGATION_BACK_ACTION);
-                       ev_navigation_action_set_history
-                               (EV_NAVIGATION_ACTION (action), history);
-
-                       action = gtk_action_group_get_action
-                               (ev_window->priv->action_group, NAVIGATION_FORWARD_ACTION);
-                       ev_navigation_action_set_history
-                               (EV_NAVIGATION_ACTION (action), history);
+                               if (password_dialog)
+                                       gtk_widget_destroy (password_dialog);
+                               break;
+                       }
 
-                       update_total_pages (ev_window);
-                       update_action_sensitivity (ev_window);
-               } else {
                        g_assert (error != NULL);
+
+                       if (error->domain == EV_DOCUMENT_ERROR &&
+                           error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
+                               char *password;
+
+                               if (password_dialog == NULL)
+                                       password_dialog = ev_password_dialog_new (GTK_WIDGET (ev_window), uri);
+                               else
+                                       ev_password_dialog_set_bad_pass (password_dialog);
+                               password = ev_window_get_password (password_dialog);
+                               if (password) {
+                                       ev_document_security_set_password (EV_DOCUMENT_SECURITY (document),
+                                                                          password);
+                                       g_free (password);
+                                       g_error_free (error);
+                                       error = NULL;
+                                       continue;
+                               } else {
+                                       gtk_widget_destroy (password_dialog);
+                               }
+                       } else {
+                               unable_to_load (ev_window, error->message);
+                       }
                        g_object_unref (document);
-                       unable_to_load (ev_window, error->message);
                        g_error_free (error);
+                       break;
                }
        } else {
                char *error_message;
@@ -451,7 +513,7 @@ overwrite_existing_file (GtkWindow *window, const gchar *file_name)
                GTK_MESSAGE_DIALOG (msgbox),
                _("Do you want to replace it with the one you are saving?"));
 
-       gtk_dialog_add_button (GTK_DIALOG (msgbox), 
+       gtk_dialog_add_button (GTK_DIALOG (msgbox),
                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
 
        gtk_dialog_add_button (GTK_DIALOG (msgbox),
@@ -499,7 +561,7 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
 {
        GtkWidget *fc;
        GtkFileFilter *pdf_filter, *all_filter;
-       gchar *uri = NULL; 
+       gchar *uri = NULL;
 
        fc = gtk_file_chooser_dialog_new (
                _("Save a Copy"),
@@ -519,7 +581,7 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
        gtk_file_filter_add_pattern (all_filter, "*");
        gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fc), all_filter);
        gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (fc), pdf_filter);
-       
+
        gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
 
        gtk_widget_show (fc);
@@ -528,7 +590,7 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
                uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
 
 /* FIXME
-               if (g_file_test (uri, G_FILE_TEST_EXISTS) &&  
+               if (g_file_test (uri, G_FILE_TEST_EXISTS) &&
                    !overwrite_existing_file (GTK_WINDOW (fc), uri))
                                continue;
 */
@@ -536,7 +598,7 @@ ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
                if (ev_document_save (ev_window->priv->document, uri, NULL))
                        break;
                else
-                       save_error_dialog (GTK_WINDOW (fc), uri);    
+                       save_error_dialog (GTK_WINDOW (fc), uri);
        }
        gtk_widget_destroy (fc);
 }
@@ -549,20 +611,20 @@ using_postscript_printer (GnomePrintConfig *config)
 
        driver = gnome_print_config_get (
                config, (const guchar *)"Settings.Engine.Backend.Driver");
-       
+
        transport = gnome_print_config_get (
                config, (const guchar *)"Settings.Transport.Backend");
-       
+
        if (driver) {
                if (!strcmp ((const gchar *)driver, "gnome-print-ps"))
                        return TRUE;
-               else 
+               else
                        return FALSE;
        } else  if (transport) {
                if (!strcmp ((const gchar *)transport, "CUPS"))
                        return TRUE;
        }
-       
+
        return FALSE;
 }
 
@@ -586,11 +648,11 @@ ev_window_print (EvWindow *ev_window)
        gtk_dialog_set_response_sensitive (GTK_DIALOG (print_dialog),
                                           GNOME_PRINT_DIALOG_RESPONSE_PREVIEW,
                                           FALSE);
-       
+
        while (TRUE) {
                int response;
                response = gtk_dialog_run (GTK_DIALOG (print_dialog));
-               
+
                if (response != GNOME_PRINT_DIALOG_RESPONSE_PRINT)
                        break;
 
@@ -599,7 +661,7 @@ ev_window_print (EvWindow *ev_window)
                 */
                if (!using_postscript_printer (config)) {
                        GtkWidget *dialog;
-                       
+
                        dialog = gtk_message_dialog_new (
                                GTK_WINDOW (print_dialog), GTK_DIALOG_MODAL,
                                GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
@@ -622,7 +684,7 @@ ev_window_print (EvWindow *ev_window)
                                          NULL);
                break;
        }
-                               
+
        gtk_widget_destroy (print_dialog);
 
        if (print_job != NULL) {
@@ -653,7 +715,7 @@ find_not_supported_dialog (EvWindow   *ev_window)
        /* If you change this so it isn't modal, be sure you don't
         * allow multiple copies of the dialog...
         */
-       
+
        dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
                                         GTK_MESSAGE_ERROR,
@@ -685,9 +747,9 @@ ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
        } else {
                gtk_widget_show (ev_window->priv->find_bar);
 
-               if (ev_window->priv->exit_fullscreen_popup) 
+               if (ev_window->priv->exit_fullscreen_popup)
                        update_fullscreen_popup (ev_window);
-       
+
                egg_find_bar_grab_focus (EGG_FIND_BAR (ev_window->priv->find_bar));
        }
 }
@@ -711,7 +773,7 @@ update_fullscreen_popup (EvWindow *window)
 
        if (!popup)
                return;
-       
+
        popup_width = popup->requisition.width;
        popup_height = popup->requisition.height;
 
@@ -726,10 +788,10 @@ update_fullscreen_popup (EvWindow *window)
                GtkRequisition req;
 
                gtk_widget_size_request (window->priv->find_bar, &req);
-               
+
                screen_rect.height -= req.height;
        }
-       
+
        if (gtk_widget_get_direction (popup) == GTK_TEXT_DIR_RTL)
        {
                gtk_window_move (GTK_WINDOW (popup),
@@ -822,7 +884,7 @@ ev_window_fullscreen (EvWindow *window)
        main_menu = gtk_ui_manager_get_widget (window->priv->ui_manager, "/MainMenu");
        gtk_widget_hide (main_menu);
        gtk_widget_hide (window->priv->statusbar);
-       
+
        update_fullscreen_popup (window);
 
        gtk_widget_show (popup);
@@ -832,21 +894,21 @@ static void
 ev_window_unfullscreen (EvWindow *window)
 {
        GtkWidget *main_menu;
-       
+
        window->priv->fullscreen_mode = FALSE;
 
        main_menu = gtk_ui_manager_get_widget (window->priv->ui_manager, "/MainMenu");
        gtk_widget_show (main_menu);
        gtk_widget_show (window->priv->statusbar);
-       
+
        destroy_exit_fullscreen_popup (window);
 }
+
 static void
 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *ev_window)
 {
        gboolean fullscreen;
-       
+
         g_return_if_fail (EV_IS_WINDOW (ev_window));
 
        fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
@@ -896,7 +958,7 @@ static gboolean
 ev_window_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *ev_window)
 {
        gtk_window_unfullscreen (GTK_WINDOW (ev_window));
-       
+
        return FALSE;
 }
 
@@ -1016,7 +1078,7 @@ ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
                N_("Evince is free software; you can redistribute it and/or modify\n"
                   "it under the terms of the GNU General Public License as published by\n"
                   "the Free Software Foundation; either version 2 of the License, or\n"
-                  "(at your option) any later version.\n"),            
+                  "(at your option) any later version.\n"),
                N_("Evince is distributed in the hope that it will be useful,\n"
                   "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
                   "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
@@ -1098,7 +1160,7 @@ menu_item_select_cb (GtkMenuItem *proxy, EvWindow *ev_window)
 
        action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
        g_return_if_fail (action != NULL);
-       
+
        g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
        if (message) {
                gtk_statusbar_push (GTK_STATUSBAR (ev_window->priv->statusbar),
@@ -1226,7 +1288,7 @@ find_bar_search_changed_cb (EggFindBar *find_bar,
        const char *search_string;
 
        g_return_if_fail (EV_IS_WINDOW (ev_window));
-       
+
        /* Either the string or case sensitivity could have changed,
         * we connect this callback to both. We also connect it
         * to ::visible so when the find bar is hidden, we should
@@ -1236,7 +1298,7 @@ find_bar_search_changed_cb (EggFindBar *find_bar,
        case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
        visible = GTK_WIDGET_VISIBLE (find_bar);
        search_string = egg_find_bar_get_search_string (find_bar);
-       
+
 #if 0
        g_printerr ("search for '%s'\n", search_string ? search_string : "(nil)");
 #endif
@@ -1271,7 +1333,7 @@ ev_window_dispose (GObject *object)
                g_object_unref (priv->action_group);
                priv->action_group = NULL;
        }
-       
+
        G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -1348,7 +1410,7 @@ static GtkActionEntry entries[] = {
           G_CALLBACK (ev_window_cmd_edit_copy) },
        { "EditSelectAll", NULL, N_("Select _All"), "<control>A",
          N_("Select the entire page"),
-         G_CALLBACK (ev_window_cmd_edit_select_all) }, 
+         G_CALLBACK (ev_window_cmd_edit_select_all) },
         { "EditFind", GTK_STOCK_FIND, N_("_Find"), "<control>F",
           N_("Find a word or phrase in the document"),
           G_CALLBACK (ev_window_cmd_edit_find) },
@@ -1385,16 +1447,16 @@ static GtkActionEntry entries[] = {
           G_CALLBACK (ev_window_cmd_go_page_down) },
         { "GoFirstPage", GTK_STOCK_GOTO_FIRST, N_("_First Page"), "<control>Home",
           N_("Go to the first page"),
-          G_CALLBACK (ev_window_cmd_go_first_page) },        
+          G_CALLBACK (ev_window_cmd_go_first_page) },
         { "GoLastPage", GTK_STOCK_GOTO_LAST, N_("_Last Page"), "<control>End",
           N_("Go to the last page"),
           G_CALLBACK (ev_window_cmd_go_last_page) },
-        
+
        /* Help menu */
        { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), NULL,
          N_("Display help for the viewer application"),
          G_CALLBACK (ev_window_cmd_help_contents) },
-        
+
        { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL,
          N_("Display credits for the document viewer creators"),
          G_CALLBACK (ev_window_cmd_help_about) },
@@ -1488,7 +1550,7 @@ ev_window_init (EvWindow *ev_window)
        ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
        gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
        gtk_widget_show (ev_window->priv->main_box);
-       
+
        action_group = gtk_action_group_new ("MenuActions");
        ev_window->priv->action_group = action_group;
        gtk_action_group_set_translation_domain (action_group, NULL);
@@ -1555,7 +1617,7 @@ ev_window_init (EvWindow *ev_window)
                             "thumbnails",
                             _("Thumbnails"),
                             sidebar_widget);
-       
+
        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
        gtk_widget_show (scrolled_window);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
@@ -1595,7 +1657,7 @@ ev_window_init (EvWindow *ev_window)
        gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
                          ev_window->priv->find_bar,
                          FALSE, TRUE, 0);
-       
+
        /* Connect to find bar signals */
        g_signal_connect (ev_window->priv->find_bar,
                          "previous",
@@ -1628,9 +1690,9 @@ ev_window_init (EvWindow *ev_window)
        g_signal_connect (ev_window, "focus_out_event",
                          G_CALLBACK (ev_window_focus_out_cb),
                          ev_window);
-       
+
        /* Give focus to the scrolled window */
        gtk_widget_grab_focus (scrolled_window);
-       
+
        update_action_sensitivity (ev_window);
-} 
+}