[gtksourceview/gnome-3-24] move-lines: fix bug with trailing newline
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/gnome-3-24] move-lines: fix bug with trailing newline
- Date: Thu, 30 Mar 2017 15:41:40 +0000 (UTC)
commit 9ba505cf1bbc7c2a77554b0a93168312ae1b78e6
Author: Sébastien Wilmet <swilmet gnome org>
Date: Thu Mar 30 15:42:33 2017 +0200
move-lines: fix bug with trailing newline
https://bugzilla.gnome.org/show_bug.cgi?id=624963
gtksourceview/gtksourceview.c | 139 +++++++++++++++++++++++++---------------
testsuite/test-view.c | 8 +-
2 files changed, 91 insertions(+), 56 deletions(-)
---
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index 8bb541d..b89245d 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -3737,6 +3737,45 @@ gtk_source_view_move_words (GtkSourceView *view,
g_free (new_text);
}
+static gboolean
+buffer_contains_trailing_newline (GtkTextBuffer *buffer)
+{
+ GtkTextIter iter;
+ gunichar ch;
+
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+ gtk_text_iter_backward_char (&iter);
+ ch = gtk_text_iter_get_char (&iter);
+
+ return (ch == '\n' || ch == '\r');
+}
+
+/* FIXME could be a function of GtkSourceBuffer, it's also useful for the
+ * FileLoader.
+ */
+static void
+remove_trailing_newline (GtkTextBuffer *buffer)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ start = end;
+
+ gtk_text_iter_set_line_offset (&start, 0);
+
+ if (gtk_text_iter_ends_line (&start) &&
+ gtk_text_iter_backward_line (&start))
+ {
+ if (!gtk_text_iter_ends_line (&start))
+ {
+ gtk_text_iter_forward_to_line_end (&start);
+ }
+
+ gtk_text_buffer_delete (buffer, &start, &end);
+ }
+}
+
static void
gtk_source_view_move_lines (GtkSourceView *view,
gboolean copy,
@@ -3745,9 +3784,12 @@ gtk_source_view_move_lines (GtkSourceView *view,
GtkTextBuffer *buffer;
GtkTextIter start;
GtkTextIter end;
- GtkTextMark *mark;
- gboolean down;
+ GtkTextIter insert_pos;
+ GtkTextMark *start_mark;
+ GtkTextMark *end_mark;
gchar *text;
+ gboolean initially_contains_trailing_newline;
+ gboolean down;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
@@ -3765,7 +3807,7 @@ gtk_source_view_move_lines (GtkSourceView *view,
/* Get the entire lines, including the paragraph terminator. */
gtk_text_iter_set_line_offset (&start, 0);
if (!gtk_text_iter_starts_line (&end) ||
- gtk_text_iter_get_line (&start) == gtk_text_iter_get_line (&end))
+ gtk_text_iter_get_line (&start) == gtk_text_iter_get_line (&end))
{
gtk_text_iter_forward_line (&end);
}
@@ -3773,34 +3815,38 @@ gtk_source_view_move_lines (GtkSourceView *view,
if ((!down && gtk_text_iter_is_start (&start)) ||
(down && gtk_text_iter_is_end (&end)))
{
+ /* Nothing to do, and the undo/redo history must remain
+ * unchanged.
+ */
return;
}
- text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
-
- /* First special case) We are moving up the last line
- * of the buffer, check if buffer ends with a paragraph
- * delimiter otherwise append a \n ourselves.
- */
- if (gtk_text_iter_is_end (&end))
- {
- GtkTextIter iter;
- iter = end;
+ start_mark = gtk_text_buffer_create_mark (buffer, NULL, &start, TRUE);
+ end_mark = gtk_text_buffer_create_mark (buffer, NULL, &end, FALSE);
- gtk_text_iter_set_line_offset (&iter, 0);
- if (!gtk_text_iter_ends_line (&iter) &&
- !gtk_text_iter_forward_to_line_end (&iter))
- {
- gchar *tmp;
+ gtk_text_buffer_begin_user_action (buffer);
- tmp = g_strdup_printf ("%s\n", text);
+ initially_contains_trailing_newline = buffer_contains_trailing_newline (buffer);
- g_free (text);
- text = tmp;
- }
+ if (!initially_contains_trailing_newline)
+ {
+ /* Insert a trailing newline. */
+ gtk_text_buffer_get_end_iter (buffer, &end);
+ gtk_text_buffer_insert (buffer, &end, "\n", -1);
}
- gtk_text_buffer_begin_user_action (buffer);
+ /* At this point all lines finish with a newline or carriage return, so
+ * there are no special cases for the last line.
+ */
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
+ gtk_text_buffer_delete_mark (buffer, start_mark);
+ gtk_text_buffer_delete_mark (buffer, end_mark);
+ start_mark = NULL;
+ end_mark = NULL;
+
+ text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
if (!copy)
{
@@ -3809,46 +3855,35 @@ gtk_source_view_move_lines (GtkSourceView *view,
if (down)
{
- gtk_text_iter_forward_line (&end);
-
- /* Second special case) We are moving down the last-but-one line
- * of the buffer, check if buffer ends with a paragraph
- * delimiter otherwise prepend a \n ourselves.
- */
- if (gtk_text_iter_is_end (&end))
- {
- GtkTextIter iter;
- iter = end;
-
- gtk_text_iter_set_line_offset (&iter, 0);
- if (!gtk_text_iter_ends_line (&iter) &&
- !gtk_text_iter_forward_to_line_end (&iter))
- {
- gtk_text_buffer_insert (buffer, &end, "\n", -1);
- }
- }
+ insert_pos = end;
+ gtk_text_iter_forward_line (&insert_pos);
}
else
{
- gtk_text_iter_backward_line (&end);
+ insert_pos = start;
+ gtk_text_iter_backward_line (&insert_pos);
}
- /* Use anon mark to be able to select after insertion. */
- mark = gtk_text_buffer_create_mark (buffer, NULL, &end, TRUE);
-
- gtk_text_buffer_insert (buffer, &end, text, -1);
-
- gtk_text_buffer_end_user_action (buffer);
+ start_mark = gtk_text_buffer_create_mark (buffer, NULL, &insert_pos, TRUE);
+ gtk_text_buffer_insert (buffer, &insert_pos, text, -1);
g_free (text);
/* Select the moved text. */
- gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
- gtk_text_buffer_select_range (buffer, &start, &end);
+ gtk_text_buffer_get_iter_at_mark (buffer, &start, start_mark);
+ gtk_text_buffer_delete_mark (buffer, start_mark);
+
+ gtk_text_buffer_select_range (buffer, &start, &insert_pos);
+
+ if (!initially_contains_trailing_newline)
+ {
+ remove_trailing_newline (buffer);
+ }
+
+ gtk_text_buffer_end_user_action (buffer);
+
gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (view),
gtk_text_buffer_get_insert (buffer));
-
- gtk_text_buffer_delete_mark (buffer, mark);
}
static gboolean
diff --git a/testsuite/test-view.c b/testsuite/test-view.c
index 5906e55..34a199b 100644
--- a/testsuite/test-view.c
+++ b/testsuite/test-view.c
@@ -161,7 +161,7 @@ test_move_lines__move_single_line (void)
g_assert_cmpstr (text, ==,
"line1\n"
"line3\n"
- "line2\n"); /* FIXME should be "line2" without the '\n'. */
+ "line2");
g_free (text);
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
@@ -209,7 +209,7 @@ test_move_lines__move_single_line (void)
g_assert_cmpstr (text, ==,
"line1\n"
"line3\n"
- "line2\n"); /* FIXME should be "line2" without the '\n'. */
+ "line2");
g_free (text);
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
@@ -455,7 +455,7 @@ test_move_lines__move_several_lines (void)
"line1\n"
"line4\n"
"line2\n"
- "line3\n"); /* FIXME should be "line3" without the '\n'. */
+ "line3");
g_free (text);
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
@@ -507,7 +507,7 @@ test_move_lines__move_several_lines (void)
"line1\n"
"line3\n"
"line4\n"
- "line2\n"); /* FIXME should be "line2" without the '\n'. */
+ "line2");
g_free (text);
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]