[gtksourceview] Bracket matching: fix bug with wrong bracket highlighted near the cursor



commit 9fdad3e1c69eb11177d874740c987e28c965296a
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Oct 23 14:44:13 2015 +0200

    Bracket matching: fix bug with wrong bracket highlighted near the cursor
    
    Return explicitly the two iters: @bracket and @bracket_match. @bracket
    is either on the right or on the left of the cursor.
    
    The bug occurred with the following content, when the cursor is between
    the two closing parenthesis:
    (ab))
    The second ) was highlighted. Now the first ) is highlighted.

 gtksourceview/gtksourcebuffer-private.h |    4 +-
 gtksourceview/gtksourcebuffer.c         |  100 ++++++++++++++++++-------------
 gtksourceview/gtksourceview.c           |   19 ++++--
 tests/test-buffer.c                     |   56 ++++++++++-------
 4 files changed, 106 insertions(+), 73 deletions(-)
---
diff --git a/gtksourceview/gtksourcebuffer-private.h b/gtksourceview/gtksourcebuffer-private.h
index b7d65be..7a553da 100644
--- a/gtksourceview/gtksourcebuffer-private.h
+++ b/gtksourceview/gtksourcebuffer-private.h
@@ -61,7 +61,9 @@ gboolean               _gtk_source_buffer_has_invalid_chars           (GtkSourceBuffer      
  *buffer
 G_GNUC_INTERNAL
 GtkSourceBracketMatchType
                         _gtk_source_buffer_find_bracket_match          (GtkSourceBuffer        *buffer,
-                                                                        GtkTextIter            *pos);
+                                                                        const GtkTextIter      *pos,
+                                                                        GtkTextIter            *bracket,
+                                                                        GtkTextIter            
*bracket_match);
 
 G_GNUC_INTERNAL
 void                    _gtk_source_buffer_save_and_clear_selection    (GtkSourceBuffer        *buffer);
diff --git a/gtksourceview/gtksourcebuffer.c b/gtksourceview/gtksourcebuffer.c
index 73d5538..466df07 100644
--- a/gtksourceview/gtksourcebuffer.c
+++ b/gtksourceview/gtksourcebuffer.c
@@ -882,13 +882,15 @@ gtk_source_buffer_move_cursor (GtkTextBuffer     *buffer,
                               GtkTextMark       *mark)
 {
        GtkSourceBuffer *source_buffer;
-       GtkTextIter start, end;
-       gunichar cursor_char;
+       GtkTextIter start;
+       GtkTextIter end;
+       GtkTextIter bracket;
+       GtkTextIter bracket_match;
        GtkSourceBracketMatchType previous_state;
 
        g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
        g_return_if_fail (iter != NULL);
-       g_return_if_fail (mark != NULL);
+       g_return_if_fail (GTK_IS_TEXT_MARK (mark));
        g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer);
 
        if (mark != gtk_text_buffer_get_insert (buffer))
@@ -921,21 +923,24 @@ gtk_source_buffer_move_cursor (GtkTextBuffer     *buffer,
                return;
        }
 
-       start = *iter;
        previous_state = source_buffer->priv->bracket_match;
-       source_buffer->priv->bracket_match = _gtk_source_buffer_find_bracket_match (source_buffer, &start);
+       source_buffer->priv->bracket_match = _gtk_source_buffer_find_bracket_match (source_buffer,
+                                                                                   iter,
+                                                                                   &bracket,
+                                                                                   &bracket_match);
 
        if (source_buffer->priv->bracket_match != GTK_SOURCE_BRACKET_MATCH_FOUND)
        {
-               /* don't emit the signal at all if chars at previous and current
-                  positions are nonbrackets. */
+               /* Don't emit the signal at all if chars at previous and current
+                * positions are nonbrackets.
+                */
                if (previous_state != GTK_SOURCE_BRACKET_MATCH_NONE ||
                    source_buffer->priv->bracket_match != GTK_SOURCE_BRACKET_MATCH_NONE)
                {
                        g_signal_emit (source_buffer,
                                       buffer_signals[BRACKET_MATCHED],
                                       0,
-                                      &end,
+                                      &end, /* FIXME end may be uninitialized here... */
                                       source_buffer->priv->bracket_match);
                }
        }
