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