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