=== added directory 'backend/pspdf'
=== added file 'backend/pspdf/Makefile.am'
--- backend/pspdf/Makefile.am	1970-01-01 00:00:00 +0000
+++ backend/pspdf/Makefile.am	2007-04-02 02:19:24 +0000
@@ -0,0 +1,13 @@
+INCLUDES =							\
+	-I$(top_srcdir)						\
+	-I$(top_srcdir)/libdocument				\
+	$(BACKEND_CFLAGS)					\
+	$(POPPLER_CFLAGS)
+
+noinst_LTLIBRARIES = libpspdfdocument.la
+
+libpspdfdocument_la_SOURCES =		\
+	pspdf-document.c		\
+	pspdf-document.h		\
+	pspdf-converter.c		\
+	pspdf-converter.h

=== added file 'backend/pspdf/pspdf-converter.c'
--- backend/pspdf/pspdf-converter.c	1970-01-01 00:00:00 +0000
+++ backend/pspdf/pspdf-converter.c	2007-04-02 06:53:07 +0000
@@ -0,0 +1,426 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+ *  Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *  Copyright 1998 - 2005 The Free Software Foundation
+ *
+ * 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 <glib/gstdio.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "pspdf-converter.h"
+
+#define MAX_BUFSIZE 1024
+
+enum { // signals
+    CONVERSION_FINISHED,
+    LAST_SIGNAL
+};
+
+static guint pspdf_signals[LAST_SIGNAL];
+
+struct _PSPDFConverter {
+    GObject parent_instance;
+
+    GPid pid;               /* PID of converter, -1 if none  */
+    GIOChannel *input;      /* stdin of converter            */
+    GIOChannel *output;     /* stdout of converter           */
+    GIOChannel *error;      /* stderr of converter           */
+    guint input_id;
+    guint output_id;
+    guint error_id;
+
+    gchar *filename;        /* the currently loaded filename */
+    GString *pdfdata;       /* the conversion result */
+    
+};
+
+struct _PSPDFConverterClass {
+    GObjectClass parent_class;
+    void (* conversion_finished) (PSPDFConverter *ps2pdf);
+};
+
+G_DEFINE_TYPE (PSPDFConverter, pspdf_converter, G_TYPE_OBJECT)
+
+
+static void
+pspdf_converter_dispose (GObject *object)
+{
+    PSPDFConverter *ps2pdf = PSPDF_CONVERTER (object);
+    
+    if (ps2pdf->pdfdata) {
+        g_string_free(ps2pdf->pdfdata, TRUE);
+        ps2pdf->pdfdata = NULL;
+    }
+
+    if (ps2pdf->filename) {
+        g_free (ps2pdf->filename);
+        ps2pdf->filename = NULL;
+    }
+
+    pspdf_converter_stop (ps2pdf);
+
+    G_OBJECT_CLASS (pspdf_converter_parent_class)->dispose (object);
+}
+
+static void
+pspdf_converter_init (PSPDFConverter *ps2pdf)
+{
+    ps2pdf->pid = -1;
+    ps2pdf->pdfdata = g_string_new(NULL);
+}
+
+static void
+pspdf_converter_class_init (PSPDFConverterClass *klass)
+{
+    GObjectClass *object_class;
+    GParamSpec *pspec;
+
+    object_class = G_OBJECT_CLASS (klass);
+
+    pspdf_signals[CONVERSION_FINISHED] =
+        g_signal_new ("conversion_finished",
+                PSPDF_TYPE_CONVERTER,
+                G_SIGNAL_RUN_LAST,
+                G_STRUCT_OFFSET (PSPDFConverterClass, conversion_finished),
+                NULL, NULL,
+                g_cclosure_marshal_VOID__VOID,
+                G_TYPE_NONE,
+                0,
+                NULL);
+    
+    object_class->dispose = pspdf_converter_dispose;
+}
+
+static void
+pspdf_converter_failed (PSPDFConverter *ps2pdf, const char *msg)
+{
+    g_warning (msg ? msg : "PS2PDF conversion failed.");
+    pspdf_converter_stop (ps2pdf);
+}
+
+static void
+pspdf_converter_finished (GPid           pid,
+        gint           status,
+        PSPDFConverter *ps2pdf)
+{
+    g_spawn_close_pid (ps2pdf->pid);
+    ps2pdf->pid = -1;
+    pspdf_converter_stop (ps2pdf);
+    g_signal_emit (ps2pdf, pspdf_signals[CONVERSION_FINISHED], 0, NULL);
+}
+
+static gboolean
+pspdf_converter_output (GIOChannel    *io,
+        GIOCondition   condition,
+        PSPDFConverter *ps2pdf)
+{
+    gchar buf[MAX_BUFSIZE + 1];
+    gsize bytes = 0;
+    GIOStatus status;
+    GError *error = NULL;
+
+    status = g_io_channel_read_chars (io, buf, MAX_BUFSIZE, &bytes, &error);
+    switch (status) {
+        case G_IO_STATUS_NORMAL:
+            if (bytes > 0) {
+                ps2pdf->pdfdata = g_string_append_len (ps2pdf->pdfdata, buf, bytes);
+            }
+            break;
+        case G_IO_STATUS_EOF:
+            g_io_channel_unref (ps2pdf->output);
+            ps2pdf->output = NULL;
+            ps2pdf->output_id = 0;
+
+            return FALSE;
+        case G_IO_STATUS_ERROR:
+            pspdf_converter_failed (ps2pdf, error->message);
+            g_error_free (error);
+            ps2pdf->output_id = 0;
+
+            return FALSE;
+        default:
+            break;
+    }
+
+    if (!ps2pdf->error) {
+            pspdf_converter_failed (ps2pdf, NULL);
+    }
+
+    return TRUE;
+}
+
+static gboolean
+pspdf_converter_error (GIOChannel    *io,
+        GIOCondition   condition,
+        PSPDFConverter *ps2pdf)
+{
+    gchar buf[MAX_BUFSIZE + 1];
+    gsize bytes = 0;
+    GIOStatus status;
+    GError *error = NULL;
+
+    status = g_io_channel_read_chars (io, buf, MAX_BUFSIZE,
+            &bytes, &error);
+    switch (status) {
+        case G_IO_STATUS_NORMAL:
+            if (bytes > 0) {
+                    buf[bytes] = '\0';
+                    g_print ("%s", buf);
+            }
+
+            break;
+        case G_IO_STATUS_EOF:
+            g_io_channel_unref (ps2pdf->error);
+            ps2pdf->error = NULL;
+            ps2pdf->error_id = 0;
+
+            return FALSE;
+        case G_IO_STATUS_ERROR:
+            pspdf_converter_failed (ps2pdf, error->message);
+            g_error_free (error);
+            ps2pdf->error_id = 0;
+
+            break;
+        default:
+            break;
+    }
+
+    if (!ps2pdf->output) {
+            pspdf_converter_failed (ps2pdf, NULL);
+    }
+
+    return TRUE;
+}
+
+/* Public methods */
+PSPDFConverter *
+pspdf_converter_new (const gchar *filename)
+{
+        PSPDFConverter *ps2pdf;
+
+        g_return_val_if_fail (filename != NULL, NULL);
+
+        ps2pdf = PSPDF_CONVERTER (g_object_new (PSPDF_TYPE_CONVERTER, NULL));
+        ps2pdf->filename = g_strdup (filename);
+
+        return ps2pdf;
+}
+
+#define NUM_ARGS    100
+#define NUM_GS_ARGS (NUM_ARGS - 20)
+#define NUM_PS2PDF_ARGS 10
+
+void
+pspdf_converter_start (PSPDFConverter *ps2pdf)
+{
+    gchar *argv[NUM_ARGS], *dir, *gs_path;
+    gchar **gs_args, **ps2pdf_args = NULL;
+    gint pin, pout, perr;
+    gint argc = 0, i;
+    GError *error = NULL;
+
+    g_assert (ps2pdf->filename != NULL);
+    g_assert (ps2pdf->pid == -1); // one converter per object
+
+    pspdf_converter_stop (ps2pdf);
+
+    dir = g_path_get_dirname (ps2pdf->filename);
+    gs_path = g_find_program_in_path ("gs");
+    gs_args = g_strsplit (gs_path, " ", NUM_GS_ARGS);
+    g_free (gs_path);
+    for (i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++) {
+        argv[argc] = gs_args[i];
+    }
+    
+    ps2pdf_args = g_strsplit (PS_TO_PDF_PARAMS, " ", NUM_PS2PDF_ARGS);
+    for (i = 0; i < NUM_PS2PDF_ARGS && ps2pdf_args[i]; i++, argc++) {
+        argv[argc] = ps2pdf_args[i];
+    }
+
+    argv[argc++] = "-q";
+    argv[argc++] = "-dSAFER";
+    argv[argc++] = "-dNOPAUSE";
+    argv[argc++] = "-dBATCH";
+    argv[argc++] = "-sOutputFile=-"; // stdout
+    argv[argc++] = ps2pdf->filename;
+
+    argv[argc++] = NULL;
+
+    if (g_spawn_async_with_pipes (dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
+                                  NULL, NULL,
+                                  &(ps2pdf->pid), &pin, &pout, &perr,
+                                  &error)) {
+        GIOFlags flags;
+
+        ps2pdf->input = g_io_channel_unix_new (pin);
+        g_io_channel_set_encoding (ps2pdf->input, NULL, NULL);
+        flags = g_io_channel_get_flags (ps2pdf->input);
+        g_io_channel_set_flags (ps2pdf->input, flags | G_IO_FLAG_NONBLOCK, NULL);
+        ps2pdf->input_id = 0;
+        
+        ps2pdf->output = g_io_channel_unix_new (pout);
+        g_io_channel_set_encoding (ps2pdf->output, NULL, NULL);
+        flags = g_io_channel_get_flags (ps2pdf->output);
+        g_io_channel_set_flags (ps2pdf->output, flags | G_IO_FLAG_NONBLOCK, NULL);
+        ps2pdf->output_id = g_io_add_watch (ps2pdf->output, G_IO_IN,
+                                        (GIOFunc)pspdf_converter_output,
+                                        ps2pdf);
+        
+        ps2pdf->error = g_io_channel_unix_new (perr);
+        flags = g_io_channel_get_flags (ps2pdf->error);
+        g_io_channel_set_flags (ps2pdf->error, flags | G_IO_FLAG_NONBLOCK, NULL);
+        ps2pdf->error_id = g_io_add_watch (ps2pdf->error, G_IO_IN,
+                                       (GIOFunc)pspdf_converter_error,
+                                       ps2pdf);
+        
+        g_child_watch_add (ps2pdf->pid,
+                           (GChildWatchFunc)pspdf_converter_finished, 
+                           ps2pdf);
+    } else {
+        g_warning (error->message);
+        g_error_free (error);
+    }
+
+    g_free (dir);
+    g_strfreev (gs_args);
+    g_strfreev (ps2pdf_args);
+}
+
+void
+pspdf_converter_start_sync (PSPDFConverter *ps2pdf)
+{
+    gchar *argv[NUM_ARGS], *dir, *gs_path;
+    gchar **gs_args, **ps2pdf_args = NULL;
+    gint pin, pout, perr;
+    gint argc = 0, i;
+    GError *error = NULL;
+
+    GIOStatus status;
+    gchar *stdoutput;
+    gsize stdoutput_length;
+
+    g_assert (ps2pdf->filename != NULL);
+    g_assert (ps2pdf->pid == -1); // one converter per object
+
+    pspdf_converter_stop (ps2pdf);
+
+    dir = g_path_get_dirname (ps2pdf->filename);
+    gs_path = g_find_program_in_path ("gs");
+    gs_args = g_strsplit (gs_path, " ", NUM_GS_ARGS);
+    g_free (gs_path);
+    for (i = 0; i < NUM_GS_ARGS && gs_args[i]; i++, argc++) {
+        argv[argc] = gs_args[i];
+    }
+    
+    ps2pdf_args = g_strsplit (PS_TO_PDF_PARAMS, " ", NUM_PS2PDF_ARGS);
+    for (i = 0; i < NUM_PS2PDF_ARGS && ps2pdf_args[i]; i++, argc++) {
+        argv[argc] = ps2pdf_args[i];
+    }
+
+    argv[argc++] = "-q";
+    argv[argc++] = "-dSAFER";
+    argv[argc++] = "-dNOPAUSE";
+    argv[argc++] = "-dBATCH";
+    argv[argc++] = "-sOutputFile=-"; // stdout
+    argv[argc++] = ps2pdf->filename;
+
+    argv[argc++] = NULL;
+
+    if (g_spawn_async_with_pipes (dir, argv, NULL, 0,
+                                  NULL, NULL,
+                                  &(ps2pdf->pid), &pin, &pout, &perr,
+                                  &error)) {
+        ps2pdf->output = g_io_channel_unix_new (pout);
+        g_io_channel_set_encoding (ps2pdf->output, NULL, NULL);
+        ps2pdf->output_id = 0;
+
+        status = g_io_channel_read_to_end(ps2pdf->output, &stdoutput,
+                &stdoutput_length, &error);
+        g_io_channel_unref(ps2pdf->output);
+        ps2pdf->output = NULL;
+
+        if (status == G_IO_STATUS_NORMAL) {
+            g_string_append_len(ps2pdf->pdfdata, stdoutput, stdoutput_length);
+            pspdf_converter_finished(ps2pdf->pid, 0, ps2pdf);
+            g_free(stdoutput);
+        } else {
+            g_warning (error->message);
+            g_error_free (error);
+        }
+    } else {
+        g_warning (error->message);
+        g_error_free (error);
+    }
+
+    g_free (dir);
+    g_strfreev (gs_args);
+    g_strfreev (ps2pdf_args);
+
+}
+
+void
+pspdf_converter_stop (PSPDFConverter *ps2pdf)
+{
+    if (ps2pdf->pid > 0) {
+        gint status = 0;
+
+        kill (ps2pdf->pid, SIGTERM);
+        while ((wait (&status) == -1) && (errno == EINTR));
+        g_spawn_close_pid (ps2pdf->pid);
+        ps2pdf->pid = -1;
+    }
+
+    if (ps2pdf->input) {
+        g_io_channel_unref (ps2pdf->input);
+        ps2pdf->input = NULL;
+
+        if (ps2pdf->input_id > 0) {
+            g_source_remove (ps2pdf->input_id);
+            ps2pdf->input_id = 0;
+        }
+    }
+
+    if (ps2pdf->output) {
+        g_io_channel_unref (ps2pdf->output);
+        ps2pdf->output = NULL;
+
+        if (ps2pdf->output_id > 0) {
+            g_source_remove (ps2pdf->output_id);
+            ps2pdf->output_id = 0;
+        }
+    }
+
+    if (ps2pdf->error) {
+        g_io_channel_unref (ps2pdf->error);
+        ps2pdf->error = NULL;
+
+        if (ps2pdf->error_id > 0) {
+            g_source_remove (ps2pdf->error_id);
+            ps2pdf->error_id = 0;
+        }
+    }
+}
+
+GString *
+pspdf_converter_get_data(PSPDFConverter *ps2pdf)
+{
+    return ps2pdf->pdfdata;
+}

