]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-view.c
vi.po: Updated Vietnamese translation.
[evince.git] / shell / ev-view.c
index 29c87a2914ffd108285436c5203b7496d71b54bd..6bc088b43a4013751db3018c8b10c5cf972bc495 100644 (file)
@@ -78,6 +78,7 @@ static guint signals[N_SIGNALS];
 
 typedef enum {
        EV_VIEW_CURSOR_NORMAL,
+       EV_VIEW_CURSOR_IBEAM,
        EV_VIEW_CURSOR_LINK,
        EV_VIEW_CURSOR_WAIT,
        EV_VIEW_CURSOR_HIDDEN,
@@ -148,6 +149,7 @@ struct _EvView {
        int find_result;
        int spacing;
 
+       int rotation;
        double scale;
 
        gboolean continuous;
@@ -257,6 +259,8 @@ static gboolean   ev_view_motion_notify_event                (GtkWidget
                                                              GdkEventMotion     *event);
 static gboolean   ev_view_button_release_event               (GtkWidget          *widget,
                                                              GdkEventButton     *event);
+static gboolean   ev_view_leave_notify_event                 (GtkWidget          *widget,
+                                                             GdkEventCrossing   *event);
 
 /*** Drawing ***/
 static guint32    ev_gdk_color_to_rgb                        (const GdkColor     *color);
@@ -350,7 +354,8 @@ static void       jump_to_find_page                          (EvView
 
 /*** Selection ***/
 static void       compute_selections                         (EvView             *view,
-                                                             GdkRectangle       *view_rect);
+                                                             GdkPoint           *start,
+                                                             GdkPoint           *stop);
 static void       clear_selection                            (EvView             *view);
 static char*      get_selected_text                          (EvView             *ev_view);
 static void       ev_view_primary_get_cb                     (GtkClipboard       *clipboard,
@@ -370,6 +375,10 @@ scroll_to_current_page (EvView *view, GtkOrientation orientation)
        GdkRectangle page_area;
        GtkBorder border;
 
+       if (view->document == NULL) {
+               return;
+       }
+
        get_page_extents (view, view->current_page, &page_area, &border);
 
        if (orientation == GTK_ORIENTATION_VERTICAL) {
@@ -523,6 +532,7 @@ view_update_range_and_current_page (EvView *view)
        ev_pixbuf_cache_set_page_range (view->pixbuf_cache,
                                        view->start_page,
                                        view->end_page,
+                                       view->rotation,
                                        view->scale,
                                        view->selection_info.selections);
 }
@@ -697,6 +707,8 @@ ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect)
        GtkAdjustment *adjustment;
        int value;
 
+       view->pending_scroll = SCROLL_TO_KEEP_POSITION;
+
        adjustment = view->vadjustment;
 
        if (rect->y < adjustment->value) {
@@ -737,25 +749,25 @@ compute_border (EvView *view, int width, int height, GtkBorder *border)
        }
 }
 
-static void       get_page_y_offset                          (EvView *view,
-                                                             int page,
-                                                             double zoom,
-                                                             int *y_offset)
+static void
+get_page_y_offset (EvView *view, int page, double zoom, int *y_offset)
 {
        int max_width, offset;
        GtkBorder border;
 
        g_return_if_fail (y_offset != NULL);
 
-       ev_page_cache_get_max_width (view->page_cache, zoom, &max_width);
+       ev_page_cache_get_max_width (view->page_cache, view->rotation, zoom, &max_width);
 
        compute_border (view, max_width, max_width, &border);
 
        if (view->dual_page) {
-               ev_page_cache_get_height_to_page (view->page_cache, page, zoom, NULL, &offset);
+               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);
        } else {
-               ev_page_cache_get_height_to_page (view->page_cache, page, zoom, &offset, NULL);
+               ev_page_cache_get_height_to_page (view->page_cache, page,
+                                                 view->rotation, zoom, &offset, NULL);
                offset += (page + 1) * view->spacing + page * (border.top + border.bottom);
        }
 
@@ -776,6 +788,7 @@ get_page_extents (EvView       *view,
 
        /* Get the size of the page */
        ev_page_cache_get_size (view->page_cache, page,
+                               view->rotation,
                                view->scale,
                                &width, &height);
        compute_border (view, width, height, border);
@@ -789,7 +802,8 @@ get_page_extents (EvView       *view,
                gint max_width;
                gint x, y;
 
-               ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+               ev_page_cache_get_max_width (view->page_cache, view->scale,
+                                            view->rotation, &max_width);
                max_width = max_width + border->left + border->right;
                /* Get the location of the bounding box */
                if (view->dual_page) {
@@ -821,6 +835,7 @@ get_page_extents (EvView       *view,
                        if (other_page < ev_page_cache_get_n_pages (view->page_cache)) {
                                ev_page_cache_get_size (view->page_cache,
                                                        other_page,
+                                                       view->rotation,
                                                        view->scale,
                                                        &width_2, &height_2);
                                if (width_2 > width)
@@ -862,16 +877,27 @@ get_page_extents (EvView       *view,
        return TRUE;
 }
 
+static void
+view_point_to_doc_point (EvView *view,
+                        GdkPoint *view_point,
+                        GdkRectangle *page_area,
+                        double  *doc_point_x,
+                        double  *doc_point_y)
+{
+       *doc_point_x = (double) (view_point->x - page_area->x) / view->scale;
+       *doc_point_y = (double) (view_point->y - page_area->y) / view->scale;
+}
+
 static void
 view_rect_to_doc_rect (EvView *view,
                       GdkRectangle *view_rect,
                       GdkRectangle *page_area,
                       EvRectangle  *doc_rect)
 {
-       doc_rect->x1 = floor ((view_rect->x - page_area->x) / view->scale);
-       doc_rect->y1 = floor ((view_rect->y - page_area->y) / view->scale);
-       doc_rect->x2 = doc_rect->x1 + ceil (view_rect->width / view->scale);
-       doc_rect->y2 = doc_rect->y1 + ceil (view_rect->height / view->scale);
+       doc_rect->x1 = (double) (view_rect->x - page_area->x) / view->scale;
+       doc_rect->y1 = (double) (view_rect->y - page_area->y) / view->scale;
+       doc_rect->x2 = doc_rect->x1 + (double) view_rect->width / view->scale;
+       doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale;
 }
 
 static void
@@ -882,16 +908,44 @@ doc_rect_to_view_rect (EvView       *view,
 {
        GdkRectangle page_area;
        GtkBorder border;
+       double x, y, w, h;
        int width, height;
 
+       ev_page_cache_get_size (view->page_cache, page,
+                               view->rotation,
+                               1.0,
+                               &width, &height);
+
+       if (view->rotation == 0) {
+               x = doc_rect->x1;
+               y = doc_rect->y1;
+               w = doc_rect->x2 - doc_rect->x1;
+               h = doc_rect->y2 - doc_rect->y1;
+       } else if (view->rotation == 90) {
+               x = width - doc_rect->y2;
+               y = doc_rect->x1;
+               w = doc_rect->y2 - doc_rect->y1;
+               h = doc_rect->x2 - doc_rect->x1;
+       } else if (view->rotation == 180) {
+               x = width - doc_rect->x2;
+               y = height - doc_rect->y2;
+               w = doc_rect->x2 - doc_rect->x1;
+               h = doc_rect->y2 - doc_rect->y1;
+       } else if (view->rotation == 270) {
+               x = doc_rect->y1;
+               y = height - doc_rect->x2;
+               w = doc_rect->y2 - doc_rect->y1;
+               h = doc_rect->x2 - doc_rect->x1;
+       } else {
+               g_assert_not_reached ();
+       }
+
        get_page_extents (view, page, &page_area, &border);
 
-       width = doc_rect->x2 - doc_rect->x1;
-       height = doc_rect->y2 - doc_rect->y1;
-       view_rect->x = floor (doc_rect->x1 * view->scale) + page_area.x;
-       view_rect->y = floor (doc_rect->y1 * view->scale) + page_area.y;
-       view_rect->width = ceil (width * view->scale);
-       view_rect->height = ceil (height * view->scale);
+       view_rect->x = x * view->scale + page_area.x;
+       view_rect->y = y * view->scale + page_area.y;
+       view_rect->width = w * view->scale;
+       view_rect->height = h * view->scale;
 }
 
 static void
@@ -932,6 +986,28 @@ find_page_at_location (EvView  *view,
        *page = -1;
 }
 
+static gboolean
+location_in_text (EvView  *view,
+                 gdouble  x,
+                 gdouble  y)
+{
+       GdkRegion *region;
+       gint page = -1;
+       gint x_offset = 0, y_offset = 0;
+
+       find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
+
+       if (page == -1)
+               return FALSE;
+       
+       region = ev_pixbuf_cache_get_text_mapping (view->pixbuf_cache, page);
+
+       if (region)
+               return gdk_region_point_in (region, x_offset / view->scale, y_offset / view->scale);
+       else
+               return FALSE;
+}
+
 /*** Hyperref ***/
 static EvLink *
 get_link_at_location (EvView  *view,
@@ -1019,7 +1095,8 @@ ev_view_size_request_continuous_dual_page (EvView         *view,
        gint n_pages;
        GtkBorder border;
 
-       ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+       ev_page_cache_get_max_width (view->page_cache, view->rotation,
+                                    view->scale, &max_width);
        compute_border (view, max_width, max_width, &border);
 
        n_pages = ev_page_cache_get_n_pages (view->page_cache) + 1;
@@ -1046,7 +1123,8 @@ ev_view_size_request_continuous (EvView         *view,
        GtkBorder border;
 
 
-       ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width);
+       ev_page_cache_get_max_width (view->page_cache, view->rotation,
+                                    view->scale, &max_width);
        n_pages = ev_page_cache_get_n_pages (view->page_cache);
        compute_border (view, max_width, max_width, &border);
 
@@ -1073,12 +1151,14 @@ ev_view_size_request_dual_page (EvView         *view,
        /* Find the largest of the two. */
        ev_page_cache_get_size (view->page_cache,
                                view->current_page,
+                               view->rotation,
                                view->scale,
                                &width, &height);
        if (view->current_page + 1 < ev_page_cache_get_n_pages (view->page_cache)) {
                gint width_2, height_2;
                ev_page_cache_get_size (view->page_cache,
                                        view->current_page + 1,
+                                       view->rotation,
                                        view->scale,
                                        &width_2, &height_2);
                if (width_2 > width) {
@@ -1110,6 +1190,7 @@ ev_view_size_request_single_page (EvView         *view,
 
        ev_page_cache_get_size (view->page_cache,
                                view->current_page,
+                               view->rotation,
                                view->scale,
                                &width, &height);
        compute_border (view, width, height, &border);
@@ -1324,8 +1405,8 @@ ev_view_button_press_event (GtkWidget      *widget,
                                gtk_widget_queue_draw (widget);
                        }
 
-                       view->selection_info.start.x = event->x;
-                       view->selection_info.start.y = event->y;
+                       view->selection_info.start.x = event->x + view->scroll_x;
+                       view->selection_info.start.y = event->y + view->scroll_y;
                        return TRUE;
                case 2:
                        /* use root coordinates as reference point because
@@ -1353,15 +1434,12 @@ ev_view_motion_notify_event (GtkWidget      *widget,
                return FALSE;
 
        if (view->pressed_button == 1) {
-               GdkRectangle selection;
-               view->selection_info.in_selection = TRUE;
-
-               selection.x = MIN (view->selection_info.start.x, event->x) + view->scroll_x;
-               selection.y = MIN (view->selection_info.start.y, event->y) + view->scroll_y;
-               selection.width = ABS (view->selection_info.start.x - event->x) + 1;
-               selection.height = ABS (view->selection_info.start.y - event->y) + 1;
+               GdkPoint point;
 
-               compute_selections (view, &selection);
+               view->selection_info.in_selection = TRUE;
+               point.x = event->x + view->scroll_x;
+               point.y = event->y + view->scroll_y;
+               compute_selections (view, &view->selection_info.start, &point);
 
                return TRUE;
        } else if (view->pressed_button == 2) {
@@ -1411,11 +1489,13 @@ ev_view_motion_notify_event (GtkWidget      *widget,
                        ev_view_set_status (view, msg);
                        ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
                        g_free (msg);
+               } else if (location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y)) {
+                       ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM);
                } else {
                        ev_view_set_status (view, NULL);
-                       if (view->cursor == EV_VIEW_CURSOR_LINK) {
+                       if (view->cursor == EV_VIEW_CURSOR_LINK ||
+                           view->cursor == EV_VIEW_CURSOR_IBEAM)
                                ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
-                       }
                }
                return TRUE;
        }
@@ -1450,6 +1530,20 @@ ev_view_button_release_event (GtkWidget      *widget,
        return FALSE;
 }
 
+static gboolean
+ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing   *event)
+{
+       EvView *view = EV_VIEW (widget);
+    
+       ev_view_set_status (view, NULL);
+
+       if (view->cursor == EV_VIEW_CURSOR_LINK ||
+           view->cursor == EV_VIEW_CURSOR_IBEAM)
+               ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
+
+       return FALSE;
+}
+
 /*** Drawing ***/
 
 static guint32
@@ -1549,7 +1643,8 @@ draw_one_page (EvView          *view,
 
        selection = find_selection_for_page (view, page);
        ev_page_cache_get_size (view->page_cache,
-                               page, view->scale,
+                               page, view->rotation,
+                               view->scale,
                                &width, &height);
        /* Render the document itself */
        real_page_area = *page_area;
@@ -1756,6 +1851,7 @@ ev_view_class_init (EvViewClass *class)
        widget_class->realize = ev_view_realize;
        widget_class->unrealize = ev_view_unrealize;
        widget_class->scroll_event = ev_view_scroll_event;
+       widget_class->leave_notify_event = ev_view_leave_notify_event;
        gtk_object_class->destroy = ev_view_destroy;
 
        class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
@@ -1984,8 +2080,9 @@ clear_caches (EvView *view)
                view->pixbuf_cache = NULL;
        }
 
-       if (view->document) {
-               ev_page_cache_clear (view->document);
+       if (view->page_cache) {
+               g_object_unref (view->page_cache);
+               view->page_cache = NULL;
        }
 }
 
@@ -2061,6 +2158,14 @@ ev_view_get_zoom (EvView *view)
        return view->scale;
 }
 
+gboolean
+ev_view_get_continuous (EvView *view)
+{
+       g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
+
+       return view->continuous;
+}
+
 void
 ev_view_set_continuous (EvView   *view,
                        gboolean  continuous)
@@ -2078,6 +2183,14 @@ ev_view_set_continuous (EvView   *view,
        g_object_notify (G_OBJECT (view), "continuous");
 }
 
+gboolean
+ev_view_get_dual_page (EvView *view)
+{
+       g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
+
+       return view->dual_page;
+}
+
 void
 ev_view_set_dual_page (EvView   *view,
                       gboolean  dual_page)
@@ -2107,11 +2220,12 @@ ev_view_set_fullscreen (EvView   *view,
 
        fullscreen = fullscreen != FALSE;
 
-       if (view->fullscreen != fullscreen) {
-               view->fullscreen = fullscreen;
-               gtk_widget_queue_resize (GTK_WIDGET (view));
-       }
-
+       if (view->fullscreen == fullscreen) 
+               return;
+               
+       view->fullscreen = fullscreen;
+       gtk_widget_queue_resize (GTK_WIDGET (view));
+       
        g_object_notify (G_OBJECT (view), "fullscreen");
 }
 
@@ -2135,7 +2249,9 @@ ev_view_set_presentation (EvView   *view,
                return;
 
        view->presentation = presentation;
+       view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
        gtk_widget_queue_resize (GTK_WIDGET (view));
+
        if (GTK_WIDGET_REALIZED (view)) {
                if (view->presentation)
                        gdk_window_set_background (GTK_WIDGET(view)->window,
@@ -2211,13 +2327,9 @@ ev_view_zoom_out (EvView *view)
 }
 
 static void
-ev_view_set_orientation (EvView         *view,
-                        EvOrientation   orientation)
+ev_view_set_rotation (EvView *view, int rotation)
 {
-       ev_document_set_orientation (view->document, orientation);
-
-       clear_caches (view);
-       setup_caches (view);
+       view->rotation = rotation;
 
        gtk_widget_queue_resize (GTK_WIDGET (view));
 }
@@ -2225,37 +2337,25 @@ ev_view_set_orientation (EvView         *view,
 void
 ev_view_rotate_right (EvView *view)
 {
-       EvOrientation orientation, new_orientation;
+       int rotation = view->rotation + 90;
 
-       orientation = ev_document_get_orientation (view->document);
-       if (orientation == EV_ORIENTATION_PORTRAIT) {
-               new_orientation = EV_ORIENTATION_LANDSCAPE;
-       } else if (orientation == EV_ORIENTATION_LANDSCAPE) {
-               new_orientation = EV_ORIENTATION_UPSIDEDOWN;
-       } else if (orientation == EV_ORIENTATION_UPSIDEDOWN) {
-               new_orientation = EV_ORIENTATION_SEASCAPE;
-       } else {
-               new_orientation = EV_ORIENTATION_PORTRAIT;
+       if (rotation >= 360) {
+               rotation -= 360;
        }
-       ev_view_set_orientation (view, new_orientation);
+
+       ev_view_set_rotation (view, rotation);
 }
 
 void
 ev_view_rotate_left (EvView *view)
 {
-       EvOrientation orientation, new_orientation;
+       int rotation = view->rotation - 90;
 
-       orientation = ev_document_get_orientation (view->document);
-       if (orientation == EV_ORIENTATION_PORTRAIT) {
-               new_orientation = EV_ORIENTATION_SEASCAPE;
-       } else if (orientation == EV_ORIENTATION_SEASCAPE) {
-               new_orientation = EV_ORIENTATION_UPSIDEDOWN;
-       } else if (orientation == EV_ORIENTATION_UPSIDEDOWN) {
-               new_orientation = EV_ORIENTATION_LANDSCAPE;
-       } else {
-               new_orientation = EV_ORIENTATION_PORTRAIT;
+       if (rotation < 0) {
+               rotation += 360;
        }
-       ev_view_set_orientation (view, new_orientation);
+
+       ev_view_set_rotation (view, rotation);
 }
 
 static double
@@ -2308,6 +2408,7 @@ ev_view_zoom_for_size_presentation (EvView *view,
 
        ev_page_cache_get_size (view->page_cache,
                                view->current_page,
+                               view->rotation,
                                1.0,
                                &doc_width,
                                &doc_height);
@@ -2327,9 +2428,11 @@ ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
        gdouble scale;
 
        ev_page_cache_get_max_width (view->page_cache,
+                                    view->rotation,
                                     1.0,
                                     &doc_width);
        ev_page_cache_get_max_height (view->page_cache,
+                                     view->rotation,
                                      1.0,
                                      &doc_height);
        compute_border (view, doc_width, doc_height, &border);
@@ -2363,9 +2466,11 @@ ev_view_zoom_for_size_continuous (EvView *view,
        gdouble scale;
 
        ev_page_cache_get_max_width (view->page_cache,
+                                    view->rotation,
                                     1.0,
                                     &doc_width);
        ev_page_cache_get_max_height (view->page_cache,
+                                     view->rotation,
                                      1.0,
                                      &doc_height);
        compute_border (view, doc_width, doc_height, &border);
@@ -2403,6 +2508,7 @@ ev_view_zoom_for_size_dual_page (EvView *view,
        /* Find the largest of the two. */
        ev_page_cache_get_size (view->page_cache,
                                view->current_page,
+                               view->rotation,
                                1.0,
                                &doc_width, &doc_height);
 
@@ -2410,6 +2516,7 @@ ev_view_zoom_for_size_dual_page (EvView *view,
                gint width_2, height_2;
                ev_page_cache_get_size (view->page_cache,
                                        other_page,
+                                       view->rotation,
                                        1.0,
                                        &width_2, &height_2);
                if (width_2 > doc_width)
@@ -2446,6 +2553,7 @@ ev_view_zoom_for_size_single_page (EvView *view,
 
        ev_page_cache_get_size (view->page_cache,
                                view->current_page,
+                               view->rotation,
                                1.0,
                                &doc_width,
                                &doc_height);
@@ -2698,23 +2806,30 @@ ev_view_find_previous (EvView *view)
  */
 static GList *
 compute_new_selection_rect (EvView       *view,
-                           GdkRectangle *view_rect)
+                           GdkPoint     *start,
+                           GdkPoint     *stop)
 {
+       GdkRectangle view_rect;
        int n_pages, i;
        GList *list = NULL;
 
        g_assert (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE);
+       
+       view_rect.x = MIN (start->x, stop->x);
+       view_rect.y = MIN (start->y, stop->y);
+       view_rect.width = MAX (start->x, stop->x) - view_rect.x;
+       view_rect.width = MAX (start->y, stop->y) - view_rect.y;
 
        n_pages = ev_page_cache_get_n_pages (view->page_cache);
 
        for (i = 0; i < n_pages; i++) {
                GdkRectangle page_area;
                GtkBorder border;
-
+               
                if (get_page_extents (view, i, &page_area, &border)) {
                        GdkRectangle overlap;
 
-                       if (gdk_rectangle_intersect (&page_area, view_rect, &overlap)) {
+                       if (gdk_rectangle_intersect (&page_area, &view_rect, &overlap)) {
                                EvViewSelection *selection;
 
                                selection = g_new0 (EvViewSelection, 1);
@@ -2730,82 +2845,93 @@ compute_new_selection_rect (EvView       *view,
        return list;
 }
 
+static gboolean
+gdk_rectangle_point_in (GdkRectangle *rectangle,
+                       GdkPoint     *point)
+{
+       return rectangle->x <= point->x &&
+               rectangle->y <= point->y &&
+               point->x < rectangle->x + rectangle->width &&
+               point->y < rectangle->y + rectangle->height;
+}
+
 static GList *
-compute_new_selection_text (EvView       *view,
-                           GdkRectangle *view_rect)
+compute_new_selection_text (EvView   *view,
+                           GdkPoint *start,
+                           GdkPoint *stop)
 {
-       int n_pages, i;
+       int n_pages, i, first, last;
        GList *list = NULL;
-       EvViewSelection *first_selection = NULL;
-       EvViewSelection *last_selection = NULL;
+       EvViewSelection *selection;
        gint width, height;
 
        g_assert (view->selection_mode == EV_VIEW_SELECTION_TEXT);
 
        n_pages = ev_page_cache_get_n_pages (view->page_cache);
 
-       /* We get the two edge pages */
+       /* First figure out the range of pages the selection
+        * affects. */
+       first = n_pages;
+       last = 0;
        for (i = 0; i < n_pages; i++) {
                GdkRectangle page_area;
                GtkBorder border;
-
-               if (get_page_extents (view, i, &page_area, &border)) {
-                       GdkRectangle overlap;
-
-                       if (gdk_rectangle_intersect (&page_area, view_rect, &overlap)) {
-                               EvViewSelection *selection;
-
-                               if (first_selection == NULL) {
-                                       first_selection = g_new0 (EvViewSelection, 1);
-                                       selection = first_selection;
-                               } else if (last_selection == NULL) {
-                                       last_selection = g_new0 (EvViewSelection, 1);
-                                       selection = last_selection;
-                               } else {
-                                       selection = last_selection;
-                               }
-
-                               selection->page = i;
-                               view_rect_to_doc_rect (view, &overlap, &page_area,
-                                                      &(selection->rect));
-                       }
+               
+               get_page_extents (view, i, &page_area, &border);
+               if (gdk_rectangle_point_in (&page_area, start) || 
+                   gdk_rectangle_point_in (&page_area, stop)) {
+                       if (first == n_pages)
+                               first = i;
+                       last = i;
                }
+
        }
 
-       /* No overlap */
-       if (first_selection == NULL)
-               return NULL;
 
-       /* only one selection.  Return a page of it */
-       if (last_selection == NULL)
-               return g_list_append (NULL, first_selection);
 
-       /*clean up the selections;
-        */
-       ev_page_cache_get_size (view->page_cache, first_selection->page,
-                               1.0, &width, &height);
-       first_selection->rect.x2 = width;
-       first_selection->rect.y2 = height;
-       list = g_list_append (NULL, first_selection);
-
-       /* Add all the intervening pages */
-       for (i = first_selection->page + 1; i < last_selection->page; i++) {
-               EvViewSelection *selection;
+       /* Now create a list of EvViewSelection's for the affected
+        * pages.  This could be an empty list, a list of just one
+        * page or a number of pages.*/
+       for (i = first; i < last + 1; i++) {
+               GdkRectangle page_area;
+               GtkBorder border;
+               GdkPoint *point;
 
-               selection = g_new0 (EvViewSelection, 1);
-               selection->page = i;
                ev_page_cache_get_size (view->page_cache, i,
+                                       view->rotation,
                                        1.0, &width, &height);
+
+               selection = g_new0 (EvViewSelection, 1);
+               selection->page = i;
                selection->rect.x1 = selection->rect.y1 = 0;
                selection->rect.x2 = width;
                selection->rect.y2 = height;
-               g_list_append (list, selection);
-       }
 
-       /* Clean up the last page */
-       last_selection->rect.x1 = 0;
-       last_selection->rect.y1 = 0;
-       list = g_list_append (list, last_selection);
+               get_page_extents (view, i, &page_area, &border);
+
+               if (gdk_rectangle_point_in (&page_area, start))
+                       point = start;
+               else
+                       point = stop;
+
+               if (i == first)
+                       view_point_to_doc_point (view, point, &page_area,
+                                                &selection->rect.x1,
+                                                &selection->rect.y1);
+
+               /* If the selection is contained within just one page,
+                * make sure we don't write 'start' into both points
+                * in selection->rect. */
+               if (first == last)
+                       point = stop;
+
+               if (i == last)
+                       view_point_to_doc_point (view, point, &page_area,
+                                                &selection->rect.x2,
+                                                &selection->rect.y2);
+
+               list = g_list_append (list, selection);
+       }
 
        return list;
 }
@@ -2827,15 +2953,16 @@ merge_selection_region (EvView *view,
 }
 
 static void
-compute_selections (EvView       *view,
-                   GdkRectangle *view_rect)
+compute_selections (EvView   *view,
+                   GdkPoint *start,
+                   GdkPoint *stop)
 {
        GList *list;
 
        if (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE)
-               list = compute_new_selection_rect (view, view_rect);
+               list = compute_new_selection_rect (view, start, stop);
        else
-               list = compute_new_selection_text (view, view_rect);
+               list = compute_new_selection_text (view, start, stop);
        merge_selection_region (view, list);
 }
 
@@ -2869,6 +2996,7 @@ ev_view_select_all (EvView *view)
                EvViewSelection *selection;
 
                ev_page_cache_get_size (view->page_cache,
+                                       view->rotation,
                                        i, 1.0, &width, &height);
 
                selection = g_new0 (EvViewSelection, 1);
@@ -3009,6 +3137,9 @@ ev_view_set_cursor (EvView *view, EvViewCursor new_cursor)
                case EV_VIEW_CURSOR_NORMAL:
                        gdk_window_set_cursor (widget->window, NULL);
                        break;
+               case EV_VIEW_CURSOR_IBEAM:
+                       cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+                       break;
                case EV_VIEW_CURSOR_LINK:
                        cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
                        break;