[latexila/wip/search] Search and replace: use the new API from GtkSourceView



commit f1ecd46b7b60f5ffb7ce825891b38f3446b62119
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Mon Sep 23 00:22:18 2013 +0200

    Search and replace: use the new API from GtkSourceView
    
    Before, the current match was highlighted with another color (orange).
    Now the current match is selected.

 src/document.vala |  596 +----------------------------------------------------
 src/search.vala   |  209 +++++++++----------
 2 files changed, 105 insertions(+), 700 deletions(-)
---
diff --git a/src/document.vala b/src/document.vala
index 5ae39d2..51418cb 100644
--- a/src/document.vala
+++ b/src/document.vala
@@ -37,20 +37,8 @@ public class Document : Gtk.SourceBuffer
     private string _etag;
     private string? encoding = null;
     private bool new_file = true;
-
     private DocumentStructure _structure = null;
 
-    private TextTag found_tag;
-    private TextTag found_tag_selected;
-    public signal void search_info_updated (bool selected, uint nb_matches,
-        uint num_match);
-    private string search_text;
-    private uint search_nb_matches;
-    private uint search_num_match;
-    private bool search_case_sensitive;
-    private bool search_entire_word;
-
-    private bool stop_cursor_moved_emission = false;
     public signal void cursor_moved ();
 
     public Document ()
@@ -64,29 +52,18 @@ public class Document : Gtk.SourceBuffer
             update_syntax_highlighting ();
             update_project_id ();
         });
+
         mark_set.connect ((location, mark) =>
         {
             if (mark == get_insert ())
-                emit_cursor_moved ();
+                cursor_moved ();
         });
+
         changed.connect (() =>
         {
             new_file = false;
-            emit_cursor_moved ();
+            cursor_moved ();
         });
-
-        found_tag = new TextTag ("found");
-        found_tag_selected = new TextTag ("found_selected");
-        sync_found_tags ();
-        TextTagTable tag_table = get_tag_table ();
-        tag_table.add (found_tag);
-        tag_table.add (found_tag_selected);
-        notify["style-scheme"].connect (sync_found_tags);
-
-        TextIter iter;
-        get_iter_at_line (out iter, 0);
-        create_mark ("search_selected_start", iter, true);
-        create_mark ("search_selected_end", iter, true);
     }
 
     public new bool get_modified ()
@@ -379,12 +356,6 @@ public class Document : Gtk.SourceBuffer
         style_scheme = manager.get_scheme (scheme_id);
     }
 
-    private void emit_cursor_moved ()
-    {
-        if (! stop_cursor_moved_emission)
-            cursor_moved ();
-    }
-
     public void comment_selected_lines ()
     {
         TextIter start;
@@ -624,563 +595,4 @@ public class Document : Gtk.SourceBuffer
 
         return true;
     }
