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