=== added file 'backend/pspdf/pspdf-converter.h'
--- backend/pspdf/pspdf-converter.h	1970-01-01 00:00:00 +0000
+++ backend/pspdf/pspdf-converter.h	2007-04-02 05:05:35 +0000
@@ -0,0 +1,46 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+ *  Copyright (C) 2007 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 __PSPDF_CONVERTER_H__
+#define __PSPDF_CONVERTER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PSPDFConverter        PSPDFConverter;
+typedef struct _PSPDFConverterClass   PSPDFConverterClass;
+
+#define PSPDF_TYPE_CONVERTER                (pspdf_converter_get_type())
+#define PSPDF_CONVERTER(object)             (G_TYPE_CHECK_INSTANCE_CAST((object), PSPDF_TYPE_CONVERTER, PSPDFConverter))
+#define PSPDF_CONVERTER_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), PSPDF_TYPE_CONVERTER, PSPDFConverterClass))
+#define PSPDF_IS_CONVERTER(object)          (G_TYPE_CHECK_INSTANCE_TYPE((object), PSPDF_TYPE_CONVERTER))
+#define PSPDF_IS_CONVERTER_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), PSPDF_TYPE_CONVERTER))
+#define PSPDF_CONVERTER_GET_CLASS(object)   (G_TYPE_INSTANCE_GET_CLASS((object), PSPDF_TYPE_CONVERTER, PSPDFConverterClass))
+
+GType           pspdf_converter_get_type    (void) G_GNUC_CONST;
+PSPDFConverter  *pspdf_converter_new        (const gchar    *filename);
+void            pspdf_converter_start       (PSPDFConverter *ps2pdf);
+void            pspdf_converter_start_sync  (PSPDFConverter *ps2pdf);
+void            pspdf_converter_stop        (PSPDFConverter *ps2pdf);
+GString *       pspdf_converter_get_data    (PSPDFConverter *ps2pdf);
+G_END_DECLS
+
+#endif /* __PSPDF_CONVERTER_H__ */

