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