]> www.fi.muni.cz Git - evince.git/blob - shell/ev-view.c
610c880c421edde61d9af32650cc0cc55a08ecc4
[evince.git] / shell / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include <gtk/gtkalignment.h>
22 #include <glib/gi18n.h>
23 #include <gtk/gtkbindings.h>
24 #include <gtk/gtkselection.h>
25 #include <gtk/gtkclipboard.h>
26 #include <gdk/gdkkeysyms.h>
27 #include <libgnomevfs/gnome-vfs-utils.h>
28
29 #include "ev-marshal.h"
30 #include "ev-view.h"
31 #include "ev-document-find.h"
32 #include "ev-document-misc.h"
33 #include "ev-debug.h"
34
35 #define EV_VIEW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
36 #define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW))
37 #define EV_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_VIEW, EvViewClass))
38
39 enum {
40         PROP_0,
41         PROP_STATUS,
42         PROP_FIND_STATUS
43 };
44
45 enum {
46   TARGET_STRING,
47   TARGET_TEXT,
48   TARGET_COMPOUND_TEXT,
49   TARGET_UTF8_STRING,
50   TARGET_TEXT_BUFFER_CONTENTS
51 };
52
53 static const GtkTargetEntry targets[] = {
54         { "STRING", 0, TARGET_STRING },
55         { "TEXT",   0, TARGET_TEXT },
56         { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
57         { "UTF8_STRING", 0, TARGET_UTF8_STRING },
58 };
59
60 typedef enum {
61         EV_VIEW_CURSOR_NORMAL,
62         EV_VIEW_CURSOR_LINK,
63         EV_VIEW_CURSOR_WAIT,
64         EV_VIEW_CURSOR_HIDDEN
65 } EvViewCursor;
66
67 #define ZOOM_IN_FACTOR  1.2
68 #define ZOOM_OUT_FACTOR (1.0/ZOOM_IN_FACTOR)
69
70 #define MIN_SCALE 0.05409
71 #define MAX_SCALE 18.4884
72
73 struct _EvView {
74         GtkWidget parent_instance;
75
76         EvDocument *document;
77         
78         GdkWindow *bin_window;
79
80         char *status;
81         char *find_status;
82         
83         int scroll_x;
84         int scroll_y;
85
86         int x_offset;
87         int y_offset;
88
89         gboolean pressed_button;
90         gboolean has_selection;
91         GdkPoint selection_start;
92         GdkRectangle selection;
93         EvViewCursor cursor;
94
95         GtkAdjustment *hadjustment;
96         GtkAdjustment *vadjustment;
97
98         int find_page;
99         int find_result;
100         int spacing;
101
102         double scale;
103         int width;
104         int height;
105 };
106
107 struct _EvViewClass {
108         GtkWidgetClass parent_class;
109
110         void    (*set_scroll_adjustments) (EvView         *view,
111                                            GtkAdjustment  *hadjustment,
112                                            GtkAdjustment  *vadjustment);
113         void    (*scroll_view)            (EvView         *view,
114                                            GtkScrollType   scroll,
115                                            gboolean        horizontal);
116         
117         /* Should this be notify::page? */
118         void    (*page_changed)           (EvView         *view);
119 };
120
121 static guint page_changed_signal = 0;
122
123 static void ev_view_set_scroll_adjustments (EvView         *view,
124                                             GtkAdjustment  *hadjustment,
125                                             GtkAdjustment  *vadjustment);
126     
127 G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_WIDGET)
128
129 /*** Helper functions ***/       
130      
131 static void
132 view_update_adjustments (EvView *view)
133 {
134         int old_x = view->scroll_x;
135         int old_y = view->scroll_y;
136   
137         if (view->hadjustment)
138                 view->scroll_x = view->hadjustment->value;
139         else
140                 view->scroll_x = 0;
141
142         if (view->vadjustment)
143                 view->scroll_y = view->vadjustment->value;
144         else
145                 view->scroll_y = 0;
146   
147         if (GTK_WIDGET_REALIZED (view) &&
148             (view->scroll_x != old_x || view->scroll_y != old_y)) {
149                 gdk_window_move (view->bin_window, - view->scroll_x, - view->scroll_y);
150                 gdk_window_process_updates (view->bin_window, TRUE);
151         }
152 }
153
154 static void
155 view_set_adjustment_values (EvView         *view,
156                             GtkOrientation  orientation)
157 {
158         GtkWidget *widget = GTK_WIDGET (view);
159         GtkAdjustment *adjustment;
160         gboolean value_changed = FALSE;
161         int requisition;
162         int allocation;
163
164         if (orientation == GTK_ORIENTATION_HORIZONTAL)  {
165                 requisition = widget->requisition.width;
166                 allocation = widget->allocation.width;
167                 adjustment = view->hadjustment;
168         } else {
169                 requisition = widget->requisition.height;
170                 allocation = widget->allocation.height;
171                 adjustment = view->vadjustment;
172         }
173
174         if (!adjustment)
175                 return;
176   
177         adjustment->page_size = allocation;
178         adjustment->step_increment = allocation * 0.1;
179         adjustment->page_increment = allocation * 0.9;
180         adjustment->lower = 0;
181         adjustment->upper = MAX (allocation, requisition);
182
183         if (adjustment->value > adjustment->upper - adjustment->page_size) {
184                 adjustment->value = adjustment->upper - adjustment->page_size;
185                 value_changed = TRUE;
186         }
187
188         gtk_adjustment_changed (adjustment);
189         if (value_changed)
190                 gtk_adjustment_value_changed (adjustment);
191 }
192
193 /*** Virtual function implementations ***/       
194      
195 static void
196 ev_view_finalize (GObject *object)
197 {
198         EvView *view = EV_VIEW (object);
199
200         LOG ("Finalize");
201
202         if (view->document)
203                 g_object_unref (view->document);
204
205         ev_view_set_scroll_adjustments (view, NULL, NULL);
206
207         G_OBJECT_CLASS (ev_view_parent_class)->finalize (object);
208 }
209
210 static void
211 ev_view_destroy (GtkObject *object)
212 {
213         EvView *view = EV_VIEW (object);
214
215         ev_view_set_scroll_adjustments (view, NULL, NULL);
216   
217         GTK_OBJECT_CLASS (ev_view_parent_class)->destroy (object);
218 }
219
220 static void
221 view_rect_to_doc_rect (EvView *view, GdkRectangle *view_rect, GdkRectangle *doc_rect)
222 {
223         doc_rect->x = (view_rect->x - view->x_offset) / view->scale;
224         doc_rect->y = (view_rect->y - view->y_offset) / view->scale;
225         doc_rect->width = view_rect->width / view->scale;
226         doc_rect->height = view_rect->height / view->scale;
227 }
228
229 static void
230 doc_rect_to_view_rect (EvView *view, GdkRectangle *doc_rect, GdkRectangle *view_rect)
231 {
232         view_rect->x = doc_rect->x * view->scale + view->x_offset;
233         view_rect->y = doc_rect->y * view->scale + view->y_offset;
234         view_rect->width = doc_rect->width * view->scale;
235         view_rect->height = doc_rect->height * view->scale;
236 }
237
238 static void
239 ev_view_size_request (GtkWidget      *widget,
240                       GtkRequisition *requisition)
241 {
242         EvView *view = EV_VIEW (widget);
243         GtkBorder border;
244         gint width, height;
245
246         if (!GTK_WIDGET_REALIZED (widget))
247                 return;
248
249         if (!view->document) {
250                 requisition->width = 1;
251                 requisition->height = 1;
252                 return;
253         }
254
255         ev_document_get_page_size (view->document, -1,
256                                    &width, &height);
257         ev_document_misc_get_page_border_size (width, height, &border);
258
259         if (view->width >= 0) {
260                 requisition->width = 0;
261         } else {
262                 requisition->width = width + border.left + border.right +
263                                      view->spacing * 2;
264         }
265         
266         if (view->height >= 0) {
267                 requisition->height = 0;
268         } else {
269                 requisition->height = height + border.top + border.bottom +
270                                       view->spacing * 2;
271         }
272 }
273
274 static void
275 ev_view_size_allocate (GtkWidget      *widget,
276                        GtkAllocation  *allocation)
277 {
278         EvView *view = EV_VIEW (widget);
279         gint target_width, target_height;       
280         GtkBorder border;
281         gint width, height;
282
283         if (view->document) {
284                 ev_document_get_page_size (view->document, -1,
285                                            &width, &height);
286                 ev_document_misc_get_page_border_size (width, height, &border);
287                 view->x_offset = view->spacing;
288                 view->y_offset = view->spacing;
289                 target_width = width + border.left + border.right + view->spacing * 2;
290                 target_height = height + border.top + border.bottom + view->spacing * 2;
291                 view->x_offset += MAX (0, (widget->allocation.width - target_width) / 2);
292                 view->y_offset += MAX (0, (widget->allocation.height - target_height) / 2);
293         }
294
295         GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
296
297         view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
298         view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
299
300         if (GTK_WIDGET_REALIZED (widget)) {
301                 gdk_window_resize (view->bin_window,
302                                    MAX (widget->allocation.width, widget->requisition.width),
303                                    MAX (widget->allocation.height, widget->requisition.height));
304         }
305 }
306
307 static void
308 ev_view_realize (GtkWidget *widget)
309 {
310         EvView *view = EV_VIEW (widget);
311         GdkWindowAttr attributes;
312
313         GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
314   
315
316         attributes.window_type = GDK_WINDOW_CHILD;
317         attributes.wclass = GDK_INPUT_OUTPUT;
318         attributes.visual = gtk_widget_get_visual (widget);
319         attributes.colormap = gtk_widget_get_colormap (widget);
320   
321         attributes.x = widget->allocation.x;
322         attributes.y = widget->allocation.y;
323         attributes.width = widget->allocation.width;
324         attributes.height = widget->allocation.height;
325         attributes.event_mask = 0;
326   
327         widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
328                                          &attributes,
329                                          GDK_WA_X | GDK_WA_Y |
330                                          GDK_WA_COLORMAP |
331                                          GDK_WA_VISUAL);
332         gdk_window_set_user_data (widget->window, widget);
333         widget->style = gtk_style_attach (widget->style, widget->window);
334         gdk_window_set_background (widget->window, &widget->style->mid[widget->state]);
335   
336         attributes.x = 0;
337         attributes.y = 0;
338         attributes.width = MAX (widget->allocation.width, widget->requisition.width);
339         attributes.height = MAX (widget->allocation.height, widget->requisition.height);
340         attributes.event_mask = GDK_EXPOSURE_MASK |
341                                 GDK_BUTTON_PRESS_MASK |
342                                 GDK_BUTTON_RELEASE_MASK |
343                                 GDK_SCROLL_MASK |
344                                 GDK_KEY_PRESS_MASK |
345                                 GDK_POINTER_MOTION_MASK |
346                                 GDK_LEAVE_NOTIFY_MASK;
347   
348         view->bin_window = gdk_window_new (widget->window,
349                                            &attributes,
350                                            GDK_WA_X | GDK_WA_Y |
351                                            GDK_WA_COLORMAP |
352                                            GDK_WA_VISUAL);
353         gdk_window_set_user_data (view->bin_window, widget);
354         gdk_window_show (view->bin_window);
355
356         widget->style = gtk_style_attach (widget->style, view->bin_window);
357         gdk_window_set_background (view->bin_window, &widget->style->mid[widget->state]);
358
359         if (view->document) {
360                 ev_document_set_target (view->document, view->bin_window);
361
362                 /* We can't get page size without a target, so we have to
363                  * queue a size request at realization. Could be fixed
364                  * with EvDocument changes to allow setting a GdkScreen
365                  * without setting a target.
366                  */
367                 gtk_widget_queue_resize (widget);
368         }
369 }
370
371 static void
372 ev_view_unrealize (GtkWidget *widget)
373 {
374         EvView *view = EV_VIEW (widget);
375
376         if (view->document)
377                 ev_document_set_target (view->document, NULL);
378
379         gdk_window_set_user_data (view->bin_window, NULL);
380         gdk_window_destroy (view->bin_window);
381         view->bin_window = NULL;
382
383         GTK_WIDGET_CLASS (ev_view_parent_class)->unrealize (widget);
384 }
385
386 static guint32
387 ev_gdk_color_to_rgb (const GdkColor *color)
388 {
389   guint32 result;
390   result = (0xff0000 | (color->red & 0xff00));
391   result <<= 8;
392   result |= ((color->green & 0xff00) | (color->blue >> 8));
393   return result;
394 }
395
396 static void
397 draw_rubberband (GtkWidget *widget, GdkWindow *window,
398                  const GdkRectangle *rect, guchar alpha)
399 {
400         GdkGC *gc;
401         GdkPixbuf *pixbuf;
402         GdkColor *fill_color_gdk;
403         guint fill_color;
404
405         fill_color_gdk = gdk_color_copy (&GTK_WIDGET (widget)->style->base[GTK_STATE_SELECTED]);
406         fill_color = ev_gdk_color_to_rgb (fill_color_gdk) << 8 | alpha;
407
408         pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
409                                  rect->width, rect->height);
410         gdk_pixbuf_fill (pixbuf, fill_color);
411
412         gdk_draw_pixbuf (window, NULL, pixbuf,
413                          0, 0,
414                          rect->x,rect->y,
415                          rect->width, rect->height,
416                          GDK_RGB_DITHER_NONE,
417                          0, 0);
418
419         g_object_unref (pixbuf);
420
421         gc = gdk_gc_new (window);
422         gdk_gc_set_rgb_fg_color (gc, fill_color_gdk);
423         gdk_draw_rectangle (window, gc, FALSE,
424                             rect->x, rect->y,
425                             rect->width - 1,
426                             rect->height - 1);
427         g_object_unref (gc);
428
429         gdk_color_free (fill_color_gdk);
430 }
431
432 static void
433 highlight_find_results (EvView *view)
434 {
435         EvDocumentFind *find;
436         int i, results;
437
438         g_return_if_fail (EV_IS_DOCUMENT_FIND (view->document));
439
440         find = EV_DOCUMENT_FIND (view->document);
441
442         results = ev_document_find_get_n_results (find);
443
444         for (i = 0; i < results; i++) {
445                 GdkRectangle rectangle;
446                 guchar alpha;
447
448                 alpha = (i == view->find_result) ? 0x90 : 0x20;
449                 ev_document_find_get_result (find, i, &rectangle);
450                 draw_rubberband (GTK_WIDGET (view), view->bin_window,
451                                  &rectangle, alpha);
452         }
453 }
454
455
456 static void
457 expose_bin_window (GtkWidget      *widget,
458                    GdkEventExpose *event)
459 {
460         EvView *view = EV_VIEW (widget);
461         GtkBorder border;
462         gint width, height;
463         GdkRectangle area;
464
465         if (view->document == NULL)
466                 return;
467
468         ev_document_get_page_size (view->document, -1,
469                                    &width, &height);
470         ev_document_misc_get_page_border_size (width, height, &border);
471         
472         /* Paint the frame */
473         area.x = view->x_offset;
474         area.y = view->y_offset;
475         area.width = width + border.left + border.right;
476         area.height = height + border.top + border.bottom;
477         ev_document_misc_paint_one_page (view->bin_window, widget, &area, &border);
478
479         /* Render the document itself */
480         ev_document_set_page_offset (view->document,
481                                      view->x_offset + border.left,
482                                      view->y_offset + border.top);
483
484         LOG ("Render area %d %d %d %d - Offset %d %d",
485              event->area.x, event->area.y,
486              event->area.width, event->area.height,
487              view->x_offset, view->y_offset);
488
489         ev_document_render (view->document,
490                             event->area.x, event->area.y,
491                             event->area.width, event->area.height);
492
493         if (EV_IS_DOCUMENT_FIND (view->document)) {
494                 highlight_find_results (view);
495         }
496
497         if (view->has_selection) {
498                 GdkRectangle rubberband;
499
500                 doc_rect_to_view_rect (view, &view->selection, &rubberband);
501                 if (rubberband.width > 0 && rubberband.height > 0) {
502                         draw_rubberband (widget, view->bin_window,
503                                          &rubberband, 0x40);
504                 }
505         }
506 }
507
508 static gboolean
509 ev_view_expose_event (GtkWidget      *widget,
510                       GdkEventExpose *event)
511 {
512         EvView *view = EV_VIEW (widget);
513
514         if (event->window == view->bin_window)
515                 expose_bin_window (widget, event);
516         else
517                 return GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event (widget, event);
518
519         return FALSE;
520 }
521
522 void
523 ev_view_select_all (EvView *ev_view)
524 {
525         GtkWidget *widget = GTK_WIDGET (ev_view);
526         GdkRectangle selection;
527         int width, height;
528         GtkBorder border;
529
530         g_return_if_fail (EV_IS_VIEW (ev_view));
531
532         ev_document_get_page_size (ev_view->document, -1, &width, &height);
533         ev_document_misc_get_page_border_size (width, height, &border);
534
535         ev_view->has_selection = TRUE;
536         selection.x = ev_view->x_offset + border.left;
537         selection.y = ev_view->y_offset + border.top;
538         selection.width = width;
539         selection.height = height;
540         view_rect_to_doc_rect (ev_view, &selection, &ev_view->selection);
541
542         gtk_widget_queue_draw (widget);
543 }
544
545 void
546 ev_view_copy (EvView *ev_view)
547 {
548         GtkClipboard *clipboard;
549         GdkRectangle selection;
550         char *text;
551
552         doc_rect_to_view_rect (ev_view, &ev_view->selection, &selection);
553         text = ev_document_get_text (ev_view->document, &selection);
554         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
555                                               GDK_SELECTION_CLIPBOARD);
556         gtk_clipboard_set_text (clipboard, text, -1);
557         g_free (text);
558 }
559
560 static void
561 ev_view_primary_get_cb (GtkClipboard     *clipboard,
562                         GtkSelectionData *selection_data,
563                         guint             info,
564                         gpointer          data)
565 {
566         EvView *ev_view = EV_VIEW (data);
567         GdkRectangle selection;
568         char *text;
569
570         doc_rect_to_view_rect (ev_view, &ev_view->selection, &selection);
571         text = ev_document_get_text (ev_view->document, &selection);
572         gtk_selection_data_set_text (selection_data, text, -1);
573 }
574
575 static void
576 ev_view_primary_clear_cb (GtkClipboard *clipboard,
577                           gpointer      data)
578 {
579         EvView *ev_view = EV_VIEW (data);
580
581         ev_view->has_selection = FALSE;
582 }
583
584 static void
585 ev_view_update_primary_selection (EvView *ev_view)
586 {
587         GtkClipboard *clipboard;
588
589         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
590                                               GDK_SELECTION_PRIMARY);
591
592         if (ev_view->has_selection) {
593                 if (!gtk_clipboard_set_with_owner (clipboard,
594                                                    targets,
595                                                    G_N_ELEMENTS (targets),
596                                                    ev_view_primary_get_cb,
597                                                    ev_view_primary_clear_cb,
598                                                    G_OBJECT (ev_view)))
599                         ev_view_primary_clear_cb (clipboard, ev_view);
600         } else {
601                 if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (ev_view))
602                         gtk_clipboard_clear (clipboard);
603         }
604 }
605
606 static gboolean
607 ev_view_button_press_event (GtkWidget      *widget,
608                             GdkEventButton *event)
609 {
610         EvView *view = EV_VIEW (widget);
611
612         if (!GTK_WIDGET_HAS_FOCUS (widget)) {
613                 gtk_widget_grab_focus (widget);
614         }
615
616         view->pressed_button = event->button;
617
618         switch (event->button) {
619                 case 1:
620                         if (view->has_selection) {
621                                 view->has_selection = FALSE;
622                                 gtk_widget_queue_draw (widget);
623                         }
624
625                         view->selection_start.x = event->x;
626                         view->selection_start.y = event->y;
627                         break;
628         }
629
630         return TRUE;
631 }
632
633 static char *
634 status_message_from_link (EvLink *link)
635 {
636         EvLinkType type;
637         char *msg;
638         int page;
639
640         type = ev_link_get_link_type (link);
641         
642         switch (type) {
643                 case EV_LINK_TYPE_TITLE:
644                         msg = g_strdup (ev_link_get_title (link));
645                         break;
646                 case EV_LINK_TYPE_PAGE:
647                         page = ev_link_get_page (link);
648                         msg = g_strdup_printf (_("Go to page %d"), page);
649                         break;
650                 case EV_LINK_TYPE_EXTERNAL_URI:
651                         msg = g_strdup (ev_link_get_uri (link));
652                         break;
653                 default:
654                         msg = NULL;
655         }
656
657         return msg;
658 }
659
660 static void
661 ev_view_set_status (EvView *view, const char *message)
662 {
663         g_return_if_fail (EV_IS_VIEW (view));
664
665         if (message != view->status) {
666                 g_free (view->status);
667                 view->status = g_strdup (message);
668                 g_object_notify (G_OBJECT (view), "status");
669         }
670 }
671
672 static void
673 ev_view_set_find_status (EvView *view, const char *message)
674 {
675         g_return_if_fail (EV_IS_VIEW (view));
676         
677         g_free (view->find_status);
678         view->find_status = g_strdup (message);
679         g_object_notify (G_OBJECT (view), "find-status");
680 }
681
682 static GdkCursor *
683 ev_view_create_invisible_cursor(void)
684 {
685        GdkBitmap *empty;
686        GdkColor black = { 0, 0, 0, 0 };
687        static unsigned char bits[] = { 0x00 };
688
689        empty = gdk_bitmap_create_from_data (NULL, bits, 1, 1);
690
691        return gdk_cursor_new_from_pixmap (empty, empty, &black, &black, 0, 0);
692 }
693
694 static void
695 ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
696 {
697         GdkCursor *cursor = NULL;
698         GdkDisplay *display;
699         GtkWidget *widget;
700
701         if (view->cursor == new_cursor) {
702                 return;
703         }
704
705         widget = gtk_widget_get_toplevel (GTK_WIDGET (view));
706         display = gtk_widget_get_display (widget);
707         view->cursor = new_cursor;
708
709         switch (new_cursor) {
710                 case EV_VIEW_CURSOR_NORMAL:
711                         gdk_window_set_cursor (widget->window, NULL);
712                         break;
713                 case EV_VIEW_CURSOR_LINK:
714                         cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
715                         break;
716                 case EV_VIEW_CURSOR_WAIT:
717                         cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
718                         break;
719                 case EV_VIEW_CURSOR_HIDDEN:
720                         cursor = ev_view_create_invisible_cursor ();
721                         break;
722
723         }
724
725         if (cursor) {
726                 gdk_window_set_cursor (widget->window, cursor);
727                 gdk_cursor_unref (cursor);
728                 gdk_flush();
729         }
730 }
731
732 static gboolean
733 ev_view_motion_notify_event (GtkWidget      *widget,
734                              GdkEventMotion *event)
735 {
736         EvView *view = EV_VIEW (widget);
737
738         if (view->pressed_button > 0) {
739                 GdkRectangle selection;
740
741                 view->has_selection = TRUE;
742                 selection.x = MIN (view->selection_start.x, event->x);
743                 selection.y = MIN (view->selection_start.y, event->y);
744                 selection.width = ABS (view->selection_start.x - event->x) + 1;
745                 selection.height = ABS (view->selection_start.y - event->y) + 1;
746                 view_rect_to_doc_rect (view, &selection, &view->selection);
747
748                 gtk_widget_queue_draw (widget);
749         } else if (view->document) {
750                 EvLink *link;
751
752                 link = ev_document_get_link (view->document, event->x, event->y);
753                 if (link) {
754                         char *msg;
755
756                         msg = status_message_from_link (link);
757                         ev_view_set_status (view, msg);
758                         ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
759                         g_free (msg);
760
761                         g_object_unref (link);
762                 } else {
763                         ev_view_set_status (view, NULL);
764                         if (view->cursor == EV_VIEW_CURSOR_LINK) {
765                                 ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
766                         }
767                 }
768         }
769
770         return TRUE;
771 }
772
773 static gboolean
774 ev_view_button_release_event (GtkWidget      *widget,
775                               GdkEventButton *event)
776 {
777         EvView *view = EV_VIEW (widget);
778
779         view->pressed_button = -1;
780
781         if (view->has_selection) {
782                 ev_view_update_primary_selection (view);
783         } else if (view->document) {
784                 EvLink *link;
785
786                 link = ev_document_get_link (view->document,
787                                              event->x,
788                                              event->y);
789                 if (link) {
790                         ev_view_go_to_link (view, link);
791                         g_object_unref (link);
792                 }
793         }
794
795         return FALSE;
796 }
797
798 static void
799 on_adjustment_value_changed (GtkAdjustment  *adjustment,
800                              EvView *view)
801 {
802         view_update_adjustments (view);
803 }
804
805 static void
806 set_scroll_adjustment (EvView *view,
807                        GtkOrientation  orientation,
808                        GtkAdjustment  *adjustment)
809 {
810         GtkAdjustment **to_set;
811
812         if (orientation == GTK_ORIENTATION_HORIZONTAL)
813                 to_set = &view->hadjustment;
814         else
815                 to_set = &view->vadjustment;
816   
817         if (*to_set != adjustment) {
818                 if (*to_set) {
819                         g_signal_handlers_disconnect_by_func (*to_set,
820                                                               (gpointer) on_adjustment_value_changed,
821                                                               view);
822                         g_object_unref (*to_set);
823                 }
824
825                 *to_set = adjustment;
826                 view_set_adjustment_values (view, orientation);
827
828                 if (*to_set) {
829                         g_object_ref (*to_set);
830                         g_signal_connect (*to_set, "value_changed",
831                                           G_CALLBACK (on_adjustment_value_changed), view);
832                 }
833         }
834 }
835
836 static void
837 ev_view_set_scroll_adjustments (EvView *view,
838                                 GtkAdjustment  *hadjustment,
839                                 GtkAdjustment  *vadjustment)
840 {
841         set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, hadjustment);
842         set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL, vadjustment);
843
844         view_update_adjustments (view);
845 }
846
847 static void
848 add_scroll_binding (GtkBindingSet  *binding_set,
849                     guint           keyval,
850                     GtkScrollType   scroll,
851                     gboolean        horizontal)
852 {
853   guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left;
854   
855   gtk_binding_entry_add_signal (binding_set, keyval, 0,
856                                 "scroll_view", 2,
857                                 GTK_TYPE_SCROLL_TYPE, scroll,
858                                 G_TYPE_BOOLEAN, horizontal);
859   gtk_binding_entry_add_signal (binding_set, keypad_keyval, 0,
860                                 "scroll_view", 2,
861                                 GTK_TYPE_SCROLL_TYPE, scroll,
862                                 G_TYPE_BOOLEAN, horizontal);
863 }
864
865 static void
866 ev_view_scroll_view (EvView *view,
867                      GtkScrollType scroll,
868                      gboolean horizontal)
869 {
870         if (scroll == GTK_SCROLL_PAGE_BACKWARD) {
871                 ev_view_set_page (view, ev_view_get_page (view) - 1);
872         } else if (scroll == GTK_SCROLL_PAGE_FORWARD) {
873                 ev_view_set_page (view, ev_view_get_page (view) + 1);
874         } else {
875                 GtkAdjustment *adjustment;
876                 double value;
877
878                 if (horizontal) {
879                         adjustment = view->hadjustment; 
880                 } else {
881                         adjustment = view->vadjustment;
882                 }
883
884                 value = adjustment->value;
885
886                 switch (scroll) {
887                         case GTK_SCROLL_STEP_BACKWARD:  
888                                 value -= adjustment->step_increment; 
889                                 break;
890                         case GTK_SCROLL_STEP_FORWARD:
891                                 value += adjustment->step_increment; 
892                                 break;
893                         default:
894                                 break;
895                 }
896
897                 value = CLAMP (value, adjustment->lower,
898                                adjustment->upper - adjustment->page_size);
899
900                 gtk_adjustment_set_value (adjustment, value);
901         }
902 }
903
904 static void
905 ev_view_set_property (GObject *object,
906                       guint prop_id,
907                       const GValue *value,
908                       GParamSpec *pspec)
909 {
910         switch (prop_id)
911         {
912                 /* Read only */
913                 case PROP_STATUS:
914                 case PROP_FIND_STATUS:
915                         break;
916         }
917 }
918
919 static void
920 ev_view_get_property (GObject *object,
921                       guint prop_id,
922                       GValue *value,
923                       GParamSpec *pspec)
924 {
925         EvView *view = EV_VIEW (object);
926
927         switch (prop_id)
928         {
929                 case PROP_STATUS:
930                         g_value_set_string (value, view->status);
931                         break;
932                 case PROP_FIND_STATUS:
933                         g_value_set_string (value, view->status);
934                         break;
935         }
936 }
937
938 static void
939 ev_view_class_init (EvViewClass *class)
940 {
941         GObjectClass *object_class = G_OBJECT_CLASS (class);
942         GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
943         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
944         GtkBindingSet *binding_set;
945
946         object_class->finalize = ev_view_finalize;
947         object_class->set_property = ev_view_set_property;
948         object_class->get_property = ev_view_get_property;
949
950         widget_class->expose_event = ev_view_expose_event;
951         widget_class->button_press_event = ev_view_button_press_event;
952         widget_class->motion_notify_event = ev_view_motion_notify_event;
953         widget_class->button_release_event = ev_view_button_release_event;
954         widget_class->size_request = ev_view_size_request;
955         widget_class->size_allocate = ev_view_size_allocate;
956         widget_class->realize = ev_view_realize;
957         widget_class->unrealize = ev_view_unrealize;
958         gtk_object_class->destroy = ev_view_destroy;
959
960         class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
961         class->scroll_view = ev_view_scroll_view;
962
963         widget_class->set_scroll_adjustments_signal =  g_signal_new ("set-scroll-adjustments",
964                                                                      G_OBJECT_CLASS_TYPE (object_class),
965                                                                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
966                                                                      G_STRUCT_OFFSET (EvViewClass, set_scroll_adjustments),
967                                                                      NULL, NULL,
968                                                                      ev_marshal_VOID__OBJECT_OBJECT,
969                                                                      G_TYPE_NONE, 2,
970                                                                      GTK_TYPE_ADJUSTMENT,
971                                                                      GTK_TYPE_ADJUSTMENT);
972         page_changed_signal = g_signal_new ("page-changed",
973                                             G_OBJECT_CLASS_TYPE (object_class),
974                                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
975                                             G_STRUCT_OFFSET (EvViewClass, page_changed),
976                                             NULL, NULL,
977                                             ev_marshal_VOID__NONE,
978                                             G_TYPE_NONE, 0);
979
980         g_signal_new ("scroll_view",
981                       G_TYPE_FROM_CLASS (object_class),
982                       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
983                       G_STRUCT_OFFSET (EvViewClass, scroll_view),
984                       NULL, NULL,
985                       ev_marshal_VOID__ENUM_BOOLEAN,
986                       G_TYPE_NONE, 2,
987                       GTK_TYPE_SCROLL_TYPE,
988                       G_TYPE_BOOLEAN);
989
990         g_object_class_install_property (object_class,
991                                          PROP_STATUS,
992                                          g_param_spec_string ("status",
993                                                               "Status Message",
994                                                               "The status message",
995                                                               NULL,
996                                                               G_PARAM_READABLE));
997
998         g_object_class_install_property (object_class,
999                                          PROP_STATUS,
1000                                          g_param_spec_string ("find-status",
1001                                                               "Find Status Message",
1002                                                               "The find status message",
1003                                                               NULL,
1004                                                               G_PARAM_READABLE));
1005
1006         binding_set = gtk_binding_set_by_class (class);
1007
1008         add_scroll_binding (binding_set, GDK_Left,  GTK_SCROLL_STEP_BACKWARD, TRUE);
1009         add_scroll_binding (binding_set, GDK_Right, GTK_SCROLL_STEP_FORWARD,  TRUE);
1010         add_scroll_binding (binding_set, GDK_Up,    GTK_SCROLL_STEP_BACKWARD, FALSE);
1011         add_scroll_binding (binding_set, GDK_Down,  GTK_SCROLL_STEP_FORWARD,  FALSE);
1012
1013         add_scroll_binding (binding_set, GDK_Page_Up,   GTK_SCROLL_PAGE_BACKWARD, FALSE);
1014         add_scroll_binding (binding_set, GDK_Page_Down, GTK_SCROLL_PAGE_FORWARD,  FALSE);
1015 }
1016
1017 static void
1018 ev_view_init (EvView *view)
1019 {
1020         GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS);
1021
1022         view->spacing = 10;
1023         view->scale = 1.0;
1024         view->pressed_button = -1;
1025         view->cursor = EV_VIEW_CURSOR_NORMAL;
1026 }
1027
1028 static void
1029 update_find_status_message (EvView *view)
1030 {
1031         char *message;
1032
1033         if (ev_document_get_page (view->document) == view->find_page) {
1034                 int results;
1035
1036                 results = ev_document_find_get_n_results
1037                                 (EV_DOCUMENT_FIND (view->document));
1038
1039                 /* TRANS: Sometimes this could be better translated as
1040                    "%d hit(s) on this page".  Therefore this string
1041                    contains plural cases. */
1042                 message = g_strdup_printf (ngettext ("%d found on this page",
1043                                                      "%d found on this page",
1044                                                      results),
1045                                            results);
1046         } else {
1047                 double percent;
1048                 
1049                 percent = ev_document_find_get_progress
1050                                 (EV_DOCUMENT_FIND (view->document));
1051
1052                 if (percent >= (1.0 - 1e-10)) {
1053                         message = g_strdup (_("Not found"));
1054                 } else {
1055                         message = g_strdup_printf (_("%3d%% remaining to search"),
1056                                                    (int) ((1.0 - percent) * 100));
1057                 }
1058                 
1059         }
1060
1061         ev_view_set_find_status (view, message);
1062         g_free (message);
1063 }
1064
1065 static void
1066 set_document_page (EvView *view, int new_page)
1067 {
1068         int page;
1069         int pages;
1070
1071         pages = ev_document_get_n_pages (view->document);
1072         page = CLAMP (new_page, 1, pages);
1073
1074         if (view->document) {
1075                 int old_page = ev_document_get_page (view->document);
1076                 int old_width, old_height;
1077
1078                 ev_document_get_page_size (view->document,
1079                                            -1, 
1080                                            &old_width, &old_height);
1081
1082                 if (old_page != page) {
1083                         if (view->cursor != EV_VIEW_CURSOR_HIDDEN) {
1084                                 ev_view_set_cursor (view, EV_VIEW_CURSOR_WAIT);
1085                         }
1086                         ev_document_set_page (view->document, page);
1087                 }
1088
1089                 if (old_page != ev_document_get_page (view->document)) {
1090                         int width, height;
1091                         
1092                         g_signal_emit (view, page_changed_signal, 0);
1093
1094                         view->has_selection = FALSE;
1095                         ev_document_get_page_size (view->document,
1096                                                    -1, 
1097                                                    &width, &height);
1098                         if (width != old_width || height != old_height)
1099                                 gtk_widget_queue_resize (GTK_WIDGET (view));
1100
1101                         gtk_adjustment_set_value (view->vadjustment,
1102                                                   view->vadjustment->lower);
1103                 }
1104
1105                 if (EV_IS_DOCUMENT_FIND (view->document)) {
1106                         view->find_page = page;
1107                         view->find_result = 0;
1108                         update_find_status_message (view);
1109                 }
1110         }
1111 }
1112
1113 #define MARGIN 5
1114
1115 static void
1116 ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect)
1117 {
1118         GtkWidget *widget = GTK_WIDGET (view);
1119         GtkAdjustment *adjustment;
1120         int value;
1121
1122         adjustment = view->vadjustment;
1123
1124         if (rect->y < adjustment->value) {
1125                 value = MAX (adjustment->lower, rect->y - MARGIN);
1126                 gtk_adjustment_set_value (view->vadjustment, value);
1127         } else if (rect->y + rect->height >
1128                    adjustment->value + widget->allocation.height) {
1129                 value = MIN (adjustment->upper, rect->y + rect->height -
1130                              widget->allocation.height + MARGIN);
1131                 gtk_adjustment_set_value (view->vadjustment, value);
1132         }
1133
1134         adjustment = view->hadjustment;
1135
1136         if (rect->x < adjustment->value) {
1137                 value = MAX (adjustment->lower, rect->x - MARGIN);
1138                 gtk_adjustment_set_value (view->hadjustment, value);
1139         } else if (rect->x + rect->height >
1140                    adjustment->value + widget->allocation.width) {
1141                 value = MIN (adjustment->upper, rect->x + rect->width -
1142                              widget->allocation.width + MARGIN);
1143                 gtk_adjustment_set_value (view->hadjustment, value);
1144         }
1145 }
1146
1147 static void
1148 jump_to_find_result (EvView *view)
1149 {
1150         EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
1151         GdkRectangle rect;
1152         int n_results;
1153
1154         n_results = ev_document_find_get_n_results (find);
1155
1156         if (n_results > view->find_result) {
1157                 ev_document_find_get_result
1158                         (find, view->find_result, &rect);
1159                 ensure_rectangle_is_visible (view, &rect);
1160         }
1161 }
1162
1163 static void
1164 jump_to_find_page (EvView *view)
1165 {
1166         int n_pages, i;
1167
1168         n_pages = ev_document_get_n_pages (view->document);
1169
1170         for (i = 0; i <= n_pages; i++) {
1171                 int has_results;
1172                 int page;
1173
1174                 page = i + view->find_page;
1175                 if (page > n_pages) {
1176                         page = page - n_pages;
1177                 }
1178
1179                 has_results = ev_document_find_page_has_results
1180                                 (EV_DOCUMENT_FIND (view->document), page);
1181                 if (has_results == -1) {
1182                         view->find_page = page;
1183                         break;
1184                 } else if (has_results == 1) {
1185                         set_document_page (view, page);
1186                         jump_to_find_result (view);
1187                         break;
1188                 }
1189         }
1190 }
1191
1192 static void
1193 find_changed_cb (EvDocument *document, int page, EvView *view)
1194 {
1195         jump_to_find_page (view);
1196         jump_to_find_result (view);
1197         update_find_status_message (view);
1198
1199         if (ev_document_get_page (document) == page) {
1200                 gtk_widget_queue_draw (GTK_WIDGET (view));
1201         }
1202 }
1203
1204 static void
1205 page_changed_callback (EvDocument *document,
1206                            EvView     *view)
1207 {
1208         gtk_widget_queue_draw (GTK_WIDGET (view));
1209
1210         if (view->cursor != EV_VIEW_CURSOR_HIDDEN) {
1211                 ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
1212         }
1213 }
1214
1215 static void
1216 scale_changed_callback (EvDocument *document,
1217                         EvView     *view)
1218 {
1219         gtk_widget_queue_resize (GTK_WIDGET (view));
1220 }
1221
1222 /*** Public API ***/       
1223      
1224 GtkWidget*
1225 ev_view_new (void)
1226 {
1227         return g_object_new (EV_TYPE_VIEW, NULL);
1228 }
1229
1230 void
1231 ev_view_set_document (EvView     *view,
1232                       EvDocument *document)
1233 {
1234         g_return_if_fail (EV_IS_VIEW (view));
1235
1236         if (document != view->document) {
1237                 if (view->document) {
1238                         g_signal_handlers_disconnect_by_func (view->document,
1239                                                               find_changed_cb,
1240                                                               view);
1241                         g_object_unref (view->document);
1242                 }
1243
1244                 view->document = document;
1245                 view->find_page = 1;
1246                 view->find_result = 0;
1247
1248                 if (view->document) {
1249                         g_object_ref (view->document);
1250                         if (EV_IS_DOCUMENT_FIND (view->document)) {
1251                                 g_signal_connect (view->document,
1252                                                   "find_changed",
1253                                                   G_CALLBACK (find_changed_cb),
1254                                                   view);
1255                         }
1256                         g_signal_connect (view->document,
1257                                           "page_changed",
1258                                           G_CALLBACK (page_changed_callback),
1259                                           view);
1260                         g_signal_connect (view->document,
1261                                           "scale_changed",
1262                                           G_CALLBACK (scale_changed_callback),
1263                                           view);
1264                 }
1265
1266                 if (GTK_WIDGET_REALIZED (view))
1267                         ev_document_set_target (view->document, view->bin_window);
1268                 
1269                 gtk_widget_queue_resize (GTK_WIDGET (view));
1270                 
1271                 g_signal_emit (view, page_changed_signal, 0);
1272         }
1273 }
1274
1275 static void
1276 go_to_link (EvView *view, EvLink *link)
1277 {
1278         EvLinkType type;
1279         const char *uri;
1280         int page;
1281
1282         type = ev_link_get_link_type (link);
1283         
1284         switch (type) {
1285                 case EV_LINK_TYPE_TITLE:
1286                         break;
1287                 case EV_LINK_TYPE_PAGE:
1288                         page = ev_link_get_page (link);
1289                         set_document_page (view, page);
1290                         break;
1291                 case EV_LINK_TYPE_EXTERNAL_URI:
1292                         uri = ev_link_get_uri (link);
1293                         gnome_vfs_url_show (uri);
1294                         break;
1295         }
1296 }
1297
1298 void
1299 ev_view_go_to_link (EvView *view, EvLink *link)
1300 {
1301         go_to_link (view, link);
1302 }
1303
1304 void
1305 ev_view_set_page (EvView *view,
1306                   int     page)
1307 {
1308         g_return_if_fail (EV_IS_VIEW (view));
1309
1310         set_document_page (view, page);
1311 }
1312
1313 int
1314 ev_view_get_page (EvView *view)
1315 {
1316         if (view->document)
1317                 return ev_document_get_page (view->document);
1318         else
1319                 return 1;
1320 }
1321
1322 static void
1323 ev_view_zoom (EvView   *view,
1324               double    factor,
1325               gboolean  relative)
1326 {
1327         double scale;
1328
1329         if (relative)
1330                 scale = view->scale * factor;
1331         else
1332                 scale = factor;
1333
1334         scale = CLAMP (scale, MIN_SCALE, MAX_SCALE);
1335
1336         view->scale = scale;
1337
1338         ev_document_set_scale (view->document, view->scale);
1339 }
1340
1341 void
1342 ev_view_zoom_in (EvView *view)
1343 {
1344         view->width = view->height = -1;
1345         ev_view_zoom (view, ZOOM_IN_FACTOR, TRUE);
1346 }
1347
1348 void
1349 ev_view_zoom_out (EvView *view)
1350 {
1351         view->width = view->height = -1;
1352         ev_view_zoom (view, ZOOM_OUT_FACTOR, TRUE);
1353 }
1354
1355 static double
1356 size_to_zoom_factor (EvView *view, int width, int height)
1357 {
1358         int doc_width, doc_height;
1359         double scale, scale_w, scale_h;
1360         GtkBorder border;
1361
1362         doc_width = doc_height = 0;
1363         scale = scale_w = scale_h = 1.0;
1364         ev_document_get_page_size (view->document, -1, &doc_width, &doc_height);
1365         /* FIXME: The border size isn't constant.  Ugh.  Still, if we have extra
1366          * space, we just cut it from the border */
1367         ev_document_misc_get_page_border_size (doc_width, doc_height, &border);
1368
1369         if (doc_width == 0 && doc_height == 0) {
1370                 return 0;
1371         }
1372
1373         if (width >= 0) {
1374                 int target_width;
1375
1376                 target_width = width - (view->spacing * 2 + border.left + border.right);
1377                 scale = scale_w = (double)target_width * view->scale / doc_width;
1378         }
1379
1380         if (height >= 0) {
1381                 int target_height;
1382
1383                 target_height = height - (view->spacing * 2 + border.top + border.bottom);
1384                 scale = scale_h = (double)target_height * view->scale / doc_height;
1385         }
1386
1387         if (width >= 0 && height >= 0) {
1388                 scale = (scale_w < scale_h) ? scale_w : scale_h;
1389         }
1390
1391         return scale;
1392 }
1393
1394 void
1395 ev_view_set_size (EvView     *view,
1396                   int         width,
1397                   int         height)
1398 {
1399         double factor;
1400
1401         if (!view->document) {
1402                 return;
1403         }
1404
1405         if (view->width != width ||
1406             view->height != height) {
1407                 view->width = width;
1408                 view->height = height;
1409                 factor = size_to_zoom_factor (view, width, height);
1410                 ev_view_zoom (view, factor, FALSE); 
1411         }
1412 }
1413
1414 const char *
1415 ev_view_get_status (EvView *view)
1416 {
1417         g_return_val_if_fail (EV_IS_VIEW (view), NULL);
1418
1419         return view->status;
1420 }
1421
1422 const char *
1423 ev_view_get_find_status (EvView *view)
1424 {
1425         g_return_val_if_fail (EV_IS_VIEW (view), NULL);
1426
1427         return view->find_status;
1428 }
1429
1430 void
1431 ev_view_find_next (EvView *view)
1432 {
1433         int n_results, n_pages;
1434         EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
1435
1436         n_results = ev_document_find_get_n_results (find);
1437         n_pages = ev_document_get_n_pages (view->document);
1438
1439         view->find_result++;
1440
1441         if (view->find_result >= n_results) {
1442                 view->find_result = 0;
1443                 view->find_page++;
1444
1445                 if (view->find_page > n_pages) {
1446                         view->find_page = 1;
1447                 }
1448
1449                 jump_to_find_page (view);
1450         } else {
1451                 jump_to_find_result (view);
1452                 gtk_widget_queue_draw (GTK_WIDGET (view));
1453         }
1454 }
1455
1456 void
1457 ev_view_find_previous (EvView *view)
1458 {
1459         int n_results, n_pages;
1460         EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
1461
1462         n_results = ev_document_find_get_n_results (find);
1463         n_pages = ev_document_get_n_pages (view->document);
1464
1465         view->find_result--;
1466
1467         if (view->find_result < 0) {
1468                 view->find_result = 0;
1469                 view->find_page--;
1470
1471                 if (view->find_page < 1) {
1472                         view->find_page = n_pages;
1473                 }
1474
1475                 jump_to_find_page (view);
1476         } else {
1477                 jump_to_find_result (view);
1478                 gtk_widget_queue_draw (GTK_WIDGET (view));
1479         }
1480 }
1481 void
1482 ev_view_hide_cursor (EvView *view)
1483 {
1484        ev_view_set_cursor (view, EV_VIEW_CURSOR_HIDDEN);
1485 }
1486
1487 void
1488 ev_view_show_cursor (EvView *view)
1489 {
1490        ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
1491 }