=== added file 'backend/pspdf/pspdf-document.c'
--- backend/pspdf/pspdf-document.c	1970-01-01 00:00:00 +0000
+++ backend/pspdf/pspdf-document.c	2007-04-02 10:27:51 +0000
@@ -0,0 +1,979 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
+/* pspdf-document.c: Implementation of EvDocument for PS
+ *
+ * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+ * Copyright (C) 2004, Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "config.h"
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <poppler.h>
+#include <poppler-document.h>
+#include <poppler-page.h>
+
+#include "pspdf-document.h"
+#include "pspdf-converter.h"
+#include "ev-document-thumbnails.h"
+#include "ev-document-fonts.h"
+#include "ev-document-find.h"
+#include "ev-document-misc.h"
+#include "ev-selection.h"
+
+typedef struct {
+    PSPDFDocument *document;
+    char *text;
+    GList **pages;
+    guint idle;
+    int start_page;
+    int search_page;
+} PSPDFDocumentSearch;
+
+struct _PSPDFDocumentClass
+{
+    GObjectClass parent_class;
+};
+
+struct _PSPDFDocument
+{
+	  GObject object;
+ 
+    PSPDFConverter *converter;
+    PopplerDocument *document;
+
+    PopplerFontInfo *font_info;
+    PopplerFontsIter *fonts_iter;
+    int fonts_scanned_pages;
+
+    PSPDFDocumentSearch *search;
+    //PdfPrintContext *print_ctx;
+
+	  gchar *uri;
+};
+
+typedef struct _PSPDFDocumentClass PSPDFDocumentClass;
+
+static void pspdf_document_document_iface_init              (EvDocumentIface *iface);
+static void pspdf_document_document_thumbnails_iface_init   (EvDocumentThumbnailsIface *iface);
+static void pspdf_selection_iface_init                      (EvSelectionIface          *iface);
+static void pspdf_document_find_iface_init                  (EvDocumentFindIface       *iface);
+static void pspdf_document_document_fonts_iface_init        (EvDocumentFontsIface *iface);
+
+
+static void pspdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
+        EvRenderContext           *rc,
+        gint                      *width,
+        gint                      *height);
+static int  pspdf_document_get_n_pages (EvDocument *document);
+static void pspdf_document_search_free (PSPDFDocumentSearch *search);
+
+G_DEFINE_TYPE_WITH_CODE (PSPDFDocument, pspdf_document, G_TYPE_OBJECT,
+    {       G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
+                pspdf_document_document_iface_init);
+    				G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
+							  pspdf_document_document_thumbnails_iface_init);
+				    G_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
+							  pspdf_selection_iface_init);
+            G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
+							  pspdf_document_find_iface_init);
+            G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
+							  pspdf_document_document_fonts_iface_init);
+    }); 
+
+static void
+set_rc_data (PSPDFDocument *pspdf_document,
+	     EvRenderContext *rc)
+{
+    if (rc->data == NULL) {
+        rc->data = poppler_document_get_page (pspdf_document->document,
+                rc->page);
+        rc->destroy = g_object_unref;
+    } else {
+        g_assert (rc->page == poppler_page_get_index (POPPLER_PAGE (rc->data)));
+    }
+}
+
+static void
+pspdf_document_search_free (PSPDFDocumentSearch   *search)
+{
+    PSPDFDocument *pspdf_document = search->document;
+    int n_pages;
+    int i;
+
+    if (search->idle != 0)
+        g_source_remove (search->idle);
+
+    n_pages = pspdf_document_get_n_pages (EV_DOCUMENT (pspdf_document));
+    for (i = 0; i < n_pages; i++) {
+            g_list_foreach (search->pages[i], (GFunc) g_free, NULL);
+            g_list_free (search->pages[i]);
+    }
+    g_free (search->pages);
+
+    g_free (search->text);
+    g_free (search);
+}
+
+static void
+conversion_finished (PSPDFConverter *pspdf_converter,
+        PSPDFDocument   *pspdf_document)
+{
+    GString* data;
+    GError * poppler_error = NULL;
+
+    data = pspdf_converter_get_data(pspdf_converter);
+    pspdf_document->document =
+		    poppler_document_new_from_data (data->str,
+                data->len,
+                NULL,
+                NULL);
+}
+
+/* EvDocument Interface Implementation*/
+
+static gboolean
+pspdf_document_load (EvDocument  *document,
+        const char  *uri,
+        GError     **error)
+{
+    PSPDFDocument   *pspdf_document = PSPDF_DOCUMENT (document);
+
+    gchar *filename;
+
+    /* FIXME: We could actually load uris  */
+    filename = g_filename_from_uri (uri, NULL, error);
+    if (!filename)
+        return FALSE;
+    
+    pspdf_document->converter = pspdf_converter_new(filename);
+    g_signal_connect (G_OBJECT (pspdf_document->converter), "conversion_finished",
+			  G_CALLBACK (conversion_finished),
+        pspdf_document);
+    pspdf_converter_start_sync(pspdf_document->converter);
+
+    pspdf_document->uri = g_strdup (uri);
+
+    return TRUE;
+}
+
+static gboolean
+pspdf_document_save (EvDocument  *document,
+		      const char  *uri,
+		      GError     **error)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document);
+    
+    return ev_xfer_uri_simple (pspdf_document->uri, uri, error); 
+}
+
+static gboolean
+pspdf_document_can_get_text (EvDocument *document)
+{
+    return TRUE;
+}
+
+static char *
+pspdf_document_get_text (EvDocument *document, int page, EvRectangle *rect)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document);
+    PopplerPage *poppler_page;
+    PopplerRectangle r;
+    double height;
+    char *text;
+
+    poppler_page = poppler_document_get_page (pspdf_document->document, page);
+    g_return_val_if_fail (poppler_page != NULL, NULL);
+
+    poppler_page_get_size (poppler_page, NULL, &height);
+    r.x1 = rect->x1;
+    r.y1 = height - rect->y2;
+    r.x2 = rect->x2;
+    r.y2 = height - rect->y1;
+
+    text = poppler_page_get_text (poppler_page, &r);
+
+    g_object_unref (poppler_page);
+
+    return text;
+}
+
+static int
+pspdf_document_get_n_pages (EvDocument *document)
+{
+    return poppler_document_get_n_pages (PSPDF_DOCUMENT (document)->document);
+}
+
+static void
+pspdf_document_get_page_size (EvDocument   *document,
+			    int           page,
+			    double       *width,
+			    double       *height)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document);
+    PopplerPage *poppler_page;
+
+    poppler_page = poppler_document_get_page (pspdf_document->document, page);
+    poppler_page_get_size (poppler_page, width, height);
+    g_object_unref (poppler_page);
+}
+
+static EvDocumentInfo *
+pspdf_document_get_info (EvDocument *document)
+{
+    EvDocumentInfo *info;
+    PopplerPageLayout layout;
+    PopplerPageMode mode;
+    PopplerViewerPreferences view_prefs;
+    PopplerPermissions permissions;
+
+    info = g_new0 (EvDocumentInfo, 1);
+
+    info->fields_mask = EV_DOCUMENT_INFO_TITLE |
+        EV_DOCUMENT_INFO_FORMAT |
+        EV_DOCUMENT_INFO_AUTHOR |
+        EV_DOCUMENT_INFO_SUBJECT |
+        EV_DOCUMENT_INFO_KEYWORDS |
+        EV_DOCUMENT_INFO_LAYOUT |
+        EV_DOCUMENT_INFO_START_MODE |
+        EV_DOCUMENT_INFO_PERMISSIONS |
+        EV_DOCUMENT_INFO_UI_HINTS |
+        EV_DOCUMENT_INFO_CREATOR |
+        EV_DOCUMENT_INFO_PRODUCER |
+        EV_DOCUMENT_INFO_CREATION_DATE |
+        EV_DOCUMENT_INFO_MOD_DATE |
+        EV_DOCUMENT_INFO_LINEARIZED |
+        EV_DOCUMENT_INFO_N_PAGES |
+        EV_DOCUMENT_INFO_SECURITY | 
+        EV_DOCUMENT_INFO_PAPER_SIZE;
+
+    g_object_get (PSPDF_DOCUMENT (document)->document,
+            "title", &(info->title),
+            "format", &(info->format),
+            "author", &(info->author),
+            "subject", &(info->subject),
+            "keywords", &(info->keywords),
+            "page-mode", &mode,
+            "page-layout", &layout,
+            "viewer-preferences", &view_prefs,
+            "permissions", &permissions,
+            "creator", &(info->creator),
+            "producer", &(info->producer),
+            "creation-date", &(info->creation_date),
+            "mod-date", &(info->modified_date),
+            "linearized", &(info->linearized),
+            NULL);
+
+    pspdf_document_get_page_size(document, 0,
+            &(info->paper_width),
+            &(info->paper_height));
+
+    // Convert to mm.
+    info->paper_width = info->paper_width / 72.0f * 25.4f;
+    info->paper_height = info->paper_height / 72.0f * 25.4f;
+
+    switch (layout) {
+        case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
+            info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
+            break;
+        case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
+            info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
+            break;
+        case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
+            info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
+            break;
+        case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT:
+            info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
+        case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT:
+            info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
+            break;
+        case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
+            info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
+            break;
+        default:
+            break;
+    }
+
+    switch (mode) {
+        case POPPLER_PAGE_MODE_NONE:
+            info->mode = EV_DOCUMENT_MODE_NONE;
+            break;
+        case POPPLER_PAGE_MODE_USE_THUMBS:
+            info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
+            break;
+        case POPPLER_PAGE_MODE_USE_OC:
+            info->mode = EV_DOCUMENT_MODE_USE_OC;
+            break;
+        case POPPLER_PAGE_MODE_FULL_SCREEN:
+            info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
+            break;
+        case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
+            info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
+        default:
+            break;
+    }
+
+    info->ui_hints = 0;
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
+            info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
+    }
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
+            info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
+    }
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
+            info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
+    }
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
+            info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
+    }
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
+            info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
+    }
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
+            info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
+    }
+    if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
+            info->ui_hints |=  EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
+    }
+
+    info->permissions = 0;
+    if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
+            info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
+    }
+    if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
+            info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
+    }
+    if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
+            info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
+    }
+    if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
+            info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
+    }
+
+    info->n_pages = ev_document_get_n_pages (document);
+    /* translators: this is the document security state */
+    info->security = g_strdup (_("No"));
+
+    return info;
+}
+
+static GdkPixbuf *
+pspdf_document_render_pixbuf (EvDocument   *document,
+			    EvRenderContext *rc)
+{
+    PSPDFDocument *pspdf_document;
+    GdkPixbuf *pixbuf;
+    double width_points, height_points;
+    gint width, height;
+
+    pspdf_document = PSPDF_DOCUMENT (document);
+
+    set_rc_data (pspdf_document, rc);
+
+    poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
+
+    if (rc->rotation == 90 || rc->rotation == 270) {
+            width = (int) ((height_points * rc->scale) + 0.5);
+            height = (int) ((width_points * rc->scale) + 0.5);
+    } else {
+            width = (int) ((width_points * rc->scale) + 0.5);
+            height = (int) ((height_points * rc->scale) + 0.5);
+    }
+
+    pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+            FALSE, 8,
+            width, height);
+
+    poppler_page_render_to_pixbuf (POPPLER_PAGE (rc->data),
+            0, 0,
+            width, height,
+            rc->scale,
+            rc->rotation,
+            pixbuf);
+
+    return pixbuf;
+}
+
+static void
+pspdf_document_document_iface_init (EvDocumentIface *iface)
+{
+    iface->load = pspdf_document_load;
+    iface->save = pspdf_document_save;
+    iface->can_get_text = pspdf_document_can_get_text;
+    iface->get_text = pspdf_document_get_text;
+    iface->get_info = pspdf_document_get_info;
+    iface->get_n_pages = pspdf_document_get_n_pages;
+    iface->get_page_size = pspdf_document_get_page_size;
+    iface->render_pixbuf = pspdf_document_render_pixbuf;
+}
+
+/* EvDocumentThumbnails Interface Implementation*/
+
+static GdkPixbuf *
+make_thumbnail_for_page (PSPDFDocument     *pspdf_document,
+			 PopplerPage     *poppler_page, 
+			 EvRenderContext *rc)
+{
+    GdkPixbuf *pixbuf;
+    int width, height;
+
+    pspdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pspdf_document),
+            rc, &width, &height);
+
+    pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+    gdk_pixbuf_fill (pixbuf, 0xffffffff);
+
+    ev_document_fc_mutex_lock ();
+        poppler_page_render_to_pixbuf (poppler_page, 0, 0,
+                width, height, rc->scale, rc->rotation, pixbuf);
+    ev_document_fc_mutex_unlock ();
+
+    return pixbuf;
+}
+
+static GdkPixbuf *
+pspdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
+				       EvRenderContext      *rc, 
+				       gboolean              border)
+{
+    PSPDFDocument *pspdf_document;
+    PopplerPage *poppler_page;
+    GdkPixbuf *pixbuf;
+    GdkPixbuf *border_pixbuf;
+
+    pspdf_document = PSPDF_DOCUMENT (document_thumbnails);
+
+    poppler_page = poppler_document_get_page (pspdf_document->document, rc->page);
+    g_return_val_if_fail (poppler_page != NULL, NULL);
+
+    pixbuf = poppler_page_get_thumbnail (poppler_page);
+    if (!pixbuf) {
+        /* There is no provided thumbnail.  We need to make one. */
+        pixbuf = make_thumbnail_for_page (pspdf_document, poppler_page, rc);
+    }
+
+    if (border) {		
+        border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
+        g_object_unref (pixbuf);
+        pixbuf = border_pixbuf;
+    }		
+
+    g_object_unref (poppler_page);
+
+    return pixbuf;
+}
+
+static void
+pspdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
+					EvRenderContext      *rc,
+					gint                 *width,
+					gint                 *height)
+{
+    PSPDFDocument *pspdf_document;
+    PopplerPage *poppler_page;
+    gint has_thumb;
+
+    pspdf_document = PSPDF_DOCUMENT (document_thumbnails);
+    poppler_page = poppler_document_get_page (pspdf_document->document, rc->page);
+
+    g_return_if_fail (poppler_page != NULL);
+
+    has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height);
+
+    if (!has_thumb) {
+        double page_width, page_height;
+
+        poppler_page_get_size (poppler_page, &page_width, &page_height);
+
+        *width = (gint) (page_width * rc->scale);
+        *height = (gint) (page_height * rc->scale);
+    }
+
+    if (rc->rotation == 90 || rc->rotation == 270) {
+        gint  temp;
+
+        temp = *width;
+        *width = *height;
+        *height = temp;
+    }
+
+    g_object_unref (poppler_page);
+}
+
+static void
+pspdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
+{
+    iface->get_thumbnail = pspdf_document_thumbnails_get_thumbnail;
+    iface->get_dimensions = pspdf_document_thumbnails_get_dimensions;
+}
+
+/* EvSelection Interface Implementation*/
+
+static void
+pspdf_selection_render_selection (EvSelection      *selection,
+				EvRenderContext  *rc,
+				GdkPixbuf       **pixbuf,
+				EvRectangle      *points,
+				EvRectangle      *old_points,
+				GdkColor        *text,
+				GdkColor        *base)
+{
+    PSPDFDocument *pspdf_document;
+    double width_points, height_points;
+    gint width, height;
+
+    pspdf_document = PSPDF_DOCUMENT (selection);
+    set_rc_data (pspdf_document, rc);
+
+    poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
+    width = (int) ((width_points * rc->scale) + 0.5);
+    height = (int) ((height_points * rc->scale) + 0.5);
+
+    if (*pixbuf == NULL) {
+        *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+    }
+
+    poppler_page_render_selection (POPPLER_PAGE (rc->data),
+            rc->scale, rc->rotation, *pixbuf,
+            (PopplerRectangle *)points,
+            (PopplerRectangle *)old_points,
+            text,
+            base);
+}
+
+
+static GdkRegion *
+pspdf_selection_get_selection_region (EvSelection     *selection,
+				    EvRenderContext *rc,
+				    EvRectangle     *points)
+{
+    PSPDFDocument *pspdf_document;
+    GdkRegion *retval;
+
+    pspdf_document = PSPDF_DOCUMENT (selection);
+
+    set_rc_data (pspdf_document, rc);
+
+    retval = poppler_page_get_selection_region ((PopplerPage *)rc->data, rc->scale, (PopplerRectangle *) points);
+
+    return retval;
+}
+
+static GdkRegion *
+pspdf_selection_get_selection_map (EvSelection     *selection,
+				 EvRenderContext *rc)
+{
+    PSPDFDocument *pspdf_document;
+    PopplerPage *poppler_page;
+    PopplerRectangle points;
+    GdkRegion *retval;
+
+    pspdf_document = PSPDF_DOCUMENT (selection);
+    poppler_page = poppler_document_get_page (pspdf_document->document,
+            rc->page);
+
+    points.x1 = 0.0;
+    points.y1 = 0.0;
+    poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
+    retval = poppler_page_get_selection_region (poppler_page, 1.0, &points);
+    g_object_unref (poppler_page);
+
+    return retval;
+}
+
+static void
+pspdf_selection_iface_init (EvSelectionIface *iface)
+{
+        iface->render_selection = pspdf_selection_render_selection;
+        iface->get_selection_region = pspdf_selection_get_selection_region;
+        iface->get_selection_map = pspdf_selection_get_selection_map;
+}
+
+/* EvDocumentFind Interface Implementation*/
+
+static gboolean
+pspdf_document_search_idle_callback (void *data)
+{
+    PSPDFDocumentSearch *search = (PSPDFDocumentSearch*) data;
+    PSPDFDocument *pspdf_document = search->document;
+    int n_pages;
+    GList *matches;
+    PopplerPage *page;
+
+    page = poppler_document_get_page (search->document->document,
+            search->search_page);
+
+    ev_document_doc_mutex_lock ();
+        matches = poppler_page_find_text (page, search->text);
+    ev_document_doc_mutex_unlock ();
+
+    g_object_unref (page);
+
+    search->pages[search->search_page] = matches;
+    ev_document_find_changed (EV_DOCUMENT_FIND (pspdf_document),
+            search->search_page);
+
+    n_pages = pspdf_document_get_n_pages (EV_DOCUMENT (search->document));
+    search->search_page += 1;
+    if (search->search_page == n_pages) {
+        /* wrap around */
+        search->search_page = 0;
+    }
+
+    if (search->search_page != search->start_page) {
+        return TRUE;
+    }
+
+    /* We're done. */
+    search->idle = 0; /* will return FALSE to remove */
+    return FALSE;
+}
+
+
+static PSPDFDocumentSearch *
+pspdf_document_search_new (PSPDFDocument *pspdf_document,
+			 int          start_page,
+			 const char  *text)
+{
+    PSPDFDocumentSearch *search;
+    int n_pages;
+    int i;
+
+    n_pages = pspdf_document_get_n_pages (EV_DOCUMENT (pspdf_document));
+
+    search = g_new0 (PSPDFDocumentSearch, 1);
+
+    search->text = g_strdup (text);
+    search->pages = g_new0 (GList *, n_pages);
+    search->document = pspdf_document;
+
+    /* We add at low priority so the progress bar repaints */
+    search->idle = g_idle_add_full (G_PRIORITY_LOW,
+            pspdf_document_search_idle_callback,
+            search,
+            NULL);
+
+    search->start_page = start_page;
+    search->search_page = start_page;
+
+    return search;
+}
+
+static void
+pspdf_document_find_begin (EvDocumentFind   *document,
+			 int               page,
+                         const char       *search_string,
+                         gboolean          case_sensitive)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document);
+
+    /* FIXME handle case_sensitive (right now XPDF
+     * code is always case insensitive for ASCII
+     * and case sensitive for all other languaages)
+     */
+
+    if (pspdf_document->search &&
+            strcmp (search_string, pspdf_document->search->text) == 0)
+        return;
+
+    if (pspdf_document->search)
+        pspdf_document_search_free (pspdf_document->search);
+
+    pspdf_document->search = pspdf_document_search_new (pspdf_document,
+            page,
+            search_string);
+}
+
+static int
+pspdf_document_find_get_n_results (EvDocumentFind *document_find, int page)
+{
+    PSPDFDocumentSearch *search = PSPDF_DOCUMENT (document_find)->search;
+
+    if (search) {
+        return g_list_length (search->pages[page]);
+    } else {
+        return 0;
+    }
+}
+
+static gboolean
+pspdf_document_find_get_result (EvDocumentFind *document_find,
+			      int             page,
+			      int             n_result,
+			      EvRectangle    *rectangle)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document_find);
+    PSPDFDocumentSearch *search = pspdf_document->search;
+    PopplerPage *poppler_page;
+    PopplerRectangle *r;
+    double height;
+
+    if (search == NULL)
+        return FALSE;
+
+    r = (PopplerRectangle *) g_list_nth_data (search->pages[page],
+            n_result);
+    if (r == NULL)
+        return FALSE;
+
+    poppler_page = poppler_document_get_page (pspdf_document->document, page);
+    poppler_page_get_size (poppler_page, NULL, &height);
+    rectangle->x1 = r->x1;
+    rectangle->y1 = height - r->y2;
+    rectangle->x2 = r->x2;
+    rectangle->y2 = height - r->y1;
+    g_object_unref (poppler_page);
+
+    return TRUE;
+}
+
+static int
+pspdf_document_find_page_has_results (EvDocumentFind *document_find,
+            int page)
+{
+	PSPDFDocumentSearch *search = PSPDF_DOCUMENT (document_find)->search;
+
+	return search && search->pages[page] != NULL;
+}
+
+static double
+pspdf_document_find_get_progress (EvDocumentFind *document_find)
+{
+    PSPDFDocumentSearch *search;
+    int n_pages, pages_done;
+
+    search = PSPDF_DOCUMENT (document_find)->search;
+
+    if (search == NULL) {
+            return 0;
+    }
+
+    n_pages = pspdf_document_get_n_pages (EV_DOCUMENT (document_find));
+    if (search->search_page > search->start_page) {
+        pages_done = search->search_page - search->start_page + 1;
+    } else if (search->search_page == search->start_page) {
+        pages_done = n_pages;
+    } else {
+        pages_done = n_pages - search->start_page + search->search_page;
+    }
+
+    return pages_done / (double) n_pages;
+}
+
+static void
+pspdf_document_find_cancel (EvDocumentFind *document)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document);
+
+    if (pspdf_document->search) {
+        pspdf_document_search_free (pspdf_document->search);
+        pspdf_document->search = NULL;
+    }
+}
+
+static void
+pspdf_document_find_iface_init (EvDocumentFindIface *iface)
+{
+    iface->begin = pspdf_document_find_begin;
+    iface->get_n_results = pspdf_document_find_get_n_results;
+    iface->get_result = pspdf_document_find_get_result;
+    iface->page_has_results = pspdf_document_find_page_has_results;
+    iface->get_progress = pspdf_document_find_get_progress;
+    iface->cancel = pspdf_document_find_cancel;
+}
+
+/* EvDocumentFonts Interface Implementation*/
+
+static gdouble
+pspdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document_fonts);
+    int n_pages;
+
+    n_pages = pspdf_document_get_n_pages (EV_DOCUMENT (pspdf_document));
+
+    return (double)pspdf_document->fonts_scanned_pages / (double)n_pages;
+}
+
+static gboolean
+pspdf_document_fonts_scan (EvDocumentFonts *document_fonts,
+			 int              n_pages)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document_fonts);
+    gboolean result;
+
+    g_return_val_if_fail (PSPDF_IS_DOCUMENT (document_fonts), FALSE);
+
+    if (pspdf_document->font_info == NULL) { 
+        pspdf_document->font_info = poppler_font_info_new (pspdf_document->document);
+    }
+
+    if (pspdf_document->fonts_iter) {
+        poppler_fonts_iter_free (pspdf_document->fonts_iter);
+    }
+
+    pspdf_document->fonts_scanned_pages += n_pages;
+
+    result = poppler_font_info_scan (pspdf_document->font_info, n_pages,
+            &pspdf_document->fonts_iter);
+
+    if (!result) {
+        pspdf_document->fonts_scanned_pages = 0;
+        poppler_font_info_free (pspdf_document->font_info);
+        pspdf_document->font_info = NULL;	
+    }
+
+    return result;
+}
+
+static const char *
+font_type_to_string (PopplerFontType type)
+{
+    switch (type) {
+        case POPPLER_FONT_TYPE_TYPE1:
+            return _("Type 1");
+        case POPPLER_FONT_TYPE_TYPE1C:
+            return _("Type 1C");
+        case POPPLER_FONT_TYPE_TYPE3:
+            return _("Type 3");
+        case POPPLER_FONT_TYPE_TRUETYPE:
+            return _("TrueType");
+        case POPPLER_FONT_TYPE_CID_TYPE0:
+            return _("Type 1 (CID)");
+        case POPPLER_FONT_TYPE_CID_TYPE0C:
+            return _("Type 1C (CID)");
+        case POPPLER_FONT_TYPE_CID_TYPE2:
+            return _("TrueType (CID)");
+        default:
+            return _("Unknown font type");
+    }
+}
+
+static void
+pspdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
+			       GtkTreeModel    *model)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT (document_fonts);
+    PopplerFontsIter *iter = pspdf_document->fonts_iter;
+
+    g_return_if_fail (PSPDF_IS_DOCUMENT (document_fonts));
+
+    if (!iter)
+        return;
+
+    do {
+        GtkTreeIter list_iter;
+        const char *name;
+        const char *type;
+        const char *embedded;
+        char *details;
+
+        name = poppler_fonts_iter_get_name (iter);
+
+        if (name == NULL) {
+            name = _("No name");
+        }
+
+        type = font_type_to_string (
+            poppler_fonts_iter_get_font_type (iter));
+
+        if (poppler_fonts_iter_is_embedded (iter)) {
+            if (poppler_fonts_iter_is_subset (iter))
+                embedded = _("Embedded subset");
+            else
+                embedded = _("Embedded");
+        } else {
+            embedded = _("Not embedded");
+        }
+
+        details = g_markup_printf_escaped ("%s\n%s", type, embedded);
+
+        gtk_list_store_append (GTK_LIST_STORE (model), &list_iter);
+        gtk_list_store_set (GTK_LIST_STORE (model), &list_iter,
+                EV_DOCUMENT_FONTS_COLUMN_NAME, name,
+                EV_DOCUMENT_FONTS_COLUMN_DETAILS, details,
+                -1);
+
+        g_free (details);
+    } while (poppler_fonts_iter_next (iter));
+}
+
+static void
+pspdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface)
+{
+	iface->fill_model = pspdf_document_fonts_fill_model;
+	iface->scan = pspdf_document_fonts_scan;
+	iface->get_progress = pspdf_document_fonts_get_progress;
+}
+
+// GObject boiler code
+static void
+pspdf_document_dispose (GObject *object)
+{
+    PSPDFDocument *pspdf_document = PSPDF_DOCUMENT(object);
+    
+    /*if (pspdf_document->print_ctx) {
+        pspdf_print_context_free (pspdf_document->print_ctx);
+        pspdf_document->print_ctx = NULL;
+	  }
+
+    if (pspdf_document->search) {
+        pspdf_document_search_free (pspdf_document->search);
+        pspdf_document->search = NULL;
+    }*/
+
+    if (pspdf_document->converter) {
+        g_object_unref (pspdf_document->converter);
+        pspdf_document->converter = NULL;
+    }
+
+    if (pspdf_document->document) {
+        g_object_unref (pspdf_document->document);
+        pspdf_document->document = NULL;
+    }
+
+    if (pspdf_document->font_info) { 
+        poppler_font_info_free (pspdf_document->font_info);
+    }
+
+    if (pspdf_document->fonts_iter) {
+        poppler_fonts_iter_free (pspdf_document->fonts_iter);
+    }
+
+    if (pspdf_document->uri) {
+        g_free(pspdf_document->uri);
+        pspdf_document->uri = NULL;
+    }
+
+    G_OBJECT_CLASS (pspdf_document_parent_class)->dispose (object);
+}
+
+static void
+pspdf_document_class_init (PSPDFDocumentClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+    gobject_class->dispose = pspdf_document_dispose;
+}
+
+
+static void
+pspdf_document_init (PSPDFDocument *pspdf_document)
+{
+    pspdf_document->uri = NULL;
+    pspdf_document->document = NULL;
+    pspdf_document->converter = NULL;
+}

