From c0d8b71bc5d4b404727b03053d27eaf35e7309b7 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 21 Dec 2009 11:29:12 -0500 Subject: [PATCH] Improve selection/arrow key behaviour in GtkTextView This patch makes the text view behave more similar to entries. Patch by Michael Natterer, see bug 50942 --- gtk/gtktextview.c | 52 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index f7f3218253..9a0f05bb84 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -337,6 +337,7 @@ static void gtk_text_view_paste_done_handler (GtkTextBuffer *buffer, static void gtk_text_view_get_cursor_location (GtkTextView *text_view, GdkRectangle *pos); static void gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view, + GtkTextIter *cursor, gint *x, gint *y); static void gtk_text_view_set_virtual_cursor_pos (GtkTextView *text_view, @@ -5035,6 +5036,7 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view, { GtkTextIter insert; GtkTextIter newplace; + gboolean cancel_selection = FALSE; gint cursor_x_pos = 0; GtkDirectionType leave_direction = -1; @@ -5111,20 +5113,46 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view, gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, gtk_text_buffer_get_insert (get_buffer (text_view))); + + if (! extend_selection) + { + GtkTextIter sel_bound; + + gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &sel_bound, + gtk_text_buffer_get_selection_bound (get_buffer (text_view))); + + /* if we move forward, assume the cursor is at the end of the selection; + * if we move backward, assume the cursor is at the start + */ + if (count > 0) + gtk_text_iter_order (&sel_bound, &insert); + else + gtk_text_iter_order (&insert, &sel_bound); + + /* if we actually have a selection, just move *to* the beginning/end + * of the selection and not *from* there on LOGICAL_POSITIONS + * and VISUAL_POSITIONS movement + */ + if (! gtk_text_iter_equal (&sel_bound, &insert)) + cancel_selection = TRUE; + } + newplace = insert; if (step == GTK_MOVEMENT_DISPLAY_LINES) - gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, NULL); + gtk_text_view_get_virtual_cursor_pos (text_view, &insert, &cursor_x_pos, NULL); switch (step) { case GTK_MOVEMENT_LOGICAL_POSITIONS: - gtk_text_iter_forward_visible_cursor_positions (&newplace, count); + if (! cancel_selection) + gtk_text_iter_forward_visible_cursor_positions (&newplace, count); break; case GTK_MOVEMENT_VISUAL_POSITIONS: - gtk_text_layout_move_iter_visually (text_view->layout, - &newplace, count); + if (! cancel_selection) + gtk_text_layout_move_iter_visually (text_view->layout, + &newplace, count); break; case GTK_MOVEMENT_WORDS: @@ -5233,7 +5261,7 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view, g_signal_emit_by_name (text_view, "move-focus", leave_direction); } } - else + else if (! cancel_selection) { gtk_widget_error_bell (GTK_WIDGET (text_view)); } @@ -5386,7 +5414,7 @@ gtk_text_view_scroll_pages (GtkTextView *text_view, } else { - gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos); + gtk_text_view_get_virtual_cursor_pos (text_view, NULL, &cursor_x_pos, &cursor_y_pos); oldval = adj->value; newval = adj->value; @@ -5467,7 +5495,7 @@ gtk_text_view_scroll_hpages (GtkTextView *text_view, } else { - gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos); + gtk_text_view_get_virtual_cursor_pos (text_view, NULL, &cursor_x_pos, &cursor_y_pos); oldval = adj->value; newval = adj->value; @@ -7484,14 +7512,22 @@ gtk_text_view_get_cursor_location (GtkTextView *text_view, static void gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view, + GtkTextIter *cursor, gint *x, gint *y) { + GtkTextIter insert; GdkRectangle pos; + if (cursor) + insert = *cursor; + else + gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert, + gtk_text_buffer_get_insert (get_buffer (text_view))); + if ((x && text_view->virtual_cursor_x == -1) || (y && text_view->virtual_cursor_y == -1)) - gtk_text_view_get_cursor_location (text_view, &pos); + gtk_text_layout_get_cursor_locations (text_view->layout, &insert, &pos, NULL); if (x) {