]> www.fi.muni.cz Git - evince.git/blob - libview/ev-view.c
[libview] Fix scrollbars position when moving to a dest in rotated documents
[evince.git] / libview / ev-view.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* this file is part of evince, a gnome document viewer
3  *
4  *  Copyright (C) 2004 Red Hat, Inc
5  *
6  * Evince is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Evince is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <math.h>
25 #include <string.h>
26
27 #include <glib/gi18n-lib.h>
28 #include <gtk/gtk.h>
29 #include <gdk/gdkkeysyms.h>
30
31 #include "ev-mapping.h"
32 #include "ev-document-forms.h"
33 #include "ev-document-images.h"
34 #include "ev-document-links.h"
35 #include "ev-document-misc.h"
36 #include "ev-document-transition.h"
37 #include "ev-pixbuf-cache.h"
38 #include "ev-transition-animation.h"
39 #include "ev-view-marshal.h"
40 #include "ev-document-annotations.h"
41 #include "ev-annotation-window.h"
42 #include "ev-view.h"
43 #include "ev-view-accessible.h"
44 #include "ev-view-private.h"
45 #include "ev-view-type-builtins.h"
46
47 #define EV_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
48 #define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW))
49 #define EV_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_VIEW, EvViewClass))
50
51 enum {
52         PROP_0,
53         PROP_CONTINUOUS,
54         PROP_DUAL_PAGE,
55         PROP_FULLSCREEN,
56         PROP_PRESENTATION,
57         PROP_SIZING_MODE,
58         PROP_ZOOM,
59         PROP_ROTATION,
60         PROP_HAS_SELECTION,
61 };
62
63 enum {
64         SIGNAL_BINDING_ACTIVATED,
65         SIGNAL_HANDLE_LINK,
66         SIGNAL_EXTERNAL_LINK,
67         SIGNAL_POPUP_MENU,
68         N_SIGNALS,
69 };
70
71 enum {
72         TARGET_DND_URI,
73         TARGET_DND_TEXT,
74         TARGET_DND_IMAGE
75 };
76
77 static guint signals[N_SIGNALS];
78
79 typedef enum {
80         EV_VIEW_FIND_NEXT,
81         EV_VIEW_FIND_PREV
82 } EvViewFindDirection;
83
84 #define ZOOM_IN_FACTOR  1.2
85 #define ZOOM_OUT_FACTOR (1.0/ZOOM_IN_FACTOR)
86
87 #define SCROLL_TIME 150
88
89 /*** Scrolling ***/
90 static void       scroll_to_current_page                     (EvView *view,
91                                                               GtkOrientation orientation);
92 static void       ev_view_set_scroll_adjustments             (GtkLayout          *layout,
93                                                               GtkAdjustment      *hadjustment,
94                                                               GtkAdjustment      *vadjustment);
95 static void       view_update_range_and_current_page         (EvView             *view);
96 static void       set_scroll_adjustment                      (EvView             *view,
97                                                               GtkOrientation      orientation,
98                                                               GtkAdjustment      *adjustment);
99 static void       add_scroll_binding_keypad                  (GtkBindingSet      *binding_set,
100                                                               guint               keyval,
101                                                               GdkModifierType modifiers,
102                                                               GtkScrollType       scroll,
103                                                               gboolean            horizontal);
104 static void       ensure_rectangle_is_visible                (EvView             *view,
105                                                               GdkRectangle       *rect);
106
107 /*** Geometry computations ***/
108 static void       compute_border                             (EvView             *view,
109                                                               int                 width,
110                                                               int                 height,
111                                                               GtkBorder          *border);
112 static void       get_page_y_offset                          (EvView             *view,
113                                                               int                 page,
114                                                               int                *y_offset);
115 static gboolean   get_page_extents                           (EvView             *view,
116                                                               gint                page,
117                                                               GdkRectangle       *page_area,
118                                                               GtkBorder          *border);
119 static void       view_rect_to_doc_rect                      (EvView             *view,
120                                                               GdkRectangle       *view_rect,
121                                                               GdkRectangle       *page_area,
122                                                               EvRectangle        *doc_rect);
123 static void       doc_rect_to_view_rect                      (EvView             *view,
124                                                               int                 page,
125                                                               EvRectangle        *doc_rect,
126                                                               GdkRectangle       *view_rect);
127 static gboolean   get_dual_even_left                         (EvView             *view);
128 static void       find_page_at_location                      (EvView             *view,
129                                                               gdouble             x,
130                                                               gdouble             y,
131                                                               gint               *page,
132                                                               gint               *x_offset,
133                                                               gint               *y_offset);
134 static void       doc_point_to_view_point                    (EvView             *view,
135                                                               int                 page,
136                                                               EvPoint            *doc_point,
137                                                               GdkPoint           *view_point);
138 /*** Hyperrefs ***/
139 static EvLink *   ev_view_get_link_at_location               (EvView             *view,
140                                                               gdouble             x,
141                                                               gdouble             y);
142 static char*      tip_from_link                              (EvView             *view,
143                                                               EvLink             *link);
144 /*** Forms ***/
145 static EvFormField *ev_view_get_form_field_at_location       (EvView             *view,
146                                                                gdouble            x,
147                                                                gdouble            y);
148
149 /*** Annotations ***/
150 static EvAnnotation *ev_view_get_annotation_at_location      (EvView             *view,
151                                                               gdouble             x,
152                                                               gdouble             y);
153 static void          show_annotation_windows                 (EvView             *view,
154                                                               gint                page);
155 static void          hide_annotation_windows                 (EvView             *view,
156                                                               gint                page);
157 /*** GtkWidget implementation ***/
158 static void       ev_view_size_request_continuous_dual_page  (EvView             *view,
159                                                               GtkRequisition     *requisition);
160 static void       ev_view_size_request_continuous            (EvView             *view,
161                                                               GtkRequisition     *requisition);
162 static void       ev_view_size_request_dual_page             (EvView             *view,
163                                                               GtkRequisition     *requisition);
164 static void       ev_view_size_request_single_page           (EvView             *view,
165                                                               GtkRequisition     *requisition);
166 static void       ev_view_size_request                       (GtkWidget          *widget,
167                                                               GtkRequisition     *requisition);
168 static void       ev_view_size_allocate                      (GtkWidget          *widget,
169                                                               GtkAllocation      *allocation);
170 static void       ev_view_realize                            (GtkWidget          *widget);
171 static gboolean   ev_view_scroll_event                       (GtkWidget          *widget,
172                                                               GdkEventScroll     *event);
173 static gboolean   ev_view_expose_event                       (GtkWidget          *widget,
174                                                               GdkEventExpose     *event);
175 static gboolean   ev_view_popup_menu                         (GtkWidget          *widget);
176 static gboolean   ev_view_button_press_event                 (GtkWidget          *widget,
177                                                               GdkEventButton     *event);
178 static gboolean   ev_view_motion_notify_event                (GtkWidget          *widget,
179                                                               GdkEventMotion     *event);
180 static gboolean   ev_view_button_release_event               (GtkWidget          *widget,
181                                                               GdkEventButton     *event);
182 static gboolean   ev_view_enter_notify_event                 (GtkWidget          *widget,
183                                                               GdkEventCrossing   *event);
184 static gboolean   ev_view_leave_notify_event                 (GtkWidget          *widget,
185                                                               GdkEventCrossing   *event);
186 static void       ev_view_style_set                          (GtkWidget          *widget,
187                                                               GtkStyle           *old_style);
188 static void       ev_view_remove_all                         (EvView             *view);
189
190 static AtkObject *ev_view_get_accessible                     (GtkWidget *widget);
191
192 /*** Drawing ***/
193 static guint32    ev_gdk_color_to_rgb                        (const GdkColor     *color);
194 static void       draw_rubberband                            (GtkWidget          *widget,
195                                                               GdkWindow          *window,
196                                                               const GdkRectangle *rect,
197                                                               guchar              alpha);
198 static void       highlight_find_results                     (EvView             *view,
199                                                               int                 page);
200 static void       draw_one_page                              (EvView             *view,
201                                                               gint                page,
202                                                               cairo_t            *cr,
203                                                               GdkRectangle       *page_area,
204                                                               GtkBorder          *border,
205                                                               GdkRectangle       *expose_area,
206                                                               gboolean           *page_ready);
207 static void       draw_loading_text                          (EvView             *view,
208                                                               GdkRectangle       *page_area,
209                                                               GdkRectangle       *expose_area);
210 static void       ev_view_reload_page                        (EvView             *view,
211                                                               gint                page,
212                                                               GdkRegion          *region);
213
214 /*** Callbacks ***/
215 static void       ev_view_change_page                        (EvView             *view,
216                                                               gint                new_page,
217                                                               gboolean            start_transition);
218 static void       job_finished_cb                            (EvPixbufCache      *pixbuf_cache,
219                                                               GdkRegion          *region,
220                                                               EvView             *view);
221 static void       ev_view_page_changed_cb                    (EvDocumentModel    *model,
222                                                               gint                old_page,
223                                                               gint                new_page,
224                                                               EvView             *view);
225 static void       on_adjustment_value_changed                (GtkAdjustment      *adjustment,
226                                                               EvView             *view);
227
228 /*** GObject ***/
229 static void       ev_view_finalize                           (GObject            *object);
230 static void       ev_view_destroy                            (GtkObject          *object);
231 static void       ev_view_set_property                       (GObject            *object,
232                                                               guint               prop_id,
233                                                               const GValue       *value,
234                                                               GParamSpec         *pspec);
235 static void       ev_view_get_property                       (GObject            *object,
236                                                               guint               prop_id,
237                                                               GValue             *value,
238                                                               GParamSpec         *pspec);
239 static void       ev_view_class_init                         (EvViewClass        *class);
240 static void       ev_view_init                               (EvView             *view);
241
242 /*** Zoom and sizing ***/
243 static double   zoom_for_size_fit_width                      (gdouble doc_width,
244                                                               gdouble doc_height,
245                                                               int     target_width,
246                                                               int     target_height);
247 static double   zoom_for_size_fit_height                     (gdouble doc_width,
248                                                               gdouble doc_height,
249                                                               int     target_width,
250                                                               int     target_height);
251 static double   zoom_for_size_best_fit                       (gdouble doc_width,
252                                                               gdouble doc_height,
253                                                               int     target_width,
254                                                               int     target_height);
255 static void     ev_view_zoom_for_size                        (EvView *view,
256                                                               int     width,
257                                                               int     height);
258 static void     ev_view_zoom_for_size_presentation           (EvView *view,
259                                                               int     width,
260                                                               int     height);
261 static void     ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
262                                                                 int     width,
263                                                                 int     height);
264 static void     ev_view_zoom_for_size_continuous               (EvView *view,
265                                                                 int     width,
266                                                                 int     height);
267 static void     ev_view_zoom_for_size_dual_page                (EvView *view,
268                                                                 int     width,
269                                                                 int     height);
270 static void     ev_view_zoom_for_size_single_page              (EvView *view,
271                                                                 int     width,
272                                                                 int     height);
273 /*** Cursors ***/
274 static GdkCursor* ev_view_create_invisible_cursor            (void);
275 static void       ev_view_set_cursor                         (EvView             *view,
276                                                               EvViewCursor        new_cursor);
277 static void       ev_view_handle_cursor_over_xy              (EvView *view,
278                                                               gint x,
279                                                               gint y);
280
281 /*** Find ***/
282 static gint         ev_view_find_get_n_results               (EvView             *view,
283                                                               gint                page);
284 static EvRectangle *ev_view_find_get_result                  (EvView             *view,
285                                                               gint                page,
286                                                               gint                result);
287 static void       jump_to_find_result                        (EvView             *view);
288 static void       jump_to_find_page                          (EvView             *view, 
289                                                               EvViewFindDirection direction,
290                                                               gint                shift);
291
292 /*** Selection ***/
293 static void       compute_selections                         (EvView             *view,
294                                                               EvSelectionStyle    style,
295                                                               GdkPoint           *start,
296                                                               GdkPoint           *stop);
297 static void       clear_selection                            (EvView             *view);
298 static void       clear_link_selected                        (EvView             *view);
299 static void       selection_free                             (EvViewSelection    *selection);
300 static char*      get_selected_text                          (EvView             *ev_view);
301 static void       ev_view_primary_get_cb                     (GtkClipboard       *clipboard,
302                                                               GtkSelectionData   *selection_data,
303                                                               guint               info,
304                                                               gpointer            data);
305 static void       ev_view_primary_clear_cb                   (GtkClipboard       *clipboard,
306                                                               gpointer            data);
307 static void       ev_view_update_primary_selection           (EvView             *ev_view);
308
309 /*** Presentation ***/
310 static void       ev_view_presentation_transition_start      (EvView             *ev_view);
311 static void       ev_view_presentation_transition_stop       (EvView             *ev_view);
312
313
314 G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_LAYOUT)
315
316 /* HeightToPage cache */
317 #define EV_HEIGHT_TO_PAGE_CACHE_KEY "ev-height-to-page-cache"
318
319 static void
320 build_height_to_page (EvHeightToPageCache *cache,
321                       EvDocument          *document,
322                       gint                 rotation)
323 {
324         gboolean swap, uniform, dual_even_left;
325         int i;
326         double uniform_height, page_height, next_page_height;
327         double saved_height;
328         gdouble u_width, u_height;
329         gint n_pages;
330
331         swap = (rotation == 90 || rotation == 270);
332
333         uniform = ev_document_is_page_size_uniform (document);
334         n_pages = ev_document_get_n_pages (document);
335         dual_even_left = (n_pages > 2);
336
337         g_free (cache->height_to_page);
338         g_free (cache->dual_height_to_page);
339
340         cache->rotation = rotation;
341         cache->height_to_page = g_new0 (gdouble, n_pages + 1);
342         cache->dual_height_to_page = g_new0 (gdouble, n_pages + 2);
343
344         if (uniform)
345                 ev_document_get_page_size (document, 0, &u_width, &u_height);
346
347         saved_height = 0;
348         for (i = 0; i <= n_pages; i++) {
349                 if (uniform) {
350                         uniform_height = swap ? u_width : u_height;
351                         cache->height_to_page[i] = i * uniform_height;
352                 } else {
353                         if (i < n_pages) {
354                                 gdouble w, h;
355
356                                 ev_document_get_page_size (document, i, &w, &h);
357                                 page_height = swap ? w : h;
358                         } else {
359                                 page_height = 0;
360                         }
361                         cache->height_to_page[i] = saved_height;
362                         saved_height += page_height;
363                 }
364         }
365
366         if (dual_even_left && !uniform) {
367                 gdouble w, h;
368
369                 ev_document_get_page_size (document, 0, &w, &h);
370                 saved_height = swap ? w : h;
371         } else {
372                 saved_height = 0;
373         }
374
375         for (i = dual_even_left; i < n_pages + 2; i += 2) {
376                 if (uniform) {
377                         uniform_height = swap ? u_width : u_height;
378                         cache->dual_height_to_page[i] = ((i + dual_even_left) / 2) * uniform_height;
379                         if (i + 1 < n_pages + 2)
380                                 cache->dual_height_to_page[i + 1] = ((i + dual_even_left) / 2) * uniform_height;
381                 } else {
382                         if (i + 1 < n_pages) {
383                                 gdouble w, h;
384
385                                 ev_document_get_page_size (document, i + 1, &w, &h);
386                                 next_page_height = swap ? w : h;
387                         } else {
388                                 next_page_height = 0;
389                         }
390
391                         if (i < n_pages) {
392                                 gdouble w, h;
393
394                                 ev_document_get_page_size (document, i, &w, &h);
395                                 page_height = swap ? w : h;
396                         } else {
397                                 page_height = 0;
398                         }
399
400                         if (i + 1 < n_pages + 2) {
401                                 cache->dual_height_to_page[i] = saved_height;
402                                 cache->dual_height_to_page[i + 1] = saved_height;
403                                 saved_height += MAX(page_height, next_page_height);
404                         } else {
405                                 cache->dual_height_to_page[i] = saved_height;
406                         }
407                 }
408         }
409 }
410
411 static void
412 ev_height_to_page_cache_get_height (EvHeightToPageCache *cache,
413                                     EvDocument          *document,
414                                     gint                 page,
415                                     gint                 rotation,
416                                     gdouble             *height,
417                                     gdouble             *dual_height)
418 {
419         if (cache->rotation != rotation)
420                 build_height_to_page (cache, document, rotation);
421
422         *height = cache->height_to_page[page];
423         *dual_height = cache->dual_height_to_page[page];
424 }
425
426 static void
427 ev_height_to_page_cache_free (EvHeightToPageCache *cache)
428 {
429         if (cache->height_to_page) {
430                 g_free (cache->height_to_page);
431                 cache->height_to_page = NULL;
432         }
433
434         if (cache->dual_height_to_page) {
435                 g_free (cache->dual_height_to_page);
436                 cache->dual_height_to_page = NULL;
437         }
438         g_free (cache);
439 }
440
441 static EvHeightToPageCache *
442 ev_view_get_height_to_page_cache (EvView *view)
443 {
444         EvHeightToPageCache *cache;
445
446         if (!view->document)
447                 return NULL;
448
449         cache = g_object_get_data (G_OBJECT (view->document), EV_HEIGHT_TO_PAGE_CACHE_KEY);
450         if (!cache) {
451                 cache = g_new0 (EvHeightToPageCache, 1);
452                 build_height_to_page (cache, view->document, view->rotation);
453                 g_object_set_data_full (G_OBJECT (view->document),
454                                         EV_HEIGHT_TO_PAGE_CACHE_KEY,
455                                         cache,
456                                         (GDestroyNotify)ev_height_to_page_cache_free);
457         }
458
459         return cache;
460 }
461
462 static void
463 ev_view_get_height_to_page (EvView *view,
464                             gint    page,
465                             gint   *height,
466                             gint   *dual_height)
467 {
468         gdouble h, dh;
469
470         if (!view->height_to_page_cache)
471                 return;
472
473         ev_height_to_page_cache_get_height (view->height_to_page_cache,
474                                             view->document,
475                                             page,
476                                             view->rotation,
477                                             &h, &dh);
478         if (height)
479                 *height = (gint)(h * view->scale + 0.5);
480
481         if (dual_height)
482                 *dual_height = (gint)(dh * view->scale + 0.5);
483 }
484
485 static void
486 scroll_to_current_page (EvView *view, GtkOrientation orientation)
487 {
488         GdkPoint view_point;
489
490         if (view->document == NULL) {
491                 return;
492         }
493
494         doc_point_to_view_point (view, view->current_page, &view->pending_point, &view_point);
495
496         if (orientation == GTK_ORIENTATION_VERTICAL) {
497                 if (view->continuous) {
498                         gtk_adjustment_clamp_page (view->vadjustment,
499                                                    view_point.y - view->spacing / 2,
500                                                    view_point.y + view->vadjustment->page_size);
501                 } else {
502                         gtk_adjustment_set_value (view->vadjustment,
503                                                   CLAMP (view_point.y,
504                                                   view->vadjustment->lower,
505                                                   view->vadjustment->upper -
506                                                   view->vadjustment->page_size));
507                 }
508         } else {
509                 if (view->dual_page) {
510                         gtk_adjustment_clamp_page (view->hadjustment,
511                                                    view_point.x,
512                                                    view_point.x + view->hadjustment->page_size);
513                 } else {
514                         gtk_adjustment_set_value (view->hadjustment,
515                                                   CLAMP (view_point.x,
516                                                   view->hadjustment->lower,
517                                                   view->hadjustment->upper -
518                                                   view->hadjustment->page_size));
519                 }
520         }
521 }
522
523 static void
524 view_set_adjustment_values (EvView         *view,
525                             GtkOrientation  orientation)
526 {
527         GtkWidget *widget = GTK_WIDGET (view);
528         GtkAdjustment *adjustment;
529         int requisition;
530         int allocation;
531
532         double factor;
533         gint new_value;
534
535         if (orientation == GTK_ORIENTATION_HORIZONTAL)  {
536                 requisition = widget->requisition.width;
537                 allocation = widget->allocation.width;
538                 adjustment = view->hadjustment;
539         } else {
540                 requisition = widget->requisition.height;
541                 allocation = widget->allocation.height;
542                 adjustment = view->vadjustment;
543         }
544
545         if (!adjustment)
546                 return;
547
548         factor = 1.0;
549         switch (view->pending_scroll) {
550                 case SCROLL_TO_KEEP_POSITION:
551                 case SCROLL_TO_FIND_LOCATION:
552                         factor = (adjustment->value) / adjustment->upper;
553                         break;
554                 case SCROLL_TO_PAGE_POSITION:
555                         break;
556                 case SCROLL_TO_CENTER:
557                         factor = (adjustment->value + adjustment->page_size * 0.5) / adjustment->upper;
558                         break;
559         }
560
561         adjustment->page_size = allocation;
562         adjustment->step_increment = allocation * 0.1;
563         adjustment->page_increment = allocation * 0.9;
564         adjustment->lower = 0;
565         adjustment->upper = MAX (allocation, requisition);
566
567         /*
568          * We add 0.5 to the values before to average out our rounding errors.
569          */
570         switch (view->pending_scroll) {
571                 case SCROLL_TO_KEEP_POSITION:
572                 case SCROLL_TO_FIND_LOCATION:
573                         new_value = CLAMP (adjustment->upper * factor + 0.5, 0, adjustment->upper - adjustment->page_size);
574                         gtk_adjustment_set_value (adjustment, (int)new_value);
575                         break;
576                 case SCROLL_TO_PAGE_POSITION:
577                         scroll_to_current_page (view, orientation);
578                         break;
579                 case SCROLL_TO_CENTER:
580                         new_value = CLAMP (adjustment->upper * factor - adjustment->page_size * 0.5 + 0.5,
581                                            0, adjustment->upper - adjustment->page_size);
582                         gtk_adjustment_set_value (adjustment, (int)new_value);
583                         break;
584         }
585
586         gtk_adjustment_changed (adjustment);
587 }
588
589 static void
590 view_update_range_and_current_page (EvView *view)
591 {
592         gint current_page;
593         gint best_current_page = -1;
594         gint start = view->start_page;
595         gint end = view->end_page;
596         
597         /* Presentation trumps all other modes */
598         if (view->presentation) {
599                 view->start_page = view->current_page;
600                 view->end_page = view->current_page;
601         } else if (view->continuous) {
602                 GdkRectangle current_area, unused, page_area;
603                 GtkBorder border;
604                 gboolean found = FALSE;
605                 gint area_max = -1, area;
606                 int i;
607
608                 if (!(view->vadjustment && view->hadjustment))
609                         return;
610
611                 current_area.x = view->hadjustment->value;
612                 current_area.width = view->hadjustment->upper;
613                 current_area.y = view->vadjustment->value;
614                 current_area.height = view->vadjustment->page_size;
615
616                 for (i = 0; i < ev_document_get_n_pages (view->document); i++) {
617
618                         get_page_extents (view, i, &page_area, &border);
619
620                         if (gdk_rectangle_intersect (&current_area, &page_area, &unused)) {
621                                 area = unused.width * unused.height;
622
623                                 if (!found) {
624                                         area_max = area;
625                                         view->start_page = i;
626                                         found = TRUE;
627                                         best_current_page = i;
628                                 }
629                                 if (area > area_max) {
630                                         best_current_page = (area == area_max) ? MIN (i, best_current_page) : i;
631                                         area_max = area;
632                                 }
633
634                                 view->end_page = i;
635                         } else if (found && view->current_page <= view->end_page) {
636                                 break;
637                         }
638                 }
639
640         } else if (view->dual_page) {
641                 if (view->current_page % 2 == get_dual_even_left (view)) {
642                         view->start_page = view->current_page;
643                         if (view->current_page + 1 < ev_document_get_n_pages (view->document))
644                                 view->end_page = view->start_page + 1;
645                         else 
646                                 view->end_page = view->start_page;
647                 } else {
648                         if (view->current_page < 1)
649                                 view->start_page = view->current_page;
650                         else
651                                 view->start_page = view->current_page - 1;
652                         view->end_page = view->current_page;
653                 }
654         } else {
655                 view->start_page = view->current_page;
656                 view->end_page = view->current_page;
657         }
658
659         best_current_page = MAX (best_current_page, view->start_page);
660         current_page = ev_document_model_get_page (view->model);
661
662         if ((current_page != best_current_page) && (view->pending_scroll == SCROLL_TO_KEEP_POSITION)) {
663                 view->current_page = best_current_page;
664                 ev_document_model_set_page (view->model, best_current_page);
665         }
666
667         if (start != view->start_page || end != view->end_page) {
668                 gint i;
669
670                 for (i = start; i < view->start_page; i++) {
671                         hide_annotation_windows (view, i);
672                 }
673
674                 for (i = end; i > view->end_page; i--) {
675                         hide_annotation_windows (view, i);
676                 }
677         }
678
679         ev_pixbuf_cache_set_page_range (view->pixbuf_cache,
680                                         view->start_page,
681                                         view->end_page,
682                                         view->rotation,
683                                         view->scale,
684                                         view->selection_info.selections);
685 }
686
687 static void
688 set_scroll_adjustment (EvView *view,
689                        GtkOrientation  orientation,
690                        GtkAdjustment  *adjustment)
691 {
692         GtkAdjustment **to_set;
693
694         if (orientation == GTK_ORIENTATION_HORIZONTAL)
695                 to_set = &view->hadjustment;
696         else
697                 to_set = &view->vadjustment;
698
699         if (*to_set != adjustment) {
700                 if (*to_set) {
701                         g_signal_handlers_disconnect_by_func (*to_set,
702                                                               (gpointer) on_adjustment_value_changed,
703                                                               view);
704                         g_object_unref (*to_set);
705                 }
706
707                 *to_set = adjustment;
708                 view_set_adjustment_values (view, orientation);
709
710                 if (*to_set) {
711                         g_object_ref (*to_set);
712                         g_signal_connect (*to_set, "value_changed",
713                                           G_CALLBACK (on_adjustment_value_changed), view);
714                 }
715         }
716 }
717
718 static void
719 ev_view_set_scroll_adjustments (GtkLayout      *layout,
720                                 GtkAdjustment  *hadjustment,
721                                 GtkAdjustment  *vadjustment)
722 {
723         EvView *view = EV_VIEW (layout);
724         
725         set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, hadjustment);
726         set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL, vadjustment);
727         
728         on_adjustment_value_changed (NULL, view);
729 }
730
731 static void
732 add_scroll_binding_keypad (GtkBindingSet  *binding_set,
733                            guint           keyval,
734                            GdkModifierType modifiers,
735                            GtkScrollType   scroll,
736                            gboolean        horizontal)
737 {
738   guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left;
739
740   gtk_binding_entry_add_signal (binding_set, keyval, modifiers,
741                                 "binding_activated", 2,
742                                 GTK_TYPE_SCROLL_TYPE, scroll,
743                                 G_TYPE_BOOLEAN, horizontal);
744   gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers,
745                                 "binding_activated", 2,
746                                 GTK_TYPE_SCROLL_TYPE, scroll,
747                                 G_TYPE_BOOLEAN, horizontal);
748 }
749
750 void
751 ev_view_scroll (EvView        *view,
752                 GtkScrollType  scroll,
753                 gboolean       horizontal)
754 {
755         GtkAdjustment *adjustment;
756         double value, increment;
757         gboolean first_page = FALSE;
758         gboolean last_page = FALSE;
759
760         view->jump_to_find_result = FALSE;
761
762         if (view->presentation || view->sizing_mode == EV_SIZING_BEST_FIT) {
763                 switch (scroll) {
764                         case GTK_SCROLL_PAGE_BACKWARD:
765                         case GTK_SCROLL_STEP_BACKWARD:
766                                 ev_view_previous_page (view);
767                                 break;
768                         case GTK_SCROLL_PAGE_FORWARD:
769                         case GTK_SCROLL_STEP_FORWARD:
770                                 ev_view_next_page (view);
771                                 break;
772                         default:
773                                 break;
774                 }
775                 return;
776         }
777
778         /* Assign values for increment and vertical adjustment */
779         adjustment = horizontal ? view->hadjustment : view->vadjustment;
780         increment = adjustment->page_size * 0.75;
781         value = adjustment->value;
782
783         /* Assign boolean for first and last page */
784         if (view->current_page == 0)
785                 first_page = TRUE;
786         if (view->current_page == ev_document_get_n_pages (view->document) - 1)
787                 last_page = TRUE;
788
789         switch (scroll) {
790                 case GTK_SCROLL_PAGE_BACKWARD:
791                         /* Do not jump backwards if at the first page */
792                         if (value == (adjustment->lower) && first_page) {
793                                 /* Do nothing */
794                                 /* At the top of a page, assign the upper bound limit of previous page */
795                         } else if (value == (adjustment->lower)) {
796                                 value = adjustment->upper - adjustment->page_size;
797                                 ev_view_previous_page (view);
798                                 /* Jump to the top */
799                         } else {
800                                 value = MAX (value - increment, adjustment->lower);
801                         }
802                         break;
803                 case GTK_SCROLL_PAGE_FORWARD:
804                         /* Do not jump forward if at the last page */
805                         if (value == (adjustment->upper - adjustment->page_size) && last_page) {
806                                 /* Do nothing */
807                         /* At the bottom of a page, assign the lower bound limit of next page */
808                         } else if (value == (adjustment->upper - adjustment->page_size)) {
809                                 value = 0;
810                                 ev_view_next_page (view);
811                         /* Jump to the bottom */
812                         } else {
813                                 value = MIN (value + increment, adjustment->upper - adjustment->page_size);
814                         }
815                         break;
816                 case GTK_SCROLL_STEP_BACKWARD:
817                         value -= adjustment->step_increment;
818                         break;
819                 case GTK_SCROLL_STEP_FORWARD:
820                         value += adjustment->step_increment;
821                         break;
822                 case GTK_SCROLL_STEP_DOWN:
823                         value -= adjustment->step_increment / 10;
824                         break;
825                 case GTK_SCROLL_STEP_UP:
826                         value += adjustment->step_increment / 10;
827                         break;
828                 default:
829                         break;
830         }
831
832         value = CLAMP (value, adjustment->lower,
833                        adjustment->upper - adjustment->page_size);      
834
835         gtk_adjustment_set_value (adjustment, value);
836 }
837
838 #define MARGIN 5
839
840 static void
841 ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect)
842 {
843         GtkWidget *widget = GTK_WIDGET (view);
844         GtkAdjustment *adjustment;
845         int value;
846
847         view->pending_scroll = SCROLL_TO_FIND_LOCATION;
848
849         adjustment = view->vadjustment;
850
851         if (rect->y < adjustment->value) {
852                 value = MAX (adjustment->lower, rect->y - MARGIN);
853                 gtk_adjustment_set_value (view->vadjustment, value);
854         } else if (rect->y + rect->height >
855                    adjustment->value + widget->allocation.height) {
856                 value = MIN (adjustment->upper, rect->y + rect->height -
857                              widget->allocation.height + MARGIN);
858                 gtk_adjustment_set_value (view->vadjustment, value);
859         }
860
861         adjustment = view->hadjustment;
862
863         if (rect->x < adjustment->value) {
864                 value = MAX (adjustment->lower, rect->x - MARGIN);
865                 gtk_adjustment_set_value (view->hadjustment, value);
866         } else if (rect->x + rect->height >
867                    adjustment->value + widget->allocation.width) {
868                 value = MIN (adjustment->upper, rect->x + rect->width -
869                              widget->allocation.width + MARGIN);
870                 gtk_adjustment_set_value (view->hadjustment, value);
871         }
872
873         gtk_widget_queue_resize (GTK_WIDGET (view));
874 }
875
876 /*** Geometry computations ***/
877
878 static void
879 compute_border (EvView *view, int width, int height, GtkBorder *border)
880 {
881         if (view->presentation) {
882                 border->left = 0;
883                 border->right = 0;
884                 border->top = 0;
885                 border->bottom = 0;
886         } else {
887                 ev_document_misc_get_page_border_size (width, height, border);
888         }
889 }
890
891 void
892 _get_page_size_for_scale_and_rotation (EvDocument *document,
893                                        gint        page,
894                                        gdouble     scale,
895                                        gint        rotation,
896                                        gint       *page_width,
897                                        gint       *page_height)
898 {
899         gdouble w, h;
900         gint    width, height;
901
902         ev_document_get_page_size (document, page, &w, &h);
903
904         width = (gint)(w * scale + 0.5);
905         height = (gint)(h * scale + 0.5);
906
907         if (page_width)
908                 *page_width = (rotation == 0 || rotation == 180) ? width : height;
909         if (page_height)
910                 *page_height = (rotation == 0 || rotation == 180) ? height : width;
911 }
912
913 static void
914 ev_view_get_page_size (EvView *view,
915                        gint    page,
916                        gint   *page_width,
917                        gint   *page_height)
918 {
919         _get_page_size_for_scale_and_rotation (view->document,
920                                                page,
921                                                view->scale,
922                                                view->rotation,
923                                                page_width,
924                                                page_height);
925 }
926
927 static void
928 ev_view_get_max_page_size (EvView *view,
929                            gint   *max_width,
930                            gint   *max_height)
931 {
932         double w, h;
933         gint   width, height;
934
935         ev_document_get_max_page_size (view->document, &w, &h);
936
937         width = (gint)(w * view->scale + 0.5);
938         height = (gint)(h * view->scale + 0.5);
939
940         if (max_width)
941                 *max_width = (view->rotation == 0 || view->rotation == 180) ? width : height;
942         if (max_height)
943                 *max_height = (view->rotation == 0 || view->rotation == 180) ? height : width;
944 }
945
946 static void
947 get_page_y_offset (EvView *view, int page, int *y_offset)
948 {
949         int max_width, offset;
950         GtkBorder border;
951
952         g_return_if_fail (y_offset != NULL);
953
954         ev_view_get_max_page_size (view, &max_width, NULL);
955         compute_border (view, max_width, max_width, &border);
956
957         if (view->dual_page) {
958                 ev_view_get_height_to_page (view, page, NULL, &offset);
959                 offset += ((page + get_dual_even_left (view)) / 2 + 1) * view->spacing +
960                         ((page + get_dual_even_left (view)) / 2 ) * (border.top + border.bottom);
961         } else {
962                 ev_view_get_height_to_page (view, page, &offset, NULL);
963                 offset += (page + 1) * view->spacing + page * (border.top + border.bottom);
964         }
965
966         *y_offset = offset;
967         return;
968 }
969
970 static gboolean
971 get_page_extents (EvView       *view,
972                   gint          page,
973                   GdkRectangle *page_area,
974                   GtkBorder    *border)
975 {
976         GtkWidget *widget;
977         int width, height;
978
979         widget = GTK_WIDGET (view);
980
981         /* Get the size of the page */
982         ev_view_get_page_size (view, page, &width, &height);
983         compute_border (view, width, height, border);
984         page_area->width = width + border->left + border->right;
985         page_area->height = height + border->top + border->bottom;
986
987         if (view->presentation) {
988                 page_area->x = (MAX (0, widget->allocation.width - width))/2;
989                 page_area->y = (MAX (0, widget->allocation.height - height))/2;
990         } else if (view->continuous) {
991                 gint max_width;
992                 gint x, y;
993
994                 ev_view_get_max_page_size (view, &max_width, NULL);
995                 max_width = max_width + border->left + border->right;
996                 /* Get the location of the bounding box */
997                 if (view->dual_page) {
998                         x = view->spacing + ((page % 2 == get_dual_even_left (view)) ? 0 : 1) * (max_width + view->spacing);
999                         x = x + MAX (0, widget->allocation.width - (max_width * 2 + view->spacing * 3)) / 2;
1000                         if (page % 2 == get_dual_even_left (view))
1001                                 x = x + (max_width - width - border->left - border->right);
1002                 } else {
1003                         x = view->spacing;
1004                         x = x + MAX (0, widget->allocation.width - (width + view->spacing * 2)) / 2;
1005                 }
1006
1007                 get_page_y_offset (view, page, &y);
1008
1009                 page_area->x = x;
1010                 page_area->y = y;
1011         } else {
1012                 gint x, y;
1013                 if (view->dual_page) {
1014                         gint width_2, height_2;
1015                         gint max_width = width;
1016                         gint max_height = height;
1017                         GtkBorder overall_border;
1018                         gint other_page;
1019
1020                         other_page = (page % 2 == get_dual_even_left (view)) ? page + 1: page - 1;
1021
1022                         /* First, we get the bounding box of the two pages */
1023                         if (other_page < ev_document_get_n_pages (view->document)
1024                             && (0 <= other_page)) {
1025                                 ev_view_get_page_size (view, other_page,
1026                                                        &width_2, &height_2);
1027                                 if (width_2 > width)
1028                                         max_width = width_2;
1029                                 if (height_2 > height)
1030                                         max_height = height_2;
1031                         }
1032                         compute_border (view, max_width, max_height, &overall_border);
1033
1034                         /* Find the offsets */
1035                         x = view->spacing;
1036                         y = view->spacing;
1037
1038                         /* Adjust for being the left or right page */
1039                         if (page % 2 == get_dual_even_left (view))
1040                                 x = x + max_width - width;
1041                         else
1042                                 x = x + (max_width + overall_border.left + overall_border.right) + view->spacing;
1043
1044                         y = y + (max_height - height)/2;
1045
1046                         /* Adjust for extra allocation */
1047                         x = x + MAX (0, widget->allocation.width -
1048                                      ((max_width + overall_border.left + overall_border.right) * 2 + view->spacing * 3))/2;
1049                         y = y + MAX (0, widget->allocation.height - (height + view->spacing * 2))/2;
1050                 } else {
1051                         x = view->spacing;
1052                         y = view->spacing;
1053
1054                         /* Adjust for extra allocation */
1055                         x = x + MAX (0, widget->allocation.width - (width + border->left + border->right + view->spacing * 2))/2;
1056                         y = y + MAX (0, widget->allocation.height - (height + border->top + border->bottom +  view->spacing * 2))/2;
1057                 }
1058
1059                 page_area->x = x;
1060                 page_area->y = y;
1061         }
1062
1063         return TRUE;
1064 }
1065
1066 static void
1067 get_doc_page_size (EvView  *view,
1068                    gint     page,
1069                    gdouble *width,
1070                    gdouble *height)
1071 {
1072         double w, h;
1073
1074         ev_document_get_page_size (view->document, page, &w, &h);
1075         if (view->rotation == 0 || view->rotation == 180) {
1076                 if (width) *width = w;
1077                 if (height) *height = h;
1078         } else {
1079                 if (width) *width = h;
1080                 if (height) *height = w;
1081         }
1082 }
1083
1084 static void
1085 view_point_to_doc_point (EvView *view,
1086                          GdkPoint *view_point,
1087                          GdkRectangle *page_area,
1088                          double  *doc_point_x,
1089                          double  *doc_point_y)
1090 {
1091         *doc_point_x = (double) (view_point->x - page_area->x) / view->scale;
1092         *doc_point_y = (double) (view_point->y - page_area->y) / view->scale;
1093 }
1094
1095 static void
1096 view_rect_to_doc_rect (EvView *view,
1097                        GdkRectangle *view_rect,
1098                        GdkRectangle *page_area,
1099                        EvRectangle  *doc_rect)
1100 {
1101         doc_rect->x1 = (double) (view_rect->x - page_area->x) / view->scale;
1102         doc_rect->y1 = (double) (view_rect->y - page_area->y) / view->scale;
1103         doc_rect->x2 = doc_rect->x1 + (double) view_rect->width / view->scale;
1104         doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale;
1105 }
1106
1107 static void
1108 doc_point_to_view_point (EvView       *view,
1109                          int           page,
1110                          EvPoint      *doc_point,
1111                          GdkPoint     *view_point)
1112 {
1113         GdkRectangle page_area;
1114         GtkBorder border;
1115         double x, y, view_x, view_y;
1116         gdouble width, height;
1117
1118         get_doc_page_size (view, page, &width, &height);
1119
1120         if (view->rotation == 0) {
1121                 x = doc_point->x;
1122                 y = doc_point->y;
1123         } else if (view->rotation == 90) {
1124                 x = width - doc_point->y;
1125                 y = doc_point->x;
1126         } else if (view->rotation == 180) {
1127                 x = width - doc_point->x;
1128                 y = height - doc_point->y;
1129         } else if (view->rotation == 270) {
1130                 x = doc_point->y;
1131                 y = height - doc_point->x;
1132         } else {
1133                 g_assert_not_reached ();
1134         }
1135
1136         get_page_extents (view, page, &page_area, &border);
1137
1138         view_x = CLAMP (x * view->scale, 0, page_area.width);
1139         view_y = CLAMP (y * view->scale, 0, page_area.height);
1140         view_point->x = view_x + page_area.x;
1141         view_point->y = view_y + page_area.y;
1142 }
1143
1144 static void
1145 doc_rect_to_view_rect (EvView       *view,
1146                        int           page,
1147                        EvRectangle  *doc_rect,
1148                        GdkRectangle *view_rect)
1149 {
1150         GdkRectangle page_area;
1151         GtkBorder border;
1152         double x, y, w, h;
1153         gdouble width, height;
1154
1155         get_doc_page_size (view, page, &width, &height);
1156
1157         if (view->rotation == 0) {
1158                 x = doc_rect->x1;
1159                 y = doc_rect->y1;
1160                 w = doc_rect->x2 - doc_rect->x1;
1161                 h = doc_rect->y2 - doc_rect->y1;
1162         } else if (view->rotation == 90) {
1163                 x = width - doc_rect->y2;
1164                 y = doc_rect->x1;
1165                 w = doc_rect->y2 - doc_rect->y1;
1166                 h = doc_rect->x2 - doc_rect->x1;
1167         } else if (view->rotation == 180) {
1168                 x = width - doc_rect->x2;
1169                 y = height - doc_rect->y2;
1170                 w = doc_rect->x2 - doc_rect->x1;
1171                 h = doc_rect->y2 - doc_rect->y1;
1172         } else if (view->rotation == 270) {
1173                 x = doc_rect->y1;
1174                 y = height - doc_rect->x2;
1175                 w = doc_rect->y2 - doc_rect->y1;
1176                 h = doc_rect->x2 - doc_rect->x1;
1177         } else {
1178                 g_assert_not_reached ();
1179         }
1180
1181         get_page_extents (view, page, &page_area, &border);
1182
1183         view_rect->x = x * view->scale + page_area.x;
1184         view_rect->y = y * view->scale + page_area.y;
1185         view_rect->width = w * view->scale;
1186         view_rect->height = h * view->scale;
1187 }
1188
1189 static gboolean
1190 get_dual_even_left (EvView *view)
1191 {
1192         return (ev_document_get_n_pages (view->document) > 2);
1193 }
1194
1195 static void
1196 find_page_at_location (EvView  *view,
1197                        gdouble  x,
1198                        gdouble  y,
1199                        gint    *page,
1200                        gint    *x_offset,
1201                        gint    *y_offset)
1202 {
1203         int i;
1204
1205         if (view->document == NULL)
1206                 return;
1207
1208         g_assert (page);
1209         g_assert (x_offset);
1210         g_assert (y_offset);
1211
1212         for (i = view->start_page; i >= 0 && i <= view->end_page; i++) {
1213                 GdkRectangle page_area;
1214                 GtkBorder border;
1215
1216                 if (! get_page_extents (view, i, &page_area, &border))
1217                         continue;
1218
1219                 if ((x >= page_area.x + border.left) &&
1220                     (x < page_area.x + page_area.width - border.right) &&
1221                     (y >= page_area.y + border.top) &&
1222                     (y < page_area.y + page_area.height - border.bottom)) {
1223                         *page = i;
1224                         *x_offset = x - (page_area.x + border.left);
1225                         *y_offset = y - (page_area.y + border.top);
1226                         return;
1227                 }
1228         }
1229
1230         *page = -1;
1231 }
1232
1233 static gboolean
1234 location_in_text (EvView  *view,
1235                   gdouble  x,
1236                   gdouble  y)
1237 {
1238         GdkRegion *region;
1239         gint page = -1;
1240         gint x_offset = 0, y_offset = 0;
1241
1242         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
1243
1244         if (page == -1)
1245                 return FALSE;
1246         
1247         region = ev_pixbuf_cache_get_text_mapping (view->pixbuf_cache, page);
1248
1249         if (region)
1250                 return gdk_region_point_in (region, x_offset / view->scale, y_offset / view->scale);
1251         else
1252                 return FALSE;
1253 }
1254
1255 static int
1256 ev_view_get_width (EvView *view)
1257 {
1258         return GTK_WIDGET (view)->allocation.width;
1259 }
1260
1261 static int
1262 ev_view_get_height (EvView *view)
1263 {
1264         return GTK_WIDGET (view)->allocation.height;
1265 }
1266
1267 static gboolean
1268 location_in_selected_text (EvView  *view,
1269                            gdouble  x,
1270                            gdouble  y)
1271 {
1272         gint page = -1;
1273         gint x_offset = 0, y_offset = 0;
1274         EvViewSelection *selection;
1275         GList *l = NULL;
1276
1277         for (l = view->selection_info.selections; l != NULL; l = l->next) {
1278                 selection = (EvViewSelection *)l->data;
1279                 
1280                 find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
1281                 
1282                 if (page != selection->page)
1283                         continue;
1284                 
1285                 if (selection->covered_region &&
1286                     gdk_region_point_in (selection->covered_region, x_offset, y_offset))
1287                         return TRUE;
1288         }
1289
1290         return FALSE;
1291 }
1292
1293 static gboolean
1294 get_doc_point_from_offset (EvView *view, 
1295                            gint    page, 
1296                            gint    x_offset, 
1297                            gint    y_offset, 
1298                            gint   *x_new, 
1299                            gint   *y_new)
1300 {
1301         gdouble width, height;
1302         double x, y;
1303
1304         get_doc_page_size (view, page, &width, &height);
1305
1306         x_offset = x_offset / view->scale;
1307         y_offset = y_offset / view->scale;
1308
1309         if (view->rotation == 0) {
1310                 x = x_offset;
1311                 y = y_offset;
1312         } else if (view->rotation == 90) {
1313                 x = y_offset;
1314                 y = width - x_offset;
1315         } else if (view->rotation == 180) {
1316                 x = width - x_offset;
1317                 y = height - y_offset;
1318         } else if (view->rotation == 270) {
1319                 x = height - y_offset; 
1320                 y = x_offset;
1321         } else {
1322                 g_assert_not_reached ();
1323         }
1324
1325         *x_new = x;
1326         *y_new = y;
1327         
1328         return TRUE;
1329 }
1330
1331 static gboolean
1332 get_doc_point_from_location (EvView  *view,
1333                              gdouble  x,
1334                              gdouble  y,
1335                              gint    *page,
1336                              gint    *x_new,
1337                              gint    *y_new)
1338 {
1339         gint x_offset = 0, y_offset = 0;
1340
1341         x += view->scroll_x;
1342         y += view->scroll_y;
1343         find_page_at_location (view, x, y, page, &x_offset, &y_offset);
1344         if (*page == -1)
1345                 return FALSE;
1346
1347         return get_doc_point_from_offset (view, *page, x_offset, y_offset, x_new, y_new);
1348 }
1349
1350 static void
1351 ev_view_get_area_from_mapping (EvView       *view,
1352                                guint         page,
1353                                GList        *mapping_list,
1354                                gconstpointer data,
1355                                GdkRectangle *area)
1356 {
1357         EvMapping *mapping;
1358
1359         mapping = ev_mapping_list_find (mapping_list, data);
1360         doc_rect_to_view_rect (view, page, &mapping->area, area);
1361         area->x -= view->scroll_x;
1362         area->y -= view->scroll_y;
1363 }
1364
1365
1366 /*** Hyperref ***/
1367 static EvLink *
1368 ev_view_get_link_at_location (EvView  *view,
1369                               gdouble  x,
1370                               gdouble  y)
1371 {
1372         gint page = -1;
1373         gint x_new = 0, y_new = 0;
1374         GList *link_mapping;
1375
1376         if (!EV_IS_DOCUMENT_LINKS (view->document))
1377                 return NULL;
1378
1379         if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new))
1380                 return NULL;
1381
1382         link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page);
1383
1384         if (link_mapping)
1385                 return ev_mapping_list_get_data (link_mapping, x_new, y_new);
1386         else
1387                 return NULL;
1388 }
1389
1390 static void
1391 goto_fitr_dest (EvView *view, EvLinkDest *dest)
1392 {
1393         EvPoint doc_point;
1394         gdouble zoom, left, top;
1395         gboolean change_left, change_top;
1396
1397         left = ev_link_dest_get_left (dest, &change_left);
1398         top = ev_link_dest_get_top (dest, &change_top);
1399
1400         zoom = zoom_for_size_best_fit (ev_link_dest_get_right (dest) - left,
1401                                        ev_link_dest_get_bottom (dest) - top,
1402                                        ev_view_get_width (view),
1403                                        ev_view_get_height (view));
1404
1405         ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE);
1406         ev_document_model_set_scale (view->model, zoom);
1407
1408         doc_point.x = change_left ? left : 0;
1409         doc_point.y = change_top ? top : 0;
1410         view->pending_point = doc_point;
1411
1412         ev_view_change_page (view, ev_link_dest_get_page (dest), TRUE);
1413 }
1414
1415 static void
1416 goto_fitv_dest (EvView *view, EvLinkDest *dest)
1417 {
1418         EvPoint doc_point;
1419         gdouble doc_width, doc_height;
1420         gint page;
1421         double zoom, left;
1422         gboolean change_left;
1423
1424         page = ev_link_dest_get_page (dest);
1425         ev_document_get_page_size (view->document, page, &doc_width, &doc_height);
1426
1427         left = ev_link_dest_get_left (dest, &change_left);
1428         doc_point.x = change_left ? left : 0;
1429         doc_point.y = 0;
1430
1431         zoom = zoom_for_size_fit_height (doc_width - doc_point.x , doc_height,
1432                                          ev_view_get_width (view),
1433                                          ev_view_get_height (view));
1434
1435         ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE);
1436         ev_document_model_set_scale (view->model, zoom);
1437
1438         view->pending_point = doc_point;
1439
1440         ev_view_change_page (view, page, TRUE);
1441 }
1442
1443 static void
1444 goto_fith_dest (EvView *view, EvLinkDest *dest)
1445 {
1446         EvPoint doc_point;
1447         gdouble doc_width, doc_height;
1448         gint page;
1449         gdouble zoom, top;
1450         gboolean change_top;
1451
1452         page = ev_link_dest_get_page (dest);
1453         ev_document_get_page_size (view->document, page, &doc_width, &doc_height);
1454
1455         top = ev_link_dest_get_top (dest, &change_top);
1456
1457         doc_point.x = 0;
1458         doc_point.y = change_top ? top : 0;
1459
1460         zoom = zoom_for_size_fit_width (doc_width, top,
1461                                         ev_view_get_width (view),
1462                                         ev_view_get_height (view));
1463
1464         ev_document_model_set_sizing_mode (view->model, EV_SIZING_FIT_WIDTH);
1465         ev_document_model_set_scale (view->model, zoom);
1466
1467         view->pending_point = doc_point;
1468
1469         ev_view_change_page (view, page, TRUE);
1470 }
1471
1472 static void
1473 goto_fit_dest (EvView *view, EvLinkDest *dest)
1474 {
1475         double zoom;
1476         gdouble doc_width, doc_height;
1477         int page;
1478
1479         page = ev_link_dest_get_page (dest);
1480         ev_document_get_page_size (view->document, page, &doc_width, &doc_height);
1481
1482         zoom = zoom_for_size_best_fit (doc_width, doc_height,
1483                                        ev_view_get_width (view),
1484                                        ev_view_get_height (view));
1485
1486         ev_document_model_set_sizing_mode (view->model, EV_SIZING_BEST_FIT);
1487         ev_document_model_set_scale (view->model, zoom);
1488
1489         ev_view_change_page (view, page, TRUE);
1490 }
1491
1492 static void
1493 goto_xyz_dest (EvView *view, EvLinkDest *dest)
1494 {
1495         EvPoint doc_point;
1496         gint page;
1497         gdouble zoom, left, top;
1498         gboolean change_zoom, change_left, change_top; 
1499
1500         zoom = ev_link_dest_get_zoom (dest, &change_zoom);
1501         page = ev_link_dest_get_page (dest);
1502
1503         if (change_zoom && zoom > 1) {
1504                 ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE);
1505                 ev_document_model_set_scale (view->model, zoom);
1506         }
1507
1508         left = ev_link_dest_get_left (dest, &change_left);
1509         top = ev_link_dest_get_top (dest, &change_top);
1510
1511         doc_point.x = change_left ? left : 0;
1512         doc_point.y = change_top ? top : 0;
1513         view->pending_point = doc_point;
1514
1515         ev_view_change_page (view, page, TRUE);
1516 }
1517
1518 static void
1519 goto_dest (EvView *view, EvLinkDest *dest)
1520 {
1521         EvLinkDestType type;
1522         int page, n_pages, current_page;
1523
1524         page = ev_link_dest_get_page (dest);
1525         n_pages = ev_document_get_n_pages (view->document);
1526
1527         if (page < 0 || page >= n_pages)
1528                 return;
1529
1530         current_page = view->current_page;
1531         
1532         type = ev_link_dest_get_dest_type (dest);
1533
1534         switch (type) {
1535                 case EV_LINK_DEST_TYPE_PAGE:
1536                         ev_document_model_set_page (view->model, page);
1537                         break;
1538                 case EV_LINK_DEST_TYPE_FIT:
1539                         goto_fit_dest (view, dest);
1540                         break;
1541                 case EV_LINK_DEST_TYPE_FITH:
1542                         goto_fith_dest (view, dest);
1543                         break;
1544                 case EV_LINK_DEST_TYPE_FITV:
1545                         goto_fitv_dest (view, dest);
1546                         break;
1547                 case EV_LINK_DEST_TYPE_FITR:
1548                         goto_fitr_dest (view, dest);
1549                         break;
1550                 case EV_LINK_DEST_TYPE_XYZ:
1551                         goto_xyz_dest (view, dest);
1552                         break;
1553                 case EV_LINK_DEST_TYPE_PAGE_LABEL:
1554                         ev_document_model_set_page_by_label (view->model, ev_link_dest_get_page_label (dest));
1555                         break;
1556                 default:
1557                         g_assert_not_reached ();
1558         }
1559
1560         if (current_page != view->current_page)
1561                 ev_document_model_set_page (view->model, view->current_page);
1562 }
1563
1564 static void
1565 ev_view_goto_dest (EvView *view, EvLinkDest *dest)
1566 {
1567         EvLinkDestType type;
1568
1569         type = ev_link_dest_get_dest_type (dest);
1570
1571         if (type == EV_LINK_DEST_TYPE_NAMED) {
1572                 EvLinkDest  *dest2;     
1573                 const gchar *named_dest;
1574
1575                 named_dest = ev_link_dest_get_named_dest (dest);
1576                 dest2 = ev_document_links_find_link_dest (EV_DOCUMENT_LINKS (view->document),
1577                                                           named_dest);
1578                 if (dest2) {
1579                         goto_dest (view, dest2);
1580                         g_object_unref (dest2);
1581                 }
1582
1583                 return;
1584         }
1585
1586         goto_dest (view, dest);
1587 }
1588         
1589 void
1590 ev_view_handle_link (EvView *view, EvLink *link)
1591 {
1592         EvLinkAction    *action = NULL;
1593         EvLinkActionType type;
1594
1595         action = ev_link_get_action (link);
1596         if (!action)
1597                 return;
1598
1599         type = ev_link_action_get_action_type (action);
1600
1601         switch (type) {
1602                 case EV_LINK_ACTION_TYPE_GOTO_DEST: {
1603                         EvLinkDest *dest;
1604                         
1605                         g_signal_emit (view, signals[SIGNAL_HANDLE_LINK], 0, link);
1606                 
1607                         dest = ev_link_action_get_dest (action);
1608                         ev_view_goto_dest (view, dest);
1609                 }
1610                         break;
1611                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
1612                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
1613                 case EV_LINK_ACTION_TYPE_LAUNCH:
1614                 case EV_LINK_ACTION_TYPE_NAMED:
1615                         g_signal_emit (view, signals[SIGNAL_EXTERNAL_LINK], 0, action);
1616                         break;
1617         }
1618 }
1619
1620 gchar *
1621 ev_view_page_label_from_dest (EvView *view, EvLinkDest *dest)
1622 {
1623         EvLinkDestType type;
1624         gchar *msg = NULL;
1625
1626         type = ev_link_dest_get_dest_type (dest);
1627
1628         switch (type) {
1629                 case EV_LINK_DEST_TYPE_NAMED: {
1630                         EvLinkDest  *dest2;
1631                         const gchar *named_dest;
1632                         
1633                         named_dest = ev_link_dest_get_named_dest (dest);
1634                         dest2 = ev_document_links_find_link_dest (EV_DOCUMENT_LINKS (view->document),
1635                                                                   named_dest);
1636                         if (dest2) {
1637                                 msg = ev_document_get_page_label (view->document,
1638                                                                   ev_link_dest_get_page (dest2));
1639                                 g_object_unref (dest2);
1640                         }
1641                 }
1642                         
1643                         break;
1644                 case EV_LINK_DEST_TYPE_PAGE_LABEL: {
1645                         msg = g_strdup (ev_link_dest_get_page_label (dest));
1646                 }
1647                         break;
1648                 default: 
1649                         msg = ev_document_get_page_label (view->document,
1650                                                           ev_link_dest_get_page (dest));
1651         }
1652         
1653         return msg;
1654 }
1655
1656 static char *
1657 tip_from_action_named (EvLinkAction *action)
1658 {
1659         const gchar *name = ev_link_action_get_name (action);
1660         
1661         if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
1662                 return g_strdup (_("Go to first page"));
1663         } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
1664                 return g_strdup (_("Go to previous page"));
1665         } else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
1666                 return g_strdup (_("Go to next page"));
1667         } else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
1668                 return g_strdup (_("Go to last page"));
1669         } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
1670                 return g_strdup (_("Go to page"));
1671         } else if (g_ascii_strcasecmp (name, "Find") == 0) {
1672                 return g_strdup (_("Find"));
1673         }
1674         
1675         return NULL;
1676 }
1677
1678 static char *
1679 tip_from_link (EvView *view, EvLink *link)
1680 {
1681         EvLinkAction *action;
1682         EvLinkActionType type;
1683         char *msg = NULL;
1684         char *page_label;
1685         const char *title;
1686
1687         action = ev_link_get_action (link);
1688         title = ev_link_get_title (link);
1689         
1690         if (!action)
1691                 return title ? g_strdup (title) : NULL;
1692                 
1693         type = ev_link_action_get_action_type (action);
1694
1695         switch (type) {
1696                 case EV_LINK_ACTION_TYPE_GOTO_DEST:
1697                         page_label = ev_view_page_label_from_dest (view,
1698                                                                    ev_link_action_get_dest (action));
1699                         if (page_label) {
1700                                 msg = g_strdup_printf (_("Go to page %s"), page_label);
1701                                 g_free (page_label);
1702                         }
1703                         break;
1704                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
1705                         if (title) {
1706                                 msg = g_strdup_printf (_("Go to %s on file “%s”"), title,
1707                                                        ev_link_action_get_filename (action));
1708                         } else {
1709                                 msg = g_strdup_printf (_("Go to file “%s”"),
1710                                                        ev_link_action_get_filename (action));
1711                         }
1712                         break;
1713                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
1714                         msg = g_strdup (ev_link_action_get_uri (action));
1715                         break;
1716                 case EV_LINK_ACTION_TYPE_LAUNCH:
1717                         msg = g_strdup_printf (_("Launch %s"),
1718                                                ev_link_action_get_filename (action));
1719                         break;
1720                 case EV_LINK_ACTION_TYPE_NAMED:
1721                         msg = tip_from_action_named (action);
1722                         break;
1723                 default:
1724                         if (title)
1725                                 msg = g_strdup (title);
1726                         break;
1727         }
1728         
1729         return msg;
1730 }
1731
1732 static void
1733 ev_view_handle_cursor_over_xy (EvView *view, gint x, gint y)
1734 {
1735         EvLink       *link;
1736         EvFormField  *field;
1737         EvAnnotation *annot = NULL;
1738
1739         if (view->cursor == EV_VIEW_CURSOR_HIDDEN)
1740                 return;
1741
1742         if (view->drag_info.in_drag) {
1743                 if (view->cursor != EV_VIEW_CURSOR_DRAG)
1744                         ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG);
1745                 return;
1746         }
1747
1748         if (view->scroll_info.autoscrolling) {
1749                 if (view->cursor != EV_VIEW_CURSOR_AUTOSCROLL)
1750                         ev_view_set_cursor (view, EV_VIEW_CURSOR_AUTOSCROLL);
1751                 return;
1752         }
1753
1754         link = ev_view_get_link_at_location (view, x, y);
1755         if (link) {
1756                 ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
1757         } else if ((field = ev_view_get_form_field_at_location (view, x, y))) {
1758                 if (field->is_read_only) {
1759                         if (view->cursor == EV_VIEW_CURSOR_LINK ||
1760                             view->cursor == EV_VIEW_CURSOR_IBEAM ||
1761                             view->cursor == EV_VIEW_CURSOR_DRAG)
1762                                 ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
1763                 } else if (EV_IS_FORM_FIELD_TEXT (field)) {
1764                         ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
1765                 } else {
1766                         ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
1767                 }
1768         } else if ((annot = ev_view_get_annotation_at_location (view, x, y))) {
1769                 ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
1770         } else if (location_in_text (view, x + view->scroll_x, y + view->scroll_y)) {
1771                 ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
1772         } else {
1773                 if (view->cursor == EV_VIEW_CURSOR_LINK ||
1774                     view->cursor == EV_VIEW_CURSOR_IBEAM ||
1775                     view->cursor == EV_VIEW_CURSOR_DRAG ||
1776                     view->cursor == EV_VIEW_CURSOR_AUTOSCROLL)
1777                         ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
1778         }
1779
1780         if (link || annot)
1781                 g_object_set (view, "has-tooltip", TRUE, NULL);
1782 }
1783
1784 /*** Images ***/
1785 static EvImage *
1786 ev_view_get_image_at_location (EvView  *view,
1787                                gdouble  x,
1788                                gdouble  y)
1789 {
1790         gint page = -1;
1791         gint x_new = 0, y_new = 0;
1792         GList *image_mapping;
1793
1794         if (!EV_IS_DOCUMENT_IMAGES (view->document))
1795                 return NULL;
1796
1797         if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new))
1798                 return NULL;
1799
1800         image_mapping = ev_pixbuf_cache_get_image_mapping (view->pixbuf_cache, page);
1801
1802         if (image_mapping)
1803                 return ev_mapping_list_get_data (image_mapping, x_new, y_new);
1804         else
1805                 return NULL;
1806 }
1807
1808 /*** Forms ***/
1809 static EvFormField *
1810 ev_view_get_form_field_at_location (EvView  *view,
1811                                     gdouble  x,
1812                                     gdouble  y)
1813 {
1814         gint page = -1;
1815         gint x_new = 0, y_new = 0;
1816         GList *forms_mapping;
1817         
1818         if (!EV_IS_DOCUMENT_FORMS (view->document))
1819                 return NULL;
1820
1821         if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new))
1822                 return NULL;
1823
1824         forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, page);
1825
1826         if (forms_mapping)
1827                 return ev_mapping_list_get_data (forms_mapping, x_new, y_new);
1828         else
1829                 return NULL;
1830 }
1831
1832 static GdkRegion *
1833 ev_view_form_field_get_region (EvView      *view,
1834                                EvFormField *field)
1835 {
1836         GdkRectangle view_area;
1837         GList       *forms_mapping;
1838
1839         forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache,
1840                                                                 field->page->index);
1841         ev_view_get_area_from_mapping (view, field->page->index,
1842                                        forms_mapping,
1843                                        field, &view_area);
1844
1845         return gdk_region_rectangle (&view_area);
1846 }
1847
1848 static gboolean
1849 ev_view_forms_remove_widgets (EvView *view)
1850 {
1851         ev_view_remove_all (view);
1852
1853         return FALSE;
1854 }
1855
1856 static void
1857 ev_view_form_field_destroy (GtkWidget *widget,
1858                             EvView    *view)
1859 {
1860         g_idle_add ((GSourceFunc)ev_view_forms_remove_widgets, view);
1861 }
1862
1863 static GtkWidget *
1864 ev_view_form_field_button_create_widget (EvView      *view,
1865                                          EvFormField *field)
1866 {
1867         EvFormFieldButton *field_button = EV_FORM_FIELD_BUTTON (field);
1868         GdkRegion         *field_region = NULL;
1869         
1870         switch (field_button->type) {
1871                 case EV_FORM_FIELD_BUTTON_PUSH:
1872                         return NULL;
1873                 case EV_FORM_FIELD_BUTTON_CHECK:
1874                 case EV_FORM_FIELD_BUTTON_RADIO: {
1875                         gboolean  state;
1876                         GList    *forms_mapping, *l;
1877
1878                         state = ev_document_forms_form_field_button_get_state (EV_DOCUMENT_FORMS (view->document),
1879                                                                                field);
1880
1881                         /* FIXME: it actually depends on NoToggleToOff flags */
1882                         if (field_button->type == EV_FORM_FIELD_BUTTON_RADIO &&
1883                             state && field_button->state)
1884                                 return NULL;
1885                         
1886                         field_region = ev_view_form_field_get_region (view, field);
1887
1888                         /* For radio buttons and checkbox buttons that are in a set
1889                          * we need to update also the region for the current selected item
1890                          */
1891                         forms_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache,
1892                                                                                 field->page->index);
1893                         for (l = forms_mapping; l; l = g_list_next (l)) {
1894                                 EvFormField *button = ((EvMapping *)(l->data))->data;
1895                                 GdkRegion   *button_region;
1896
1897                                 if (button->id == field->id)
1898                                         continue;
1899
1900                                 /* FIXME: only buttons in the same group should be updated */
1901                                 if (!EV_IS_FORM_FIELD_BUTTON (button) ||
1902                                     EV_FORM_FIELD_BUTTON (button)->type != field_button->type ||
1903                                     EV_FORM_FIELD_BUTTON (button)->state != TRUE)
1904                                         continue;
1905
1906                                 button_region = ev_view_form_field_get_region (view, button);
1907                                 gdk_region_union (field_region, button_region);
1908                                 gdk_region_destroy (button_region);
1909                         }
1910                         
1911                         ev_document_forms_form_field_button_set_state (EV_DOCUMENT_FORMS (view->document),
1912                                                                        field, !state);
1913                         field_button->state = !state;
1914                 }
1915                         break;
1916         }
1917
1918         ev_view_reload_page (view, field->page->index, field_region);
1919         gdk_region_destroy (field_region);
1920         
1921         return NULL;
1922 }
1923
1924 static void
1925 ev_view_form_field_text_save (EvView    *view,
1926                               GtkWidget *widget)
1927 {
1928         EvFormField *field;
1929
1930         if (!view->document)
1931                 return;
1932         
1933         field = g_object_get_data (G_OBJECT (widget), "form-field");
1934         
1935         if (field->changed) {
1936                 EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
1937                 GdkRegion       *field_region;
1938
1939                 field_region = ev_view_form_field_get_region (view, field);
1940                 
1941                 ev_document_forms_form_field_text_set_text (EV_DOCUMENT_FORMS (view->document),
1942                                                             field, field_text->text);
1943                 field->changed = FALSE;
1944                 ev_view_reload_page (view, field->page->index, field_region);
1945                 gdk_region_destroy (field_region);
1946         }
1947 }
1948
1949 static void
1950 ev_view_form_field_text_changed (GtkWidget   *widget,
1951                                  EvFormField *field)
1952 {
1953         EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
1954         gchar           *text = NULL;
1955
1956         if (GTK_IS_ENTRY (widget)) {
1957                 text = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
1958         } else if (GTK_IS_TEXT_BUFFER (widget)) {
1959                 GtkTextIter start, end;
1960
1961                 gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (widget), &start, &end);
1962                 text = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (widget),
1963                                                  &start, &end, FALSE);
1964         }
1965
1966         if (!field_text->text ||
1967             (field_text->text && g_ascii_strcasecmp (field_text->text, text) != 0)) {
1968                 g_free (field_text->text);
1969                 field_text->text = text;
1970                 field->changed = TRUE;
1971         }
1972 }
1973
1974 static GtkWidget *
1975 ev_view_form_field_text_create_widget (EvView      *view,
1976                                        EvFormField *field)
1977 {
1978         EvFormFieldText *field_text = EV_FORM_FIELD_TEXT (field);
1979         GtkWidget       *text = NULL;
1980         gchar           *txt;
1981
1982         txt = ev_document_forms_form_field_text_get_text (EV_DOCUMENT_FORMS (view->document),
1983                                                           field);
1984
1985         switch (field_text->type) {
1986                 case EV_FORM_FIELD_TEXT_FILE_SELECT:
1987                         /* TODO */
1988                 case EV_FORM_FIELD_TEXT_NORMAL:
1989                         text = gtk_entry_new ();
1990                         gtk_entry_set_has_frame (GTK_ENTRY (text), FALSE);
1991                         gtk_entry_set_max_length (GTK_ENTRY (text), field_text->max_len);
1992                         gtk_entry_set_visibility (GTK_ENTRY (text), !field_text->is_password);
1993                         
1994                         if (txt) {
1995                                 gtk_entry_set_text (GTK_ENTRY (text), txt);
1996                                 g_free (txt);
1997                         }
1998
1999                         g_signal_connect (text, "changed",
2000                                           G_CALLBACK (ev_view_form_field_text_changed),
2001                                           field);
2002                         g_signal_connect_after (text, "activate",
2003                                                 G_CALLBACK (ev_view_form_field_destroy),
2004                                                 view);
2005                         break;
2006                 case EV_FORM_FIELD_TEXT_MULTILINE: {
2007                         GtkTextBuffer *buffer;
2008                 
2009                         text = gtk_text_view_new ();
2010                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
2011                         
2012                         if (txt) {
2013                                 gtk_text_buffer_set_text (buffer, txt, -1);
2014                                 g_free (txt);
2015                         }
2016                         
2017                         g_signal_connect (buffer, "changed",
2018                                           G_CALLBACK (ev_view_form_field_text_changed),
2019                                           field);
2020                 }
2021                         break;
2022         }                       
2023
2024         g_object_weak_ref (G_OBJECT (text),
2025                            (GWeakNotify)ev_view_form_field_text_save,
2026                            view);
2027
2028         return text;
2029 }
2030
2031 static void
2032 ev_view_form_field_choice_save (EvView    *view,
2033                                 GtkWidget *widget)
2034 {
2035         EvFormField *field;
2036
2037         if (!view->document)
2038                 return;
2039         
2040         field = g_object_get_data (G_OBJECT (widget), "form-field");
2041
2042         if (field->changed) {
2043                 GList             *l;
2044                 EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
2045                 GdkRegion         *field_region;
2046
2047                 field_region = ev_view_form_field_get_region (view, field);
2048
2049                 if (field_choice->is_editable) {
2050                         ev_document_forms_form_field_choice_set_text (EV_DOCUMENT_FORMS (view->document),
2051                                                                       field, field_choice->text);
2052                 } else {
2053                         ev_document_forms_form_field_choice_unselect_all (EV_DOCUMENT_FORMS (view->document), field);
2054                         for (l = field_choice->selected_items; l; l = g_list_next (l)) {
2055                                 ev_document_forms_form_field_choice_select_item (EV_DOCUMENT_FORMS (view->document),
2056                                                                                  field,
2057                                                                                  GPOINTER_TO_INT (l->data));
2058                         }
2059                 }
2060                 field->changed = FALSE;
2061                 ev_view_reload_page (view, field->page->index, field_region);
2062                 gdk_region_destroy (field_region);
2063         }
2064 }
2065
2066 static void
2067 ev_view_form_field_choice_changed (GtkWidget   *widget,
2068                                    EvFormField *field)
2069 {
2070         EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
2071         
2072         if (GTK_IS_COMBO_BOX (widget)) {
2073                 gint item;
2074                 
2075                 item = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
2076                 if (!field_choice->selected_items ||
2077                     GPOINTER_TO_INT (field_choice->selected_items->data) != item) {
2078                         g_list_free (field_choice->selected_items);
2079                         field_choice->selected_items = NULL;
2080                         field_choice->selected_items = g_list_prepend (field_choice->selected_items,
2081                                                                        GINT_TO_POINTER (item));
2082                         field->changed = TRUE;
2083                 }
2084
2085                 if (GTK_IS_COMBO_BOX_ENTRY (widget)) {
2086                         gchar *text;
2087                         
2088                         text = gtk_combo_box_get_active_text (GTK_COMBO_BOX (widget));
2089                         if (!field_choice->text ||
2090                             (field_choice->text && g_ascii_strcasecmp (field_choice->text, text) != 0)) {
2091                                 g_free (field_choice->text);
2092                                 field_choice->text = text;
2093                                 field->changed = TRUE;
2094                         }
2095                 }
2096         } else if (GTK_IS_TREE_SELECTION (widget)) {
2097                 GtkTreeSelection *selection = GTK_TREE_SELECTION (widget);
2098                 GtkTreeModel     *model;
2099                 GList            *items, *l;
2100                 
2101                 items = gtk_tree_selection_get_selected_rows (selection, &model);
2102                 g_list_free (field_choice->selected_items);
2103                 field_choice->selected_items = NULL;
2104
2105                 for (l = items; l && l->data; l = g_list_next (l)) {
2106                         GtkTreeIter  iter;
2107                         GtkTreePath *path = (GtkTreePath *)l->data;
2108                         gint         item;
2109                         
2110                         gtk_tree_model_get_iter (model, &iter, path);
2111                         gtk_tree_model_get (model, &iter, 1, &item, -1);
2112
2113                         field_choice->selected_items = g_list_prepend (field_choice->selected_items,
2114                                                                        GINT_TO_POINTER (item));
2115
2116                         gtk_tree_path_free (path);
2117                 }
2118
2119                 g_list_free (items);
2120
2121                 field->changed = TRUE;
2122         }
2123 }
2124
2125 static GtkWidget *
2126 ev_view_form_field_choice_create_widget (EvView      *view,
2127                                          EvFormField *field)
2128 {
2129         EvFormFieldChoice *field_choice = EV_FORM_FIELD_CHOICE (field);
2130         GtkWidget         *choice;
2131         GtkTreeModel      *model;
2132         gint               n_items, i;
2133         gint               selected_item = 0;
2134
2135         n_items = ev_document_forms_form_field_choice_get_n_items (EV_DOCUMENT_FORMS (view->document),
2136                                                                    field);
2137         model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT));
2138         for (i = 0; i < n_items; i++) {
2139                 GtkTreeIter iter;
2140                 gchar      *item;
2141
2142                 item = ev_document_forms_form_field_choice_get_item (EV_DOCUMENT_FORMS (view->document),
2143                                                                      field, i);
2144                 if (ev_document_forms_form_field_choice_is_item_selected (
2145                             EV_DOCUMENT_FORMS (view->document), field, i)) {
2146                         selected_item = i;
2147                         /* FIXME: we need a get_selected_items function in poppler */
2148                         field_choice->selected_items = g_list_prepend (field_choice->selected_items,
2149                                                                        GINT_TO_POINTER (i));
2150                 }
2151                 
2152                 if (item) {
2153                         gtk_list_store_append (GTK_LIST_STORE (model), &iter);
2154                         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
2155                                             0, item,
2156                                             1, i,
2157                                             -1);
2158                         g_free (item);
2159                 }
2160         }
2161
2162         if (field_choice->type == EV_FORM_FIELD_CHOICE_LIST) {
2163                 GtkCellRenderer  *renderer;
2164                 GtkWidget        *tree_view;
2165                 GtkTreeSelection *selection;
2166
2167                 tree_view = gtk_tree_view_new_with_model (model);
2168                 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
2169
2170                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
2171                 if (field_choice->multi_select) {
2172                         gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
2173                 }
2174
2175                 /* TODO: set selected items */
2176
2177                 renderer = gtk_cell_renderer_text_new ();
2178                 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
2179                                                              0,
2180                                                              "choix", renderer,
2181                                                              "text", 0,
2182                                                              NULL);
2183
2184                 choice = gtk_scrolled_window_new (NULL, NULL);
2185                 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (choice),
2186                                                 GTK_POLICY_AUTOMATIC,
2187                                                 GTK_POLICY_AUTOMATIC);
2188                 gtk_container_add (GTK_CONTAINER (choice), tree_view);
2189                 gtk_widget_show (tree_view);
2190
2191                 g_signal_connect (selection, "changed",
2192                                   G_CALLBACK (ev_view_form_field_choice_changed),
2193                                   field);
2194                 g_signal_connect_after (selection, "changed",
2195                                         G_CALLBACK (ev_view_form_field_destroy),
2196                                         view);
2197         } else if (field_choice->is_editable) { /* ComboBoxEntry */
2198                 gchar *text;
2199                 
2200                 choice = gtk_combo_box_entry_new_with_model (model, 0);
2201                 text = ev_document_forms_form_field_choice_get_text (EV_DOCUMENT_FORMS (view->document), field);
2202                 if (text) {
2203                         gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (choice))), text);
2204                         g_free (text);
2205                 }
2206
2207                 g_signal_connect (choice, "changed",
2208                                   G_CALLBACK (ev_view_form_field_choice_changed),
2209                                   field);
2210                 g_signal_connect_after (GTK_BIN(choice)->child, "activate",
2211                                         G_CALLBACK (ev_view_form_field_destroy),
2212                                         view);
2213         } else { /* ComboBoxText */
2214                 GtkCellRenderer *renderer;
2215
2216                 choice = gtk_combo_box_new_with_model (model);
2217                 renderer = gtk_cell_renderer_text_new ();
2218                 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (choice),
2219                                             renderer, TRUE);
2220                 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (choice),
2221                                                 renderer,
2222                                                 "text", 0,
2223                                                 NULL);
2224                 gtk_combo_box_set_active (GTK_COMBO_BOX (choice), selected_item);
2225                 gtk_combo_box_popup (GTK_COMBO_BOX (choice));
2226                 
2227                 g_signal_connect (choice, "changed",
2228                                   G_CALLBACK (ev_view_form_field_choice_changed),
2229                                   field);
2230                 g_signal_connect_after (choice, "changed",
2231                                         G_CALLBACK (ev_view_form_field_destroy),
2232                                         view);
2233         }
2234
2235         g_object_unref (model);
2236
2237         g_object_weak_ref (G_OBJECT (choice),
2238                            (GWeakNotify)ev_view_form_field_choice_save,
2239                            view);
2240
2241         return choice;
2242 }
2243
2244 static void
2245 ev_view_handle_form_field (EvView      *view,
2246                            EvFormField *field,
2247                            gdouble      x,
2248                            gdouble      y)
2249 {
2250         GtkWidget   *field_widget = NULL;
2251         GList       *form_field_mapping;
2252         GdkRectangle view_area;
2253
2254         if (field->is_read_only)
2255                 return;
2256         
2257         if (EV_IS_FORM_FIELD_BUTTON (field)) {
2258                 field_widget = ev_view_form_field_button_create_widget (view, field);
2259         } else if (EV_IS_FORM_FIELD_TEXT (field)) {
2260                 field_widget = ev_view_form_field_text_create_widget (view, field);
2261         } else if (EV_IS_FORM_FIELD_CHOICE (field)) {
2262                 field_widget = ev_view_form_field_choice_create_widget (view, field);
2263         } else if (EV_IS_FORM_FIELD_SIGNATURE (field)) {
2264                 /* TODO */
2265         }
2266
2267         /* Form field doesn't require a widget */
2268         if (!field_widget)
2269                 return;
2270
2271         g_object_set_data_full (G_OBJECT (field_widget), "form-field",
2272                                 g_object_ref (field),
2273                                 (GDestroyNotify)g_object_unref);
2274
2275         form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache, field->page->index);
2276         ev_view_get_area_from_mapping (view, field->page->index,
2277                                        form_field_mapping,
2278                                        field, &view_area);
2279
2280         gtk_layout_put (GTK_LAYOUT (view), field_widget, view_area.x, view_area.y);
2281         gtk_widget_show (field_widget);
2282         gtk_widget_grab_focus (field_widget);
2283 }
2284
2285 /* Annotations */
2286 static EvViewWindowChild *
2287 ev_view_get_window_child (EvView    *view,
2288                           GtkWidget *window)
2289 {
2290         GList *children = view->window_children;
2291
2292         while (children) {
2293                 EvViewWindowChild *child;
2294
2295                 child = (EvViewWindowChild *)children->data;
2296                 children = children->next;
2297
2298                 if (child->window == window)
2299                         return child;
2300         }
2301
2302         return NULL;
2303 }
2304
2305 static void
2306 ev_view_window_child_move (EvView            *view,
2307                            EvViewWindowChild *child,
2308                            gint               x,
2309                            gint               y)
2310 {
2311         child->x = x;
2312         child->y = y;
2313         gtk_window_move (GTK_WINDOW (child->window),
2314                          MAX (child->parent_x, x),
2315                          MAX (child->parent_y, y));
2316 }
2317
2318 static void
2319 ev_view_window_child_move_with_parent (EvView    *view,
2320                                        GtkWidget *window)
2321 {
2322         EvViewWindowChild *child;
2323         gint               root_x, root_y;
2324
2325         child = ev_view_get_window_child (view, window);
2326         gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
2327                                &root_x, &root_y);
2328         if (root_x != child->parent_x || root_y != child->parent_y) {
2329                 gint dest_x, dest_y;
2330
2331                 dest_x = child->x + (root_x - child->parent_x);
2332                 dest_y = child->y + (root_y - child->parent_y);
2333                 child->parent_x = root_x;
2334                 child->parent_y = root_y;
2335                 ev_view_window_child_move (view, child, dest_x, dest_y);
2336         }
2337
2338         if (child->visible && !GTK_WIDGET_VISIBLE (window))
2339                 gtk_widget_show (window);
2340 }
2341
2342 static void
2343 ev_view_window_child_put (EvView    *view,
2344                           GtkWidget *window,
2345                           guint      page,
2346                           gint       x,
2347                           gint       y,
2348                           gdouble    orig_x,
2349                           gdouble    orig_y)
2350 {
2351         EvViewWindowChild *child;
2352         gint               root_x, root_y;
2353
2354         gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
2355                                &root_x, &root_y);
2356
2357         child = g_new0 (EvViewWindowChild, 1);
2358         child->window = window;
2359         child->page = page;
2360         child->orig_x = orig_x;
2361         child->orig_y = orig_y;
2362         child->parent_x = root_x;
2363         child->parent_y = root_y;
2364         child->visible = ev_annotation_window_is_open (EV_ANNOTATION_WINDOW (window));
2365         ev_view_window_child_move (view, child, x + root_x, y + root_y);
2366
2367         if (child->visible)
2368                 gtk_widget_show (window);
2369         else
2370                 gtk_widget_hide (window);
2371
2372         view->window_children = g_list_append (view->window_children, child);
2373 }
2374
2375 static EvViewWindowChild *
2376 ev_view_find_window_child_for_annot (EvView       *view,
2377                                      guint         page,
2378                                      EvAnnotation *annot)
2379 {
2380         GList *children = view->window_children;
2381
2382         while (children) {
2383                 EvViewWindowChild *child;
2384                 EvAnnotation      *wannot;
2385
2386                 child = (EvViewWindowChild *)children->data;
2387                 children = children->next;
2388
2389                 if (child->page != page)
2390                         continue;
2391
2392                 wannot = ev_annotation_window_get_annotation (EV_ANNOTATION_WINDOW (child->window));
2393                 if (wannot == annot || strcmp (wannot->name, annot->name) == 0)
2394                         return child;
2395         }
2396
2397         return NULL;
2398 }
2399
2400 static void
2401 ev_view_window_children_free (EvView *view)
2402 {
2403         GList *l;
2404
2405         if (!view->window_children)
2406                 return;
2407
2408         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
2409                 EvViewWindowChild *child;
2410
2411                 child = (EvViewWindowChild *)l->data;
2412                 gtk_widget_destroy (GTK_WIDGET (child->window));
2413                 g_free (child);
2414         }
2415         g_list_free (view->window_children);
2416         view->window_children = NULL;
2417         view->window_child_focus = NULL;
2418 }
2419
2420 static void
2421 annotation_window_grab_focus (GtkWidget *widget,
2422                               EvView    *view)
2423 {
2424         if (view->window_child_focus)
2425                 ev_annotation_window_ungrab_focus (EV_ANNOTATION_WINDOW (view->window_child_focus->window));
2426         view->window_child_focus = ev_view_get_window_child (view, widget);
2427 }
2428
2429 static void
2430 annotation_window_closed (EvAnnotationWindow *window,
2431                           EvView             *view)
2432 {
2433         EvViewWindowChild *child;
2434
2435         child = ev_view_get_window_child (view, GTK_WIDGET (window));
2436         child->visible = FALSE;
2437 }
2438
2439 static void
2440 annotation_window_moved (EvAnnotationWindow *window,
2441                          gint                x,
2442                          gint                y,
2443                          EvView             *view)
2444 {
2445         EvViewWindowChild *child;
2446         GdkRectangle       page_area;
2447         GtkBorder          border;
2448         GdkRectangle       view_rect;
2449         EvRectangle        doc_rect;
2450         gint               width, height;
2451
2452         child = ev_view_get_window_child (view, GTK_WIDGET (window));
2453         if (child->x == x && child->y == y)
2454                 return;
2455
2456         child->moved = TRUE;
2457         child->x = x;
2458         child->y = y;
2459
2460         /* Window has been moved by the user,
2461          * we have to set a new origin in doc coords
2462          */
2463         gtk_window_get_size (GTK_WINDOW (window), &width, &height);
2464         view_rect.x = (x - child->parent_x) + view->scroll_x;
2465         view_rect.y = (y - child->parent_y) + view->scroll_y;
2466         view_rect.width = width;
2467         view_rect.height = height;
2468
2469         get_page_extents (view, child->page, &page_area, &border);
2470         view_rect_to_doc_rect (view, &view_rect, &page_area, &doc_rect);
2471         child->orig_x = doc_rect.x1;
2472         child->orig_y = doc_rect.y1;
2473 }
2474
2475 static void
2476 ev_view_annotation_save (EvView       *view,
2477                          EvAnnotation *annot)
2478 {
2479         if (!view->document)
2480                 return;
2481
2482         if (!annot->changed)
2483                 return;
2484
2485         ev_document_annotations_annotation_set_contents (EV_DOCUMENT_ANNOTATIONS (view->document),
2486                                                          annot, annot->contents);
2487         annot->changed = FALSE;
2488 }
2489
2490 static void
2491 show_annotation_windows (EvView *view,
2492                          gint    page)
2493 {
2494         GList     *annots, *l;
2495         GtkWindow *parent;
2496
2497         parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
2498
2499         annots = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page);
2500
2501         for (l = annots; l && l->data; l = g_list_next (l)) {
2502                 EvAnnotation      *annot;
2503                 EvViewWindowChild *child;
2504                 GtkWidget         *window;
2505                 EvRectangle       *doc_rect;
2506                 GdkRectangle       view_rect;
2507
2508                 annot = ((EvMapping *)(l->data))->data;
2509
2510                 if (!EV_IS_ANNOTATION_MARKUP (annot))
2511                         continue;
2512
2513                 if (!ev_annotation_markup_has_popup (EV_ANNOTATION_MARKUP (annot)))
2514                         continue;
2515
2516                 window = g_object_get_data (G_OBJECT (annot), "popup");
2517                 if (window) {
2518                         ev_view_window_child_move_with_parent (view, window);
2519                         continue;
2520                 }
2521
2522                 /* Look if we already have a popup for this annot */
2523                 child = ev_view_find_window_child_for_annot (view, page, annot);
2524                 window = child ? child->window : NULL;
2525                 if (window) {
2526                         ev_annotation_window_set_annotation (EV_ANNOTATION_WINDOW (window), annot);
2527                         g_object_set_data (G_OBJECT (annot), "popup", window);
2528                         ev_view_window_child_move_with_parent (view, window);
2529                 } else {
2530                         window = ev_annotation_window_new (annot, parent);
2531                         g_signal_connect (window, "grab_focus",
2532                                           G_CALLBACK (annotation_window_grab_focus),
2533                                           view);
2534                         g_signal_connect (window, "closed",
2535                                           G_CALLBACK (annotation_window_closed),
2536                                           view);
2537                         g_signal_connect (window, "moved",
2538                                           G_CALLBACK (annotation_window_moved),
2539                                           view);
2540                         g_object_set_data (G_OBJECT (annot), "popup", window);
2541
2542                         doc_rect = (EvRectangle *)ev_annotation_window_get_rectangle (EV_ANNOTATION_WINDOW (window));
2543                         doc_rect_to_view_rect (view, page, doc_rect, &view_rect);
2544                         view_rect.x -= view->scroll_x;
2545                         view_rect.y -= view->scroll_y;
2546
2547                         ev_view_window_child_put (view, window, page,
2548                                                   view_rect.x, view_rect.y,
2549                                                   doc_rect->x1, doc_rect->y1);
2550
2551                         g_object_weak_ref (G_OBJECT (annot),
2552                                            (GWeakNotify)ev_view_annotation_save,
2553                                            view);
2554                 }
2555         }
2556 }
2557
2558 static void
2559 hide_annotation_windows (EvView *view,
2560                          gint    page)
2561 {
2562         GList *annots, *l;
2563
2564         annots = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page);
2565
2566         for (l = annots; l && l->data; l = g_list_next (l)) {
2567                 EvAnnotation *annot;
2568                 GtkWidget    *window;
2569
2570                 annot = ((EvMapping *)(l->data))->data;
2571
2572                 if (!EV_IS_ANNOTATION_MARKUP (annot))
2573                         continue;
2574
2575                 window = g_object_get_data (G_OBJECT (annot), "popup");
2576                 if (window)
2577                         gtk_widget_hide (window);
2578         }
2579 }
2580
2581 static EvAnnotation *
2582 ev_view_get_annotation_at_location (EvView  *view,
2583                                     gdouble  x,
2584                                     gdouble  y)
2585 {
2586         gint page = -1;
2587         gint x_new = 0, y_new = 0;
2588         GList *annotations_mapping;
2589
2590         if (!EV_IS_DOCUMENT_ANNOTATIONS (view->document))
2591                 return NULL;
2592
2593         if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new))
2594                 return NULL;
2595
2596         annotations_mapping = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page);
2597
2598         if (annotations_mapping)
2599                 return ev_mapping_list_get_data (annotations_mapping, x_new, y_new);
2600         else
2601                 return NULL;
2602 }
2603
2604 static void
2605 ev_view_handle_annotation (EvView       *view,
2606                            EvAnnotation *annot,
2607                            gdouble       x,
2608                            gdouble       y)
2609 {
2610         if (EV_IS_ANNOTATION_MARKUP (annot)) {
2611                 GtkWidget *window;
2612
2613                 window = g_object_get_data (G_OBJECT (annot), "popup");
2614                 if (window) {
2615                         EvViewWindowChild *child;
2616
2617                         child = ev_view_get_window_child (view, window);
2618                         if (!child->visible) {
2619                                 child->visible = TRUE;
2620                                 ev_view_window_child_move (view, child, child->x, child->y);
2621                                 gtk_widget_show (window);
2622                         }
2623                 }
2624         }
2625 }
2626
2627 /*** GtkWidget implementation ***/
2628
2629 static void
2630 ev_view_size_request_continuous_dual_page (EvView         *view,
2631                                            GtkRequisition *requisition)
2632 {
2633         int max_width;
2634         gint n_pages;
2635         GtkBorder border;
2636
2637         ev_view_get_max_page_size (view, &max_width, NULL);
2638         compute_border (view, max_width, max_width, &border);
2639
2640         n_pages = ev_document_get_n_pages (view->document) + 1;
2641
2642         requisition->width = (max_width + border.left + border.right) * 2 + (view->spacing * 3);
2643         get_page_y_offset (view, n_pages, &requisition->height);
2644
2645         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
2646                 requisition->width = 1;
2647         } else if (view->sizing_mode == EV_SIZING_BEST_FIT) {
2648                 requisition->width = 1;
2649                 /* FIXME: This could actually be set on one page docs or docs
2650                  * with a strange aspect ratio. */
2651                 /* requisition->height = 1;*/
2652         }
2653 }
2654
2655 static void
2656 ev_view_size_request_continuous (EvView         *view,
2657                                  GtkRequisition *requisition)
2658 {
2659         int max_width;
2660         int n_pages;
2661         GtkBorder border;
2662
2663         ev_view_get_max_page_size (view, &max_width, NULL);
2664         n_pages = ev_document_get_n_pages (view->document);
2665         compute_border (view, max_width, max_width, &border);
2666
2667         requisition->width = max_width + (view->spacing * 2) + border.left + border.right;
2668         get_page_y_offset (view, n_pages, &requisition->height);
2669
2670         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
2671                 requisition->width = 1;
2672         } else if (view->sizing_mode == EV_SIZING_BEST_FIT) {
2673                 requisition->width = 1;
2674                 /* FIXME: This could actually be set on one page docs or docs
2675                  * with a strange aspect ratio. */
2676                 /* requisition->height = 1;*/
2677         }
2678 }
2679
2680 static void
2681 ev_view_size_request_dual_page (EvView         *view,
2682                                 GtkRequisition *requisition)
2683 {
2684         GtkBorder border;
2685         gint width, height;
2686
2687         /* Find the largest of the two. */
2688         ev_view_get_page_size (view,
2689                                view->current_page,
2690                                &width, &height);
2691         if (view->current_page + 1 < ev_document_get_n_pages (view->document)) {
2692                 gint width_2, height_2;
2693                 ev_view_get_page_size (view,
2694                                        view->current_page + 1,
2695                                        &width_2, &height_2);
2696                 if (width_2 > width) {
2697                         width = width_2;
2698                         height = height_2;
2699                 }
2700         }
2701         compute_border (view, width, height, &border);
2702
2703         requisition->width = ((width + border.left + border.right) * 2) +
2704                 (view->spacing * 3);
2705         requisition->height = (height + border.top + border.bottom) +
2706                 (view->spacing * 2);
2707
2708         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
2709                 requisition->width = 1;
2710         } else if (view->sizing_mode == EV_SIZING_BEST_FIT) {
2711                 requisition->width = 1;
2712                 requisition->height = 1;
2713         }
2714 }
2715
2716 static void
2717 ev_view_size_request_single_page (EvView         *view,
2718                                   GtkRequisition *requisition)
2719 {
2720         GtkBorder border;
2721         gint width, height;
2722
2723         ev_view_get_page_size (view, view->current_page, &width, &height);
2724         compute_border (view, width, height, &border);
2725
2726         requisition->width = width + border.left + border.right + (2 * view->spacing);
2727         requisition->height = height + border.top + border.bottom + (2 * view->spacing);
2728
2729         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
2730                 requisition->width = 1;
2731                 requisition->height = height + border.top + border.bottom + (2 * view->spacing);
2732         } else if (view->sizing_mode == EV_SIZING_BEST_FIT) {
2733                 requisition->width = 1;
2734                 requisition->height = 1;
2735         }
2736 }
2737
2738 static void
2739 ev_view_size_request (GtkWidget      *widget,
2740                       GtkRequisition *requisition)
2741 {
2742         EvView *view = EV_VIEW (widget);
2743         
2744         if (view->document == NULL) {
2745                 requisition->width = 1;
2746                 requisition->height = 1;
2747                 return;
2748         }
2749
2750         if (view->presentation) {
2751                 requisition->width = 1;
2752                 requisition->height = 1;
2753                 return;
2754         }
2755
2756         if (view->continuous && view->dual_page)
2757                 ev_view_size_request_continuous_dual_page (view, requisition);
2758         else if (view->continuous)
2759                 ev_view_size_request_continuous (view, requisition);
2760         else if (view->dual_page)
2761                 ev_view_size_request_dual_page (view, requisition);
2762         else
2763                 ev_view_size_request_single_page (view, requisition);
2764 }
2765
2766 static void
2767 ev_view_size_allocate (GtkWidget      *widget,
2768                        GtkAllocation  *allocation)
2769 {
2770         EvView *view = EV_VIEW (widget);
2771         GList  *children, *l;
2772         gint    root_x, root_y;
2773
2774         GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
2775         
2776         if (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
2777             view->sizing_mode == EV_SIZING_BEST_FIT) {
2778                 ev_view_zoom_for_size (view,
2779                                        allocation->width,
2780                                        allocation->height);
2781                 ev_view_size_request (widget, &widget->requisition);
2782         }
2783         
2784         view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
2785         view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
2786
2787         if (view->document)
2788                 view_update_range_and_current_page (view);
2789
2790         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
2791         view->pending_resize = FALSE;
2792         view->pending_point.x = 0;
2793         view->pending_point.y = 0;
2794
2795         children = gtk_container_get_children (GTK_CONTAINER (widget));
2796         for (l = children; l && l->data; l = g_list_next (l)) {
2797                 EvFormField   *field;
2798                 GdkRectangle   view_area;
2799                 GList         *form_field_mapping;
2800                 GtkAllocation  child_allocation;
2801                 GtkRequisition child_requisition;
2802                 GtkWidget     *child = (GtkWidget *)l->data;
2803                 
2804                 field = g_object_get_data (G_OBJECT (child), "form-field");
2805                 if (!field)
2806                         continue;
2807
2808                 form_field_mapping = ev_pixbuf_cache_get_form_field_mapping (view->pixbuf_cache,
2809                                                                              field->page->index);
2810                 ev_view_get_area_from_mapping (view, field->page->index,
2811                                                form_field_mapping,
2812                                                field, &view_area);
2813
2814                 gtk_widget_size_request (child, &child_requisition);
2815                 if (child_requisition.width != view_area.width ||
2816                     child_requisition.height != view_area.height)
2817                         gtk_widget_set_size_request (child, view_area.width, view_area.height);
2818
2819                 gtk_container_child_get (GTK_CONTAINER (widget),
2820                                          child,
2821                                          "x", &child_allocation.x,
2822                                          "y", &child_allocation.y,
2823                                          NULL);
2824                 if (child_allocation.x != view_area.x ||
2825                     child_allocation.y != view_area.y) {
2826                         gtk_layout_move (GTK_LAYOUT (widget), child, view_area.x, view_area.y);
2827                 }
2828         }
2829         g_list_free (children);
2830
2831         if (view->window_children)
2832                 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
2833                                        &root_x, &root_y);
2834
2835         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
2836                 EvViewWindowChild *child;
2837                 EvRectangle        doc_rect;
2838                 GdkRectangle       view_rect;
2839
2840                 child = (EvViewWindowChild *)l->data;
2841
2842                 doc_rect = *ev_annotation_window_get_rectangle (EV_ANNOTATION_WINDOW (child->window));
2843                 if (child->moved) {
2844                         doc_rect.x1 = child->orig_x;
2845                         doc_rect.y1 = child->orig_y;
2846                 }
2847                 doc_rect_to_view_rect (view, child->page, &doc_rect, &view_rect);
2848                 view_rect.x -= view->scroll_x;
2849                 view_rect.y -= view->scroll_y;
2850
2851                 if (view_rect.x != child->orig_x || view_rect.y != child->orig_y) {
2852                         child->parent_x = root_x;
2853                         child->parent_y = root_y;
2854                         ev_view_window_child_move (view, child, view_rect.x + root_x, view_rect.y + root_y);
2855                 }
2856         }
2857 }
2858
2859 static void
2860 ev_view_realize (GtkWidget *widget)
2861 {
2862         EvView *view = EV_VIEW (widget);
2863
2864         if (GTK_WIDGET_CLASS (ev_view_parent_class)->realize)
2865                 (* GTK_WIDGET_CLASS (ev_view_parent_class)->realize) (widget);
2866
2867         gdk_window_set_events (view->layout.bin_window,
2868                                (gdk_window_get_events (view->layout.bin_window) | 
2869                                 GDK_EXPOSURE_MASK |
2870                                 GDK_BUTTON_PRESS_MASK |
2871                                 GDK_BUTTON_RELEASE_MASK |
2872                                 GDK_SCROLL_MASK |
2873                                 GDK_KEY_PRESS_MASK |
2874                                 GDK_POINTER_MOTION_MASK |
2875                                 GDK_POINTER_MOTION_HINT_MASK |
2876                                 GDK_ENTER_NOTIFY_MASK |
2877                                 GDK_LEAVE_NOTIFY_MASK));
2878
2879         if (view->presentation)
2880                 gdk_window_set_background (view->layout.bin_window, &widget->style->black);
2881         else
2882                 gdk_window_set_background (view->layout.bin_window, &widget->style->mid [GTK_STATE_NORMAL]);
2883
2884         on_adjustment_value_changed (NULL, view);
2885 }
2886
2887 static gboolean
2888 ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event)
2889 {
2890         EvView *view = EV_VIEW (widget);
2891         guint state;
2892
2893         state = event->state & gtk_accelerator_get_default_mod_mask ();
2894
2895         if (state == GDK_CONTROL_MASK && view->presentation == FALSE) {
2896                 ev_view_set_sizing_mode (view, EV_SIZING_FREE);
2897
2898                 if (event->direction == GDK_SCROLL_UP ||
2899                     event->direction == GDK_SCROLL_LEFT) {
2900                         if (ev_view_can_zoom_in (view)) {
2901                                 ev_view_zoom_in (view);
2902                         }
2903                 } else {
2904                         if (ev_view_can_zoom_out (view)) {
2905                                 ev_view_zoom_out (view);
2906                         }
2907                 }
2908
2909                 return TRUE;
2910         }
2911
2912         view->jump_to_find_result = FALSE;
2913
2914         /* Shift+Wheel scrolls the in the perpendicular direction */
2915         if (state & GDK_SHIFT_MASK) {
2916                 if (event->direction == GDK_SCROLL_UP)
2917                         event->direction = GDK_SCROLL_LEFT;
2918                 else if (event->direction == GDK_SCROLL_LEFT)
2919                         event->direction = GDK_SCROLL_UP;
2920                 else if (event->direction == GDK_SCROLL_DOWN)
2921                         event->direction = GDK_SCROLL_RIGHT;
2922                 else if (event->direction == GDK_SCROLL_RIGHT)
2923                         event->direction = GDK_SCROLL_DOWN;
2924
2925                 event->state &= ~GDK_SHIFT_MASK;
2926                 state &= ~GDK_SHIFT_MASK;
2927         }
2928
2929         if (state == 0 &&
2930             (view->presentation ||
2931              (view->sizing_mode == EV_SIZING_BEST_FIT && !view->continuous))) {
2932                 switch (event->direction) {
2933                         case GDK_SCROLL_DOWN:
2934                         case GDK_SCROLL_RIGHT:
2935                                 ev_view_next_page (view);       
2936                                 break;
2937                         case GDK_SCROLL_UP:
2938                         case GDK_SCROLL_LEFT:
2939                                 ev_view_previous_page (view);
2940                                 break;
2941                 }
2942
2943                 return TRUE;
2944         }
2945
2946         return FALSE;
2947 }
2948
2949 static EvViewSelection *
2950 find_selection_for_page (EvView *view,
2951                          gint    page)
2952 {
2953         GList *list;
2954
2955         for (list = view->selection_info.selections; list != NULL; list = list->next) {
2956                 EvViewSelection *selection;
2957
2958                 selection = (EvViewSelection *) list->data;
2959
2960                 if (selection->page == page)
2961                         return selection;
2962         }
2963
2964         return NULL;
2965 }
2966
2967 static void
2968 draw_end_presentation_page (EvView       *view,
2969                             GdkRectangle *page_area)
2970 {
2971         PangoLayout *layout;
2972         PangoFontDescription *font_desc;
2973         gchar *markup;
2974         const gchar *text = _("End of presentation. Press Escape to exit.");
2975
2976         if (view->presentation_state != EV_PRESENTATION_END)
2977                 return;
2978
2979         layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL);
2980         markup = g_strdup_printf ("<span foreground=\"white\">%s</span>", text);
2981         pango_layout_set_markup (layout, markup, -1);
2982         g_free (markup);
2983
2984         font_desc = pango_font_description_new ();
2985         pango_font_description_set_size (font_desc, 16 * PANGO_SCALE);
2986         pango_layout_set_font_description (layout, font_desc);
2987
2988         gtk_paint_layout (GTK_WIDGET (view)->style,
2989                           view->layout.bin_window,
2990                           GTK_WIDGET_STATE (view),
2991                           FALSE,
2992                           page_area,
2993                           GTK_WIDGET (view),
2994                           NULL,
2995                           page_area->x + 15,
2996                           page_area->y + 15,
2997                           layout);
2998
2999         pango_font_description_free (font_desc);
3000         g_object_unref (layout);
3001 }
3002
3003 static gboolean
3004 ev_view_expose_event (GtkWidget      *widget,
3005                       GdkEventExpose *event)
3006 {
3007         EvView  *view = EV_VIEW (widget);
3008         cairo_t *cr;
3009         gint     i;
3010
3011         if (view->animation) {
3012                 if (ev_transition_animation_ready (view->animation)) {
3013                         GdkRectangle page_area;
3014                         GtkBorder    border;
3015
3016                         if (get_page_extents (view, view->current_page, &page_area, &border)) {
3017                                 cr = gdk_cairo_create (view->layout.bin_window);
3018
3019                                 /* normalize to x=0, y=0 */
3020                                 cairo_translate (cr, page_area.x, page_area.y);
3021                                 page_area.x = page_area.y = 0;
3022
3023                                 ev_transition_animation_paint (view->animation, cr, page_area);
3024                                 cairo_destroy (cr);
3025                         }
3026                 }
3027
3028                 return TRUE;
3029         }
3030
3031         if (view->presentation) {
3032                 switch (view->presentation_state) {
3033                         case EV_PRESENTATION_END: {
3034                                 GdkRectangle area = {0};
3035
3036                                 area.width = widget->allocation.width;
3037                                 area.height = widget->allocation.height;
3038                                 
3039                                 draw_end_presentation_page (view, &area);
3040                         }
3041                                 return FALSE;
3042                         case EV_PRESENTATION_BLACK:
3043                         case EV_PRESENTATION_WHITE:
3044                                 return FALSE;
3045                         case EV_PRESENTATION_NORMAL:
3046                         default:
3047                                 break;
3048                 }
3049         } else if (view->loading) {
3050                 GdkRectangle area = {0};
3051                 
3052                 area.width = widget->allocation.width;
3053                 area.height = widget->allocation.height;
3054
3055                 draw_loading_text (view,
3056                                    &area,
3057                                    &(event->area));
3058         }
3059
3060         if (view->document == NULL)
3061                 return FALSE;
3062
3063         cr = gdk_cairo_create (view->layout.bin_window);
3064         
3065         for (i = view->start_page; i >= 0 && i <= view->end_page; i++) {
3066                 GdkRectangle page_area;
3067                 GtkBorder border;
3068                 gboolean page_ready = TRUE;
3069
3070                 if (!get_page_extents (view, i, &page_area, &border))
3071                         continue;
3072
3073                 page_area.x -= view->scroll_x;
3074                 page_area.y -= view->scroll_y;
3075
3076                 draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready);
3077
3078                 if (page_ready && view->find_pages && view->highlight_find_results)
3079                         highlight_find_results (view, i);
3080                 if (page_ready && EV_IS_DOCUMENT_ANNOTATIONS (view->document))
3081                         show_annotation_windows (view, i);
3082         }
3083
3084         cairo_destroy (cr);
3085
3086         if (GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event)
3087                 (* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event);
3088
3089         return FALSE;
3090 }
3091
3092 static gboolean
3093 ev_view_do_popup_menu (EvView *view,
3094                        gdouble x,
3095                        gdouble y)
3096 {
3097         EvLink  *link;
3098         EvImage *image;
3099
3100         image = ev_view_get_image_at_location (view, x, y);
3101         if (image) {
3102                 g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, image);
3103                 return TRUE;
3104         }
3105
3106         link = ev_view_get_link_at_location (view, x, y);
3107         if (link) {
3108                 g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, link);
3109                 return TRUE;
3110         }
3111
3112         g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, NULL);
3113
3114         return TRUE;
3115 }
3116
3117 static gboolean
3118 ev_view_popup_menu (GtkWidget *widget)
3119 {
3120         gint x, y;
3121         
3122         gtk_widget_get_pointer (widget, &x, &y);
3123         return ev_view_do_popup_menu (EV_VIEW (widget), x, y);
3124 }
3125
3126 static void
3127 get_link_area (EvView       *view,
3128                gint          x,
3129                gint          y,
3130                EvLink       *link,
3131                GdkRectangle *area)
3132 {
3133         GList *link_mapping;
3134         gint   page;
3135         gint   x_offset = 0, y_offset = 0;
3136
3137         x += view->scroll_x;
3138         y += view->scroll_y;
3139         
3140         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
3141         
3142         link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page);
3143         ev_view_get_area_from_mapping (view, page,
3144                                        link_mapping,
3145                                        link, area);
3146 }
3147
3148 static void
3149 get_annot_area (EvView       *view,
3150                gint          x,
3151                gint          y,
3152                EvAnnotation *annot,
3153                GdkRectangle *area)
3154 {
3155         GList *annots_mapping;
3156         gint   page;
3157         gint   x_offset = 0, y_offset = 0;
3158
3159         x += view->scroll_x;
3160         y += view->scroll_y;
3161
3162         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
3163
3164         annots_mapping = ev_pixbuf_cache_get_annots_mapping (view->pixbuf_cache, page);
3165         ev_view_get_area_from_mapping (view, page,
3166                                        annots_mapping,
3167                                        annot, area);
3168 }
3169
3170 static gboolean
3171 ev_view_query_tooltip (GtkWidget  *widget,
3172                        gint        x,
3173                        gint        y,
3174                        gboolean    keyboard_tip,
3175                        GtkTooltip *tooltip)
3176 {
3177         EvView       *view = EV_VIEW (widget);
3178         EvLink       *link;
3179         EvAnnotation *annot;
3180         gchar        *text;
3181
3182         annot = ev_view_get_annotation_at_location (view, x, y);
3183         if (annot && annot->contents) {
3184                 GdkRectangle annot_area;
3185
3186                 get_annot_area (view, x, y, annot, &annot_area);
3187                 gtk_tooltip_set_text (tooltip, annot->contents);
3188                 gtk_tooltip_set_tip_area (tooltip, &annot_area);
3189
3190                 return TRUE;
3191         }
3192
3193         link = ev_view_get_link_at_location (view, x, y);
3194         if (!link)
3195                 return FALSE;
3196
3197         text = tip_from_link (view, link);
3198         if (text && g_utf8_validate (text, -1, NULL)) {
3199                 GdkRectangle link_area;
3200
3201                 get_link_area (view, x, y, link, &link_area);
3202                 gtk_tooltip_set_text (tooltip, text);
3203                 gtk_tooltip_set_tip_area (tooltip, &link_area);
3204         }
3205         g_free (text);
3206
3207         return TRUE;
3208 }
3209
3210 static void
3211 start_selection_for_event (EvView         *view,
3212                            GdkEventButton *event)
3213 {
3214         clear_selection (view);
3215
3216         view->selection_info.start.x = event->x + view->scroll_x;
3217         view->selection_info.start.y = event->y + view->scroll_y;
3218
3219         switch (event->type) {
3220                 case GDK_2BUTTON_PRESS:
3221                         view->selection_info.style = EV_SELECTION_STYLE_WORD;
3222                         break;
3223                 case GDK_3BUTTON_PRESS:
3224                         view->selection_info.style = EV_SELECTION_STYLE_LINE;
3225                         break;
3226                 default:
3227                         view->selection_info.style = EV_SELECTION_STYLE_GLYPH;
3228                         return;
3229         }
3230
3231         /* In case of WORD or LINE, compute selections now */
3232         compute_selections (view,
3233                             view->selection_info.style,
3234                             &(view->selection_info.start),
3235                             &(view->selection_info.start));
3236 }
3237
3238 static gboolean
3239 ev_view_button_press_event (GtkWidget      *widget,
3240                             GdkEventButton *event)
3241 {
3242         EvView *view = EV_VIEW (widget);
3243
3244         if (!view->document)
3245                 return FALSE;
3246         
3247         if (!GTK_WIDGET_HAS_FOCUS (widget)) {
3248                 gtk_widget_grab_focus (widget);
3249         }
3250
3251         if (view->window_child_focus) {
3252                 EvAnnotationWindow *window;
3253                 EvAnnotation       *annot;
3254
3255                 window = EV_ANNOTATION_WINDOW (view->window_child_focus->window);
3256                 annot = ev_annotation_window_get_annotation (window);
3257                 ev_annotation_window_ungrab_focus (window);
3258                 ev_view_annotation_save (view, annot);
3259                 view->window_child_focus = NULL;
3260         }
3261         
3262         view->pressed_button = event->button;
3263         view->selection_info.in_drag = FALSE;
3264
3265         if (view->scroll_info.autoscrolling)
3266                 return TRUE;
3267         
3268         switch (event->button) {
3269                 case 1: {
3270                         EvImage *image;
3271                         EvAnnotation *annot;
3272                         EvFormField *field;
3273
3274                         if (EV_IS_SELECTION (view->document) && view->selection_info.selections) {
3275                                 if (event->type == GDK_3BUTTON_PRESS) {
3276                                         start_selection_for_event (view, event);
3277                                 } else if (location_in_selected_text (view,
3278                                                                event->x + view->scroll_x,
3279                                                                event->y + view->scroll_y)) {
3280                                         view->selection_info.in_drag = TRUE;
3281                                 } else {
3282                                         start_selection_for_event (view, event);
3283                                 }
3284
3285                                 gtk_widget_queue_draw (widget);
3286                         } else if ((annot = ev_view_get_annotation_at_location (view, event->x, event->y))) {
3287                                 ev_view_handle_annotation (view, annot, event->x, event->y);
3288                         } else if ((field = ev_view_get_form_field_at_location (view, event->x, event->y))) {
3289                                 ev_view_remove_all (view);
3290                                 ev_view_handle_form_field (view, field, event->x, event->y);
3291                         } else if (!location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y) &&
3292                                    (image = ev_view_get_image_at_location (view, event->x, event->y))) {
3293                                 if (view->image_dnd_info.image)
3294                                         g_object_unref (view->image_dnd_info.image);
3295                                 view->image_dnd_info.image = g_object_ref (image);
3296                                 view->image_dnd_info.in_drag = TRUE;
3297
3298                                 view->image_dnd_info.start.x = event->x + view->scroll_x;
3299                                 view->image_dnd_info.start.y = event->y + view->scroll_y;
3300                         } else {
3301                                 ev_view_remove_all (view);
3302                                 
3303                                 if (EV_IS_SELECTION (view->document))
3304                                         start_selection_for_event (view, event);
3305                         }
3306                 }                       
3307                         return TRUE;
3308                 case 2:
3309                         /* use root coordinates as reference point because
3310                          * scrolling changes window relative coordinates */
3311                         view->drag_info.start.x = event->x_root;
3312                         view->drag_info.start.y = event->y_root;
3313                         view->drag_info.hadj = gtk_adjustment_get_value (view->hadjustment);
3314                         view->drag_info.vadj = gtk_adjustment_get_value (view->vadjustment);
3315
3316                         ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG);
3317
3318                         return TRUE;
3319                 case 3:
3320                         view->scroll_info.start_y = event->y;
3321                         return ev_view_do_popup_menu (view, event->x, event->y);
3322         }
3323         
3324         return FALSE;
3325 }
3326
3327 static void
3328 ev_view_remove_all (EvView *view)
3329 {
3330         GList *children, *child;
3331
3332         children = gtk_container_get_children (GTK_CONTAINER (view));
3333         for (child = children; child && child->data; child = g_list_next (child)) {
3334                 gtk_container_remove (GTK_CONTAINER (view),
3335                                       GTK_WIDGET (child->data));
3336         }
3337         g_list_free (children);
3338 }
3339
3340 /*** Drag and Drop ***/
3341 static void
3342 ev_view_drag_data_get (GtkWidget        *widget,
3343                        GdkDragContext   *context,
3344                        GtkSelectionData *selection_data,
3345                        guint             info,
3346                        guint             time)
3347 {
3348         EvView *view = EV_VIEW (widget);
3349
3350         switch (info) {
3351                 case TARGET_DND_TEXT:
3352                         if (EV_IS_SELECTION (view->document) &&
3353                             view->selection_info.selections) {
3354                                 gchar *text;
3355
3356                                 text = get_selected_text (view);
3357                                 gtk_selection_data_set_text (selection_data,
3358                                                              text,
3359                                                              strlen (text));
3360                                 g_free (text);
3361                         }
3362                         break;
3363                 case TARGET_DND_IMAGE:
3364                         if (view->image_dnd_info.image) {
3365                                 GdkPixbuf *pixbuf;
3366
3367                                 ev_document_doc_mutex_lock ();
3368                                 pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document),
3369                                                                        view->image_dnd_info.image);
3370                                 ev_document_doc_mutex_unlock ();
3371                                 
3372                                 gtk_selection_data_set_pixbuf (selection_data, pixbuf);
3373                                 g_object_unref (pixbuf);
3374                         }
3375                         break;
3376                 case TARGET_DND_URI:
3377                         if (view->image_dnd_info.image) {
3378                                 GdkPixbuf   *pixbuf;
3379                                 const gchar *tmp_uri;
3380                                 gchar       *uris[2];
3381
3382                                 ev_document_doc_mutex_lock ();
3383                                 pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document),
3384                                                                        view->image_dnd_info.image);
3385                                 ev_document_doc_mutex_unlock ();
3386                                 
3387                                 tmp_uri = ev_image_save_tmp (view->image_dnd_info.image, pixbuf);
3388                                 g_object_unref (pixbuf);
3389
3390                                 uris[0] = (gchar *)tmp_uri;
3391                                 uris[1] = NULL;
3392                                 gtk_selection_data_set_uris (selection_data, uris);
3393                         }
3394         }
3395 }
3396
3397 static gboolean
3398 ev_view_drag_motion (GtkWidget      *widget,
3399                      GdkDragContext *context,
3400                      gint            x,
3401                      gint            y,
3402                      guint           time)
3403 {
3404         if (gtk_drag_get_source_widget (context) == widget)
3405                 gdk_drag_status (context, 0, time);
3406         else
3407                 gdk_drag_status (context, context->suggested_action, time);
3408         
3409         return TRUE;
3410 }
3411                      
3412 static gboolean
3413 selection_update_idle_cb (EvView *view)
3414 {
3415         compute_selections (view,
3416                             view->selection_info.style,
3417                             &view->selection_info.start,
3418                             &view->motion);
3419         view->selection_update_id = 0;
3420         return FALSE;
3421 }
3422
3423 static gboolean
3424 selection_scroll_timeout_cb (EvView *view)
3425 {       
3426         gint x, y, shift = 0;
3427         GtkWidget *widget = GTK_WIDGET (view);
3428         
3429         gtk_widget_get_pointer (widget, &x, &y);
3430
3431         if (y > widget->allocation.height) {
3432                 shift = (y - widget->allocation.height) / 2;
3433         } else if (y < 0) {
3434                 shift = y / 2;
3435         }
3436
3437         if (shift)
3438                 gtk_adjustment_set_value (view->vadjustment,
3439                                           CLAMP (view->vadjustment->value + shift,
3440                                           view->vadjustment->lower,
3441                                           view->vadjustment->upper -
3442                                           view->vadjustment->page_size));       
3443
3444         if (x > widget->allocation.width) {
3445                 shift = (x - widget->allocation.width) / 2;
3446         } else if (x < 0) {
3447                 shift = x / 2;
3448         }
3449
3450         if (shift)
3451                 gtk_adjustment_set_value (view->hadjustment,
3452                                           CLAMP (view->hadjustment->value + shift,
3453                                           view->hadjustment->lower,
3454                                           view->hadjustment->upper -
3455                                           view->hadjustment->page_size));       
3456
3457         return TRUE;
3458 }
3459
3460 static gboolean
3461 ev_view_drag_update_momentum (EvView *view)
3462 {
3463         int i;
3464         if (!view->drag_info.in_drag)
3465                 return FALSE;
3466         
3467         for (i = DRAG_HISTORY - 1; i > 0; i--) {
3468                 view->drag_info.buffer[i].x = view->drag_info.buffer[i-1].x;
3469                 view->drag_info.buffer[i].y = view->drag_info.buffer[i-1].y;
3470         }
3471
3472         /* Momentum is a moving average of 10ms granularity over
3473          * the last 100ms with each 10ms stored in buffer. 
3474          */
3475         
3476         view->drag_info.momentum.x = (view->drag_info.buffer[DRAG_HISTORY - 1].x - view->drag_info.buffer[0].x);
3477         view->drag_info.momentum.y = (view->drag_info.buffer[DRAG_HISTORY - 1].y - view->drag_info.buffer[0].y);
3478
3479         return TRUE;
3480 }
3481
3482 static gboolean
3483 ev_view_scroll_drag_release (EvView *view)
3484 {
3485         gdouble dhadj_value, dvadj_value;
3486         gdouble oldhadjustment, oldvadjustment;
3487
3488         view->drag_info.momentum.x /= 1.2;
3489         view->drag_info.momentum.y /= 1.2; /* Alter these constants to change "friction" */
3490
3491         dhadj_value = view->hadjustment->page_size *
3492                       (gdouble)view->drag_info.momentum.x / GTK_WIDGET (view)->allocation.width;
3493         dvadj_value = view->vadjustment->page_size *
3494                       (gdouble)view->drag_info.momentum.y / GTK_WIDGET (view)->allocation.height;
3495
3496         oldhadjustment = gtk_adjustment_get_value (view->hadjustment);
3497         oldvadjustment = gtk_adjustment_get_value (view->vadjustment);
3498
3499      /* When we reach the edges, we need either to absorb some momentum and bounce by
3500       * multiplying it on -0.5 or stop scrolling by setting momentum to 0. */   
3501      if (((oldhadjustment + dhadj_value) > (view->hadjustment->upper - view->hadjustment->page_size)) ||
3502            ((oldhadjustment + dhadj_value) < 0))
3503                 view->drag_info.momentum.x = 0;
3504         if (((oldvadjustment + dvadj_value) > (view->vadjustment->upper - view->vadjustment->page_size)) ||
3505            ((oldvadjustment + dvadj_value) < 0))
3506                 view->drag_info.momentum.y = 0;
3507
3508         gtk_adjustment_set_value (view->hadjustment,
3509                                 MIN (oldhadjustment + dhadj_value,
3510                                 view->hadjustment->upper - view->hadjustment->page_size));
3511         gtk_adjustment_set_value (view->vadjustment,
3512                                 MIN (oldvadjustment + dvadj_value,
3513                                 view->vadjustment->upper - view->vadjustment->page_size));
3514
3515         if (((view->drag_info.momentum.x < 1) && (view->drag_info.momentum.x > -1)) &&
3516            ((view->drag_info.momentum.y < 1) && (view->drag_info.momentum.y > -1)))
3517                 return FALSE;
3518         else
3519                 return TRUE;
3520 }
3521
3522 static gboolean
3523 ev_view_motion_notify_event (GtkWidget      *widget,
3524                              GdkEventMotion *event)
3525 {
3526         EvView *view = EV_VIEW (widget);
3527         gint x, y;
3528
3529         if (!view->document)
3530                 return FALSE;
3531         
3532                 
3533         if (event->is_hint || event->window != view->layout.bin_window) {
3534             gtk_widget_get_pointer (widget, &x, &y);
3535         } else {
3536             x = event->x;
3537             y = event->y;
3538         }
3539
3540         if (view->scroll_info.autoscrolling) {
3541                 view->scroll_info.last_y = y;
3542                 return TRUE;
3543         }
3544
3545         if (view->selection_info.in_drag) {
3546                 if (gtk_drag_check_threshold (widget,
3547                                               view->selection_info.start.x,
3548                                               view->selection_info.start.y,
3549                                               x, y)) {
3550                         GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
3551
3552                         gtk_target_list_add_text_targets (target_list, TARGET_DND_TEXT);
3553
3554                         gtk_drag_begin (widget, target_list,
3555                                         GDK_ACTION_COPY,
3556                                         1, (GdkEvent *)event);
3557
3558                         view->selection_info.in_drag = FALSE;
3559
3560                         gtk_target_list_unref (target_list);
3561
3562                         return TRUE;
3563                 }
3564         } else if (view->image_dnd_info.in_drag) {
3565                 if (gtk_drag_check_threshold (widget,
3566                                               view->selection_info.start.x,
3567                                               view->selection_info.start.y,
3568                                               x, y)) {
3569                         GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
3570
3571                         gtk_target_list_add_uri_targets (target_list, TARGET_DND_URI);
3572                         gtk_target_list_add_image_targets (target_list, TARGET_DND_IMAGE, TRUE);
3573
3574                         gtk_drag_begin (widget, target_list,
3575                                         GDK_ACTION_COPY,
3576                                         1, (GdkEvent *)event);
3577
3578                         view->image_dnd_info.in_drag = FALSE;
3579
3580                         gtk_target_list_unref (target_list);
3581
3582                         return TRUE;
3583                 }
3584         }
3585         
3586         switch (view->pressed_button) {
3587         case 1:
3588                 /* For the Evince 0.4.x release, we limit selection to un-rotated
3589                  * documents only.
3590                  */
3591                 if (view->rotation != 0)
3592                         return FALSE;
3593
3594                 /* Schedule timeout to scroll during selection and additionally 
3595                  * scroll once to allow arbitrary speed. */
3596                 if (!view->selection_scroll_id)
3597                     view->selection_scroll_id = g_timeout_add (SCROLL_TIME,
3598                                                                (GSourceFunc)selection_scroll_timeout_cb,
3599                                                                view);
3600                 else 
3601                     selection_scroll_timeout_cb (view);
3602
3603                 view->selection_info.in_selection = TRUE;
3604                 view->motion.x = x + view->scroll_x;
3605                 view->motion.y = y + view->scroll_y;
3606
3607                 /* Queue an idle to handle the motion.  We do this because      
3608                  * handling any selection events in the motion could be slower  
3609                  * than new motion events reach us.  We always put it in the    
3610                  * idle to make sure we catch up and don't visibly lag the      
3611                  * mouse. */
3612                 if (!view->selection_update_id)
3613                         view->selection_update_id = g_idle_add ((GSourceFunc)selection_update_idle_cb, view);
3614
3615                 return TRUE;
3616         case 2:
3617                 if (!view->drag_info.in_drag) {
3618                         gboolean start;
3619                         int i;
3620
3621                         start = gtk_drag_check_threshold (widget,
3622                                                           view->drag_info.start.x,
3623                                                           view->drag_info.start.y,
3624                                                           event->x_root,
3625                                                           event->y_root);
3626                         view->drag_info.in_drag = start;
3627                         view->drag_info.drag_timeout_id = g_timeout_add (10,
3628                                 (GSourceFunc)ev_view_drag_update_momentum, view);
3629                         /* Set 100 to choose how long it takes to build up momentum */
3630                         /* Clear out previous momentum info: */
3631                         for (i = 0; i < DRAG_HISTORY; i++) {
3632                                 view->drag_info.buffer[i].x = event->x;
3633                                 view->drag_info.buffer[i].y = event->y;
3634                         }
3635                         view->drag_info.momentum.x = 0;
3636                         view->drag_info.momentum.y = 0;
3637                 }
3638
3639                 if (view->drag_info.in_drag) {
3640                         int dx, dy;
3641                         gdouble dhadj_value, dvadj_value;
3642
3643                         view->drag_info.buffer[0].x = event->x;
3644                         view->drag_info.buffer[0].y = event->y;
3645
3646                         dx = event->x_root - view->drag_info.start.x;
3647                         dy = event->y_root - view->drag_info.start.y;
3648
3649                         dhadj_value = view->hadjustment->page_size *
3650                                       (gdouble)dx / widget->allocation.width;
3651                         dvadj_value = view->vadjustment->page_size *
3652                                       (gdouble)dy / widget->allocation.height;
3653
3654                         /* clamp scrolling to visible area */
3655                         gtk_adjustment_set_value (view->hadjustment,
3656                                                   MIN(view->drag_info.hadj - dhadj_value,
3657                                                       view->hadjustment->upper -
3658                                                       view->hadjustment->page_size));
3659                         gtk_adjustment_set_value (view->vadjustment,
3660                                                   MIN(view->drag_info.vadj - dvadj_value,
3661                                                       view->vadjustment->upper -
3662                                                       view->vadjustment->page_size));
3663
3664                         return TRUE;
3665                 }
3666
3667                 break;
3668         default:
3669                 ev_view_handle_cursor_over_xy (view, x, y);
3670         } 
3671
3672         return FALSE;
3673 }
3674
3675 static gboolean
3676 ev_view_button_release_event (GtkWidget      *widget,
3677                               GdkEventButton *event)
3678 {
3679         EvView *view = EV_VIEW (widget);
3680         EvLink *link = NULL;
3681
3682         view->image_dnd_info.in_drag = FALSE;
3683
3684         if (view->scroll_info.autoscrolling) {
3685                 ev_view_autoscroll_stop (view);
3686                 view->pressed_button = -1;
3687
3688                 return TRUE;
3689         } 
3690
3691         if (view->drag_info.in_drag) {
3692                 view->drag_info.release_timeout_id =
3693                         g_timeout_add (20,
3694                                        (GSourceFunc)ev_view_scroll_drag_release, view);
3695         }
3696
3697         if (view->document && !view->drag_info.in_drag && view->pressed_button != 3) {
3698                 link = ev_view_get_link_at_location (view, event->x, event->y);
3699         }
3700         
3701         view->drag_info.in_drag = FALSE;
3702
3703         if (view->pressed_button == 2) {
3704                 ev_view_handle_cursor_over_xy (view, event->x, event->y);
3705         }
3706
3707         view->pressed_button = -1;
3708
3709         if (view->selection_scroll_id) {
3710             g_source_remove (view->selection_scroll_id);
3711             view->selection_scroll_id = 0;
3712         }
3713         if (view->selection_update_id) {
3714             g_source_remove (view->selection_update_id);
3715             view->selection_update_id = 0;
3716         }
3717
3718         if (view->selection_info.selections) {
3719                 clear_link_selected (view);
3720                 ev_view_update_primary_selection (view);
3721                 
3722                 if (view->selection_info.in_drag) {
3723                         clear_selection (view);
3724                         gtk_widget_queue_draw (widget);
3725                 }
3726                 
3727                 view->selection_info.in_drag = FALSE;
3728         } else if (link) {
3729                 if (event->button == 2) {
3730                         EvLinkAction    *action;
3731                         EvLinkActionType type;
3732
3733                         action = ev_link_get_action (link);
3734                         if (!action)
3735                                 return FALSE;
3736
3737                         type = ev_link_action_get_action_type (action);
3738                         if (type == EV_LINK_ACTION_TYPE_GOTO_DEST) {
3739                                 g_signal_emit (view,
3740                                                signals[SIGNAL_EXTERNAL_LINK],
3741                                                0, action);
3742                         }
3743                 } else {
3744                         ev_view_handle_link (view, link);
3745                 }
3746         } else if (view->presentation) {
3747                 switch (event->button) {
3748                         case 1:
3749                                 ev_view_next_page (view);       
3750                                 return TRUE;
3751                         case 3:
3752                                 ev_view_previous_page (view);   
3753                                 return TRUE;
3754                 }
3755         }
3756  
3757         return FALSE;
3758 }
3759
3760 /* Goto Window */
3761 /* Cut and paste from gtkwindow.c */
3762 static void
3763 send_focus_change (GtkWidget *widget,
3764                    gboolean   in)
3765 {
3766         GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
3767
3768         g_object_ref (widget);
3769
3770         if (in)
3771                 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
3772         else
3773                 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
3774
3775         fevent->focus_change.type = GDK_FOCUS_CHANGE;
3776         fevent->focus_change.window = g_object_ref (widget->window);
3777         fevent->focus_change.in = in;
3778
3779         gtk_widget_event (widget, fevent);
3780
3781         g_object_notify (G_OBJECT (widget), "has-focus");
3782
3783         g_object_unref (widget);
3784         gdk_event_free (fevent);
3785 }
3786
3787 static void
3788 ev_view_goto_window_hide (EvView *view)
3789 {
3790         /* send focus-in event */
3791         send_focus_change (view->goto_entry, FALSE);
3792         gtk_widget_hide (view->goto_window);
3793         gtk_entry_set_text (GTK_ENTRY (view->goto_entry), "");
3794 }
3795
3796 static gboolean
3797 ev_view_goto_window_delete_event (GtkWidget   *widget,
3798                                   GdkEventAny *event,
3799                                   EvView      *view)
3800 {
3801         ev_view_goto_window_hide (view);
3802
3803         return TRUE;
3804 }
3805
3806 static gboolean
3807 key_is_numeric (guint keyval)
3808 {
3809         return ((keyval >= GDK_0 && keyval <= GDK_9) ||
3810                 (keyval >= GDK_KP_0 && keyval <= GDK_KP_9));
3811 }
3812
3813 static gboolean
3814 ev_view_goto_window_key_press_event (GtkWidget   *widget,
3815                                      GdkEventKey *event,
3816                                      EvView      *view)
3817 {
3818         switch (event->keyval) {
3819                 case GDK_Escape:
3820                 case GDK_Tab:
3821                 case GDK_KP_Tab:
3822                 case GDK_ISO_Left_Tab:
3823                         ev_view_goto_window_hide (view);
3824                         return TRUE;
3825                 case GDK_Return:
3826                 case GDK_KP_Enter:
3827                 case GDK_ISO_Enter:
3828                 case GDK_BackSpace:
3829                 case GDK_Delete:
3830                         return FALSE;
3831                 default:
3832                         if (!key_is_numeric (event->keyval))
3833                                 return TRUE;
3834         }
3835
3836         return FALSE;
3837 }
3838
3839 static gboolean
3840 ev_view_goto_window_button_press_event (GtkWidget      *widget,
3841                                         GdkEventButton *event,
3842                                         EvView         *view)
3843 {
3844         ev_view_goto_window_hide (view);
3845
3846         return TRUE;
3847 }
3848
3849 static void
3850 ev_view_goto_entry_activate (GtkEntry *entry,
3851                              EvView   *view)
3852 {
3853         const gchar *text;
3854         gint         page;
3855
3856         text = gtk_entry_get_text (entry);
3857         page = atoi (text) - 1;
3858         
3859         ev_view_goto_window_hide (view);
3860
3861         if (page >= 0 && page < ev_document_get_n_pages (view->document)) {
3862                 ev_document_model_set_page (view->model, page);
3863         }
3864 }
3865
3866 static void
3867 ev_view_goto_window_create (EvView *view)
3868 {
3869         GtkWidget *frame, *hbox, *toplevel, *label;
3870
3871         toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
3872         
3873         if (view->goto_window) {
3874                 if (GTK_WINDOW (toplevel)->group)
3875                         gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
3876                                                      GTK_WINDOW (view->goto_window));
3877                 else if (GTK_WINDOW (view->goto_window)->group)
3878                         gtk_window_group_remove_window (GTK_WINDOW (view->goto_window)->group,
3879                                                         GTK_WINDOW (view->goto_window));
3880                 return;
3881         }
3882
3883         view->goto_window = gtk_window_new (GTK_WINDOW_POPUP);
3884         gtk_window_set_screen (GTK_WINDOW (view->goto_window),
3885                                gtk_widget_get_screen (GTK_WIDGET (view)));
3886
3887         if (GTK_WINDOW (toplevel)->group)
3888                 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
3889                                              GTK_WINDOW (view->goto_window));
3890         
3891         gtk_window_set_modal (GTK_WINDOW (view->goto_window), TRUE);
3892
3893         g_signal_connect (view->goto_window, "delete_event",
3894                           G_CALLBACK (ev_view_goto_window_delete_event),
3895                           view);
3896         g_signal_connect (view->goto_window, "key_press_event",
3897                           G_CALLBACK (ev_view_goto_window_key_press_event),
3898                           view);
3899         g_signal_connect (view->goto_window, "button_press_event",
3900                           G_CALLBACK (ev_view_goto_window_button_press_event),
3901                           view);
3902
3903         frame = gtk_frame_new (NULL);
3904         gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
3905         gtk_container_add (GTK_CONTAINER (view->goto_window), frame);
3906         gtk_widget_show (frame);
3907
3908         hbox = gtk_hbox_new (FALSE, 0);
3909         gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
3910         gtk_container_add (GTK_CONTAINER (frame), hbox);
3911         gtk_widget_show (hbox);
3912
3913         label = gtk_label_new(_("Jump to page:"));
3914         gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 3);
3915         gtk_widget_show (label);
3916         gtk_widget_realize (label);
3917
3918         view->goto_entry = gtk_entry_new ();
3919         g_signal_connect (view->goto_entry, "activate",
3920                           G_CALLBACK (ev_view_goto_entry_activate),
3921                           view);
3922         gtk_box_pack_start (GTK_BOX (hbox), view->goto_entry, TRUE, TRUE, 0);
3923         gtk_widget_show (view->goto_entry);
3924         gtk_widget_realize (view->goto_entry);
3925 }
3926
3927 static void
3928 ev_view_goto_entry_grab_focus (EvView *view)
3929 {
3930         GtkWidgetClass *entry_parent_class;
3931         
3932         entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (view->goto_entry));
3933         (entry_parent_class->grab_focus) (view->goto_entry);
3934
3935         send_focus_change (view->goto_entry, TRUE);
3936 }
3937
3938 static void
3939 ev_view_goto_window_send_key_event (EvView   *view,
3940                                     GdkEvent *event)
3941 {
3942         GdkEventKey *new_event;
3943         GdkScreen   *screen;
3944
3945         /* Move goto window off screen */
3946         screen = gtk_widget_get_screen (GTK_WIDGET (view));
3947         gtk_window_move (GTK_WINDOW (view->goto_window),
3948                          gdk_screen_get_width (screen) + 1,
3949                          gdk_screen_get_height (screen) + 1);
3950         gtk_widget_show (view->goto_window);
3951
3952         new_event = (GdkEventKey *) gdk_event_copy (event);
3953         g_object_unref (new_event->window);
3954         new_event->window = g_object_ref (view->goto_window->window);
3955         gtk_widget_realize (view->goto_window);
3956
3957         gtk_widget_event (view->goto_window, (GdkEvent *)new_event);
3958         gdk_event_free ((GdkEvent *)new_event);
3959         gtk_widget_hide (view->goto_window);
3960 }
3961
3962 static gboolean
3963 ev_view_key_press_event (GtkWidget   *widget,
3964                          GdkEventKey *event)
3965 {
3966         EvView *view = EV_VIEW (widget);
3967         EvPresentationState current;
3968
3969         if (!view->document)
3970                 return FALSE;
3971
3972         if (!GTK_WIDGET_HAS_FOCUS (widget)) {
3973                 /* Forward key events to current focused window child */
3974                 if (view->window_child_focus) {
3975                         GdkEventKey *new_event;
3976                         gboolean     handled;
3977
3978                         new_event = (GdkEventKey *) gdk_event_copy ((GdkEvent *)event);
3979                         g_object_unref (new_event->window);
3980                         new_event->window = g_object_ref (view->window_child_focus->window->window);
3981                         gtk_widget_realize (view->window_child_focus->window);
3982                         handled = gtk_widget_event (view->window_child_focus->window, (GdkEvent *)new_event);
3983                         gdk_event_free ((GdkEvent *)new_event);
3984
3985                         return handled;
3986                 }
3987
3988                 return FALSE;
3989         }
3990
3991         if (!view->presentation ||
3992             view->presentation_state == EV_PRESENTATION_END)
3993                 return gtk_bindings_activate_event (GTK_OBJECT (widget), event);
3994
3995
3996         current = view->presentation_state;
3997
3998         switch (event->keyval) {
3999                 case GDK_b:
4000                 case GDK_B:
4001                 case GDK_period:
4002                 case GDK_KP_Decimal:
4003                         view->presentation_state =
4004                                 (view->presentation_state == EV_PRESENTATION_BLACK) ?
4005                                 EV_PRESENTATION_NORMAL : EV_PRESENTATION_BLACK;
4006                         break;
4007                 case GDK_w:
4008                 case GDK_W:
4009                         view->presentation_state =
4010                                 (view->presentation_state == EV_PRESENTATION_WHITE) ?
4011                                 EV_PRESENTATION_NORMAL : EV_PRESENTATION_WHITE;
4012                         break;
4013                 default:
4014                         if (view->presentation_state == EV_PRESENTATION_BLACK ||
4015                             view->presentation_state == EV_PRESENTATION_WHITE) {
4016                                 view->presentation_state = EV_PRESENTATION_NORMAL;
4017                         }
4018         }
4019
4020         if (current == view->presentation_state) {
4021                 if (ev_document_get_n_pages (view->document) > 1 &&
4022                     key_is_numeric (event->keyval)) {
4023                         gint x, y;
4024                         
4025                         ev_view_goto_window_create (view);
4026                         ev_view_goto_window_send_key_event (view, (GdkEvent *)event);
4027                         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4028                         gtk_window_move (GTK_WINDOW (view->goto_window), x, y);
4029                         gtk_widget_show (view->goto_window);
4030                         ev_view_goto_entry_grab_focus (view);
4031                         
4032                         return TRUE;
4033                 }
4034                 
4035                 return gtk_bindings_activate_event (GTK_OBJECT (widget), event);
4036         }
4037
4038         switch (view->presentation_state) {
4039                 case EV_PRESENTATION_NORMAL:
4040                 case EV_PRESENTATION_BLACK:
4041                         gdk_window_set_background (view->layout.bin_window,
4042                                                    &widget->style->black);
4043                         break;
4044                 case EV_PRESENTATION_WHITE:
4045                         gdk_window_set_background (view->layout.bin_window,
4046                                                    &widget->style->white);
4047                         break;
4048                 default:
4049                         return gtk_bindings_activate_event (GTK_OBJECT (widget), event);
4050         }
4051
4052         gtk_widget_queue_draw (widget);
4053         return TRUE;
4054 }
4055
4056 static gint
4057 ev_view_focus_in (GtkWidget     *widget,
4058                   GdkEventFocus *event)
4059 {
4060         if (EV_VIEW (widget)->pixbuf_cache)
4061                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
4062         gtk_widget_queue_draw (widget);
4063
4064         return FALSE;
4065 }
4066
4067 static gint
4068 ev_view_focus_out (GtkWidget     *widget,
4069                      GdkEventFocus *event)
4070 {
4071         if (EV_VIEW (widget)->goto_window)
4072                 ev_view_goto_window_hide (EV_VIEW (widget));
4073         
4074         if (EV_VIEW (widget)->pixbuf_cache)
4075                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
4076         gtk_widget_queue_draw (widget);
4077
4078         return FALSE;
4079 }
4080
4081 static gboolean
4082 ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
4083 {
4084         EvView *view = EV_VIEW (widget);
4085
4086         if (view->cursor != EV_VIEW_CURSOR_NORMAL)
4087                 ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
4088
4089         return FALSE;
4090 }
4091
4092 static gboolean
4093 ev_view_enter_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
4094 {
4095         EvView *view = EV_VIEW (widget);
4096
4097         ev_view_handle_cursor_over_xy (view, event->x, event->y);
4098     
4099         return FALSE;
4100 }
4101
4102 static void
4103 ev_view_style_set (GtkWidget *widget,
4104                    GtkStyle  *old_style)
4105 {
4106         if (EV_VIEW (widget)->pixbuf_cache)
4107                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
4108
4109         GTK_WIDGET_CLASS (ev_view_parent_class)->style_set (widget, old_style);
4110 }
4111
4112 /*** Drawing ***/
4113
4114 static guint32
4115 ev_gdk_color_to_rgb (const GdkColor *color)
4116 {
4117   guint32 result;
4118   result = (0xff0000 | (color->red & 0xff00));
4119   result <<= 8;
4120   result |= ((color->green & 0xff00) | (color->blue >> 8));
4121   return result;
4122 }
4123
4124 static void
4125 draw_rubberband (GtkWidget *widget, GdkWindow *window,
4126                  const GdkRectangle *rect, guchar alpha)
4127 {
4128         GdkGC *gc;
4129         GdkPixbuf *pixbuf;
4130         GdkColor *fill_color_gdk;
4131         guint fill_color;
4132
4133         fill_color_gdk = gdk_color_copy (&GTK_WIDGET (widget)->style->base[GTK_STATE_SELECTED]);
4134         fill_color = ev_gdk_color_to_rgb (fill_color_gdk) << 8 | alpha;
4135
4136         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
4137                                  rect->width, rect->height);
4138         gdk_pixbuf_fill (pixbuf, fill_color);
4139
4140         gdk_draw_pixbuf (window, NULL, pixbuf,
4141                          0, 0,
4142                          rect->x - EV_VIEW (widget)->scroll_x, rect->y - EV_VIEW (widget)->scroll_y,
4143                          rect->width, rect->height,
4144                          GDK_RGB_DITHER_NONE,
4145                          0, 0);
4146
4147         g_object_unref (pixbuf);
4148
4149         gc = gdk_gc_new (window);
4150         gdk_gc_set_rgb_fg_color (gc, fill_color_gdk);
4151         gdk_draw_rectangle (window, gc, FALSE,
4152                             rect->x - EV_VIEW (widget)->scroll_x, rect->y - EV_VIEW (widget)->scroll_y,
4153                             rect->width - 1,
4154                             rect->height - 1);
4155         g_object_unref (gc);
4156
4157         gdk_color_free (fill_color_gdk);
4158 }
4159
4160
4161 static void
4162 highlight_find_results (EvView *view, int page)
4163 {
4164         gint i, n_results = 0;
4165
4166         n_results = ev_view_find_get_n_results (view, page);
4167
4168         for (i = 0; i < n_results; i++) {
4169                 EvRectangle *rectangle;
4170                 GdkRectangle view_rectangle;
4171                 guchar alpha;
4172
4173                 if (i == view->find_result && page == view->current_page) {
4174                         alpha = 0x90;
4175                 } else {
4176                         alpha = 0x20;
4177                 }
4178
4179                 rectangle = ev_view_find_get_result (view, page, i);
4180                 doc_rect_to_view_rect (view, page, rectangle, &view_rectangle);
4181                 draw_rubberband (GTK_WIDGET (view), view->layout.bin_window,
4182                                  &view_rectangle, alpha);
4183         }
4184 }
4185
4186 static void
4187 draw_loading_text (EvView       *view,
4188                    GdkRectangle *page_area,
4189                    GdkRectangle *expose_area)
4190 {
4191         cairo_t *cr;
4192         gint     width, height;
4193
4194         if (!view->loading_text) {
4195                 const gchar *loading_text = _("Loading...");
4196                 PangoLayout *layout;
4197                 PangoFontDescription *font_desc;
4198                 PangoRectangle logical_rect;
4199                 gint target_width;
4200                 gdouble real_scale;
4201
4202                 ev_document_fc_mutex_lock ();
4203
4204                 layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text);
4205                 
4206                 font_desc = pango_font_description_new ();
4207                 
4208                 /* We set the font to be 10 points, get the size, and scale appropriately */
4209                 pango_font_description_set_size (font_desc, 10 * PANGO_SCALE);
4210                 pango_layout_set_font_description (layout, font_desc);
4211                 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
4212
4213                 target_width = MAX (page_area->width / 2, 1);
4214                 real_scale = ((double)target_width / (double) logical_rect.width) * (PANGO_SCALE * 10);
4215                 pango_font_description_set_size (font_desc, (int)real_scale);
4216                 pango_layout_set_font_description (layout, font_desc);
4217                 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
4218
4219                 view->loading_text = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
4220                                                                  logical_rect.width,
4221                                                                  logical_rect.height);
4222                 cr = cairo_create (view->loading_text);
4223                 cairo_set_source_rgb (cr,
4224                                       155 / (double)255,
4225                                       155 / (double)255,
4226                                       155 / (double)255);
4227                 pango_cairo_show_layout (cr, layout);
4228                 cairo_destroy (cr);
4229
4230                 pango_font_description_free (font_desc);
4231                 g_object_unref (layout);
4232
4233                 ev_document_fc_mutex_unlock ();
4234         }
4235
4236         width = (page_area->width - cairo_image_surface_get_width (view->loading_text)) / 2;
4237         height = (page_area->height - cairo_image_surface_get_height (view->loading_text)) / 2;
4238         
4239         cr = gdk_cairo_create (view->layout.bin_window);
4240         cairo_translate (cr,
4241                          page_area->x + width,
4242                          page_area->y + height);
4243         cairo_set_source_surface (cr, view->loading_text, 0, 0);
4244         cairo_paint (cr);
4245         cairo_destroy (cr);
4246 }
4247
4248 static void
4249 draw_one_page (EvView       *view,
4250                gint          page,
4251                cairo_t      *cr,
4252                GdkRectangle *page_area,
4253                GtkBorder    *border,
4254                GdkRectangle *expose_area,
4255                gboolean     *page_ready)
4256 {
4257         GdkRectangle overlap;
4258         GdkRectangle real_page_area;
4259
4260         g_assert (view->document);
4261
4262         if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
4263                 return;
4264
4265         /* Render the document itself */
4266         real_page_area = *page_area;
4267
4268         real_page_area.x += border->left;
4269         real_page_area.y += border->top;
4270         real_page_area.width -= (border->left + border->right);
4271         real_page_area.height -= (border->top + border->bottom);
4272         *page_ready = TRUE;
4273
4274         if (!view->presentation) {
4275                 gint current_page;
4276                 
4277                 current_page = ev_document_model_get_page (view->model);
4278                 ev_document_misc_paint_one_page (view->layout.bin_window,
4279                                                  GTK_WIDGET (view),
4280                                                  page_area, border, 
4281                                                  page == current_page);
4282         }
4283
4284         if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
4285                 gint             width, height;
4286                 gint             page_width, page_height;
4287                 cairo_surface_t *page_surface = NULL;
4288                 gint             selection_width, selection_height;
4289                 cairo_surface_t *selection_surface = NULL;
4290
4291                 page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
4292
4293                 if (!page_surface) {
4294                         if (!view->presentation) {
4295                                 draw_loading_text (view,
4296                                                    &real_page_area,
4297                                                    expose_area);
4298                         }
4299
4300                         *page_ready = FALSE;
4301
4302                         return;
4303                 }
4304
4305                 ev_view_get_page_size (view, page, &width, &height);
4306
4307                 page_width = cairo_image_surface_get_width (page_surface);
4308                 page_height = cairo_image_surface_get_height (page_surface);
4309
4310                 cairo_save (cr);
4311                 cairo_translate (cr, overlap.x, overlap.y);
4312
4313                 if (width != page_width || height != page_height) {
4314                         cairo_pattern_set_filter (cairo_get_source (cr),
4315                                                   CAIRO_FILTER_FAST);
4316                         cairo_scale (cr,
4317                                      (gdouble)width / page_width,
4318                                      (gdouble)height / page_height);
4319                 }
4320
4321                 cairo_surface_set_device_offset (page_surface,
4322                                                  overlap.x - real_page_area.x,
4323                                                  overlap.y - real_page_area.y);
4324                 cairo_set_source_surface (cr, page_surface, 0, 0);
4325                 cairo_paint (cr);
4326                 cairo_restore (cr);
4327                 
4328                 /* Get the selection pixbuf iff we have something to draw */
4329                 if (find_selection_for_page (view, page) &&
4330                     view->selection_mode == EV_VIEW_SELECTION_TEXT) {
4331                         selection_surface =
4332                                 ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
4333                                                                        page,
4334                                                                        view->scale,
4335                                                                        NULL);
4336                 }
4337
4338                 if (!selection_surface) {
4339                         return;
4340                 }
4341
4342                 selection_width = cairo_image_surface_get_width (selection_surface);
4343                 selection_height = cairo_image_surface_get_height (selection_surface);
4344
4345                 cairo_save (cr);
4346                 cairo_translate (cr, overlap.x, overlap.y);
4347
4348                 if (width != selection_width || height != selection_height) {
4349                         cairo_pattern_set_filter (cairo_get_source (cr),
4350                                                   CAIRO_FILTER_FAST);
4351                         cairo_scale (cr,
4352                                      (gdouble)width / selection_width,
4353                                      (gdouble)height / selection_height);
4354                 }
4355
4356                 cairo_surface_set_device_offset (selection_surface,
4357                                                  overlap.x - real_page_area.x,
4358                                                  overlap.y - real_page_area.y);
4359                 cairo_set_source_surface (cr, selection_surface, 0, 0);
4360                 cairo_paint (cr);
4361                 cairo_restore (cr);
4362         }
4363 }
4364
4365 /*** GObject functions ***/
4366
4367 static void
4368 ev_view_finalize (GObject *object)
4369 {
4370         EvView *view = EV_VIEW (object);
4371
4372         clear_selection (view);
4373         clear_link_selected (view);
4374
4375         if (view->image_dnd_info.image)
4376                 g_object_unref (view->image_dnd_info.image);
4377         view->image_dnd_info.image = NULL;
4378
4379         G_OBJECT_CLASS (ev_view_parent_class)->finalize (object);
4380 }
4381
4382 static void
4383 ev_view_destroy (GtkObject *object)
4384 {
4385         EvView *view = EV_VIEW (object);
4386
4387         if (view->model) {
4388                 g_object_unref (view->model);
4389                 view->model = NULL;
4390         }
4391
4392         if (view->document) {
4393                 g_object_unref (view->document);
4394                 view->document = NULL;
4395         }
4396
4397         if (view->pixbuf_cache) {
4398                 g_object_unref (view->pixbuf_cache);
4399                 view->pixbuf_cache = NULL;
4400         }
4401
4402         if (view->goto_window) {
4403                 gtk_widget_destroy (view->goto_window);
4404                 view->goto_window = NULL;
4405                 view->goto_entry = NULL;
4406         }
4407
4408         ev_view_window_children_free (view);
4409
4410         if (view->selection_scroll_id) {
4411             g_source_remove (view->selection_scroll_id);
4412             view->selection_scroll_id = 0;
4413         }
4414
4415         if (view->selection_update_id) {
4416             g_source_remove (view->selection_update_id);
4417             view->selection_update_id = 0;
4418         }
4419
4420         if (view->loading_text) {
4421                 cairo_surface_destroy (view->loading_text);
4422                 view->loading_text = NULL;
4423         }
4424
4425         if (view->scroll_info.timeout_id) {
4426             g_source_remove (view->scroll_info.timeout_id);
4427             view->scroll_info.timeout_id = 0;
4428         }
4429
4430         if (view->drag_info.drag_timeout_id) {
4431                 g_source_remove (view->drag_info.drag_timeout_id);
4432                 view->drag_info.drag_timeout_id = 0;
4433         }
4434
4435         if (view->drag_info.release_timeout_id) {
4436                 g_source_remove (view->drag_info.release_timeout_id);
4437                 view->drag_info.release_timeout_id = 0;
4438         }
4439
4440         ev_view_presentation_transition_stop (view);
4441
4442         ev_view_set_scroll_adjustments (GTK_LAYOUT (view), NULL, NULL);
4443
4444         GTK_OBJECT_CLASS (ev_view_parent_class)->destroy (object);
4445 }
4446
4447 static void
4448 ev_view_set_property (GObject      *object,
4449                       guint         prop_id,
4450                       const GValue *value,
4451                       GParamSpec   *pspec)
4452 {
4453         EvView *view = EV_VIEW (object);
4454
4455         switch (prop_id) {
4456                 case PROP_CONTINUOUS:
4457                         ev_view_set_continuous (view, g_value_get_boolean (value));
4458                         break;
4459                 case PROP_DUAL_PAGE:
4460                         ev_view_set_dual_page (view, g_value_get_boolean (value));
4461                         break;
4462                 case PROP_FULLSCREEN:
4463                         ev_view_set_fullscreen (view, g_value_get_boolean (value));
4464                         break;
4465                 case PROP_PRESENTATION:
4466                         ev_view_set_presentation (view, g_value_get_boolean (value));
4467                         break;
4468                 case PROP_SIZING_MODE:
4469                         ev_view_set_sizing_mode (view, g_value_get_enum (value));
4470                         break;
4471                 case PROP_ZOOM:
4472                         ev_view_set_zoom (view, g_value_get_double (value));
4473                         break;
4474                 case PROP_ROTATION:
4475                         ev_view_set_rotation (view, g_value_get_int (value));
4476                         break;
4477                 default:
4478                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4479         }
4480 }
4481
4482 static AtkObject *
4483 ev_view_get_accessible (GtkWidget *widget)
4484 {
4485         static gboolean first_time = TRUE;
4486
4487         if (first_time) {
4488                 AtkObjectFactory *factory;
4489                 AtkRegistry *registry;
4490                 GType derived_type; 
4491                 GType derived_atk_type; 
4492
4493                 /*
4494                  * Figure out whether accessibility is enabled by looking at the
4495                  * type of the accessible object which would be created for
4496                  * the parent type of EvView.
4497                  */
4498                 derived_type = g_type_parent (EV_TYPE_VIEW);
4499
4500                 registry = atk_get_default_registry ();
4501                 factory = atk_registry_get_factory (registry,
4502                                                     derived_type);
4503                 derived_atk_type = atk_object_factory_get_accessible_type (factory);
4504                 if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE)) 
4505                         atk_registry_set_factory_type (registry, 
4506                                                        EV_TYPE_VIEW,
4507                                                        ev_view_accessible_factory_get_type ());
4508                 first_time = FALSE;
4509         } 
4510         return GTK_WIDGET_CLASS (ev_view_parent_class)->get_accessible (widget);
4511 }
4512
4513 static void
4514 ev_view_get_property (GObject *object,
4515                       guint prop_id,
4516                       GValue *value,
4517                       GParamSpec *pspec)
4518 {
4519         EvView *view = EV_VIEW (object);
4520
4521         switch (prop_id) {
4522                 case PROP_CONTINUOUS:
4523                         g_value_set_boolean (value, view->continuous);
4524                         break;
4525                 case PROP_DUAL_PAGE:
4526                         g_value_set_boolean (value, view->dual_page);
4527                         break;
4528                 case PROP_FULLSCREEN:
4529                         g_value_set_boolean (value, view->fullscreen);
4530                         break;
4531                 case PROP_PRESENTATION:
4532                         g_value_set_boolean (value, view->presentation);
4533                         break;
4534                 case PROP_SIZING_MODE:
4535                         g_value_set_enum (value, view->sizing_mode);
4536                         break;
4537                 case PROP_ZOOM:
4538                         g_value_set_double (value, view->scale);
4539                         break;
4540                 case PROP_ROTATION:
4541                         g_value_set_int (value, view->rotation);
4542                         break;
4543                 case PROP_HAS_SELECTION:
4544                         g_value_set_boolean (value,
4545                                              view->selection_info.selections != NULL);
4546                         break;
4547                 default:
4548                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4549         }
4550 }
4551
4552 static void
4553 ev_view_class_init (EvViewClass *class)
4554 {
4555         GObjectClass *object_class = G_OBJECT_CLASS (class);
4556         GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
4557         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
4558         GtkLayoutClass *layout_class = GTK_LAYOUT_CLASS (class);
4559         GtkBindingSet *binding_set;
4560
4561         object_class->finalize = ev_view_finalize;
4562         object_class->set_property = ev_view_set_property;
4563         object_class->get_property = ev_view_get_property;
4564
4565         widget_class->expose_event = ev_view_expose_event;
4566         widget_class->button_press_event = ev_view_button_press_event;
4567         widget_class->motion_notify_event = ev_view_motion_notify_event;
4568         widget_class->button_release_event = ev_view_button_release_event;
4569         widget_class->key_press_event = ev_view_key_press_event;
4570         widget_class->focus_in_event = ev_view_focus_in;
4571         widget_class->focus_out_event = ev_view_focus_out;
4572         widget_class->get_accessible = ev_view_get_accessible;
4573         widget_class->size_request = ev_view_size_request;
4574         widget_class->size_allocate = ev_view_size_allocate;
4575         widget_class->realize = ev_view_realize;
4576         widget_class->scroll_event = ev_view_scroll_event;
4577         widget_class->enter_notify_event = ev_view_enter_notify_event;
4578         widget_class->leave_notify_event = ev_view_leave_notify_event;
4579         widget_class->style_set = ev_view_style_set;
4580         widget_class->drag_data_get = ev_view_drag_data_get;
4581         widget_class->drag_motion = ev_view_drag_motion;
4582         widget_class->popup_menu = ev_view_popup_menu;
4583         widget_class->query_tooltip = ev_view_query_tooltip;
4584
4585         gtk_object_class->destroy = ev_view_destroy;
4586
4587         layout_class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
4588         
4589         class->binding_activated = ev_view_scroll;
4590
4591         signals[SIGNAL_BINDING_ACTIVATED] = g_signal_new ("binding_activated",
4592                          G_TYPE_FROM_CLASS (object_class),
4593                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4594                          G_STRUCT_OFFSET (EvViewClass, binding_activated),
4595                          NULL, NULL,
4596                          ev_view_marshal_VOID__ENUM_BOOLEAN,
4597                          G_TYPE_NONE, 2,
4598                          GTK_TYPE_SCROLL_TYPE,
4599                          G_TYPE_BOOLEAN);
4600         signals[SIGNAL_HANDLE_LINK] = g_signal_new ("handle-link",
4601                          G_TYPE_FROM_CLASS (object_class),
4602                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4603                          G_STRUCT_OFFSET (EvViewClass, handle_link),
4604                          NULL, NULL,
4605                          g_cclosure_marshal_VOID__OBJECT,
4606                          G_TYPE_NONE, 1,
4607                          G_TYPE_OBJECT);
4608         signals[SIGNAL_EXTERNAL_LINK] = g_signal_new ("external-link",
4609                          G_TYPE_FROM_CLASS (object_class),
4610                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4611                          G_STRUCT_OFFSET (EvViewClass, external_link),
4612                          NULL, NULL,
4613                          g_cclosure_marshal_VOID__OBJECT,
4614                          G_TYPE_NONE, 1,
4615                          G_TYPE_OBJECT);
4616         signals[SIGNAL_POPUP_MENU] = g_signal_new ("popup",
4617                          G_TYPE_FROM_CLASS (object_class),
4618                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4619                          G_STRUCT_OFFSET (EvViewClass, popup_menu),
4620                          NULL, NULL,
4621                          g_cclosure_marshal_VOID__OBJECT,
4622                          G_TYPE_NONE, 1,
4623                          G_TYPE_OBJECT);
4624
4625
4626         g_object_class_install_property (object_class,
4627                                          PROP_CONTINUOUS,
4628                                          g_param_spec_boolean ("continuous",
4629                                                                "Continuous",
4630                                                                "Continuous scrolling mode",
4631                                                                TRUE,
4632                                                                G_PARAM_READWRITE));
4633
4634         g_object_class_install_property (object_class,
4635                                          PROP_DUAL_PAGE,
4636                                          g_param_spec_boolean ("dual-page",
4637                                                                "Dual Page",
4638                                                                "Two pages visible at once",
4639                                                                FALSE,
4640                                                                G_PARAM_READWRITE));
4641         g_object_class_install_property (object_class,
4642                                          PROP_FULLSCREEN,
4643                                          g_param_spec_boolean ("fullscreen",
4644                                                                "Full Screen",
4645                                                                "Draw page in a fullscreen fashion",
4646                                                                FALSE,
4647                                                                G_PARAM_READWRITE));
4648         g_object_class_install_property (object_class,
4649                                          PROP_PRESENTATION,
4650                                          g_param_spec_boolean ("presentation",
4651                                                                "Presentation",
4652                                                                "Draw page in presentation mode",
4653                                                                TRUE,
4654                                                                G_PARAM_READWRITE));
4655
4656         g_object_class_install_property (object_class,
4657                                          PROP_SIZING_MODE,
4658                                          g_param_spec_enum ("sizing-mode",
4659                                                             "Sizing Mode",
4660                                                             "Sizing Mode",
4661                                                             EV_TYPE_SIZING_MODE,
4662                                                             EV_SIZING_FIT_WIDTH,
4663                                                             G_PARAM_READWRITE));
4664
4665         g_object_class_install_property (object_class,
4666                                          PROP_ZOOM,
4667                                          g_param_spec_double ("zoom",
4668                                                               "Zoom factor",
4669                                                               "Zoom factor",
4670                                                               0,
4671                                                               G_MAXDOUBLE,
4672                                                               1.0,
4673                                                               G_PARAM_READWRITE));
4674         g_object_class_install_property (object_class,
4675                                          PROP_ROTATION,
4676                                          g_param_spec_double ("rotation",
4677                                                               "Rotation",
4678                                                               "Rotation",
4679                                                               0,
4680                                                               360,
4681                                                               0,
4682                                                               G_PARAM_READWRITE));
4683
4684         g_object_class_install_property (object_class,
4685                                          PROP_HAS_SELECTION,
4686                                          g_param_spec_boolean ("has-selection",
4687                                                                "Has selection",
4688                                                                "The view has selections",
4689                                                                FALSE,
4690                                                                G_PARAM_READABLE));
4691
4692         binding_set = gtk_binding_set_by_class (class);
4693
4694         add_scroll_binding_keypad (binding_set, GDK_Left,  0, GTK_SCROLL_STEP_BACKWARD, TRUE);
4695         add_scroll_binding_keypad (binding_set, GDK_Right, 0, GTK_SCROLL_STEP_FORWARD,  TRUE);
4696         add_scroll_binding_keypad (binding_set, GDK_Left,  GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, TRUE);
4697         add_scroll_binding_keypad (binding_set, GDK_Right, GDK_MOD1_MASK, GTK_SCROLL_STEP_UP,  TRUE);
4698         add_scroll_binding_keypad (binding_set, GDK_Up,    0, GTK_SCROLL_STEP_BACKWARD, FALSE);
4699         add_scroll_binding_keypad (binding_set, GDK_Down,  0, GTK_SCROLL_STEP_FORWARD,  FALSE);
4700         add_scroll_binding_keypad (binding_set, GDK_Up,    GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, FALSE);
4701         add_scroll_binding_keypad (binding_set, GDK_Down,  GDK_MOD1_MASK, GTK_SCROLL_STEP_UP,  FALSE);
4702         gtk_binding_entry_add_signal (binding_set, GDK_H, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4703                                       GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, TRUE);
4704         gtk_binding_entry_add_signal (binding_set, GDK_J, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4705                                       GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, FALSE);
4706         gtk_binding_entry_add_signal (binding_set, GDK_K, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4707                                       GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, FALSE);
4708         gtk_binding_entry_add_signal (binding_set, GDK_L, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4709                                       GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, TRUE);
4710         
4711 }
4712
4713 static void
4714 ev_view_init (EvView *view)
4715 {
4716         GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS);
4717
4718         view->start_page = -1;
4719         view->end_page = -1;
4720         view->spacing = 5;
4721         view->scale = 1.0;
4722         view->current_page = 0;
4723         view->pressed_button = -1;
4724         view->cursor = EV_VIEW_CURSOR_NORMAL;
4725         view->drag_info.in_drag = FALSE;
4726         view->scroll_info.autoscrolling = FALSE;
4727         view->selection_info.selections = NULL;
4728         view->selection_info.in_selection = FALSE;
4729         view->selection_info.in_drag = FALSE;
4730         view->selection_mode = EV_VIEW_SELECTION_TEXT;
4731         view->continuous = TRUE;
4732         view->dual_page = FALSE;
4733         view->presentation = FALSE;
4734         view->presentation_state = EV_PRESENTATION_NORMAL;
4735         view->fullscreen = FALSE;
4736         view->sizing_mode = EV_SIZING_FIT_WIDTH;
4737         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
4738         view->jump_to_find_result = TRUE;
4739         view->highlight_find_results = FALSE;
4740
4741         gtk_layout_set_hadjustment (GTK_LAYOUT (view), NULL);
4742         gtk_layout_set_vadjustment (GTK_LAYOUT (view), NULL);
4743 }
4744
4745 /*** Callbacks ***/
4746
4747 static void
4748 ev_view_change_page (EvView *view,
4749                      gint    new_page,
4750                      gboolean start_transition)
4751 {
4752         gint x, y;
4753
4754         view->current_page = new_page;
4755         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
4756
4757         if (view->presentation && start_transition)
4758                 ev_view_presentation_transition_start (view);
4759
4760         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4761         ev_view_handle_cursor_over_xy (view, x, y);
4762
4763         gtk_widget_queue_resize (GTK_WIDGET (view));
4764 }
4765
4766 static void
4767 ev_view_transition_animation_finish (EvTransitionAnimation *animation,
4768                                      EvView                *view)
4769 {
4770         g_object_unref (view->animation);
4771         view->animation = NULL;
4772         ev_view_change_page (view, view->current_page, TRUE);
4773 }
4774
4775 /**
4776  * ev_view_transition_animation_cancel:
4777  * @animation: Animation to finish
4778  * @view: An EvView
4779  *
4780  * Does almost the same as cancel, but without scheduling the transition.
4781  */
4782
4783 static void
4784 ev_view_transition_animation_cancel (EvTransitionAnimation *animation,
4785                                      EvView                *view)
4786 {
4787         g_object_unref (view->animation);
4788         view->animation = NULL;
4789         ev_view_change_page (view, view->current_page, FALSE);
4790 }
4791
4792 static void
4793 ev_view_transition_animation_frame (EvTransitionAnimation *animation,
4794                                     gdouble                progress,
4795                                     EvView                *view)
4796 {
4797         gtk_widget_queue_draw (GTK_WIDGET (view));
4798 }
4799
4800 static void
4801 ev_view_presentation_animation_start (EvView *view,
4802                                       int     new_page)
4803 {
4804         EvTransitionEffect *effect = NULL;
4805         cairo_surface_t *surface;
4806
4807         if (EV_IS_DOCUMENT_TRANSITION (view->document))
4808                 effect = ev_document_transition_get_effect (EV_DOCUMENT_TRANSITION (view->document),
4809                                                             view->current_page);
4810         if (!effect)
4811                 return;
4812
4813         view->animation = ev_transition_animation_new (effect);
4814
4815         surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, view->current_page);
4816         ev_transition_animation_set_origin_surface (view->animation, surface);
4817         surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, new_page);
4818         if (surface)
4819                 ev_transition_animation_set_dest_surface (view->animation, surface);
4820
4821         g_signal_connect (view->animation, "frame",
4822                           G_CALLBACK (ev_view_transition_animation_frame), view);
4823         g_signal_connect (view->animation, "finished",
4824                           G_CALLBACK (ev_view_transition_animation_finish), view);
4825 }
4826
4827 static void
4828 job_finished_cb (EvPixbufCache *pixbuf_cache,
4829                  GdkRegion     *region,
4830                  EvView        *view)
4831 {
4832         if (view->animation) {
4833                 cairo_surface_t *surface;
4834
4835                 surface = ev_pixbuf_cache_get_surface (pixbuf_cache, view->current_page);
4836                 ev_transition_animation_set_dest_surface (view->animation, surface);
4837         }
4838
4839         if (region) {
4840                 gdk_window_invalidate_region (view->layout.bin_window,
4841                                               region, TRUE);
4842         } else {
4843                 gtk_widget_queue_draw (GTK_WIDGET (view));
4844         }
4845 }
4846
4847 static void
4848 ev_view_page_changed_cb (EvDocumentModel *model,
4849                          gint             old_page,
4850                          gint             new_page,
4851                          EvView          *view)
4852 {
4853         if (!view->document)
4854                 return;
4855
4856         if (view->current_page != new_page) {
4857                 if (view->presentation)
4858                         ev_view_presentation_animation_start (view, new_page);
4859
4860                 ev_view_change_page (view, new_page, TRUE);
4861         } else {
4862                 gtk_widget_queue_draw (GTK_WIDGET (view));
4863         }
4864
4865         view->find_result = 0;
4866 }
4867
4868 static void
4869 on_adjustment_value_changed (GtkAdjustment *adjustment,
4870                              EvView        *view)
4871 {
4872         int dx = 0, dy = 0;
4873         gint x, y;
4874         GList *children, *l;
4875
4876         if (! GTK_WIDGET_REALIZED (view))
4877                 return;
4878
4879         if (view->hadjustment) {
4880                 dx = view->scroll_x - (int) view->hadjustment->value;
4881                 view->scroll_x = (int) view->hadjustment->value;
4882         } else {
4883                 view->scroll_x = 0;
4884         }
4885
4886         if (view->vadjustment) {
4887                 dy = view->scroll_y - (int) view->vadjustment->value;
4888                 view->scroll_y = (int) view->vadjustment->value;
4889         } else {
4890                 view->scroll_y = 0;
4891         }
4892
4893         children = gtk_container_get_children (GTK_CONTAINER (view));
4894         for (l = children; l && l->data; l = g_list_next (l)) {
4895                 gint       child_x, child_y;
4896                 GtkWidget *child = (GtkWidget *)l->data;
4897                 
4898                 gtk_container_child_get (GTK_CONTAINER (view),
4899                                          child,
4900                                          "x", &child_x,
4901                                          "y", &child_y,
4902                                          NULL);
4903                 gtk_layout_move (GTK_LAYOUT (view), child, child_x + dx, child_y + dy);
4904         }
4905         g_list_free (children);
4906
4907         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
4908                 EvViewWindowChild *child;
4909
4910                 child = (EvViewWindowChild *)l->data;
4911
4912                 ev_view_window_child_move (view, child, child->x + dx, child->y + dy);
4913         }
4914         
4915         if (view->pending_resize)
4916                 gtk_widget_queue_draw (GTK_WIDGET (view));
4917         else
4918                 gdk_window_scroll (view->layout.bin_window, dx, dy);
4919                 
4920         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4921         ev_view_handle_cursor_over_xy (view, x, y);
4922
4923         if (view->document)
4924                 view_update_range_and_current_page (view);
4925 }
4926
4927 GtkWidget*
4928 ev_view_new (void)
4929 {
4930         GtkWidget *view;
4931
4932         view = g_object_new (EV_TYPE_VIEW, NULL);
4933
4934         return view;
4935 }
4936
4937 static void
4938 setup_caches (EvView *view)
4939 {
4940         view->height_to_page_cache = ev_view_get_height_to_page_cache (view);
4941         view->pixbuf_cache = ev_pixbuf_cache_new (GTK_WIDGET (view), view->document);
4942         g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view);
4943 }
4944
4945 static void
4946 clear_caches (EvView *view)
4947 {
4948         if (view->pixbuf_cache) {
4949                 g_object_unref (view->pixbuf_cache);
4950                 view->pixbuf_cache = NULL;
4951         }
4952 }
4953
4954 void
4955 ev_view_set_loading (EvView       *view,
4956                      gboolean      loading)
4957 {
4958         view->loading = loading;
4959         gtk_widget_queue_draw (GTK_WIDGET (view));
4960 }
4961
4962 static gboolean
4963 ev_view_autoscroll_cb (EvView *view)
4964 {
4965         gdouble speed, value;
4966
4967         /* If the user stops autoscrolling, autoscrolling will be
4968          * set to false but the timeout will continue; stop the timeout: */
4969         if (!view->scroll_info.autoscrolling) {
4970                 view->scroll_info.timeout_id = 0;
4971                 return FALSE;
4972         }
4973         
4974         if (view->scroll_info.last_y > view->scroll_info.start_y && 
4975                 (view->scroll_info.last_y < view->scroll_info.start_y))
4976                 return TRUE; 
4977
4978         /* Replace 100 with your speed of choice: The lower the faster.
4979          * Replace 3 with another speed of choice: The higher, the faster it accelerated
4980          *      based on the distance of the starting point from the mouse
4981          * (All also effected by the timeout interval of this callback) */
4982
4983         if (view->scroll_info.start_y > view->scroll_info.last_y)
4984                 speed = -pow ((((gdouble)view->scroll_info.start_y - view->scroll_info.last_y) / 100), 3);
4985         else
4986                 speed = pow ((((gdouble)view->scroll_info.last_y - view->scroll_info.start_y) / 100), 3);
4987         
4988         value = gtk_adjustment_get_value (view->vadjustment);
4989         value = CLAMP (value + speed, 0, view->vadjustment->upper - view->vadjustment->page_size);
4990         gtk_adjustment_set_value (view->vadjustment, value);
4991         
4992         return TRUE;
4993
4994 }
4995
4996 void
4997 ev_view_autoscroll_start (EvView *view)
4998 {
4999         gint x, y;
5000         
5001         g_return_if_fail (EV_IS_VIEW (view));
5002
5003         if (view->scroll_info.autoscrolling)
5004                 return;
5005         
5006         view->scroll_info.autoscrolling = TRUE;
5007         view->scroll_info.timeout_id =
5008                 g_timeout_add (20, (GSourceFunc)ev_view_autoscroll_cb,
5009                                view);
5010         
5011         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
5012         ev_view_handle_cursor_over_xy (view, x, y);
5013 }
5014
5015 void
5016 ev_view_autoscroll_stop (EvView *view)
5017 {
5018         gint x, y;
5019         
5020         g_return_if_fail (EV_IS_VIEW (view));
5021
5022         if (!view->scroll_info.autoscrolling)
5023                 return;
5024
5025         view->scroll_info.autoscrolling = FALSE;
5026         if (view->scroll_info.timeout_id) {
5027                 g_source_remove (view->scroll_info.timeout_id);
5028                 view->scroll_info.timeout_id = 0;
5029         }
5030
5031         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
5032         ev_view_handle_cursor_over_xy (view, x, y);
5033 }
5034
5035 static void
5036 ev_view_document_changed_cb (EvDocumentModel *model,
5037                              GParamSpec      *pspec,
5038                              EvView          *view)
5039 {
5040         EvDocument *document = ev_document_model_get_document (model);
5041
5042         view->loading = FALSE;
5043
5044         if (document != view->document) {
5045                 clear_caches (view);
5046
5047                 if (view->document) {
5048                         g_object_unref (view->document);
5049                 }
5050
5051                 view->document = document;
5052                 view->find_result = 0;
5053
5054                 if (view->document) {
5055                         g_object_ref (view->document);
5056                         setup_caches (view);
5057                 }
5058
5059                 ev_view_change_page (view,
5060                                      ev_document_model_get_page (model),
5061                                      TRUE);
5062         }
5063 }
5064
5065 static void
5066 ev_view_rotation_changed_cb (EvDocumentModel *model,
5067                              GParamSpec      *pspec,
5068                              EvView          *view)
5069 {
5070         gint rotation = ev_document_model_get_rotation (model);
5071
5072         ev_view_set_rotation (view, rotation);
5073
5074         if (view->pixbuf_cache) {
5075                 ev_pixbuf_cache_clear (view->pixbuf_cache);
5076                 gtk_widget_queue_resize (GTK_WIDGET (view));
5077         }
5078
5079         if (rotation != 0)
5080                 clear_selection (view);
5081 }
5082
5083 static void
5084 ev_view_sizing_mode_changed_cb (EvDocumentModel *model,
5085                                 GParamSpec      *pspec,
5086                                 EvView          *view)
5087 {
5088         EvSizingMode mode = ev_document_model_get_sizing_mode (model);
5089
5090         ev_view_set_sizing_mode (view, mode);
5091
5092         if (mode != EV_SIZING_FREE)
5093                 gtk_widget_queue_resize (GTK_WIDGET (view));
5094 }
5095
5096 #define EPSILON 0.0000001
5097 static void
5098 ev_view_scale_changed_cb (EvDocumentModel *model,
5099                           GParamSpec      *pspec,
5100                           EvView          *view)
5101 {
5102         gdouble scale = ev_document_model_get_scale (model);
5103
5104         if (ABS (view->scale - scale) < EPSILON)
5105                 return;
5106
5107         if (view->loading_text) {
5108                 cairo_surface_destroy (view->loading_text);
5109                 view->loading_text = NULL;
5110         }
5111
5112         ev_view_set_zoom (view, scale);
5113
5114         view->pending_resize = TRUE;
5115         gtk_widget_queue_resize (GTK_WIDGET (view));
5116 }
5117
5118 static void
5119 ev_view_continuous_changed_cb (EvDocumentModel *model,
5120                                GParamSpec      *pspec,
5121                                EvView          *view)
5122 {
5123         gboolean continuous = ev_document_model_get_continuous (model);
5124
5125         ev_view_set_continuous (view, continuous);
5126         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
5127         gtk_widget_queue_resize (GTK_WIDGET (view));
5128 }
5129
5130 static void
5131 ev_view_dual_page_changed_cb (EvDocumentModel *model,
5132                               GParamSpec      *pspec,
5133                               EvView          *view)
5134 {
5135         gboolean dual_page = ev_document_model_get_dual_page (model);
5136
5137         ev_view_set_dual_page (view, dual_page);
5138         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
5139         /* FIXME: if we're keeping the pixbuf cache around, we should extend the
5140          * preload_cache_size to be 2 if dual_page is set.
5141          */
5142         gtk_widget_queue_resize (GTK_WIDGET (view));
5143 }
5144
5145 static void
5146 ev_view_fullscreen_changed_cb (EvDocumentModel *model,
5147                                GParamSpec      *pspec,
5148                                EvView          *view)
5149 {
5150         gboolean fullscreen = ev_document_model_get_fullscreen (model);
5151
5152         ev_view_set_fullscreen (view, fullscreen);
5153         gtk_widget_queue_resize (GTK_WIDGET (view));
5154 }
5155
5156 void
5157 ev_view_set_model (EvView          *view,
5158                    EvDocumentModel *model)
5159 {
5160         g_return_if_fail (EV_IS_VIEW (view));
5161         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
5162
5163         if (model == view->model)
5164                 return;
5165
5166         if (view->model) {
5167                 g_signal_handlers_disconnect_by_func (view->model,
5168                                                       ev_view_document_changed_cb,
5169                                                       view);
5170                 g_signal_handlers_disconnect_by_func (view->model,
5171                                                       ev_view_page_changed_cb,
5172                                                       view);
5173                 g_object_unref (view->model);
5174         }
5175         view->model = g_object_ref (model);
5176         g_signal_connect (view->model, "notify::document",
5177                           G_CALLBACK (ev_view_document_changed_cb),
5178                           view);
5179         g_signal_connect (view->model, "notify::rotation",
5180                           G_CALLBACK (ev_view_rotation_changed_cb),
5181                           view);
5182         g_signal_connect (view->model, "notify::sizing-mode",
5183                           G_CALLBACK (ev_view_sizing_mode_changed_cb),
5184                           view);
5185         g_signal_connect (view->model, "notify::scale",
5186                           G_CALLBACK (ev_view_scale_changed_cb),
5187                           view);
5188         g_signal_connect (view->model, "notify::continuous",
5189                           G_CALLBACK (ev_view_continuous_changed_cb),
5190                           view);
5191         g_signal_connect (view->model, "notify::dual-page",
5192                           G_CALLBACK (ev_view_dual_page_changed_cb),
5193                           view);
5194         g_signal_connect (view->model, "notify::fullscreen",
5195                           G_CALLBACK (ev_view_fullscreen_changed_cb),
5196                           view);
5197         g_signal_connect (view->model, "page-changed",
5198                           G_CALLBACK (ev_view_page_changed_cb),
5199                           view);
5200 }
5201
5202 static void
5203 ev_view_reload_page (EvView    *view,
5204                      gint       page,
5205                      GdkRegion *region)
5206 {
5207         ev_pixbuf_cache_reload_page (view->pixbuf_cache,
5208                                      region,
5209                                      page,
5210                                      view->rotation,
5211                                      view->scale);
5212 }
5213
5214 void
5215 ev_view_reload (EvView *view)
5216 {
5217         ev_pixbuf_cache_clear (view->pixbuf_cache);
5218         view_update_range_and_current_page (view);
5219 }
5220
5221 /*** Zoom and sizing mode ***/
5222
5223 void
5224 ev_view_set_zoom (EvView   *view,
5225                   double    scale)
5226 {
5227         view->scale = scale;
5228
5229         g_object_notify (G_OBJECT (view), "zoom");
5230 }
5231
5232 double
5233 ev_view_get_zoom (EvView *view)
5234 {
5235         return view->scale;
5236 }
5237
5238 gboolean
5239 ev_view_get_continuous (EvView *view)
5240 {
5241         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
5242
5243         return view->continuous;
5244 }
5245
5246 void
5247 ev_view_set_continuous (EvView   *view,
5248                         gboolean  continuous)
5249 {
5250         g_return_if_fail (EV_IS_VIEW (view));
5251
5252         view->continuous = continuous;
5253
5254         g_object_notify (G_OBJECT (view), "continuous");
5255 }
5256
5257 gboolean
5258 ev_view_get_dual_page (EvView *view)
5259 {
5260         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
5261
5262         return view->dual_page;
5263 }
5264
5265 void
5266 ev_view_set_dual_page (EvView   *view,
5267                        gboolean  dual_page)
5268 {
5269         g_return_if_fail (EV_IS_VIEW (view));
5270
5271         view->dual_page = dual_page;
5272
5273         g_object_notify (G_OBJECT (view), "dual-page");
5274 }
5275
5276 void
5277 ev_view_set_fullscreen (EvView   *view,
5278                          gboolean  fullscreen)
5279 {
5280         g_return_if_fail (EV_IS_VIEW (view));
5281
5282         view->fullscreen = fullscreen;
5283
5284         g_object_notify (G_OBJECT (view), "fullscreen");
5285 }
5286
5287 gboolean
5288 ev_view_get_fullscreen (EvView *view)
5289 {
5290         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
5291
5292         return view->fullscreen;
5293 }
5294
5295 void
5296 ev_view_set_presentation (EvView   *view,
5297                           gboolean  presentation)
5298 {
5299         g_return_if_fail (EV_IS_VIEW (view));
5300
5301         presentation = presentation != FALSE;
5302
5303         if (view->presentation == presentation)
5304                 return;
5305
5306         if (!presentation)
5307                 view->presentation_state = EV_PRESENTATION_NORMAL;
5308         
5309         view->presentation = presentation;
5310         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
5311         
5312         if (presentation) {
5313                 view->sizing_mode_saved = view->sizing_mode;
5314                 view->scale_saved = view->scale;
5315                 ev_view_set_sizing_mode (view, EV_SIZING_BEST_FIT);
5316         } else {
5317                 ev_document_model_set_sizing_mode (view->model, view->sizing_mode_saved);
5318                 ev_document_model_set_scale (view->model, view->scale_saved);
5319         }
5320         
5321         gtk_widget_queue_resize (GTK_WIDGET (view));
5322
5323         if (presentation)
5324                 ev_view_presentation_transition_start (view);
5325         else {
5326                 ev_view_presentation_transition_stop (view);
5327
5328                 if (view->animation) {
5329                         /* stop any running animation */
5330                         ev_view_transition_animation_cancel (view->animation, view);
5331                 }
5332         }
5333
5334         if (GTK_WIDGET_REALIZED (view)) {
5335                 if (view->presentation)
5336                         gdk_window_set_background (view->layout.bin_window,
5337                                                    &GTK_WIDGET (view)->style->black);
5338                 else
5339                         gdk_window_set_background (view->layout.bin_window,
5340                                                    &GTK_WIDGET (view)->style->mid [GTK_STATE_NORMAL]);
5341         }
5342
5343         g_object_notify (G_OBJECT (view), "presentation");
5344 }
5345
5346 gboolean
5347 ev_view_get_presentation (EvView *view)
5348 {
5349         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
5350
5351         return view->presentation;
5352 }
5353
5354 static gboolean
5355 transition_next_page (EvView *view)
5356 {
5357         ev_view_next_page (view);
5358
5359         return FALSE;
5360 }
5361
5362 static void
5363 ev_view_presentation_transition_stop (EvView *view)
5364 {
5365         if (view->trans_timeout_id > 0)
5366                 g_source_remove (view->trans_timeout_id);
5367         view->trans_timeout_id = 0;
5368 }
5369
5370 static void
5371 ev_view_presentation_transition_start (EvView *view)
5372 {
5373         gdouble duration;
5374         
5375         if (!EV_IS_DOCUMENT_TRANSITION (view->document))
5376                 return;
5377
5378         ev_view_presentation_transition_stop (view);
5379
5380         duration = ev_document_transition_get_page_duration (EV_DOCUMENT_TRANSITION (view->document),
5381                                                              view->current_page);
5382         if (duration > 0) {
5383                 view->trans_timeout_id =
5384                         g_timeout_add_seconds (duration,
5385                                                (GSourceFunc) transition_next_page,
5386                                                view);
5387         }
5388 }
5389
5390 void
5391 ev_view_set_sizing_mode (EvView       *view,
5392                          EvSizingMode  sizing_mode)
5393 {
5394         view->sizing_mode = sizing_mode;
5395
5396         g_object_notify (G_OBJECT (view), "sizing-mode");
5397 }
5398
5399 EvSizingMode
5400 ev_view_get_sizing_mode (EvView *view)
5401 {
5402         g_return_val_if_fail (EV_IS_VIEW (view), EV_SIZING_FREE);
5403
5404         return view->sizing_mode;
5405 }
5406
5407 gboolean
5408 ev_view_can_zoom_in (EvView *view)
5409 {
5410         return view->scale * ZOOM_IN_FACTOR <= ev_document_model_get_max_scale (view->model);
5411 }
5412
5413 gboolean
5414 ev_view_can_zoom_out (EvView *view)
5415 {
5416         return view->scale * ZOOM_OUT_FACTOR >= ev_document_model_get_min_scale (view->model);
5417 }
5418
5419 void
5420 ev_view_zoom_in (EvView *view)
5421 {
5422         gdouble scale;
5423
5424         g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
5425
5426         if (view->presentation)
5427                 return;
5428
5429         view->pending_scroll = SCROLL_TO_CENTER;
5430         scale = ev_document_model_get_scale (view->model) * ZOOM_IN_FACTOR;
5431         ev_document_model_set_scale (view->model, scale);
5432 }
5433
5434 void
5435 ev_view_zoom_out (EvView *view)
5436 {
5437         gdouble scale;
5438
5439         g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
5440
5441         if (view->presentation)
5442                 return;
5443
5444         view->pending_scroll = SCROLL_TO_CENTER;
5445         scale = ev_document_model_get_scale (view->model) * ZOOM_OUT_FACTOR;
5446         ev_document_model_set_scale (view->model, scale);
5447 }
5448
5449 void
5450 ev_view_set_rotation (EvView *view, int rotation)
5451 {
5452         view->rotation = rotation;
5453
5454         g_object_notify (G_OBJECT (view), "rotation");
5455 }
5456
5457 int
5458 ev_view_get_rotation (EvView *view)
5459 {
5460         return view->rotation;
5461 }
5462
5463 static double
5464 zoom_for_size_fit_width (gdouble doc_width,
5465                          gdouble doc_height,
5466                          int     target_width,
5467                          int     target_height)
5468 {
5469         double scale;
5470
5471         scale = (double)target_width / doc_width;
5472
5473         if (doc_height * scale > target_height)
5474                 scale = (double)target_width / doc_width;
5475
5476         return scale;
5477 }
5478
5479 static double
5480 zoom_for_size_fit_height (gdouble doc_width,
5481                           gdouble doc_height,
5482                           int     target_width,
5483                           int     target_height)
5484 {
5485         double scale;
5486
5487         scale = (double)target_height / doc_height;
5488
5489         if (doc_width * scale > target_width)
5490                 scale = (double)target_height / doc_height;
5491
5492         return scale;
5493 }
5494
5495 static double
5496 zoom_for_size_best_fit (gdouble doc_width,
5497                         gdouble doc_height,
5498                         int     target_width,
5499                         int     target_height)
5500 {
5501         double w_scale;
5502         double h_scale;
5503
5504         w_scale = (double)target_width / doc_width;
5505         h_scale = (double)target_height / doc_height;
5506
5507         if (doc_height * w_scale > target_height)
5508                 w_scale = (double)target_width / doc_width;
5509         if (doc_width * h_scale > target_width)
5510                 h_scale = (double)target_height / doc_height;
5511
5512         return MIN (w_scale, h_scale);
5513 }
5514
5515
5516 static void
5517 ev_view_zoom_for_size_presentation (EvView *view,
5518                                     int     width,
5519                                     int     height)
5520 {
5521         gdouble doc_width, doc_height;
5522         gdouble scale;
5523
5524         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
5525         scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5526         ev_document_model_set_scale (view->model, scale);
5527 }
5528
5529 static void
5530 ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
5531                                                 int     width,
5532                                                 int     height)
5533 {
5534         gdouble doc_width, doc_height;
5535         GtkBorder border;
5536         gdouble scale;
5537
5538         ev_document_get_max_page_size (view->document, &doc_width, &doc_height);
5539         if (view->rotation == 90 || view->rotation == 270) {
5540                 gdouble tmp;
5541
5542                 tmp = doc_width;
5543                 doc_width = doc_height;
5544                 doc_height = tmp;
5545         }
5546
5547         compute_border (view, doc_width, doc_height, &border);
5548
5549         doc_width *= 2;
5550         width -= (2 * (border.left + border.right) + 3 * view->spacing);
5551         height -= (border.top + border.bottom + 2 * view->spacing - 1);
5552
5553         if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
5554                 scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
5555         else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5556                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5557         else
5558                 g_assert_not_reached ();
5559
5560         ev_document_model_set_scale (view->model, scale);
5561 }
5562
5563 static void
5564 ev_view_zoom_for_size_continuous (EvView *view,
5565                                   int     width,
5566                                   int     height)
5567 {
5568         gdouble doc_width, doc_height;
5569         GtkBorder border;
5570         gdouble scale;
5571
5572         ev_document_get_max_page_size (view->document, &doc_width, &doc_height);
5573         if (view->rotation == 90 || view->rotation == 270) {
5574                 gdouble tmp;
5575
5576                 tmp = doc_width;
5577                 doc_width = doc_height;
5578                 doc_height = tmp;
5579         }
5580
5581         compute_border (view, doc_width, doc_height, &border);
5582
5583         width -= (border.left + border.right + 2 * view->spacing);
5584         height -= (border.top + border.bottom + 2 * view->spacing - 1);
5585
5586         if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
5587                 scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
5588         else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5589                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5590         else
5591                 g_assert_not_reached ();
5592
5593         ev_document_model_set_scale (view->model, scale);
5594 }
5595
5596 static void
5597 ev_view_zoom_for_size_dual_page (EvView *view,
5598                                  int     width,
5599                                  int     height)
5600 {
5601         GtkBorder border;
5602         gdouble doc_width, doc_height;
5603         gdouble scale;
5604         gint other_page;
5605
5606         other_page = view->current_page ^ 1;
5607
5608         /* Find the largest of the two. */
5609         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
5610         if (other_page < ev_document_get_n_pages (view->document)) {
5611                 gdouble width_2, height_2;
5612
5613                 get_doc_page_size (view, other_page, &width_2, &height_2);
5614                 if (width_2 > doc_width)
5615                         doc_width = width_2;
5616                 if (height_2 > doc_height)
5617                         doc_height = height_2;
5618         }
5619         compute_border (view, width, height, &border);
5620
5621         doc_width = doc_width * 2;
5622         width -= ((border.left + border.right)* 2 + 3 * view->spacing);
5623         height -= (border.top + border.bottom + 2 * view->spacing);
5624
5625         if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
5626                 scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
5627         else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5628                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5629         else
5630                 g_assert_not_reached ();
5631
5632         ev_document_model_set_scale (view->model, scale);
5633 }
5634
5635 static void
5636 ev_view_zoom_for_size_single_page (EvView *view,
5637                                    int     width,
5638                                    int     height)
5639 {
5640         gdouble doc_width, doc_height;
5641         GtkBorder border;
5642         gdouble scale;
5643
5644         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
5645
5646         /* Get an approximate border */
5647         compute_border (view, width, height, &border);
5648
5649         width -= (border.left + border.right + 2 * view->spacing);
5650         height -= (border.top + border.bottom + 2 * view->spacing);
5651
5652         if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
5653                 scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
5654         else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5655                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5656         else
5657                 g_assert_not_reached ();
5658
5659         ev_document_model_set_scale (view->model, scale);
5660 }
5661
5662 static void
5663 ev_view_zoom_for_size (EvView *view,
5664                        int     width,
5665                        int     height)
5666 {
5667         g_return_if_fail (EV_IS_VIEW (view));
5668         g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
5669                           view->sizing_mode == EV_SIZING_BEST_FIT);
5670         g_return_if_fail (width >= 0);
5671         g_return_if_fail (height >= 0);
5672
5673         if (view->document == NULL)
5674                 return;
5675
5676         if (view->presentation)
5677                 ev_view_zoom_for_size_presentation (view, width, height);
5678         else if (view->continuous && view->dual_page)
5679                 ev_view_zoom_for_size_continuous_and_dual_page (view, width, height);
5680         else if (view->continuous)
5681                 ev_view_zoom_for_size_continuous (view, width, height);
5682         else if (view->dual_page)
5683                 ev_view_zoom_for_size_dual_page (view, width, height);
5684         else
5685                 ev_view_zoom_for_size_single_page (view, width, height);
5686 }
5687
5688 /*** Find ***/
5689 static gint
5690 ev_view_find_get_n_results (EvView *view, gint page)
5691 {
5692         return view->find_pages ? g_list_length (view->find_pages[page]) : 0;
5693 }
5694
5695 static EvRectangle *
5696 ev_view_find_get_result (EvView *view, gint page, gint result)
5697 {
5698         return view->find_pages ? (EvRectangle *) g_list_nth_data (view->find_pages[page], result) : NULL;
5699 }
5700
5701 static void
5702 jump_to_find_result (EvView *view)
5703 {
5704         gint n_results;
5705         gint page = view->current_page;
5706
5707         n_results = ev_view_find_get_n_results (view, page);
5708
5709         if (n_results > 0 && view->find_result < n_results) {
5710                 EvRectangle *rect;
5711                 GdkRectangle view_rect;
5712
5713                 rect = ev_view_find_get_result (view, page, view->find_result);
5714                 doc_rect_to_view_rect (view, page, rect, &view_rect);
5715                 ensure_rectangle_is_visible (view, &view_rect);
5716                 view->jump_to_find_result = FALSE;
5717         }
5718 }
5719
5720 /**
5721  * jump_to_find_page
5722  * @view: #EvView instance
5723  * @direction: Direction to look
5724  * @shift: Shift from current page
5725  *
5726  * Jumps to the first page that has occurences of searched word.
5727  * Uses a direction where to look and a shift from current page. 
5728  *
5729  */
5730 static void
5731 jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
5732 {
5733         int n_pages, i;
5734
5735         n_pages = ev_document_get_n_pages (view->document);
5736
5737         for (i = 0; i < n_pages; i++) {
5738                 int page;
5739                 
5740                 if (direction == EV_VIEW_FIND_NEXT)
5741                         page = view->current_page + i;
5742                 else
5743                         page = view->current_page - i;          
5744                 page += shift;
5745                 
5746                 if (page >= n_pages) {
5747                         page = page - n_pages;
5748                 } else if (page < 0) 
5749                         page = page + n_pages;
5750
5751                 if (ev_view_find_get_n_results (view, page) > 0) {
5752                         ev_document_model_set_page (view->model, page);
5753                         break;
5754                 }
5755         }
5756 }
5757
5758 void
5759 ev_view_find_changed (EvView *view, GList **results, gint page)
5760 {
5761         view->find_pages = results;
5762         
5763         if (view->jump_to_find_result == TRUE) {
5764                 jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
5765                 jump_to_find_result (view);
5766         }
5767
5768         if (view->current_page == page)
5769                 gtk_widget_queue_draw (GTK_WIDGET (view));
5770 }
5771
5772 void
5773 ev_view_find_next (EvView *view)
5774 {
5775         gint n_results;
5776
5777         n_results = ev_view_find_get_n_results (view, view->current_page);
5778         view->find_result++;
5779
5780         if (view->find_result >= n_results) {
5781                 view->find_result = 0;
5782                 jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1);
5783                 jump_to_find_result (view);
5784         } else {
5785                 jump_to_find_result (view);
5786                 gtk_widget_queue_draw (GTK_WIDGET (view));
5787         }
5788 }
5789
5790 void
5791 ev_view_find_previous (EvView *view)
5792 {
5793         view->find_result--;
5794
5795         if (view->find_result < 0) {
5796                 jump_to_find_page (view, EV_VIEW_FIND_PREV, -1);
5797                 view->find_result = MAX (0, ev_view_find_get_n_results (view, view->current_page) - 1);
5798                 jump_to_find_result (view);
5799         } else {
5800                 jump_to_find_result (view);
5801                 gtk_widget_queue_draw (GTK_WIDGET (view));
5802         }
5803 }
5804
5805 void
5806 ev_view_find_search_changed (EvView *view)
5807 {
5808         /* search string has changed, focus on new search result */
5809         view->jump_to_find_result = TRUE;
5810         view->find_pages = NULL;
5811 }
5812
5813 void
5814 ev_view_find_set_highlight_search (EvView *view, gboolean value)
5815 {
5816         view->highlight_find_results = value;
5817         gtk_widget_queue_draw (GTK_WIDGET (view));
5818 }
5819
5820 void
5821 ev_view_find_cancel (EvView *view)
5822 {
5823         view->find_pages = NULL;
5824 }
5825
5826 /*** Selections ***/
5827
5828 /* compute_new_selection_rect/text calculates the area currently selected by
5829  * view_rect.  each handles a different mode;
5830  */
5831 static GList *
5832 compute_new_selection_rect (EvView       *view,
5833                             GdkPoint     *start,
5834                             GdkPoint     *stop)
5835 {
5836         GdkRectangle view_rect;
5837         int n_pages, i;
5838         GList *list = NULL;
5839
5840         g_assert (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE);
5841         
5842         view_rect.x = MIN (start->x, stop->x);
5843         view_rect.y = MIN (start->y, stop->y);
5844         view_rect.width = MAX (start->x, stop->x) - view_rect.x;
5845         view_rect.width = MAX (start->y, stop->y) - view_rect.y;
5846
5847         n_pages = ev_document_get_n_pages (view->document);
5848
5849         for (i = 0; i < n_pages; i++) {
5850                 GdkRectangle page_area;
5851                 GtkBorder border;
5852                 
5853                 if (get_page_extents (view, i, &page_area, &border)) {
5854                         GdkRectangle overlap;
5855
5856                         if (gdk_rectangle_intersect (&page_area, &view_rect, &overlap)) {
5857                                 EvViewSelection *selection;
5858
5859                                 selection = g_new0 (EvViewSelection, 1);
5860                                 selection->page = i;
5861                                 view_rect_to_doc_rect (view, &overlap, &page_area,
5862                                                        &(selection->rect));
5863
5864                                 list = g_list_append (list, selection);
5865                         }
5866                 }
5867         }
5868
5869         return list;
5870 }
5871
5872 static gboolean
5873 gdk_rectangle_point_in (GdkRectangle *rectangle,
5874                         GdkPoint     *point)
5875 {
5876         return rectangle->x <= point->x &&
5877                 rectangle->y <= point->y &&
5878                 point->x < rectangle->x + rectangle->width &&
5879                 point->y < rectangle->y + rectangle->height;
5880 }
5881
5882 static GList *
5883 compute_new_selection_text (EvView          *view,
5884                             EvSelectionStyle style,
5885                             GdkPoint        *start,
5886                             GdkPoint        *stop)
5887 {
5888         int n_pages, i, first, last;
5889         GList *list = NULL;
5890         EvViewSelection *selection;
5891         gdouble width, height;
5892         int start_page, end_page;
5893
5894         g_assert (view->selection_mode == EV_VIEW_SELECTION_TEXT);
5895
5896         n_pages = ev_document_get_n_pages (view->document);
5897
5898         /* First figure out the range of pages the selection
5899          * affects. */
5900         first = n_pages;
5901         last = 0;
5902         if (view->continuous) {
5903                 start_page = 0;
5904                 end_page = n_pages;
5905         } else if (view->dual_page) {
5906                 start_page = view->start_page;
5907                 end_page = view->end_page + 1;
5908         } else {
5909                 start_page = view->current_page;
5910                 end_page = view->current_page + 1;
5911         }
5912
5913         for (i = start_page; i < end_page; i++) {
5914                 GdkRectangle page_area;
5915                 GtkBorder border;
5916                 
5917                 get_page_extents (view, i, &page_area, &border);
5918                 if (gdk_rectangle_point_in (&page_area, start) || 
5919                     gdk_rectangle_point_in (&page_area, stop)) {
5920                         if (first == n_pages)
5921                                 first = i;
5922                         last = i;
5923                 }
5924
5925         }
5926
5927         /* Now create a list of EvViewSelection's for the affected
5928          * pages.  This could be an empty list, a list of just one
5929          * page or a number of pages.*/
5930         for (i = first; i < last + 1; i++) {
5931                 GdkRectangle page_area;
5932                 GtkBorder border;
5933                 GdkPoint *point;
5934
5935                 get_doc_page_size (view, i, &width, &height);
5936
5937                 selection = g_new0 (EvViewSelection, 1);
5938                 selection->page = i;
5939                 selection->style = style;
5940                 selection->rect.x1 = selection->rect.y1 = 0;
5941                 selection->rect.x2 = width;
5942                 selection->rect.y2 = height;
5943
5944                 get_page_extents (view, i, &page_area, &border);
5945
5946                 if (gdk_rectangle_point_in (&page_area, start))
5947                         point = start;
5948                 else
5949                         point = stop;
5950
5951                 if (i == first)
5952                         view_point_to_doc_point (view, point, &page_area,
5953                                                  &selection->rect.x1,
5954                                                  &selection->rect.y1);
5955
5956                 /* If the selection is contained within just one page,
5957                  * make sure we don't write 'start' into both points
5958                  * in selection->rect. */
5959                 if (first == last)
5960                         point = stop;
5961
5962                 if (i == last)
5963                         view_point_to_doc_point (view, point, &page_area,
5964                                                  &selection->rect.x2,
5965                                                  &selection->rect.y2);
5966
5967                 list = g_list_append (list, selection);
5968         }
5969
5970         return list;
5971 }
5972
5973 /* This function takes the newly calculated list, and figures out which regions
5974  * have changed.  It then queues a redraw approporiately.
5975  */
5976 static void
5977 merge_selection_region (EvView *view,
5978                         GList  *new_list)
5979 {
5980         GList *old_list;
5981         GList *new_list_ptr, *old_list_ptr;
5982
5983         /* Update the selection */
5984         old_list = ev_pixbuf_cache_get_selection_list (view->pixbuf_cache);
5985         g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
5986         g_list_free (view->selection_info.selections);
5987         view->selection_info.selections = new_list;
5988         ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, new_list);
5989         g_object_notify (G_OBJECT (view), "has-selection");
5990
5991         new_list_ptr = new_list;
5992         old_list_ptr = old_list;
5993
5994         while (new_list_ptr || old_list_ptr) {
5995                 EvViewSelection *old_sel, *new_sel;
5996                 int cur_page;
5997                 GdkRegion *region = NULL;
5998
5999                 new_sel = (new_list_ptr) ? (new_list_ptr->data) : NULL;
6000                 old_sel = (old_list_ptr) ? (old_list_ptr->data) : NULL;
6001
6002                 /* Assume that the lists are in order, and we run through them
6003                  * comparing them, one page at a time.  We come out with the
6004                  * first page we see. */
6005                 if (new_sel && old_sel) {
6006                         if (new_sel->page < old_sel->page) {
6007                                 new_list_ptr = new_list_ptr->next;
6008                                 old_sel = NULL;
6009                         } else if (new_sel->page > old_sel->page) {
6010                                 old_list_ptr = old_list_ptr->next;
6011                                 new_sel = NULL;
6012                         } else {
6013                                 new_list_ptr = new_list_ptr->next;
6014                                 old_list_ptr = old_list_ptr->next;
6015                         }
6016                 } else if (new_sel) {
6017                         new_list_ptr = new_list_ptr->next;
6018                 } else if (old_sel) {
6019                         old_list_ptr = old_list_ptr->next;
6020                 }
6021
6022                 g_assert (new_sel || old_sel);
6023
6024                 /* is the page we're looking at on the screen?*/
6025                 cur_page = new_sel ? new_sel->page : old_sel->page;
6026                 if (cur_page < view->start_page || cur_page > view->end_page)
6027                         continue;
6028
6029                 /* seed the cache with a new page.  We are going to need the new
6030                  * region too. */
6031                 if (new_sel) {
6032                         GdkRegion *tmp_region = NULL;
6033
6034                         ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
6035                                                                cur_page,
6036                                                                view->scale,
6037                                                                &tmp_region);
6038
6039                         if (tmp_region) {
6040                                 new_sel->covered_region = gdk_region_copy (tmp_region);
6041                         }
6042                 }
6043
6044                 /* Now we figure out what needs redrawing */
6045                 if (old_sel && new_sel) {
6046                         if (old_sel->covered_region && new_sel->covered_region) {
6047                                 /* We only want to redraw the areas that have
6048                                  * changed, so we xor the old and new regions
6049                                  * and redraw if it's different */
6050                                 region = gdk_region_copy (old_sel->covered_region);
6051                                 gdk_region_xor (region, new_sel->covered_region);
6052                                 if (gdk_region_empty (region)) {
6053                                         gdk_region_destroy (region);
6054                                         region = NULL;
6055                                 }
6056                         } else if (old_sel->covered_region) {
6057                                 region = gdk_region_copy (old_sel->covered_region);
6058                         } else if (new_sel->covered_region) {
6059                                 region = gdk_region_copy (new_sel->covered_region);
6060                         }
6061                 } else if (old_sel && !new_sel) {
6062                         if (old_sel->covered_region && !gdk_region_empty (old_sel->covered_region)) {
6063                                 region = gdk_region_copy (old_sel->covered_region);
6064                         }
6065                 } else if (!old_sel && new_sel) {
6066                         if (new_sel->covered_region && !gdk_region_empty (new_sel->covered_region)) {
6067                                 region = gdk_region_copy (new_sel->covered_region);
6068                         }
6069                 } else {
6070                         g_assert_not_reached ();
6071                 }
6072
6073                 /* Redraw the damaged region! */
6074                 if (region) {
6075                         GdkRectangle page_area;
6076                         GtkBorder border;
6077
6078                         /* I don't know why but the region is smaller
6079                          * than expected. This hack fixes it, I guess
6080                          * 10 pixels more won't hurt
6081                          */
6082                         gdk_region_shrink (region, -5, -5);
6083
6084                         get_page_extents (view, cur_page, &page_area, &border);
6085                         gdk_region_offset (region,
6086                                            page_area.x + border.left - view->scroll_x,
6087                                            page_area.y + border.top - view->scroll_y);
6088                         gdk_window_invalidate_region (view->layout.bin_window, region, TRUE);
6089                         gdk_region_destroy (region);
6090                 }
6091         }
6092
6093         /* Free the old list, now that we're done with it. */
6094         g_list_foreach (old_list, (GFunc) selection_free, NULL);
6095         g_list_free (old_list);
6096 }
6097
6098 static void
6099 compute_selections (EvView          *view,
6100                     EvSelectionStyle style,
6101                     GdkPoint        *start,
6102                     GdkPoint        *stop)
6103 {
6104         GList *list;
6105
6106         if (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE)
6107                 list = compute_new_selection_rect (view, start, stop);
6108         else
6109                 list = compute_new_selection_text (view, style, start, stop);
6110         merge_selection_region (view, list);
6111 }
6112
6113 /* Free's the selection.  It's up to the caller to queue redraws if needed.
6114  */
6115 static void
6116 selection_free (EvViewSelection *selection)
6117 {
6118         if (selection->covered_region)
6119                 gdk_region_destroy (selection->covered_region);
6120         g_free (selection);
6121 }
6122
6123 static void
6124 clear_selection (EvView *view)
6125 {
6126         g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
6127         g_list_free (view->selection_info.selections);
6128         view->selection_info.selections = NULL;
6129         view->selection_info.in_selection = FALSE;
6130         if (view->pixbuf_cache)
6131                 ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, NULL);
6132         g_object_notify (G_OBJECT (view), "has-selection");
6133 }
6134
6135 void
6136 ev_view_select_all (EvView *view)
6137 {
6138         GList *selections = NULL;
6139         int n_pages, i;
6140
6141         /* Disable selection on rotated pages for the 0.4.0 series */
6142         if (view->rotation != 0)
6143                 return;
6144
6145         clear_selection (view);
6146         
6147         n_pages = ev_document_get_n_pages (view->document);
6148         for (i = 0; i < n_pages; i++) {
6149                 gdouble width, height;
6150                 EvViewSelection *selection;
6151
6152                 get_doc_page_size (view, i, &width, &height);
6153
6154                 selection = g_new0 (EvViewSelection, 1);
6155                 selection->page = i;
6156                 selection->style = EV_SELECTION_STYLE_GLYPH;
6157                 selection->rect.x1 = selection->rect.y1 = 0;
6158                 selection->rect.x2 = width;
6159                 selection->rect.y2 = height;
6160
6161                 selections = g_list_append (selections, selection);
6162         }
6163
6164         merge_selection_region (view, selections);
6165         gtk_widget_queue_draw (GTK_WIDGET (view));
6166 }
6167
6168 gboolean
6169 ev_view_get_has_selection (EvView *view)
6170 {
6171         return view->selection_info.selections != NULL;
6172 }
6173
6174 static char *
6175 get_selected_text (EvView *view)
6176 {
6177         GString *text;
6178         GList *l;
6179         gchar *normalized_text;
6180         EvRenderContext *rc;
6181
6182         text = g_string_new (NULL);
6183         rc = ev_render_context_new (NULL, view->rotation, view->scale);
6184
6185         ev_document_doc_mutex_lock ();
6186
6187         for (l = view->selection_info.selections; l != NULL; l = l->next) {
6188                 EvViewSelection *selection = (EvViewSelection *)l->data;
6189                 EvPage *page;
6190                 gchar *tmp;
6191
6192                 page = ev_document_get_page (view->document, selection->page);
6193                 ev_render_context_set_page (rc, page);
6194                 g_object_unref (page);
6195                 
6196                 tmp = ev_selection_get_selected_text (EV_SELECTION (view->document),
6197                                                       rc, selection->style,
6198                                                       &(selection->rect));
6199
6200                 g_string_append (text, tmp);
6201                 g_free (tmp);
6202         }
6203
6204         g_object_unref (rc);
6205         
6206         ev_document_doc_mutex_unlock ();
6207         
6208         normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC);
6209         g_string_free (text, TRUE);
6210         return normalized_text;
6211 }
6212
6213 static void
6214 ev_view_clipboard_copy (EvView      *view,
6215                         const gchar *text)
6216 {
6217         GtkClipboard *clipboard;
6218
6219         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
6220                                               GDK_SELECTION_CLIPBOARD);
6221         gtk_clipboard_set_text (clipboard, text, -1);
6222 }
6223
6224 void
6225 ev_view_copy (EvView *ev_view)
6226 {
6227         char *text;
6228
6229         if (!EV_IS_SELECTION (ev_view->document))
6230                 return;
6231
6232         text = get_selected_text (ev_view);
6233         ev_view_clipboard_copy (ev_view, text);
6234         g_free (text);
6235 }
6236
6237 static void
6238 ev_view_primary_get_cb (GtkClipboard     *clipboard,
6239                         GtkSelectionData *selection_data,
6240                         guint             info,
6241                         gpointer          data)
6242 {
6243         EvView *ev_view = EV_VIEW (data);
6244
6245         if (ev_view->link_selected) {
6246                 gtk_selection_data_set_text (selection_data,
6247                                              ev_link_action_get_uri (ev_view->link_selected),
6248                                              -1);
6249         } else if (EV_IS_SELECTION (ev_view->document) &&
6250                    ev_view->selection_info.selections) {
6251                 gchar *text;
6252                 
6253                 text = get_selected_text (ev_view);
6254                 if (text) {
6255                         gtk_selection_data_set_text (selection_data, text, -1);
6256                         g_free (text);
6257                 }
6258         }
6259 }
6260
6261 static void
6262 ev_view_primary_clear_cb (GtkClipboard *clipboard,
6263                           gpointer      data)
6264 {
6265         EvView *view = EV_VIEW (data);
6266
6267         clear_selection (view);
6268         clear_link_selected (view);
6269 }
6270
6271 static void
6272 ev_view_update_primary_selection (EvView *ev_view)
6273 {
6274         GtkClipboard *clipboard;
6275
6276         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
6277                                               GDK_SELECTION_PRIMARY);
6278
6279         if (ev_view->selection_info.selections || ev_view->link_selected) {
6280                 GtkTargetList *target_list;
6281                 GtkTargetEntry *targets;
6282                 int n_targets;
6283
6284                 target_list = gtk_target_list_new (NULL, 0);
6285                 gtk_target_list_add_text_targets (target_list, 0);
6286                 targets = gtk_target_table_new_from_list (target_list, &n_targets);
6287                 gtk_target_list_unref (target_list);
6288                 
6289                 if (!gtk_clipboard_set_with_owner (clipboard,
6290                                                    targets, n_targets,
6291                                                    ev_view_primary_get_cb,
6292                                                    ev_view_primary_clear_cb,
6293                                                    G_OBJECT (ev_view)))
6294                         ev_view_primary_clear_cb (clipboard, ev_view);
6295
6296                 gtk_target_table_free (targets, n_targets);
6297         } else {
6298                 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (ev_view))
6299                         gtk_clipboard_clear (clipboard);
6300         }
6301 }
6302
6303 static void
6304 clear_link_selected (EvView *view)
6305 {
6306         if (view->link_selected) {
6307                 g_object_unref (view->link_selected);
6308                 view->link_selected = NULL;
6309         }
6310 }
6311
6312 void
6313 ev_view_copy_link_address (EvView       *view,
6314                            EvLinkAction *action)
6315 {
6316         clear_link_selected (view);
6317         
6318         ev_view_clipboard_copy (view, ev_link_action_get_uri (action));
6319         
6320         view->link_selected = g_object_ref (action);
6321         ev_view_update_primary_selection (view);
6322 }
6323
6324 /*** Cursor operations ***/
6325
6326 static GdkCursor *
6327 ev_view_create_invisible_cursor(void)
6328 {
6329        GdkBitmap *empty;
6330        GdkColor black = { 0, 0, 0, 0 };
6331        static char bits[] = { 0x00 };
6332
6333        empty = gdk_bitmap_create_from_data (NULL, bits, 1, 1);
6334
6335        return gdk_cursor_new_from_pixmap (empty, empty, &black, &black, 0, 0);
6336 }
6337
6338 static void
6339 ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
6340 {
6341         GdkCursor *cursor = NULL;
6342         GdkDisplay *display;
6343         GtkWidget *widget;
6344
6345         if (view->cursor == new_cursor) {
6346                 return;
6347         }
6348
6349         widget = gtk_widget_get_toplevel (GTK_WIDGET (view));
6350         display = gtk_widget_get_display (widget);
6351         view->cursor = new_cursor;
6352
6353         switch (new_cursor) {
6354                 case EV_VIEW_CURSOR_NORMAL:
6355                         gdk_window_set_cursor (view->layout.bin_window, NULL);
6356                         break;
6357                 case EV_VIEW_CURSOR_IBEAM:
6358                         cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
6359                         break;
6360                 case EV_VIEW_CURSOR_LINK:
6361                         cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
6362                         break;
6363                 case EV_VIEW_CURSOR_WAIT:
6364                         cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
6365                         break;
6366                 case EV_VIEW_CURSOR_HIDDEN:
6367                         cursor = ev_view_create_invisible_cursor ();
6368                         break;
6369                 case EV_VIEW_CURSOR_DRAG:
6370                         cursor = gdk_cursor_new_for_display (display, GDK_FLEUR);
6371                         break;
6372                 case EV_VIEW_CURSOR_AUTOSCROLL:
6373                         cursor = gdk_cursor_new_for_display (display, GDK_DOUBLE_ARROW);
6374                         break;
6375         }
6376
6377         if (cursor) {
6378                 gdk_window_set_cursor (view->layout.bin_window, cursor);
6379                 gdk_cursor_unref (cursor);
6380                 gdk_flush();
6381         }
6382 }
6383
6384 void
6385 ev_view_hide_cursor (EvView *view)
6386 {
6387        ev_view_set_cursor (view, EV_VIEW_CURSOR_HIDDEN);
6388 }
6389
6390 void
6391 ev_view_show_cursor (EvView *view)
6392 {
6393        ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
6394 }
6395
6396 static void
6397 ev_view_reset_presentation_state (EvView *view)
6398 {
6399         if (!view->presentation ||
6400             view->presentation_state == EV_PRESENTATION_NORMAL)
6401                 return;
6402
6403         view->presentation_state = EV_PRESENTATION_NORMAL;
6404         gdk_window_set_background (view->layout.bin_window,
6405                                    &GTK_WIDGET (view)->style->black);
6406         gtk_widget_queue_draw (GTK_WIDGET (view));
6407 }
6408
6409 gboolean
6410 ev_view_next_page (EvView *view)
6411 {
6412         int page, n_pages;
6413
6414         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
6415         
6416         if (!view->document)
6417                 return FALSE;
6418
6419         if (view->presentation &&
6420             (view->presentation_state == EV_PRESENTATION_BLACK ||
6421              view->presentation_state == EV_PRESENTATION_WHITE)) {
6422                 ev_view_reset_presentation_state (view);
6423                 return FALSE; 
6424         }
6425
6426         if (view->animation) {
6427                 ev_view_transition_animation_cancel (view->animation, view);
6428         }
6429
6430         ev_view_presentation_transition_stop (view);
6431         ev_view_reset_presentation_state (view);
6432         
6433         page = ev_document_model_get_page (view->model);
6434         n_pages = ev_document_get_n_pages (view->document);
6435
6436         if (view->dual_page && !view->presentation)
6437                 page = page + 2; 
6438         else 
6439                 page = page + 1;
6440
6441         if (page < n_pages) {
6442                 ev_document_model_set_page (view->model, page);
6443                 return TRUE;
6444         } else if (view->presentation && page == n_pages) {
6445                 view->presentation_state = EV_PRESENTATION_END;
6446                 gtk_widget_queue_draw (GTK_WIDGET (view));
6447                 return TRUE;
6448         } else if (view->dual_page && page == n_pages) {
6449                 ev_document_model_set_page (view->model, page - 1);
6450                 return TRUE;
6451         } else {
6452                 return FALSE;
6453         }
6454 }
6455
6456 gboolean
6457 ev_view_previous_page (EvView *view)
6458 {
6459         int page;
6460
6461         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
6462
6463         if (!view->document)
6464                 return FALSE;
6465
6466         if (view->presentation &&
6467             view->presentation_state == EV_PRESENTATION_END) {
6468                 ev_view_reset_presentation_state (view);
6469                 return TRUE;
6470         }
6471         
6472         if (view->presentation && 
6473             (view->presentation_state == EV_PRESENTATION_BLACK ||
6474              view->presentation_state == EV_PRESENTATION_WHITE)) {
6475                 ev_view_reset_presentation_state (view);
6476                 return FALSE; 
6477         }       
6478
6479         if (view->animation) {
6480                 ev_view_transition_animation_cancel (view->animation, view);
6481         }
6482
6483         ev_view_reset_presentation_state (view);
6484
6485         page = ev_document_model_get_page (view->model);
6486
6487         if (view->dual_page && !view->presentation)
6488                 page = page - 2; 
6489         else 
6490                 page = page - 1;
6491
6492         if (page >= 0) {
6493                 ev_document_model_set_page (view->model, page);
6494                 return TRUE;
6495         } else if (ev_view_get_dual_page (view) && page == -1) {
6496                 ev_document_model_set_page (view->model, 0);
6497                 return TRUE;
6498         } else {        
6499                 return FALSE;
6500         }
6501 }
6502