=== added file 'backend/pspdf/pspdf-document.h'
--- backend/pspdf/pspdf-document.h	1970-01-01 00:00:00 +0000
+++ backend/pspdf/pspdf-document.h	2007-04-02 10:28:10 +0000
@@ -0,0 +1,41 @@
+/* pdfdocument.h: Implementation of EvDocument for PS
+ *
+ * Copyright (C) 2007 Ali Sabil <ali.sabil@gmail.com>
+ * Copyright (C) 2004, Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PSPDF_DOCUMENT_H__
+#define __PSPDF_DOCUMENT_H__
+
+#include <glib-object.h>
+
+#include "ev-document.h"
+
+G_BEGIN_DECLS
+
+#define PSPDF_TYPE_DOCUMENT             (pspdf_document_get_type ())
+#define PSPDF_DOCUMENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPDF_TYPE_DOCUMENT, PSPDFDocument))
+#define PSPDF_IS_DOCUMENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPDF_TYPE_DOCUMENT))
+
+typedef struct _PSPDFDocument PSPDFDocument;
+
+PSPDFDocument   *pspdf_document_new     (void);
+GType           pspdf_document_get_type (void) G_GNUC_CONST;
+     
+G_END_DECLS
+
+#endif /* __PSPDF_DOCUMENT_H__ */

