]> www.fi.muni.cz Git - evince.git/blob - backend/pdf/ev-poppler.cc
Remove #ifdef HAVE_FORMS, so that forms support works again.
[evince.git] / backend / pdf / ev-poppler.cc
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* pdfdocument.h: Implementation of EvDocument for PDF
3  * Copyright (C) 2004, Red Hat, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <math.h>
23 #include <string.h>
24 #include <gtk/gtk.h>
25 #include <poppler.h>
26 #include <poppler-document.h>
27 #include <poppler-page.h>
28 #ifdef HAVE_CAIRO_PDF
29 #include <cairo-pdf.h>
30 #endif
31 #ifdef HAVE_CAIRO_PS
32 #include <cairo-ps.h>
33 #endif
34 #include <glib/gi18n.h>
35
36 #include "ev-poppler.h"
37 #include "ev-file-exporter.h"
38 #include "ev-document-find.h"
39 #include "ev-document-misc.h"
40 #include "ev-document-links.h"
41 #include "ev-document-images.h"
42 #include "ev-document-fonts.h"
43 #include "ev-document-security.h"
44 #include "ev-document-thumbnails.h"
45 #include "ev-document-transition.h"
46 #include "ev-document-forms.h"
47 #include "ev-selection.h"
48 #include "ev-attachment.h"
49 #include "ev-image.h"
50
51 #if defined (HAVE_CAIRO_PDF) || defined (HAVE_CAIRO_PS)
52 #define HAVE_CAIRO_PRINT
53 #endif
54
55 typedef struct {
56         PdfDocument *document;
57         char *text;
58         GList **pages;
59         guint idle;
60         int start_page;
61         int search_page;
62 } PdfDocumentSearch;
63
64 typedef struct {
65         EvFileExporterFormat format;
66
67         /* Pages per sheet */
68         gint pages_per_sheet;
69         gint pages_printed;
70         gint pages_x;
71         gint pages_y;
72         gdouble paper_width;
73         gdouble paper_height;
74         
75 #ifdef HAVE_CAIRO_PRINT
76         cairo_t *cr;
77 #else
78         PopplerPSFile *ps_file;
79 #endif
80 } PdfPrintContext;
81
82 struct _PdfDocumentClass
83 {
84         GObjectClass parent_class;
85 };
86
87 struct _PdfDocument
88 {
89         GObject parent_instance;
90
91         PopplerDocument *document;
92         gchar *password;
93
94         PopplerFontInfo *font_info;
95         PopplerFontsIter *fonts_iter;
96         int fonts_scanned_pages;
97
98         PdfDocumentSearch *search;
99         PdfPrintContext *print_ctx;
100 };
101
102 static void pdf_document_document_iface_init            (EvDocumentIface           *iface);
103 static void pdf_document_security_iface_init            (EvDocumentSecurityIface   *iface);
104 static void pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
105 static void pdf_document_document_links_iface_init      (EvDocumentLinksIface      *iface);
106 static void pdf_document_document_images_iface_init     (EvDocumentImagesIface     *iface);
107 static void pdf_document_document_forms_iface_init      (EvDocumentFormsIface      *iface);
108 static void pdf_document_document_fonts_iface_init      (EvDocumentFontsIface      *iface);
109 static void pdf_document_find_iface_init                (EvDocumentFindIface       *iface);
110 static void pdf_document_file_exporter_iface_init       (EvFileExporterIface       *iface);
111 static void pdf_selection_iface_init                    (EvSelectionIface          *iface);
112 static void pdf_document_page_transition_iface_init     (EvDocumentTransitionIface *iface);
113 static void pdf_document_thumbnails_get_dimensions      (EvDocumentThumbnails      *document_thumbnails,
114                                                          EvRenderContext           *rc,
115                                                          gint                      *width,
116                                                          gint                      *height);
117 static int  pdf_document_get_n_pages                    (EvDocument                *document);
118
119 static EvLinkDest *ev_link_dest_from_dest   (PdfDocument       *pdf_document,
120                                              PopplerDest       *dest);
121 static EvLink     *ev_link_from_action      (PdfDocument       *pdf_document,
122                                              PopplerAction     *action);
123 static void        pdf_document_search_free (PdfDocumentSearch *search);
124 static void        pdf_print_context_free   (PdfPrintContext   *ctx);
125
126 G_DEFINE_TYPE_WITH_CODE (PdfDocument, pdf_document, G_TYPE_OBJECT,
127                          {
128                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT,
129                                                         pdf_document_document_iface_init);
130                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_SECURITY,
131                                                         pdf_document_security_iface_init);
132                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
133                                                         pdf_document_document_thumbnails_iface_init);
134                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_LINKS,
135                                                         pdf_document_document_links_iface_init);
136                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_IMAGES,
137                                                         pdf_document_document_images_iface_init);
138                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FORMS,
139                                                         pdf_document_document_forms_iface_init);
140                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FONTS,
141                                                         pdf_document_document_fonts_iface_init);
142                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_FIND,
143                                                         pdf_document_find_iface_init);
144                                  G_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
145                                                         pdf_document_file_exporter_iface_init);
146                                  G_IMPLEMENT_INTERFACE (EV_TYPE_SELECTION,
147                                                         pdf_selection_iface_init);
148                                  G_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_TRANSITION,
149                                                         pdf_document_page_transition_iface_init);
150                          });
151
152 static void
153 set_rc_data (PdfDocument     *pdf_document,
154              EvRenderContext *rc)
155 {
156         if (rc->data == NULL) {
157                 rc->data = poppler_document_get_page (pdf_document->document,
158                                                       rc->page);
159                 rc->destroy = g_object_unref;
160         } else {
161                 g_assert (rc->page == poppler_page_get_index (POPPLER_PAGE (rc->data)));
162         }
163 }
164
165 static void
166 pdf_document_search_free (PdfDocumentSearch   *search)
167 {
168         PdfDocument *pdf_document = search->document;
169         int n_pages;
170         int i;
171
172         if (search->idle != 0)
173                 g_source_remove (search->idle);
174
175         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
176         for (i = 0; i < n_pages; i++) {
177                 g_list_foreach (search->pages[i], (GFunc) g_free, NULL);
178                 g_list_free (search->pages[i]);
179         }
180         g_free (search->pages);
181         
182         g_free (search->text);
183         g_free (search);
184 }
185
186 static void
187 pdf_document_dispose (GObject *object)
188 {
189         PdfDocument *pdf_document = PDF_DOCUMENT(object);
190
191         if (pdf_document->print_ctx) {
192                 pdf_print_context_free (pdf_document->print_ctx);
193                 pdf_document->print_ctx = NULL;
194         }
195         
196         if (pdf_document->search) {
197                 pdf_document_search_free (pdf_document->search);
198                 pdf_document->search = NULL;
199         }
200
201         if (pdf_document->document) {
202                 g_object_unref (pdf_document->document);
203         }
204
205         if (pdf_document->font_info) { 
206                 poppler_font_info_free (pdf_document->font_info);
207         }
208
209         if (pdf_document->fonts_iter) {
210                 poppler_fonts_iter_free (pdf_document->fonts_iter);
211         }
212
213         G_OBJECT_CLASS (pdf_document_parent_class)->dispose (object);
214 }
215
216 static void
217 pdf_document_class_init (PdfDocumentClass *klass)
218 {
219         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
220
221         g_object_class->dispose = pdf_document_dispose;
222 }
223
224 static void
225 pdf_document_init (PdfDocument *pdf_document)
226 {
227         pdf_document->password = NULL;
228 }
229
230 static void
231 convert_error (GError  *poppler_error,
232                GError **error)
233 {
234         if (poppler_error == NULL)
235                 return;
236
237         if (poppler_error->domain == POPPLER_ERROR) {
238                 /* convert poppler errors into EvDocument errors */
239                 gint code = EV_DOCUMENT_ERROR_INVALID;
240                 if (poppler_error->code == POPPLER_ERROR_INVALID)
241                         code = EV_DOCUMENT_ERROR_INVALID;
242                 else if (poppler_error->code == POPPLER_ERROR_ENCRYPTED)
243                         code = EV_DOCUMENT_ERROR_ENCRYPTED;
244                         
245
246                 g_set_error (error,
247                              EV_DOCUMENT_ERROR,
248                              code,
249                              poppler_error->message,
250                              NULL);
251         } else {
252                 g_propagate_error (error, poppler_error);
253         }
254 }
255
256
257 /* EvDocument */
258 static gboolean
259 pdf_document_save (EvDocument  *document,
260                    const char  *uri,
261                    GError     **error)
262 {
263         gboolean retval;
264         GError *poppler_error = NULL;
265
266         retval = poppler_document_save (PDF_DOCUMENT (document)->document,
267                                         uri,
268                                         &poppler_error);
269         if (! retval)
270                 convert_error (poppler_error, error);
271
272         return retval;
273 }
274
275 static gboolean
276 pdf_document_load (EvDocument   *document,
277                    const char   *uri,
278                    GError      **error)
279 {
280         GError *poppler_error = NULL;
281         PdfDocument *pdf_document = PDF_DOCUMENT (document);
282
283         pdf_document->document =
284                 poppler_document_new_from_file (uri, pdf_document->password, &poppler_error);
285
286         if (pdf_document->document == NULL) {
287                 convert_error (poppler_error, error);
288                 return FALSE;
289         }
290
291         return TRUE;
292 }
293
294 static int
295 pdf_document_get_n_pages (EvDocument *document)
296 {
297         return poppler_document_get_n_pages (PDF_DOCUMENT (document)->document);
298 }
299
300 static void
301 pdf_document_get_page_size (EvDocument   *document,
302                             int           page,
303                             double       *width,
304                             double       *height)
305 {
306         PdfDocument *pdf_document = PDF_DOCUMENT (document);
307         PopplerPage *poppler_page;
308
309         poppler_page = poppler_document_get_page (pdf_document->document, page);
310         poppler_page_get_size (poppler_page, width, height);
311         g_object_unref (poppler_page);
312 }
313
314 static char *
315 pdf_document_get_page_label (EvDocument *document,
316                              int         page)
317 {
318         PopplerPage *poppler_page;
319         char *label = NULL;
320
321         poppler_page = poppler_document_get_page (PDF_DOCUMENT (document)->document,
322                                                   page);
323
324         g_object_get (G_OBJECT (poppler_page),
325                       "label", &label,
326                       NULL);
327         g_object_unref (poppler_page);
328
329         return label;
330 }
331
332 static gboolean
333 pdf_document_has_attachments (EvDocument *document)
334 {
335         PdfDocument *pdf_document;
336
337         pdf_document = PDF_DOCUMENT (document);
338
339         return poppler_document_has_attachments (pdf_document->document);
340 }
341
342 struct SaveToBufferData {
343         gchar *buffer;
344         gsize len, max;
345 };
346
347 static gboolean
348 attachment_save_to_buffer_callback (const gchar  *buf,
349                                     gsize         count,
350                                     gpointer      user_data,
351                                     GError      **error)
352 {
353         struct SaveToBufferData *sdata = (SaveToBufferData *)user_data;
354         gchar *new_buffer;
355         gsize new_max;
356
357         if (sdata->len + count > sdata->max) {
358                 new_max = MAX (sdata->max * 2, sdata->len + count);
359                 new_buffer = (gchar *)g_realloc (sdata->buffer, new_max);
360
361                 sdata->buffer = new_buffer;
362                 sdata->max = new_max;
363         }
364         
365         memcpy (sdata->buffer + sdata->len, buf, count);
366         sdata->len += count;
367         
368         return TRUE;
369 }
370
371 static gboolean
372 attachment_save_to_buffer (PopplerAttachment  *attachment,
373                            gchar             **buffer,
374                            gsize              *buffer_size,
375                            GError            **error)
376 {
377         static const gint initial_max = 1024;
378         struct SaveToBufferData sdata;
379
380         *buffer = NULL;
381         *buffer_size = 0;
382
383         sdata.buffer = (gchar *) g_malloc (initial_max);
384         sdata.max = initial_max;
385         sdata.len = 0;
386
387         if (! poppler_attachment_save_to_callback (attachment,
388                                                    attachment_save_to_buffer_callback,
389                                                    &sdata,
390                                                    error)) {
391                 g_free (sdata.buffer);
392                 return FALSE;
393         }
394
395         *buffer = sdata.buffer;
396         *buffer_size = sdata.len;
397         
398         return TRUE;
399 }
400
401 static GList *
402 pdf_document_get_attachments (EvDocument *document)
403 {
404         PdfDocument *pdf_document;
405         GList *attachments;
406         GList *list;
407         GList *retval = NULL;
408
409         pdf_document = PDF_DOCUMENT (document);
410
411         if (!pdf_document_has_attachments (document))
412                 return NULL;
413
414         attachments = poppler_document_get_attachments (pdf_document->document);
415         
416         for (list = attachments; list; list = list->next) {
417                 PopplerAttachment *attachment;
418                 EvAttachment *ev_attachment;
419                 gchar *data = NULL;
420                 gsize size;
421                 GError *error = NULL;
422
423                 attachment = (PopplerAttachment *) list->data;
424
425                 if (attachment_save_to_buffer (attachment, &data, &size, &error)) {
426                         ev_attachment = ev_attachment_new (attachment->name,
427                                                            attachment->description,
428                                                            attachment->mtime,
429                                                            attachment->ctime,
430                                                            size, data);
431                         
432                         retval = g_list_prepend (retval, ev_attachment);
433                 } else {
434                         if (error) {
435                                 g_warning ("%s", error->message);
436                                 g_error_free (error);
437
438                                 g_free (data);
439                         }
440                 }
441
442                 g_object_unref (attachment);
443         }
444
445         return g_list_reverse (retval);
446 }
447
448 static cairo_surface_t *
449 pdf_document_render (EvDocument      *document,
450                      EvRenderContext *rc)
451 {
452         PdfDocument *pdf_document;
453         cairo_surface_t *surface;
454         double width_points, height_points;
455         gint width, height;
456
457         pdf_document = PDF_DOCUMENT (document);
458
459         set_rc_data (pdf_document, rc);
460
461         poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
462
463         if (rc->rotation == 90 || rc->rotation == 270) {
464                 width = (int) ((height_points * rc->scale) + 0.5);
465                 height = (int) ((width_points * rc->scale) + 0.5);
466         } else {
467                 width = (int) ((width_points * rc->scale) + 0.5);
468                 height = (int) ((height_points * rc->scale) + 0.5);
469         }
470
471 #ifdef HAVE_POPPLER_PAGE_RENDER
472         cairo_t *cr;
473         
474         surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
475                                               width, height);
476         memset (cairo_image_surface_get_data (surface), 0xff,
477                 cairo_image_surface_get_height (surface) *
478                 cairo_image_surface_get_stride (surface));
479         
480         cr = cairo_create (surface);
481         switch (rc->rotation) {
482                 case 90:
483                         cairo_translate (cr, width, 0);
484                         break;
485                 case 180:
486                         cairo_translate (cr, width, height);
487                         break;
488                 case 270:
489                         cairo_translate (cr, 0, height);
490                         break;
491                 default:
492                         cairo_translate (cr, 0, 0);
493         }
494         cairo_scale (cr, rc->scale, rc->scale);
495         cairo_rotate (cr, rc->rotation * G_PI / 180.0);
496         poppler_page_render (POPPLER_PAGE (rc->data), cr);
497         cairo_destroy (cr);
498 #else /* HAVE_POPPLER_PAGE_RENDER */
499         GdkPixbuf *pixbuf;
500         
501         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
502                                  FALSE, 8,
503                                  width, height);
504
505         poppler_page_render_to_pixbuf (POPPLER_PAGE (rc->data),
506                                        0, 0,
507                                        width, height,
508                                        rc->scale,
509                                        rc->rotation,
510                                        pixbuf);
511         surface = ev_document_misc_surface_from_pixbuf (pixbuf);
512         g_object_unref (pixbuf);
513 #endif /* HAVE_POPPLER_PAGE_RENDER */
514
515         return surface;
516 }
517
518 /* EvDocumentSecurity */
519
520 static gboolean
521 pdf_document_has_document_security (EvDocumentSecurity *document_security)
522 {
523         /* FIXME: do we really need to have this? */
524         return FALSE;
525 }
526
527 static void
528 pdf_document_set_password (EvDocumentSecurity *document_security,
529                            const char         *password)
530 {
531         PdfDocument *document = PDF_DOCUMENT (document_security);
532
533         if (document->password)
534                 g_free (document->password);
535
536         document->password = g_strdup (password);
537 }
538
539 static EvDocumentInfo *
540 pdf_document_get_info (EvDocument *document)
541 {
542         EvDocumentInfo *info;
543         PopplerPageLayout layout;
544         PopplerPageMode mode;
545         PopplerViewerPreferences view_prefs;
546         PopplerPermissions permissions;
547
548         info = g_new0 (EvDocumentInfo, 1);
549
550         info->fields_mask = EV_DOCUMENT_INFO_TITLE |
551                             EV_DOCUMENT_INFO_FORMAT |
552                             EV_DOCUMENT_INFO_AUTHOR |
553                             EV_DOCUMENT_INFO_SUBJECT |
554                             EV_DOCUMENT_INFO_KEYWORDS |
555                             EV_DOCUMENT_INFO_LAYOUT |
556                             EV_DOCUMENT_INFO_START_MODE |
557                             EV_DOCUMENT_INFO_PERMISSIONS |
558                             EV_DOCUMENT_INFO_UI_HINTS |
559                             EV_DOCUMENT_INFO_CREATOR |
560                             EV_DOCUMENT_INFO_PRODUCER |
561                             EV_DOCUMENT_INFO_CREATION_DATE |
562                             EV_DOCUMENT_INFO_MOD_DATE |
563                             EV_DOCUMENT_INFO_LINEARIZED |
564                             EV_DOCUMENT_INFO_N_PAGES |
565                             EV_DOCUMENT_INFO_SECURITY | 
566                             EV_DOCUMENT_INFO_PAPER_SIZE;
567
568         g_object_get (PDF_DOCUMENT (document)->document,
569                       "title", &(info->title),
570                       "format", &(info->format),
571                       "author", &(info->author),
572                       "subject", &(info->subject),
573                       "keywords", &(info->keywords),
574                       "page-mode", &mode,
575                       "page-layout", &layout,
576                       "viewer-preferences", &view_prefs,
577                       "permissions", &permissions,
578                       "creator", &(info->creator),
579                       "producer", &(info->producer),
580                       "creation-date", &(info->creation_date),
581                       "mod-date", &(info->modified_date),
582                       "linearized", &(info->linearized),
583                       NULL);
584
585         pdf_document_get_page_size(document, 0,
586                                    &(info->paper_width),
587                                    &(info->paper_height));
588
589         // Convert to mm.
590         info->paper_width = info->paper_width / 72.0f * 25.4f;
591         info->paper_height = info->paper_height / 72.0f * 25.4f;
592
593         switch (layout) {
594                 case POPPLER_PAGE_LAYOUT_SINGLE_PAGE:
595                         info->layout = EV_DOCUMENT_LAYOUT_SINGLE_PAGE;
596                         break;
597                 case POPPLER_PAGE_LAYOUT_ONE_COLUMN:
598                         info->layout = EV_DOCUMENT_LAYOUT_ONE_COLUMN;
599                         break;
600                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT:
601                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_LEFT;
602                         break;
603                 case POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT:
604                         info->layout = EV_DOCUMENT_LAYOUT_TWO_COLUMN_RIGHT;
605                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT:
606                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_LEFT;
607                         break;
608                 case POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT:
609                         info->layout = EV_DOCUMENT_LAYOUT_TWO_PAGE_RIGHT;
610                         break;
611                 default:
612                         break;
613         }
614
615         switch (mode) {
616                 case POPPLER_PAGE_MODE_NONE:
617                         info->mode = EV_DOCUMENT_MODE_NONE;
618                         break;
619                 case POPPLER_PAGE_MODE_USE_THUMBS:
620                         info->mode = EV_DOCUMENT_MODE_USE_THUMBS;
621                         break;
622                 case POPPLER_PAGE_MODE_USE_OC:
623                         info->mode = EV_DOCUMENT_MODE_USE_OC;
624                         break;
625                 case POPPLER_PAGE_MODE_FULL_SCREEN:
626                         info->mode = EV_DOCUMENT_MODE_FULL_SCREEN;
627                         break;
628                 case POPPLER_PAGE_MODE_USE_ATTACHMENTS:
629                         info->mode = EV_DOCUMENT_MODE_USE_ATTACHMENTS;
630                 default:
631                         break;
632         }
633
634         info->ui_hints = 0;
635         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_TOOLBAR) {
636                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_TOOLBAR;
637         }
638         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_MENUBAR) {
639                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_MENUBAR;
640         }
641         if (view_prefs & POPPLER_VIEWER_PREFERENCES_HIDE_WINDOWUI) {
642                 info->ui_hints |= EV_DOCUMENT_UI_HINT_HIDE_WINDOWUI;
643         }
644         if (view_prefs & POPPLER_VIEWER_PREFERENCES_FIT_WINDOW) {
645                 info->ui_hints |= EV_DOCUMENT_UI_HINT_FIT_WINDOW;
646         }
647         if (view_prefs & POPPLER_VIEWER_PREFERENCES_CENTER_WINDOW) {
648                 info->ui_hints |= EV_DOCUMENT_UI_HINT_CENTER_WINDOW;
649         }
650         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DISPLAY_DOC_TITLE) {
651                 info->ui_hints |= EV_DOCUMENT_UI_HINT_DISPLAY_DOC_TITLE;
652         }
653         if (view_prefs & POPPLER_VIEWER_PREFERENCES_DIRECTION_RTL) {
654                 info->ui_hints |=  EV_DOCUMENT_UI_HINT_DIRECTION_RTL;
655         }
656
657         info->permissions = 0;
658         if (permissions & POPPLER_PERMISSIONS_OK_TO_PRINT) {
659                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT;
660         }
661         if (permissions & POPPLER_PERMISSIONS_OK_TO_MODIFY) {
662                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_MODIFY;
663         }
664         if (permissions & POPPLER_PERMISSIONS_OK_TO_COPY) {
665                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_COPY;
666         }
667         if (permissions & POPPLER_PERMISSIONS_OK_TO_ADD_NOTES) {
668                 info->permissions |= EV_DOCUMENT_PERMISSIONS_OK_TO_ADD_NOTES;
669         }
670
671         info->n_pages = ev_document_get_n_pages (document);
672
673         if (ev_document_security_has_document_security (EV_DOCUMENT_SECURITY (document))) {
674                 /* translators: this is the document security state */
675                 info->security = g_strdup (_("Yes"));
676         } else {
677                 /* translators: this is the document security state */
678                 info->security = g_strdup (_("No"));
679         }
680
681         return info;
682 }
683
684 static void
685 pdf_document_document_iface_init (EvDocumentIface *iface)
686 {
687         iface->save = pdf_document_save;
688         iface->load = pdf_document_load;
689         iface->get_n_pages = pdf_document_get_n_pages;
690         iface->get_page_size = pdf_document_get_page_size;
691         iface->get_page_label = pdf_document_get_page_label;
692         iface->has_attachments = pdf_document_has_attachments;
693         iface->get_attachments = pdf_document_get_attachments;
694         iface->render = pdf_document_render;
695         iface->get_info = pdf_document_get_info;
696 };
697
698 static void
699 pdf_document_security_iface_init (EvDocumentSecurityIface *iface)
700 {
701         iface->has_document_security = pdf_document_has_document_security;
702         iface->set_password = pdf_document_set_password;
703 }
704
705 static gdouble
706 pdf_document_fonts_get_progress (EvDocumentFonts *document_fonts)
707 {
708         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
709         int n_pages;
710
711         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
712
713         return (double)pdf_document->fonts_scanned_pages / (double)n_pages;
714 }
715
716 static gboolean
717 pdf_document_fonts_scan (EvDocumentFonts *document_fonts,
718                          int              n_pages)
719 {
720         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
721         gboolean result;
722
723         g_return_val_if_fail (PDF_IS_DOCUMENT (document_fonts), FALSE);
724
725         if (pdf_document->font_info == NULL) { 
726                 pdf_document->font_info = poppler_font_info_new (pdf_document->document);
727         }
728
729         if (pdf_document->fonts_iter) {
730                 poppler_fonts_iter_free (pdf_document->fonts_iter);
731         }
732
733         pdf_document->fonts_scanned_pages += n_pages;
734
735         result = poppler_font_info_scan (pdf_document->font_info, n_pages,
736                                          &pdf_document->fonts_iter);
737         if (!result) {
738                 pdf_document->fonts_scanned_pages = 0;
739                 poppler_font_info_free (pdf_document->font_info);
740                 pdf_document->font_info = NULL; 
741         }
742
743         return result;
744 }
745
746 static const char *
747 font_type_to_string (PopplerFontType type)
748 {
749         switch (type) {
750                 case POPPLER_FONT_TYPE_TYPE1:
751                         return _("Type 1");
752                 case POPPLER_FONT_TYPE_TYPE1C:
753                         return _("Type 1C");
754                 case POPPLER_FONT_TYPE_TYPE3:
755                         return _("Type 3");
756                 case POPPLER_FONT_TYPE_TRUETYPE:
757                         return _("TrueType");
758                 case POPPLER_FONT_TYPE_CID_TYPE0:
759                         return _("Type 1 (CID)");
760                 case POPPLER_FONT_TYPE_CID_TYPE0C:
761                         return _("Type 1C (CID)");
762                 case POPPLER_FONT_TYPE_CID_TYPE2:
763                         return _("TrueType (CID)");
764                 default:
765                         return _("Unknown font type");
766         }
767 }
768
769 static void
770 pdf_document_fonts_fill_model (EvDocumentFonts *document_fonts,
771                                GtkTreeModel    *model)
772 {
773         PdfDocument *pdf_document = PDF_DOCUMENT (document_fonts);
774         PopplerFontsIter *iter = pdf_document->fonts_iter;
775
776         g_return_if_fail (PDF_IS_DOCUMENT (document_fonts));
777
778         if (!iter)
779                 return;
780
781         do {
782                 GtkTreeIter list_iter;
783                 const char *name;
784                 const char *type;
785                 const char *embedded;
786                 char *details;
787                 
788                 name = poppler_fonts_iter_get_name (iter);
789
790                 if (name == NULL) {
791                         name = _("No name");
792                 }
793
794                 type = font_type_to_string (
795                         poppler_fonts_iter_get_font_type (iter));
796
797                 if (poppler_fonts_iter_is_embedded (iter)) {
798                         if (poppler_fonts_iter_is_subset (iter))
799                                 embedded = _("Embedded subset");
800                         else
801                                 embedded = _("Embedded");
802                 } else {
803                         embedded = _("Not embedded");
804                 }
805
806                 details = g_markup_printf_escaped ("%s\n%s", type, embedded);
807
808                 gtk_list_store_append (GTK_LIST_STORE (model), &list_iter);
809                 gtk_list_store_set (GTK_LIST_STORE (model), &list_iter,
810                                     EV_DOCUMENT_FONTS_COLUMN_NAME, name,
811                                     EV_DOCUMENT_FONTS_COLUMN_DETAILS, details,
812                                     -1);
813
814                 g_free (details);
815         } while (poppler_fonts_iter_next (iter));
816 }
817
818 static void
819 pdf_document_document_fonts_iface_init (EvDocumentFontsIface *iface)
820 {
821         iface->fill_model = pdf_document_fonts_fill_model;
822         iface->scan = pdf_document_fonts_scan;
823         iface->get_progress = pdf_document_fonts_get_progress;
824 }
825
826 static gboolean
827 pdf_document_links_has_document_links (EvDocumentLinks *document_links)
828 {
829         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
830         PopplerIndexIter *iter;
831
832         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), FALSE);
833
834         iter = poppler_index_iter_new (pdf_document->document);
835         if (iter == NULL)
836                 return FALSE;
837         poppler_index_iter_free (iter);
838
839         return TRUE;
840 }
841
842 static EvLinkDest *
843 ev_link_dest_from_dest (PdfDocument *pdf_document,
844                         PopplerDest *dest)
845 {
846         EvLinkDest *ev_dest = NULL;
847         const char *unimplemented_dest = NULL;
848
849         g_assert (dest != NULL);
850
851         switch (dest->type) {
852                 case POPPLER_DEST_XYZ: {
853                         PopplerPage *poppler_page;
854                         double height;
855
856                         poppler_page = poppler_document_get_page (pdf_document->document,
857                                                                   MAX (0, dest->page_num - 1));
858                         poppler_page_get_size (poppler_page, NULL, &height);
859                         ev_dest = ev_link_dest_new_xyz (dest->page_num - 1,
860                                                         dest->left,
861                                                         height - dest->top,
862                                                         dest->zoom);
863                         g_object_unref (poppler_page);
864                 }
865                         break;
866                 case POPPLER_DEST_FIT:
867                         ev_dest = ev_link_dest_new_fit (dest->page_num - 1);
868                         break;
869                 case POPPLER_DEST_FITH: {
870                         PopplerPage *poppler_page;
871                         double height;
872
873                         poppler_page = poppler_document_get_page (pdf_document->document,
874                                                                   MAX (0, dest->page_num - 1));
875                         poppler_page_get_size (poppler_page, NULL, &height);
876                         ev_dest = ev_link_dest_new_fith (dest->page_num - 1,
877                                                          height - dest->top);
878                         g_object_unref (poppler_page);
879                 }
880                         break;
881                 case POPPLER_DEST_FITV:
882                         ev_dest = ev_link_dest_new_fitv (dest->page_num - 1,
883                                                          dest->left);
884                         break;
885                 case POPPLER_DEST_FITR: {
886                         PopplerPage *poppler_page;
887                         double height;
888
889                         poppler_page = poppler_document_get_page (pdf_document->document,
890                                                                   MAX (0, dest->page_num - 1));
891                         poppler_page_get_size (poppler_page, NULL, &height);
892                         ev_dest = ev_link_dest_new_fitr (dest->page_num - 1,
893                                                          dest->left,
894                                                          height - dest->bottom,
895                                                          dest->right,
896                                                          height - dest->top);
897                         g_object_unref (poppler_page);
898                 }
899                         break;
900                 case POPPLER_DEST_FITB:
901                         unimplemented_dest = "POPPLER_DEST_FITB";
902                         break;
903                 case POPPLER_DEST_FITBH:
904                         unimplemented_dest = "POPPLER_DEST_FITBH";
905                         break;
906                 case POPPLER_DEST_FITBV:
907                         unimplemented_dest = "POPPLER_DEST_FITBV";
908                         break;
909                 case POPPLER_DEST_NAMED:
910                         ev_dest = ev_link_dest_new_named (dest->named_dest);
911                         break;
912                 case POPPLER_DEST_UNKNOWN:
913                         unimplemented_dest = "POPPLER_DEST_UNKNOWN";
914                         break;
915         }
916
917         if (unimplemented_dest) {
918                 g_warning ("Unimplemented named action: %s, please post a "
919                            "bug report in Evince bugzilla "
920                            "(http://bugzilla.gnome.org) with a testcase.",
921                            unimplemented_dest);
922         }
923
924         if (!ev_dest)
925                 ev_dest = ev_link_dest_new_page (dest->page_num - 1);
926         
927         return ev_dest;
928 }
929
930 static EvLink *
931 ev_link_from_action (PdfDocument   *pdf_document,
932                      PopplerAction *action)
933 {
934         EvLink       *link = NULL;
935         EvLinkAction *ev_action = NULL;
936         const char   *unimplemented_action = NULL;
937
938         switch (action->type) {
939                 case POPPLER_ACTION_GOTO_DEST: {
940                         EvLinkDest *dest;
941                         
942                         dest = ev_link_dest_from_dest (pdf_document, action->goto_dest.dest);
943                         ev_action = ev_link_action_new_dest (dest);
944                 }
945                         break;
946                 case POPPLER_ACTION_GOTO_REMOTE: {
947                         EvLinkDest *dest;
948                         
949                         dest = ev_link_dest_from_dest (pdf_document, action->goto_remote.dest);
950                         ev_action = ev_link_action_new_remote (dest, 
951                                                                action->goto_remote.file_name);
952                         
953                 }
954                         break;
955                 case POPPLER_ACTION_LAUNCH:
956                         ev_action = ev_link_action_new_launch (action->launch.file_name,
957                                                                action->launch.params);
958                         break;
959                 case POPPLER_ACTION_URI:
960                         ev_action = ev_link_action_new_external_uri (action->uri.uri);
961                         break;
962                 case POPPLER_ACTION_NAMED:
963                         ev_action = ev_link_action_new_named (action->named.named_dest);
964                         break;
965                 case POPPLER_ACTION_MOVIE:
966                         unimplemented_action = "POPPLER_ACTION_MOVIE";
967                         break;
968                 case POPPLER_ACTION_UNKNOWN:
969                         unimplemented_action = "POPPLER_ACTION_UNKNOWN";
970         }
971         
972         if (unimplemented_action) {
973                 g_warning ("Unimplemented action: %s, please post a bug report with a testcase.",
974                            unimplemented_action);
975         }
976         
977         link = ev_link_new (action->any.title, ev_action);
978         
979         return link;    
980 }
981
982 static void
983 build_tree (PdfDocument      *pdf_document,
984             GtkTreeModel     *model,
985             GtkTreeIter      *parent,
986             PopplerIndexIter *iter)
987 {
988         
989         do {
990                 GtkTreeIter tree_iter;
991                 PopplerIndexIter *child;
992                 PopplerAction *action;
993                 EvLink *link = NULL;
994                 gboolean expand;
995                 char *title_markup;
996                 
997                 action = poppler_index_iter_get_action (iter);
998                 expand = poppler_index_iter_is_open (iter);
999
1000                 if (!action)
1001                         continue;
1002
1003                 switch (action->type) {
1004                         case POPPLER_ACTION_GOTO_DEST: {
1005                                 /* For bookmarks, solve named destinations */
1006                                 if (action->goto_dest.dest->type == POPPLER_DEST_NAMED) {
1007                                         PopplerDest *dest;
1008                                         EvLinkDest *ev_dest = NULL;
1009                                         EvLinkAction *ev_action;
1010                                         
1011                                         dest = poppler_document_find_dest (pdf_document->document,
1012                                                                            action->goto_dest.dest->named_dest);
1013                                         if (!dest) {
1014                                                 link = ev_link_from_action (pdf_document, action);
1015                                                 break;
1016                                         }
1017                                         
1018                                         ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1019                                         poppler_dest_free (dest);
1020                                         
1021                                         ev_action = ev_link_action_new_dest (ev_dest);
1022                                         link = ev_link_new (action->any.title, ev_action);
1023                                 } else {
1024                                         link = ev_link_from_action (pdf_document, action);
1025                                 }
1026                         }
1027                                 break;
1028                         default:
1029                                 link = ev_link_from_action (pdf_document, action);
1030                                 break;
1031                 }
1032                 
1033                 if (!link || strlen (ev_link_get_title (link)) <= 0) {
1034                         poppler_action_free (action);
1035                         if (link)
1036                                 g_object_unref (link);
1037                         
1038                         continue;
1039                 }
1040
1041                 gtk_tree_store_append (GTK_TREE_STORE (model), &tree_iter, parent);
1042                 title_markup = g_markup_escape_text (ev_link_get_title (link), -1);
1043                 
1044                 gtk_tree_store_set (GTK_TREE_STORE (model), &tree_iter,
1045                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, title_markup,
1046                                     EV_DOCUMENT_LINKS_COLUMN_LINK, link,
1047                                     EV_DOCUMENT_LINKS_COLUMN_EXPAND, expand,
1048                                     -1);
1049                 
1050                 g_free (title_markup);
1051                 g_object_unref (link);
1052                 
1053                 child = poppler_index_iter_get_child (iter);
1054                 if (child)
1055                         build_tree (pdf_document, model, &tree_iter, child);
1056                 poppler_index_iter_free (child);
1057                 poppler_action_free (action);
1058                 
1059         } while (poppler_index_iter_next (iter));
1060 }
1061
1062 static GtkTreeModel *
1063 pdf_document_links_get_links_model (EvDocumentLinks *document_links)
1064 {
1065         PdfDocument *pdf_document = PDF_DOCUMENT (document_links);
1066         GtkTreeModel *model = NULL;
1067         PopplerIndexIter *iter;
1068         
1069         g_return_val_if_fail (PDF_IS_DOCUMENT (document_links), NULL);
1070
1071         iter = poppler_index_iter_new (pdf_document->document);
1072         /* Create the model if we have items*/
1073         if (iter != NULL) {
1074                 model = (GtkTreeModel *) gtk_tree_store_new (EV_DOCUMENT_LINKS_COLUMN_NUM_COLUMNS,
1075                                                              G_TYPE_STRING,
1076                                                              G_TYPE_OBJECT,
1077                                                              G_TYPE_BOOLEAN,
1078                                                              G_TYPE_STRING);
1079                 build_tree (pdf_document, model, NULL, iter);
1080                 poppler_index_iter_free (iter);
1081         }
1082         
1083         return model;
1084 }
1085
1086 static GList *
1087 pdf_document_links_get_links (EvDocumentLinks *document_links,
1088                               gint             page)
1089 {
1090         PdfDocument *pdf_document;
1091         PopplerPage *poppler_page;
1092         GList *retval = NULL;
1093         GList *mapping_list;
1094         GList *list;
1095         double height;
1096
1097         pdf_document = PDF_DOCUMENT (document_links);
1098         poppler_page = poppler_document_get_page (pdf_document->document,
1099                                                   page);
1100         mapping_list = poppler_page_get_link_mapping (poppler_page);
1101         poppler_page_get_size (poppler_page, NULL, &height);
1102
1103         for (list = mapping_list; list; list = list->next) {
1104                 PopplerLinkMapping *link_mapping;
1105                 EvLinkMapping *ev_link_mapping;
1106
1107                 link_mapping = (PopplerLinkMapping *)list->data;
1108                 ev_link_mapping = g_new (EvLinkMapping, 1);
1109                 ev_link_mapping->link = ev_link_from_action (pdf_document,
1110                                                              link_mapping->action);
1111                 ev_link_mapping->x1 = link_mapping->area.x1;
1112                 ev_link_mapping->x2 = link_mapping->area.x2;
1113                 /* Invert this for X-style coordinates */
1114                 ev_link_mapping->y1 = height - link_mapping->area.y2;
1115                 ev_link_mapping->y2 = height - link_mapping->area.y1;
1116
1117                 retval = g_list_prepend (retval, ev_link_mapping);
1118         }
1119
1120         poppler_page_free_link_mapping (mapping_list);
1121         g_object_unref (poppler_page);
1122
1123         return g_list_reverse (retval);
1124 }
1125
1126 static EvLinkDest *
1127 pdf_document_links_find_link_dest (EvDocumentLinks  *document_links,
1128                                    const gchar      *link_name)
1129 {
1130         PdfDocument *pdf_document;
1131         PopplerDest *dest;
1132         EvLinkDest *ev_dest = NULL;
1133
1134         pdf_document = PDF_DOCUMENT (document_links);
1135         dest = poppler_document_find_dest (pdf_document->document,
1136                                            link_name);
1137         if (dest) {
1138                 ev_dest = ev_link_dest_from_dest (pdf_document, dest);
1139                 poppler_dest_free (dest);
1140         }
1141
1142         return ev_dest;
1143 }
1144
1145 static void
1146 pdf_document_document_links_iface_init (EvDocumentLinksIface *iface)
1147 {
1148         iface->has_document_links = pdf_document_links_has_document_links;
1149         iface->get_links_model = pdf_document_links_get_links_model;
1150         iface->get_links = pdf_document_links_get_links;
1151         iface->find_link_dest = pdf_document_links_find_link_dest;
1152 }
1153
1154 static GList *
1155 pdf_document_images_get_images (EvDocumentImages *document_images,
1156                                 gint              page)
1157 {
1158         GList *retval = NULL;
1159         PdfDocument *pdf_document;
1160         PopplerPage *poppler_page;
1161         GList *mapping_list;
1162         GList *list;
1163
1164         pdf_document = PDF_DOCUMENT (document_images);
1165         poppler_page = poppler_document_get_page (pdf_document->document, page);
1166         mapping_list = poppler_page_get_image_mapping (poppler_page);
1167
1168         for (list = mapping_list; list; list = list->next) {
1169                 PopplerImageMapping *image_mapping;
1170                 EvImageMapping *ev_image_mapping;
1171
1172                 image_mapping = (PopplerImageMapping *)list->data;
1173
1174                 ev_image_mapping = g_new (EvImageMapping, 1);
1175                 
1176                 ev_image_mapping->image = ev_image_new_from_pixbuf (image_mapping->image);
1177                 ev_image_mapping->x1 = image_mapping->area.x1;
1178                 ev_image_mapping->x2 = image_mapping->area.x2;
1179                 ev_image_mapping->y1 = image_mapping->area.y1;
1180                 ev_image_mapping->y2 = image_mapping->area.y2;
1181
1182                 retval = g_list_prepend (retval, ev_image_mapping);
1183         }
1184
1185         poppler_page_free_image_mapping (mapping_list);
1186         g_object_unref (poppler_page);
1187
1188         return retval;
1189 }
1190
1191 static void
1192 pdf_document_document_images_iface_init (EvDocumentImagesIface *iface)
1193 {
1194         iface->get_images = pdf_document_images_get_images;
1195 }
1196
1197 static GdkPixbuf *
1198 make_thumbnail_for_page (PdfDocument     *pdf_document,
1199                          PopplerPage     *poppler_page, 
1200                          EvRenderContext *rc)
1201 {
1202         GdkPixbuf *pixbuf;
1203         int width, height;
1204
1205         pdf_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (pdf_document),
1206                                                 rc, &width, &height);
1207
1208         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
1209                                  width, height);
1210         gdk_pixbuf_fill (pixbuf, 0xffffffff);
1211
1212         ev_document_fc_mutex_lock ();
1213         poppler_page_render_to_pixbuf (poppler_page, 0, 0,
1214                                        width, height,
1215                                        rc->scale, rc->rotation, pixbuf);
1216         ev_document_fc_mutex_unlock ();
1217
1218         return pixbuf;
1219 }
1220
1221 static GdkPixbuf *
1222 pdf_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document_thumbnails,
1223                                        EvRenderContext      *rc, 
1224                                        gboolean              border)
1225 {
1226         PdfDocument *pdf_document;
1227         PopplerPage *poppler_page;
1228         GdkPixbuf *pixbuf;
1229         GdkPixbuf *border_pixbuf;
1230
1231         pdf_document = PDF_DOCUMENT (document_thumbnails);
1232
1233         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1234         g_return_val_if_fail (poppler_page != NULL, NULL);
1235
1236         pixbuf = poppler_page_get_thumbnail (poppler_page);
1237         if (pixbuf) {
1238                 /* Rotate provided thumbnail if needed */
1239                 GdkPixbuf *rotated_pixbuf;
1240
1241                 rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf,
1242                                                            (GdkPixbufRotation) (360 - rc->rotation));
1243                 g_object_unref (pixbuf);
1244                 pixbuf = rotated_pixbuf;
1245         } else {
1246                 /* There is no provided thumbnail.  We need to make one. */
1247                 pixbuf = make_thumbnail_for_page (pdf_document, poppler_page, rc);
1248         }
1249
1250         if (border) {           
1251                 border_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, pixbuf);
1252                 g_object_unref (pixbuf);
1253                 pixbuf = border_pixbuf;
1254         }               
1255
1256         g_object_unref (poppler_page);
1257         
1258         return pixbuf;
1259 }
1260
1261 static void
1262 pdf_document_thumbnails_get_dimensions (EvDocumentThumbnails *document_thumbnails,
1263                                         EvRenderContext      *rc,
1264                                         gint                 *width,
1265                                         gint                 *height)
1266 {
1267         PdfDocument *pdf_document;
1268         PopplerPage *poppler_page;
1269         gint has_thumb;
1270         
1271         pdf_document = PDF_DOCUMENT (document_thumbnails);
1272         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1273
1274         g_return_if_fail (poppler_page != NULL);
1275
1276         has_thumb = poppler_page_get_thumbnail_size (poppler_page, width, height);
1277
1278         if (!has_thumb) {
1279                 double page_width, page_height;
1280
1281                 poppler_page_get_size (poppler_page, &page_width, &page_height);
1282
1283                 *width = (gint) MAX (page_width * rc->scale, 1);
1284                 *height = (gint) MAX (page_height * rc->scale, 1);
1285         }
1286         
1287         if (rc->rotation == 90 || rc->rotation == 270) {
1288                 gint  temp;
1289
1290                 temp = *width;
1291                 *width = *height;
1292                 *height = temp;
1293         }
1294         
1295         g_object_unref (poppler_page);
1296 }
1297
1298 static void
1299 pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
1300 {
1301         iface->get_thumbnail = pdf_document_thumbnails_get_thumbnail;
1302         iface->get_dimensions = pdf_document_thumbnails_get_dimensions;
1303 }
1304
1305
1306 static gboolean
1307 pdf_document_search_idle_callback (void *data)
1308 {
1309         PdfDocumentSearch *search = (PdfDocumentSearch*) data;
1310         PdfDocument *pdf_document = search->document;
1311         int n_pages;
1312         GList *matches;
1313         PopplerPage *page;
1314
1315         page = poppler_document_get_page (search->document->document,
1316                                           search->search_page);
1317
1318         ev_document_doc_mutex_lock ();
1319         matches = poppler_page_find_text (page, search->text);
1320         ev_document_doc_mutex_unlock ();
1321
1322         g_object_unref (page);
1323
1324         search->pages[search->search_page] = matches;
1325         ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
1326                                   search->search_page);
1327
1328         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document));
1329         search->search_page += 1;
1330         if (search->search_page == n_pages) {
1331                 /* wrap around */
1332                 search->search_page = 0;
1333         }
1334
1335         if (search->search_page != search->start_page) {
1336                 return TRUE;
1337         }
1338
1339         /* We're done. */
1340         search->idle = 0; /* will return FALSE to remove */
1341         return FALSE;
1342 }
1343
1344
1345 static PdfDocumentSearch *
1346 pdf_document_search_new (PdfDocument *pdf_document,
1347                          int          start_page,
1348                          const char  *text)
1349 {
1350         PdfDocumentSearch *search;
1351         int n_pages;
1352         int i;
1353
1354         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
1355
1356         search = g_new0 (PdfDocumentSearch, 1);
1357
1358         search->text = g_strdup (text);
1359         search->pages = g_new0 (GList *, n_pages);
1360         search->document = pdf_document;
1361
1362         /* We add at low priority so the progress bar repaints */
1363         search->idle = g_idle_add_full (G_PRIORITY_LOW,
1364                                         pdf_document_search_idle_callback,
1365                                         search,
1366                                         NULL);
1367
1368         search->start_page = start_page;
1369         search->search_page = start_page;
1370
1371         return search;
1372 }
1373
1374 static void
1375 pdf_document_find_begin (EvDocumentFind   *document,
1376                          int               page,
1377                          const char       *search_string,
1378                          gboolean          case_sensitive)
1379 {
1380         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1381
1382         /* FIXME handle case_sensitive (right now XPDF
1383          * code is always case insensitive for ASCII
1384          * and case sensitive for all other languaages)
1385          */
1386
1387         if (pdf_document->search &&
1388             strcmp (search_string, pdf_document->search->text) == 0)
1389                 return;
1390
1391         if (pdf_document->search)
1392                 pdf_document_search_free (pdf_document->search);
1393
1394         pdf_document->search = pdf_document_search_new (pdf_document,
1395                                                         page,
1396                                                         search_string);
1397 }
1398
1399 static int
1400 pdf_document_find_get_n_results (EvDocumentFind *document_find, int page)
1401 {
1402         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1403
1404         if (search) {
1405                 return g_list_length (search->pages[page]);
1406         } else {
1407                 return 0;
1408         }
1409 }
1410
1411 static gboolean
1412 pdf_document_find_get_result (EvDocumentFind *document_find,
1413                               int             page,
1414                               int             n_result,
1415                               EvRectangle    *rectangle)
1416 {
1417         PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
1418         PdfDocumentSearch *search = pdf_document->search;
1419         PopplerPage *poppler_page;
1420         PopplerRectangle *r;
1421         double height;
1422
1423         if (search == NULL)
1424                 return FALSE;
1425
1426         r = (PopplerRectangle *) g_list_nth_data (search->pages[page],
1427                                                   n_result);
1428         if (r == NULL)
1429                 return FALSE;
1430
1431         poppler_page = poppler_document_get_page (pdf_document->document, page);
1432         poppler_page_get_size (poppler_page, NULL, &height);
1433         rectangle->x1 = r->x1;
1434         rectangle->y1 = height - r->y2;
1435         rectangle->x2 = r->x2;
1436         rectangle->y2 = height - r->y1;
1437         g_object_unref (poppler_page);
1438                 
1439         return TRUE;
1440 }
1441
1442 static int
1443 pdf_document_find_page_has_results (EvDocumentFind *document_find,
1444                                     int             page)
1445 {
1446         PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
1447
1448         return search && search->pages[page] != NULL;
1449 }
1450
1451 static double
1452 pdf_document_find_get_progress (EvDocumentFind *document_find)
1453 {
1454         PdfDocumentSearch *search;
1455         int n_pages, pages_done;
1456
1457         search = PDF_DOCUMENT (document_find)->search;
1458
1459         if (search == NULL) {
1460                 return 0;
1461         }
1462
1463         n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find));
1464         if (search->search_page > search->start_page) {
1465                 pages_done = search->search_page - search->start_page + 1;
1466         } else if (search->search_page == search->start_page) {
1467                 pages_done = n_pages;
1468         } else {
1469                 pages_done = n_pages - search->start_page + search->search_page;
1470         }
1471
1472         return pages_done / (double) n_pages;
1473 }
1474
1475 static void
1476 pdf_document_find_cancel (EvDocumentFind *document)
1477 {
1478         PdfDocument *pdf_document = PDF_DOCUMENT (document);
1479
1480         if (pdf_document->search) {
1481                 pdf_document_search_free (pdf_document->search);
1482                 pdf_document->search = NULL;
1483         }
1484 }
1485
1486 static void
1487 pdf_document_find_iface_init (EvDocumentFindIface *iface)
1488 {
1489         iface->begin = pdf_document_find_begin;
1490         iface->get_n_results = pdf_document_find_get_n_results;
1491         iface->get_result = pdf_document_find_get_result;
1492         iface->page_has_results = pdf_document_find_page_has_results;
1493         iface->get_progress = pdf_document_find_get_progress;
1494         iface->cancel = pdf_document_find_cancel;
1495 }
1496
1497 static void
1498 pdf_print_context_free (PdfPrintContext *ctx)
1499 {
1500         if (!ctx)
1501                 return;
1502
1503 #ifdef HAVE_CAIRO_PRINT
1504         if (ctx->cr) {
1505                 cairo_destroy (ctx->cr);
1506                 ctx->cr = NULL;
1507         }
1508 #else
1509         if (ctx->ps_file) {
1510                 poppler_ps_file_free (ctx->ps_file);
1511                 ctx->ps_file = NULL;
1512         }
1513 #endif
1514         g_free (ctx);
1515 }
1516
1517 static void
1518 pdf_document_file_exporter_begin (EvFileExporter        *exporter,
1519                                   EvFileExporterContext *fc)
1520 {
1521         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1522         PdfPrintContext *ctx;
1523         gdouble width, height;
1524 #ifdef HAVE_CAIRO_PRINT
1525         cairo_surface_t *surface = NULL;
1526 #endif
1527         
1528         if (pdf_document->print_ctx)
1529                 pdf_print_context_free (pdf_document->print_ctx);
1530         pdf_document->print_ctx = g_new0 (PdfPrintContext, 1);
1531         ctx = pdf_document->print_ctx;
1532         ctx->format = fc->format;
1533         ctx->pages_per_sheet = fc->pages_per_sheet;
1534
1535         ctx->paper_width = fc->paper_width;
1536         ctx->paper_height = fc->paper_height;
1537         
1538         switch (fc->pages_per_sheet) {
1539                 default:
1540                 case 1:
1541                         ctx->pages_x = 1;
1542                         ctx->pages_y = 1;
1543                         break;
1544                 case 2:
1545                         ctx->pages_x = 1;
1546                         ctx->pages_y = 2;
1547                         break;
1548                 case 4:
1549                         ctx->pages_x = 2;
1550                         ctx->pages_y = 2;
1551                         break;
1552                 case 6:
1553                         ctx->pages_x = 2;
1554                         ctx->pages_y = 3;
1555                         break;
1556                 case 9:
1557                         ctx->pages_x = 3;
1558                         ctx->pages_y = 3;
1559                         break;
1560                 case 16:
1561                         ctx->pages_x = 4;
1562                         ctx->pages_y = 4;
1563                         break;
1564         }
1565
1566         ctx->pages_printed = 0;
1567
1568         switch (fc->format) {
1569                 case EV_FILE_FORMAT_PS:
1570 #ifdef HAVE_CAIRO_PS
1571                         surface = cairo_ps_surface_create (fc->filename, fc->paper_width, fc->paper_height);
1572 #else
1573                         ctx->ps_file = poppler_ps_file_new (pdf_document->document,
1574                                                             fc->filename, fc->first_page,
1575                                                             fc->last_page - fc->first_page + 1);
1576                         poppler_ps_file_set_paper_size (ctx->ps_file, fc->paper_width, fc->paper_height);
1577                         poppler_ps_file_set_duplex (ctx->ps_file, fc->duplex);
1578 #endif /* HAVE_CAIRO_PS */
1579                         break;
1580                 case EV_FILE_FORMAT_PDF:
1581 #ifdef HAVE_CAIRO_PDF
1582                         surface = cairo_pdf_surface_create (fc->filename, fc->paper_width, fc->paper_height);
1583 #endif
1584                         break;
1585                 default:
1586                         g_assert_not_reached ();
1587         }
1588
1589 #ifdef HAVE_CAIRO_PRINT
1590         ctx->cr = cairo_create (surface);
1591         cairo_surface_destroy (surface);
1592 #endif
1593 }
1594
1595 static void
1596 pdf_document_file_exporter_do_page (EvFileExporter  *exporter,
1597                                     EvRenderContext *rc)
1598 {
1599         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1600         PdfPrintContext *ctx = pdf_document->print_ctx;
1601         PopplerPage *poppler_page;
1602 #ifdef HAVE_CAIRO_PRINT
1603         gdouble  page_width, page_height;
1604         gint     x, y;
1605         gboolean rotate, landscape;
1606         gdouble  width, height;
1607         gdouble  pwidth, pheight;
1608         gdouble  xscale, yscale;
1609 #endif
1610
1611         g_return_if_fail (pdf_document->print_ctx != NULL);
1612
1613         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1614         
1615 #ifdef HAVE_CAIRO_PRINT
1616         x = (ctx->pages_printed % ctx->pages_per_sheet) % ctx->pages_x;
1617         y = (ctx->pages_printed % ctx->pages_per_sheet) / ctx->pages_x;
1618         poppler_page_get_size (poppler_page, &page_width, &page_height);
1619
1620         if (page_width > page_height && page_width > ctx->paper_width) {
1621                 rotate = TRUE;
1622         } else {
1623                 rotate = FALSE;
1624         }
1625
1626         landscape = (ctx->paper_width > ctx->paper_height);
1627
1628         /* Use always portrait mode and rotate when necessary */
1629         if (ctx->paper_width > ctx->paper_height) {
1630                 width = ctx->paper_height;
1631                 height = ctx->paper_width;
1632                 rotate = !rotate;
1633
1634                 cairo_ps_surface_set_size (cairo_get_target (ctx->cr),
1635                                            width, height);
1636         } else {
1637                 width = ctx->paper_width;
1638                 height = ctx->paper_height;
1639         }
1640
1641         if (ctx->pages_per_sheet == 2 || ctx->pages_per_sheet == 6) {
1642                 rotate = !rotate;
1643         }       
1644
1645         if (rotate) {
1646                 gint tmp1;
1647                 gdouble tmp2;
1648
1649                 tmp1 = x;
1650                 x = y;
1651                 y = tmp1;
1652
1653                 tmp2 = page_width;
1654                 page_width = page_height;
1655                 page_height = tmp2;
1656
1657         }
1658
1659         pwidth = width / ctx->pages_x;
1660         pheight = height / ctx->pages_y;
1661
1662         if ((page_width > pwidth || page_height > pheight) ||
1663             (page_width < pwidth && page_height < pheight)) {
1664                 xscale = pwidth / page_width;
1665                 yscale = pheight / page_height;
1666                 
1667                 if (yscale < xscale) {
1668                         xscale = yscale;
1669                 } else {
1670                         yscale = xscale;
1671                 }
1672                 
1673         } else {        
1674                 xscale = yscale = 1;
1675         }
1676
1677         /* TODO: center */
1678
1679         cairo_save (ctx->cr);
1680         if (rotate) {
1681                 cairo_matrix_t matrix;
1682                 
1683                 cairo_translate (ctx->cr, width, 0);
1684                 cairo_matrix_init (&matrix,
1685                                    0,  1,
1686                                    -1,  0,
1687                                    0,  0);
1688                 cairo_transform (ctx->cr, &matrix);
1689         }
1690         
1691         cairo_translate (ctx->cr,
1692                          x * (rotate ? pheight : pwidth),
1693                          y * (rotate ? pwidth : pheight));
1694         cairo_scale (ctx->cr, xscale, yscale);
1695         
1696 #ifdef HAVE_POPPLER_PAGE_RENDER
1697         poppler_page_render (poppler_page, ctx->cr);
1698 #endif
1699         ctx->pages_printed++;
1700                         
1701         if (ctx->pages_printed % ctx->pages_per_sheet == 0) {
1702                 cairo_show_page (ctx->cr);
1703         }
1704         cairo_restore (ctx->cr);
1705 #else /* HAVE_CAIRO_PRINT */
1706         if (ctx->format == EV_FILE_FORMAT_PS)
1707                 poppler_page_render_to_ps (poppler_page, ctx->ps_file);
1708 #endif /* HAVE_CAIRO_PRINT */
1709         
1710         g_object_unref (poppler_page);
1711 }
1712
1713 static void
1714 pdf_document_file_exporter_end (EvFileExporter *exporter)
1715 {
1716         PdfDocument *pdf_document = PDF_DOCUMENT (exporter);
1717
1718         pdf_print_context_free (pdf_document->print_ctx);
1719         pdf_document->print_ctx = NULL;
1720 }
1721
1722 static EvFileExporterCapabilities
1723 pdf_document_file_exporter_get_capabilities (EvFileExporter *exporter)
1724 {
1725         return  (EvFileExporterCapabilities) (
1726                 EV_FILE_EXPORTER_CAN_PAGE_SET |
1727                 EV_FILE_EXPORTER_CAN_COPIES |
1728                 EV_FILE_EXPORTER_CAN_COLLATE |
1729                 EV_FILE_EXPORTER_CAN_REVERSE |
1730                 EV_FILE_EXPORTER_CAN_SCALE |
1731 #ifdef HAVE_CAIRO_PRINT
1732 #ifdef HAVE_POPPLER_PAGE_RENDER
1733 #if GTK_CHECK_VERSION (2, 11, 1)
1734                 EV_FILE_EXPORTER_CAN_NUMBER_UP |
1735 #endif
1736 #endif
1737 #endif
1738                 
1739 #ifdef HAVE_CAIRO_PDF
1740 #ifdef HAVE_POPPLER_PAGE_RENDER
1741                 EV_FILE_EXPORTER_CAN_GENERATE_PDF |
1742 #endif
1743 #endif
1744                 EV_FILE_EXPORTER_CAN_GENERATE_PS);
1745 }
1746
1747 static void
1748 pdf_document_file_exporter_iface_init (EvFileExporterIface *iface)
1749 {
1750         iface->begin = pdf_document_file_exporter_begin;
1751         iface->do_page = pdf_document_file_exporter_do_page;
1752         iface->end = pdf_document_file_exporter_end;
1753         iface->get_capabilities = pdf_document_file_exporter_get_capabilities;
1754 }
1755
1756 static void
1757 pdf_selection_render_selection (EvSelection      *selection,
1758                                 EvRenderContext  *rc,
1759                                 cairo_surface_t **surface,
1760                                 EvRectangle      *points,
1761                                 EvRectangle      *old_points,
1762                                 EvSelectionStyle  style,
1763                                 GdkColor         *text,
1764                                 GdkColor         *base)
1765 {
1766         PdfDocument *pdf_document;
1767         double width_points, height_points;
1768         gint width, height;
1769
1770         pdf_document = PDF_DOCUMENT (selection);
1771         set_rc_data (pdf_document, rc);
1772
1773         poppler_page_get_size (POPPLER_PAGE (rc->data),
1774                                &width_points, &height_points);
1775         width = (int) ((width_points * rc->scale) + 0.5);
1776         height = (int) ((height_points * rc->scale) + 0.5);
1777
1778 #ifdef HAVE_POPPLER_PAGE_RENDER
1779         cairo_t *cr;
1780
1781         if (*surface == NULL) {
1782                 *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1783                                                        width, height);
1784                 
1785         }
1786
1787         cr = cairo_create (*surface);
1788         cairo_scale (cr, rc->scale, rc->scale);
1789         cairo_surface_set_device_offset (*surface, 0, 0);
1790         memset (cairo_image_surface_get_data (*surface), 0x00,
1791                 cairo_image_surface_get_height (*surface) *
1792                 cairo_image_surface_get_stride (*surface));
1793         poppler_page_render_selection (POPPLER_PAGE (rc->data),
1794                                        cr,
1795                                        (PopplerRectangle *)points,
1796                                        (PopplerRectangle *)old_points,
1797                                        (PopplerSelectionStyle)style,
1798                                        text,
1799                                        base);
1800         cairo_destroy (cr);
1801 #else /* HAVE_POPPLER_PAGE_RENDER */
1802         GdkPixbuf *pixbuf;
1803         
1804         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
1805                                  TRUE, 8,
1806                                  width, height);
1807
1808         poppler_page_render_selection_to_pixbuf (POPPLER_PAGE (rc->data),
1809                                                  rc->scale, rc->rotation, pixbuf,
1810                                                  (PopplerRectangle *)points,
1811                                                  (PopplerRectangle *)old_points,
1812                                                  (PopplerSelectionStyle)style,
1813                                                  text,
1814                                                  base);
1815         if (*surface)
1816                 cairo_surface_destroy (*surface);
1817         *surface = ev_document_misc_surface_from_pixbuf (pixbuf);
1818         g_object_unref (pixbuf);
1819 #endif /* HAVE_POPPLER_PAGE_RENDER */
1820 }
1821
1822 static gchar *
1823 pdf_selection_get_selected_text (EvSelection     *selection,
1824                                  EvRenderContext *rc,
1825                                  EvSelectionStyle style,
1826                                  EvRectangle     *points)
1827 {
1828         PdfDocument *pdf_document = PDF_DOCUMENT (selection);
1829         PopplerPage *poppler_page;
1830         PopplerRectangle r;
1831         double height;
1832         char *retval;
1833         
1834         poppler_page = poppler_document_get_page (pdf_document->document, rc->page);
1835         g_return_val_if_fail (poppler_page != NULL, NULL);
1836
1837         poppler_page_get_size (poppler_page, NULL, &height);
1838         r.x1 = points->x1;
1839         r.y1 = height - points->y2;
1840         r.x2 = points->x2;
1841         r.y2 = height - points->y1;
1842
1843         retval = poppler_page_get_text (poppler_page,
1844                                         (PopplerSelectionStyle)style,
1845                                         &r);
1846
1847         g_object_unref (poppler_page);
1848
1849         return retval;
1850 }
1851
1852 static GdkRegion *
1853 pdf_selection_get_selection_region (EvSelection     *selection,
1854                                     EvRenderContext *rc,
1855                                     EvSelectionStyle style,
1856                                     EvRectangle     *points)
1857 {
1858         PdfDocument *pdf_document;
1859         GdkRegion *retval;
1860
1861         pdf_document = PDF_DOCUMENT (selection);
1862
1863         set_rc_data (pdf_document, rc);
1864
1865         retval = poppler_page_get_selection_region ((PopplerPage *)rc->data,
1866                                                     rc->scale,
1867                                                     (PopplerSelectionStyle)style,
1868                                                     (PopplerRectangle *) points);
1869         return retval;
1870 }
1871
1872 static GdkRegion *
1873 pdf_selection_get_selection_map (EvSelection     *selection,
1874                                  EvRenderContext *rc)
1875 {
1876         PdfDocument *pdf_document;
1877         PopplerPage *poppler_page;
1878         PopplerRectangle points;
1879         GdkRegion *retval;
1880
1881         pdf_document = PDF_DOCUMENT (selection);
1882         poppler_page = poppler_document_get_page (pdf_document->document,
1883                                                   rc->page);
1884
1885         points.x1 = 0.0;
1886         points.y1 = 0.0;
1887         poppler_page_get_size (poppler_page, &(points.x2), &(points.y2));
1888         retval = poppler_page_get_selection_region (poppler_page, 1.0,
1889                                                     POPPLER_SELECTION_GLYPH,
1890                                                     &points);
1891         g_object_unref (poppler_page);
1892
1893         return retval;
1894 }
1895
1896 static void
1897 pdf_selection_iface_init (EvSelectionIface *iface)
1898 {
1899         iface->render_selection = pdf_selection_render_selection;
1900         iface->get_selected_text = pdf_selection_get_selected_text;
1901         iface->get_selection_region = pdf_selection_get_selection_region;
1902         iface->get_selection_map = pdf_selection_get_selection_map;
1903 }
1904
1905 /* Page Transitions */
1906 static gdouble
1907 pdf_document_get_page_duration (EvDocumentTransition *trans,
1908                                 gint                  page)
1909 {
1910         PdfDocument *pdf_document;
1911         PopplerPage *poppler_page;
1912         gdouble      duration = -1;
1913
1914         pdf_document = PDF_DOCUMENT (trans);
1915         poppler_page = poppler_document_get_page (pdf_document->document, page);
1916         if (!poppler_page)
1917                 return -1;
1918
1919         duration = poppler_page_get_duration (poppler_page);
1920         g_object_unref (poppler_page);
1921
1922         return duration;
1923 }
1924
1925 static void
1926 pdf_document_page_transition_iface_init (EvDocumentTransitionIface *iface)
1927 {
1928         iface->get_page_duration = pdf_document_get_page_duration;
1929 }
1930
1931 PdfDocument *
1932 pdf_document_new (void)
1933 {
1934         return PDF_DOCUMENT (g_object_new (PDF_TYPE_DOCUMENT, NULL));
1935 }
1936
1937 /* Forms */
1938 static void
1939 pdf_document_get_crop_box (EvDocument  *document, 
1940                            int          page, 
1941                            EvRectangle *rect)
1942 {
1943         PdfDocument *pdf_document;
1944         PopplerPage *poppler_page;
1945         PopplerRectangle poppler_rect;
1946
1947         pdf_document = PDF_DOCUMENT (document);
1948         poppler_page = poppler_document_get_page (pdf_document->document, page);
1949         poppler_page_get_crop_box (poppler_page, &poppler_rect);
1950         rect->x1 = poppler_rect.x1;
1951         rect->x2 = poppler_rect.x2;
1952         rect->y1 = poppler_rect.y1;
1953         rect->y2 = poppler_rect.y2;
1954 }
1955
1956 static EvFormField *
1957 ev_form_field_from_poppler_field (PopplerFormField *poppler_field)
1958 {
1959         EvFormField *ev_field = NULL;
1960         gint         id;
1961         gdouble      font_size;
1962         gboolean     is_read_only;
1963
1964         id = poppler_form_field_get_id (poppler_field);
1965         font_size = poppler_form_field_get_font_size (poppler_field);
1966         is_read_only = poppler_form_field_is_read_only (poppler_field);
1967
1968         switch (poppler_form_field_get_field_type (poppler_field)) {
1969                 case POPPLER_FORM_FIELD_TEXT: {
1970                         EvFormFieldText    *field_text;
1971                         EvFormFieldTextType ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
1972
1973                         switch (poppler_form_field_text_get_text_type (poppler_field)) {
1974                                 case POPPLER_FORM_TEXT_NORMAL:
1975                                         ev_text_type = EV_FORM_FIELD_TEXT_NORMAL;
1976                                         break;
1977                                 case POPPLER_FORM_TEXT_MULTILINE:
1978                                         ev_text_type = EV_FORM_FIELD_TEXT_MULTILINE;
1979                                         break;
1980                                 case POPPLER_FORM_TEXT_FILE_SELECT:
1981                                         ev_text_type = EV_FORM_FIELD_TEXT_FILE_SELECT;
1982                                         break;
1983                         }
1984                         
1985                         ev_field = ev_form_field_text_new (id, ev_text_type);
1986                         field_text = EV_FORM_FIELD_TEXT (ev_field);
1987
1988                         field_text->do_spell_check = poppler_form_field_text_do_spell_check (poppler_field);
1989                         field_text->do_scroll = poppler_form_field_text_do_scroll (poppler_field);
1990                         field_text->is_rich_text = poppler_form_field_text_is_rich_text (poppler_field);
1991                         field_text->is_password = poppler_form_field_text_is_password (poppler_field);
1992                         field_text->max_len = poppler_form_field_text_get_max_len (poppler_field);
1993                         field_text->text = poppler_form_field_text_get_text (poppler_field);
1994
1995                 }
1996                         break;
1997                 case POPPLER_FORM_FIELD_BUTTON: {
1998                         EvFormFieldButton    *field_button;
1999                         EvFormFieldButtonType ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2000
2001                         switch (poppler_form_field_button_get_button_type (poppler_field)) {
2002                                 case POPPLER_FORM_BUTTON_PUSH:
2003                                         ev_button_type = EV_FORM_FIELD_BUTTON_PUSH;
2004                                         break;
2005                                 case POPPLER_FORM_BUTTON_CHECK:
2006                                         ev_button_type = EV_FORM_FIELD_BUTTON_CHECK;
2007                                         break;
2008                                 case POPPLER_FORM_BUTTON_RADIO:
2009                                         ev_button_type = EV_FORM_FIELD_BUTTON_RADIO;
2010                                         break;
2011                         }
2012
2013                         ev_field = ev_form_field_button_new (id, ev_button_type);
2014                         field_button = EV_FORM_FIELD_BUTTON (ev_field);
2015                         
2016                         field_button->state = poppler_form_field_button_get_state (poppler_field);
2017                 }
2018                         break;
2019                 case POPPLER_FORM_FIELD_CHOICE: {
2020                         EvFormFieldChoice    *field_choice;
2021                         EvFormFieldChoiceType ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2022
2023                         switch (poppler_form_field_choice_get_choice_type (poppler_field)) {
2024                                 case POPPLER_FORM_CHOICE_COMBO:
2025                                         ev_choice_type = EV_FORM_FIELD_CHOICE_COMBO;
2026                                         break;
2027                                 case EV_FORM_FIELD_CHOICE_LIST:
2028                                         ev_choice_type = EV_FORM_FIELD_CHOICE_LIST;
2029                                         break;
2030                         }
2031
2032                         ev_field = ev_form_field_choice_new (id, ev_choice_type);
2033                         field_choice = EV_FORM_FIELD_CHOICE (ev_field);
2034
2035                         field_choice->is_editable = poppler_form_field_choice_is_editable (poppler_field);
2036                         field_choice->multi_select = poppler_form_field_choice_can_select_multiple (poppler_field);
2037                         field_choice->do_spell_check = poppler_form_field_choice_do_spell_check (poppler_field);
2038                         field_choice->commit_on_sel_change = poppler_form_field_choice_commit_on_change (poppler_field);
2039
2040                         /* TODO: we need poppler_form_field_choice_get_selected_items in poppler 
2041                         field_choice->selected_items = poppler_form_field_choice_get_selected_items (poppler_field);*/
2042                         if (field_choice->is_editable)
2043                                 field_choice->text = poppler_form_field_choice_get_text (poppler_field);
2044                 }
2045                         break;
2046                 case POPPLER_FORM_FIELD_SIGNATURE:
2047                         /* TODO */
2048                         ev_field = ev_form_field_signature_new (id);
2049                         break;
2050                 case POPPLER_FORM_FIELD_UNKNOWN:
2051                         break;
2052         }
2053
2054         ev_field->font_size = font_size;
2055         ev_field->is_read_only = is_read_only;
2056
2057         return ev_field;
2058 }
2059
2060 static GList *
2061 pdf_document_forms_get_form_fields (EvDocumentForms *document, 
2062                                     gint             page)
2063 {
2064         PdfDocument *pdf_document;
2065         PopplerPage *poppler_page;
2066         GList *retval = NULL;
2067         GList *fields;
2068         GList *list;
2069         double height;
2070         
2071
2072         pdf_document = PDF_DOCUMENT (document);
2073         poppler_page = poppler_document_get_page (pdf_document->document, page);
2074         fields = poppler_page_get_form_field_mapping (poppler_page);
2075         poppler_page_get_size (poppler_page, NULL, &height);
2076
2077         for (list = fields; list; list = list->next) {
2078                 PopplerFormFieldMapping *mapping;
2079                 EvFormFieldMapping *field_mapping;
2080                 
2081                 mapping = (PopplerFormFieldMapping *)list->data;
2082
2083                 field_mapping = g_new0 (EvFormFieldMapping, 1);
2084                 field_mapping->x1 = mapping->area.x1;
2085                 field_mapping->x2 = mapping->area.x2;
2086                 field_mapping->y1 = height - mapping->area.y2;
2087                 field_mapping->y2 = height - mapping->area.y1;
2088                 field_mapping->field = ev_form_field_from_poppler_field (mapping->field);
2089                 field_mapping->field->page = page;
2090                 
2091                 retval = g_list_prepend (retval, field_mapping);
2092         }
2093         poppler_page_free_form_field_mapping (fields);
2094         g_object_unref (poppler_page);
2095
2096         return g_list_reverse (retval);
2097 }
2098
2099 static gchar *
2100 pdf_document_forms_form_field_text_get_text (EvDocumentForms *document,
2101                                              EvFormField     *field)
2102         
2103 {
2104         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2105         PopplerFormField *poppler_field;
2106         gchar *text;
2107
2108         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2109         if (!poppler_field)
2110                 return NULL;
2111         
2112         text = poppler_form_field_text_get_text (poppler_field);
2113         g_object_unref (poppler_field);
2114
2115         return text;
2116 }
2117
2118 static void
2119 pdf_document_forms_form_field_text_set_text (EvDocumentForms *document, 
2120                                              EvFormField     *field,
2121                                              const gchar     *text)
2122 {
2123         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2124         PopplerFormField *poppler_field;
2125
2126         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2127         if (!poppler_field)
2128                 return;
2129         poppler_form_field_text_set_text (poppler_field, text);
2130         g_object_unref (poppler_field);
2131 }
2132
2133 static void
2134 pdf_document_forms_form_field_button_set_state (EvDocumentForms *document, 
2135                                                 EvFormField     *field,
2136                                                 gboolean         state)
2137 {
2138         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2139         PopplerFormField *poppler_field;
2140
2141         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2142         if (!poppler_field)
2143                 return;
2144         
2145         poppler_form_field_button_set_state (poppler_field, state);
2146         g_object_unref (poppler_field);
2147 }
2148
2149 static gboolean
2150 pdf_document_forms_form_field_button_get_state (EvDocumentForms *document, 
2151                                                 EvFormField     *field)
2152 {
2153         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2154         PopplerFormField *poppler_field;
2155         gboolean state;
2156
2157         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2158         if (!poppler_field)
2159                 return FALSE;
2160
2161         state = poppler_form_field_button_get_state (poppler_field);
2162         g_object_unref (poppler_field);
2163
2164         return state;
2165 }
2166
2167 static gchar *
2168 pdf_document_forms_form_field_choice_get_item (EvDocumentForms *document, 
2169                                                EvFormField     *field,
2170                                                gint             index)
2171 {
2172         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2173         PopplerFormField *poppler_field;
2174         gchar *text;
2175
2176         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2177         if (!poppler_field)
2178                 return NULL;
2179
2180         text = poppler_form_field_choice_get_item (poppler_field, index);
2181         g_object_unref (poppler_field);
2182
2183         return text;
2184 }
2185
2186 static int
2187 pdf_document_forms_form_field_choice_get_n_items (EvDocumentForms *document, 
2188                                                   EvFormField     *field)
2189 {
2190         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2191         PopplerFormField *poppler_field;
2192         gint n_items;
2193
2194         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2195         if (!poppler_field)
2196                 return -1;
2197         
2198         n_items = poppler_form_field_choice_get_n_items (poppler_field);
2199         g_object_unref (poppler_field);
2200
2201         return n_items;
2202 }
2203
2204 static gboolean
2205 pdf_document_forms_form_field_choice_is_item_selected (EvDocumentForms *document, 
2206                                                        EvFormField     *field,
2207                                                        gint             index)
2208 {
2209         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2210         PopplerFormField *poppler_field;
2211         gboolean selected;
2212
2213         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2214         if (!poppler_field)
2215                 return FALSE;
2216
2217         selected = poppler_form_field_choice_is_item_selected (poppler_field, index);
2218         g_object_unref (poppler_field);
2219
2220         return selected;
2221 }
2222
2223 static void
2224 pdf_document_forms_form_field_choice_select_item (EvDocumentForms *document, 
2225                                                   EvFormField     *field,
2226                                                   gint             index)
2227 {
2228         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2229         PopplerFormField *poppler_field;
2230
2231         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2232         if (!poppler_field)
2233                 return;
2234
2235         poppler_form_field_choice_select_item (poppler_field, index);
2236         g_object_unref (poppler_field);
2237 }
2238
2239 static void
2240 pdf_document_forms_form_field_choice_toggle_item (EvDocumentForms *document, 
2241                                                   EvFormField     *field,
2242                                                   gint             index)
2243 {
2244         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2245         PopplerFormField *poppler_field;
2246
2247         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2248         if (!poppler_field)
2249                 return;
2250
2251         poppler_form_field_choice_toggle_item (poppler_field, index);
2252         g_object_unref (poppler_field);
2253 }
2254
2255 static void
2256 pdf_document_forms_form_field_choice_unselect_all (EvDocumentForms *document, 
2257                                                    EvFormField     *field)
2258 {
2259         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2260         PopplerFormField *poppler_field;
2261
2262         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2263         if (!poppler_field)
2264                 return;
2265         
2266         poppler_form_field_choice_unselect_all (poppler_field);
2267         g_object_unref (poppler_field);
2268 }
2269
2270 static void
2271 pdf_document_forms_form_field_choice_set_text (EvDocumentForms *document,
2272                                                EvFormField     *field,
2273                                                const gchar     *text)
2274 {
2275         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2276         PopplerFormField *poppler_field;
2277
2278         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2279         if (!poppler_field)
2280                 return;
2281         
2282         poppler_form_field_choice_set_text (poppler_field, text);
2283         g_object_unref (poppler_field);
2284 }
2285
2286 static gchar *
2287 pdf_document_forms_form_field_choice_get_text (EvDocumentForms *document,
2288                                                EvFormField     *field)
2289 {
2290         PdfDocument *pdf_document = PDF_DOCUMENT (document);
2291         PopplerFormField *poppler_field;
2292         gchar *text;
2293
2294         poppler_field = poppler_document_get_form_field (pdf_document->document, field->id);
2295         if (!poppler_field)
2296                 return NULL;
2297
2298         text = poppler_form_field_choice_get_text (poppler_field);
2299         g_object_unref (poppler_field);
2300
2301         return text;
2302 }
2303
2304 static void
2305 pdf_document_document_forms_iface_init (EvDocumentFormsIface *iface)
2306 {
2307         iface->get_form_fields = pdf_document_forms_get_form_fields;
2308         iface->form_field_text_get_text = pdf_document_forms_form_field_text_get_text;
2309         iface->form_field_text_set_text = pdf_document_forms_form_field_text_set_text;
2310         iface->form_field_button_set_state = pdf_document_forms_form_field_button_set_state;
2311         iface->form_field_button_get_state = pdf_document_forms_form_field_button_get_state;
2312         iface->form_field_choice_get_item = pdf_document_forms_form_field_choice_get_item;
2313         iface->form_field_choice_get_n_items = pdf_document_forms_form_field_choice_get_n_items;
2314         iface->form_field_choice_is_item_selected = pdf_document_forms_form_field_choice_is_item_selected;
2315         iface->form_field_choice_select_item = pdf_document_forms_form_field_choice_select_item;
2316         iface->form_field_choice_toggle_item = pdf_document_forms_form_field_choice_toggle_item;
2317         iface->form_field_choice_unselect_all = pdf_document_forms_form_field_choice_unselect_all;
2318         iface->form_field_choice_set_text = pdf_document_forms_form_field_choice_set_text;
2319         iface->form_field_choice_get_text = pdf_document_forms_form_field_choice_get_text;
2320 }
2321