]> www.fi.muni.cz Git - evince.git/blob - libview/ev-view.c
bdf738f86b5e8cbc986ca0f5fa671a6d0d130d58
[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_get_preferred_width (GtkWidget *widget,
3139                              gint      *minimum,
3140                              gint      *natural)
3141 {
3142         GtkRequisition requisition;
3143
3144         ev_view_size_request (widget, &requisition);
3145
3146         *minimum = *natural = requisition.width;
3147 }
3148
3149 static void
3150 ev_view_get_preferred_height (GtkWidget *widget,
3151                               gint      *minimum,
3152                               gint      *natural)
3153 {
3154         GtkRequisition requisition;
3155
3156         ev_view_size_request (widget, &requisition);
3157
3158         *minimum = *natural = requisition.height;
3159 }
3160
3161 static void
3162 ev_view_size_allocate (GtkWidget      *widget,
3163                        GtkAllocation  *allocation)
3164 {
3165         EvView *view = EV_VIEW (widget);
3166         GList  *children, *l;
3167         gint    root_x, root_y;
3168
3169         GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
3170
3171         if (!view->document)
3172                 return;
3173
3174         if (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
3175             view->sizing_mode == EV_SIZING_BEST_FIT) {
3176                 GtkRequisition req;
3177
3178                 ev_view_zoom_for_size (view,
3179                                        allocation->width,
3180                                        allocation->height);
3181                 view->internal_size_request = TRUE;
3182                 ev_view_size_request (widget, &req);
3183                 view->internal_size_request = FALSE;
3184         }
3185         
3186         ev_view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
3187         ev_view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
3188
3189         if (view->document)
3190                 view_update_range_and_current_page (view);
3191
3192         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
3193         view->pending_resize = FALSE;
3194         view->pending_point.x = 0;
3195         view->pending_point.y = 0;
3196
3197         children = gtk_container_get_children (GTK_CONTAINER (widget));
3198         for (l = children; l && l->data; l = g_list_next (l)) {
3199                 EvFormField   *field;
3200                 GdkRectangle   view_area;
3201                 EvMappingList *form_field_mapping;
3202                 GtkAllocation  child_allocation;
3203                 GtkRequisition child_requisition;
3204                 GtkWidget     *child = (GtkWidget *)l->data;
3205                 
3206                 field = g_object_get_data (G_OBJECT (child), "form-field");
3207                 if (!field)
3208                         continue;
3209
3210                 form_field_mapping = ev_page_cache_get_form_field_mapping (view->page_cache,
3211                                                                            field->page->index);
3212                 ev_view_get_area_from_mapping (view, field->page->index,
3213                                                form_field_mapping,
3214                                                field, &view_area);
3215
3216                 gtk_widget_get_preferred_size (child, &child_requisition, NULL);
3217                 if (child_requisition.width != view_area.width ||
3218                     child_requisition.height != view_area.height)
3219                         gtk_widget_set_size_request (child, view_area.width, view_area.height);
3220
3221                 gtk_container_child_get (GTK_CONTAINER (widget),
3222                                          child,
3223                                          "x", &child_allocation.x,
3224                                          "y", &child_allocation.y,
3225                                          NULL);
3226                 if (child_allocation.x != view_area.x ||
3227                     child_allocation.y != view_area.y) {
3228                         gtk_fixed_move (GTK_FIXED (widget), child, view_area.x, view_area.y);
3229                 }
3230         }
3231         g_list_free (children);
3232
3233         if (view->window_children)
3234                 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
3235                                        &root_x, &root_y);
3236
3237         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
3238                 EvViewWindowChild *child;
3239                 EvRectangle        doc_rect;
3240                 GdkRectangle       view_rect;
3241
3242                 child = (EvViewWindowChild *)l->data;
3243
3244                 ev_annotation_window_get_rectangle (EV_ANNOTATION_WINDOW (child->window), &doc_rect);
3245                 if (child->moved) {
3246                         doc_rect.x1 = child->orig_x;
3247                         doc_rect.y1 = child->orig_y;
3248                 }
3249                 doc_rect_to_view_rect (view, child->page, &doc_rect, &view_rect);
3250                 view_rect.x -= view->scroll_x;
3251                 view_rect.y -= view->scroll_y;
3252
3253                 if (view_rect.x != child->orig_x || view_rect.y != child->orig_y) {
3254                         child->parent_x = root_x;
3255                         child->parent_y = root_y;
3256                         ev_view_window_child_move (view, child, view_rect.x + root_x, view_rect.y + root_y);
3257                 }
3258         }
3259 }
3260
3261 static gboolean
3262 ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event)
3263 {
3264         EvView *view = EV_VIEW (widget);
3265         guint state;
3266
3267         state = event->state & gtk_accelerator_get_default_mod_mask ();
3268
3269         if (state == GDK_CONTROL_MASK) {
3270                 ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE);
3271                 if (event->direction == GDK_SCROLL_UP ||
3272                     event->direction == GDK_SCROLL_LEFT) {
3273                         if (ev_view_can_zoom_in (view)) {
3274                                 ev_view_zoom_in (view);
3275                         }
3276                 } else {
3277                         if (ev_view_can_zoom_out (view)) {
3278                                 ev_view_zoom_out (view);
3279                         }
3280                 }
3281
3282                 return TRUE;
3283         }
3284
3285         view->jump_to_find_result = FALSE;
3286
3287         /* Shift+Wheel scrolls the in the perpendicular direction */
3288         if (state & GDK_SHIFT_MASK) {
3289                 if (event->direction == GDK_SCROLL_UP)
3290                         event->direction = GDK_SCROLL_LEFT;
3291                 else if (event->direction == GDK_SCROLL_LEFT)
3292                         event->direction = GDK_SCROLL_UP;
3293                 else if (event->direction == GDK_SCROLL_DOWN)
3294                         event->direction = GDK_SCROLL_RIGHT;
3295                 else if (event->direction == GDK_SCROLL_RIGHT)
3296                         event->direction = GDK_SCROLL_DOWN;
3297
3298                 event->state &= ~GDK_SHIFT_MASK;
3299                 state &= ~GDK_SHIFT_MASK;
3300         }
3301
3302         if (state == 0 && view->sizing_mode == EV_SIZING_BEST_FIT && !view->continuous) {
3303                 switch (event->direction) {
3304                         case GDK_SCROLL_DOWN:
3305                         case GDK_SCROLL_RIGHT:
3306                                 ev_view_next_page (view);       
3307                                 break;
3308                         case GDK_SCROLL_UP:
3309                         case GDK_SCROLL_LEFT:
3310                                 ev_view_previous_page (view);
3311                                 break;
3312                 }
3313
3314                 return TRUE;
3315         }
3316
3317         return FALSE;
3318 }
3319
3320 static EvViewSelection *
3321 find_selection_for_page (EvView *view,
3322                          gint    page)
3323 {
3324         GList *list;
3325
3326         for (list = view->selection_info.selections; list != NULL; list = list->next) {
3327                 EvViewSelection *selection;
3328
3329                 selection = (EvViewSelection *) list->data;
3330
3331                 if (selection->page == page)
3332                         return selection;
3333         }
3334
3335         return NULL;
3336 }
3337
3338 static gboolean
3339 ev_view_draw (GtkWidget *widget,
3340               cairo_t   *cr)
3341 {
3342         EvView      *view = EV_VIEW (widget);
3343         gint         i;
3344         GdkRectangle clip_rect;
3345
3346         if (view->loading) {
3347                 show_loading_window (view);
3348         } else if (view->loading_window &&
3349                    gtk_widget_get_visible (view->loading_window)) {
3350                 ev_view_loading_window_move (view);
3351         }
3352
3353         if (view->document == NULL)
3354                 return FALSE;
3355
3356         if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
3357                 return FALSE;
3358
3359         for (i = view->start_page; i >= 0 && i <= view->end_page; i++) {
3360                 GdkRectangle page_area;
3361                 GtkBorder border;
3362                 gboolean page_ready = TRUE;
3363
3364                 if (!ev_view_get_page_extents (view, i, &page_area, &border))
3365                         continue;
3366
3367                 page_area.x -= view->scroll_x;
3368                 page_area.y -= view->scroll_y;
3369
3370                 draw_one_page (view, i, cr, &page_area, &border, &clip_rect, &page_ready);
3371
3372                 if (page_ready && view->find_pages && view->highlight_find_results)
3373                         highlight_find_results (view, cr, i);
3374                 if (page_ready && EV_IS_DOCUMENT_ANNOTATIONS (view->document))
3375                         show_annotation_windows (view, i);
3376                 if (page_ready && view->focus_annotation)
3377                         focus_annotation (view, cr, i, &clip_rect);
3378                 if (page_ready && view->synctex_result)
3379                         highlight_forward_search_results (view, cr, i);
3380         }
3381
3382         if (GTK_WIDGET_CLASS (ev_view_parent_class)->draw)
3383                 GTK_WIDGET_CLASS (ev_view_parent_class)->draw (widget, cr);
3384
3385         return FALSE;
3386 }
3387
3388 static gboolean
3389 ev_view_do_popup_menu (EvView *view,
3390                        gdouble x,
3391                        gdouble y)
3392 {
3393         GList        *items = NULL;
3394         EvLink       *link;
3395         EvImage      *image;
3396         EvAnnotation *annot;
3397
3398         image = ev_view_get_image_at_location (view, x, y);
3399         if (image)
3400                 items = g_list_prepend (items, image);
3401
3402         link = ev_view_get_link_at_location (view, x, y);
3403         if (link)
3404                 items = g_list_prepend (items, link);
3405
3406         annot = ev_view_get_annotation_at_location (view, x, y);
3407         if (annot)
3408                 items = g_list_prepend (items, annot);
3409
3410         g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, items);
3411
3412         g_list_free (items);
3413
3414         return TRUE;
3415 }
3416
3417 static gboolean
3418 ev_view_popup_menu (GtkWidget *widget)
3419 {
3420         gint x, y;
3421         
3422         gtk_widget_get_pointer (widget, &x, &y);
3423         return ev_view_do_popup_menu (EV_VIEW (widget), x, y);
3424 }
3425
3426 static void
3427 get_link_area (EvView       *view,
3428                gint          x,
3429                gint          y,
3430                EvLink       *link,
3431                GdkRectangle *area)
3432 {
3433         EvMappingList *link_mapping;
3434         gint           page;
3435         gint           x_offset = 0, y_offset = 0;
3436
3437         x += view->scroll_x;
3438         y += view->scroll_y;
3439         
3440         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
3441         
3442         link_mapping = ev_page_cache_get_link_mapping (view->page_cache, page);
3443         ev_view_get_area_from_mapping (view, page,
3444                                        link_mapping,
3445                                        link, area);
3446 }
3447
3448 static void
3449 get_annot_area (EvView       *view,
3450                gint          x,
3451                gint          y,
3452                EvAnnotation *annot,
3453                GdkRectangle *area)
3454 {
3455         EvMappingList *annot_mapping;
3456         gint           page;
3457         gint           x_offset = 0, y_offset = 0;
3458
3459         x += view->scroll_x;
3460         y += view->scroll_y;
3461
3462         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
3463
3464         annot_mapping = ev_page_cache_get_annot_mapping (view->page_cache, page);
3465         ev_view_get_area_from_mapping (view, page,
3466                                        annot_mapping,
3467                                        annot, area);
3468 }
3469
3470 static gboolean
3471 ev_view_query_tooltip (GtkWidget  *widget,
3472                        gint        x,
3473                        gint        y,
3474                        gboolean    keyboard_tip,
3475                        GtkTooltip *tooltip)
3476 {
3477         EvView       *view = EV_VIEW (widget);
3478         EvLink       *link;
3479         EvAnnotation *annot;
3480         gchar        *text;
3481
3482         annot = ev_view_get_annotation_at_location (view, x, y);
3483         if (annot) {
3484                 const gchar *contents;
3485
3486                 if ((contents = ev_annotation_get_contents (annot))) {
3487                         GdkRectangle annot_area;
3488
3489                         get_annot_area (view, x, y, annot, &annot_area);
3490                         gtk_tooltip_set_text (tooltip, contents);
3491                         gtk_tooltip_set_tip_area (tooltip, &annot_area);
3492
3493                         return TRUE;
3494                 }
3495         }
3496
3497         link = ev_view_get_link_at_location (view, x, y);
3498         if (!link)
3499                 return FALSE;
3500
3501         text = tip_from_link (view, link);
3502         if (text && g_utf8_validate (text, -1, NULL)) {
3503                 GdkRectangle link_area;
3504
3505                 get_link_area (view, x, y, link, &link_area);
3506                 gtk_tooltip_set_text (tooltip, text);
3507                 gtk_tooltip_set_tip_area (tooltip, &link_area);
3508                 g_free (text);
3509
3510                 return TRUE;
3511         }
3512         g_free (text);
3513
3514         return FALSE;
3515 }
3516
3517 static void
3518 start_selection_for_event (EvView         *view,
3519                            GdkEventButton *event)
3520 {
3521         clear_selection (view);
3522
3523         view->selection_info.start.x = event->x + view->scroll_x;
3524         view->selection_info.start.y = event->y + view->scroll_y;
3525
3526         switch (event->type) {
3527                 case GDK_2BUTTON_PRESS:
3528                         view->selection_info.style = EV_SELECTION_STYLE_WORD;
3529                         break;
3530                 case GDK_3BUTTON_PRESS:
3531                         view->selection_info.style = EV_SELECTION_STYLE_LINE;
3532                         break;
3533                 default:
3534                         view->selection_info.style = EV_SELECTION_STYLE_GLYPH;
3535                         return;
3536         }
3537
3538         /* In case of WORD or LINE, compute selections now */
3539         compute_selections (view,
3540                             view->selection_info.style,
3541                             &(view->selection_info.start),
3542                             &(view->selection_info.start));
3543 }
3544
3545 static gboolean
3546 ev_view_button_press_event (GtkWidget      *widget,
3547                             GdkEventButton *event)
3548 {
3549         EvView *view = EV_VIEW (widget);
3550
3551         if (!view->document)
3552                 return FALSE;
3553         
3554         if (!gtk_widget_has_focus (widget)) {
3555                 gtk_widget_grab_focus (widget);
3556         }
3557
3558         if (view->window_child_focus) {
3559                 EvAnnotationWindow *window;
3560                 EvAnnotation       *annot;
3561
3562                 window = EV_ANNOTATION_WINDOW (view->window_child_focus->window);
3563                 annot = ev_annotation_window_get_annotation (window);
3564                 ev_annotation_window_ungrab_focus (window);
3565                 view->window_child_focus = NULL;
3566         }
3567         
3568         view->pressed_button = event->button;
3569         view->selection_info.in_drag = FALSE;
3570
3571         if (view->adding_annot)
3572                 return FALSE;
3573
3574         if (view->scroll_info.autoscrolling)
3575                 return TRUE;
3576         
3577         switch (event->button) {
3578                 case 1: {
3579                         EvImage *image;
3580                         EvAnnotation *annot;
3581                         EvFormField *field;
3582
3583                         if (event->state & GDK_CONTROL_MASK)
3584                                 return ev_view_synctex_backward_search (view, event->x , event->y);
3585
3586                         if (EV_IS_SELECTION (view->document) && view->selection_info.selections) {
3587                                 if (event->type == GDK_3BUTTON_PRESS) {
3588                                         start_selection_for_event (view, event);
3589                                 } else if (location_in_selected_text (view,
3590                                                                event->x + view->scroll_x,
3591                                                                event->y + view->scroll_y)) {
3592                                         view->selection_info.in_drag = TRUE;
3593                                 } else {
3594                                         start_selection_for_event (view, event);
3595                                 }
3596
3597                                 gtk_widget_queue_draw (widget);
3598                         } else if ((annot = ev_view_get_annotation_at_location (view, event->x, event->y))) {
3599                                 ev_view_handle_annotation (view, annot, event->x, event->y, event->time);
3600                         } else if ((field = ev_view_get_form_field_at_location (view, event->x, event->y))) {
3601                                 ev_view_remove_all (view);
3602                                 ev_view_handle_form_field (view, field, event->x, event->y);
3603                         } else if (!location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y) &&
3604                                    (image = ev_view_get_image_at_location (view, event->x, event->y))) {
3605                                 if (view->image_dnd_info.image)
3606                                         g_object_unref (view->image_dnd_info.image);
3607                                 view->image_dnd_info.image = g_object_ref (image);
3608                                 view->image_dnd_info.in_drag = TRUE;
3609
3610                                 view->image_dnd_info.start.x = event->x + view->scroll_x;
3611                                 view->image_dnd_info.start.y = event->y + view->scroll_y;
3612                         } else {
3613                                 ev_view_remove_all (view);
3614
3615                                 if (view->synctex_result) {
3616                                         g_free (view->synctex_result);
3617                                         view->synctex_result = NULL;
3618                                         gtk_widget_queue_draw (widget);
3619                                 }
3620
3621                                 if (view->focus_annotation)
3622                                         view->focus_annotation = NULL;
3623
3624                                 if (EV_IS_SELECTION (view->document))
3625                                         start_selection_for_event (view, event);
3626                         }
3627                 }                       
3628                         return TRUE;
3629                 case 2:
3630                         /* use root coordinates as reference point because
3631                          * scrolling changes window relative coordinates */
3632                         view->drag_info.start.x = event->x_root;
3633                         view->drag_info.start.y = event->y_root;
3634                         view->drag_info.hadj = gtk_adjustment_get_value (view->hadjustment);
3635                         view->drag_info.vadj = gtk_adjustment_get_value (view->vadjustment);
3636
3637                         ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG);
3638
3639                         return TRUE;
3640                 case 3:
3641                         view->scroll_info.start_y = event->y;
3642                         return ev_view_do_popup_menu (view, event->x, event->y);
3643         }
3644         
3645         return FALSE;
3646 }
3647
3648 static void
3649 ev_view_remove_all (EvView *view)
3650 {
3651         GList *children, *child;
3652
3653         children = gtk_container_get_children (GTK_CONTAINER (view));
3654         for (child = children; child && child->data; child = g_list_next (child)) {
3655                 gtk_container_remove (GTK_CONTAINER (view),
3656                                       GTK_WIDGET (child->data));
3657         }
3658         g_list_free (children);
3659 }
3660
3661 /*** Drag and Drop ***/
3662 static void
3663 ev_view_drag_data_get (GtkWidget        *widget,
3664                        GdkDragContext   *context,
3665                        GtkSelectionData *selection_data,
3666                        guint             info,
3667                        guint             time)
3668 {
3669         EvView *view = EV_VIEW (widget);
3670
3671         switch (info) {
3672                 case TARGET_DND_TEXT:
3673                         if (EV_IS_SELECTION (view->document) &&
3674                             view->selection_info.selections) {
3675                                 gchar *text;
3676
3677                                 text = get_selected_text (view);
3678                                 gtk_selection_data_set_text (selection_data,
3679                                                              text,
3680                                                              strlen (text));
3681                                 g_free (text);
3682                         }
3683                         break;
3684                 case TARGET_DND_IMAGE:
3685                         if (view->image_dnd_info.image) {
3686                                 GdkPixbuf *pixbuf;
3687
3688                                 ev_document_doc_mutex_lock ();
3689                                 pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document),
3690                                                                        view->image_dnd_info.image);
3691                                 ev_document_doc_mutex_unlock ();
3692                                 
3693                                 gtk_selection_data_set_pixbuf (selection_data, pixbuf);
3694                                 g_object_unref (pixbuf);
3695                         }
3696                         break;
3697                 case TARGET_DND_URI:
3698                         if (view->image_dnd_info.image) {
3699                                 GdkPixbuf   *pixbuf;
3700                                 const gchar *tmp_uri;
3701                                 gchar       *uris[2];
3702
3703                                 ev_document_doc_mutex_lock ();
3704                                 pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document),
3705                                                                        view->image_dnd_info.image);
3706                                 ev_document_doc_mutex_unlock ();
3707                                 
3708                                 tmp_uri = ev_image_save_tmp (view->image_dnd_info.image, pixbuf);
3709                                 g_object_unref (pixbuf);
3710
3711                                 uris[0] = (gchar *)tmp_uri;
3712                                 uris[1] = NULL;
3713                                 gtk_selection_data_set_uris (selection_data, uris);
3714                         }
3715         }
3716 }
3717
3718 static gboolean
3719 ev_view_drag_motion (GtkWidget      *widget,
3720                      GdkDragContext *context,
3721                      gint            x,
3722                      gint            y,
3723                      guint           time)
3724 {
3725         if (gtk_drag_get_source_widget (context) == widget)
3726                 gdk_drag_status (context, 0, time);
3727         else
3728                 gdk_drag_status (context, gdk_drag_context_get_suggested_action (context), time);
3729         
3730         return TRUE;
3731 }
3732                      
3733 static gboolean
3734 selection_update_idle_cb (EvView *view)
3735 {
3736         compute_selections (view,
3737                             view->selection_info.style,
3738                             &view->selection_info.start,
3739                             &view->motion);
3740         view->selection_update_id = 0;
3741         return FALSE;
3742 }
3743
3744 static gboolean
3745 selection_scroll_timeout_cb (EvView *view)
3746 {       
3747         gint x, y, shift = 0;
3748         GtkWidget *widget = GTK_WIDGET (view);
3749         GtkAllocation allocation;
3750
3751         gtk_widget_get_allocation (widget, &allocation);
3752         gtk_widget_get_pointer (widget, &x, &y);
3753
3754         if (y > allocation.height) {
3755                 shift = (y - allocation.height) / 2;
3756         } else if (y < 0) {
3757                 shift = y / 2;
3758         }
3759
3760         if (shift)
3761                 gtk_adjustment_set_value (view->vadjustment,
3762                                           CLAMP (gtk_adjustment_get_value (view->vadjustment) + shift,
3763                                                  gtk_adjustment_get_lower (view->vadjustment),
3764                                                  gtk_adjustment_get_upper (view->vadjustment) -
3765                                                  gtk_adjustment_get_page_size (view->vadjustment)));
3766
3767         if (x > allocation.width) {
3768                 shift = (x - allocation.width) / 2;
3769         } else if (x < 0) {
3770                 shift = x / 2;
3771         }
3772
3773         if (shift)
3774                 gtk_adjustment_set_value (view->hadjustment,
3775                                           CLAMP (gtk_adjustment_get_value (view->hadjustment) + shift,
3776                                                  gtk_adjustment_get_lower (view->hadjustment),
3777                                                  gtk_adjustment_get_upper (view->hadjustment) -
3778                                                  gtk_adjustment_get_page_size (view->hadjustment)));
3779
3780         return TRUE;
3781 }
3782
3783 static gboolean
3784 ev_view_drag_update_momentum (EvView *view)
3785 {
3786         int i;
3787         if (!view->drag_info.in_drag)
3788                 return FALSE;
3789         
3790         for (i = DRAG_HISTORY - 1; i > 0; i--) {
3791                 view->drag_info.buffer[i].x = view->drag_info.buffer[i-1].x;
3792                 view->drag_info.buffer[i].y = view->drag_info.buffer[i-1].y;
3793         }
3794
3795         /* Momentum is a moving average of 10ms granularity over
3796          * the last 100ms with each 10ms stored in buffer. 
3797          */
3798         
3799         view->drag_info.momentum.x = (view->drag_info.buffer[DRAG_HISTORY - 1].x - view->drag_info.buffer[0].x);
3800         view->drag_info.momentum.y = (view->drag_info.buffer[DRAG_HISTORY - 1].y - view->drag_info.buffer[0].y);
3801
3802         return TRUE;
3803 }
3804
3805 static gboolean
3806 ev_view_scroll_drag_release (EvView *view)
3807 {
3808         gdouble dhadj_value, dvadj_value;
3809         gdouble oldhadjustment, oldvadjustment;
3810         gdouble h_page_size, v_page_size;
3811         gdouble h_upper, v_upper;
3812         GtkAllocation allocation;
3813
3814         view->drag_info.momentum.x /= 1.2;
3815         view->drag_info.momentum.y /= 1.2; /* Alter these constants to change "friction" */
3816
3817         gtk_widget_get_allocation (GTK_WIDGET (view), &allocation);
3818
3819         h_page_size = gtk_adjustment_get_page_size (view->hadjustment);
3820         v_page_size = gtk_adjustment_get_page_size (view->vadjustment);
3821
3822         dhadj_value = h_page_size *
3823                       (gdouble)view->drag_info.momentum.x / allocation.width;
3824         dvadj_value = v_page_size *
3825                       (gdouble)view->drag_info.momentum.y / allocation.height;
3826
3827         oldhadjustment = gtk_adjustment_get_value (view->hadjustment);
3828         oldvadjustment = gtk_adjustment_get_value (view->vadjustment);
3829
3830         h_upper = gtk_adjustment_get_upper (view->hadjustment);
3831         v_upper = gtk_adjustment_get_upper (view->vadjustment);
3832
3833         /* When we reach the edges, we need either to absorb some momentum and bounce by
3834          * multiplying it on -0.5 or stop scrolling by setting momentum to 0. */
3835         if (((oldhadjustment + dhadj_value) > (h_upper - h_page_size)) ||
3836             ((oldhadjustment + dhadj_value) < 0))
3837                 view->drag_info.momentum.x = 0;
3838         if (((oldvadjustment + dvadj_value) > (v_upper - v_page_size)) ||
3839             ((oldvadjustment + dvadj_value) < 0))
3840                 view->drag_info.momentum.y = 0;
3841
3842         gtk_adjustment_set_value (view->hadjustment,
3843                                   MIN (oldhadjustment + dhadj_value,
3844                                        h_upper - h_page_size));
3845         gtk_adjustment_set_value (view->vadjustment,
3846                                   MIN (oldvadjustment + dvadj_value,
3847                                        v_upper - v_page_size));
3848
3849         if (((view->drag_info.momentum.x < 1) && (view->drag_info.momentum.x > -1)) &&
3850             ((view->drag_info.momentum.y < 1) && (view->drag_info.momentum.y > -1)))
3851                 return FALSE;
3852         else
3853                 return TRUE;
3854 }
3855
3856 static gboolean
3857 ev_view_motion_notify_event (GtkWidget      *widget,
3858                              GdkEventMotion *event)
3859 {
3860         EvView    *view = EV_VIEW (widget);
3861         GdkWindow *window;
3862         gint       x, y;
3863
3864         if (!view->document)
3865                 return FALSE;
3866
3867         window = gtk_widget_get_window (widget);
3868
3869         if (event->is_hint || event->window != window) {
3870             gtk_widget_get_pointer (widget, &x, &y);
3871         } else {
3872             x = event->x;
3873             y = event->y;
3874         }
3875
3876         if (view->scroll_info.autoscrolling) {
3877                 view->scroll_info.last_y = y;
3878                 return TRUE;
3879         }
3880
3881         if (view->selection_info.in_drag) {
3882                 if (gtk_drag_check_threshold (widget,
3883                                               view->selection_info.start.x,
3884                                               view->selection_info.start.y,
3885                                               x, y)) {
3886                         GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
3887
3888                         gtk_target_list_add_text_targets (target_list, TARGET_DND_TEXT);
3889
3890                         gtk_drag_begin (widget, target_list,
3891                                         GDK_ACTION_COPY,
3892                                         1, (GdkEvent *)event);
3893
3894                         view->selection_info.in_drag = FALSE;
3895
3896                         gtk_target_list_unref (target_list);
3897
3898                         return TRUE;
3899                 }
3900         } else if (view->image_dnd_info.in_drag) {
3901                 if (gtk_drag_check_threshold (widget,
3902                                               view->selection_info.start.x,
3903                                               view->selection_info.start.y,
3904                                               x, y)) {
3905                         GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
3906
3907                         gtk_target_list_add_uri_targets (target_list, TARGET_DND_URI);
3908                         gtk_target_list_add_image_targets (target_list, TARGET_DND_IMAGE, TRUE);
3909
3910                         gtk_drag_begin (widget, target_list,
3911                                         GDK_ACTION_COPY,
3912                                         1, (GdkEvent *)event);
3913
3914                         view->image_dnd_info.in_drag = FALSE;
3915
3916                         gtk_target_list_unref (target_list);
3917
3918                         return TRUE;
3919                 }
3920         }
3921         
3922         switch (view->pressed_button) {
3923         case 1:
3924                 /* For the Evince 0.4.x release, we limit selection to un-rotated
3925                  * documents only.
3926                  */
3927                 if (view->rotation != 0)
3928                         return FALSE;
3929
3930                 /* Schedule timeout to scroll during selection and additionally 
3931                  * scroll once to allow arbitrary speed. */
3932                 if (!view->selection_scroll_id)
3933                     view->selection_scroll_id = g_timeout_add (SCROLL_TIME,
3934                                                                (GSourceFunc)selection_scroll_timeout_cb,
3935                                                                view);
3936                 else 
3937                     selection_scroll_timeout_cb (view);
3938
3939                 view->selection_info.in_selection = TRUE;
3940                 view->motion.x = x + view->scroll_x;
3941                 view->motion.y = y + view->scroll_y;
3942
3943                 /* Queue an idle to handle the motion.  We do this because      
3944                  * handling any selection events in the motion could be slower  
3945                  * than new motion events reach us.  We always put it in the    
3946                  * idle to make sure we catch up and don't visibly lag the      
3947                  * mouse. */
3948                 if (!view->selection_update_id)
3949                         view->selection_update_id = g_idle_add ((GSourceFunc)selection_update_idle_cb, view);
3950
3951                 return TRUE;
3952         case 2:
3953                 if (!view->drag_info.in_drag) {
3954                         gboolean start;
3955                         int i;
3956
3957                         start = gtk_drag_check_threshold (widget,
3958                                                           view->drag_info.start.x,
3959                                                           view->drag_info.start.y,
3960                                                           event->x_root,
3961                                                           event->y_root);
3962                         view->drag_info.in_drag = start;
3963                         view->drag_info.drag_timeout_id = g_timeout_add (10,
3964                                 (GSourceFunc)ev_view_drag_update_momentum, view);
3965                         /* Set 100 to choose how long it takes to build up momentum */
3966                         /* Clear out previous momentum info: */
3967                         for (i = 0; i < DRAG_HISTORY; i++) {
3968                                 view->drag_info.buffer[i].x = event->x;
3969                                 view->drag_info.buffer[i].y = event->y;
3970                         }
3971                         view->drag_info.momentum.x = 0;
3972                         view->drag_info.momentum.y = 0;
3973                 }
3974
3975                 if (view->drag_info.in_drag) {
3976                         int dx, dy;
3977                         gdouble dhadj_value, dvadj_value;
3978                         GtkAllocation allocation;
3979
3980                         view->drag_info.buffer[0].x = event->x;
3981                         view->drag_info.buffer[0].y = event->y;
3982
3983                         dx = event->x_root - view->drag_info.start.x;
3984                         dy = event->y_root - view->drag_info.start.y;
3985
3986                         gtk_widget_get_allocation (widget, &allocation);
3987
3988                         dhadj_value = gtk_adjustment_get_page_size (view->hadjustment) *
3989                                       (gdouble)dx / allocation.width;
3990                         dvadj_value = gtk_adjustment_get_page_size (view->vadjustment) *
3991                                       (gdouble)dy / allocation.height;
3992
3993                         /* clamp scrolling to visible area */
3994                         gtk_adjustment_set_value (view->hadjustment,
3995                                                   MIN (view->drag_info.hadj - dhadj_value,
3996                                                        gtk_adjustment_get_upper (view->hadjustment) -
3997                                                        gtk_adjustment_get_page_size (view->hadjustment)));
3998                         gtk_adjustment_set_value (view->vadjustment,
3999                                                   MIN (view->drag_info.vadj - dvadj_value,
4000                                                        gtk_adjustment_get_upper (view->vadjustment) -
4001                                                        gtk_adjustment_get_page_size (view->vadjustment)));
4002
4003                         return TRUE;
4004                 }
4005
4006                 break;
4007         default:
4008                 ev_view_handle_cursor_over_xy (view, x, y);
4009         } 
4010
4011         return FALSE;
4012 }
4013
4014 static gboolean
4015 ev_view_button_release_event (GtkWidget      *widget,
4016                               GdkEventButton *event)
4017 {
4018         EvView *view = EV_VIEW (widget);
4019         EvLink *link = NULL;
4020
4021         view->image_dnd_info.in_drag = FALSE;
4022
4023         if (view->scroll_info.autoscrolling) {
4024                 ev_view_autoscroll_stop (view);
4025                 view->pressed_button = -1;
4026
4027                 return TRUE;
4028         }
4029
4030         if (view->pressed_button == 1 && event->state & GDK_CONTROL_MASK) {
4031                 view->pressed_button = -1;
4032                 return TRUE;
4033         }
4034
4035         if (view->drag_info.in_drag) {
4036                 view->drag_info.release_timeout_id =
4037                         g_timeout_add (20,
4038                                        (GSourceFunc)ev_view_scroll_drag_release, view);
4039         }
4040
4041         if (view->document && !view->drag_info.in_drag && view->pressed_button != 3) {
4042                 link = ev_view_get_link_at_location (view, event->x, event->y);
4043         }
4044
4045         view->drag_info.in_drag = FALSE;
4046
4047         if (view->adding_annot && view->pressed_button == 1) {
4048                 view->adding_annot = FALSE;
4049                 ev_view_handle_cursor_over_xy (view, event->x, event->y);
4050                 view->pressed_button = -1;
4051
4052                 ev_view_create_annotation (view,
4053                                            view->adding_annot_type,
4054                                            event->x + view->scroll_x,
4055                                            event->y + view->scroll_y);
4056
4057                 return FALSE;
4058         }
4059
4060         if (view->pressed_button == 2) {
4061                 ev_view_handle_cursor_over_xy (view, event->x, event->y);
4062         }
4063
4064         view->pressed_button = -1;
4065
4066         if (view->selection_scroll_id) {
4067             g_source_remove (view->selection_scroll_id);
4068             view->selection_scroll_id = 0;
4069         }
4070         if (view->selection_update_id) {
4071             g_source_remove (view->selection_update_id);
4072             view->selection_update_id = 0;
4073         }
4074
4075         if (view->selection_info.selections) {
4076                 clear_link_selected (view);
4077                 ev_view_update_primary_selection (view);
4078                 
4079                 if (view->selection_info.in_drag) {
4080                         clear_selection (view);
4081                         gtk_widget_queue_draw (widget);
4082                 }
4083                 
4084                 view->selection_info.in_drag = FALSE;
4085         } else if (link) {
4086                 if (event->button == 2) {
4087                         EvLinkAction    *action;
4088                         EvLinkActionType type;
4089
4090                         action = ev_link_get_action (link);
4091                         if (!action)
4092                                 return FALSE;
4093
4094                         type = ev_link_action_get_action_type (action);
4095                         if (type == EV_LINK_ACTION_TYPE_GOTO_DEST) {
4096                                 g_signal_emit (view,
4097                                                signals[SIGNAL_EXTERNAL_LINK],
4098                                                0, action);
4099                         }
4100                 } else {
4101                         ev_view_handle_link (view, link);
4102                 }
4103         }
4104
4105         return FALSE;
4106 }
4107
4108 static gboolean
4109 ev_view_key_press_event (GtkWidget   *widget,
4110                          GdkEventKey *event)
4111 {
4112         EvView *view = EV_VIEW (widget);
4113
4114         if (!view->document)
4115                 return FALSE;
4116
4117         if (!gtk_widget_has_focus (widget)) {
4118                 /* Forward key events to current focused window child */
4119                 if (view->window_child_focus) {
4120                         GdkEventKey *new_event;
4121                         gboolean     handled;
4122
4123                         new_event = (GdkEventKey *) gdk_event_copy ((GdkEvent *)event);
4124                         g_object_unref (new_event->window);
4125                         new_event->window = gtk_widget_get_window (view->window_child_focus->window);
4126                         if (new_event->window)
4127                                 g_object_ref (new_event->window);
4128                         gtk_widget_realize (view->window_child_focus->window);
4129                         handled = gtk_widget_event (view->window_child_focus->window, (GdkEvent *)new_event);
4130                         gdk_event_free ((GdkEvent *)new_event);
4131
4132                         return handled;
4133                 }
4134
4135                 return FALSE;
4136         }
4137
4138         return gtk_bindings_activate_event (G_OBJECT (widget), event);
4139 }
4140
4141 static gint
4142 ev_view_focus_in (GtkWidget     *widget,
4143                   GdkEventFocus *event)
4144 {
4145         if (EV_VIEW (widget)->pixbuf_cache)
4146                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
4147         gtk_widget_queue_draw (widget);
4148
4149         return FALSE;
4150 }
4151
4152 static gint
4153 ev_view_focus_out (GtkWidget     *widget,
4154                    GdkEventFocus *event)
4155 {
4156         if (EV_VIEW (widget)->pixbuf_cache)
4157                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
4158         gtk_widget_queue_draw (widget);
4159
4160         return FALSE;
4161 }
4162
4163 static gboolean
4164 ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
4165 {
4166         EvView *view = EV_VIEW (widget);
4167
4168         if (view->cursor != EV_VIEW_CURSOR_NORMAL)
4169                 ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
4170
4171         return FALSE;
4172 }
4173
4174 static gboolean
4175 ev_view_enter_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
4176 {
4177         EvView *view = EV_VIEW (widget);
4178
4179         ev_view_handle_cursor_over_xy (view, event->x, event->y);
4180     
4181         return FALSE;
4182 }
4183
4184 static void
4185 ev_view_style_set (GtkWidget *widget,
4186                    GtkStyle  *old_style)
4187 {
4188         if (EV_VIEW (widget)->pixbuf_cache)
4189                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
4190
4191         GTK_WIDGET_CLASS (ev_view_parent_class)->style_set (widget, old_style);
4192 }
4193
4194 /*** Drawing ***/
4195
4196 static void
4197 draw_rubberband (EvView             *view,
4198                  cairo_t            *cr,
4199                  const GdkRectangle *rect,
4200                  gdouble             alpha)
4201 {
4202         GtkStyle *style;
4203         const GdkColor *fill_color_gdk;
4204         gdouble   r, g, b;
4205
4206         style = gtk_widget_get_style (GTK_WIDGET (view));
4207         fill_color_gdk = &style->base[GTK_STATE_SELECTED];
4208         r = fill_color_gdk->red / 65535.;
4209         g = fill_color_gdk->green / 65535.;
4210         b = fill_color_gdk->blue / 65535.;
4211
4212         cairo_save (cr);
4213
4214         cairo_set_source_rgba (cr, r, g, b, alpha);
4215         cairo_rectangle (cr,
4216                          rect->x - view->scroll_x,
4217                          rect->y - view->scroll_y,
4218                          rect->width, rect->height);
4219         cairo_fill_preserve (cr);
4220
4221         cairo_set_line_width (cr, 0.5);
4222         cairo_set_source_rgb (cr, r, g, b);
4223         cairo_stroke (cr);
4224
4225         cairo_restore (cr);
4226 }
4227
4228
4229 static void
4230 highlight_find_results (EvView *view,
4231                         cairo_t *cr,
4232                         int page)
4233 {
4234         gint       i, n_results = 0;
4235         n_results = ev_view_find_get_n_results (view, page);
4236
4237         for (i = 0; i < n_results; i++) {
4238                 EvRectangle *rectangle;
4239                 GdkRectangle view_rectangle;
4240                 gdouble      alpha;
4241
4242                 if (i == view->find_result && page == view->current_page) {
4243                         alpha = 0.6;
4244                 } else {
4245                         alpha = 0.3;
4246                 }
4247
4248                 rectangle = ev_view_find_get_result (view, page, i);
4249                 doc_rect_to_view_rect (view, page, rectangle, &view_rectangle);
4250                 draw_rubberband (view, cr, &view_rectangle, alpha);
4251         }
4252 }
4253
4254 static void
4255 highlight_forward_search_results (EvView *view,
4256                                   cairo_t *cr,
4257                                   int page)
4258 {
4259         GdkRectangle rect;
4260         EvMapping   *mapping = view->synctex_result;
4261
4262         if (GPOINTER_TO_INT (mapping->data) != page)
4263                 return;
4264
4265         doc_rect_to_view_rect (view, page, &mapping->area, &rect);
4266
4267         cairo_save (cr);
4268         cairo_set_source_rgb (cr, 1., 0., 0.);
4269         cairo_rectangle (cr,
4270                          rect.x - view->scroll_x,
4271                          rect.y - view->scroll_y,
4272                          rect.width, rect.height);
4273         cairo_stroke (cr);
4274         cairo_restore (cr);
4275 }
4276
4277 static void
4278 focus_annotation (EvView       *view,
4279                   cairo_t      *cr,
4280                   gint          page,
4281                   GdkRectangle *clip)
4282 {
4283         GtkWidget    *widget = GTK_WIDGET (view);
4284         GdkRectangle  rect;
4285         EvMapping    *mapping = view->focus_annotation;
4286         EvAnnotation *annot = (EvAnnotation *)mapping->data;
4287
4288         if (ev_annotation_get_page_index (annot) != page)
4289                 return;
4290
4291         doc_rect_to_view_rect (view, page, &mapping->area, &rect);
4292
4293         gtk_paint_focus (gtk_widget_get_style (widget),
4294                          cr,
4295                          gtk_widget_get_state (widget),
4296                          widget, NULL,
4297                          rect.x - view->scroll_x,
4298                          rect.y - view->scroll_y,
4299                          rect.width + 1, rect.height + 1);
4300 }
4301
4302 static void
4303 ev_view_loading_window_move (EvView *view)
4304 {
4305         GtkWidget       *widget = GTK_WIDGET (view);
4306         EvLoadingWindow *window = EV_LOADING_WINDOW (view->loading_window);
4307         gint             root_x, root_y;
4308         gint             window_width;
4309         GtkAllocation    allocation;
4310
4311         gtk_widget_get_allocation (widget, &allocation);
4312         gdk_window_get_origin (gtk_widget_get_window (widget), &root_x, &root_y);
4313         ev_loading_window_get_size (window, &window_width, NULL);
4314
4315         root_x += allocation.width - window_width - 10;
4316         root_y += 10;
4317
4318         ev_loading_window_move (window, root_x, root_y);
4319 }
4320
4321 static gboolean
4322 show_loading_window_cb (EvView *view)
4323 {
4324         if (!view->loading_window) {
4325                 GtkWindow *parent;
4326                 GdkScreen *screen;
4327
4328                 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
4329                 view->loading_window = ev_loading_window_new (parent);
4330
4331                 /* Show the window off screen to get a valid size asap */
4332                 screen = gtk_widget_get_screen (GTK_WIDGET (view));
4333                 gtk_window_move (GTK_WINDOW (view->loading_window),
4334                                  gdk_screen_get_width (screen) + 1,
4335                                  gdk_screen_get_height (screen) + 1);
4336                 gtk_widget_show (view->loading_window);
4337         }
4338
4339         ev_view_loading_window_move (view);
4340
4341         gtk_widget_show (view->loading_window);
4342
4343         view->loading_timeout = 0;
4344
4345         return FALSE;
4346 }
4347
4348 static void
4349 show_loading_window (EvView *view)
4350 {
4351         if (view->loading_window && gtk_widget_get_visible (view->loading_window)) {
4352                 ev_view_loading_window_move (view);
4353                 return;
4354         }
4355
4356         if (!view->loading_timeout) {
4357                 view->loading_timeout =
4358                         g_timeout_add_full (G_PRIORITY_LOW,
4359                                             0.5, (GSourceFunc)show_loading_window_cb,
4360                                             view, NULL);
4361         }
4362 }
4363
4364 static void
4365 hide_loading_window (EvView *view)
4366 {
4367         if (view->loading_timeout) {
4368                 g_source_remove (view->loading_timeout);
4369                 view->loading_timeout = 0;
4370         }
4371
4372         if (view->loading_window && gtk_widget_get_visible (view->loading_window)) {
4373                 gtk_widget_hide (view->loading_window);
4374         }
4375 }
4376
4377 static void
4378 draw_one_page (EvView       *view,
4379                gint          page,
4380                cairo_t      *cr,
4381                GdkRectangle *page_area,
4382                GtkBorder    *border,
4383                GdkRectangle *expose_area,
4384                gboolean     *page_ready)
4385 {
4386         GdkRectangle overlap;
4387         GdkRectangle real_page_area;
4388         gint         current_page;
4389         gboolean     inverted_colors;
4390
4391         g_assert (view->document);
4392
4393         if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
4394                 return;
4395
4396         /* Render the document itself */
4397         real_page_area = *page_area;
4398
4399         real_page_area.x += border->left;
4400         real_page_area.y += border->top;
4401         real_page_area.width -= (border->left + border->right);
4402         real_page_area.height -= (border->top + border->bottom);
4403         *page_ready = TRUE;
4404
4405         current_page = ev_document_model_get_page (view->model);
4406         inverted_colors = ev_document_model_get_inverted_colors (view->model);
4407         ev_document_misc_paint_one_page (cr,
4408                                          GTK_WIDGET (view),
4409                                          page_area, border,
4410                                          page == current_page,
4411                                          inverted_colors);
4412
4413         if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
4414                 gint             width, height;
4415                 gint             page_width, page_height;
4416                 cairo_surface_t *page_surface = NULL;
4417                 gint             selection_width, selection_height;
4418                 cairo_surface_t *selection_surface = NULL;
4419
4420                 page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
4421
4422                 if (!page_surface) {
4423                         if (page == current_page)
4424                                 show_loading_window (view);
4425
4426                         *page_ready = FALSE;
4427
4428                         return;
4429                 }
4430
4431                 if (page == current_page)
4432                         hide_loading_window (view);
4433
4434                 ev_view_get_page_size (view, page, &width, &height);
4435
4436                 page_width = cairo_image_surface_get_width (page_surface);
4437                 page_height = cairo_image_surface_get_height (page_surface);
4438
4439                 cairo_save (cr);
4440                 cairo_translate (cr, overlap.x, overlap.y);
4441
4442                 if (width != page_width || height != page_height) {
4443                         cairo_pattern_set_filter (cairo_get_source (cr),
4444                                                   CAIRO_FILTER_FAST);
4445                         cairo_scale (cr,
4446                                      (gdouble)width / page_width,
4447                                      (gdouble)height / page_height);
4448                 }
4449
4450                 cairo_surface_set_device_offset (page_surface,
4451                                                  overlap.x - real_page_area.x,
4452                                                  overlap.y - real_page_area.y);
4453                 cairo_set_source_surface (cr, page_surface, 0, 0);
4454                 cairo_paint (cr);
4455                 cairo_restore (cr);
4456                 
4457                 /* Get the selection pixbuf iff we have something to draw */
4458                 if (find_selection_for_page (view, page) &&
4459                     view->selection_mode == EV_VIEW_SELECTION_TEXT) {
4460                         selection_surface =
4461                                 ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
4462                                                                        page,
4463                                                                        view->scale,
4464                                                                        NULL);
4465                 }
4466
4467                 if (!selection_surface) {
4468                         return;
4469                 }
4470
4471                 selection_width = cairo_image_surface_get_width (selection_surface);
4472                 selection_height = cairo_image_surface_get_height (selection_surface);
4473
4474                 cairo_save (cr);
4475                 cairo_translate (cr, overlap.x, overlap.y);
4476
4477                 if (width != selection_width || height != selection_height) {
4478                         cairo_pattern_set_filter (cairo_get_source (cr),
4479                                                   CAIRO_FILTER_FAST);
4480                         cairo_scale (cr,
4481                                      (gdouble)width / selection_width,
4482                                      (gdouble)height / selection_height);
4483                 }
4484
4485                 cairo_surface_set_device_offset (selection_surface,
4486                                                  overlap.x - real_page_area.x,
4487                                                  overlap.y - real_page_area.y);
4488
4489                 cairo_set_source_surface (cr, selection_surface, 0, 0);
4490                 cairo_paint (cr);
4491                 cairo_restore (cr);
4492         }
4493 }
4494
4495 /*** GObject functions ***/
4496
4497 static void
4498 ev_view_finalize (GObject *object)
4499 {
4500         EvView *view = EV_VIEW (object);
4501
4502         clear_selection (view);
4503         clear_link_selected (view);
4504
4505         if (view->synctex_result) {
4506                 g_free (view->synctex_result);
4507                 view->synctex_result = NULL;
4508         }
4509
4510         if (view->image_dnd_info.image)
4511                 g_object_unref (view->image_dnd_info.image);
4512         view->image_dnd_info.image = NULL;
4513
4514         G_OBJECT_CLASS (ev_view_parent_class)->finalize (object);
4515 }
4516
4517 static void
4518 ev_view_dispose (GObject *object)
4519 {
4520         EvView *view = EV_VIEW (object);
4521
4522         if (view->model) {
4523                 g_object_unref (view->model);
4524                 view->model = NULL;
4525         }
4526
4527         if (view->pixbuf_cache) {
4528                 g_object_unref (view->pixbuf_cache);
4529                 view->pixbuf_cache = NULL;
4530         }
4531
4532         if (view->document) {
4533                 g_object_unref (view->document);
4534                 view->document = NULL;
4535         }
4536
4537         if (view->page_cache) {
4538                 g_object_unref (view->page_cache);
4539                 view->page_cache = NULL;
4540         }
4541
4542         ev_view_window_children_free (view);
4543
4544         if (view->selection_scroll_id) {
4545             g_source_remove (view->selection_scroll_id);
4546             view->selection_scroll_id = 0;
4547         }
4548
4549         if (view->selection_update_id) {
4550             g_source_remove (view->selection_update_id);
4551             view->selection_update_id = 0;
4552         }
4553
4554         if (view->scroll_info.timeout_id) {
4555             g_source_remove (view->scroll_info.timeout_id);
4556             view->scroll_info.timeout_id = 0;
4557         }
4558
4559         if (view->drag_info.drag_timeout_id) {
4560                 g_source_remove (view->drag_info.drag_timeout_id);
4561                 view->drag_info.drag_timeout_id = 0;
4562         }
4563
4564         if (view->drag_info.release_timeout_id) {
4565                 g_source_remove (view->drag_info.release_timeout_id);
4566                 view->drag_info.release_timeout_id = 0;
4567         }
4568
4569         if (view->loading_timeout) {
4570                 g_source_remove (view->loading_timeout);
4571                 view->loading_timeout = 0;
4572         }
4573
4574         gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (view), NULL);
4575         gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (view), NULL);
4576
4577         G_OBJECT_CLASS (ev_view_parent_class)->dispose (object);
4578 }
4579
4580 static void
4581 ev_view_get_property (GObject     *object,
4582                       guint        prop_id,
4583                       GValue      *value,
4584                       GParamSpec  *pspec)
4585 {
4586         EvView *view = EV_VIEW (object);
4587
4588         switch (prop_id) {
4589         case PROP_HADJUSTMENT:
4590                 g_value_set_object (value, view->hadjustment);
4591                 break;
4592         case PROP_VADJUSTMENT:
4593                 g_value_set_object (value, view->vadjustment);
4594                 break;
4595         case PROP_HSCROLL_POLICY:
4596                 g_value_set_enum (value, view->hscroll_policy);
4597                 break;
4598         case PROP_VSCROLL_POLICY:
4599                 g_value_set_enum (value, view->vscroll_policy);
4600                 break;
4601         default:
4602                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4603                 break;
4604         }
4605 }
4606
4607 static void
4608 ev_view_set_property (GObject      *object,
4609                       guint         prop_id,
4610                       const GValue *value,
4611                       GParamSpec   *pspec)
4612 {
4613         EvView *view = EV_VIEW (object);
4614
4615         switch (prop_id) {
4616         case PROP_HADJUSTMENT:
4617                 ev_view_set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL,
4618                                                (GtkAdjustment *) g_value_get_object (value));
4619                 break;
4620         case PROP_VADJUSTMENT:
4621                 ev_view_set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL,
4622                                                (GtkAdjustment *) g_value_get_object (value));
4623                 break;
4624         case PROP_HSCROLL_POLICY:
4625                 view->hscroll_policy = g_value_get_enum (value);
4626                 gtk_widget_queue_resize (GTK_WIDGET (view));
4627                 break;
4628         case PROP_VSCROLL_POLICY:
4629                 view->vscroll_policy = g_value_get_enum (value);
4630                 gtk_widget_queue_resize (GTK_WIDGET (view));
4631                 break;
4632         default:
4633                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4634                 break;
4635         }
4636 }
4637
4638 static AtkObject *
4639 ev_view_get_accessible (GtkWidget *widget)
4640 {
4641         static gboolean first_time = TRUE;
4642
4643         if (first_time) {
4644                 AtkObjectFactory *factory;
4645                 AtkRegistry *registry;
4646                 GType derived_type; 
4647                 GType derived_atk_type; 
4648
4649                 /*
4650                  * Figure out whether accessibility is enabled by looking at the
4651                  * type of the accessible object which would be created for
4652                  * the parent type of EvView.
4653                  */
4654                 derived_type = g_type_parent (EV_TYPE_VIEW);
4655
4656                 registry = atk_get_default_registry ();
4657                 factory = atk_registry_get_factory (registry,
4658                                                     derived_type);
4659                 derived_atk_type = atk_object_factory_get_accessible_type (factory);
4660                 if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE)) {
4661                         atk_registry_set_factory_type (registry,
4662                                                        EV_TYPE_VIEW,
4663                                                        ev_view_accessible_factory_get_type ());
4664                         EV_VIEW (widget)->a11y_enabled = TRUE;
4665                 }
4666                 first_time = FALSE;
4667         } 
4668         return GTK_WIDGET_CLASS (ev_view_parent_class)->get_accessible (widget);
4669 }
4670
4671 static void
4672 ev_view_class_init (EvViewClass *class)
4673 {
4674         GObjectClass *object_class = G_OBJECT_CLASS (class);
4675         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
4676         GtkBindingSet *binding_set;
4677
4678         object_class->get_property = ev_view_get_property;
4679         object_class->set_property = ev_view_set_property;
4680         object_class->dispose = ev_view_dispose;
4681         object_class->finalize = ev_view_finalize;
4682
4683         widget_class->draw = ev_view_draw;
4684         widget_class->button_press_event = ev_view_button_press_event;
4685         widget_class->motion_notify_event = ev_view_motion_notify_event;
4686         widget_class->button_release_event = ev_view_button_release_event;
4687         widget_class->key_press_event = ev_view_key_press_event;
4688         widget_class->focus_in_event = ev_view_focus_in;
4689         widget_class->focus_out_event = ev_view_focus_out;
4690         widget_class->get_accessible = ev_view_get_accessible;
4691         widget_class->get_preferred_width = ev_view_get_preferred_width;
4692         widget_class->get_preferred_height = ev_view_get_preferred_height;
4693         widget_class->size_allocate = ev_view_size_allocate;
4694         widget_class->scroll_event = ev_view_scroll_event;
4695         widget_class->enter_notify_event = ev_view_enter_notify_event;
4696         widget_class->leave_notify_event = ev_view_leave_notify_event;
4697         widget_class->style_set = ev_view_style_set;
4698         widget_class->drag_data_get = ev_view_drag_data_get;
4699         widget_class->drag_motion = ev_view_drag_motion;
4700         widget_class->popup_menu = ev_view_popup_menu;
4701         widget_class->query_tooltip = ev_view_query_tooltip;
4702
4703         class->binding_activated = ev_view_scroll;
4704
4705         /* Scrollable interface */
4706         g_object_class_override_property (object_class, PROP_HADJUSTMENT, "hadjustment");
4707         g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment");
4708         g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
4709         g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
4710
4711         signals[SIGNAL_BINDING_ACTIVATED] = g_signal_new ("binding_activated",
4712                          G_TYPE_FROM_CLASS (object_class),
4713                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4714                          G_STRUCT_OFFSET (EvViewClass, binding_activated),
4715                          NULL, NULL,
4716                          ev_view_marshal_VOID__ENUM_BOOLEAN,
4717                          G_TYPE_NONE, 2,
4718                          GTK_TYPE_SCROLL_TYPE,
4719                          G_TYPE_BOOLEAN);
4720         signals[SIGNAL_HANDLE_LINK] = g_signal_new ("handle-link",
4721                          G_TYPE_FROM_CLASS (object_class),
4722                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4723                          G_STRUCT_OFFSET (EvViewClass, handle_link),
4724                          NULL, NULL,
4725                          g_cclosure_marshal_VOID__OBJECT,
4726                          G_TYPE_NONE, 1,
4727                          G_TYPE_OBJECT);
4728         signals[SIGNAL_EXTERNAL_LINK] = g_signal_new ("external-link",
4729                          G_TYPE_FROM_CLASS (object_class),
4730                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4731                          G_STRUCT_OFFSET (EvViewClass, external_link),
4732                          NULL, NULL,
4733                          g_cclosure_marshal_VOID__OBJECT,
4734                          G_TYPE_NONE, 1,
4735                          G_TYPE_OBJECT);
4736         signals[SIGNAL_POPUP_MENU] = g_signal_new ("popup",
4737                          G_TYPE_FROM_CLASS (object_class),
4738                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4739                          G_STRUCT_OFFSET (EvViewClass, popup_menu),
4740                          NULL, NULL,
4741                          g_cclosure_marshal_VOID__POINTER,
4742                          G_TYPE_NONE, 1,
4743                          G_TYPE_POINTER);
4744         signals[SIGNAL_SELECTION_CHANGED] = g_signal_new ("selection-changed",
4745                          G_TYPE_FROM_CLASS (object_class),
4746                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4747                          G_STRUCT_OFFSET (EvViewClass, selection_changed),
4748                          NULL, NULL,
4749                          g_cclosure_marshal_VOID__VOID,
4750                          G_TYPE_NONE, 0,
4751                          G_TYPE_NONE);
4752         signals[SIGNAL_SYNC_SOURCE] = g_signal_new ("sync-source",
4753                          G_TYPE_FROM_CLASS (object_class),
4754                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4755                          G_STRUCT_OFFSET (EvViewClass, sync_source),
4756                          NULL, NULL,
4757                          g_cclosure_marshal_VOID__POINTER,
4758                          G_TYPE_NONE, 1,
4759                          G_TYPE_POINTER);
4760         signals[SIGNAL_ANNOT_ADDED] = g_signal_new ("annot-added",
4761                          G_TYPE_FROM_CLASS (object_class),
4762                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4763                          G_STRUCT_OFFSET (EvViewClass, annot_added),
4764                          NULL, NULL,
4765                          g_cclosure_marshal_VOID__OBJECT,
4766                          G_TYPE_NONE, 1,
4767                          EV_TYPE_ANNOTATION);
4768         signals[SIGNAL_LAYERS_CHANGED] = g_signal_new ("layers-changed",
4769                          G_TYPE_FROM_CLASS (object_class),
4770                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4771                          G_STRUCT_OFFSET (EvViewClass, layers_changed),
4772                          NULL, NULL,
4773                          g_cclosure_marshal_VOID__VOID,
4774                          G_TYPE_NONE, 0,
4775                          G_TYPE_NONE);
4776
4777         binding_set = gtk_binding_set_by_class (class);
4778
4779         add_scroll_binding_keypad (binding_set, GDK_KEY_Left,  0, GTK_SCROLL_STEP_BACKWARD, TRUE);
4780         add_scroll_binding_keypad (binding_set, GDK_KEY_Right, 0, GTK_SCROLL_STEP_FORWARD,  TRUE);
4781         add_scroll_binding_keypad (binding_set, GDK_KEY_Left,  GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, TRUE);
4782         add_scroll_binding_keypad (binding_set, GDK_KEY_Right, GDK_MOD1_MASK, GTK_SCROLL_STEP_UP,  TRUE);
4783         add_scroll_binding_keypad (binding_set, GDK_KEY_Up,    0, GTK_SCROLL_STEP_BACKWARD, FALSE);
4784         add_scroll_binding_keypad (binding_set, GDK_KEY_Down,  0, GTK_SCROLL_STEP_FORWARD,  FALSE);
4785         add_scroll_binding_keypad (binding_set, GDK_KEY_Up,    GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, FALSE);
4786         add_scroll_binding_keypad (binding_set, GDK_KEY_Down,  GDK_MOD1_MASK, GTK_SCROLL_STEP_UP,  FALSE);
4787         gtk_binding_entry_add_signal (binding_set, GDK_KEY_H, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4788                                       GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, TRUE);
4789         gtk_binding_entry_add_signal (binding_set, GDK_KEY_J, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4790                                       GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, FALSE);
4791         gtk_binding_entry_add_signal (binding_set, GDK_KEY_K, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4792                                       GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, FALSE);
4793         gtk_binding_entry_add_signal (binding_set, GDK_KEY_L, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4794                                       GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, TRUE);
4795         
4796 }
4797
4798 static void
4799 ev_view_init (EvView *view)
4800 {
4801         gtk_widget_set_has_window (GTK_WIDGET (view), TRUE);
4802         gtk_widget_set_can_focus (GTK_WIDGET (view), TRUE);
4803         gtk_widget_set_redraw_on_allocate (GTK_WIDGET (view), FALSE);
4804         gtk_container_set_resize_mode (GTK_CONTAINER (view), GTK_RESIZE_QUEUE);
4805
4806         gtk_widget_set_events (GTK_WIDGET (view),
4807                                GDK_EXPOSURE_MASK |
4808                                GDK_BUTTON_PRESS_MASK |
4809                                GDK_BUTTON_RELEASE_MASK |
4810                                GDK_SCROLL_MASK |
4811                                GDK_KEY_PRESS_MASK |
4812                                GDK_POINTER_MOTION_MASK |
4813                                GDK_POINTER_MOTION_HINT_MASK |
4814                                GDK_ENTER_NOTIFY_MASK |
4815                                GDK_LEAVE_NOTIFY_MASK);
4816
4817         view->start_page = -1;
4818         view->end_page = -1;
4819         view->spacing = 5;
4820         view->scale = 1.0;
4821         view->current_page = 0;
4822         view->pressed_button = -1;
4823         view->cursor = EV_VIEW_CURSOR_NORMAL;
4824         view->drag_info.in_drag = FALSE;
4825         view->scroll_info.autoscrolling = FALSE;
4826         view->selection_info.selections = NULL;
4827         view->selection_info.in_selection = FALSE;
4828         view->selection_info.in_drag = FALSE;
4829         view->selection_mode = EV_VIEW_SELECTION_TEXT;
4830         view->continuous = TRUE;
4831         view->dual_page = FALSE;
4832         view->fullscreen = FALSE;
4833         view->sizing_mode = EV_SIZING_FIT_WIDTH;
4834         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
4835         view->jump_to_find_result = TRUE;
4836         view->highlight_find_results = FALSE;
4837 }
4838
4839 /*** Callbacks ***/
4840
4841 static void
4842 ev_view_change_page (EvView *view,
4843                      gint    new_page)
4844 {
4845         gint x, y;
4846
4847         view->current_page = new_page;
4848         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
4849
4850         hide_loading_window (view);
4851
4852         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4853         ev_view_handle_cursor_over_xy (view, x, y);
4854
4855         gtk_widget_queue_resize (GTK_WIDGET (view));
4856 }
4857
4858 static void
4859 job_finished_cb (EvPixbufCache  *pixbuf_cache,
4860                  cairo_region_t *region,
4861                  EvView         *view)
4862 {
4863         if (region) {
4864                 gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)), region, TRUE);
4865         } else {
4866                 gtk_widget_queue_draw (GTK_WIDGET (view));
4867         }
4868 }
4869
4870 static void
4871 ev_view_page_changed_cb (EvDocumentModel *model,
4872                          gint             old_page,
4873                          gint             new_page,
4874                          EvView          *view)
4875 {
4876         if (!view->document)
4877                 return;
4878
4879         if (view->current_page != new_page) {
4880                 ev_view_change_page (view, new_page);
4881         } else {
4882                 gtk_widget_queue_draw (GTK_WIDGET (view));
4883         }
4884
4885         view->find_result = 0;
4886 }
4887
4888 static void
4889 on_adjustment_value_changed (GtkAdjustment *adjustment,
4890                              EvView        *view)
4891 {
4892         int dx = 0, dy = 0;
4893         gint x, y;
4894         gint value;
4895         GList *children, *l;
4896
4897         if (!gtk_widget_get_realized (GTK_WIDGET (view)))
4898                 return;
4899
4900         if (view->hadjustment) {
4901                 value = (gint) gtk_adjustment_get_value (view->hadjustment);
4902                 dx = view->scroll_x - value;
4903                 view->scroll_x = value;
4904         } else {
4905                 view->scroll_x = 0;
4906         }
4907
4908         if (view->vadjustment) {
4909                 value = (gint) gtk_adjustment_get_value (view->vadjustment);
4910                 dy = view->scroll_y - value;
4911                 view->scroll_y = value;
4912         } else {
4913                 view->scroll_y = 0;
4914         }
4915
4916         children = gtk_container_get_children (GTK_CONTAINER (view));
4917         for (l = children; l && l->data; l = g_list_next (l)) {
4918                 gint       child_x, child_y;
4919                 GtkWidget *child = (GtkWidget *)l->data;
4920                 
4921                 gtk_container_child_get (GTK_CONTAINER (view),
4922                                          child,
4923                                          "x", &child_x,
4924                                          "y", &child_y,
4925                                          NULL);
4926                 gtk_fixed_move (GTK_FIXED (view), child, child_x + dx, child_y + dy);
4927         }
4928         g_list_free (children);
4929
4930         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
4931                 EvViewWindowChild *child;
4932
4933                 child = (EvViewWindowChild *)l->data;
4934
4935                 ev_view_window_child_move (view, child, child->x + dx, child->y + dy);
4936         }
4937         
4938         if (view->pending_resize) {
4939                 gtk_widget_queue_draw (GTK_WIDGET (view));
4940         } else {
4941                 gdk_window_scroll (gtk_widget_get_window (GTK_WIDGET (view)), dx, dy);
4942         }
4943
4944         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4945         ev_view_handle_cursor_over_xy (view, x, y);
4946
4947         if (view->document)
4948                 view_update_range_and_current_page (view);
4949 }
4950
4951 GtkWidget*
4952 ev_view_new (void)
4953 {
4954         GtkWidget *view;
4955
4956         view = g_object_new (EV_TYPE_VIEW, NULL);
4957
4958         return view;
4959 }
4960
4961 static void
4962 setup_caches (EvView *view)
4963 {
4964         gboolean inverted_colors;
4965
4966         view->height_to_page_cache = ev_view_get_height_to_page_cache (view);
4967         view->pixbuf_cache = ev_pixbuf_cache_new (GTK_WIDGET (view), view->model, view->pixbuf_cache_size);
4968         view->page_cache = ev_page_cache_new (view->document);
4969         if (view->a11y_enabled) {
4970                 EvJobPageDataFlags flags = ev_page_cache_get_flags (view->page_cache);
4971
4972                 ev_page_cache_set_flags (view->page_cache,
4973                                          flags |
4974                                          EV_PAGE_DATA_INCLUDE_TEXT_LAYOUT |
4975                                          EV_PAGE_DATA_INCLUDE_TEXT);
4976         }
4977         inverted_colors = ev_document_model_get_inverted_colors (view->model);
4978         ev_pixbuf_cache_set_inverted_colors (view->pixbuf_cache, inverted_colors);
4979         g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view);
4980 }
4981
4982 static void
4983 clear_caches (EvView *view)
4984 {
4985         if (view->pixbuf_cache) {
4986                 g_object_unref (view->pixbuf_cache);
4987                 view->pixbuf_cache = NULL;
4988         }
4989
4990         if (view->page_cache) {
4991                 g_object_unref (view->page_cache);
4992                 view->page_cache = NULL;
4993         }
4994 }
4995
4996 /**
4997  * ev_view_set_page_cache_size:
4998  * @view:
4999  * @cache_size:
5000  *
5001  * Sets the maximum size in bytes that will be used to cache
5002  * rendered pages. Use 0 to disable caching rendered pages.
5003  *
5004  * Note that this limit doesn't affect the current visible page range,
5005  * which will always be rendered. In order to limit the total memory used
5006  * you have to use ev_document_model_set_max_scale() too.
5007  *
5008  */
5009 void
5010 ev_view_set_page_cache_size (EvView *view,
5011                              gsize   cache_size)
5012 {
5013         if (view->pixbuf_cache_size == cache_size)
5014                 return;
5015
5016         view->pixbuf_cache_size = cache_size;
5017         if (view->pixbuf_cache)
5018                 ev_pixbuf_cache_set_max_size (view->pixbuf_cache, cache_size);
5019 }
5020
5021 void
5022 ev_view_set_loading (EvView       *view,
5023                      gboolean      loading)
5024 {
5025         if (view->loading && !loading)
5026                 hide_loading_window (view);
5027         view->loading = loading;
5028         gtk_widget_queue_draw (GTK_WIDGET (view));
5029 }
5030
5031 static gboolean
5032 ev_view_autoscroll_cb (EvView *view)
5033 {
5034         gdouble speed, value;
5035
5036         /* If the user stops autoscrolling, autoscrolling will be
5037          * set to false but the timeout will continue; stop the timeout: */
5038         if (!view->scroll_info.autoscrolling) {
5039                 view->scroll_info.timeout_id = 0;
5040                 return FALSE;
5041         }
5042         
5043         if (view->scroll_info.last_y > view->scroll_info.start_y && 
5044                 (view->scroll_info.last_y < view->scroll_info.start_y))
5045                 return TRUE; 
5046
5047         /* Replace 100 with your speed of choice: The lower the faster.
5048          * Replace 3 with another speed of choice: The higher, the faster it accelerated
5049          *      based on the distance of the starting point from the mouse
5050          * (All also effected by the timeout interval of this callback) */
5051
5052         if (view->scroll_info.start_y > view->scroll_info.last_y)
5053                 speed = -pow ((((gdouble)view->scroll_info.start_y - view->scroll_info.last_y) / 100), 3);
5054         else
5055                 speed = pow ((((gdouble)view->scroll_info.last_y - view->scroll_info.start_y) / 100), 3);
5056         
5057         value = gtk_adjustment_get_value (view->vadjustment);
5058         value = CLAMP (value + speed, 0,
5059                        gtk_adjustment_get_upper (view->vadjustment) -
5060                        gtk_adjustment_get_page_size (view->vadjustment));
5061         gtk_adjustment_set_value (view->vadjustment, value);
5062         
5063         return TRUE;
5064
5065 }
5066
5067 void
5068 ev_view_autoscroll_start (EvView *view)
5069 {
5070         gint x, y;
5071         
5072         g_return_if_fail (EV_IS_VIEW (view));
5073
5074         if (view->scroll_info.autoscrolling)
5075                 return;
5076         
5077         view->scroll_info.autoscrolling = TRUE;
5078         view->scroll_info.timeout_id =
5079                 g_timeout_add (20, (GSourceFunc)ev_view_autoscroll_cb,
5080                                view);
5081         
5082         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
5083         ev_view_handle_cursor_over_xy (view, x, y);
5084 }
5085
5086 void
5087 ev_view_autoscroll_stop (EvView *view)
5088 {
5089         gint x, y;
5090         
5091         g_return_if_fail (EV_IS_VIEW (view));
5092
5093         if (!view->scroll_info.autoscrolling)
5094                 return;
5095
5096         view->scroll_info.autoscrolling = FALSE;
5097         if (view->scroll_info.timeout_id) {
5098                 g_source_remove (view->scroll_info.timeout_id);
5099                 view->scroll_info.timeout_id = 0;
5100         }
5101
5102         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
5103         ev_view_handle_cursor_over_xy (view, x, y);
5104 }
5105
5106 static void
5107 ev_view_document_changed_cb (EvDocumentModel *model,
5108                              GParamSpec      *pspec,
5109                              EvView          *view)
5110 {
5111         EvDocument *document = ev_document_model_get_document (model);
5112
5113         if (document != view->document) {
5114                 gint current_page;
5115
5116                 clear_caches (view);
5117
5118                 if (view->document) {
5119                         g_object_unref (view->document);
5120                 }
5121
5122                 view->document = document;
5123                 view->find_result = 0;
5124
5125                 if (view->document) {
5126                         view->loading = FALSE;
5127                         g_object_ref (view->document);
5128                         setup_caches (view);
5129                 }
5130
5131                 current_page = ev_document_model_get_page (model);
5132                 if (view->current_page != current_page) {
5133                         ev_view_change_page (view, current_page);
5134                 } else {
5135                         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
5136                         gtk_widget_queue_resize (GTK_WIDGET (view));
5137                 }
5138         }
5139 }
5140
5141 static void
5142 ev_view_rotation_changed_cb (EvDocumentModel *model,
5143                              GParamSpec      *pspec,
5144                              EvView          *view)
5145 {
5146         gint rotation = ev_document_model_get_rotation (model);
5147
5148         view->rotation = rotation;
5149
5150         if (view->pixbuf_cache) {
5151                 ev_pixbuf_cache_clear (view->pixbuf_cache);
5152                 if (!ev_document_is_page_size_uniform (view->document))
5153                         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
5154                 gtk_widget_queue_resize (GTK_WIDGET (view));
5155         }
5156
5157         ev_view_remove_all (view);
5158
5159         if (rotation != 0)
5160                 clear_selection (view);
5161 }
5162
5163 static void
5164 ev_view_inverted_colors_changed_cb (EvDocumentModel *model,
5165                                     GParamSpec      *pspec,
5166                                     EvView          *view)
5167 {
5168         if (view->pixbuf_cache) {
5169                 gboolean inverted_colors;
5170
5171                 inverted_colors = ev_document_model_get_inverted_colors (model);
5172                 ev_pixbuf_cache_set_inverted_colors (view->pixbuf_cache, inverted_colors);
5173                 gtk_widget_queue_draw (GTK_WIDGET (view));
5174         }
5175 }
5176
5177 static void
5178 ev_view_sizing_mode_changed_cb (EvDocumentModel *model,
5179                                 GParamSpec      *pspec,
5180                                 EvView          *view)
5181 {
5182         EvSizingMode mode = ev_document_model_get_sizing_mode (model);
5183
5184         view->sizing_mode = mode;
5185         if (mode != EV_SIZING_FREE)
5186                 gtk_widget_queue_resize (GTK_WIDGET (view));
5187 }
5188
5189 #define EPSILON 0.0000001
5190 static void
5191 ev_view_scale_changed_cb (EvDocumentModel *model,
5192                           GParamSpec      *pspec,
5193                           EvView          *view)
5194 {
5195         gdouble scale = ev_document_model_get_scale (model);
5196
5197         if (ABS (view->scale - scale) < EPSILON)
5198                 return;
5199
5200         view->scale = scale;
5201
5202         view->pending_resize = TRUE;
5203         if (view->sizing_mode == EV_SIZING_FREE)
5204                 gtk_widget_queue_resize (GTK_WIDGET (view));
5205 }
5206
5207 static void
5208 ev_view_continuous_changed_cb (EvDocumentModel *model,
5209                                GParamSpec      *pspec,
5210                                EvView          *view)
5211 {
5212         gboolean continuous = ev_document_model_get_continuous (model);
5213
5214         view->continuous = continuous;
5215         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
5216         gtk_widget_queue_resize (GTK_WIDGET (view));
5217 }
5218
5219 static void
5220 ev_view_dual_page_changed_cb (EvDocumentModel *model,
5221                               GParamSpec      *pspec,
5222                               EvView          *view)
5223 {
5224         gboolean dual_page = ev_document_model_get_dual_page (model);
5225
5226         view->dual_page = dual_page;
5227         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
5228         /* FIXME: if we're keeping the pixbuf cache around, we should extend the
5229          * preload_cache_size to be 2 if dual_page is set.
5230          */
5231         gtk_widget_queue_resize (GTK_WIDGET (view));
5232 }
5233
5234 static void
5235 ev_view_fullscreen_changed_cb (EvDocumentModel *model,
5236                                GParamSpec      *pspec,
5237                                EvView          *view)
5238 {
5239         gboolean fullscreen = ev_document_model_get_fullscreen (model);
5240
5241         view->fullscreen = fullscreen;
5242         gtk_widget_queue_resize (GTK_WIDGET (view));
5243 }
5244
5245 void
5246 ev_view_set_model (EvView          *view,
5247                    EvDocumentModel *model)
5248 {
5249         g_return_if_fail (EV_IS_VIEW (view));
5250         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
5251
5252         if (model == view->model)
5253                 return;
5254
5255         if (view->model) {
5256                 g_signal_handlers_disconnect_by_func (view->model,
5257                                                       ev_view_document_changed_cb,
5258                                                       view);
5259                 g_signal_handlers_disconnect_by_func (view->model,
5260                                                       ev_view_page_changed_cb,
5261                                                       view);
5262                 g_object_unref (view->model);
5263         }
5264         view->model = g_object_ref (model);
5265
5266         /* Initialize view from model */
5267         view->rotation = ev_document_model_get_rotation (view->model);
5268         view->sizing_mode = ev_document_model_get_sizing_mode (view->model);
5269         view->scale = ev_document_model_get_scale (view->model);
5270         view->continuous = ev_document_model_get_continuous (view->model);
5271         view->dual_page = ev_document_model_get_dual_page (view->model);
5272         view->fullscreen = ev_document_model_get_fullscreen (view->model);
5273         ev_view_document_changed_cb (view->model, NULL, view);
5274
5275         g_signal_connect (view->model, "notify::document",
5276                           G_CALLBACK (ev_view_document_changed_cb),
5277                           view);
5278         g_signal_connect (view->model, "notify::rotation",
5279                           G_CALLBACK (ev_view_rotation_changed_cb),
5280                           view);
5281         g_signal_connect (view->model, "notify::inverted-colors",
5282                           G_CALLBACK (ev_view_inverted_colors_changed_cb),
5283                           view);
5284         g_signal_connect (view->model, "notify::sizing-mode",
5285                           G_CALLBACK (ev_view_sizing_mode_changed_cb),
5286                           view);
5287         g_signal_connect (view->model, "notify::scale",
5288                           G_CALLBACK (ev_view_scale_changed_cb),
5289                           view);
5290         g_signal_connect (view->model, "notify::continuous",
5291                           G_CALLBACK (ev_view_continuous_changed_cb),
5292                           view);
5293         g_signal_connect (view->model, "notify::dual-page",
5294                           G_CALLBACK (ev_view_dual_page_changed_cb),
5295                           view);
5296         g_signal_connect (view->model, "notify::fullscreen",
5297                           G_CALLBACK (ev_view_fullscreen_changed_cb),
5298                           view);
5299         g_signal_connect (view->model, "page-changed",
5300                           G_CALLBACK (ev_view_page_changed_cb),
5301                           view);
5302 }
5303
5304 static void
5305 ev_view_reload_page (EvView         *view,
5306                      gint            page,
5307                      cairo_region_t *region)
5308 {
5309         ev_pixbuf_cache_reload_page (view->pixbuf_cache,
5310                                      region,
5311                                      page,
5312                                      view->rotation,
5313                                      view->scale);
5314 }
5315
5316 void
5317 ev_view_reload (EvView *view)
5318 {
5319         ev_pixbuf_cache_clear (view->pixbuf_cache);
5320         view_update_range_and_current_page (view);
5321 }
5322
5323 /*** Zoom and sizing mode ***/
5324
5325 gboolean
5326 ev_view_can_zoom_in (EvView *view)
5327 {
5328         return view->scale * ZOOM_IN_FACTOR <= ev_document_model_get_max_scale (view->model);
5329 }
5330
5331 gboolean
5332 ev_view_can_zoom_out (EvView *view)
5333 {
5334         return view->scale * ZOOM_OUT_FACTOR >= ev_document_model_get_min_scale (view->model);
5335 }
5336
5337 void
5338 ev_view_zoom_in (EvView *view)
5339 {
5340         gdouble scale;
5341
5342         g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
5343
5344         view->pending_scroll = SCROLL_TO_CENTER;
5345         scale = ev_document_model_get_scale (view->model) * ZOOM_IN_FACTOR;
5346         ev_document_model_set_scale (view->model, scale);
5347 }
5348
5349 void
5350 ev_view_zoom_out (EvView *view)
5351 {
5352         gdouble scale;
5353
5354         g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
5355
5356         view->pending_scroll = SCROLL_TO_CENTER;
5357         scale = ev_document_model_get_scale (view->model) * ZOOM_OUT_FACTOR;
5358         ev_document_model_set_scale (view->model, scale);
5359 }
5360
5361 static double
5362 zoom_for_size_fit_width (gdouble doc_width,
5363                          gdouble doc_height,
5364                          int     target_width,
5365                          int     target_height)
5366 {
5367         return (double)target_width / doc_width;
5368 }
5369
5370 static double
5371 zoom_for_size_fit_height (gdouble doc_width,
5372                           gdouble doc_height,
5373                           int     target_width,
5374                           int     target_height)
5375 {
5376         return (double)target_height / doc_height;
5377 }
5378
5379 static double
5380 zoom_for_size_best_fit (gdouble doc_width,
5381                         gdouble doc_height,
5382                         int     target_width,
5383                         int     target_height)
5384 {
5385         double w_scale;
5386         double h_scale;
5387
5388         w_scale = (double)target_width / doc_width;
5389         h_scale = (double)target_height / doc_height;
5390
5391         return MIN (w_scale, h_scale);
5392 }
5393
5394 static void
5395 ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
5396                                                 int     width,
5397                                                 int     height)
5398 {
5399         gdouble doc_width, doc_height;
5400         GtkBorder border;
5401         gdouble scale;
5402         gint sb_size;
5403
5404         ev_document_get_max_page_size (view->document, &doc_width, &doc_height);
5405         if (view->rotation == 90 || view->rotation == 270) {
5406                 gdouble tmp;
5407
5408                 tmp = doc_width;
5409                 doc_width = doc_height;
5410                 doc_height = tmp;
5411         }
5412
5413         compute_border (view, doc_width, doc_height, &border);
5414
5415         doc_width *= 2;
5416         width -= (2 * (border.left + border.right) + 3 * view->spacing);
5417         height -= (border.top + border.bottom + 2 * view->spacing - 1);
5418
5419         sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
5420
5421         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
5422                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
5423         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5424                 scale = zoom_for_size_best_fit (doc_width, doc_height, width - sb_size, height);
5425         else
5426                 g_assert_not_reached ();
5427
5428         ev_document_model_set_scale (view->model, scale);
5429 }
5430
5431 static void
5432 ev_view_zoom_for_size_continuous (EvView *view,
5433                                   int     width,
5434                                   int     height)
5435 {
5436         gdouble doc_width, doc_height;
5437         GtkBorder border;
5438         gdouble scale;
5439         gint sb_size;
5440
5441         ev_document_get_max_page_size (view->document, &doc_width, &doc_height);
5442         if (view->rotation == 90 || view->rotation == 270) {
5443                 gdouble tmp;
5444
5445                 tmp = doc_width;
5446                 doc_width = doc_height;
5447                 doc_height = tmp;
5448         }
5449
5450         compute_border (view, doc_width, doc_height, &border);
5451
5452         width -= (border.left + border.right + 2 * view->spacing);
5453         height -= (border.top + border.bottom + 2 * view->spacing - 1);
5454
5455         sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
5456
5457         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
5458                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
5459         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5460                 scale = zoom_for_size_best_fit (doc_width, doc_height, width - sb_size, height);
5461         else
5462                 g_assert_not_reached ();
5463
5464         ev_document_model_set_scale (view->model, scale);
5465 }
5466
5467 static void
5468 ev_view_zoom_for_size_dual_page (EvView *view,
5469                                  int     width,
5470                                  int     height)
5471 {
5472         GtkBorder border;
5473         gdouble doc_width, doc_height;
5474         gdouble scale;
5475         gint other_page;
5476
5477         other_page = view->current_page ^ 1;
5478
5479         /* Find the largest of the two. */
5480         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
5481         if (other_page < ev_document_get_n_pages (view->document)) {
5482                 gdouble width_2, height_2;
5483
5484                 get_doc_page_size (view, other_page, &width_2, &height_2);
5485                 if (width_2 > doc_width)
5486                         doc_width = width_2;
5487                 if (height_2 > doc_height)
5488                         doc_height = height_2;
5489         }
5490         compute_border (view, width, height, &border);
5491
5492         doc_width = doc_width * 2;
5493         width -= ((border.left + border.right)* 2 + 3 * view->spacing);
5494         height -= (border.top + border.bottom + 2 * view->spacing);
5495
5496         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
5497                 gint sb_size;
5498
5499                 sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
5500                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
5501         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5502                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5503         else
5504                 g_assert_not_reached ();
5505
5506         ev_document_model_set_scale (view->model, scale);
5507 }
5508
5509 static void
5510 ev_view_zoom_for_size_single_page (EvView *view,
5511                                    int     width,
5512                                    int     height)
5513 {
5514         gdouble doc_width, doc_height;
5515         GtkBorder border;
5516         gdouble scale;
5517
5518         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
5519
5520         /* Get an approximate border */
5521         compute_border (view, width, height, &border);
5522
5523         width -= (border.left + border.right + 2 * view->spacing);
5524         height -= (border.top + border.bottom + 2 * view->spacing);
5525
5526         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
5527                 gint sb_size;
5528
5529                 sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
5530                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
5531         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5532                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5533         else
5534                 g_assert_not_reached ();
5535
5536         ev_document_model_set_scale (view->model, scale);
5537 }
5538
5539 static void
5540 ev_view_zoom_for_size (EvView *view,
5541                        int     width,
5542                        int     height)
5543 {
5544         g_return_if_fail (EV_IS_VIEW (view));
5545         g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
5546                           view->sizing_mode == EV_SIZING_BEST_FIT);
5547         g_return_if_fail (width >= 0);
5548         g_return_if_fail (height >= 0);
5549
5550         if (view->document == NULL)
5551                 return;
5552
5553         if (view->continuous && view->dual_page)
5554                 ev_view_zoom_for_size_continuous_and_dual_page (view, width, height);
5555         else if (view->continuous)
5556                 ev_view_zoom_for_size_continuous (view, width, height);
5557         else if (view->dual_page)
5558                 ev_view_zoom_for_size_dual_page (view, width, height);
5559         else
5560                 ev_view_zoom_for_size_single_page (view, width, height);
5561 }
5562
5563 /*** Find ***/
5564 static gint
5565 ev_view_find_get_n_results (EvView *view, gint page)
5566 {
5567         return view->find_pages ? g_list_length (view->find_pages[page]) : 0;
5568 }
5569
5570 static EvRectangle *
5571 ev_view_find_get_result (EvView *view, gint page, gint result)
5572 {
5573         return view->find_pages ? (EvRectangle *) g_list_nth_data (view->find_pages[page], result) : NULL;
5574 }
5575
5576 static void
5577 jump_to_find_result (EvView *view)
5578 {
5579         gint n_results;
5580         gint page = view->current_page;
5581
5582         n_results = ev_view_find_get_n_results (view, page);
5583
5584         if (n_results > 0 && view->find_result < n_results) {
5585                 EvRectangle *rect;
5586                 GdkRectangle view_rect;
5587
5588                 rect = ev_view_find_get_result (view, page, view->find_result);
5589                 doc_rect_to_view_rect (view, page, rect, &view_rect);
5590                 ensure_rectangle_is_visible (view, &view_rect);
5591                 view->jump_to_find_result = FALSE;
5592         }
5593 }
5594
5595 /**
5596  * jump_to_find_page
5597  * @view: #EvView instance
5598  * @direction: Direction to look
5599  * @shift: Shift from current page
5600  *
5601  * Jumps to the first page that has occurences of searched word.
5602  * Uses a direction where to look and a shift from current page. 
5603  *
5604  */
5605 static void
5606 jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
5607 {
5608         int n_pages, i;
5609
5610         n_pages = ev_document_get_n_pages (view->document);
5611
5612         for (i = 0; i < n_pages; i++) {
5613                 int page;
5614                 
5615                 if (direction == EV_VIEW_FIND_NEXT)
5616                         page = view->current_page + i;
5617                 else
5618                         page = view->current_page - i;          
5619                 page += shift;
5620                 
5621                 if (page >= n_pages) {
5622                         page = page - n_pages;
5623                 } else if (page < 0) 
5624                         page = page + n_pages;
5625
5626                 if (ev_view_find_get_n_results (view, page) > 0) {
5627                         ev_document_model_set_page (view->model, page);
5628                         break;
5629                 }
5630         }
5631 }
5632
5633 void
5634 ev_view_find_changed (EvView *view, GList **results, gint page)
5635 {
5636         view->find_pages = results;
5637         
5638         if (view->jump_to_find_result == TRUE) {
5639                 jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
5640                 jump_to_find_result (view);
5641         }
5642
5643         if (view->current_page == page)
5644                 gtk_widget_queue_draw (GTK_WIDGET (view));
5645 }
5646
5647 void
5648 ev_view_find_next (EvView *view)
5649 {
5650         gint n_results;
5651
5652         n_results = ev_view_find_get_n_results (view, view->current_page);
5653         view->find_result++;
5654
5655         if (view->find_result >= n_results) {
5656                 view->find_result = 0;
5657                 jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1);
5658                 jump_to_find_result (view);
5659         } else {
5660                 jump_to_find_result (view);
5661                 gtk_widget_queue_draw (GTK_WIDGET (view));
5662         }
5663 }
5664
5665 void
5666 ev_view_find_previous (EvView *view)
5667 {
5668         view->find_result--;
5669
5670         if (view->find_result < 0) {
5671                 jump_to_find_page (view, EV_VIEW_FIND_PREV, -1);
5672                 view->find_result = MAX (0, ev_view_find_get_n_results (view, view->current_page) - 1);
5673                 jump_to_find_result (view);
5674         } else {
5675                 jump_to_find_result (view);
5676                 gtk_widget_queue_draw (GTK_WIDGET (view));
5677         }
5678 }
5679
5680 void
5681 ev_view_find_search_changed (EvView *view)
5682 {
5683         /* search string has changed, focus on new search result */
5684         view->jump_to_find_result = TRUE;
5685         view->find_pages = NULL;
5686 }
5687
5688 void
5689 ev_view_find_set_highlight_search (EvView *view, gboolean value)
5690 {
5691         view->highlight_find_results = value;
5692         gtk_widget_queue_draw (GTK_WIDGET (view));
5693 }
5694
5695 void
5696 ev_view_find_cancel (EvView *view)
5697 {
5698         view->find_pages = NULL;
5699 }
5700
5701 /*** Synctex ***/
5702 void
5703 ev_view_highlight_forward_search (EvView       *view,
5704                                   EvSourceLink *link)
5705 {
5706         EvMapping   *mapping;
5707         gint         page;
5708         GdkRectangle view_rect;
5709
5710         if (!ev_document_has_synctex (view->document))
5711                 return;
5712
5713         mapping = ev_document_synctex_forward_search (view->document, link);
5714         if (!mapping)
5715                 return;
5716
5717         if (view->synctex_result)
5718                 g_free (view->synctex_result);
5719         view->synctex_result = mapping;
5720
5721         page = GPOINTER_TO_INT (mapping->data);
5722         ev_document_model_set_page (view->model, page);
5723
5724         doc_rect_to_view_rect (view, page, &mapping->area, &view_rect);
5725         ensure_rectangle_is_visible (view, &view_rect);
5726         gtk_widget_queue_draw (GTK_WIDGET (view));
5727 }
5728
5729 /*** Selections ***/
5730
5731 /* compute_new_selection_rect/text calculates the area currently selected by
5732  * view_rect.  each handles a different mode;
5733  */
5734 static GList *
5735 compute_new_selection_rect (EvView       *view,
5736                             GdkPoint     *start,
5737                             GdkPoint     *stop)
5738 {
5739         GdkRectangle view_rect;
5740         int n_pages, i;
5741         GList *list = NULL;
5742
5743         g_assert (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE);
5744         
5745         view_rect.x = MIN (start->x, stop->x);
5746         view_rect.y = MIN (start->y, stop->y);
5747         view_rect.width = MAX (start->x, stop->x) - view_rect.x;
5748         view_rect.width = MAX (start->y, stop->y) - view_rect.y;
5749
5750         n_pages = ev_document_get_n_pages (view->document);
5751
5752         for (i = 0; i < n_pages; i++) {
5753                 GdkRectangle page_area;
5754                 GtkBorder border;
5755                 
5756                 if (ev_view_get_page_extents (view, i, &page_area, &border)) {
5757                         GdkRectangle overlap;
5758
5759                         if (gdk_rectangle_intersect (&page_area, &view_rect, &overlap)) {
5760                                 EvViewSelection *selection;
5761
5762                                 selection = g_new0 (EvViewSelection, 1);
5763                                 selection->page = i;
5764                                 view_rect_to_doc_rect (view, &overlap, &page_area,
5765                                                        &(selection->rect));
5766
5767                                 list = g_list_append (list, selection);
5768                         }
5769                 }
5770         }
5771
5772         return list;
5773 }
5774
5775 static gboolean
5776 gdk_rectangle_point_in (GdkRectangle *rectangle,
5777                         GdkPoint     *point)
5778 {
5779         return rectangle->x <= point->x &&
5780                 rectangle->y <= point->y &&
5781                 point->x < rectangle->x + rectangle->width &&
5782                 point->y < rectangle->y + rectangle->height;
5783 }
5784
5785 static GList *
5786 compute_new_selection_text (EvView          *view,
5787                             EvSelectionStyle style,
5788                             GdkPoint        *start,
5789                             GdkPoint        *stop)
5790 {
5791         int n_pages, i, first, last;
5792         GList *list = NULL;
5793         EvViewSelection *selection;
5794         gdouble width, height;
5795         int start_page, end_page;
5796
5797         g_assert (view->selection_mode == EV_VIEW_SELECTION_TEXT);
5798
5799         n_pages = ev_document_get_n_pages (view->document);
5800
5801         /* First figure out the range of pages the selection
5802          * affects. */
5803         first = n_pages;
5804         last = 0;
5805         if (view->continuous) {
5806                 start_page = 0;
5807                 end_page = n_pages;
5808         } else if (view->dual_page) {
5809                 start_page = view->start_page;
5810                 end_page = view->end_page + 1;
5811         } else {
5812                 start_page = view->current_page;
5813                 end_page = view->current_page + 1;
5814         }
5815
5816         for (i = start_page; i < end_page; i++) {
5817                 GdkRectangle page_area;
5818                 GtkBorder border;
5819                 
5820                 ev_view_get_page_extents (view, i, &page_area, &border);
5821                 if (gdk_rectangle_point_in (&page_area, start) || 
5822                     gdk_rectangle_point_in (&page_area, stop)) {
5823                         if (first == n_pages)
5824                                 first = i;
5825                         last = i;
5826                 }
5827
5828         }
5829
5830         /* Now create a list of EvViewSelection's for the affected
5831          * pages.  This could be an empty list, a list of just one
5832          * page or a number of pages.*/
5833         for (i = first; i < last + 1; i++) {
5834                 GdkRectangle page_area;
5835                 GtkBorder border;
5836                 GdkPoint *point;
5837
5838                 get_doc_page_size (view, i, &width, &height);
5839
5840                 selection = g_new0 (EvViewSelection, 1);
5841                 selection->page = i;
5842                 selection->style = style;
5843                 selection->rect.x1 = selection->rect.y1 = 0;
5844                 selection->rect.x2 = width;
5845                 selection->rect.y2 = height;
5846
5847                 ev_view_get_page_extents (view, i, &page_area, &border);
5848
5849                 if (gdk_rectangle_point_in (&page_area, start))
5850                         point = start;
5851                 else
5852                         point = stop;
5853
5854                 if (i == first)
5855                         view_point_to_doc_point (view, point, &page_area,
5856                                                  &selection->rect.x1,
5857                                                  &selection->rect.y1);
5858
5859                 /* If the selection is contained within just one page,
5860                  * make sure we don't write 'start' into both points
5861                  * in selection->rect. */
5862                 if (first == last)
5863                         point = stop;
5864
5865                 if (i == last)
5866                         view_point_to_doc_point (view, point, &page_area,
5867                                                  &selection->rect.x2,
5868                                                  &selection->rect.y2);
5869
5870                 list = g_list_append (list, selection);
5871         }
5872
5873         return list;
5874 }
5875
5876 /* This function takes the newly calculated list, and figures out which regions
5877  * have changed.  It then queues a redraw approporiately.
5878  */
5879 static void
5880 merge_selection_region (EvView *view,
5881                         GList  *new_list)
5882 {
5883         GList *old_list;
5884         GList *new_list_ptr, *old_list_ptr;
5885
5886         /* Update the selection */
5887         old_list = ev_pixbuf_cache_get_selection_list (view->pixbuf_cache);
5888         g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
5889         g_list_free (view->selection_info.selections);
5890         view->selection_info.selections = new_list;
5891         ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, new_list);
5892         g_signal_emit (view, signals[SIGNAL_SELECTION_CHANGED], 0, NULL);
5893
5894         new_list_ptr = new_list;
5895         old_list_ptr = old_list;
5896
5897         while (new_list_ptr || old_list_ptr) {
5898                 EvViewSelection *old_sel, *new_sel;
5899                 int cur_page;
5900                 cairo_region_t *region = NULL;
5901
5902                 new_sel = (new_list_ptr) ? (new_list_ptr->data) : NULL;
5903                 old_sel = (old_list_ptr) ? (old_list_ptr->data) : NULL;
5904
5905                 /* Assume that the lists are in order, and we run through them
5906                  * comparing them, one page at a time.  We come out with the
5907                  * first page we see. */
5908                 if (new_sel && old_sel) {
5909                         if (new_sel->page < old_sel->page) {
5910                                 new_list_ptr = new_list_ptr->next;
5911                                 old_sel = NULL;
5912                         } else if (new_sel->page > old_sel->page) {
5913                                 old_list_ptr = old_list_ptr->next;
5914                                 new_sel = NULL;
5915                         } else {
5916                                 new_list_ptr = new_list_ptr->next;
5917                                 old_list_ptr = old_list_ptr->next;
5918                         }
5919                 } else if (new_sel) {
5920                         new_list_ptr = new_list_ptr->next;
5921                 } else if (old_sel) {
5922                         old_list_ptr = old_list_ptr->next;
5923                 }
5924
5925                 g_assert (new_sel || old_sel);
5926
5927                 /* is the page we're looking at on the screen?*/
5928                 cur_page = new_sel ? new_sel->page : old_sel->page;
5929                 if (cur_page < view->start_page || cur_page > view->end_page)
5930                         continue;
5931
5932                 /* seed the cache with a new page.  We are going to need the new
5933                  * region too. */
5934                 if (new_sel) {
5935                         cairo_region_t *tmp_region = NULL;
5936
5937                         ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
5938                                                                cur_page,
5939                                                                view->scale,
5940                                                                &tmp_region);
5941
5942                         if (tmp_region && !cairo_region_is_empty (tmp_region)) {
5943                                 new_sel->covered_region = cairo_region_reference (tmp_region);
5944                         }
5945                 }
5946
5947                 /* Now we figure out what needs redrawing */
5948                 if (old_sel && new_sel) {
5949                         if (old_sel->covered_region && new_sel->covered_region) {
5950                                 /* We only want to redraw the areas that have
5951                                  * changed, so we xor the old and new regions
5952                                  * and redraw if it's different */
5953                                 region = cairo_region_copy (old_sel->covered_region);
5954 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 9, 12)
5955                                 cairo_region_xor (region, new_sel->covered_region);
5956 #else
5957                                 cairo_region_t *tbr;
5958                                 tbr = cairo_region_copy (new_sel->covered_region);
5959
5960                                 /* xor old_sel, new_sel*/
5961                                 cairo_region_subtract (tbr, region);
5962                                 cairo_region_subtract (region, new_sel->covered_region);
5963                                 cairo_region_union (region, tbr);
5964                                 cairo_region_destroy (tbr);
5965 #endif
5966
5967                                 if (cairo_region_is_empty (region)) {
5968                                         cairo_region_destroy (region);
5969                                         region = NULL;
5970                                 } else {
5971                                         gint num_rectangles = cairo_region_num_rectangles (region);
5972                                         GdkRectangle r;
5973
5974                                         /* We need to make the damage region a little bigger
5975                                          * because the edges of the old selection might change
5976                                          */
5977                                         cairo_region_get_rectangle (region, 0, &r);
5978                                         r.x -= 5;
5979                                         r.width = 5;
5980                                         cairo_region_union_rectangle (region, &r);
5981
5982                                         cairo_region_get_rectangle (region, num_rectangles - 1, &r);
5983                                         r.x += r.width;
5984                                         r.width = 5;
5985                                         cairo_region_union_rectangle (region, &r);
5986                                 }
5987                         } else if (old_sel->covered_region) {
5988                                 region = cairo_region_copy (old_sel->covered_region);
5989                         } else if (new_sel->covered_region) {
5990                                 region = cairo_region_copy (new_sel->covered_region);
5991                         }
5992                 } else if (old_sel && !new_sel) {
5993                         if (old_sel->covered_region && !cairo_region_is_empty (old_sel->covered_region)) {
5994                                 region = cairo_region_copy (old_sel->covered_region);
5995                         }
5996                 } else if (!old_sel && new_sel) {
5997                         if (new_sel->covered_region && !cairo_region_is_empty (new_sel->covered_region)) {
5998                                 region = cairo_region_copy (new_sel->covered_region);
5999                         }
6000                 } else {
6001                         g_assert_not_reached ();
6002                 }
6003
6004                 /* Redraw the damaged region! */
6005                 if (region) {
6006                         GdkRectangle page_area;
6007                         GtkBorder    border;
6008
6009                         ev_view_get_page_extents (view, cur_page, &page_area, &border);
6010                         cairo_region_translate (region,
6011                                            page_area.x + border.left - view->scroll_x,
6012                                            page_area.y + border.top - view->scroll_y);
6013                         gdk_window_invalidate_region (gtk_widget_get_window (GTK_WIDGET (view)), region, TRUE);
6014                         cairo_region_destroy (region);
6015                 }
6016         }
6017
6018         /* Free the old list, now that we're done with it. */
6019         g_list_foreach (old_list, (GFunc) selection_free, NULL);
6020         g_list_free (old_list);
6021 }
6022
6023 static void
6024 compute_selections (EvView          *view,
6025                     EvSelectionStyle style,
6026                     GdkPoint        *start,
6027                     GdkPoint        *stop)
6028 {
6029         GList *list;
6030
6031         if (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE)
6032                 list = compute_new_selection_rect (view, start, stop);
6033         else
6034                 list = compute_new_selection_text (view, style, start, stop);
6035         merge_selection_region (view, list);
6036 }
6037
6038 /* Free's the selection.  It's up to the caller to queue redraws if needed.
6039  */
6040 static void
6041 selection_free (EvViewSelection *selection)
6042 {
6043         if (selection->covered_region)
6044                 cairo_region_destroy (selection->covered_region);
6045         g_free (selection);
6046 }
6047
6048 static void
6049 clear_selection (EvView *view)
6050 {
6051         if (view->selection_info.selections) {
6052                 g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
6053                 g_list_free (view->selection_info.selections);
6054                 view->selection_info.selections = NULL;
6055
6056                 g_signal_emit (view, signals[SIGNAL_SELECTION_CHANGED], 0, NULL);
6057         }
6058         view->selection_info.in_selection = FALSE;
6059         if (view->pixbuf_cache)
6060                 ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, NULL);
6061 }
6062
6063 void
6064 ev_view_select_all (EvView *view)
6065 {
6066         GList *selections = NULL;
6067         int n_pages, i;
6068
6069         /* Disable selection on rotated pages for the 0.4.0 series */
6070         if (view->rotation != 0)
6071                 return;
6072
6073         clear_selection (view);
6074         
6075         n_pages = ev_document_get_n_pages (view->document);
6076         for (i = 0; i < n_pages; i++) {
6077                 gdouble width, height;
6078                 EvViewSelection *selection;
6079
6080                 get_doc_page_size (view, i, &width, &height);
6081
6082                 selection = g_new0 (EvViewSelection, 1);
6083                 selection->page = i;
6084                 selection->style = EV_SELECTION_STYLE_GLYPH;
6085                 selection->rect.x1 = selection->rect.y1 = 0;
6086                 selection->rect.x2 = width;
6087                 selection->rect.y2 = height;
6088
6089                 selections = g_list_append (selections, selection);
6090         }
6091
6092         merge_selection_region (view, selections);
6093         gtk_widget_queue_draw (GTK_WIDGET (view));
6094 }
6095
6096 gboolean
6097 ev_view_get_has_selection (EvView *view)
6098 {
6099         return view->selection_info.selections != NULL;
6100 }
6101
6102 static char *
6103 get_selected_text (EvView *view)
6104 {
6105         GString *text;
6106         GList *l;
6107         gchar *normalized_text;
6108
6109         text = g_string_new (NULL);
6110
6111         ev_document_doc_mutex_lock ();
6112
6113         for (l = view->selection_info.selections; l != NULL; l = l->next) {
6114                 EvViewSelection *selection = (EvViewSelection *)l->data;
6115                 EvPage *page;
6116                 gchar *tmp;
6117
6118                 page = ev_document_get_page (view->document, selection->page);
6119                 tmp = ev_selection_get_selected_text (EV_SELECTION (view->document),
6120                                                       page, selection->style,
6121                                                       &(selection->rect));
6122                 g_object_unref (page);
6123                 g_string_append (text, tmp);
6124                 g_free (tmp);
6125         }
6126
6127         ev_document_doc_mutex_unlock ();
6128         
6129         normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC);
6130         g_string_free (text, TRUE);
6131         return normalized_text;
6132 }
6133
6134 static void
6135 ev_view_clipboard_copy (EvView      *view,
6136                         const gchar *text)
6137 {
6138         GtkClipboard *clipboard;
6139
6140         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
6141                                               GDK_SELECTION_CLIPBOARD);
6142         gtk_clipboard_set_text (clipboard, text, -1);
6143 }
6144
6145 void
6146 ev_view_copy (EvView *ev_view)
6147 {
6148         char *text;
6149
6150         if (!EV_IS_SELECTION (ev_view->document))
6151                 return;
6152
6153         text = get_selected_text (ev_view);
6154         ev_view_clipboard_copy (ev_view, text);
6155         g_free (text);
6156 }
6157
6158 static void
6159 ev_view_primary_get_cb (GtkClipboard     *clipboard,
6160                         GtkSelectionData *selection_data,
6161                         guint             info,
6162                         gpointer          data)
6163 {
6164         EvView *ev_view = EV_VIEW (data);
6165
6166         if (ev_view->link_selected) {
6167                 gtk_selection_data_set_text (selection_data,
6168                                              ev_link_action_get_uri (ev_view->link_selected),
6169                                              -1);
6170         } else if (EV_IS_SELECTION (ev_view->document) &&
6171                    ev_view->selection_info.selections) {
6172                 gchar *text;
6173                 
6174                 text = get_selected_text (ev_view);
6175                 if (text) {
6176                         gtk_selection_data_set_text (selection_data, text, -1);
6177                         g_free (text);
6178                 }
6179         }
6180 }
6181
6182 static void
6183 ev_view_primary_clear_cb (GtkClipboard *clipboard,
6184                           gpointer      data)
6185 {
6186         EvView *view = EV_VIEW (data);
6187
6188         clear_selection (view);
6189         clear_link_selected (view);
6190 }
6191
6192 static void
6193 ev_view_update_primary_selection (EvView *ev_view)
6194 {
6195         GtkClipboard *clipboard;
6196
6197         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
6198                                               GDK_SELECTION_PRIMARY);
6199
6200         if (ev_view->selection_info.selections || ev_view->link_selected) {
6201                 GtkTargetList *target_list;
6202                 GtkTargetEntry *targets;
6203                 int n_targets;
6204
6205                 target_list = gtk_target_list_new (NULL, 0);
6206                 gtk_target_list_add_text_targets (target_list, 0);
6207                 targets = gtk_target_table_new_from_list (target_list, &n_targets);
6208                 gtk_target_list_unref (target_list);
6209                 
6210                 if (!gtk_clipboard_set_with_owner (clipboard,
6211                                                    targets, n_targets,
6212                                                    ev_view_primary_get_cb,
6213                                                    ev_view_primary_clear_cb,
6214                                                    G_OBJECT (ev_view)))
6215                         ev_view_primary_clear_cb (clipboard, ev_view);
6216
6217                 gtk_target_table_free (targets, n_targets);
6218         } else {
6219                 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (ev_view))
6220                         gtk_clipboard_clear (clipboard);
6221         }
6222 }
6223
6224 static void
6225 clear_link_selected (EvView *view)
6226 {
6227         if (view->link_selected) {
6228                 g_object_unref (view->link_selected);
6229                 view->link_selected = NULL;
6230         }
6231 }
6232
6233 void
6234 ev_view_copy_link_address (EvView       *view,
6235                            EvLinkAction *action)
6236 {
6237         clear_link_selected (view);
6238         
6239         ev_view_clipboard_copy (view, ev_link_action_get_uri (action));
6240         
6241         view->link_selected = g_object_ref (action);
6242         ev_view_update_primary_selection (view);
6243 }
6244
6245 /*** Cursor operations ***/
6246 static void
6247 ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
6248 {
6249         GdkCursor *cursor = NULL;
6250         GtkWidget *widget;
6251         GdkWindow *window;
6252
6253         if (view->cursor == new_cursor) {
6254                 return;
6255         }
6256
6257         view->cursor = new_cursor;
6258
6259         window = gtk_widget_get_window (GTK_WIDGET (view));
6260         widget = gtk_widget_get_toplevel (GTK_WIDGET (view));
6261         cursor = ev_view_cursor_new (gtk_widget_get_display (widget), new_cursor);
6262         gdk_window_set_cursor (window, cursor);
6263         gdk_flush ();
6264         if (cursor)
6265                 gdk_cursor_unref (cursor);
6266 }
6267
6268 void
6269 ev_view_hide_cursor (EvView *view)
6270 {
6271        ev_view_set_cursor (view, EV_VIEW_CURSOR_HIDDEN);
6272 }
6273
6274 void
6275 ev_view_show_cursor (EvView *view)
6276 {
6277        ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
6278 }
6279
6280 gboolean
6281 ev_view_next_page (EvView *view)
6282 {
6283         int page, n_pages;
6284
6285         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
6286         
6287         if (!view->document)
6288                 return FALSE;
6289
6290         page = ev_document_model_get_page (view->model);
6291         n_pages = ev_document_get_n_pages (view->document);
6292
6293         if (view->dual_page)
6294                 page = page + 2; 
6295         else 
6296                 page = page + 1;
6297
6298         if (page < n_pages) {
6299                 ev_document_model_set_page (view->model, page);
6300                 return TRUE;
6301         } else if (view->dual_page && page == n_pages) {
6302                 ev_document_model_set_page (view->model, page - 1);
6303                 return TRUE;
6304         } else {
6305                 return FALSE;
6306         }
6307 }
6308
6309 gboolean
6310 ev_view_previous_page (EvView *view)
6311 {
6312         int page;
6313
6314         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
6315
6316         if (!view->document)
6317                 return FALSE;
6318
6319         page = ev_document_model_get_page (view->model);
6320
6321         if (view->dual_page)
6322                 page = page - 2; 
6323         else 
6324                 page = page - 1;
6325
6326         if (page >= 0) {
6327                 ev_document_model_set_page (view->model, page);
6328                 return TRUE;
6329         } else if (view->dual_page && page == -1) {
6330                 ev_document_model_set_page (view->model, 0);
6331                 return TRUE;
6332         } else {        
6333                 return FALSE;
6334         }
6335 }
6336