[gtksourceview/wip/fix-move-lines: 3/3] move-lines: fix bug with trailing newline
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/fix-move-lines: 3/3] move-lines: fix bug with trailing newline
- Date: Thu, 30 Mar 2017 13:47:35 +0000 (UTC)
commit 6efb71d34cf93ba8871f65204183150b1b72ecda
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 | 153 ++++++++++++++++++++++++++---------------
testsuite/test-view.c | 8 +-
2 files changed, 101 insertions(+), 60 deletions(-)
---
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index e4a3516..3040fde 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -3699,6 +3699,66 @@ 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');
+}
+
+/* TODO 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
+get_move_lines_boundaries (GtkTextBuffer *buffer,
+ GtkTextIter *start,
+ GtkTextIter *end)
+{
+ g_assert (start != NULL);
+ g_assert (end != NULL);
+
+ gtk_text_buffer_get_selection_bounds (buffer, start, end);
+
+ /* 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_forward_line (end);
+ }
+}
+
static void
gtk_source_view_move_lines (GtkSourceView *view,
gboolean copy,
@@ -3707,9 +3767,11 @@ gtk_source_view_move_lines (GtkSourceView *view,
GtkTextBuffer *buffer;
GtkTextIter start;
GtkTextIter end;
+ GtkTextIter insert_pos;
GtkTextMark *mark;
- gboolean down;
gchar *text;
+ gboolean initially_contains_trailing_newline;
+ gboolean down;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
@@ -3722,47 +3784,35 @@ gtk_source_view_move_lines (GtkSourceView *view,
down = step > 0;
- gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
-
- /* 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_forward_line (&end);
- }
+ get_move_lines_boundaries (buffer, &start, &end);
if ((!down && gtk_text_iter_is_start (&start)) ||
(down && gtk_text_iter_is_end (&end)))
{
+ /* Nothing must be done, and the undo/redo history must remain
+ * unchanged.
+ */
return;
}
- text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
+ gtk_text_buffer_begin_user_action (buffer);
- /* 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;
+ initially_contains_trailing_newline = buffer_contains_trailing_newline (buffer);
- 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;
+ 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);
+ }
- tmp = g_strdup_printf ("%s\n", text);
+ /* At this point all lines finish with a newline or carriage return, so
+ * there are no special cases for the last line.
+ */
- g_free (text);
- text = tmp;
- }
- }
+ get_move_lines_boundaries (buffer, &start, &end);
- gtk_text_buffer_begin_user_action (buffer);
+ text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
if (!copy)
{
@@ -3771,45 +3821,36 @@ 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);
+ /* Left gravity mark */
+ mark = gtk_text_buffer_create_mark (buffer, NULL, &insert_pos, TRUE);
- g_free (text);
+ gtk_text_buffer_insert (buffer, &insert_pos, text, -1);
/* Select the moved text. */
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
+ end = insert_pos;
gtk_text_buffer_select_range (buffer, &start, &end);
+
+ 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));
+ g_free (text);
gtk_text_buffer_delete_mark (buffer, mark);
}
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]