+static void
+update_window_title (EvDocument *document, GParamSpec *pspec, EvWindow *ev_window)
+{
+ char *title = NULL;
+ char *doc_title = NULL;
+ gboolean password_needed;
+
+ password_needed = (ev_window->priv->password_document != NULL);
+ if (document) {
+ doc_title = ev_page_cache_get_title (ev_window->priv->page_cache);
+
+ /* Make sure we get a valid title back */
+ if (doc_title) {
+ if (doc_title[0] == '\000' ||
+ !g_utf8_validate (doc_title, -1, NULL)) {
+ g_free (doc_title);
+ doc_title = NULL;
+ }
+ }
+ }
+
+ if (doc_title) {
+ char *p;
+
+ for (p = doc_title; *p; ++p) {
+ /* an '\n' byte is always ASCII, no need for UTF-8 special casing */
+ if (*p == '\n')
+ *p = ' ';
+ }
+ }
+
+ if (doc_title == NULL && ev_window->priv->uri) {
+ char *basename;
+
+ basename = g_path_get_basename (ev_window->priv->uri);
+ doc_title = gnome_vfs_unescape_string_for_display (basename);
+ g_free (basename);
+ }
+
+ if (password_needed) {
+ if (doc_title == NULL) {
+ title = g_strdup (_("Document Viewer - Password Required"));
+ } else {
+ title = g_strdup_printf (_("%s - Password Required"), doc_title);
+ }
+ } else {
+ if (doc_title == NULL) {
+ title = g_strdup (_("Document Viewer"));
+ } else {
+ title = g_strdup (doc_title);
+ }
+ }
+
+ gtk_window_set_title (GTK_WINDOW (ev_window), title);
+
+ g_free (doc_title);
+ g_free (title);
+}
+
+static void
+update_total_pages (EvWindow *ev_window)
+{
+ GtkAction *action;
+ int pages;
+
+ pages = ev_page_cache_get_n_pages (ev_window->priv->page_cache);
+ action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
+ ev_page_action_set_total_pages (EV_PAGE_ACTION (action), pages);
+}
+
+/* This function assumes that ev_window just had ev_window->document set.
+ */
+static gboolean
+document_supports_sidebar (EvDocument *document)
+{
+ /* FIXME: Remove the (TRUE ||) after links are fixed in poppler-glib */
+ return (EV_IS_DOCUMENT_THUMBNAILS (document) && (EV_IS_DOCUMENT_LINKS (document)));
+}
+
+static void
+hide_sidebar_and_actions (EvWindow *ev_window)
+{
+ GtkAction *action;
+ /* Alsthough we update the hiddenness of the sidebar, we don't want to
+ * store the value */
+ g_signal_handlers_disconnect_by_func (ev_window->priv->sidebar,
+ ev_window_sidebar_visibility_changed_cb,
+ ev_window);
+ gtk_widget_hide (ev_window->priv->sidebar);
+ action = gtk_action_group_get_action (ev_window->priv->action_group, "ViewSidebar");
+ gtk_action_set_sensitive (action, FALSE);
+
+}
+
+static void
+page_changed_cb (EvPageCache *page_cache,
+ gint page,
+ EvWindow *ev_window)
+{
+ GtkAction *action;
+
+ action = gtk_action_group_get_action
+ (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
+
+ ev_page_action_set_current_page (EV_PAGE_ACTION (action), page);
+ update_action_sensitivity (ev_window);
+}
+
+
+static void
+ev_window_setup_document (EvWindow *ev_window)
+{
+ EvDocument *document;
+ EvView *view = EV_VIEW (ev_window->priv->view);
+ EvSidebar *sidebar = EV_SIDEBAR (ev_window->priv->sidebar);
+
+ document = ev_window->priv->document;
+ ev_window->priv->page_cache = ev_document_get_page_cache (ev_window->priv->document);
+ g_signal_connect (ev_window->priv->page_cache, "page-changed", G_CALLBACK (page_changed_cb), ev_window);
+
+ g_signal_connect_object (G_OBJECT (document),
+ "notify::title",
+ G_CALLBACK (update_window_title),
+ ev_window, 0);
+
+ ev_window_set_page_mode (ev_window, PAGE_MODE_SINGLE_PAGE);
+
+ if (document_supports_sidebar (document))
+ ev_sidebar_set_document (sidebar, document);
+ else
+ hide_sidebar_and_actions (ev_window);
+
+ ev_view_set_document (view, document);
+
+ update_window_title (document, NULL, ev_window);
+ update_total_pages (ev_window);
+ update_action_sensitivity (ev_window);
+}
+
+static void
+password_dialog_response (GtkWidget *password_dialog,
+ gint response_id,
+ EvWindow *ev_window)
+{
+ char *password;
+
+ if (response_id == GTK_RESPONSE_OK) {
+ EvDocument *document;
+ gchar *uri;
+
+ password = ev_password_dialog_get_password (password_dialog);
+ if (password) {
+ g_mutex_lock (EV_DOC_MUTEX);
+ ev_document_security_set_password (EV_DOCUMENT_SECURITY (ev_window->priv->password_document),
+ password);
+ g_mutex_unlock (EV_DOC_MUTEX);
+ }
+ g_free (password);
+
+ document = ev_window->priv->password_document;
+ uri = ev_window->priv->password_uri;
+
+ ev_window->priv->password_document = NULL;
+ ev_window->priv->password_uri = NULL;
+
+ if (start_loading_document (ev_window, document, uri)) {
+ gtk_widget_destroy (password_dialog);
+ }
+
+ g_object_unref (document);
+ g_free (uri);
+
+ return;
+ }
+
+ gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE);
+ gtk_widget_destroy (password_dialog);
+}
+
+/* Called either by start_loading_document or by the "unlock" callback on the
+ * password_view page. It assumes that ev_window->priv->password_* has been set
+ * correctly. These are cleared by password_dialog_response() */
+
+static void
+ev_window_popup_password_dialog (EvWindow *ev_window)
+{
+ g_assert (ev_window->priv->password_document);
+ g_assert (ev_window->priv->password_uri);
+
+ gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
+
+ update_window_title (ev_window->priv->password_document, NULL, ev_window);
+ if (ev_window->priv->password_dialog == NULL) {
+ gchar *basename, *file_name;
+
+ basename = g_path_get_basename (ev_window->priv->password_uri);
+ file_name = gnome_vfs_unescape_string_for_display (basename);
+ ev_window->priv->password_dialog =
+ ev_password_dialog_new (GTK_WIDGET (ev_window), file_name);
+ g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog),
+ (gpointer *) &(ev_window->priv->password_dialog));
+ g_signal_connect (ev_window->priv->password_dialog,
+ "response",
+ G_CALLBACK (password_dialog_response),
+ ev_window);
+ g_free (basename);
+ g_free (file_name);
+ gtk_widget_show (ev_window->priv->password_dialog);
+ } else {
+ ev_password_dialog_set_bad_pass (ev_window->priv->password_dialog);
+ }
+}
+
+/* This wil try to load the document. It might be called multiple times on the
+ * same document by the password dialog.
+ *
+ * Since the flow of the error dialog is very confusing, we assume that both
+ * document and uri will go away after this function is called, and thus we need
+ * to ref/dup them. Additionally, it needs to clear
+ * ev_window->priv->password_{uri,document}, and thus people who call this
+ * function should _not_ necessarily expect those to exist after being
+ * called. */
+static gboolean
+start_loading_document (EvWindow *ev_window,
+ EvDocument *document,
+ const char *uri)
+{
+ gboolean result;
+ GError *error = NULL;
+
+ g_assert (document);
+ g_assert (document != ev_window->priv->document);
+ g_assert (uri);
+ if (ev_window->priv->password_document) {
+ g_object_unref (ev_window->priv->password_document);
+ ev_window->priv->password_document = NULL;
+ }
+ if (ev_window->priv->password_uri) {
+ g_free (ev_window->priv->password_uri);
+ ev_window->priv->password_uri = NULL;
+ }
+
+ result = ev_document_load (document, uri, &error);
+
+ /* Success! */
+ if (result) {
+ if (ev_window->priv->document)
+ g_object_unref (ev_window->priv->document);
+ ev_window->priv->document = g_object_ref (document);
+ ev_window_setup_document (ev_window);
+
+ return TRUE;
+ }
+
+ /* unable to load the document */
+ g_assert (error != NULL);
+
+ if (error->domain == EV_DOCUMENT_ERROR &&
+ error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
+ char *file_name;
+
+ ev_window->priv->password_document = g_object_ref (document);
+ ev_window->priv->password_uri = g_strdup (uri);
+
+ file_name = g_path_get_basename (uri);
+ ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
+ file_name);
+ g_free (file_name);
+ ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
+
+ ev_window_popup_password_dialog (ev_window);
+ } else {
+ unable_to_load (ev_window, error->message);
+ }
+ g_error_free (error);
+
+ return FALSE;
+}
+
+static gboolean
+is_file_supported (const gchar *mime_type)
+{
+ static char *supported_types [] = {
+ "application/pdf",
+ "application/postscript",
+ "application/x-gzpostscript",
+ "image/x-eps",
+ NULL
+ };
+ gint i;
+
+ g_return_val_if_fail (mime_type != NULL, FALSE);
+
+ if (mime_type_supported_by_gdk_pixbuf (mime_type))
+ return TRUE;
+
+ for (i = 0; supported_types[i] != NULL; i++) {
+ if (g_ascii_strcasecmp (mime_type, supported_types[i]) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+