-
-
-    /***************
-     *    SEARCH
-     ***************/
-
-    public void set_search_text (string text, bool case_sensitive, bool entire_word,
-        out uint nb_matches, out uint num_match, bool select = true)
-    {
-        num_match = 0;
-
-        // connect signals
-        if (search_text == null)
-        {
-            cursor_moved.connect (search_cursor_moved_handler);
-            delete_range.connect (search_delete_range_before_handler);
-            delete_range.connect_after (search_delete_range_after_handler);
-            insert_text.connect (search_insert_text_before_handler);
-            insert_text.connect_after (search_insert_text_after_handler);
-        }
-
-        // if nothing has changed
-        if (search_text == text
-            && search_case_sensitive == case_sensitive
-            && search_entire_word == entire_word)
-        {
-            nb_matches = search_nb_matches;
-            num_match = search_num_match;
-            return;
-        }
-
-        invalidate_search_selected_marks ();
-        clear_search (false);
-        search_text = text;
-        search_case_sensitive = case_sensitive;
-        search_entire_word = entire_word;
-
-        TextIter start = {};
-        TextIter match_start = {};
-        TextIter match_end = {};
-        TextIter insert = {};
-        TextIter try_match_start = {};
-        TextIter try_match_end = {};
-
-        get_start_iter (out start);
-        get_iter_at_mark (out insert, get_insert ());
-        bool next_match_after_cursor_found = ! select;
-        uint i = 0;
-
-        while (iter_forward_search (start, null, out try_match_start, out try_match_end))
-        {
-            match_start = try_match_start;
-            match_end = try_match_end;
-
-            if (! next_match_after_cursor_found && insert.compare (match_end) <= 0)
-            {
-                next_match_after_cursor_found = true;
-                search_num_match = num_match = i;
-                move_search_marks (match_start, match_end, true);
-            }
-            else
-                apply_tag (found_tag, match_start, match_end);
-
-            start = match_end;
-            i++;
-        }
-
-        // if the cursor was after the last match, take the last match
-        // (if we want to select one)
-        if (! next_match_after_cursor_found && i > 0)
-        {
-            search_num_match = num_match = i;
-            move_search_marks (match_start, match_end, true);
-        }
-
-        search_nb_matches = nb_matches = i;
-
-        if (search_nb_matches == 0)
-            clear_search_tags ();
-    }
-
-    public void select_current_match ()
-    {
-        TextIter start, end;
-        get_iter_at_mark (out start, get_mark ("search_selected_start"));
-        get_iter_at_mark (out end, get_mark ("search_selected_end"));
-        place_cursor (start);
-        move_mark (get_mark ("selection_bound"), end);
-    }
-
-    public void search_forward ()
-    {
-        return_if_fail (search_text != null);
-
-        if (search_nb_matches == 0)
-            return;
-
-        TextIter start_search, start, match_start, match_end;
-        get_iter_at_mark (out start_search, get_insert ());
-        get_start_iter (out start);
-
-        bool increment = false;
-        if (start_search.has_tag (found_tag_selected))
-        {
-            get_iter_at_mark (out start_search, get_mark ("search_selected_end"));
-            increment = true;
-        }
-
-        replace_found_tag_selected ();
-
-        // search forward
-        if (iter_forward_search (start_search, null, out match_start, out match_end))
-        {
-            move_search_marks (match_start, match_end, true);
-
-            if (increment)
-            {
-                search_num_match++;
-                search_info_updated (true, search_nb_matches, search_num_match);
-                return;
-            }
-        }
-
-        else if (iter_forward_search (start, null, out match_start, out match_end))
-        {
-            move_search_marks (match_start, match_end, true);
-
-            search_num_match = 1;
-            search_info_updated (true, search_nb_matches, search_num_match);
-            return;
-        }
-
-        find_num_match ();
-    }
-
-    public void search_backward ()
-    {
-        return_if_fail (search_text != null);
-
-        if (search_nb_matches == 0)
-            return;
-
-        TextIter start_search, end, match_start, match_end;
-        get_iter_at_mark (out start_search, get_insert ());
-        get_end_iter (out end);
-
-        bool decrement = false;
-        bool move_cursor = true;
-
-        TextIter start_prev = start_search;
-        start_prev.backward_char ();
-
-        // the cursor is on a match
-        if (start_search.has_tag (found_tag_selected) ||
-            start_prev.has_tag (found_tag_selected))
-        {
-            get_iter_at_mark (out start_search, get_mark ("search_selected_start"));
-            decrement = true;
-        }
-
-        // the user has clicked in the middle or at the beginning of a match
-        else if (start_search.has_tag (found_tag))
-        {
-            move_cursor = false;
-            start_search.forward_chars ((int) search_text.length);
-        }
-
-        // the user has clicked at the end of a match
-        else if (start_prev.has_tag (found_tag))
-            move_cursor = false;
-
-        replace_found_tag_selected ();
-
-        // search backward
-        if (iter_backward_search (start_search, null, out match_start, out match_end))
-        {
-            move_search_marks (match_start, match_end, move_cursor);
-
-            if (decrement)
-            {
-                search_num_match--;
-                search_info_updated (true, search_nb_matches, search_num_match);
-                return;
-            }
-        }
-
-        // take the last match
-        else if (iter_backward_search (end, null, out match_start, out match_end))
-        {
-            move_search_marks (match_start, match_end, true);
-
-            search_num_match = search_nb_matches;
-            search_info_updated (true, search_nb_matches, search_num_match);
-            return;
-        }
-
-        find_num_match ();
-    }
-
-    private bool iter_forward_search (TextIter start, TextIter? end,
-        out TextIter match_start, out TextIter match_end)
-    {
-        match_start = TextIter ();
-        match_end = TextIter ();
-
-        bool found = false;
-        while (! found)
-        {
-            found = start.forward_search (search_text, get_search_flags (),
-                out match_start, out match_end, end);
-
-            if (found && search_entire_word)
-            {
-                found = match_start.starts_word () && match_end.ends_word ();
-                if (! found)
-                    start = match_end;
-            }
-            else
-                break;
-        }
-
-        return found;
-    }
-
-    private bool iter_backward_search (TextIter start, TextIter? end,
-        out TextIter match_start, out TextIter match_end)
-    {
-        match_start = TextIter ();
-        match_end = TextIter ();
-
-        bool found = false;
-        while (! found)
-        {
-            found = start.backward_search (search_text, get_search_flags (),
-                out match_start, out match_end, end);
-
-            if (found && search_entire_word)
-            {
-                found = match_start.starts_word () && match_end.ends_word ();
-                if (! found)
-                    start = match_start;
-            }
-            else
-                break;
-        }
-
-        return found;
-    }
-
-    public void clear_search (bool disconnect_signals = true)
-    {
-        clear_search_tags ();
-        search_text = null;
-
-        if (disconnect_signals)
-        {
-            cursor_moved.disconnect (search_cursor_moved_handler);
-            delete_range.disconnect (search_delete_range_before_handler);
-            delete_range.disconnect (search_delete_range_after_handler);
-            insert_text.disconnect (search_insert_text_before_handler);
-            insert_text.disconnect (search_insert_text_after_handler);
-        }
-    }
-
-    private void clear_search_tags ()
-    {
-        invalidate_search_selected_marks ();
-
-        TextIter start, end;
-        get_bounds (out start, out end);
-        remove_tag (found_tag, start, end);
-        remove_tag (found_tag_selected, start, end);
-    }
-
-    private void search_cursor_moved_handler ()
-    {
-        TextIter insert, insert_previous;
-        get_iter_at_mark (out insert, get_insert ());
-        insert_previous = insert;
-        insert_previous.backward_char ();
-        if (insert.has_tag (found_tag_selected) ||
-            insert_previous.has_tag (found_tag_selected))
-        {
-            return;
-        }
-
-        replace_found_tag_selected ();
-        invalidate_search_selected_marks ();
-
-        if (insert.has_tag (found_tag) || insert_previous.has_tag (found_tag))
-            search_backward ();
-        else
-            search_info_updated (false, search_nb_matches, 0);
-    }
-
-    private void search_delete_range_before_handler (TextIter start, TextIter end)
-    {
-        TextIter start_search, stop_search, match_start, match_end;
-        start_search = start;
-        start_search.backward_chars ((int) search_text.length - 1);
-        stop_search = end;
-        stop_search.forward_chars ((int) search_text.length - 1);
-
-        replace_found_tag_selected ();
-        invalidate_search_selected_marks ();
-
-        while (iter_forward_search (start_search, stop_search, out match_start,
-            out match_end))
-        {
-            if (match_start.compare (start) < 0 || match_end.compare (end) > 0)
-            {
-                remove_tag (found_tag, match_start, match_end);
-                remove_tag (found_tag_selected, match_start, match_end);
-            }
-
-            search_nb_matches--;
-            start_search = match_end;
-        }
-    }
-
-    private void search_delete_range_after_handler (TextIter location)
-    {
-        TextIter start_search, stop_search;
-        start_search = stop_search = location;
-        start_search.backward_chars ((int) search_text.length - 1);
-        stop_search.forward_chars ((int) search_text.length - 1);
-
-        search_matches_between (start_search, stop_search);
-    }
-
-    private void search_insert_text_before_handler (TextIter location)
-    {
-        // if text inserted in the middle of a current match, remove the tags
-        if (location.has_tag (found_tag) || location.has_tag (found_tag_selected))
-        {
-            replace_found_tag_selected ();
-            invalidate_search_selected_marks ();
-
-            TextIter start_search, match_start, match_end;
-            start_search = location;
-            start_search.forward_chars ((int) search_text.length - 1);
-
-            if (iter_backward_search (start_search, null, out match_start, out match_end))
-            {
-                // in the middle
-                if (location.compare (match_end) < 0)
-                {
-                    remove_tag (found_tag, match_start, match_end);
-                    remove_tag (found_tag_selected, match_start, match_end);
-                    search_nb_matches--;
-                }
-            }
-        }
-    }
-
-    private void search_insert_text_after_handler (TextIter location, string text,
-        int len)
-    {
-        // remove tags in text inserted
-        TextIter left_text = location;
-        left_text.backward_chars (len);
-        remove_tag (found_tag, left_text, location);
-        remove_tag (found_tag_selected, left_text, location);
-
-        TextIter start_search, stop_search;
-        start_search = stop_search = location;
-        start_search.backward_chars (len + (int) search_text.length - 1);
-        stop_search.forward_chars ((int) search_text.length - 1);
-
-        search_matches_between (start_search, stop_search);
-    }
-
-    private void search_matches_between (TextIter start_search, TextIter stop_search)
-    {
-        TextIter match_start, match_end;
-
-        while (iter_forward_search (start_search, stop_search, out match_start,
-            out match_end))
-        {
-            apply_tag (found_tag, match_start, match_end);
-            search_nb_matches++;
-            start_search = match_end;
-        }
-
-        replace_found_tag_selected ();
-        invalidate_search_selected_marks ();
-
-        // simulate a cursor move
-        search_cursor_moved_handler ();
-    }
-
-    private TextSearchFlags get_search_flags ()
-    {
-        var flags = TextSearchFlags.TEXT_ONLY | TextSearchFlags.VISIBLE_ONLY;
-        if (! search_case_sensitive)
-            flags |= TextSearchFlags.CASE_INSENSITIVE;
-        return flags;
-    }
-
-    private void move_search_marks (TextIter start, TextIter end, bool move_cursor)
-    {
-        remove_tag (found_tag, start, end);
-        apply_tag (found_tag_selected, start, end);
-
-        move_mark_by_name ("search_selected_start", start);
-        move_mark_by_name ("search_selected_end", end);
-
-        if (move_cursor)
-        {
-            place_cursor (start);
-            tab.view.scroll_to_cursor ();
-        }
-    }
-
-    private void replace_found_tag_selected ()
-    {
-        TextIter start, end;
-        get_iter_at_mark (out start, get_mark ("search_selected_start"));
-        get_iter_at_mark (out end, get_mark ("search_selected_end"));
-        remove_tag (found_tag_selected, start, end);
-        apply_tag (found_tag, start, end);
-    }
-
-    private void find_num_match ()
-    {
-        TextIter start, stop, match_end;
-        get_start_iter (out start);
-        get_iter_at_mark (out stop, get_mark ("search_selected_start"));
-
-        uint i = 0;
-        while (iter_forward_search (start, stop, null, out match_end))
-        {
-            i++;
-            start = match_end;
-        }
-
-        search_num_match = i + 1;
-        search_info_updated (true, search_nb_matches, search_num_match);
-    }
-
-    private void invalidate_search_selected_marks ()
-    {
-        TextIter iter;
-        get_start_iter (out iter);
-        move_mark_by_name ("search_selected_start", iter);
-        move_mark_by_name ("search_selected_end", iter);
-    }
-
-    private void set_search_match_colors (TextTag text_tag)
-    {
-        SourceStyleScheme style_scheme = get_style_scheme ();
-        SourceStyle style = null;
-
-        if (style_scheme != null)
-            style = style_scheme.get_style ("search-match");
-
-        if (style_scheme == null || style == null)
-        {
-            text_tag.background = "#FFFF78";
-            return;
-        }
-
-        if (style.foreground_set && style.foreground != null)
-            text_tag.foreground = style.foreground;
-        else
-            text_tag.foreground = null;
-
-        if (style.background_set && style.background != null)
-            text_tag.background = style.background;
-        else
-            text_tag.background = null;
-
-        if (style.line_background_set && style.line_background != null)
-            text_tag.paragraph_background = style.line_background;
-        else
-            text_tag.paragraph_background = null;
-
-        text_tag.weight = style.bold_set && style.bold ?
-            Pango.Weight.BOLD : Pango.Weight.NORMAL;
-
-        text_tag.style = style.italic_set && style.italic ?
-            Pango.Style.ITALIC : Pango.Style.NORMAL;
-
-        text_tag.underline = style.underline_set && style.underline ?
-            Pango.Underline.SINGLE : Pango.Underline.NONE;
-
-        text_tag.strikethrough = style.strikethrough_set && style.strikethrough;
-    }
-
-    private void sync_found_tags ()
-    {
-        set_search_match_colors (found_tag);
-
-        // found tag selected: same as found tag but with orange background
-        set_search_match_colors (found_tag_selected);
-        found_tag_selected.background = "#FF8C00";
-    }
-
-
-    /****************
-     *    REPLACE
-     ****************/
-
-    public void replace (string text)
-    {
-        return_if_fail (search_text != null);
-        return_if_fail (! readonly);
-
-        /* the cursor is on a match? */
-        TextIter insert, insert_prev;
-        get_iter_at_mark (out insert, get_insert ());
-        insert_prev = insert;
-        insert_prev.backward_char ();
-
-        // no match selected, we search forward
-        if (! insert.has_tag (found_tag_selected) &&
-            ! insert_prev.has_tag (found_tag_selected))
-        {
-            search_forward ();
-            return;
-        }
-
-        /* replace text */
-        TextIter start, end;
-        get_iter_at_mark (out start, get_mark ("search_selected_start"));
-        get_iter_at_mark (out end, get_mark ("search_selected_end"));
-
-        begin_user_action ();
-        this.delete (ref start, ref end);
-        this.insert (ref start, text, -1);
-        end_user_action ();
-
-        // if the next match was directly after the previous, don't search forward
-        if (! start.has_tag (found_tag_selected))
-            search_forward ();
-    }
-
-    public void replace_all (string text)
-    {
-        return_if_fail (search_text != null);
-        return_if_fail (! readonly);
-
-        TextIter start, match_start, match_end;
-        get_start_iter (out start);
-
-        stop_cursor_moved_emission = true;
-        begin_user_action ();
-
-        while (iter_forward_search (start, null, out match_start, out match_end))
-        {
-            this.delete (ref match_start, ref match_end);
-            this.insert (ref match_start, text, -1);
-            start = match_start;
-        }
-
-        end_user_action ();
-        stop_cursor_moved_emission = false;
-        emit_cursor_moved ();
-    }
 }
