]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-view.c
Don't jump on scrolling, fix for the bug #333127.
[evince.git] / shell / ev-view.c
index 1f089fcf3ed41a95ddcdcbfb9de9352cfb887235..d8a802498de1529a4c8f79733d9f9dbc97a06b1e 100644 (file)
@@ -113,10 +113,8 @@ static void       ev_view_set_scroll_adjustments             (EvView
                                                              GtkAdjustment      *vadjustment);
 static void       add_scroll_binding_keypad                  (GtkBindingSet      *binding_set,
                                                              guint               keyval,
-                                                             GtkScrollType       scroll,
-                                                             gboolean            horizontal);
-static void       ev_view_binding_activated                  (EvView             *view,
-                                                             GtkScrollType       scroll,
+                                                             GdkModifierType modifiers,
+                                                             EvScrollType       scroll,
                                                              gboolean            horizontal);
 static void       ensure_rectangle_is_visible                (EvView             *view,
                                                              GdkRectangle       *rect);
@@ -179,6 +177,7 @@ static gboolean   ev_view_scroll_event                       (GtkWidget
                                                              GdkEventScroll     *event);
 static gboolean   ev_view_expose_event                       (GtkWidget          *widget,
                                                              GdkEventExpose     *event);
+static gboolean   ev_view_popup_menu                         (GtkWidget         *widget);
 static gboolean   ev_view_button_press_event                 (GtkWidget          *widget,
                                                              GdkEventButton     *event);
 static gboolean   ev_view_motion_notify_event                (GtkWidget          *widget,
@@ -207,6 +206,9 @@ static void       draw_one_page                              (EvView
                                                              GdkRectangle       *page_area,
                                                              GtkBorder          *border,
                                                              GdkRectangle       *expose_area);
+static void      draw_loading_text                          (EvView             *view,
+                                                             GdkRectangle       *page_area,
+                                                             GdkRectangle       *expose_area);
 
 /*** Callbacks ***/
 static void       find_changed_cb                            (EvDocument         *document,
@@ -282,13 +284,15 @@ static void       ev_view_set_cursor                         (EvView
 /*** Status messages ***/
 static void       ev_view_set_status                         (EvView             *view,
                                                              const char         *message);
-static void       update_find_status_message                 (EvView             *view);
+static void       update_find_status_message                 (EvView             *view,
+                                                             gboolean            this_page);
 static void       ev_view_set_find_status                    (EvView             *view,
                                                              const char         *message);
 /*** Find ***/
 static void       jump_to_find_result                        (EvView             *view);
 static void       jump_to_find_page                          (EvView             *view, 
-                                                             EvViewFindDirection direction);
+                                                             EvViewFindDirection direction,
+                                                             gint                shift);
 
 /*** Selection ***/
 static void       compute_selections                         (EvView             *view,
@@ -328,11 +332,14 @@ scroll_to_current_page (EvView *view, GtkOrientation orientation)
        if (orientation == GTK_ORIENTATION_VERTICAL) {
                if (view->continuous) {
                        gtk_adjustment_clamp_page (view->vadjustment,
-                                                  view_point.y - view->spacing,
+                                                  view_point.y - view->spacing / 2,
                                                   view_point.y + view->vadjustment->page_size);
                } else {
                        gtk_adjustment_set_value (view->vadjustment,
-                                                 view_point.y);
+                                                 CLAMP (view_point.y,
+                                                 view->vadjustment->lower,
+                                                 view->vadjustment->upper -
+                                                 view->vadjustment->page_size));
                }
        } else {
                if (view->dual_page) {
@@ -416,6 +423,8 @@ view_set_adjustment_values (EvView         *view,
 static void
 view_update_range_and_current_page (EvView *view)
 {
+       gint current_page;
+       
        if (view->pending_scroll != SCROLL_TO_KEEP_POSITION)
                return;
 
@@ -426,7 +435,6 @@ view_update_range_and_current_page (EvView *view)
        } else if (view->continuous) {
                GdkRectangle current_area, unused, page_area;
                GtkBorder border;
-               gint current_page;
                gboolean found = FALSE;
                int i;
 
@@ -454,28 +462,33 @@ view_update_range_and_current_page (EvView *view)
                        }
                }
 
-               current_page = ev_page_cache_get_current_page (view->page_cache);
-
-               if (current_page < view->start_page || current_page > view->end_page) {
-                       view->current_page = view->start_page;
-                       ev_page_cache_set_current_page (view->page_cache, view->start_page);
-               }
        } else {
                if (view->dual_page) {
-                       if (view->current_page % 2 == 0) {
+                       if (view->current_page % 2 == ev_page_cache_get_dual_even_left (view->page_cache)) {
                                view->start_page = view->current_page;
                                if (view->current_page + 1 < ev_page_cache_get_n_pages (view->page_cache))
                                        view->end_page = view->start_page + 1;
                                else 
                                        view->end_page = view->start_page;
                        } else {
-                               view->start_page = view->current_page - 1;
+                               if (view->current_page < 1)
+                                       view->start_page = view->current_page;
+                               else
+                                       view->start_page = view->current_page - 1;
                                view->end_page = view->current_page;
                        }
                } else {
                        view->start_page = view->current_page;
                        view->end_page = view->current_page;
                }
+
+       }
+
+       current_page = ev_page_cache_get_current_page (view->page_cache);
+
+       if (current_page < view->start_page || current_page > view->end_page) {
+               view->current_page = view->start_page;
+               ev_page_cache_set_current_page (view->page_cache, view->start_page);
        }
 
        ev_pixbuf_cache_set_page_range (view->pixbuf_cache,
@@ -531,32 +544,50 @@ ev_view_set_scroll_adjustments (EvView *view,
 static void
 add_scroll_binding_keypad (GtkBindingSet  *binding_set,
                           guint           keyval,
-                          GtkScrollType   scroll,
+                          GdkModifierType modifiers,
+                          EvScrollType    scroll,
                           gboolean        horizontal)
 {
   guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left;
 
-  gtk_binding_entry_add_signal (binding_set, keyval, 0,
+  gtk_binding_entry_add_signal (binding_set, keyval, modifiers,
                                 "binding_activated", 2,
-                                GTK_TYPE_SCROLL_TYPE, scroll,
+                                EV_TYPE_SCROLL_TYPE, scroll,
                                G_TYPE_BOOLEAN, horizontal);
-  gtk_binding_entry_add_signal (binding_set, keypad_keyval, 0,
+  gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers,
                                 "binding_activated", 2,
-                                GTK_TYPE_SCROLL_TYPE, scroll,
+                                EV_TYPE_SCROLL_TYPE, scroll,
                                G_TYPE_BOOLEAN, horizontal);
 }
 
 void
 ev_view_scroll (EvView        *view,
-               EvScrollType   scroll)
+               EvScrollType   scroll,
+               gboolean horizontal)
 {
        GtkAdjustment *adjustment;
        double value, increment;
        gboolean first_page = FALSE;
        gboolean last_page = FALSE;
 
+       view->jump_to_find_result = FALSE;
+
+       if (view->presentation) {
+               switch (scroll) {
+                       case EV_SCROLL_STEP_BACKWARD:
+                               ev_view_previous_page (view);
+                               break;
+                       case EV_SCROLL_STEP_FORWARD:
+                               ev_view_next_page (view);
+                               break;
+                       default:
+                               break;
+               }
+               return;
+       }
+
        /* Assign values for increment and vertical adjustment */
-       adjustment = view->vadjustment;
+       adjustment = horizontal ? view->hadjustment : view->vadjustment;
        increment = adjustment->page_size * 0.75;
        value = adjustment->value;
 
@@ -574,7 +605,7 @@ ev_view_scroll (EvView        *view,
                                /* At the top of a page, assign the upper bound limit of previous page */
                        } else if (value == (adjustment->lower)) {
                                value = adjustment->upper - adjustment->page_size;
-                               ev_page_cache_set_current_page (view->page_cache, view->current_page - 1);
+                               ev_view_previous_page (view);
                                /* Jump to the top */
                        } else {
                                value = MAX (value - increment, adjustment->lower);
@@ -587,64 +618,33 @@ ev_view_scroll (EvView        *view,
                        /* At the bottom of a page, assign the lower bound limit of next page */
                        } else if (value == (adjustment->upper - adjustment->page_size)) {
                                value = 0;
-                               ev_page_cache_set_current_page (view->page_cache, view->current_page + 1);
+                               ev_view_next_page (view);
                        /* Jump to the bottom */
                        } else {
                                value = MIN (value + increment, adjustment->upper - adjustment->page_size);
                        }
                        break;
-               default:
-                       break;
-       }
-
-       gtk_adjustment_set_value (adjustment, value);
-}
-
-static void
-ev_view_binding_activated (EvView *view,
-                          GtkScrollType scroll,
-                          gboolean horizontal)
-{
-       GtkAdjustment *adjustment;
-       double value;
-
-       if (view->presentation) {
-               switch (scroll) {
-                       case GTK_SCROLL_STEP_BACKWARD:
-                               ev_view_previous_page (view);
-                               break;
-                       case GTK_SCROLL_STEP_FORWARD:
-                               ev_view_next_page (view);
-                               break;
-                       default:
-                               break;
-               }
-               return;
-       }
-
-       if (horizontal) {
-               adjustment = view->hadjustment;
-       } else {
-               adjustment = view->vadjustment;
-       }
-
-       value = adjustment->value;
-
-       switch (scroll) {
-               case GTK_SCROLL_STEP_BACKWARD:
+               case EV_SCROLL_STEP_BACKWARD:
                        value -= adjustment->step_increment;
                        break;
-               case GTK_SCROLL_STEP_FORWARD:
+               case EV_SCROLL_STEP_FORWARD:
                        value += adjustment->step_increment;
                        break;
-               default:
+               case EV_SCROLL_STEP_DOWN:
+                       value -= adjustment->step_increment / 10;
+                       break;
+               case EV_SCROLL_STEP_UP:
+                       value += adjustment->step_increment / 10;
+                       break;
+               default:
                        break;
        }
 
        value = CLAMP (value, adjustment->lower,
-                      adjustment->upper - adjustment->page_size);
+                      adjustment->upper - adjustment->page_size);      
 
        gtk_adjustment_set_value (adjustment, value);
+
 }
 
 #define MARGIN 5
@@ -713,7 +713,7 @@ get_page_y_offset (EvView *view, int page, double zoom, int *y_offset)
        if (view->dual_page) {
                ev_page_cache_get_height_to_page (view->page_cache, page,
                                                  view->rotation, zoom, NULL, &offset);
-               offset += (page / 2 + 1) * view->spacing + (page / 2) * (border.top + border.bottom);
+               offset += ((page + ev_page_cache_get_dual_even_left (view->page_cache)) / 2 + 1) * view->spacing + ((page + ev_page_cache_get_dual_even_left (view->page_cache)) / 2 ) * (border.top + border.bottom);
        } else {
                ev_page_cache_get_height_to_page (view->page_cache, page,
                                                  view->rotation, zoom, &offset, NULL);
@@ -756,9 +756,9 @@ get_page_extents (EvView       *view,
                max_width = max_width + border->left + border->right;
                /* Get the location of the bounding box */
                if (view->dual_page) {
-                       x = view->spacing + (page % 2) * (max_width + view->spacing);
+                       x = view->spacing + ((page % 2 == ev_page_cache_get_dual_even_left (view->page_cache)) ? 0 : 1) * (max_width + view->spacing);
                        x = x + MAX (0, widget->allocation.width - (max_width * 2 + view->spacing * 3)) / 2;
-                       if (page % 2 == 0)
+                       if (page % 2 == ev_page_cache_get_dual_even_left (view->page_cache))
                                x = x + (max_width - width - border->left - border->right);
                } else {
                        x = view->spacing;
@@ -778,10 +778,11 @@ get_page_extents (EvView       *view,
                        GtkBorder overall_border;
                        gint other_page;
 
-                       other_page = page ^ 1;
+                       other_page = (page % 2 == ev_page_cache_get_dual_even_left (view->page_cache)) ? page + 1: page - 1;
 
                        /* First, we get the bounding box of the two pages */
-                       if (other_page < ev_page_cache_get_n_pages (view->page_cache)) {
+                       if (other_page < ev_page_cache_get_n_pages (view->page_cache)
+                           && (0 <= other_page)) {
                                ev_page_cache_get_size (view->page_cache,
                                                        other_page,
                                                        view->rotation,
@@ -799,7 +800,7 @@ get_page_extents (EvView       *view,
                        y = view->spacing;
 
                        /* Adjust for being the left or right page */
-                       if (page % 2 == 0)
+                       if (page % 2 == ev_page_cache_get_dual_even_left (view->page_cache))
                                x = x + max_width - width;
                        else
                                x = x + (max_width + overall_border.left + overall_border.right) + view->spacing;
@@ -1542,6 +1543,7 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event)
                return TRUE;
        }
 
+       view->jump_to_find_result = FALSE;
        /* Shift+Wheel scrolls the in the perpendicular direction */
        if (state & GDK_SHIFT_MASK) {
                if (event->direction == GDK_SCROLL_UP)
@@ -1600,6 +1602,12 @@ ev_view_expose_event (GtkWidget      *widget,
        EvView *view = EV_VIEW (widget);
        int i;
 
+       if (view->loading) {
+               draw_loading_text (view,
+                                  &(widget->allocation),
+                                  &(event->area));
+       }
+
        if (view->document == NULL)
                return FALSE;
 
@@ -1622,6 +1630,19 @@ ev_view_expose_event (GtkWidget      *widget,
        return FALSE;
 }
 
+static gboolean
+ev_view_popup_menu (GtkWidget *widget)
+{
+    gint x, y;
+    EvLink *link;
+    EvView *view = EV_VIEW (widget);
+    
+    gtk_widget_get_pointer (widget, &x, &y);
+    link = ev_view_get_link_at_location (view, x, y);
+    g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, link);
+    return TRUE;
+}
+
 static gboolean
 ev_view_button_press_event (GtkWidget      *widget,
                            GdkEventButton *event)
@@ -1706,10 +1727,10 @@ selection_update_idle_cb (EvView *view)
 static gboolean
 selection_scroll_timeout_cb (EvView *view)
 {      
-       gint y, shift = 0;
+       gint x, y, shift = 0;
        GtkWidget *widget = GTK_WIDGET (view);
        
-       gtk_widget_get_pointer (widget, NULL, &y);
+       gtk_widget_get_pointer (widget, &x, &y);
 
        if (y > widget->allocation.height) {
                shift = (y - widget->allocation.height) / 2;
@@ -1723,6 +1744,20 @@ selection_scroll_timeout_cb (EvView *view)
                                          view->vadjustment->lower,
                                          view->vadjustment->upper -
                                          view->vadjustment->page_size));       
+
+       if (x > widget->allocation.width) {
+               shift = (x - widget->allocation.width) / 2;
+       } else if (x < 0) {
+               shift = x / 2;
+       }
+
+       if (shift)
+               gtk_adjustment_set_value (view->hadjustment,
+                                         CLAMP (view->hadjustment->value + shift,
+                                         view->hadjustment->lower,
+                                         view->hadjustment->upper -
+                                         view->hadjustment->page_size));       
+
        return TRUE;
 }
 
@@ -2019,7 +2054,7 @@ highlight_find_results (EvView *view, int page)
                GdkRectangle view_rectangle;
                guchar alpha;
 
-               if (i == view->find_result && page == view->find_page) {
+               if (i == view->find_result && page == view->current_page) {
                        alpha = 0x90;
                } else {
                        alpha = 0x20;
@@ -2089,11 +2124,14 @@ draw_one_page (EvView          *view,
        GdkRectangle overlap;
        GdkRectangle real_page_area;
        EvViewSelection *selection;
+       gint current_page;
 
        g_assert (view->document);
+       
        if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
                return;
-
+       
+       current_page = ev_page_cache_get_current_page (view->page_cache);
        selection = find_selection_for_page (view, page);
        ev_page_cache_get_size (view->page_cache,
                                page, view->rotation,
@@ -2109,7 +2147,8 @@ draw_one_page (EvView          *view,
 
        ev_document_misc_paint_one_page (GTK_WIDGET(view)->window,
                                         GTK_WIDGET (view),
-                                        page_area, border);
+                                        page_area, border, 
+                                        page == current_page);
 
        if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
                GdkPixbuf *selection_pixbuf = NULL;
@@ -2372,10 +2411,11 @@ ev_view_class_init (EvViewClass *class)
        widget_class->leave_notify_event = ev_view_leave_notify_event;
        widget_class->style_set = ev_view_style_set;
        widget_class->drag_data_get = ev_view_drag_data_get;
+       widget_class->popup_menu = ev_view_popup_menu;
        gtk_object_class->destroy = ev_view_destroy;
 
        class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
-       class->binding_activated = ev_view_binding_activated;
+       class->binding_activated = ev_view_scroll;
 
        widget_class->set_scroll_adjustments_signal =
            g_signal_new ("set-scroll-adjustments",
@@ -2505,10 +2545,14 @@ ev_view_class_init (EvViewClass *class)
 
        binding_set = gtk_binding_set_by_class (class);
 
-       add_scroll_binding_keypad (binding_set, GDK_Left,  GTK_SCROLL_STEP_BACKWARD, TRUE);
-       add_scroll_binding_keypad (binding_set, GDK_Right, GTK_SCROLL_STEP_FORWARD,  TRUE);
-       add_scroll_binding_keypad (binding_set, GDK_Up,    GTK_SCROLL_STEP_BACKWARD, FALSE);
-       add_scroll_binding_keypad (binding_set, GDK_Down,  GTK_SCROLL_STEP_FORWARD,  FALSE);
+       add_scroll_binding_keypad (binding_set, GDK_Left,  0, EV_SCROLL_STEP_BACKWARD, TRUE);
+       add_scroll_binding_keypad (binding_set, GDK_Right, 0, EV_SCROLL_STEP_FORWARD,  TRUE);
+       add_scroll_binding_keypad (binding_set, GDK_Left,  GDK_MOD1_MASK, EV_SCROLL_STEP_DOWN, TRUE);
+       add_scroll_binding_keypad (binding_set, GDK_Right, GDK_MOD1_MASK, EV_SCROLL_STEP_UP,  TRUE);
+       add_scroll_binding_keypad (binding_set, GDK_Up,    0, EV_SCROLL_STEP_BACKWARD, FALSE);
+       add_scroll_binding_keypad (binding_set, GDK_Down,  0, EV_SCROLL_STEP_FORWARD,  FALSE);
+       add_scroll_binding_keypad (binding_set, GDK_Up,    GDK_MOD1_MASK, EV_SCROLL_STEP_DOWN, FALSE);
+       add_scroll_binding_keypad (binding_set, GDK_Down,  GDK_MOD1_MASK, EV_SCROLL_STEP_UP,  FALSE);
 }
 
 static void
@@ -2532,6 +2576,7 @@ ev_view_init (EvView *view)
        view->fullscreen = FALSE;
        view->sizing_mode = EV_SIZING_FIT_WIDTH;
        view->pending_scroll = SCROLL_TO_KEEP_POSITION;
+       view->jump_to_find_result = TRUE;
 }
 
 /*** Callbacks ***/
@@ -2539,10 +2584,18 @@ ev_view_init (EvView *view)
 static void
 find_changed_cb (EvDocument *document, int page, EvView *view)
 {
-       jump_to_find_page (view, EV_VIEW_FIND_NEXT);
-       jump_to_find_result (view);
-       update_find_status_message (view);
+       double percent;
+       int n_pages;
 
+       percent = ev_document_find_get_progress
+                       (EV_DOCUMENT_FIND (view->document)); 
+       n_pages = ev_page_cache_get_n_pages (view->page_cache);
+       
+       if (view->jump_to_find_result == TRUE) {
+               jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
+               jump_to_find_result (view);
+       }
+       update_find_status_message (view, percent * n_pages >= n_pages - 1 );
        if (view->current_page == page)
                gtk_widget_queue_draw (GTK_WIDGET (view));
 }
@@ -2560,16 +2613,16 @@ page_changed_cb (EvPageCache *page_cache,
                 EvView      *view)
 {
        if (view->current_page != new_page) {
-
                view->current_page = new_page;
                view->pending_scroll = SCROLL_TO_PAGE_POSITION;
                gtk_widget_queue_resize (GTK_WIDGET (view));
+       } else {
+               gtk_widget_queue_draw (GTK_WIDGET (view));
+       }
 
-               if (EV_IS_DOCUMENT_FIND (view->document)) {
-                       view->find_page = new_page;
-                       view->find_result = 0;
-                       update_find_status_message (view);
-               }
+       if (EV_IS_DOCUMENT_FIND (view->document)) {
+               view->find_result = 0;
+               update_find_status_message (view, TRUE);
        }
 }
 
@@ -2638,12 +2691,22 @@ clear_caches (EvView *view)
        }
 }
 
+void
+ev_view_set_loading (EvView      *view,
+                    gboolean      loading)
+{
+       view->loading = loading;
+       gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
 void
 ev_view_set_document (EvView     *view,
                      EvDocument *document)
 {
        g_return_if_fail (EV_IS_VIEW (view));
 
+       view->loading = FALSE;
+       
        if (document != view->document) {
                clear_caches (view);
 
@@ -2657,7 +2720,6 @@ ev_view_set_document (EvView     *view,
                 }
 
                view->document = document;
-               view->find_page = 0;
                view->find_result = 0;
 
                if (view->document) {
@@ -3206,11 +3268,11 @@ ev_view_set_status (EvView *view, const char *message)
 }
 
 static void
-update_find_status_message (EvView *view)
+update_find_status_message (EvView *view, gboolean this_page)
 {
        char *message;
 
-       if (view->current_page == view->find_page) {
+       if (this_page) {
                int results;
 
                results = ev_document_find_get_n_results
@@ -3228,13 +3290,9 @@ update_find_status_message (EvView *view)
 
                percent = ev_document_find_get_progress
                                (EV_DOCUMENT_FIND (view->document));
-               if (percent >= (1.0 - 1e-10)) {
-                       message = g_strdup (_("Not found"));
-               } else {
-                       message = g_strdup_printf (_("%3d%% remaining to search"),
-                                                  (int) ((1.0 - percent) * 100));
-               }
-
+               message = g_strdup_printf (_("%3d%% remaining to search"),
+                                          (int) ((1.0 - percent) * 100));
+               
        }
        ev_view_set_find_status (view, message);
        g_free (message);
@@ -3267,7 +3325,7 @@ jump_to_find_result (EvView *view)
        EvRectangle rect;
        GdkRectangle view_rect;
        int n_results;
-       int page = view->find_page;
+       int page = view->current_page;
 
        n_results = ev_document_find_get_n_results (find, page);
 
@@ -3280,8 +3338,18 @@ jump_to_find_result (EvView *view)
        }
 }
 
+/**
+ * jump_to_find_page
+ * @view: #EvView instance
+ * @direction: Direction to look
+ * @shift: Shift from current page
+ *
+ * Jumps to the first page that has occurences of searched word.
+ * Uses a direction where to look and a shift from current page. 
+ *
+ */
 static void
-jump_to_find_page (EvView *view, EvViewFindDirection direction)
+jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
 {
        int n_pages, i;
 
@@ -3292,11 +3360,11 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction)
                int page;
                
                if (direction == EV_VIEW_FIND_NEXT)
-                       page = view->find_page + i;
+                       page = view->current_page + i;
                else
-                       page = view->find_page - i;
-
-
+                       page = view->current_page - i;          
+               page += shift;
+               
                if (page >= n_pages) {
                        page = page - n_pages;
                }
@@ -3306,7 +3374,6 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction)
                has_results = ev_document_find_page_has_results
                                (EV_DOCUMENT_FIND (view->document), page);
                if (has_results == -1) {
-                       view->find_page = page;
                        break;
                } else if (has_results == 1) {
                        ev_page_cache_set_current_page (view->page_cache, page);
@@ -3348,12 +3415,7 @@ ev_view_find_next (EvView *view)
        if (view->find_result >= n_results) {
 
                view->find_result = 0;
-               view->find_page++;
-               if (view->find_page >= n_pages) {
-                       view->find_page = 0;
-               }
-
-               jump_to_find_page (view, EV_VIEW_FIND_NEXT);
+               jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1);
                jump_to_find_result (view);
        } else {
                jump_to_find_result (view);
@@ -3378,12 +3440,7 @@ ev_view_find_previous (EvView *view)
 
        if (view->find_result < 0) {
 
-               view->find_page--;
-               if (view->find_page < 0) {
-                       view->find_page = n_pages - 1;
-               }
-
-               jump_to_find_page (view, EV_VIEW_FIND_PREV);
+               jump_to_find_page (view, EV_VIEW_FIND_PREV, -1);
                view->find_result = ev_document_find_get_n_results (find, view->current_page) - 1;
                jump_to_find_result (view);
        } else {
@@ -3392,6 +3449,12 @@ ev_view_find_previous (EvView *view)
        }
 }
 
+void ev_view_search_changed (EvView *view)
+{
+       /* search string has changed, focus on new search result */
+       view->jump_to_find_result = TRUE;
+}
+
 /*** Selections ***/
 
 /* compute_new_selection_rect/text calculates the area currently selected by
@@ -3901,11 +3964,18 @@ ev_view_next_page (EvView *view)
        g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
 
        page = ev_page_cache_get_current_page (view->page_cache);
-       page = ev_view_get_dual_page (view) ? page + 2 : page + 1;
+
+       if (view->dual_page && !view->presentation)
+               page = page + 2; 
+       else 
+               page = page + 1;
 
        if (page < ev_page_cache_get_n_pages (view->page_cache)) {
                ev_page_cache_set_current_page (view->page_cache, page);
                return TRUE;
+       } else if (ev_view_get_dual_page (view) && page == ev_page_cache_get_n_pages (view->page_cache)) {
+               ev_page_cache_set_current_page (view->page_cache, page - 1);
+               return TRUE;
        } else {
                return FALSE;
        }
@@ -3919,12 +3989,19 @@ ev_view_previous_page (EvView *view)
        g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
 
        page = ev_page_cache_get_current_page (view->page_cache);
-       page = ev_view_get_dual_page (view) ? page - 2 : page - 1;
+
+       if (view->dual_page && !view->presentation)
+               page = page - 2; 
+       else 
+               page = page - 1;
 
        if (page >= 0) {
                ev_page_cache_set_current_page (view->page_cache, page);
                return TRUE;
-       } else {
+       } else if (ev_view_get_dual_page (view) && page == -1) {
+               ev_page_cache_set_current_page (view->page_cache, 0);
+               return TRUE;
+       } else {        
                return FALSE;
        }
 }
@@ -3946,3 +4023,22 @@ ev_sizing_mode_get_type (void)
   }
   return etype;
 }
+
+GType
+ev_scroll_type_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      { EV_SCROLL_PAGE_FORWARD, "EV_SCROLL_PAGE_FORWARD", "scroll-page-forward" },
+      { EV_SCROLL_PAGE_BACKWARD, "EV_SCROLL_PAGE_BACKWARD", "scroll-page-backward" },
+      { EV_SCROLL_STEP_FORWARD, "EV_SCROLL_STEP_FORWARD", "scroll-step-forward" },
+      { EV_SCROLL_STEP_FORWARD, "EV_SCROLL_STEP_FORWARD", "scroll-step-forward" },
+      { EV_SCROLL_STEP_UP, "EV_SCROLL_STEP_UP", "scroll-step-up" },
+      { EV_SCROLL_STEP_DOWN, "EV_SCROLL_STEP_DOWN", "scroll-step-down" },
+      { 0, NULL, NULL }
+    };
+    etype = g_enum_register_static ("EvScrollType", values);
+  }
+  return etype;
+}