+ g_error_free (error);
+ g_free (old_filename);
+ g_free (new_filename);
+
+ return;
+ }
+
+ g_free (old_filename);
+
+ symlink_uri = g_filename_to_uri (new_filename, NULL, NULL);
+ g_free (new_filename);
+
+ ev_application_open_uri_at_dest (EV_APP,
+ symlink_uri,
+ gtk_window_get_screen (GTK_WINDOW (window)),
+ dest,
+ 0,
+ TRUE,
+ NULL,
+ GDK_CURRENT_TIME);
+ g_free (symlink_uri);
+}
+
+static void
+ev_window_cmd_file_open_copy (GtkAction *action, EvWindow *window)
+{
+ EvPageCache *page_cache;
+ EvLinkDest *dest;
+ gint current_page;
+
+ page_cache = ev_page_cache_get (window->priv->document);
+ current_page = ev_page_cache_get_current_page (page_cache);
+
+ dest = ev_link_dest_new_page (current_page);
+ ev_window_cmd_file_open_copy_at_dest (window, dest);
+ g_object_unref (dest);
+}
+
+#ifdef HAVE_GTK_RECENT
+static void
+ev_window_cmd_recent_file_activate (GtkAction *action,
+ EvWindow *window)
+{
+ GtkRecentInfo *info;
+ const gchar *uri;
+
+ info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
+ g_assert (info != NULL);
+
+ uri = gtk_recent_info_get_uri (info);
+
+ ev_application_open_uri_at_dest (EV_APP, uri,
+ gtk_window_get_screen (GTK_WINDOW (window)),
+ NULL, 0, FALSE, NULL,
+ GDK_CURRENT_TIME);
+}
+#else
+static void
+ev_window_cmd_recent_file_activate (GtkAction *action,
+ EvWindow *ev_window)
+{
+ char *uri;
+ EggRecentItem *item;
+
+ item = egg_recent_view_uimanager_get_item (ev_window->priv->recent_view,
+ action);
+
+ uri = egg_recent_item_get_uri (item);
+
+ ev_application_open_uri_at_dest (EV_APP, uri,
+ gtk_window_get_screen (GTK_WINDOW (ev_window)),
+ NULL, 0, FALSE, NULL,
+ GDK_CURRENT_TIME);
+
+ g_free (uri);
+}
+#endif /* HAVE_GTK_RECENT */
+
+static void
+ev_window_add_recent (EvWindow *window, const char *filename)
+{
+#ifdef HAVE_GTK_RECENT
+ gtk_recent_manager_add_item (window->priv->recent_manager, filename);
+#else
+ EggRecentItem *item;
+
+ item = egg_recent_item_new_from_uri (filename);
+ egg_recent_item_add_group (item, "Evince");
+ egg_recent_model_add_full (ev_application_get_recent_model (EV_APP), item);
+#endif /* HAVE_GTK_RECENT */
+}
+
+#ifdef HAVE_GTK_RECENT
+static gint
+compare_recent_items (GtkRecentInfo *a, GtkRecentInfo *b)
+{
+ gboolean has_ev_a, has_ev_b;
+ const gchar *evince = g_get_application_name ();
+
+ has_ev_a = gtk_recent_info_has_application (a, evince);
+ has_ev_b = gtk_recent_info_has_application (b, evince);
+
+ if (has_ev_a && has_ev_b) {
+ time_t time_a, time_b;
+
+ time_a = gtk_recent_info_get_modified (a);
+ time_b = gtk_recent_info_get_modified (b);
+
+ return (time_b - time_a);
+ } else if (has_ev_a) {
+ return -1;
+ } else if (has_ev_b) {
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* HAVE_GTK_RECENT */
+
+/*
+ * Doubles underscore to avoid spurious menu accels.
+ */
+static gchar *
+ev_window_get_recent_file_label (gint index, const gchar *filename)
+{
+ GString *str;
+ gint length;
+ const gchar *p;
+ const gchar *end;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ length = strlen (filename);
+ str = g_string_sized_new (length + 10);
+ g_string_printf (str, "_%d. ", index);
+
+ p = filename;
+ end = filename + length;
+
+ while (p != end) {
+ const gchar *next;
+ next = g_utf8_next_char (p);
+
+ switch (*p) {
+ case '_':
+ g_string_append (str, "__");
+ break;
+ default:
+ g_string_append_len (str, p, next - p);
+ break;
+ }
+
+ p = next;
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+static void
+ev_window_setup_recent (EvWindow *ev_window)
+{
+#ifdef HAVE_GTK_RECENT
+ GList *items, *l;
+ guint n_items = 0;
+ const gchar *evince = g_get_application_name ();
+ static guint i = 0;
+
+ if (ev_window->priv->recent_ui_id > 0) {
+ gtk_ui_manager_remove_ui (ev_window->priv->ui_manager,
+ ev_window->priv->recent_ui_id);
+ gtk_ui_manager_ensure_update (ev_window->priv->ui_manager);
+ }
+ ev_window->priv->recent_ui_id = gtk_ui_manager_new_merge_id (ev_window->priv->ui_manager);
+
+ if (ev_window->priv->recent_action_group) {
+ gtk_ui_manager_remove_action_group (ev_window->priv->ui_manager,
+ ev_window->priv->recent_action_group);
+ g_object_unref (ev_window->priv->recent_action_group);
+ }
+ ev_window->priv->recent_action_group = gtk_action_group_new ("RecentFilesActions");
+ gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
+ ev_window->priv->recent_action_group, 0);
+
+ items = gtk_recent_manager_get_items (ev_window->priv->recent_manager);
+ items = g_list_sort (items, (GCompareFunc) compare_recent_items);
+
+ for (l = items; l && l->data; l = g_list_next (l)) {
+ GtkRecentInfo *info;
+ GtkAction *action;
+ gchar *action_name;
+ gchar *label;
+
+ info = (GtkRecentInfo *) l->data;
+
+ if (!gtk_recent_info_has_application (info, evince) ||
+ (gtk_recent_info_is_local (info) && !gtk_recent_info_exists (info)))
+ continue;
+
+ action_name = g_strdup_printf ("RecentFile%u", i++);
+ label = ev_window_get_recent_file_label (
+ n_items + 1, gtk_recent_info_get_display_name (info));
+
+ action = g_object_new (GTK_TYPE_ACTION,
+ "name", action_name,
+ "label", label,
+ NULL);
+
+ g_object_set_data_full (G_OBJECT (action),
+ "gtk-recent-info",
+ gtk_recent_info_ref (info),
+ (GDestroyNotify) gtk_recent_info_unref);
+
+ g_signal_connect (G_OBJECT (action), "activate",
+ G_CALLBACK (ev_window_cmd_recent_file_activate),
+ (gpointer) ev_window);
+
+ gtk_action_group_add_action (ev_window->priv->recent_action_group,
+ action);
+ g_object_unref (action);
+
+ gtk_ui_manager_add_ui (ev_window->priv->ui_manager,
+ ev_window->priv->recent_ui_id,
+ "/MainMenu/FileMenu/RecentFilesMenu",
+ label,
+ action_name,
+ GTK_UI_MANAGER_MENUITEM,
+ FALSE);
+ g_free (action_name);
+ g_free (label);
+
+ if (++n_items == 5)
+ break;
+ }
+
+ g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+ g_list_free (items);
+#else /* HAVE_GTK_RECENT */
+ ev_window->priv->recent_view = egg_recent_view_uimanager_new (ev_window->priv->ui_manager,
+ "/MainMenu/FileMenu/RecentFilesMenu",
+ G_CALLBACK (ev_window_cmd_recent_file_activate),
+ ev_window);
+
+ egg_recent_view_uimanager_show_icons (EGG_RECENT_VIEW_UIMANAGER (ev_window->priv->recent_view), FALSE);
+
+ egg_recent_view_set_model (EGG_RECENT_VIEW (ev_window->priv->recent_view),
+ ev_application_get_recent_model (EV_APP));
+
+ egg_recent_view_uimanager_set_trailing_sep (ev_window->priv->recent_view, TRUE);
+
+ g_signal_connect (ev_window->priv->recent_view, "activate",
+ G_CALLBACK (ev_window_cmd_recent_file_activate), ev_window);
+#endif /* HAVE_GTK_RECENT */
+}
+
+static gint
+save_xfer_update_progress_callback (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *info,
+ GnomeVFSURI *tmp_uri)
+{
+ switch (info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+ gchar *uri;
+
+ uri = gnome_vfs_uri_to_string (tmp_uri, 0);
+ ev_tmp_uri_unlink (uri);
+ g_free (uri);
+ gnome_vfs_uri_unref (tmp_uri);
+ }
+ return 1;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ if (info->vfs_status != GNOME_VFS_OK) {
+ GtkWidget *dialog;
+ gchar *uri;
+
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("The file could not be saved as “%s”."),
+ info->target_name);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ gnome_vfs_result_to_string (info->vfs_status));
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+ gtk_widget_show (dialog);
+
+ uri = gnome_vfs_uri_to_string (tmp_uri, 0);
+ ev_tmp_uri_unlink (uri);
+ g_free (uri);
+ gnome_vfs_uri_unref (tmp_uri);
+ }
+ return 1;
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+ case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
+ return 1;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return 0;
+}
+
+static void
+ev_window_save_remote (EvWindow *ev_window,
+ GnomeVFSURI *src,
+ GnomeVFSURI *dst)
+{
+ GnomeVFSAsyncHandle *handle;
+ GList *slist = NULL;
+ GList *tlist = NULL;
+
+ slist = g_list_prepend (slist, src);
+ tlist = g_list_prepend (tlist, dst);
+ gnome_vfs_async_xfer (&handle, slist, tlist,
+ GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
+ GNOME_VFS_XFER_ERROR_MODE_ABORT,
+ GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ (GnomeVFSAsyncXferProgressCallback)
+ save_xfer_update_progress_callback,
+ gnome_vfs_uri_ref (src),
+ NULL, NULL);
+ g_list_free (slist);
+ g_list_free (tlist);