=== modified file 'backend/Makefile.am'
--- backend/Makefile.am	2007-03-30 03:30:10 +0000
+++ backend/Makefile.am	2007-04-11 05:18:13 +0000
@@ -6,10 +6,16 @@
 SUBDIRS += pdf
 endif
 
-if ENABLE_PS 
+if ENABLE_PS
+if WITH_PS_BACKEND
 SUBDIRS += ps
 endif
 
+if WITH_PSPDF_BACKEND
+SUBDIRS += pspdf
+endif
+endif
+
 if ENABLE_PIXBUF
 SUBDIRS += pixbuf    
 endif

=== modified file 'configure.ac'
--- configure.ac	2007-03-30 03:30:10 +0000
+++ configure.ac	2007-04-11 05:37:53 +0000
@@ -228,16 +228,26 @@
 dnl ================== end of pdf checks ============================================
 
 dnl ================== ggv checks ===================================================
-AC_ARG_ENABLE(ps,
-  	[AC_HELP_STRING([--disable-ps], [Compile without PostScript backend])],enable_ps=$enableval,enable_ps="yes")
-
-if test x$enable_ps = xyes; then
- 	AC_DEFINE([ENABLE_PS], [1], [Enable support for PostScript files.])
-fi 
-
-AM_CONDITIONAL(ENABLE_PS, test x$enable_ps = xyes)
-
-if test x$enable_ps = xyes; then
+AC_ARG_WITH(postscript,
+            [AC_HELP_STRING([--with-postscript=no/ps/pspdf], [Compile with PostScript backend [default=ps]])],
+            enable_postscript=$withval,
+            enable_postscript="ps")
+
+if test "x$enable_postscript" = "xps"; then
+    AC_DEFINE([WITH_PS_BACKEND],[1],[Use the PS backend for PostScript support.])
+    AC_DEFINE([ENABLE_PS], [1], [Enable support for PostScript files.])
+fi
+
+if test "x$enable_postscript" = "xpspdf"; then   
+    AC_DEFINE([WITH_PSPDF_BACKEND],[1],[Use the PSPDF backend for PostScript support.])
+    AC_DEFINE([ENABLE_PS], [1], [Enable support for PostScript files.])
+fi
+   
+AM_CONDITIONAL(WITH_PS_BACKEND, test x$enable_postscript = xps)
+AM_CONDITIONAL(WITH_PSPDF_BACKEND, test x$enable_postscript = xpspdf)
+AM_CONDITIONAL(ENABLE_PS, test ! x$enable_postscript = xno)
+
+if test ! x$enable_postscript = xno; then
 
 dnl check for GS version
 AC_MSG_CHECKING(for Ghostscript version...)
