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