diff options
-rw-r--r-- | libview/ev-view.c | 77 |
1 files changed, 47 insertions, 30 deletions
diff --git a/libview/ev-view.c b/libview/ev-view.c index 2cd2a864..0c5f6973 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -4231,9 +4231,11 @@ position_caret_cursor_at_location (EvView *view, guint n_areas = 0; gint page; gint offset = -1 ; + gint first_line_offset; + gint last_line_offset = -1; gint doc_x, doc_y; EvRectangle *rect; - guint i, j; + guint i; if (!view->caret_enabled || view->rotation != 0) return FALSE; @@ -4249,29 +4251,38 @@ position_caret_cursor_at_location (EvView *view, if (!areas) return FALSE; - /* First look for the line of text at location */ - for (i = 0; i < n_areas; i++) { + i = 0; + while (i < n_areas && offset == -1) { rect = areas + i; - if (doc_y >= rect->y1 && doc_y <= rect->y2) - break; - } - - if (i == n_areas) - return FALSE; - - if (doc_x <= rect->x1) { - /* Location is before the start of the line */ - offset = i; - } else { - for (j = i; j < n_areas; j++) { - rect = areas + j; + first_line_offset = -1; + while (doc_y >= rect->y1 && doc_y <= rect->y2) { + if (first_line_offset == -1) { + if (doc_x <= rect->x1) { + /* Location is before the start of the line */ + if (last_line_offset != -1) { + EvRectangle *last = areas + last_line_offset; + gint dx1, dx2; + + /* If there's a previous line, check distances */ + + dx1 = doc_x - last->x2; + dx2 = rect->x1 - doc_x; + + if (dx1 < dx2) + offset = last_line_offset; + else + offset = i; + } else { + offset = i; + } - if (doc_y < rect->y1) { - /* Location is after the end of the line */ - offset = j; - break; + last_line_offset = i + 1; + break; + } + first_line_offset = i; } + last_line_offset = i + 1; if (doc_x >= rect->x1 && doc_x <= rect->x2) { /* Location is inside the line. Position the caret before @@ -4279,20 +4290,26 @@ position_caret_cursor_at_location (EvView *view, * falls within the left or right half of the bounding box. */ if (doc_x <= rect->x1 + (rect->x2 - rect->x1) / 2) - offset = j; + offset = i; else - offset = j + 1; + offset = i + 1; break; } + i++; + rect = areas + i; } - } - if (offset == -1) { - /* This is the last line and loocation is after the end of the line */ - offset = n_areas; + if (first_line_offset == -1) + i++; } + if (last_line_offset == -1) + return FALSE; + + if (offset == -1) + offset = last_line_offset; + if (view->cursor_offset != offset || view->cursor_page != page) { view->cursor_offset = offset; view->cursor_page = page; @@ -5170,7 +5187,6 @@ cursor_backward_line (EvView *view) PangoLogAttr *log_attrs = NULL; gulong n_attrs; - /* FIXME: Keep the line offset when moving between lines */ if (!cursor_go_to_line_start (view)) return FALSE; @@ -5181,7 +5197,8 @@ cursor_backward_line (EvView *view) do { view->cursor_offset--; - } while (view->cursor_offset >= 0 && !log_attrs[view->cursor_offset].is_cursor_position); + } while (view->cursor_offset >= 0 && !log_attrs[view->cursor_offset].is_mandatory_break); + view->cursor_offset = MAX (0, view->cursor_offset); return TRUE; } @@ -5219,7 +5236,6 @@ cursor_forward_line (EvView *view) PangoLogAttr *log_attrs = NULL; gulong n_attrs; - /* FIXME: Keep the line offset when moving between lines */ if (!cursor_go_to_line_end (view)) return FALSE; @@ -5324,7 +5340,8 @@ ev_view_move_cursor (EvView *view, return TRUE; if (step == GTK_MOVEMENT_DISPLAY_LINES) { - position_caret_cursor_at_location (view, view->cursor_line_offset, + position_caret_cursor_at_location (view, + MAX (rect.x, view->cursor_line_offset), rect.y + (rect.height / 2)); } else { view->cursor_line_offset = rect.x; |