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