@@ -254,6 +264,12 @@
 AC_DEFINE_UNQUOTED(ALPHA_PARAMS, "$AA_PARMS", [Anti-aliasing parameters for Ghostscript.])
 AC_MSG_RESULT(Antialiasing parameters for Ghostscript: $AA_PARMS)
 
+AC_ARG_WITH(gs-ps2pdf-params,
+            [AC_HELP_STRING([--with-gs-ps2pdf-params], [Define Ghostscript ps to pdf parameters])],PS2PDF_PARMS=$withval,
+	    PS2PDF_PARMS="-sDEVICE=pdfwrite"
+	    )
+AC_DEFINE_UNQUOTED(PS_TO_PDF_PARAMS, "$PS2PDF_PARMS", [Ps to Pdf parameters for Ghostscript.])
+AC_MSG_RESULT(Ps to Pdf parameters for Ghostscript: $PS2PDF_PARMS)
 fi
 dnl ======================== End of ggv checks =================================
 
@@ -384,7 +400,7 @@
 if test "x$enable_pdf" = "xyes" ; then
 	EVINCE_MIME_TYPES="application/pdf;application/x-bzpdf;application/x-gzpdf"
 fi
-if test "x$enable_ps" = "xyes" ; then
+if test ! "x$enable_postscript" = "xno" ; then
 	EVINCE_MIME_TYPES="$EVINCE_MIME_TYPES;application/postscript;application/x-bzpostscript;application/x-gzpostscript;image/x-eps;image/x-bzeps;image/x-gzeps"
 fi
 if test "x$enable_dvi" = "xyes"; then