@@ -944,31 +949,33 @@ gtk_source_buffer_move_cursor (GtkTextBuffer     *buffer,
                g_signal_emit (source_buffer,
                               buffer_signals[BRACKET_MATCHED],
                               0,
-                              &start,
-                              source_buffer->priv->bracket_match);
+                              &bracket_match,
+                              GTK_SOURCE_BRACKET_MATCH_FOUND);
 
                /* allow_bracket_match will allow the bracket match tag to be
-                  applied to the buffer. See apply_tag_real for more
-                  information */
+                * applied to the buffer. See apply_tag_real for more
+                * information.
+                */
                source_buffer->priv->allow_bracket_match = TRUE;
 
                /* Mark matching bracket */
-               if (!source_buffer->priv->bracket_mark_match)
+               if (source_buffer->priv->bracket_mark_match == NULL)
                {
                        source_buffer->priv->bracket_mark_match =
                                gtk_text_buffer_create_mark (buffer,
                                                             NULL,
-                                                            &start,
+                                                            &bracket_match,
                                                             TRUE);
                }
                else
                {
                        gtk_text_buffer_move_mark (buffer,
                                                   source_buffer->priv->bracket_mark_match,
-                                                  &start);
+                                                  &bracket_match);
                }
 
-               end = start;
+               start = bracket_match;
+               end = bracket_match;
                gtk_text_iter_forward_char (&end);
                gtk_text_buffer_apply_tag (buffer,
                                           get_bracket_match_tag (source_buffer),
@@ -976,29 +983,23 @@ gtk_source_buffer_move_cursor (GtkTextBuffer     *buffer,
                                           &end);
 
                /* Mark the bracket near the cursor */
-               start = *iter;
-               cursor_char = gtk_text_iter_get_char (&start);
-               if (bracket_pair (cursor_char, NULL) == 0)
-               {
-                       gtk_text_iter_backward_char (&start);
-               }
-
-               if (!source_buffer->priv->bracket_mark_cursor)
+               if (source_buffer->priv->bracket_mark_cursor == NULL)
                {
                        source_buffer->priv->bracket_mark_cursor =
                                gtk_text_buffer_create_mark (buffer,
                                                             NULL,
-                                                            &start,
+                                                            &bracket,
                                                             FALSE);
                }
                else
                {
                        gtk_text_buffer_move_mark (buffer,
                                                   source_buffer->priv->bracket_mark_cursor,
-                                                  &start);
+                                                  &bracket);
                }
 
