]> www.fi.muni.cz Git - evince.git/blob - libview/ev-view.c
[libview] Do nothing in size_allocate when document is not yet loaded
[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->document)
2880                 return;
2881
2882         if (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
2883             view->sizing_mode == EV_SIZING_BEST_FIT) {
2884                 GtkRequisition req;
2885
2886                 ev_view_zoom_for_size (view,
2887                                        allocation->width,
2888                                        allocation->height);
2889                 view->internal_size_request = TRUE;
2890                 ev_view_size_request (widget, &req);
2891                 view->internal_size_request = FALSE;
2892         }
2893         
2894         view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
2895         view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
2896
2897         if (view->document)
2898                 view_update_range_and_current_page (view);
2899
2900         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
2901         view->pending_resize = FALSE;
2902         view->pending_point.x = 0;
2903         view->pending_point.y = 0;
2904
2905         children = gtk_container_get_children (GTK_CONTAINER (widget));
2906         for (l = children; l && l->data; l = g_list_next (l)) {
2907                 EvFormField   *field;
2908                 GdkRectangle   view_area;
2909                 GList         *form_field_mapping;
2910                 GtkAllocation  child_allocation;
2911                 GtkRequisition child_requisition;
2912                 GtkWidget     *child = (GtkWidget *)l->data;
2913                 
2914                 field = g_object_get_data (G_OBJECT (child), "form-field");
2915                 if (!field)
2916                         continue;
2917
2918                 form_field_mapping = ev_page_cache_get_form_field_mapping (view->page_cache,
2919                                                                            field->page->index);
2920                 ev_view_get_area_from_mapping (view, field->page->index,
2921                                                form_field_mapping,
2922                                                field, &view_area);
2923
2924                 gtk_widget_size_request (child, &child_requisition);
2925                 if (child_requisition.width != view_area.width ||
2926                     child_requisition.height != view_area.height)
2927                         gtk_widget_set_size_request (child, view_area.width, view_area.height);
2928
2929                 gtk_container_child_get (GTK_CONTAINER (widget),
2930                                          child,
2931                                          "x", &child_allocation.x,
2932                                          "y", &child_allocation.y,
2933                                          NULL);
2934                 if (child_allocation.x != view_area.x ||
2935                     child_allocation.y != view_area.y) {
2936                         gtk_layout_move (GTK_LAYOUT (widget), child, view_area.x, view_area.y);
2937                 }
2938         }
2939         g_list_free (children);
2940
2941         if (view->window_children)
2942                 gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (view)),
2943                                        &root_x, &root_y);
2944
2945         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
2946                 EvViewWindowChild *child;
2947                 EvRectangle        doc_rect;
2948                 GdkRectangle       view_rect;
2949
2950                 child = (EvViewWindowChild *)l->data;
2951
2952                 doc_rect = *ev_annotation_window_get_rectangle (EV_ANNOTATION_WINDOW (child->window));
2953                 if (child->moved) {
2954                         doc_rect.x1 = child->orig_x;
2955                         doc_rect.y1 = child->orig_y;
2956                 }
2957                 doc_rect_to_view_rect (view, child->page, &doc_rect, &view_rect);
2958                 view_rect.x -= view->scroll_x;
2959                 view_rect.y -= view->scroll_y;
2960
2961                 if (view_rect.x != child->orig_x || view_rect.y != child->orig_y) {
2962                         child->parent_x = root_x;
2963                         child->parent_y = root_y;
2964                         ev_view_window_child_move (view, child, view_rect.x + root_x, view_rect.y + root_y);
2965                 }
2966         }
2967 }
2968
2969 static void
2970 ev_view_realize (GtkWidget *widget)
2971 {
2972         EvView *view = EV_VIEW (widget);
2973
2974         if (GTK_WIDGET_CLASS (ev_view_parent_class)->realize)
2975                 (* GTK_WIDGET_CLASS (ev_view_parent_class)->realize) (widget);
2976
2977         gdk_window_set_events (view->layout.bin_window,
2978                                (gdk_window_get_events (view->layout.bin_window) | 
2979                                 GDK_EXPOSURE_MASK |
2980                                 GDK_BUTTON_PRESS_MASK |
2981                                 GDK_BUTTON_RELEASE_MASK |
2982                                 GDK_SCROLL_MASK |
2983                                 GDK_KEY_PRESS_MASK |
2984                                 GDK_POINTER_MOTION_MASK |
2985                                 GDK_POINTER_MOTION_HINT_MASK |
2986                                 GDK_ENTER_NOTIFY_MASK |
2987                                 GDK_LEAVE_NOTIFY_MASK));
2988
2989         gdk_window_set_background (view->layout.bin_window, &widget->style->mid [GTK_STATE_NORMAL]);
2990
2991         on_adjustment_value_changed (NULL, view);
2992 }
2993
2994 static gboolean
2995 ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event)
2996 {
2997         EvView *view = EV_VIEW (widget);
2998         guint state;
2999
3000         state = event->state & gtk_accelerator_get_default_mod_mask ();
3001
3002         if (state == GDK_CONTROL_MASK) {
3003                 ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE);
3004                 if (event->direction == GDK_SCROLL_UP ||
3005                     event->direction == GDK_SCROLL_LEFT) {
3006                         if (ev_view_can_zoom_in (view)) {
3007                                 ev_view_zoom_in (view);
3008                         }
3009                 } else {
3010                         if (ev_view_can_zoom_out (view)) {
3011                                 ev_view_zoom_out (view);
3012                         }
3013                 }
3014
3015                 return TRUE;
3016         }
3017
3018         view->jump_to_find_result = FALSE;
3019
3020         /* Shift+Wheel scrolls the in the perpendicular direction */
3021         if (state & GDK_SHIFT_MASK) {
3022                 if (event->direction == GDK_SCROLL_UP)
3023                         event->direction = GDK_SCROLL_LEFT;
3024                 else if (event->direction == GDK_SCROLL_LEFT)
3025                         event->direction = GDK_SCROLL_UP;
3026                 else if (event->direction == GDK_SCROLL_DOWN)
3027                         event->direction = GDK_SCROLL_RIGHT;
3028                 else if (event->direction == GDK_SCROLL_RIGHT)
3029                         event->direction = GDK_SCROLL_DOWN;
3030
3031                 event->state &= ~GDK_SHIFT_MASK;
3032                 state &= ~GDK_SHIFT_MASK;
3033         }
3034
3035         if (state == 0 && view->sizing_mode == EV_SIZING_BEST_FIT && !view->continuous) {
3036                 switch (event->direction) {
3037                         case GDK_SCROLL_DOWN:
3038                         case GDK_SCROLL_RIGHT:
3039                                 ev_view_next_page (view);       
3040                                 break;
3041                         case GDK_SCROLL_UP:
3042                         case GDK_SCROLL_LEFT:
3043                                 ev_view_previous_page (view);
3044                                 break;
3045                 }
3046
3047                 return TRUE;
3048         }
3049
3050         return FALSE;
3051 }
3052
3053 static EvViewSelection *
3054 find_selection_for_page (EvView *view,
3055                          gint    page)
3056 {
3057         GList *list;
3058
3059         for (list = view->selection_info.selections; list != NULL; list = list->next) {
3060                 EvViewSelection *selection;
3061
3062                 selection = (EvViewSelection *) list->data;
3063
3064                 if (selection->page == page)
3065                         return selection;
3066         }
3067
3068         return NULL;
3069 }
3070
3071 static gboolean
3072 ev_view_expose_event (GtkWidget      *widget,
3073                       GdkEventExpose *event)
3074 {
3075         EvView  *view = EV_VIEW (widget);
3076         cairo_t *cr;
3077         gint     i;
3078
3079         if (view->loading) {
3080                 show_loading_window (view);
3081         } else if (view->loading_window &&
3082                    gtk_widget_get_visible (view->loading_window)) {
3083                 ev_view_loading_window_move (view);
3084         }
3085
3086         if (view->document == NULL)
3087                 return FALSE;
3088
3089         cr = gdk_cairo_create (view->layout.bin_window);
3090
3091         for (i = view->start_page; i >= 0 && i <= view->end_page; i++) {
3092                 GdkRectangle page_area;
3093                 GtkBorder border;
3094                 gboolean page_ready = TRUE;
3095
3096                 if (!get_page_extents (view, i, &page_area, &border))
3097                         continue;
3098
3099                 page_area.x -= view->scroll_x;
3100                 page_area.y -= view->scroll_y;
3101
3102                 draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready);
3103
3104                 if (page_ready && view->find_pages && view->highlight_find_results)
3105                         highlight_find_results (view, i);
3106                 if (page_ready && EV_IS_DOCUMENT_ANNOTATIONS (view->document))
3107                         show_annotation_windows (view, i);
3108         }
3109
3110         cairo_destroy (cr);
3111
3112         if (GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event)
3113                 (* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event);
3114
3115         return FALSE;
3116 }
3117
3118 static gboolean
3119 ev_view_do_popup_menu (EvView *view,
3120                        gdouble x,
3121                        gdouble y)
3122 {
3123         GList        *items = NULL;
3124         EvLink       *link;
3125         EvImage      *image;
3126         EvAnnotation *annot;
3127
3128         image = ev_view_get_image_at_location (view, x, y);
3129         if (image)
3130                 items = g_list_prepend (items, image);
3131
3132         link = ev_view_get_link_at_location (view, x, y);
3133         if (link)
3134                 items = g_list_prepend (items, link);
3135
3136         annot = ev_view_get_annotation_at_location (view, x, y);
3137         if (annot)
3138                 items = g_list_prepend (items, annot);
3139
3140         g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, items);
3141
3142         g_list_free (items);
3143
3144         return TRUE;
3145 }
3146
3147 static gboolean
3148 ev_view_popup_menu (GtkWidget *widget)
3149 {
3150         gint x, y;
3151         
3152         gtk_widget_get_pointer (widget, &x, &y);
3153         return ev_view_do_popup_menu (EV_VIEW (widget), x, y);
3154 }
3155
3156 static void
3157 get_link_area (EvView       *view,
3158                gint          x,
3159                gint          y,
3160                EvLink       *link,
3161                GdkRectangle *area)
3162 {
3163         GList *link_mapping;
3164         gint   page;
3165         gint   x_offset = 0, y_offset = 0;
3166
3167         x += view->scroll_x;
3168         y += view->scroll_y;
3169         
3170         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
3171         
3172         link_mapping = ev_page_cache_get_link_mapping (view->page_cache, page);
3173         ev_view_get_area_from_mapping (view, page,
3174                                        link_mapping,
3175                                        link, area);
3176 }
3177
3178 static void
3179 get_annot_area (EvView       *view,
3180                gint          x,
3181                gint          y,
3182                EvAnnotation *annot,
3183                GdkRectangle *area)
3184 {
3185         GList *annot_mapping;
3186         gint   page;
3187         gint   x_offset = 0, y_offset = 0;
3188
3189         x += view->scroll_x;
3190         y += view->scroll_y;
3191
3192         find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
3193
3194         annot_mapping = ev_page_cache_get_annot_mapping (view->page_cache, page);
3195         ev_view_get_area_from_mapping (view, page,
3196                                        annot_mapping,
3197                                        annot, area);
3198 }
3199
3200 static gboolean
3201 ev_view_query_tooltip (GtkWidget  *widget,
3202                        gint        x,
3203                        gint        y,
3204                        gboolean    keyboard_tip,
3205                        GtkTooltip *tooltip)
3206 {
3207         EvView       *view = EV_VIEW (widget);
3208         EvLink       *link;
3209         EvAnnotation *annot;
3210         gchar        *text;
3211
3212         annot = ev_view_get_annotation_at_location (view, x, y);
3213         if (annot && annot->contents) {
3214                 GdkRectangle annot_area;
3215
3216                 get_annot_area (view, x, y, annot, &annot_area);
3217                 gtk_tooltip_set_text (tooltip, annot->contents);
3218                 gtk_tooltip_set_tip_area (tooltip, &annot_area);
3219
3220                 return TRUE;
3221         }
3222
3223         link = ev_view_get_link_at_location (view, x, y);
3224         if (!link)
3225                 return FALSE;
3226
3227         text = tip_from_link (view, link);
3228         if (text && g_utf8_validate (text, -1, NULL)) {
3229                 GdkRectangle link_area;
3230
3231                 get_link_area (view, x, y, link, &link_area);
3232                 gtk_tooltip_set_text (tooltip, text);
3233                 gtk_tooltip_set_tip_area (tooltip, &link_area);
3234         }
3235         g_free (text);
3236
3237         return TRUE;
3238 }
3239
3240 static void
3241 start_selection_for_event (EvView         *view,
3242                            GdkEventButton *event)
3243 {
3244         clear_selection (view);
3245
3246         view->selection_info.start.x = event->x + view->scroll_x;
3247         view->selection_info.start.y = event->y + view->scroll_y;
3248
3249         switch (event->type) {
3250                 case GDK_2BUTTON_PRESS:
3251                         view->selection_info.style = EV_SELECTION_STYLE_WORD;
3252                         break;
3253                 case GDK_3BUTTON_PRESS:
3254                         view->selection_info.style = EV_SELECTION_STYLE_LINE;
3255                         break;
3256                 default:
3257                         view->selection_info.style = EV_SELECTION_STYLE_GLYPH;
3258                         return;
3259         }
3260
3261         /* In case of WORD or LINE, compute selections now */
3262         compute_selections (view,
3263                             view->selection_info.style,
3264                             &(view->selection_info.start),
3265                             &(view->selection_info.start));
3266 }
3267
3268 static gboolean
3269 ev_view_button_press_event (GtkWidget      *widget,
3270                             GdkEventButton *event)
3271 {
3272         EvView *view = EV_VIEW (widget);
3273
3274         if (!view->document)
3275                 return FALSE;
3276         
3277         if (!gtk_widget_has_focus (widget)) {
3278                 gtk_widget_grab_focus (widget);
3279         }
3280
3281         if (view->window_child_focus) {
3282                 EvAnnotationWindow *window;
3283                 EvAnnotation       *annot;
3284
3285                 window = EV_ANNOTATION_WINDOW (view->window_child_focus->window);
3286                 annot = ev_annotation_window_get_annotation (window);
3287                 ev_annotation_window_ungrab_focus (window);
3288                 ev_view_annotation_save (view, annot);
3289                 view->window_child_focus = NULL;
3290         }
3291         
3292         view->pressed_button = event->button;
3293         view->selection_info.in_drag = FALSE;
3294
3295         if (view->scroll_info.autoscrolling)
3296                 return TRUE;
3297         
3298         switch (event->button) {
3299                 case 1: {
3300                         EvImage *image;
3301                         EvAnnotation *annot;
3302                         EvFormField *field;
3303
3304                         if (EV_IS_SELECTION (view->document) && view->selection_info.selections) {
3305                                 if (event->type == GDK_3BUTTON_PRESS) {
3306                                         start_selection_for_event (view, event);
3307                                 } else if (location_in_selected_text (view,
3308                                                                event->x + view->scroll_x,
3309                                                                event->y + view->scroll_y)) {
3310                                         view->selection_info.in_drag = TRUE;
3311                                 } else {
3312                                         start_selection_for_event (view, event);
3313                                 }
3314
3315                                 gtk_widget_queue_draw (widget);
3316                         } else if ((annot = ev_view_get_annotation_at_location (view, event->x, event->y))) {
3317                                 ev_view_handle_annotation (view, annot, event->x, event->y, event->time);
3318                         } else if ((field = ev_view_get_form_field_at_location (view, event->x, event->y))) {
3319                                 ev_view_remove_all (view);
3320                                 ev_view_handle_form_field (view, field, event->x, event->y);
3321                         } else if (!location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y) &&
3322                                    (image = ev_view_get_image_at_location (view, event->x, event->y))) {
3323                                 if (view->image_dnd_info.image)
3324                                         g_object_unref (view->image_dnd_info.image);
3325                                 view->image_dnd_info.image = g_object_ref (image);
3326                                 view->image_dnd_info.in_drag = TRUE;
3327
3328                                 view->image_dnd_info.start.x = event->x + view->scroll_x;
3329                                 view->image_dnd_info.start.y = event->y + view->scroll_y;
3330                         } else {
3331                                 ev_view_remove_all (view);
3332                                 
3333                                 if (EV_IS_SELECTION (view->document))
3334                                         start_selection_for_event (view, event);
3335                         }
3336                 }                       
3337                         return TRUE;
3338                 case 2:
3339                         /* use root coordinates as reference point because
3340                          * scrolling changes window relative coordinates */
3341                         view->drag_info.start.x = event->x_root;
3342                         view->drag_info.start.y = event->y_root;
3343                         view->drag_info.hadj = gtk_adjustment_get_value (view->hadjustment);
3344                         view->drag_info.vadj = gtk_adjustment_get_value (view->vadjustment);
3345
3346                         ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG);
3347
3348                         return TRUE;
3349                 case 3:
3350                         view->scroll_info.start_y = event->y;
3351                         return ev_view_do_popup_menu (view, event->x, event->y);
3352         }
3353         
3354         return FALSE;
3355 }
3356
3357 static void
3358 ev_view_remove_all (EvView *view)
3359 {
3360         GList *children, *child;
3361
3362         children = gtk_container_get_children (GTK_CONTAINER (view));
3363         for (child = children; child && child->data; child = g_list_next (child)) {
3364                 gtk_container_remove (GTK_CONTAINER (view),
3365                                       GTK_WIDGET (child->data));
3366         }
3367         g_list_free (children);
3368 }
3369
3370 /*** Drag and Drop ***/
3371 static void
3372 ev_view_drag_data_get (GtkWidget        *widget,
3373                        GdkDragContext   *context,
3374                        GtkSelectionData *selection_data,
3375                        guint             info,
3376                        guint             time)
3377 {
3378         EvView *view = EV_VIEW (widget);
3379
3380         switch (info) {
3381                 case TARGET_DND_TEXT:
3382                         if (EV_IS_SELECTION (view->document) &&
3383                             view->selection_info.selections) {
3384                                 gchar *text;
3385
3386                                 text = get_selected_text (view);
3387                                 gtk_selection_data_set_text (selection_data,
3388                                                              text,
3389                                                              strlen (text));
3390                                 g_free (text);
3391                         }
3392                         break;
3393                 case TARGET_DND_IMAGE:
3394                         if (view->image_dnd_info.image) {
3395                                 GdkPixbuf *pixbuf;
3396
3397                                 ev_document_doc_mutex_lock ();
3398                                 pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document),
3399                                                                        view->image_dnd_info.image);
3400                                 ev_document_doc_mutex_unlock ();
3401                                 
3402                                 gtk_selection_data_set_pixbuf (selection_data, pixbuf);
3403                                 g_object_unref (pixbuf);
3404                         }
3405                         break;
3406                 case TARGET_DND_URI:
3407                         if (view->image_dnd_info.image) {
3408                                 GdkPixbuf   *pixbuf;
3409                                 const gchar *tmp_uri;
3410                                 gchar       *uris[2];
3411
3412                                 ev_document_doc_mutex_lock ();
3413                                 pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (view->document),
3414                                                                        view->image_dnd_info.image);
3415                                 ev_document_doc_mutex_unlock ();
3416                                 
3417                                 tmp_uri = ev_image_save_tmp (view->image_dnd_info.image, pixbuf);
3418                                 g_object_unref (pixbuf);
3419
3420                                 uris[0] = (gchar *)tmp_uri;
3421                                 uris[1] = NULL;
3422                                 gtk_selection_data_set_uris (selection_data, uris);
3423                         }
3424         }
3425 }
3426
3427 static gboolean
3428 ev_view_drag_motion (GtkWidget      *widget,
3429                      GdkDragContext *context,
3430                      gint            x,
3431                      gint            y,
3432                      guint           time)
3433 {
3434         if (gtk_drag_get_source_widget (context) == widget)
3435                 gdk_drag_status (context, 0, time);
3436         else
3437                 gdk_drag_status (context, context->suggested_action, time);
3438         
3439         return TRUE;
3440 }
3441                      
3442 static gboolean
3443 selection_update_idle_cb (EvView *view)
3444 {
3445         compute_selections (view,
3446                             view->selection_info.style,
3447                             &view->selection_info.start,
3448                             &view->motion);
3449         view->selection_update_id = 0;
3450         return FALSE;
3451 }
3452
3453 static gboolean
3454 selection_scroll_timeout_cb (EvView *view)
3455 {       
3456         gint x, y, shift = 0;
3457         GtkWidget *widget = GTK_WIDGET (view);
3458         
3459         gtk_widget_get_pointer (widget, &x, &y);
3460
3461         if (y > widget->allocation.height) {
3462                 shift = (y - widget->allocation.height) / 2;
3463         } else if (y < 0) {
3464                 shift = y / 2;
3465         }
3466
3467         if (shift)
3468                 gtk_adjustment_set_value (view->vadjustment,
3469                                           CLAMP (view->vadjustment->value + shift,
3470                                           view->vadjustment->lower,
3471                                           view->vadjustment->upper -
3472                                           view->vadjustment->page_size));       
3473
3474         if (x > widget->allocation.width) {
3475                 shift = (x - widget->allocation.width) / 2;
3476         } else if (x < 0) {
3477                 shift = x / 2;
3478         }
3479
3480         if (shift)
3481                 gtk_adjustment_set_value (view->hadjustment,
3482                                           CLAMP (view->hadjustment->value + shift,
3483                                           view->hadjustment->lower,
3484                                           view->hadjustment->upper -
3485                                           view->hadjustment->page_size));       
3486
3487         return TRUE;
3488 }
3489
3490 static gboolean
3491 ev_view_drag_update_momentum (EvView *view)
3492 {
3493         int i;
3494         if (!view->drag_info.in_drag)
3495                 return FALSE;
3496         
3497         for (i = DRAG_HISTORY - 1; i > 0; i--) {
3498                 view->drag_info.buffer[i].x = view->drag_info.buffer[i-1].x;
3499                 view->drag_info.buffer[i].y = view->drag_info.buffer[i-1].y;
3500         }
3501
3502         /* Momentum is a moving average of 10ms granularity over
3503          * the last 100ms with each 10ms stored in buffer. 
3504          */
3505         
3506         view->drag_info.momentum.x = (view->drag_info.buffer[DRAG_HISTORY - 1].x - view->drag_info.buffer[0].x);
3507         view->drag_info.momentum.y = (view->drag_info.buffer[DRAG_HISTORY - 1].y - view->drag_info.buffer[0].y);
3508
3509         return TRUE;
3510 }
3511
3512 static gboolean
3513 ev_view_scroll_drag_release (EvView *view)
3514 {
3515         gdouble dhadj_value, dvadj_value;
3516         gdouble oldhadjustment, oldvadjustment;
3517
3518         view->drag_info.momentum.x /= 1.2;
3519         view->drag_info.momentum.y /= 1.2; /* Alter these constants to change "friction" */
3520
3521         dhadj_value = view->hadjustment->page_size *
3522                       (gdouble)view->drag_info.momentum.x / GTK_WIDGET (view)->allocation.width;
3523         dvadj_value = view->vadjustment->page_size *
3524                       (gdouble)view->drag_info.momentum.y / GTK_WIDGET (view)->allocation.height;
3525
3526         oldhadjustment = gtk_adjustment_get_value (view->hadjustment);
3527         oldvadjustment = gtk_adjustment_get_value (view->vadjustment);
3528
3529      /* When we reach the edges, we need either to absorb some momentum and bounce by
3530       * multiplying it on -0.5 or stop scrolling by setting momentum to 0. */   
3531      if (((oldhadjustment + dhadj_value) > (view->hadjustment->upper - view->hadjustment->page_size)) ||
3532            ((oldhadjustment + dhadj_value) < 0))
3533                 view->drag_info.momentum.x = 0;
3534         if (((oldvadjustment + dvadj_value) > (view->vadjustment->upper - view->vadjustment->page_size)) ||
3535            ((oldvadjustment + dvadj_value) < 0))
3536                 view->drag_info.momentum.y = 0;
3537
3538         gtk_adjustment_set_value (view->hadjustment,
3539                                 MIN (oldhadjustment + dhadj_value,
3540                                 view->hadjustment->upper - view->hadjustment->page_size));
3541         gtk_adjustment_set_value (view->vadjustment,
3542                                 MIN (oldvadjustment + dvadj_value,
3543                                 view->vadjustment->upper - view->vadjustment->page_size));
3544
3545         if (((view->drag_info.momentum.x < 1) && (view->drag_info.momentum.x > -1)) &&
3546            ((view->drag_info.momentum.y < 1) && (view->drag_info.momentum.y > -1)))
3547                 return FALSE;
3548         else
3549                 return TRUE;
3550 }
3551
3552 static gboolean
3553 ev_view_motion_notify_event (GtkWidget      *widget,
3554                              GdkEventMotion *event)
3555 {
3556         EvView *view = EV_VIEW (widget);
3557         gint x, y;
3558
3559         if (!view->document)
3560                 return FALSE;
3561
3562         if (event->is_hint || event->window != view->layout.bin_window) {
3563             gtk_widget_get_pointer (widget, &x, &y);
3564         } else {
3565             x = event->x;
3566             y = event->y;
3567         }
3568
3569         if (view->scroll_info.autoscrolling) {
3570                 view->scroll_info.last_y = y;
3571                 return TRUE;
3572         }
3573
3574         if (view->selection_info.in_drag) {
3575                 if (gtk_drag_check_threshold (widget,
3576                                               view->selection_info.start.x,
3577                                               view->selection_info.start.y,
3578                                               x, y)) {
3579                         GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
3580
3581                         gtk_target_list_add_text_targets (target_list, TARGET_DND_TEXT);
3582
3583                         gtk_drag_begin (widget, target_list,
3584                                         GDK_ACTION_COPY,
3585                                         1, (GdkEvent *)event);
3586
3587                         view->selection_info.in_drag = FALSE;
3588
3589                         gtk_target_list_unref (target_list);
3590
3591                         return TRUE;
3592                 }
3593         } else if (view->image_dnd_info.in_drag) {
3594                 if (gtk_drag_check_threshold (widget,
3595                                               view->selection_info.start.x,
3596                                               view->selection_info.start.y,
3597                                               x, y)) {
3598                         GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
3599
3600                         gtk_target_list_add_uri_targets (target_list, TARGET_DND_URI);
3601                         gtk_target_list_add_image_targets (target_list, TARGET_DND_IMAGE, TRUE);
3602
3603                         gtk_drag_begin (widget, target_list,
3604                                         GDK_ACTION_COPY,
3605                                         1, (GdkEvent *)event);
3606
3607                         view->image_dnd_info.in_drag = FALSE;
3608
3609                         gtk_target_list_unref (target_list);
3610
3611                         return TRUE;
3612                 }
3613         }
3614         
3615         switch (view->pressed_button) {
3616         case 1:
3617                 /* For the Evince 0.4.x release, we limit selection to un-rotated
3618                  * documents only.
3619                  */
3620                 if (view->rotation != 0)
3621                         return FALSE;
3622
3623                 /* Schedule timeout to scroll during selection and additionally 
3624                  * scroll once to allow arbitrary speed. */
3625                 if (!view->selection_scroll_id)
3626                     view->selection_scroll_id = g_timeout_add (SCROLL_TIME,
3627                                                                (GSourceFunc)selection_scroll_timeout_cb,
3628                                                                view);
3629                 else 
3630                     selection_scroll_timeout_cb (view);
3631
3632                 view->selection_info.in_selection = TRUE;
3633                 view->motion.x = x + view->scroll_x;
3634                 view->motion.y = y + view->scroll_y;
3635
3636                 /* Queue an idle to handle the motion.  We do this because      
3637                  * handling any selection events in the motion could be slower  
3638                  * than new motion events reach us.  We always put it in the    
3639                  * idle to make sure we catch up and don't visibly lag the      
3640                  * mouse. */
3641                 if (!view->selection_update_id)
3642                         view->selection_update_id = g_idle_add ((GSourceFunc)selection_update_idle_cb, view);
3643
3644                 return TRUE;
3645         case 2:
3646                 if (!view->drag_info.in_drag) {
3647                         gboolean start;
3648                         int i;
3649
3650                         start = gtk_drag_check_threshold (widget,
3651                                                           view->drag_info.start.x,
3652                                                           view->drag_info.start.y,
3653                                                           event->x_root,
3654                                                           event->y_root);
3655                         view->drag_info.in_drag = start;
3656                         view->drag_info.drag_timeout_id = g_timeout_add (10,
3657                                 (GSourceFunc)ev_view_drag_update_momentum, view);
3658                         /* Set 100 to choose how long it takes to build up momentum */
3659                         /* Clear out previous momentum info: */
3660                         for (i = 0; i < DRAG_HISTORY; i++) {
3661                                 view->drag_info.buffer[i].x = event->x;
3662                                 view->drag_info.buffer[i].y = event->y;
3663                         }
3664                         view->drag_info.momentum.x = 0;
3665                         view->drag_info.momentum.y = 0;
3666                 }
3667
3668                 if (view->drag_info.in_drag) {
3669                         int dx, dy;
3670                         gdouble dhadj_value, dvadj_value;
3671
3672                         view->drag_info.buffer[0].x = event->x;
3673                         view->drag_info.buffer[0].y = event->y;
3674
3675                         dx = event->x_root - view->drag_info.start.x;
3676                         dy = event->y_root - view->drag_info.start.y;
3677
3678                         dhadj_value = view->hadjustment->page_size *
3679                                       (gdouble)dx / widget->allocation.width;
3680                         dvadj_value = view->vadjustment->page_size *
3681                                       (gdouble)dy / widget->allocation.height;
3682
3683                         /* clamp scrolling to visible area */
3684                         gtk_adjustment_set_value (view->hadjustment,
3685                                                   MIN(view->drag_info.hadj - dhadj_value,
3686                                                       view->hadjustment->upper -
3687                                                       view->hadjustment->page_size));
3688                         gtk_adjustment_set_value (view->vadjustment,
3689                                                   MIN(view->drag_info.vadj - dvadj_value,
3690                                                       view->vadjustment->upper -
3691                                                       view->vadjustment->page_size));
3692
3693                         return TRUE;
3694                 }
3695
3696                 break;
3697         default:
3698                 ev_view_handle_cursor_over_xy (view, x, y);
3699         } 
3700
3701         return FALSE;
3702 }
3703
3704 static gboolean
3705 ev_view_button_release_event (GtkWidget      *widget,
3706                               GdkEventButton *event)
3707 {
3708         EvView *view = EV_VIEW (widget);
3709         EvLink *link = NULL;
3710
3711         view->image_dnd_info.in_drag = FALSE;
3712
3713         if (view->scroll_info.autoscrolling) {
3714                 ev_view_autoscroll_stop (view);
3715                 view->pressed_button = -1;
3716
3717                 return TRUE;
3718         } 
3719
3720         if (view->drag_info.in_drag) {
3721                 view->drag_info.release_timeout_id =
3722                         g_timeout_add (20,
3723                                        (GSourceFunc)ev_view_scroll_drag_release, view);
3724         }
3725
3726         if (view->document && !view->drag_info.in_drag && view->pressed_button != 3) {
3727                 link = ev_view_get_link_at_location (view, event->x, event->y);
3728         }
3729
3730         view->drag_info.in_drag = FALSE;
3731
3732         if (view->pressed_button == 2) {
3733                 ev_view_handle_cursor_over_xy (view, event->x, event->y);
3734         }
3735
3736         view->pressed_button = -1;
3737
3738         if (view->selection_scroll_id) {
3739             g_source_remove (view->selection_scroll_id);
3740             view->selection_scroll_id = 0;
3741         }
3742         if (view->selection_update_id) {
3743             g_source_remove (view->selection_update_id);
3744             view->selection_update_id = 0;
3745         }
3746
3747         if (view->selection_info.selections) {
3748                 clear_link_selected (view);
3749                 ev_view_update_primary_selection (view);
3750                 
3751                 if (view->selection_info.in_drag) {
3752                         clear_selection (view);
3753                         gtk_widget_queue_draw (widget);
3754                 }
3755                 
3756                 view->selection_info.in_drag = FALSE;
3757         } else if (link) {
3758                 if (event->button == 2) {
3759                         EvLinkAction    *action;
3760                         EvLinkActionType type;
3761
3762                         action = ev_link_get_action (link);
3763                         if (!action)
3764                                 return FALSE;
3765
3766                         type = ev_link_action_get_action_type (action);
3767                         if (type == EV_LINK_ACTION_TYPE_GOTO_DEST) {
3768                                 g_signal_emit (view,
3769                                                signals[SIGNAL_EXTERNAL_LINK],
3770                                                0, action);
3771                         }
3772                 } else {
3773                         ev_view_handle_link (view, link);
3774                 }
3775         }
3776
3777         return FALSE;
3778 }
3779
3780 static gboolean
3781 ev_view_key_press_event (GtkWidget   *widget,
3782                          GdkEventKey *event)
3783 {
3784         EvView *view = EV_VIEW (widget);
3785
3786         if (!view->document)
3787                 return FALSE;
3788
3789         if (!gtk_widget_has_focus (widget)) {
3790                 /* Forward key events to current focused window child */
3791                 if (view->window_child_focus) {
3792                         GdkEventKey *new_event;
3793                         gboolean     handled;
3794
3795                         new_event = (GdkEventKey *) gdk_event_copy ((GdkEvent *)event);
3796                         g_object_unref (new_event->window);
3797                         new_event->window = g_object_ref (view->window_child_focus->window->window);
3798                         gtk_widget_realize (view->window_child_focus->window);
3799                         handled = gtk_widget_event (view->window_child_focus->window, (GdkEvent *)new_event);
3800                         gdk_event_free ((GdkEvent *)new_event);
3801
3802                         return handled;
3803                 }
3804
3805                 return FALSE;
3806         }
3807
3808         return gtk_bindings_activate_event (GTK_OBJECT (widget), event);
3809 }
3810
3811 static gint
3812 ev_view_focus_in (GtkWidget     *widget,
3813                   GdkEventFocus *event)
3814 {
3815         if (EV_VIEW (widget)->pixbuf_cache)
3816                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
3817         gtk_widget_queue_draw (widget);
3818
3819         return FALSE;
3820 }
3821
3822 static gint
3823 ev_view_focus_out (GtkWidget     *widget,
3824                    GdkEventFocus *event)
3825 {
3826         if (EV_VIEW (widget)->pixbuf_cache)
3827                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
3828         gtk_widget_queue_draw (widget);
3829
3830         return FALSE;
3831 }
3832
3833 static gboolean
3834 ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
3835 {
3836         EvView *view = EV_VIEW (widget);
3837
3838         if (view->cursor != EV_VIEW_CURSOR_NORMAL)
3839                 ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
3840
3841         return FALSE;
3842 }
3843
3844 static gboolean
3845 ev_view_enter_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
3846 {
3847         EvView *view = EV_VIEW (widget);
3848
3849         ev_view_handle_cursor_over_xy (view, event->x, event->y);
3850     
3851         return FALSE;
3852 }
3853
3854 static void
3855 ev_view_style_set (GtkWidget *widget,
3856                    GtkStyle  *old_style)
3857 {
3858         if (EV_VIEW (widget)->pixbuf_cache)
3859                 ev_pixbuf_cache_style_changed (EV_VIEW (widget)->pixbuf_cache);
3860
3861         GTK_WIDGET_CLASS (ev_view_parent_class)->style_set (widget, old_style);
3862 }
3863
3864 /*** Drawing ***/
3865
3866 static guint32
3867 ev_gdk_color_to_rgb (const GdkColor *color)
3868 {
3869   guint32 result;
3870   result = (0xff0000 | (color->red & 0xff00));
3871   result <<= 8;
3872   result |= ((color->green & 0xff00) | (color->blue >> 8));
3873   return result;
3874 }
3875
3876 static void
3877 draw_rubberband (GtkWidget *widget, GdkWindow *window,
3878                  const GdkRectangle *rect, guchar alpha)
3879 {
3880         GdkGC *gc;
3881         GdkPixbuf *pixbuf;
3882         GdkColor *fill_color_gdk;
3883         guint fill_color;
3884
3885         fill_color_gdk = gdk_color_copy (&GTK_WIDGET (widget)->style->base[GTK_STATE_SELECTED]);
3886         fill_color = ev_gdk_color_to_rgb (fill_color_gdk) << 8 | alpha;
3887
3888         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
3889                                  rect->width, rect->height);
3890         gdk_pixbuf_fill (pixbuf, fill_color);
3891
3892         gdk_draw_pixbuf (window, NULL, pixbuf,
3893                          0, 0,
3894                          rect->x - EV_VIEW (widget)->scroll_x, rect->y - EV_VIEW (widget)->scroll_y,
3895                          rect->width, rect->height,
3896                          GDK_RGB_DITHER_NONE,
3897                          0, 0);
3898
3899         g_object_unref (pixbuf);
3900
3901         gc = gdk_gc_new (window);
3902         gdk_gc_set_rgb_fg_color (gc, fill_color_gdk);
3903         gdk_draw_rectangle (window, gc, FALSE,
3904                             rect->x - EV_VIEW (widget)->scroll_x, rect->y - EV_VIEW (widget)->scroll_y,
3905                             rect->width - 1,
3906                             rect->height - 1);
3907         g_object_unref (gc);
3908
3909         gdk_color_free (fill_color_gdk);
3910 }
3911
3912
3913 static void
3914 highlight_find_results (EvView *view, int page)
3915 {
3916         gint i, n_results = 0;
3917
3918         n_results = ev_view_find_get_n_results (view, page);
3919
3920         for (i = 0; i < n_results; i++) {
3921                 EvRectangle *rectangle;
3922                 GdkRectangle view_rectangle;
3923                 guchar alpha;
3924
3925                 if (i == view->find_result && page == view->current_page) {
3926                         alpha = 0x90;
3927                 } else {
3928                         alpha = 0x20;
3929                 }
3930
3931                 rectangle = ev_view_find_get_result (view, page, i);
3932                 doc_rect_to_view_rect (view, page, rectangle, &view_rectangle);
3933                 draw_rubberband (GTK_WIDGET (view), view->layout.bin_window,
3934                                  &view_rectangle, alpha);
3935         }
3936 }
3937
3938 static void
3939 ev_view_loading_window_move (EvView *view)
3940 {
3941         GtkWidget       *widget = GTK_WIDGET (view);
3942         EvLoadingWindow *window = EV_LOADING_WINDOW (view->loading_window);
3943         gint             root_x, root_y;
3944         gint             window_width;
3945         GtkAllocation    allocation;
3946
3947         gtk_widget_get_allocation (widget, &allocation);
3948         gdk_window_get_origin (gtk_widget_get_window (widget), &root_x, &root_y);
3949         ev_loading_window_get_size (window, &window_width, NULL);
3950
3951         root_x += allocation.width - window_width - 10;
3952         root_y += 10;
3953
3954         ev_loading_window_move (window, root_x, root_y);
3955 }
3956
3957 static gboolean
3958 show_loading_window_cb (EvView *view)
3959 {
3960         if (!view->loading_window) {
3961                 GtkWindow *parent;
3962                 GdkScreen *screen;
3963
3964                 parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view)));
3965                 view->loading_window = ev_loading_window_new (parent);
3966
3967                 /* Show the window off screen to get a valid size asap */
3968                 screen = gtk_widget_get_screen (GTK_WIDGET (view));
3969                 gtk_window_move (GTK_WINDOW (view->loading_window),
3970                                  gdk_screen_get_width (screen) + 1,
3971                                  gdk_screen_get_height (screen) + 1);
3972                 gtk_widget_show (view->loading_window);
3973         }
3974
3975         ev_view_loading_window_move (view);
3976
3977         gtk_widget_show (view->loading_window);
3978
3979         view->loading_timeout = 0;
3980
3981         return FALSE;
3982 }
3983
3984 static void
3985 show_loading_window (EvView *view)
3986 {
3987         if (view->loading_window && gtk_widget_get_visible (view->loading_window)) {
3988                 ev_view_loading_window_move (view);
3989                 return;
3990         }
3991
3992         if (!view->loading_timeout) {
3993                 view->loading_timeout =
3994                         g_timeout_add_full (G_PRIORITY_LOW,
3995                                             0.5, (GSourceFunc)show_loading_window_cb,
3996                                             view, NULL);
3997         }
3998 }
3999
4000 static void
4001 hide_loading_window (EvView *view)
4002 {
4003         if (view->loading_timeout) {
4004                 g_source_remove (view->loading_timeout);
4005                 view->loading_timeout = 0;
4006         }
4007
4008         if (view->loading_window && gtk_widget_get_visible (view->loading_window)) {
4009                 gtk_widget_hide (view->loading_window);
4010         }
4011 }
4012
4013 static void
4014 draw_one_page (EvView       *view,
4015                gint          page,
4016                cairo_t      *cr,
4017                GdkRectangle *page_area,
4018                GtkBorder    *border,
4019                GdkRectangle *expose_area,
4020                gboolean     *page_ready)
4021 {
4022         GdkRectangle overlap;
4023         GdkRectangle real_page_area;
4024         gint         current_page;
4025         gboolean     inverted_colors;
4026
4027         g_assert (view->document);
4028
4029         if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
4030                 return;
4031
4032         /* Render the document itself */
4033         real_page_area = *page_area;
4034
4035         real_page_area.x += border->left;
4036         real_page_area.y += border->top;
4037         real_page_area.width -= (border->left + border->right);
4038         real_page_area.height -= (border->top + border->bottom);
4039         *page_ready = TRUE;
4040
4041         current_page = ev_document_model_get_page (view->model);
4042         inverted_colors = ev_document_model_get_inverted_colors (view->model);
4043         ev_document_misc_paint_one_page (view->layout.bin_window,
4044                                          GTK_WIDGET (view),
4045                                          page_area, border,
4046                                          page == current_page,
4047                                          inverted_colors);
4048
4049         if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
4050                 gint             width, height;
4051                 gint             page_width, page_height;
4052                 cairo_surface_t *page_surface = NULL;
4053                 gint             selection_width, selection_height;
4054                 cairo_surface_t *selection_surface = NULL;
4055
4056                 page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
4057
4058                 if (!page_surface) {
4059                         if (page == current_page)
4060                                 show_loading_window (view);
4061
4062                         *page_ready = FALSE;
4063
4064                         return;
4065                 }
4066
4067                 if (page == current_page)
4068                         hide_loading_window (view);
4069
4070                 ev_view_get_page_size (view, page, &width, &height);
4071
4072                 page_width = cairo_image_surface_get_width (page_surface);
4073                 page_height = cairo_image_surface_get_height (page_surface);
4074
4075                 cairo_save (cr);
4076                 cairo_translate (cr, overlap.x, overlap.y);
4077
4078                 if (width != page_width || height != page_height) {
4079                         cairo_pattern_set_filter (cairo_get_source (cr),
4080                                                   CAIRO_FILTER_FAST);
4081                         cairo_scale (cr,
4082                                      (gdouble)width / page_width,
4083                                      (gdouble)height / page_height);
4084                 }
4085
4086                 cairo_surface_set_device_offset (page_surface,
4087                                                  overlap.x - real_page_area.x,
4088                                                  overlap.y - real_page_area.y);
4089                 cairo_set_source_surface (cr, page_surface, 0, 0);
4090                 cairo_paint (cr);
4091                 cairo_restore (cr);
4092                 
4093                 /* Get the selection pixbuf iff we have something to draw */
4094                 if (find_selection_for_page (view, page) &&
4095                     view->selection_mode == EV_VIEW_SELECTION_TEXT) {
4096                         selection_surface =
4097                                 ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
4098                                                                        page,
4099                                                                        view->scale,
4100                                                                        NULL);
4101                 }
4102
4103                 if (!selection_surface) {
4104                         return;
4105                 }
4106
4107                 selection_width = cairo_image_surface_get_width (selection_surface);
4108                 selection_height = cairo_image_surface_get_height (selection_surface);
4109
4110                 cairo_save (cr);
4111                 cairo_translate (cr, overlap.x, overlap.y);
4112
4113                 if (width != selection_width || height != selection_height) {
4114                         cairo_pattern_set_filter (cairo_get_source (cr),
4115                                                   CAIRO_FILTER_FAST);
4116                         cairo_scale (cr,
4117                                      (gdouble)width / selection_width,
4118                                      (gdouble)height / selection_height);
4119                 }
4120
4121                 cairo_surface_set_device_offset (selection_surface,
4122                                                  overlap.x - real_page_area.x,
4123                                                  overlap.y - real_page_area.y);
4124                 cairo_set_source_surface (cr, selection_surface, 0, 0);
4125                 cairo_paint (cr);
4126                 cairo_restore (cr);
4127         }
4128 }
4129
4130 /*** GObject functions ***/
4131
4132 static void
4133 ev_view_finalize (GObject *object)
4134 {
4135         EvView *view = EV_VIEW (object);
4136
4137         clear_selection (view);
4138         clear_link_selected (view);
4139
4140         if (view->image_dnd_info.image)
4141                 g_object_unref (view->image_dnd_info.image);
4142         view->image_dnd_info.image = NULL;
4143
4144         G_OBJECT_CLASS (ev_view_parent_class)->finalize (object);
4145 }
4146
4147 static void
4148 ev_view_destroy (GtkObject *object)
4149 {
4150         EvView *view = EV_VIEW (object);
4151
4152         if (view->model) {
4153                 g_object_unref (view->model);
4154                 view->model = NULL;
4155         }
4156
4157         if (view->pixbuf_cache) {
4158                 g_object_unref (view->pixbuf_cache);
4159                 view->pixbuf_cache = NULL;
4160         }
4161
4162         if (view->document) {
4163                 g_object_unref (view->document);
4164                 view->document = NULL;
4165         }
4166
4167         if (view->page_cache) {
4168                 g_object_unref (view->page_cache);
4169                 view->page_cache = NULL;
4170         }
4171
4172         ev_view_window_children_free (view);
4173
4174         if (view->selection_scroll_id) {
4175             g_source_remove (view->selection_scroll_id);
4176             view->selection_scroll_id = 0;
4177         }
4178
4179         if (view->selection_update_id) {
4180             g_source_remove (view->selection_update_id);
4181             view->selection_update_id = 0;
4182         }
4183
4184         if (view->scroll_info.timeout_id) {
4185             g_source_remove (view->scroll_info.timeout_id);
4186             view->scroll_info.timeout_id = 0;
4187         }
4188
4189         if (view->drag_info.drag_timeout_id) {
4190                 g_source_remove (view->drag_info.drag_timeout_id);
4191                 view->drag_info.drag_timeout_id = 0;
4192         }
4193
4194         if (view->drag_info.release_timeout_id) {
4195                 g_source_remove (view->drag_info.release_timeout_id);
4196                 view->drag_info.release_timeout_id = 0;
4197         }
4198
4199         if (view->loading_timeout) {
4200                 g_source_remove (view->loading_timeout);
4201                 view->loading_timeout = 0;
4202         }
4203
4204         ev_view_set_scroll_adjustments (GTK_LAYOUT (view), NULL, NULL);
4205
4206         GTK_OBJECT_CLASS (ev_view_parent_class)->destroy (object);
4207 }
4208
4209 static AtkObject *
4210 ev_view_get_accessible (GtkWidget *widget)
4211 {
4212         static gboolean first_time = TRUE;
4213
4214         if (first_time) {
4215                 AtkObjectFactory *factory;
4216                 AtkRegistry *registry;
4217                 GType derived_type; 
4218                 GType derived_atk_type; 
4219
4220                 /*
4221                  * Figure out whether accessibility is enabled by looking at the
4222                  * type of the accessible object which would be created for
4223                  * the parent type of EvView.
4224                  */
4225                 derived_type = g_type_parent (EV_TYPE_VIEW);
4226
4227                 registry = atk_get_default_registry ();
4228                 factory = atk_registry_get_factory (registry,
4229                                                     derived_type);
4230                 derived_atk_type = atk_object_factory_get_accessible_type (factory);
4231                 if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE)) 
4232                         atk_registry_set_factory_type (registry, 
4233                                                        EV_TYPE_VIEW,
4234                                                        ev_view_accessible_factory_get_type ());
4235                 first_time = FALSE;
4236         } 
4237         return GTK_WIDGET_CLASS (ev_view_parent_class)->get_accessible (widget);
4238 }
4239
4240 static void
4241 ev_view_class_init (EvViewClass *class)
4242 {
4243         GObjectClass *object_class = G_OBJECT_CLASS (class);
4244         GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
4245         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
4246         GtkLayoutClass *layout_class = GTK_LAYOUT_CLASS (class);
4247         GtkBindingSet *binding_set;
4248
4249         object_class->finalize = ev_view_finalize;
4250
4251         widget_class->expose_event = ev_view_expose_event;
4252         widget_class->button_press_event = ev_view_button_press_event;
4253         widget_class->motion_notify_event = ev_view_motion_notify_event;
4254         widget_class->button_release_event = ev_view_button_release_event;
4255         widget_class->key_press_event = ev_view_key_press_event;
4256         widget_class->focus_in_event = ev_view_focus_in;
4257         widget_class->focus_out_event = ev_view_focus_out;
4258         widget_class->get_accessible = ev_view_get_accessible;
4259         widget_class->size_request = ev_view_size_request;
4260         widget_class->size_allocate = ev_view_size_allocate;
4261         widget_class->realize = ev_view_realize;
4262         widget_class->scroll_event = ev_view_scroll_event;
4263         widget_class->enter_notify_event = ev_view_enter_notify_event;
4264         widget_class->leave_notify_event = ev_view_leave_notify_event;
4265         widget_class->style_set = ev_view_style_set;
4266         widget_class->drag_data_get = ev_view_drag_data_get;
4267         widget_class->drag_motion = ev_view_drag_motion;
4268         widget_class->popup_menu = ev_view_popup_menu;
4269         widget_class->query_tooltip = ev_view_query_tooltip;
4270
4271         gtk_object_class->destroy = ev_view_destroy;
4272
4273         layout_class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
4274         
4275         class->binding_activated = ev_view_scroll;
4276
4277         signals[SIGNAL_BINDING_ACTIVATED] = g_signal_new ("binding_activated",
4278                          G_TYPE_FROM_CLASS (object_class),
4279                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4280                          G_STRUCT_OFFSET (EvViewClass, binding_activated),
4281                          NULL, NULL,
4282                          ev_view_marshal_VOID__ENUM_BOOLEAN,
4283                          G_TYPE_NONE, 2,
4284                          GTK_TYPE_SCROLL_TYPE,
4285                          G_TYPE_BOOLEAN);
4286         signals[SIGNAL_HANDLE_LINK] = g_signal_new ("handle-link",
4287                          G_TYPE_FROM_CLASS (object_class),
4288                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4289                          G_STRUCT_OFFSET (EvViewClass, handle_link),
4290                          NULL, NULL,
4291                          g_cclosure_marshal_VOID__OBJECT,
4292                          G_TYPE_NONE, 1,
4293                          G_TYPE_OBJECT);
4294         signals[SIGNAL_EXTERNAL_LINK] = g_signal_new ("external-link",
4295                          G_TYPE_FROM_CLASS (object_class),
4296                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4297                          G_STRUCT_OFFSET (EvViewClass, external_link),
4298                          NULL, NULL,
4299                          g_cclosure_marshal_VOID__OBJECT,
4300                          G_TYPE_NONE, 1,
4301                          G_TYPE_OBJECT);
4302         signals[SIGNAL_POPUP_MENU] = g_signal_new ("popup",
4303                          G_TYPE_FROM_CLASS (object_class),
4304                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4305                          G_STRUCT_OFFSET (EvViewClass, popup_menu),
4306                          NULL, NULL,
4307                          g_cclosure_marshal_VOID__POINTER,
4308                          G_TYPE_NONE, 1,
4309                          G_TYPE_POINTER);
4310         signals[SIGNAL_SELECTION_CHANGED] = g_signal_new ("selection-changed",
4311                          G_TYPE_FROM_CLASS (object_class),
4312                          G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4313                          G_STRUCT_OFFSET (EvViewClass, selection_changed),
4314                          NULL, NULL,
4315                          g_cclosure_marshal_VOID__VOID,
4316                          G_TYPE_NONE, 0,
4317                          G_TYPE_NONE);
4318
4319         binding_set = gtk_binding_set_by_class (class);
4320
4321         add_scroll_binding_keypad (binding_set, GDK_Left,  0, GTK_SCROLL_STEP_BACKWARD, TRUE);
4322         add_scroll_binding_keypad (binding_set, GDK_Right, 0, GTK_SCROLL_STEP_FORWARD,  TRUE);
4323         add_scroll_binding_keypad (binding_set, GDK_Left,  GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, TRUE);
4324         add_scroll_binding_keypad (binding_set, GDK_Right, GDK_MOD1_MASK, GTK_SCROLL_STEP_UP,  TRUE);
4325         add_scroll_binding_keypad (binding_set, GDK_Up,    0, GTK_SCROLL_STEP_BACKWARD, FALSE);
4326         add_scroll_binding_keypad (binding_set, GDK_Down,  0, GTK_SCROLL_STEP_FORWARD,  FALSE);
4327         add_scroll_binding_keypad (binding_set, GDK_Up,    GDK_MOD1_MASK, GTK_SCROLL_STEP_DOWN, FALSE);
4328         add_scroll_binding_keypad (binding_set, GDK_Down,  GDK_MOD1_MASK, GTK_SCROLL_STEP_UP,  FALSE);
4329         gtk_binding_entry_add_signal (binding_set, GDK_H, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4330                                       GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, TRUE);
4331         gtk_binding_entry_add_signal (binding_set, GDK_J, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4332                                       GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, FALSE);
4333         gtk_binding_entry_add_signal (binding_set, GDK_K, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4334                                       GTK_SCROLL_STEP_BACKWARD, G_TYPE_BOOLEAN, FALSE);
4335         gtk_binding_entry_add_signal (binding_set, GDK_L, 0, "binding_activated", 2, GTK_TYPE_SCROLL_TYPE,
4336                                       GTK_SCROLL_STEP_FORWARD, G_TYPE_BOOLEAN, TRUE);
4337         
4338 }
4339
4340 static void
4341 ev_view_init (EvView *view)
4342 {
4343         GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS);
4344
4345         view->start_page = -1;
4346         view->end_page = -1;
4347         view->spacing = 5;
4348         view->scale = 1.0;
4349         view->current_page = 0;
4350         view->pressed_button = -1;
4351         view->cursor = EV_VIEW_CURSOR_NORMAL;
4352         view->drag_info.in_drag = FALSE;
4353         view->scroll_info.autoscrolling = FALSE;
4354         view->selection_info.selections = NULL;
4355         view->selection_info.in_selection = FALSE;
4356         view->selection_info.in_drag = FALSE;
4357         view->selection_mode = EV_VIEW_SELECTION_TEXT;
4358         view->continuous = TRUE;
4359         view->dual_page = FALSE;
4360         view->fullscreen = FALSE;
4361         view->sizing_mode = EV_SIZING_FIT_WIDTH;
4362         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
4363         view->jump_to_find_result = TRUE;
4364         view->highlight_find_results = FALSE;
4365
4366         gtk_layout_set_hadjustment (GTK_LAYOUT (view), NULL);
4367         gtk_layout_set_vadjustment (GTK_LAYOUT (view), NULL);
4368 }
4369
4370 /*** Callbacks ***/
4371
4372 static void
4373 ev_view_change_page (EvView *view,
4374                      gint    new_page)
4375 {
4376         gint x, y;
4377
4378         view->current_page = new_page;
4379         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
4380
4381         hide_loading_window (view);
4382
4383         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4384         ev_view_handle_cursor_over_xy (view, x, y);
4385
4386         gtk_widget_queue_resize (GTK_WIDGET (view));
4387 }
4388
4389 static void
4390 job_finished_cb (EvPixbufCache *pixbuf_cache,
4391                  GdkRegion     *region,
4392                  EvView        *view)
4393 {
4394         if (region) {
4395                 gdk_window_invalidate_region (view->layout.bin_window,
4396                                               region, TRUE);
4397         } else {
4398                 gtk_widget_queue_draw (GTK_WIDGET (view));
4399         }
4400 }
4401
4402 static void
4403 ev_view_page_changed_cb (EvDocumentModel *model,
4404                          gint             old_page,
4405                          gint             new_page,
4406                          EvView          *view)
4407 {
4408         if (!view->document)
4409                 return;
4410
4411         if (view->current_page != new_page) {
4412                 ev_view_change_page (view, new_page);
4413         } else {
4414                 gtk_widget_queue_draw (GTK_WIDGET (view));
4415         }
4416
4417         view->find_result = 0;
4418 }
4419
4420 static void
4421 on_adjustment_value_changed (GtkAdjustment *adjustment,
4422                              EvView        *view)
4423 {
4424         int dx = 0, dy = 0;
4425         gint x, y;
4426         GList *children, *l;
4427
4428         if (!gtk_widget_get_realized (GTK_WIDGET (view)))
4429                 return;
4430
4431         if (view->hadjustment) {
4432                 dx = view->scroll_x - (int) view->hadjustment->value;
4433                 view->scroll_x = (int) view->hadjustment->value;
4434         } else {
4435                 view->scroll_x = 0;
4436         }
4437
4438         if (view->vadjustment) {
4439                 dy = view->scroll_y - (int) view->vadjustment->value;
4440                 view->scroll_y = (int) view->vadjustment->value;
4441         } else {
4442                 view->scroll_y = 0;
4443         }
4444
4445         children = gtk_container_get_children (GTK_CONTAINER (view));
4446         for (l = children; l && l->data; l = g_list_next (l)) {
4447                 gint       child_x, child_y;
4448                 GtkWidget *child = (GtkWidget *)l->data;
4449                 
4450                 gtk_container_child_get (GTK_CONTAINER (view),
4451                                          child,
4452                                          "x", &child_x,
4453                                          "y", &child_y,
4454                                          NULL);
4455                 gtk_layout_move (GTK_LAYOUT (view), child, child_x + dx, child_y + dy);
4456         }
4457         g_list_free (children);
4458
4459         for (l = view->window_children; l && l->data; l = g_list_next (l)) {
4460                 EvViewWindowChild *child;
4461
4462                 child = (EvViewWindowChild *)l->data;
4463
4464                 ev_view_window_child_move (view, child, child->x + dx, child->y + dy);
4465         }
4466         
4467         if (view->pending_resize)
4468                 gtk_widget_queue_draw (GTK_WIDGET (view));
4469         else
4470                 gdk_window_scroll (view->layout.bin_window, dx, dy);
4471                 
4472         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4473         ev_view_handle_cursor_over_xy (view, x, y);
4474
4475         if (view->document)
4476                 view_update_range_and_current_page (view);
4477 }
4478
4479 GtkWidget*
4480 ev_view_new (void)
4481 {
4482         GtkWidget *view;
4483
4484         view = g_object_new (EV_TYPE_VIEW, NULL);
4485
4486         return view;
4487 }
4488
4489 static void
4490 setup_caches (EvView *view)
4491 {
4492         gboolean inverted_colors;
4493
4494         view->height_to_page_cache = ev_view_get_height_to_page_cache (view);
4495         view->pixbuf_cache = ev_pixbuf_cache_new (GTK_WIDGET (view), view->document);
4496         view->page_cache = ev_page_cache_new (view->document);
4497         inverted_colors = ev_document_model_get_inverted_colors (view->model);
4498         ev_pixbuf_cache_set_inverted_colors (view->pixbuf_cache, inverted_colors);
4499         g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view);
4500 }
4501
4502 static void
4503 clear_caches (EvView *view)
4504 {
4505         if (view->pixbuf_cache) {
4506                 g_object_unref (view->pixbuf_cache);
4507                 view->pixbuf_cache = NULL;
4508         }
4509
4510         if (view->page_cache) {
4511                 g_object_unref (view->page_cache);
4512                 view->page_cache = NULL;
4513         }
4514 }
4515
4516 void
4517 ev_view_set_loading (EvView       *view,
4518                      gboolean      loading)
4519 {
4520         view->loading = loading;
4521         gtk_widget_queue_draw (GTK_WIDGET (view));
4522 }
4523
4524 static gboolean
4525 ev_view_autoscroll_cb (EvView *view)
4526 {
4527         gdouble speed, value;
4528
4529         /* If the user stops autoscrolling, autoscrolling will be
4530          * set to false but the timeout will continue; stop the timeout: */
4531         if (!view->scroll_info.autoscrolling) {
4532                 view->scroll_info.timeout_id = 0;
4533                 return FALSE;
4534         }
4535         
4536         if (view->scroll_info.last_y > view->scroll_info.start_y && 
4537                 (view->scroll_info.last_y < view->scroll_info.start_y))
4538                 return TRUE; 
4539
4540         /* Replace 100 with your speed of choice: The lower the faster.
4541          * Replace 3 with another speed of choice: The higher, the faster it accelerated
4542          *      based on the distance of the starting point from the mouse
4543          * (All also effected by the timeout interval of this callback) */
4544
4545         if (view->scroll_info.start_y > view->scroll_info.last_y)
4546                 speed = -pow ((((gdouble)view->scroll_info.start_y - view->scroll_info.last_y) / 100), 3);
4547         else
4548                 speed = pow ((((gdouble)view->scroll_info.last_y - view->scroll_info.start_y) / 100), 3);
4549         
4550         value = gtk_adjustment_get_value (view->vadjustment);
4551         value = CLAMP (value + speed, 0, view->vadjustment->upper - view->vadjustment->page_size);
4552         gtk_adjustment_set_value (view->vadjustment, value);
4553         
4554         return TRUE;
4555
4556 }
4557
4558 void
4559 ev_view_autoscroll_start (EvView *view)
4560 {
4561         gint x, y;
4562         
4563         g_return_if_fail (EV_IS_VIEW (view));
4564
4565         if (view->scroll_info.autoscrolling)
4566                 return;
4567         
4568         view->scroll_info.autoscrolling = TRUE;
4569         view->scroll_info.timeout_id =
4570                 g_timeout_add (20, (GSourceFunc)ev_view_autoscroll_cb,
4571                                view);
4572         
4573         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4574         ev_view_handle_cursor_over_xy (view, x, y);
4575 }
4576
4577 void
4578 ev_view_autoscroll_stop (EvView *view)
4579 {
4580         gint x, y;
4581         
4582         g_return_if_fail (EV_IS_VIEW (view));
4583
4584         if (!view->scroll_info.autoscrolling)
4585                 return;
4586
4587         view->scroll_info.autoscrolling = FALSE;
4588         if (view->scroll_info.timeout_id) {
4589                 g_source_remove (view->scroll_info.timeout_id);
4590                 view->scroll_info.timeout_id = 0;
4591         }
4592
4593         gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
4594         ev_view_handle_cursor_over_xy (view, x, y);
4595 }
4596
4597 static void
4598 ev_view_document_changed_cb (EvDocumentModel *model,
4599                              GParamSpec      *pspec,
4600                              EvView          *view)
4601 {
4602         EvDocument *document = ev_document_model_get_document (model);
4603
4604         if (document != view->document) {
4605                 gint current_page;
4606
4607                 clear_caches (view);
4608
4609                 if (view->document) {
4610                         g_object_unref (view->document);
4611                 }
4612
4613                 view->document = document;
4614                 view->find_result = 0;
4615
4616                 if (view->document) {
4617                         view->loading = FALSE;
4618                         g_object_ref (view->document);
4619                         setup_caches (view);
4620                 }
4621
4622                 current_page = ev_document_model_get_page (model);
4623                 if (view->current_page != current_page) {
4624                         ev_view_change_page (view, current_page);
4625                 } else {
4626                         view->pending_scroll = SCROLL_TO_KEEP_POSITION;
4627                         gtk_widget_queue_resize (GTK_WIDGET (view));
4628                 }
4629         }
4630 }
4631
4632 static void
4633 ev_view_rotation_changed_cb (EvDocumentModel *model,
4634                              GParamSpec      *pspec,
4635                              EvView          *view)
4636 {
4637         gint rotation = ev_document_model_get_rotation (model);
4638
4639         view->rotation = rotation;
4640
4641         if (view->pixbuf_cache) {
4642                 ev_pixbuf_cache_clear (view->pixbuf_cache);
4643                 if (!ev_document_is_page_size_uniform (view->document))
4644                         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
4645                 gtk_widget_queue_resize (GTK_WIDGET (view));
4646         }
4647
4648         ev_view_remove_all (view);
4649
4650         if (rotation != 0)
4651                 clear_selection (view);
4652 }
4653
4654 static void
4655 ev_view_inverted_colors_changed_cb (EvDocumentModel *model,
4656                                     GParamSpec      *pspec,
4657                                     EvView          *view)
4658 {
4659         if (view->pixbuf_cache) {
4660                 gboolean inverted_colors;
4661
4662                 inverted_colors = ev_document_model_get_inverted_colors (model);
4663                 ev_pixbuf_cache_set_inverted_colors (view->pixbuf_cache, inverted_colors);
4664                 gtk_widget_queue_draw (GTK_WIDGET (view));
4665         }
4666 }
4667
4668 static void
4669 ev_view_sizing_mode_changed_cb (EvDocumentModel *model,
4670                                 GParamSpec      *pspec,
4671                                 EvView          *view)
4672 {
4673         EvSizingMode mode = ev_document_model_get_sizing_mode (model);
4674
4675         view->sizing_mode = mode;
4676         if (mode != EV_SIZING_FREE)
4677                 gtk_widget_queue_resize (GTK_WIDGET (view));
4678 }
4679
4680 #define EPSILON 0.0000001
4681 static void
4682 ev_view_scale_changed_cb (EvDocumentModel *model,
4683                           GParamSpec      *pspec,
4684                           EvView          *view)
4685 {
4686         gdouble scale = ev_document_model_get_scale (model);
4687
4688         if (ABS (view->scale - scale) < EPSILON)
4689                 return;
4690
4691         view->scale = scale;
4692
4693         view->pending_resize = TRUE;
4694         if (view->sizing_mode == EV_SIZING_FREE)
4695                 gtk_widget_queue_resize (GTK_WIDGET (view));
4696 }
4697
4698 static void
4699 ev_view_continuous_changed_cb (EvDocumentModel *model,
4700                                GParamSpec      *pspec,
4701                                EvView          *view)
4702 {
4703         gboolean continuous = ev_document_model_get_continuous (model);
4704
4705         view->continuous = continuous;
4706         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
4707         gtk_widget_queue_resize (GTK_WIDGET (view));
4708 }
4709
4710 static void
4711 ev_view_dual_page_changed_cb (EvDocumentModel *model,
4712                               GParamSpec      *pspec,
4713                               EvView          *view)
4714 {
4715         gboolean dual_page = ev_document_model_get_dual_page (model);
4716
4717         view->dual_page = dual_page;
4718         view->pending_scroll = SCROLL_TO_PAGE_POSITION;
4719         /* FIXME: if we're keeping the pixbuf cache around, we should extend the
4720          * preload_cache_size to be 2 if dual_page is set.
4721          */
4722         gtk_widget_queue_resize (GTK_WIDGET (view));
4723 }
4724
4725 static void
4726 ev_view_fullscreen_changed_cb (EvDocumentModel *model,
4727                                GParamSpec      *pspec,
4728                                EvView          *view)
4729 {
4730         gboolean fullscreen = ev_document_model_get_fullscreen (model);
4731
4732         view->fullscreen = fullscreen;
4733         gtk_widget_queue_resize (GTK_WIDGET (view));
4734 }
4735
4736 void
4737 ev_view_set_model (EvView          *view,
4738                    EvDocumentModel *model)
4739 {
4740         g_return_if_fail (EV_IS_VIEW (view));
4741         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
4742
4743         if (model == view->model)
4744                 return;
4745
4746         if (view->model) {
4747                 g_signal_handlers_disconnect_by_func (view->model,
4748                                                       ev_view_document_changed_cb,
4749                                                       view);
4750                 g_signal_handlers_disconnect_by_func (view->model,
4751                                                       ev_view_page_changed_cb,
4752                                                       view);
4753                 g_object_unref (view->model);
4754         }
4755         view->model = g_object_ref (model);
4756
4757         /* Initialize view from model */
4758         view->rotation = ev_document_model_get_rotation (view->model);
4759         view->sizing_mode = ev_document_model_get_sizing_mode (view->model);
4760         view->scale = ev_document_model_get_scale (view->model);
4761         view->continuous = ev_document_model_get_continuous (view->model);
4762         view->dual_page = ev_document_model_get_dual_page (view->model);
4763         view->fullscreen = ev_document_model_get_fullscreen (view->model);
4764         ev_view_document_changed_cb (view->model, NULL, view);
4765
4766         g_signal_connect (view->model, "notify::document",
4767                           G_CALLBACK (ev_view_document_changed_cb),
4768                           view);
4769         g_signal_connect (view->model, "notify::rotation",
4770                           G_CALLBACK (ev_view_rotation_changed_cb),
4771                           view);
4772         g_signal_connect (view->model, "notify::inverted-colors",
4773                           G_CALLBACK (ev_view_inverted_colors_changed_cb),
4774                           view);
4775         g_signal_connect (view->model, "notify::sizing-mode",
4776                           G_CALLBACK (ev_view_sizing_mode_changed_cb),
4777                           view);
4778         g_signal_connect (view->model, "notify::scale",
4779                           G_CALLBACK (ev_view_scale_changed_cb),
4780                           view);
4781         g_signal_connect (view->model, "notify::continuous",
4782                           G_CALLBACK (ev_view_continuous_changed_cb),
4783                           view);
4784         g_signal_connect (view->model, "notify::dual-page",
4785                           G_CALLBACK (ev_view_dual_page_changed_cb),
4786                           view);
4787         g_signal_connect (view->model, "notify::fullscreen",
4788                           G_CALLBACK (ev_view_fullscreen_changed_cb),
4789                           view);
4790         g_signal_connect (view->model, "page-changed",
4791                           G_CALLBACK (ev_view_page_changed_cb),
4792                           view);
4793 }
4794
4795 static void
4796 ev_view_reload_page (EvView    *view,
4797                      gint       page,
4798                      GdkRegion *region)
4799 {
4800         ev_pixbuf_cache_reload_page (view->pixbuf_cache,
4801                                      region,
4802                                      page,
4803                                      view->rotation,
4804                                      view->scale);
4805 }
4806
4807 void
4808 ev_view_reload (EvView *view)
4809 {
4810         ev_pixbuf_cache_clear (view->pixbuf_cache);
4811         view_update_range_and_current_page (view);
4812 }
4813
4814 /*** Zoom and sizing mode ***/
4815
4816 gboolean
4817 ev_view_can_zoom_in (EvView *view)
4818 {
4819         return view->scale * ZOOM_IN_FACTOR <= ev_document_model_get_max_scale (view->model);
4820 }
4821
4822 gboolean
4823 ev_view_can_zoom_out (EvView *view)
4824 {
4825         return view->scale * ZOOM_OUT_FACTOR >= ev_document_model_get_min_scale (view->model);
4826 }
4827
4828 void
4829 ev_view_zoom_in (EvView *view)
4830 {
4831         gdouble scale;
4832
4833         g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
4834
4835         view->pending_scroll = SCROLL_TO_CENTER;
4836         scale = ev_document_model_get_scale (view->model) * ZOOM_IN_FACTOR;
4837         ev_document_model_set_scale (view->model, scale);
4838 }
4839
4840 void
4841 ev_view_zoom_out (EvView *view)
4842 {
4843         gdouble scale;
4844
4845         g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
4846
4847         view->pending_scroll = SCROLL_TO_CENTER;
4848         scale = ev_document_model_get_scale (view->model) * ZOOM_OUT_FACTOR;
4849         ev_document_model_set_scale (view->model, scale);
4850 }
4851
4852 static double
4853 zoom_for_size_fit_width (gdouble doc_width,
4854                          gdouble doc_height,
4855                          int     target_width,
4856                          int     target_height)
4857 {
4858         return (double)target_width / doc_width;
4859 }
4860
4861 static double
4862 zoom_for_size_fit_height (gdouble doc_width,
4863                           gdouble doc_height,
4864                           int     target_width,
4865                           int     target_height)
4866 {
4867         return (double)target_height / doc_height;
4868 }
4869
4870 static double
4871 zoom_for_size_best_fit (gdouble doc_width,
4872                         gdouble doc_height,
4873                         int     target_width,
4874                         int     target_height)
4875 {
4876         double w_scale;
4877         double h_scale;
4878
4879         w_scale = (double)target_width / doc_width;
4880         h_scale = (double)target_height / doc_height;
4881
4882         return MIN (w_scale, h_scale);
4883 }
4884
4885 static void
4886 ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
4887                                                 int     width,
4888                                                 int     height)
4889 {
4890         gdouble doc_width, doc_height;
4891         GtkBorder border;
4892         gdouble scale;
4893         gint sb_size;
4894
4895         ev_document_get_max_page_size (view->document, &doc_width, &doc_height);
4896         if (view->rotation == 90 || view->rotation == 270) {
4897                 gdouble tmp;
4898
4899                 tmp = doc_width;
4900                 doc_width = doc_height;
4901                 doc_height = tmp;
4902         }
4903
4904         compute_border (view, doc_width, doc_height, &border);
4905
4906         doc_width *= 2;
4907         width -= (2 * (border.left + border.right) + 3 * view->spacing);
4908         height -= (border.top + border.bottom + 2 * view->spacing - 1);
4909
4910         sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
4911
4912         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
4913                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
4914         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
4915                 scale = zoom_for_size_best_fit (doc_width, doc_height, width - sb_size, height);
4916         else
4917                 g_assert_not_reached ();
4918
4919         ev_document_model_set_scale (view->model, scale);
4920 }
4921
4922 static void
4923 ev_view_zoom_for_size_continuous (EvView *view,
4924                                   int     width,
4925                                   int     height)
4926 {
4927         gdouble doc_width, doc_height;
4928         GtkBorder border;
4929         gdouble scale;
4930         gint sb_size;
4931
4932         ev_document_get_max_page_size (view->document, &doc_width, &doc_height);
4933         if (view->rotation == 90 || view->rotation == 270) {
4934                 gdouble tmp;
4935
4936                 tmp = doc_width;
4937                 doc_width = doc_height;
4938                 doc_height = tmp;
4939         }
4940
4941         compute_border (view, doc_width, doc_height, &border);
4942
4943         width -= (border.left + border.right + 2 * view->spacing);
4944         height -= (border.top + border.bottom + 2 * view->spacing - 1);
4945
4946         sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
4947
4948         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
4949                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
4950         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
4951                 scale = zoom_for_size_best_fit (doc_width, doc_height, width - sb_size, height);
4952         else
4953                 g_assert_not_reached ();
4954
4955         ev_document_model_set_scale (view->model, scale);
4956 }
4957
4958 static void
4959 ev_view_zoom_for_size_dual_page (EvView *view,
4960                                  int     width,
4961                                  int     height)
4962 {
4963         GtkBorder border;
4964         gdouble doc_width, doc_height;
4965         gdouble scale;
4966         gint other_page;
4967
4968         other_page = view->current_page ^ 1;
4969
4970         /* Find the largest of the two. */
4971         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
4972         if (other_page < ev_document_get_n_pages (view->document)) {
4973                 gdouble width_2, height_2;
4974
4975                 get_doc_page_size (view, other_page, &width_2, &height_2);
4976                 if (width_2 > doc_width)
4977                         doc_width = width_2;
4978                 if (height_2 > doc_height)
4979                         doc_height = height_2;
4980         }
4981         compute_border (view, width, height, &border);
4982
4983         doc_width = doc_width * 2;
4984         width -= ((border.left + border.right)* 2 + 3 * view->spacing);
4985         height -= (border.top + border.bottom + 2 * view->spacing);
4986
4987         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
4988                 gint sb_size;
4989
4990                 sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
4991                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
4992         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
4993                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
4994         else
4995                 g_assert_not_reached ();
4996
4997         ev_document_model_set_scale (view->model, scale);
4998 }
4999
5000 static void
5001 ev_view_zoom_for_size_single_page (EvView *view,
5002                                    int     width,
5003                                    int     height)
5004 {
5005         gdouble doc_width, doc_height;
5006         GtkBorder border;
5007         gdouble scale;
5008
5009         get_doc_page_size (view, view->current_page, &doc_width, &doc_height);
5010
5011         /* Get an approximate border */
5012         compute_border (view, width, height, &border);
5013
5014         width -= (border.left + border.right + 2 * view->spacing);
5015         height -= (border.top + border.bottom + 2 * view->spacing);
5016
5017         if (view->sizing_mode == EV_SIZING_FIT_WIDTH) {
5018                 gint sb_size;
5019
5020                 sb_size = ev_view_get_scrollbar_size (view, GTK_ORIENTATION_VERTICAL);
5021                 scale = zoom_for_size_fit_width (doc_width, doc_height, width - sb_size, height);
5022         } else if (view->sizing_mode == EV_SIZING_BEST_FIT)
5023                 scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
5024         else
5025                 g_assert_not_reached ();
5026
5027         ev_document_model_set_scale (view->model, scale);
5028 }
5029
5030 static void
5031 ev_view_zoom_for_size (EvView *view,
5032                        int     width,
5033                        int     height)
5034 {
5035         g_return_if_fail (EV_IS_VIEW (view));
5036         g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
5037                           view->sizing_mode == EV_SIZING_BEST_FIT);
5038         g_return_if_fail (width >= 0);
5039         g_return_if_fail (height >= 0);
5040
5041         if (view->document == NULL)
5042                 return;
5043
5044         if (view->continuous && view->dual_page)
5045                 ev_view_zoom_for_size_continuous_and_dual_page (view, width, height);
5046         else if (view->continuous)
5047                 ev_view_zoom_for_size_continuous (view, width, height);
5048         else if (view->dual_page)
5049                 ev_view_zoom_for_size_dual_page (view, width, height);
5050         else
5051                 ev_view_zoom_for_size_single_page (view, width, height);
5052 }
5053
5054 /*** Find ***/
5055 static gint
5056 ev_view_find_get_n_results (EvView *view, gint page)
5057 {
5058         return view->find_pages ? g_list_length (view->find_pages[page]) : 0;
5059 }
5060
5061 static EvRectangle *
5062 ev_view_find_get_result (EvView *view, gint page, gint result)
5063 {
5064         return view->find_pages ? (EvRectangle *) g_list_nth_data (view->find_pages[page], result) : NULL;
5065 }
5066
5067 static void
5068 jump_to_find_result (EvView *view)
5069 {
5070         gint n_results;
5071         gint page = view->current_page;
5072
5073         n_results = ev_view_find_get_n_results (view, page);
5074
5075         if (n_results > 0 && view->find_result < n_results) {
5076                 EvRectangle *rect;
5077                 GdkRectangle view_rect;
5078
5079                 rect = ev_view_find_get_result (view, page, view->find_result);
5080                 doc_rect_to_view_rect (view, page, rect, &view_rect);
5081                 ensure_rectangle_is_visible (view, &view_rect);
5082                 view->jump_to_find_result = FALSE;
5083         }
5084 }
5085
5086 /**
5087  * jump_to_find_page
5088  * @view: #EvView instance
5089  * @direction: Direction to look
5090  * @shift: Shift from current page
5091  *
5092  * Jumps to the first page that has occurences of searched word.
5093  * Uses a direction where to look and a shift from current page. 
5094  *
5095  */
5096 static void
5097 jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
5098 {
5099         int n_pages, i;
5100
5101         n_pages = ev_document_get_n_pages (view->document);
5102
5103         for (i = 0; i < n_pages; i++) {
5104                 int page;
5105                 
5106                 if (direction == EV_VIEW_FIND_NEXT)
5107                         page = view->current_page + i;
5108                 else
5109                         page = view->current_page - i;          
5110                 page += shift;
5111                 
5112                 if (page >= n_pages) {
5113                         page = page - n_pages;
5114                 } else if (page < 0) 
5115                         page = page + n_pages;
5116
5117                 if (ev_view_find_get_n_results (view, page) > 0) {
5118                         ev_document_model_set_page (view->model, page);
5119                         break;
5120                 }
5121         }
5122 }
5123
5124 void
5125 ev_view_find_changed (EvView *view, GList **results, gint page)
5126 {
5127         view->find_pages = results;
5128         
5129         if (view->jump_to_find_result == TRUE) {
5130                 jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
5131                 jump_to_find_result (view);
5132         }
5133
5134         if (view->current_page == page)
5135                 gtk_widget_queue_draw (GTK_WIDGET (view));
5136 }
5137
5138 void
5139 ev_view_find_next (EvView *view)
5140 {
5141         gint n_results;
5142
5143         n_results = ev_view_find_get_n_results (view, view->current_page);
5144         view->find_result++;
5145
5146         if (view->find_result >= n_results) {
5147                 view->find_result = 0;
5148                 jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1);
5149                 jump_to_find_result (view);
5150         } else {
5151                 jump_to_find_result (view);
5152                 gtk_widget_queue_draw (GTK_WIDGET (view));
5153         }
5154 }
5155
5156 void
5157 ev_view_find_previous (EvView *view)
5158 {
5159         view->find_result--;
5160
5161         if (view->find_result < 0) {
5162                 jump_to_find_page (view, EV_VIEW_FIND_PREV, -1);
5163                 view->find_result = MAX (0, ev_view_find_get_n_results (view, view->current_page) - 1);
5164                 jump_to_find_result (view);
5165         } else {
5166                 jump_to_find_result (view);
5167                 gtk_widget_queue_draw (GTK_WIDGET (view));
5168         }
5169 }
5170
5171 void
5172 ev_view_find_search_changed (EvView *view)
5173 {
5174         /* search string has changed, focus on new search result */
5175         view->jump_to_find_result = TRUE;
5176         view->find_pages = NULL;
5177 }
5178
5179 void
5180 ev_view_find_set_highlight_search (EvView *view, gboolean value)
5181 {
5182         view->highlight_find_results = value;
5183         gtk_widget_queue_draw (GTK_WIDGET (view));
5184 }
5185
5186 void
5187 ev_view_find_cancel (EvView *view)
5188 {
5189         view->find_pages = NULL;
5190 }
5191
5192 /*** Selections ***/
5193
5194 /* compute_new_selection_rect/text calculates the area currently selected by
5195  * view_rect.  each handles a different mode;
5196  */
5197 static GList *
5198 compute_new_selection_rect (EvView       *view,
5199                             GdkPoint     *start,
5200                             GdkPoint     *stop)
5201 {
5202         GdkRectangle view_rect;
5203         int n_pages, i;
5204         GList *list = NULL;
5205
5206         g_assert (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE);
5207         
5208         view_rect.x = MIN (start->x, stop->x);
5209         view_rect.y = MIN (start->y, stop->y);
5210         view_rect.width = MAX (start->x, stop->x) - view_rect.x;
5211         view_rect.width = MAX (start->y, stop->y) - view_rect.y;
5212
5213         n_pages = ev_document_get_n_pages (view->document);
5214
5215         for (i = 0; i < n_pages; i++) {
5216                 GdkRectangle page_area;
5217                 GtkBorder border;
5218                 
5219                 if (get_page_extents (view, i, &page_area, &border)) {
5220                         GdkRectangle overlap;
5221
5222                         if (gdk_rectangle_intersect (&page_area, &view_rect, &overlap)) {
5223                                 EvViewSelection *selection;
5224
5225                                 selection = g_new0 (EvViewSelection, 1);
5226                                 selection->page = i;
5227                                 view_rect_to_doc_rect (view, &overlap, &page_area,
5228                                                        &(selection->rect));
5229
5230                                 list = g_list_append (list, selection);
5231                         }
5232                 }
5233         }
5234
5235         return list;
5236 }
5237
5238 static gboolean
5239 gdk_rectangle_point_in (GdkRectangle *rectangle,
5240                         GdkPoint     *point)
5241 {
5242         return rectangle->x <= point->x &&
5243                 rectangle->y <= point->y &&
5244                 point->x < rectangle->x + rectangle->width &&
5245                 point->y < rectangle->y + rectangle->height;
5246 }
5247
5248 static GList *
5249 compute_new_selection_text (EvView          *view,
5250                             EvSelectionStyle style,
5251                             GdkPoint        *start,
5252                             GdkPoint        *stop)
5253 {
5254         int n_pages, i, first, last;
5255         GList *list = NULL;
5256         EvViewSelection *selection;
5257         gdouble width, height;
5258         int start_page, end_page;
5259
5260         g_assert (view->selection_mode == EV_VIEW_SELECTION_TEXT);
5261
5262         n_pages = ev_document_get_n_pages (view->document);
5263
5264         /* First figure out the range of pages the selection
5265          * affects. */
5266         first = n_pages;
5267         last = 0;
5268         if (view->continuous) {
5269                 start_page = 0;
5270                 end_page = n_pages;
5271         } else if (view->dual_page) {
5272                 start_page = view->start_page;
5273                 end_page = view->end_page + 1;
5274         } else {
5275                 start_page = view->current_page;
5276                 end_page = view->current_page + 1;
5277         }
5278
5279         for (i = start_page; i < end_page; i++) {
5280                 GdkRectangle page_area;
5281                 GtkBorder border;
5282                 
5283                 get_page_extents (view, i, &page_area, &border);
5284                 if (gdk_rectangle_point_in (&page_area, start) || 
5285                     gdk_rectangle_point_in (&page_area, stop)) {
5286                         if (first == n_pages)
5287                                 first = i;
5288                         last = i;
5289                 }
5290
5291         }
5292
5293         /* Now create a list of EvViewSelection's for the affected
5294          * pages.  This could be an empty list, a list of just one
5295          * page or a number of pages.*/
5296         for (i = first; i < last + 1; i++) {
5297                 GdkRectangle page_area;
5298                 GtkBorder border;
5299                 GdkPoint *point;
5300
5301                 get_doc_page_size (view, i, &width, &height);
5302
5303                 selection = g_new0 (EvViewSelection, 1);
5304                 selection->page = i;
5305                 selection->style = style;
5306                 selection->rect.x1 = selection->rect.y1 = 0;
5307                 selection->rect.x2 = width;
5308                 selection->rect.y2 = height;
5309
5310                 get_page_extents (view, i, &page_area, &border);
5311
5312                 if (gdk_rectangle_point_in (&page_area, start))
5313                         point = start;
5314                 else
5315                         point = stop;
5316
5317                 if (i == first)
5318                         view_point_to_doc_point (view, point, &page_area,
5319                                                  &selection->rect.x1,
5320                                                  &selection->rect.y1);
5321
5322                 /* If the selection is contained within just one page,
5323                  * make sure we don't write 'start' into both points
5324                  * in selection->rect. */
5325                 if (first == last)
5326                         point = stop;
5327
5328                 if (i == last)
5329                         view_point_to_doc_point (view, point, &page_area,
5330                                                  &selection->rect.x2,
5331                                                  &selection->rect.y2);
5332
5333                 list = g_list_append (list, selection);
5334         }
5335
5336         return list;
5337 }
5338
5339 /* This function takes the newly calculated list, and figures out which regions
5340  * have changed.  It then queues a redraw approporiately.
5341  */
5342 static void
5343 merge_selection_region (EvView *view,
5344                         GList  *new_list)
5345 {
5346         GList *old_list;
5347         GList *new_list_ptr, *old_list_ptr;
5348
5349         /* Update the selection */
5350         old_list = ev_pixbuf_cache_get_selection_list (view->pixbuf_cache);
5351         g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
5352         g_list_free (view->selection_info.selections);
5353         view->selection_info.selections = new_list;
5354         ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, new_list);
5355         g_signal_emit (view, signals[SIGNAL_SELECTION_CHANGED], 0, NULL);
5356
5357         new_list_ptr = new_list;
5358         old_list_ptr = old_list;
5359
5360         while (new_list_ptr || old_list_ptr) {
5361                 EvViewSelection *old_sel, *new_sel;
5362                 int cur_page;
5363                 GdkRegion *region = NULL;
5364
5365                 new_sel = (new_list_ptr) ? (new_list_ptr->data) : NULL;
5366                 old_sel = (old_list_ptr) ? (old_list_ptr->data) : NULL;
5367
5368                 /* Assume that the lists are in order, and we run through them
5369                  * comparing them, one page at a time.  We come out with the
5370                  * first page we see. */
5371                 if (new_sel && old_sel) {
5372                         if (new_sel->page < old_sel->page) {
5373                                 new_list_ptr = new_list_ptr->next;
5374                                 old_sel = NULL;
5375                         } else if (new_sel->page > old_sel->page) {
5376                                 old_list_ptr = old_list_ptr->next;
5377                                 new_sel = NULL;
5378                         } else {
5379                                 new_list_ptr = new_list_ptr->next;
5380                                 old_list_ptr = old_list_ptr->next;
5381                         }
5382                 } else if (new_sel) {
5383                         new_list_ptr = new_list_ptr->next;
5384                 } else if (old_sel) {
5385                         old_list_ptr = old_list_ptr->next;
5386                 }
5387
5388                 g_assert (new_sel || old_sel);
5389
5390                 /* is the page we're looking at on the screen?*/
5391                 cur_page = new_sel ? new_sel->page : old_sel->page;
5392                 if (cur_page < view->start_page || cur_page > view->end_page)
5393                         continue;
5394
5395                 /* seed the cache with a new page.  We are going to need the new
5396                  * region too. */
5397                 if (new_sel) {
5398                         GdkRegion *tmp_region = NULL;
5399
5400                         ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
5401                                                                cur_page,
5402                                                                view->scale,
5403                                                                &tmp_region);
5404
5405                         if (tmp_region && !gdk_region_empty (tmp_region)) {
5406                                 new_sel->covered_region = gdk_region_copy (tmp_region);
5407                         }
5408                 }
5409
5410                 /* Now we figure out what needs redrawing */
5411                 if (old_sel && new_sel) {
5412                         if (old_sel->covered_region && new_sel->covered_region) {
5413                                 /* We only want to redraw the areas that have
5414                                  * changed, so we xor the old and new regions
5415                                  * and redraw if it's different */
5416                                 region = gdk_region_copy (old_sel->covered_region);
5417                                 gdk_region_xor (region, new_sel->covered_region);
5418                                 if (gdk_region_empty (region)) {
5419                                         gdk_region_destroy (region);
5420                                         region = NULL;
5421                                 }
5422                         } else if (old_sel->covered_region) {
5423                                 region = gdk_region_copy (old_sel->covered_region);
5424                         } else if (new_sel->covered_region) {
5425                                 region = gdk_region_copy (new_sel->covered_region);
5426                         }
5427                 } else if (old_sel && !new_sel) {
5428                         if (old_sel->covered_region && !gdk_region_empty (old_sel->covered_region)) {
5429                                 region = gdk_region_copy (old_sel->covered_region);
5430                         }
5431                 } else if (!old_sel && new_sel) {
5432                         if (new_sel->covered_region && !gdk_region_empty (new_sel->covered_region)) {
5433                                 region = gdk_region_copy (new_sel->covered_region);
5434                         }
5435                 } else {
5436                         g_assert_not_reached ();
5437                 }
5438
5439                 /* Redraw the damaged region! */
5440                 if (region) {
5441                         GdkRectangle page_area;
5442                         GtkBorder border;
5443
5444                         /* I don't know why but the region is smaller
5445                          * than expected. This hack fixes it, I guess
5446                          * 10 pixels more won't hurt
5447                          */
5448                         gdk_region_shrink (region, -5, -5);
5449
5450                         get_page_extents (view, cur_page, &page_area, &border);
5451                         gdk_region_offset (region,
5452                                            page_area.x + border.left - view->scroll_x,
5453                                            page_area.y + border.top - view->scroll_y);
5454                         gdk_window_invalidate_region (view->layout.bin_window, region, TRUE);
5455                         gdk_region_destroy (region);
5456                 }
5457         }
5458
5459         /* Free the old list, now that we're done with it. */
5460         g_list_foreach (old_list, (GFunc) selection_free, NULL);
5461         g_list_free (old_list);
5462 }
5463
5464 static void
5465 compute_selections (EvView          *view,
5466                     EvSelectionStyle style,
5467                     GdkPoint        *start,
5468                     GdkPoint        *stop)
5469 {
5470         GList *list;
5471
5472         if (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE)
5473                 list = compute_new_selection_rect (view, start, stop);
5474         else
5475                 list = compute_new_selection_text (view, style, start, stop);
5476         merge_selection_region (view, list);
5477 }
5478
5479 /* Free's the selection.  It's up to the caller to queue redraws if needed.
5480  */
5481 static void
5482 selection_free (EvViewSelection *selection)
5483 {
5484         if (selection->covered_region)
5485                 gdk_region_destroy (selection->covered_region);
5486         g_free (selection);
5487 }
5488
5489 static void
5490 clear_selection (EvView *view)
5491 {
5492         if (view->selection_info.selections) {
5493                 g_list_foreach (view->selection_info.selections, (GFunc)selection_free, NULL);
5494                 g_list_free (view->selection_info.selections);
5495                 view->selection_info.selections = NULL;
5496
5497                 g_signal_emit (view, signals[SIGNAL_SELECTION_CHANGED], 0, NULL);
5498         }
5499         view->selection_info.in_selection = FALSE;
5500         if (view->pixbuf_cache)
5501                 ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, NULL);
5502 }
5503
5504 void
5505 ev_view_select_all (EvView *view)
5506 {
5507         GList *selections = NULL;
5508         int n_pages, i;
5509
5510         /* Disable selection on rotated pages for the 0.4.0 series */
5511         if (view->rotation != 0)
5512                 return;
5513
5514         clear_selection (view);
5515         
5516         n_pages = ev_document_get_n_pages (view->document);
5517         for (i = 0; i < n_pages; i++) {
5518                 gdouble width, height;
5519                 EvViewSelection *selection;
5520
5521                 get_doc_page_size (view, i, &width, &height);
5522
5523                 selection = g_new0 (EvViewSelection, 1);
5524                 selection->page = i;
5525                 selection->style = EV_SELECTION_STYLE_GLYPH;
5526                 selection->rect.x1 = selection->rect.y1 = 0;
5527                 selection->rect.x2 = width;
5528                 selection->rect.y2 = height;
5529
5530                 selections = g_list_append (selections, selection);
5531         }
5532
5533         merge_selection_region (view, selections);
5534         gtk_widget_queue_draw (GTK_WIDGET (view));
5535 }
5536
5537 gboolean
5538 ev_view_get_has_selection (EvView *view)
5539 {
5540         return view->selection_info.selections != NULL;
5541 }
5542
5543 static char *
5544 get_selected_text (EvView *view)
5545 {
5546         GString *text;
5547         GList *l;
5548         gchar *normalized_text;
5549
5550         text = g_string_new (NULL);
5551
5552         ev_document_doc_mutex_lock ();
5553
5554         for (l = view->selection_info.selections; l != NULL; l = l->next) {
5555                 EvViewSelection *selection = (EvViewSelection *)l->data;
5556                 EvPage *page;
5557                 gchar *tmp;
5558
5559                 page = ev_document_get_page (view->document, selection->page);
5560                 tmp = ev_selection_get_selected_text (EV_SELECTION (view->document),
5561                                                       page, selection->style,
5562                                                       &(selection->rect));
5563                 g_object_unref (page);
5564                 g_string_append (text, tmp);
5565                 g_free (tmp);
5566         }
5567
5568         ev_document_doc_mutex_unlock ();
5569         
5570         normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC);
5571         g_string_free (text, TRUE);
5572         return normalized_text;
5573 }
5574
5575 static void
5576 ev_view_clipboard_copy (EvView      *view,
5577                         const gchar *text)
5578 {
5579         GtkClipboard *clipboard;
5580
5581         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (view),
5582                                               GDK_SELECTION_CLIPBOARD);
5583         gtk_clipboard_set_text (clipboard, text, -1);
5584 }
5585
5586 void
5587 ev_view_copy (EvView *ev_view)
5588 {
5589         char *text;
5590
5591         if (!EV_IS_SELECTION (ev_view->document))
5592                 return;
5593
5594         text = get_selected_text (ev_view);
5595         ev_view_clipboard_copy (ev_view, text);
5596         g_free (text);
5597 }
5598
5599 static void
5600 ev_view_primary_get_cb (GtkClipboard     *clipboard,
5601                         GtkSelectionData *selection_data,
5602                         guint             info,
5603                         gpointer          data)
5604 {
5605         EvView *ev_view = EV_VIEW (data);
5606
5607         if (ev_view->link_selected) {
5608                 gtk_selection_data_set_text (selection_data,
5609                                              ev_link_action_get_uri (ev_view->link_selected),
5610                                              -1);
5611         } else if (EV_IS_SELECTION (ev_view->document) &&
5612                    ev_view->selection_info.selections) {
5613                 gchar *text;
5614                 
5615                 text = get_selected_text (ev_view);
5616                 if (text) {
5617                         gtk_selection_data_set_text (selection_data, text, -1);
5618                         g_free (text);
5619                 }
5620         }
5621 }
5622
5623 static void
5624 ev_view_primary_clear_cb (GtkClipboard *clipboard,
5625                           gpointer      data)
5626 {
5627         EvView *view = EV_VIEW (data);
5628
5629         clear_selection (view);
5630         clear_link_selected (view);
5631 }
5632
5633 static void
5634 ev_view_update_primary_selection (EvView *ev_view)
5635 {
5636         GtkClipboard *clipboard;
5637
5638         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
5639                                               GDK_SELECTION_PRIMARY);
5640
5641         if (ev_view->selection_info.selections || ev_view->link_selected) {
5642                 GtkTargetList *target_list;
5643                 GtkTargetEntry *targets;
5644                 int n_targets;
5645
5646                 target_list = gtk_target_list_new (NULL, 0);
5647                 gtk_target_list_add_text_targets (target_list, 0);
5648                 targets = gtk_target_table_new_from_list (target_list, &n_targets);
5649                 gtk_target_list_unref (target_list);
5650                 
5651                 if (!gtk_clipboard_set_with_owner (clipboard,
5652                                                    targets, n_targets,
5653                                                    ev_view_primary_get_cb,
5654                                                    ev_view_primary_clear_cb,
5655                                                    G_OBJECT (ev_view)))
5656                         ev_view_primary_clear_cb (clipboard, ev_view);
5657
5658                 gtk_target_table_free (targets, n_targets);
5659         } else {
5660                 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (ev_view))
5661                         gtk_clipboard_clear (clipboard);
5662         }
5663 }
5664
5665 static void
5666 clear_link_selected (EvView *view)
5667 {
5668         if (view->link_selected) {
5669                 g_object_unref (view->link_selected);
5670                 view->link_selected = NULL;
5671         }
5672 }
5673
5674 void
5675 ev_view_copy_link_address (EvView       *view,
5676                            EvLinkAction *action)
5677 {
5678         clear_link_selected (view);
5679         
5680         ev_view_clipboard_copy (view, ev_link_action_get_uri (action));
5681         
5682         view->link_selected = g_object_ref (action);
5683         ev_view_update_primary_selection (view);
5684 }
5685
5686 /*** Cursor operations ***/
5687 static void
5688 ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
5689 {
5690         GdkCursor *cursor = NULL;
5691         GtkWidget *widget;
5692
5693         if (view->cursor == new_cursor) {
5694                 return;
5695         }
5696
5697         view->cursor = new_cursor;
5698
5699         widget = gtk_widget_get_toplevel (GTK_WIDGET (view));
5700         cursor = ev_view_cursor_new (gtk_widget_get_display (widget), new_cursor);
5701         gdk_window_set_cursor (view->layout.bin_window, cursor);
5702         gdk_flush ();
5703         if (cursor)
5704                 gdk_cursor_unref (cursor);
5705 }
5706
5707 void
5708 ev_view_hide_cursor (EvView *view)
5709 {
5710        ev_view_set_cursor (view, EV_VIEW_CURSOR_HIDDEN);
5711 }
5712
5713 void
5714 ev_view_show_cursor (EvView *view)
5715 {
5716        ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
5717 }
5718
5719 gboolean
5720 ev_view_next_page (EvView *view)
5721 {
5722         int page, n_pages;
5723
5724         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
5725         
5726         if (!view->document)
5727                 return FALSE;
5728
5729         page = ev_document_model_get_page (view->model);
5730         n_pages = ev_document_get_n_pages (view->document);
5731
5732         if (view->dual_page)
5733                 page = page + 2; 
5734         else 
5735                 page = page + 1;
5736
5737         if (page < n_pages) {
5738                 ev_document_model_set_page (view->model, page);
5739                 return TRUE;
5740         } else if (view->dual_page && page == n_pages) {
5741                 ev_document_model_set_page (view->model, page - 1);
5742                 return TRUE;
5743         } else {
5744                 return FALSE;
5745         }
5746 }
5747
5748 gboolean
5749 ev_view_previous_page (EvView *view)
5750 {
5751         int page;
5752
5753         g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
5754
5755         if (!view->document)
5756                 return FALSE;
5757
5758         page = ev_document_model_get_page (view->model);
5759
5760         if (view->dual_page)
5761                 page = page - 2; 
5762         else 
5763                 page = page - 1;
5764
5765         if (page >= 0) {
5766                 ev_document_model_set_page (view->model, page);
5767                 return TRUE;
5768         } else if (view->dual_page && page == -1) {
5769                 ev_document_model_set_page (view->model, 0);
5770                 return TRUE;
5771         } else {        
5772                 return FALSE;
5773         }
5774 }
5775