@@ -417,6 +433,7 @@
 backend/pdf/Makefile
 backend/pixbuf/Makefile
 backend/ps/Makefile
+backend/pspdf/Makefile
 backend/tiff/Makefile
 cut-n-paste/Makefile
 cut-n-paste/recent-files/Makefile
@@ -461,7 +478,7 @@
 	Gtk-Doc Support....:  $enable_gtk_doc
 
 	PDF Backend........:  $enable_pdf
-	PostScript Backend.:  $enable_ps
+	PostScript Backend.:  $enable_postscript
 	TIFF Backend.......:  $enable_tiff
 	DJVU Backend.......:  $enable_djvu
 	DVI Backend........:  $enable_dvi

=== modified file 'libdocument/Makefile.am'
--- libdocument/Makefile.am	2007-03-30 03:30:10 +0000
+++ libdocument/Makefile.am	2007-04-11 05:20:34 +0000
@@ -4,6 +4,7 @@
 	-I$(top_srcdir)/backend/pdf			\
 	-I$(top_srcdir)/backend/pixbuf			\
 	-I$(top_srcdir)/backend/tiff			\
+	-I$(top_srcdir)/backend/pspdf	                \
 	-I$(top_srcdir)/backend/ps	                \
 	-I$(top_srcdir)/backend/djvu			\
 	-I$(top_srcdir)/backend/dvi			\