diff --git a/src/search.vala b/src/search.vala
index 2931f9b..fd57e17 100644
--- a/src/search.vala
+++ b/src/search.vala
@@ -91,21 +91,17 @@ public class GotoLine : Grid
 public class SearchAndReplace : GLib.Object
 {
     private unowned MainWindow _main_window;
-    private Document _working_document;
 
     private Grid _main_grid;
     private Grid _replace_grid;
 
-    private Button _button_arrow;
     private Arrow _arrow;
 
     private ErrorEntry _entry_find;
     private Entry _entry_replace;
 
-    private CheckMenuItem _check_case_sensitive;
-    private CheckMenuItem _check_entire_word;
-
-    private int min_nb_chars_for_inc_search = 3;
+    private SourceSearchSettings _search_settings;
+    private SourceSearchContext? _search_context = null;
 
     private enum Mode
     {
@@ -115,34 +111,25 @@ public class SearchAndReplace : GLib.Object
 
     private Mode get_mode ()
     {
-        if (_arrow.arrow_type == ArrowType.UP)
-            return Mode.SEARCH_AND_REPLACE;
-
-        return Mode.SEARCH;
-    }
-
-    private bool case_sensitive
-    {
-        get { return _check_case_sensitive.get_active (); }
-    }
-
-    private bool entire_word
-    {
-        get { return _check_entire_word.get_active (); }
+        return _arrow.arrow_type == ArrowType.UP ? Mode.SEARCH_AND_REPLACE : Mode.SEARCH;
     }
 
     public SearchAndReplace (MainWindow main_window)
     {
         _main_window = main_window;
+
+        _search_settings = new SourceSearchSettings ();
+        _search_settings.set_wrap_around (true);
+
         _main_grid = new Grid ();
         _main_grid.set_column_spacing (3);
         _main_grid.set_row_spacing (3);
 
         /* Arrow */
-        _button_arrow = new Button ();
+        Button button_arrow = new Button ();
         _arrow = new Arrow (ArrowType.DOWN, ShadowType.OUT);
-        _button_arrow.add (_arrow);
-        _main_grid.attach (_button_arrow, 0, 0, 1, 1);
+        button_arrow.add (_arrow);
+        _main_grid.attach (button_arrow, 0, 0, 1, 1);
 
         /* Find entry */
         Grid find_grid = new Grid ();
@@ -154,17 +141,14 @@ public class SearchAndReplace : GLib.Object
         find_grid.add (_entry_find);
 
         /* Buttons at the right of the find entry */
-        Button button_clear_find = get_button (Stock.CLEAR);
         Button button_previous = get_button (Stock.GO_UP);
         Button button_next = get_button (Stock.GO_DOWN);
         Button button_close = get_button (Stock.CLOSE);
 
-        find_grid.add (button_clear_find);
         find_grid.add (button_previous);
         find_grid.add (button_next);
         find_grid.add (button_close);
 
-        button_clear_find.sensitive = false;
         button_previous.sensitive = false;
         button_next.sensitive = false;
 
@@ -181,7 +165,6 @@ public class SearchAndReplace : GLib.Object
         _replace_grid.add (_entry_replace);
 
         /* Buttons at the right of the replace entry */
-        Button button_clear_replace = get_button (Stock.CLEAR);
         Button button_replace = get_button (Stock.FIND_AND_REPLACE);
 
         // replace all: image + label
@@ -198,17 +181,15 @@ public class SearchAndReplace : GLib.Object
         replace_all_grid.add (label);
         button_replace_all.add (replace_all_grid);
 
-        _replace_grid.add (button_clear_replace);
         _replace_grid.add (button_replace);
         _replace_grid.add (button_replace_all);
 
-        button_clear_replace.sensitive = false;
         button_replace.sensitive = false;
         button_replace_all.sensitive = false;
 
         /* signal handlers */
 
-        _button_arrow.clicked.connect (() =>
+        button_arrow.clicked.connect (() =>
         {
             // search and replace -> search
             if (get_mode () == Mode.SEARCH_AND_REPLACE)
@@ -227,14 +208,23 @@ public class SearchAndReplace : GLib.Object
 
         button_close.clicked.connect (hide);
 
-        button_clear_find.clicked.connect (() => _entry_find.text = "");
-        button_clear_replace.clicked.connect (() => _entry_replace.text = "");
-
         button_previous.clicked.connect (() =>
         {
-            set_search_text (false);
-            return_if_fail (_working_document != null);
-            _working_document.search_backward ();
+            if (_search_context == null)
+                return;
+
+            TextIter iter;
+            TextIter match_start;
+            TextIter match_end;
+
+            Document doc = _search_context.get_buffer () as Document;
+            doc.get_selection_bounds (out iter, null);
+
+            if (_search_context.backward (iter, out match_start, out match_end))
+            {
+                doc.select_range (match_start, match_end);
+                doc.tab.view.scroll_to_cursor ();
+            }
         });
 
         button_next.clicked.connect (search_forward);
@@ -243,34 +233,28 @@ public class SearchAndReplace : GLib.Object
         _entry_find.changed.connect (() =>
         {
             bool sensitive = _entry_find.text_length > 0;
-            button_clear_find.sensitive = sensitive;
             button_previous.sensitive = sensitive;
             button_next.sensitive = sensitive;
             button_replace.sensitive = sensitive;
             button_replace_all.sensitive = sensitive;
-
-            if (_entry_find.text_length == 0)
-                clear_search ();
-            else if (_entry_find.text_length >= min_nb_chars_for_inc_search)
-                set_search_text ();
         });
 
-        _entry_replace.changed.connect (() =>
-        {
-            button_clear_replace.sensitive = _entry_replace.text_length > 0;
-        });
-
-        _check_case_sensitive.toggled.connect (() => set_search_text ());
-        _check_entire_word.toggled.connect (() => set_search_text ());
-
         button_replace.clicked.connect (replace);
         _entry_replace.activate.connect (replace);
 
         button_replace_all.clicked.connect (() =>
         {
-            return_if_fail (_entry_find.text_length != 0);
-            set_search_text ();
-            _working_document.replace_all (_entry_replace.text);
+            if (_search_context != null)
+            {
+                try
+                {
+                    _search_context.replace_all (_entry_replace.text, -1);
+                }
+                catch (Error e)
+                {
+                    /* Do nothing. An error can occur only for a regex search. */
+                }
+            }
         });
 
         _entry_find.key_press_event.connect ((event) =>
@@ -284,8 +268,6 @@ public class SearchAndReplace : GLib.Object
                     return true;
 
                 case Gdk.Key.Escape:
-                    // Escape in find => select text and hide search
-                    select_current_match ();
                     hide ();
                     return true;
 
@@ -298,7 +280,6 @@ public class SearchAndReplace : GLib.Object
         _main_grid.hide ();
     }
 
-    /* Find entry */
     private void init_find_entry ()
     {
         _entry_find = new ErrorEntry ();
@@ -309,14 +290,30 @@ public class SearchAndReplace : GLib.Object
         _entry_find.can_focus = true;
         _entry_find.set_width_chars (25);
 
+        _entry_find.bind_property ("text", _search_settings, "search-text",
+            BindingFlags.DEFAULT);
+
         /* Options menu */
         Gtk.Menu menu = new Gtk.Menu ();
-        _check_case_sensitive = new CheckMenuItem.with_label (_("Case sensitive"));
-        _check_entire_word = new CheckMenuItem.with_label (_("Entire words only"));
-        menu.append (_check_case_sensitive);
-        menu.append (_check_entire_word);
+
+        CheckMenuItem check_case_sensitive =
+            new CheckMenuItem.with_label (_("Case sensitive"));
+
+        CheckMenuItem check_entire_word =
+            new CheckMenuItem.with_label (_("Entire words only"));
+
+        menu.append (check_case_sensitive);
+        menu.append (check_entire_word);
         menu.show_all ();
 
+        check_case_sensitive.bind_property ("active",
+            _search_settings, "case-sensitive",
+            BindingFlags.DEFAULT);
+
+        check_entire_word.bind_property ("active",
+            _search_settings, "at-word-boundaries",
+            BindingFlags.DEFAULT);
+
         _entry_find.icon_press.connect ((icon_pos, event) =>
         {
             if (icon_pos == EntryIconPosition.PRIMARY)
@@ -357,7 +354,6 @@ public class SearchAndReplace : GLib.Object
 
         _main_grid.show_all ();
         _entry_find.grab_focus ();
-        set_replace_sensitivity ();
 
         // if text is selected in the active document, and if this text contains no \n,
         // search this text
@@ -369,78 +365,75 @@ public class SearchAndReplace : GLib.Object
             _entry_find.text = doc.get_text (start, end, false);
         }
 
-        _main_window.notify["active-document"].connect (set_replace_sensitivity);
+        _main_window.notify["active-document"].connect (connect_active_document);
+        connect_active_document ();
     }
 
     public void hide ()
     {
+        _main_window.notify["active-document"].disconnect (connect_active_document);
+        _search_context = null;
+
         _main_grid.hide ();
-        if (_working_document != null)
-            clear_search ();
 
         if (_main_window.active_view != null)
             _main_window.active_view.grab_focus ();
-
-        _main_window.notify["active-document"].disconnect (set_replace_sensitivity);
     }
 
-    private void set_search_text (bool select = true)
+    private void connect_active_document ()
     {
-        return_if_fail (_main_window.active_document != null);
-
-        if (_entry_find.text_length == 0)
-            return;
-
-        if (_main_window.active_document != _working_document)
+        if (_main_window.active_document == null)
         {
-            if (_working_document != null)
-                clear_search ();
-
-            _working_document = _main_window.active_document;
+            _search_context = null;
         }
+        else
+        {
+            _search_context = new SourceSearchContext (_main_window.active_document,
+                _search_settings);
 
-        uint nb_matches;
-
-        _working_document.set_search_text (_entry_find.text, case_sensitive,
-            entire_word, out nb_matches, null, select);
-
-        _entry_find.error = nb_matches == 0;
+            bool readonly = _main_window.active_document.readonly;
+            _replace_grid.set_sensitive (! readonly);
+        }
     }
 
-    private void select_current_match ()
+    private void search_forward ()
     {
-        return_if_fail (_main_window.active_document != null);
+        if (_search_context == null)
+            return;
 
-        if (_working_document != null);
-            _working_document.select_current_match ();
-    }
+        TextIter iter;
+        TextIter match_start;
+        TextIter match_end;
 
-    private void search_forward ()
-    {
-        set_search_text (false);
-        return_if_fail (_working_document != null);
-        _working_document.search_forward ();
-    }
+        Document doc = _search_context.get_buffer () as Document;
+        doc.get_selection_bounds (null, out iter);
 
-    private void clear_search ()
-    {
-        if (_working_document != null)
+        if (_search_context.forward (iter, out match_start, out match_end))
         {
-            _working_document.clear_search ();
-            _working_document = null;
+            doc.select_range (match_start, match_end);
+            doc.tab.view.scroll_to_cursor ();
         }
     }
 
-    private void set_replace_sensitivity ()
-    {
-        bool readonly = _main_window.active_document.readonly;
-        _replace_grid.set_sensitive (! readonly);
-    }
-
     private void replace ()
     {
-        return_if_fail (_entry_find.text_length != 0);
-        set_search_text ();
-        _working_document.replace (_entry_replace.text);
+        if (_search_context == null)
+            return;
+
+        TextIter match_start;
+        TextIter match_end;
+        SourceBuffer buffer = _search_context.get_buffer ();
+        buffer.get_selection_bounds (out match_start, out match_end);
+
+        try
+        {
+            _search_context.replace (match_start, match_end, _entry_replace.text, -1);
+        }
+        catch (Error e)
+        {
+            /* Do nothing. An error can occur only for a regex search. */
+        }
+
+        search_forward ();
     }
 }


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