-               end = start;
+               start = bracket;
+               end = bracket;
                gtk_text_iter_forward_char (&end);
                gtk_text_buffer_apply_tag (buffer,
                                           get_bracket_match_tag (source_buffer),
@@ -1260,35 +1261,50 @@ gtk_source_buffer_find_bracket_match_real (GtkSourceBuffer *buffer,
        return GTK_SOURCE_BRACKET_MATCH_NOT_FOUND;
 }
 
-/* Moves @pos to the matching bracket, if found.
- * Note that we take into account both the character following @pos and the one
+/* Note that we take into account both the character following @pos and the one
  * preceding it. If there are brackets on both sides, the one following @pos
  * takes precedence.
+ * @bracket and @bracket_match are valid only if GTK_SOURCE_BRACKET_MATCH_FOUND
+ * is returned. @bracket is set either to @pos or @pos-1.
  */
 GtkSourceBracketMatchType
-_gtk_source_buffer_find_bracket_match (GtkSourceBuffer *buffer,
-                                       GtkTextIter     *pos)
+_gtk_source_buffer_find_bracket_match (GtkSourceBuffer   *buffer,
+                                      const GtkTextIter *pos,
+                                      GtkTextIter       *bracket,
+                                      GtkTextIter       *bracket_match)
 {
-       GtkTextIter bracket_match;
        GtkSourceBracketMatchType result;
+       GtkTextIter prev;
 
-       bracket_match = *pos;
-       result = gtk_source_buffer_find_bracket_match_real (buffer, &bracket_match);
+       g_return_val_if_fail (GTK_SOURCE_IS_BUFFER (buffer), GTK_SOURCE_BRACKET_MATCH_NONE);
+       g_return_val_if_fail (pos != NULL, GTK_SOURCE_BRACKET_MATCH_NONE);
+       g_return_val_if_fail (bracket_match != NULL, GTK_SOURCE_BRACKET_MATCH_NONE);
 
-       if (result != GTK_SOURCE_BRACKET_MATCH_FOUND)
-       {
-               bracket_match = *pos;
+       *bracket_match = *pos;
+       result = gtk_source_buffer_find_bracket_match_real (buffer, bracket_match);
 
-               if (!gtk_text_iter_starts_line (&bracket_match) &&
-                   gtk_text_iter_backward_char (&bracket_match))
+       if (result == GTK_SOURCE_BRACKET_MATCH_FOUND)
+       {
+               if (bracket != NULL)
                {
-                       result = gtk_source_buffer_find_bracket_match_real (buffer, &bracket_match);
+                       *bracket = *pos;
                }
+
+               return GTK_SOURCE_BRACKET_MATCH_FOUND;
        }
 
-       if (result == GTK_SOURCE_BRACKET_MATCH_FOUND)
+       prev = *pos;
+       if (!gtk_text_iter_starts_line (&prev) &&
+           gtk_text_iter_backward_cursor_position (&prev))
+       {
+               *bracket_match = prev;
+               result = gtk_source_buffer_find_bracket_match_real (buffer, bracket_match);
+       }
+
+       if (result == GTK_SOURCE_BRACKET_MATCH_FOUND &&
+           bracket != NULL)
        {
-               *pos = bracket_match;
+               *bracket = prev;
        }
 
        return result;
diff --git a/gtksourceview/gtksourceview.c b/gtksourceview/gtksourceview.c
index 738e6f0..dbc70dd 100644
--- a/gtksourceview/gtksourceview.c
+++ b/gtksourceview/gtksourceview.c
@@ -320,23 +320,28 @@ gtk_source_view_move_to_matching_bracket (GtkSourceView *view,
        GtkTextView *text_view = GTK_TEXT_VIEW (view);
        GtkTextBuffer *buffer;
        GtkTextMark *insert_mark;
-       GtkTextIter iter;
+       GtkTextIter insert;
+       GtkTextIter bracket_match;
+       GtkSourceBracketMatchType result;
 
        buffer = gtk_text_view_get_buffer (text_view);
        insert_mark = gtk_text_buffer_get_insert (buffer);
-       gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert_mark);
+       gtk_text_buffer_get_iter_at_mark (buffer, &insert, insert_mark);
+
+       result = _gtk_source_buffer_find_bracket_match (GTK_SOURCE_BUFFER (buffer),
+                                                       &insert,
+                                                       NULL,
+                                                       &bracket_match);
 
-       if (_gtk_source_buffer_find_bracket_match (GTK_SOURCE_BUFFER (buffer),
-                                                  &iter) == GTK_SOURCE_BRACKET_MATCH_FOUND)
+       if (result == GTK_SOURCE_BRACKET_MATCH_FOUND)
        {
                if (extend_selection)
                {
-                       gtk_text_buffer_move_mark (buffer, insert_mark,
-                                                  &iter);
+                       gtk_text_buffer_move_mark (buffer, insert_mark, &bracket_match);
                }
                else
                {
-                       gtk_text_buffer_place_cursor (buffer, &iter);
+                       gtk_text_buffer_place_cursor (buffer, &bracket_match);
                }
 
                gtk_text_view_scroll_mark_onscreen (text_view, insert_mark);
diff --git a/tests/test-buffer.c b/tests/test-buffer.c
index b09e36e..cfc7869 100644
--- a/tests/test-buffer.c
+++ b/tests/test-buffer.c
@@ -282,24 +282,38 @@ test_sort_lines (void)
 static void
 do_test_bracket_matching (GtkSourceBuffer           *source_buffer,
                          const gchar               *text,
-                         gint                       offset_before,
-                         gint                       expected_offset_after,
+                         gint                       offset,
+                         gint                       expected_offset_bracket,
+                         gint                       expected_offset_match,
                          GtkSourceBracketMatchType  expected_result)
 {
        GtkTextBuffer *text_buffer = GTK_TEXT_BUFFER (source_buffer);
        GtkTextIter iter;
+       GtkTextIter bracket;
+       GtkTextIter bracket_match;
        GtkSourceBracketMatchType result;
-       gint offset_after;
 
        gtk_text_buffer_set_text (text_buffer, text, -1);
 
-       gtk_text_buffer_get_iter_at_offset (text_buffer, &iter, offset_before);
+       gtk_text_buffer_get_iter_at_offset (text_buffer, &iter, offset);
 
-       result = _gtk_source_buffer_find_bracket_match (source_buffer, &iter);
+       result = _gtk_source_buffer_find_bracket_match (source_buffer,
+                                                       &iter,
+                                                       &bracket,
+                                                       &bracket_match);
        g_assert_cmpint (result, ==, expected_result);
 
-       offset_after = gtk_text_iter_get_offset (&iter);
-       g_assert_cmpint (offset_after, ==, expected_offset_after);
+       if (result == GTK_SOURCE_BRACKET_MATCH_FOUND)
+       {
+               gint offset_bracket;
+               gint offset_match;
+
+               offset_bracket = gtk_text_iter_get_offset (&bracket);
+               offset_match = gtk_text_iter_get_offset (&bracket_match);
+
+               g_assert_cmpint (offset_bracket, ==, expected_offset_bracket);
+               g_assert_cmpint (offset_match, ==, expected_offset_match);
+       }
 }
 
 static void
@@ -316,22 +330,18 @@ test_bracket_matching (void)
        g_assert (c_language != NULL);
        gtk_source_buffer_set_language (buffer, c_language);
 
-       do_test_bracket_matching (buffer, "(ab)", 0, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       do_test_bracket_matching (buffer, "(ab)", 1, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       do_test_bracket_matching (buffer, "(ab)", 2, 2, GTK_SOURCE_BRACKET_MATCH_NONE);
-       do_test_bracket_matching (buffer, "(ab)", 3, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       do_test_bracket_matching (buffer, "(ab)", 4, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
-
-       do_test_bracket_matching (buffer, "(ab))", 0, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       do_test_bracket_matching (buffer, "(ab))", 1, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       do_test_bracket_matching (buffer, "(ab))", 2, 2, GTK_SOURCE_BRACKET_MATCH_NONE);
-       do_test_bracket_matching (buffer, "(ab))", 3, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       /* FIXME ok, the bracket at offset 3 (on the left) matches the bracket
-        * at offset 0. But the highlighting is wrong, the second ) is
-        * highlighted.
-        */
-       do_test_bracket_matching (buffer, "(ab))", 4, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
-       do_test_bracket_matching (buffer, "(ab))", 5, 5, GTK_SOURCE_BRACKET_MATCH_NOT_FOUND);
+       do_test_bracket_matching (buffer, "(ab)", 0, 0, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab)", 1, 0, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab)", 2, -1, -1, GTK_SOURCE_BRACKET_MATCH_NONE);
+       do_test_bracket_matching (buffer, "(ab)", 3, 3, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab)", 4, 3, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
+
+       do_test_bracket_matching (buffer, "(ab))", 0, 0, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab))", 1, 0, 3, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab))", 2, -1, -1, GTK_SOURCE_BRACKET_MATCH_NONE);
+       do_test_bracket_matching (buffer, "(ab))", 3, 3, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab))", 4, 3, 0, GTK_SOURCE_BRACKET_MATCH_FOUND);
+       do_test_bracket_matching (buffer, "(ab))", 5, -1, -1, GTK_SOURCE_BRACKET_MATCH_NOT_FOUND);
 
        g_object_unref (buffer);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]