@@ -67,10 +68,17 @@
 endif
 
 if ENABLE_PS
+if WITH_PS_BACKEND
 libevbackend_la_LIBADD += 			\
 	$(top_builddir)/backend/ps/libpsdocument.la
 endif
 
+if WITH_PSPDF_BACKEND
+libevbackend_la_LIBADD += 			\
+	$(top_builddir)/backend/pspdf/libpspdfdocument.la
+endif
+endif
+
 if ENABLE_PIXBUF
 libevbackend_la_LIBADD += 			\
 	$(top_builddir)/backend/pixbuf/libpixbufdocument.la

=== modified file 'libdocument/ev-document-factory.c'
--- libdocument/ev-document-factory.c	2007-03-30 03:30:10 +0000
+++ libdocument/ev-document-factory.c	2007-04-11 05:28:45 +0000
@@ -29,7 +29,11 @@
 #include "ev-poppler.h"
 #endif
 #ifdef ENABLE_PS
-#include "ps-document.h"
+#   ifdef WITH_PS_BACKEND
+#       include "ps-document.h"
+#   elif defined(WITH_PSPDF_BACKEND)
+#       include "pspdf-document.h"
+#   endif
 #endif
 #ifdef ENABLE_TIFF
 #include "tiff-document.h"
@@ -78,12 +82,21 @@
 
 #ifdef ENABLE_PS
 	/* Postscript: */
+#   ifdef WITH_PS_BACKEND
 	{"application/postscript",     EV_COMPRESSION_NONE,  EV_BACKEND_PS,   ps_document_get_type},
 	{"application/x-bzpostscript", EV_COMPRESSION_BZIP2, EV_BACKEND_PS,   ps_document_get_type},
 	{"application/x-gzpostscript", EV_COMPRESSION_GZIP,  EV_BACKEND_PS,   ps_document_get_type},
 	{"image/x-eps",                EV_COMPRESSION_NONE,  EV_BACKEND_PS,   ps_document_get_type},
 	{"image/x-bzeps",              EV_COMPRESSION_BZIP2, EV_BACKEND_PS,   ps_document_get_type},
 	{"image/x-gzeps",              EV_COMPRESSION_GZIP,  EV_BACKEND_PS,   ps_document_get_type},
+#   elif defined(WITH_PSPDF_BACKEND)
+	{"application/postscript",     EV_COMPRESSION_NONE,  EV_BACKEND_PS,   pspdf_document_get_type},
+	{"application/x-bzpostscript", EV_COMPRESSION_BZIP2, EV_BACKEND_PS,   pspdf_document_get_type},
+	{"application/x-gzpostscript", EV_COMPRESSION_GZIP,  EV_BACKEND_PS,   pspdf_document_get_type},
+	{"image/x-eps",                EV_COMPRESSION_NONE,  EV_BACKEND_PS,   pspdf_document_get_type},
+	{"image/x-bzeps",              EV_COMPRESSION_BZIP2, EV_BACKEND_PS,   pspdf_document_get_type},
+	{"image/x-gzeps",              EV_COMPRESSION_GZIP,  EV_BACKEND_PS,   pspdf_document_get_type},
+#   endif
 #endif
 
 #ifdef ENABLE_TIFF

