Index: plugins/search/search-get-next.c
===================================================================
--- plugins/search/search-get-next.c	(revision 0)
+++ plugins/search/search-get-next.c	(revision 0)
@@ -0,0 +1,219 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Maxim Ermilov 2009 <ermilov.maxim@gmail.com>
+ *
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "search-get-next.h"
+
+typedef struct _SearchGetNextPrivate SearchGetNextPrivate;
+struct _SearchGetNextPrivate
+{
+	GMutex *lock_work;
+	GList *entries;
+	GList *work_data;
+	Search *s;
+	gboolean end_activity;
+	gboolean flag_select;
+	gboolean interactive;
+	SearchReplace *sr;
+	gint nb_results;
+};
+
+#define SEARCH_GET_NEXT_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate))
+
+G_DEFINE_TYPE (SearchGetNext, search_get_next, ANJUTA_TYPE_ASYNC_COMMAND);
+
+static guint
+search_get_next_run (AnjutaCommand *obj)
+{
+	GList *tmp;
+	SearchEntry *se;
+	FileBuffer *fb;
+	gint nb_results;
+	static long start_sel = 0;
+	static long end_sel = 0;
+	static MatchInfo *mi;
+	SearchGetNext *object = SEARCH_GET_NEXT (obj);
+	SearchGetNextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate);
+	GList *entries = priv->entries;
+	Search *s = priv->s;
+	gboolean end_activity = priv->end_activity;
+	gboolean flag_select = priv->flag_select;
+	gboolean interactive = priv->interactive;
+	SearchReplace *sr = priv->sr;
+	int num;
+
+	nb_results = 0;
+	for (tmp = entries; tmp && (nb_results <= s->expr.actions_max);
+		 tmp = g_list_next(tmp))
+	{
+		GList *pack = NULL;
+		struct Data2 *d2 = g_new (struct Data2, 1);
+
+		num = 0;
+
+		if (end_activity)
+			break;
+		/*to eliminate un-needed moves, when not bookmarking, this could be
+		  current line i.e. ianjuta_editor_get_lineno (IANJUTA_EDITOR (se->te), NULL);
+		  or sometimes last-line ? */
+
+		se = (SearchEntry *) tmp->data;
+		if (flag_select)
+		{
+			se->start_pos = start_sel;
+			se->end_pos = end_sel;
+		}
+		else
+			end_sel = se->end_pos;
+		d2->se = se;
+
+		if (SE_BUFFER == se->type)
+			fb = file_buffer_new_from_te(se->te);
+		else /* if (SE_FILE == se->type) */
+			fb = file_buffer_new_from_path(se->path, NULL, -1, 0);
+		d2->fb = NULL;
+		if (fb && fb->buf)
+		{
+			fb->pos = se->start_pos;
+			d2->fb = file_buffer_dup (fb);
+		//FIXME enable clearing of marks by some means other than a 0-match search
+			while (interactive ||
+				NULL != (mi = get_next_match(fb, s->range.direction, &(s->expr))))
+			{
+				struct Data1 *t = g_new (struct Data1, 1);
+				if ((s->range.direction == SD_BACKWARD) && (mi->pos < se->end_pos))
+						break;
+				if ((s->range.direction != SD_BACKWARD) && ((se->end_pos != -1) &&
+					(mi->pos+mi->len > se->end_pos)))
+						break;
+				nb_results++;
+				if (nb_results > sr->search.expr.actions_max)
+					break;
+				t->mi = match_info_dup (mi);
+				pack = g_list_append (pack, t);
+				num++;
+				if (num >= 100)
+				{
+					num = 0;
+					d2->data1 = pack;
+					g_mutex_lock (priv->lock_work);
+					if (d2->fb && d2->fb->buf)
+						priv->work_data = g_list_append (priv->work_data, d2);
+					g_mutex_unlock (priv->lock_work);
+					d2 = g_new (struct Data2, 1);
+					d2->fb = file_buffer_dup (fb);
+					d2->se = se;
+					pack = NULL;
+					anjuta_command_notify_data_arrived (ANJUTA_COMMAND (object));
+				}
+				/* NOTE - mi->line is "editor-style" 1-based, but some things
+					here use/expect 0-base, so adjustments are made as needed */
+
+				if (SA_REPLACE != s->action || !interactive)
+					match_info_free (mi);
+				if (SA_SELECT == s->action ||
+					((SA_REPLACE == s->action || SA_REPLACEALL == s->action) && interactive))
+					break;
+			}
+		}
+		file_buffer_free (fb);
+		d2->data1 = pack;
+		g_mutex_lock (priv->lock_work);
+		if (d2->fb && d2->fb->buf)
+			priv->work_data = g_list_append (priv->work_data, d2);
+		g_mutex_unlock (priv->lock_work);
+
+		anjuta_command_notify_data_arrived (ANJUTA_COMMAND (object));
+
+		if (SA_SELECT == s->action && nb_results > 0)
+			break;
+	}
+	priv->nb_results = nb_results;
+	return 0;
+}
+
+GList * search_get_next_get_entries (SearchGetNext *object)
+{
+	SearchGetNextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate);
+	return priv->entries;
+}
+
+Search * search_get_next_get_s (SearchGetNext *object)
+{
+	SearchGetNextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate);
+	return priv->s;
+}
+
+gint search_get_next_get_nb_result (SearchGetNext *object)
+{
+	SearchGetNextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate);
+	return priv->nb_results;
+}
+
+GList * search_get_next_get_data (SearchGetNext *object)
+{
+	SearchGetNextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(object, SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate);
+	g_mutex_lock (priv->lock_work);
+	GList *t = priv->work_data;
+	priv->work_data = g_list_remove_link (priv->work_data, priv->work_data);
+	g_mutex_unlock (priv->lock_work);
+	return t;
+}
+
+static void
+search_get_next_init (SearchGetNext *object)
+{
+}
+
+static void
+search_get_next_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (search_get_next_parent_class)->finalize (object);
+}
+
+static void
+search_get_next_class_init (SearchGetNextClass *klass)
+{
+	GObjectClass* object_class = G_OBJECT_CLASS (klass);
+	AnjutaCommandClass* parent_class = ANJUTA_COMMAND_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (SearchGetNextPrivate));
+
+	object_class->finalize = search_get_next_finalize;
+	parent_class->run = search_get_next_run;
+}
+
+SearchGetNext *
+search_get_next_new (GList *entries, Search *s, gboolean end_activity, gboolean flag_select,
+						gboolean interactive, SearchReplace *sr)
+{
+	SearchGetNext *self;
+
+	self = g_object_new (SEARCH_TYPE_GET_NEXT, NULL);
+	SearchGetNextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE(self, SEARCH_TYPE_GET_NEXT, SearchGetNextPrivate);
+
+	priv->entries = entries;
+	priv->work_data = NULL;
+	priv->s = s;
+	priv->end_activity = end_activity;
+	priv->flag_select = flag_select;
+	priv->interactive = interactive;
+	priv->sr = sr;
+	priv->lock_work = g_mutex_new();
+	return self;
+}
Index: plugins/search/search-get-next.h
===================================================================
--- plugins/search/search-get-next.h	(revision 0)
+++ plugins/search/search-get-next.h	(revision 0)
@@ -0,0 +1,73 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * anjuta
+ * Copyright (C) Maxim Ermilov 2009 <ermilov.maxim@gmail.com>
+ *
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SEARCH_GET_NEXT_H_
+#define _SEARCH_GET_NEXT_H_
+
+#include <glib-object.h>
+#include <libanjuta/anjuta-async-command.h>
+#include "search-replace_backend.h"
+#include "search-replace.h"
+#include "search_preferences.h"
+
+G_BEGIN_DECLS
+
+#define SEARCH_TYPE_GET_NEXT             (search_get_next_get_type ())
+#define SEARCH_GET_NEXT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEARCH_TYPE_GET_NEXT, SearchGetNext))
+#define SEARCH_GET_NEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SEARCH_TYPE_GET_NEXT, SearchGetNextClass))
+#define SEARCH_IS_GET_NEXT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEARCH_TYPE_GET_NEXT))
+#define SEARCH_IS_GET_NEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SEARCH_TYPE_GET_NEXT))
+#define SEARCH_GET_NEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SEARCH_TYPE_GET_NEXT, SearchGetNextClass))
+
+typedef struct _SearchGetNextClass SearchGetNextClass;
+typedef struct _SearchGetNext SearchGetNext;
+
+struct _SearchGetNextClass
+{
+	AnjutaAsyncCommandClass parent_class;
+};
+
+struct _SearchGetNext
+{
+	AnjutaAsyncCommand parent_instance;
+};
+
+GType search_get_next_get_type (void) G_GNUC_CONST;
+SearchGetNext * search_get_next_new (GList *entries, Search *s, gboolean end_activity,
+										gboolean flag_select, gboolean interactive, SearchReplace *sr);
+
+GList * search_get_next_get_entries (SearchGetNext *object);
+Search * search_get_next_get_s (SearchGetNext *object);
+gint search_get_next_get_nb_result (SearchGetNext *object);
+GList * search_get_next_get_data (SearchGetNext *object);
+
+G_END_DECLS
+struct Data1
+{
+	MatchInfo *mi;
+};
+
+struct Data2
+{
+	GList *data1;
+	FileBuffer *fb;
+	SearchEntry *se;
+};
+
+#endif /* _SEARCH_GET_NEXT_H_ */
Index: plugins/search/search-replace.c
===================================================================
--- plugins/search/search-replace.c	(revision 4699)
+++ plugins/search/search-replace.c	(working copy)
@@ -37,6 +37,7 @@
 #include "search-replace_backend.h"
 #include "search-replace.h"
 #include "search_preferences.h"
+#include "search-get-next.h"
 
 #include <libanjuta/interfaces/ianjuta-project-manager.h>
 #include <glib/gi18n.h>
@@ -274,281 +275,158 @@
 	sr = create_search_replace_instance (dm);
 }
 
-void
-search_and_replace (void)
+static void
+search_update_ui (GList *work_data, IAnjutaMessageView* view, GList *entries, const Search *s, const gint nb_results, gboolean release)
 {
-	GList *entries;
-	GList *tmp;
-	SearchEntry *se;
-	FileBuffer *fb;
-	static MatchInfo *mi;
-	Search *s;
+	gint found_line = 0;
 	gint offset;
-	gint found_line = 0;
+	GList *cur;
+	gboolean save_file = FALSE;
+
+	gchar *regx_pattern;
 	static gint os = 0;
-	gint nb_results;
-	static long start_sel = 0;
-	static long end_sel = 0;
 	static gchar *ch = NULL;
-	gchar *regx_pattern;
-	gboolean save_file = FALSE;
-	IAnjutaMessageManager* msgman;
-	IAnjutaMessageView* view = NULL;
-	gboolean backward;
-					
-	g_return_if_fail(sr);
-	s = &(sr->search);
-	
-	if (s->expr.search_str == NULL)
-		return;
-	
-	entries = create_search_entries(s);
-	if (!entries)
-		return;
-	
-	end_activity = FALSE;
-	backward = (s->range.direction == SD_BACKWARD);
-	
-	search_update_combos (); 
-	if (s->action == SA_REPLACE || s->action == SA_REPLACEALL)
-		replace_update_combos ();
 
-	if (SA_FIND_PANE == s->action)
+	SearchEntry *se;
+	GList *tmp;
+	if (tmp = work_data, tmp != NULL)
 	{
-		/* Avoid space in translated string */
-		gchar* name = g_strconcat(_("Find:"), " ", s->expr.search_str, NULL);		
-		AnjutaShell* shell;
-		g_object_get(G_OBJECT(sr->docman), "shell", &shell, NULL);
-		msgman = anjuta_shell_get_interface(shell, 
-			IAnjutaMessageManager, NULL);
-		g_return_if_fail(msgman != NULL);
-		
-		view = ianjuta_message_manager_get_view_by_name(msgman, name, NULL);
-		if (view == NULL)	
-		{
-			view = ianjuta_message_manager_add_view(msgman, name,
-													GTK_STOCK_FIND_AND_REPLACE, NULL);	
-			g_return_if_fail(view != NULL);
-			g_signal_connect (G_OBJECT(view), "buffer_flushed",
-			                  G_CALLBACK (on_message_buffer_flush), NULL);
-			g_signal_connect (G_OBJECT(view), "message_clicked",
-			                  G_CALLBACK (on_message_clicked), NULL);
-			g_object_weak_ref (G_OBJECT(view), on_message_view_destroyed, NULL);
-		}
-		else
-			ianjuta_message_view_clear(view, NULL);
-		ianjuta_message_manager_set_current_view(msgman, view, NULL);
-	}
-	gtk_widget_set_sensitive (sr_get_gladewidget(STOP_BUTTON)->widget, TRUE);
-	nb_results = 0;
-	for (tmp = entries; tmp && (nb_results <= s->expr.actions_max); 
-		 tmp = g_list_next(tmp))
-	{
-		if (end_activity)
-			break;
-		while(gtk_events_pending())
-			gtk_main_iteration();
-		
-		/*to eliminate un-needed moves, when not bookmarking, this could be
-		  current line i.e. ianjuta_editor_get_lineno (IANJUTA_EDITOR (se->te), NULL);
-		  or sometimes last-line ? */
+		int n;
+		FileBuffer *fb;
+		se = (SearchEntry *) ((struct Data2*)tmp->data)->se;
+		fb = ((struct Data2*)tmp->data)->fb;
 		found_line = (s->action == SA_BOOKMARK) ? -1 : 1;
-
-		se = (SearchEntry *) tmp->data;
-		if (flag_select)
+		offset = 0;
+		for (n = 0, cur = ((struct Data2*)tmp->data)->data1; cur != NULL; cur = g_list_next (cur), n++)
 		{
-			se->start_pos = start_sel;
-			se->end_pos = end_sel;
-		}
-		else
-			end_sel = se->end_pos;
-		if (SE_BUFFER == se->type)
-			fb = file_buffer_new_from_te(se->te);
-		else /* if (SE_FILE == se->type) */
-			fb = file_buffer_new_from_path(se->path, NULL, -1, 0);
+			static MatchInfo *mi;
+			mi = ((struct Data1*)(cur->data))->mi;
+ 			if (s->action == SA_HIGHLIGHT && n == 0)
+ 				ianjuta_indicable_clear (IANJUTA_INDICABLE(fb->te), NULL);
 
-		if (fb && fb->buf)
-		{		
-			fb->pos = se->start_pos;
-			offset = 0;
-		//FIXME enable clearing of marks by some means other than a 0-match search
-			if (s->action == SA_HIGHLIGHT)	
-				ianjuta_indicable_clear (IANJUTA_INDICABLE(fb->te), NULL); 				
-	
-			while (interactive || 
-				NULL != (mi = get_next_match(fb, s->range.direction, &(s->expr))))
+			switch (s->action)
 			{
-				if ((s->range.direction == SD_BACKWARD) && (mi->pos < se->end_pos))
-						break; 
-				if ((s->range.direction != SD_BACKWARD) && ((se->end_pos != -1) &&
-					(mi->pos+mi->len > se->end_pos)))
-						break; 
-				nb_results++; 
-				if (nb_results > sr->search.expr.actions_max)
+				case SA_HIGHLIGHT:
+					found_line = mi->line;
+
+					if (fb->te == NULL)
+						fb->te =
+							IANJUTA_EDITOR (ianjuta_document_manager_get_current_document
+								(sr->docman, NULL));
+
+					if (IANJUTA_INDICABLE (fb->te))
+					{
+						IAnjutaIterable *start_pos, *end_pos;
+						/* end-location is correct for sourceview, 1-too-big for scintilla */
+						start_pos = ianjuta_editor_get_position_from_offset (fb->te, mi->pos, NULL);
+						end_pos = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len, NULL);
+						ianjuta_indicable_set (IANJUTA_INDICABLE(fb->te),
+											   start_pos, end_pos,
+											   IANJUTA_INDICABLE_IMPORTANT, NULL);
+						g_object_unref (start_pos);
+						g_object_unref (end_pos);
+					}
 					break;
-				
-				/* NOTE - mi->line is "editor-style" 1-based, but some things
-					here use/expect 0-base, so adjustments are made as needed */
-				
-				switch (s->action)
-				{
-					case SA_HIGHLIGHT:
-						found_line = mi->line;
 
-						if (fb->te == NULL)
-							fb->te =
-								IANJUTA_EDITOR (ianjuta_document_manager_get_current_document
-									(sr->docman, NULL));
+				case SA_BOOKMARK:
+					if (found_line != mi->line)
+					{
+						GFile* file = g_file_new_for_uri (fb->uri);
+						found_line = mi->line + 1; /* different line count between search and editor */
+						ianjuta_document_manager_add_bookmark (sr->docman,
+															   file,
+															   found_line,
+															   NULL);
+						g_object_unref (file);
+					}
+					break;
 
-						if (IANJUTA_INDICABLE (fb->te))
+				case SA_SELECT:
+					if (found_line != mi->line || fb->te == NULL)
+					{
+						if (fb->te)
+							ianjuta_editor_goto_line (fb->te, mi->line, NULL);
+						else
 						{
-							IAnjutaIterable *start_pos, *end_pos;
-							/* end-location is correct for sourceview, 1-too-big for scintilla */
-							start_pos = ianjuta_editor_get_position_from_offset (fb->te, mi->pos, NULL);
-							end_pos = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len, NULL);
-							ianjuta_indicable_set (IANJUTA_INDICABLE(fb->te),
-												   start_pos, end_pos,
-												   IANJUTA_INDICABLE_IMPORTANT, NULL);
-							g_object_unref (start_pos);
-							g_object_unref (end_pos);
-						}
-						break;
-
-					case SA_BOOKMARK:
-						if (found_line != mi->line)
-						{
 							GFile* file = g_file_new_for_uri (fb->uri);
-							found_line = mi->line + 1; /* different line count between search and editor */
-							ianjuta_document_manager_add_bookmark (sr->docman,
-																   file,
-																   found_line,
-																   NULL);
-							g_object_unref (file);			  
+							fb->te = ianjuta_document_manager_goto_file_line_mark
+								(sr->docman, file, mi->line, FALSE, NULL);
+							g_object_unref (file);
 						}
+						found_line = mi->line;
+					}
+					{
+						IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos, NULL);
+						IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len, NULL);
+						ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te),
+													 start,
+													 end,
+													 TRUE,
+													 NULL);
+						g_object_unref (start);
+						g_object_unref (end);
 						break;
-						
-					case SA_SELECT:
-						if (found_line != mi->line || fb->te == NULL)
-						{
-							if (fb->te)
-								ianjuta_editor_goto_line (fb->te, mi->line, NULL);
-							else
-							{
-								GFile* file = g_file_new_for_uri (fb->uri);
-								fb->te = ianjuta_document_manager_goto_file_line_mark
-									(sr->docman, file, mi->line, FALSE, NULL);
-								g_object_unref (file);
-							}
-							found_line = mi->line;
-						}
-						{
-							IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos, NULL);
-							IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len, NULL);
-							ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te), 
-														 start,
-														 end,
-														 TRUE,
-														 NULL);
-							g_object_unref (start);
-							g_object_unref (end);
-							break;
-						}
-						
-					case SA_FIND_PANE: 
-						write_message_pane(view, fb, se, mi);
-						break;
-					
-					case SA_REPLACE:
-						if (found_line != mi->line || fb->te == NULL)
-							{
-							if (fb->te)
-								ianjuta_editor_goto_line (fb->te, mi->line, NULL);
-							else
-							{
-								GFile* file = g_file_new_for_uri (fb->uri);
-								fb->te = ianjuta_document_manager_goto_file_line_mark
-									(sr->docman, file, mi->line, FALSE, NULL);
-								g_object_unref (file);
-							}
-							found_line = mi->line;
-							}
+					}
 
-						if (!interactive)
+				case SA_FIND_PANE:
+					write_message_pane(view, fb, se, mi);
+					break;
+
+				case SA_REPLACE:
+					if (found_line != mi->line || fb->te == NULL)
 						{
-							IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - offset, NULL);
-							IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - offset + mi->len, NULL);
-							ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te), 
-														 start,
-														 end,
-														 TRUE,
-														 NULL);
-							g_object_unref (start);
-							g_object_unref (end);
-							interactive = TRUE;
-							os = offset;
-							modify_label_image_button(SEARCH_BUTTON, _("Replace"), 
-								                      GTK_STOCK_FIND_AND_REPLACE);
-							show_jump_button(TRUE);
-							if (sr->replace.regex && sr->search.expr.regex)
-							{
-									g_free (ch);
-								ch = regex_backref (mi, fb);
-								}
-							}
+						if (fb->te)
+							ianjuta_editor_goto_line (fb->te, mi->line, NULL);
 						else
 						{
-						if (ch && sr->replace.regex && sr->search.expr.regex)
-						{
-								g_free (sr->replace.repl_str);
-								sr->replace.repl_str = g_strdup (ch);
-							g_free (ch);
-								ch = NULL;
+							GFile* file = g_file_new_for_uri (fb->uri);
+							fb->te = ianjuta_document_manager_goto_file_line_mark
+								(sr->docman, file, mi->line, FALSE, NULL);
+							g_object_unref (file);
 						}
-							{
-								IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - os, NULL);
-								IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len - os, NULL);
-								ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te),  
-															 start,														 
-															 end,
-															 TRUE,
-															 NULL);
-								ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb->te), 
-																 sr->replace.repl_str,
-																 strlen(sr->replace.repl_str),
-																 NULL);
-								g_object_unref (start);
-								g_object_unref (end);
-							}
-						if (se->direction != SD_BACKWARD)
-							offset += mi->len - (sr->replace.repl_str?strlen(sr->replace.repl_str):0);
-						
-						interactive = FALSE;
+						found_line = mi->line;
 						}
-						break;
 
-					case SA_REPLACEALL:
+					if (!interactive)
+					{
+						IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - offset, NULL);
+						IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - offset + mi->len, NULL);
+						ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te),
+													 start,
+													 end,
+													 TRUE,
+													 NULL);
+						g_object_unref (start);
+						g_object_unref (end);
+						interactive = TRUE;
+						os = offset;
+						modify_label_image_button(SEARCH_BUTTON, _("Replace"),
+							                      GTK_STOCK_FIND_AND_REPLACE);
+						show_jump_button(TRUE);
 						if (sr->replace.regex && sr->search.expr.regex)
 						{
-							regx_pattern = sr->replace.repl_str;	/* preserve for later matches */
-							sr->replace.repl_str = regex_backref (mi, fb);
+								g_free (ch);
+							ch = regex_backref (mi, fb);
+							}
 						}
-						else
-							regx_pattern = NULL;
-						if (fb->te == NULL) /* NON OPENED FILES */
+					else
+					{
+						if (ch && sr->replace.regex && sr->search.expr.regex)
 						{
-							if (replace_in_not_opened_files(fb, mi, sr->replace.repl_str))
-								save_file = TRUE;
+							g_free (sr->replace.repl_str);
+							sr->replace.repl_str = g_strdup (ch);
+							g_free (ch);
+							ch = NULL;
 						}
-						else
 						{
-							IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - offset, NULL);
-							IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len - offset, NULL);
-							ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te),  
+							IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - os, NULL);
+							IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len - os, NULL);
+							ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te),
 														 start,
 														 end,
 														 TRUE,
 														 NULL);
-							ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb->te), 
+							ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb->te),
 															 sr->replace.repl_str,
 															 strlen(sr->replace.repl_str),
 															 NULL);
@@ -556,72 +434,195 @@
 							g_object_unref (end);
 						}
 						if (se->direction != SD_BACKWARD)
- 							offset += mi->len - (sr->replace.repl_str?strlen(sr->replace.repl_str):0);
-						if (regx_pattern)
-						{
-							g_free (sr->replace.repl_str);
-							sr->replace.repl_str = regx_pattern;
-						}
-						break;
+							offset += mi->len - (sr->replace.repl_str?strlen(sr->replace.repl_str):0);
 
-					default:
-						g_warning ("Not implemented - File %s - Line %d\n", __FILE__, __LINE__);
-						break;
-				}  // switch
+						interactive = FALSE;
+					}
+					break;
 
-				if (se->direction != SD_BACKWARD)
-					start_sel = mi->pos + mi->len - offset; 
-				else
-					start_sel = mi->pos - offset; 
-				
-				if (SA_REPLACE != s->action || !interactive)
-					match_info_free(mi);
-				
-				if (SA_SELECT == s->action ||
-					((SA_REPLACE == s->action || SA_REPLACEALL == s->action) && interactive))
+				case SA_REPLACEALL:
+					if (sr->replace.regex && sr->search.expr.regex)
+					{
+						regx_pattern = sr->replace.repl_str;	/* preserve for later matches */
+						sr->replace.repl_str = regex_backref (mi, fb);
+					}
+					else
+						regx_pattern = NULL;
+					if (fb->te == NULL) /* NON OPENED FILES */
+					{
+						if (replace_in_not_opened_files(fb, mi, sr->replace.repl_str))
+							save_file = TRUE;
+					}
+					else
+					{
+						IAnjutaIterable* start = ianjuta_editor_get_position_from_offset (fb->te, mi->pos - offset, NULL);
+						IAnjutaIterable* end = ianjuta_editor_get_position_from_offset (fb->te, mi->pos + mi->len - offset, NULL);
+						ianjuta_editor_selection_set(IANJUTA_EDITOR_SELECTION (fb->te),
+													 start,
+													 end,
+													 TRUE,
+													 NULL);
+						ianjuta_editor_selection_replace(IANJUTA_EDITOR_SELECTION (fb->te),
+														 sr->replace.repl_str,
+														 strlen(sr->replace.repl_str),
+														 NULL);
+						g_object_unref (start);
+						g_object_unref (end);
+					}
+					if (se->direction != SD_BACKWARD)
+							offset += mi->len - (sr->replace.repl_str?strlen(sr->replace.repl_str):0);
+					if (regx_pattern)
+					{
+						g_free (sr->replace.repl_str);
+						sr->replace.repl_str = regx_pattern;
+					}
 					break;
-			}
-			if (save_file)
-			{
-				save_not_opened_files (fb);
-				save_file = FALSE;
-			}
-			
+
+				default:
+					g_warning ("Not implemented - File %s - Line %d\n", __FILE__, __LINE__);
+					break;
+			}  // switch
+			if (SA_REPLACE != s->action || !interactive)
+				match_info_free (mi);
 		}
+
+		if (save_file)
+		{
+			save_not_opened_files (fb);
+			save_file = FALSE;
+		}
 		file_buffer_free (fb);
+		g_list_free (((struct Data2*)tmp->data)->data1);
+		g_free (((struct Data2*)tmp->data));
+	}
 
-		if (SA_SELECT == s->action && nb_results > 0)
-			break;
+	if (release)
+	{
+		gtk_widget_set_sensitive (sr_get_gladewidget(STOP_BUTTON)->widget, FALSE);
+
+		if (s->range.type == SR_BLOCK || s->range.type == SR_FUNCTION ||
+			s->range.type == SR_SELECTION)
+				flag_select = TRUE;
+
+		free_search_entries  (entries);
+
+		if (s->action == SA_FIND_PANE)
+		{
+			ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_INFO,
+										 _("Search complete"), "", NULL);
+		}
+
+		if (nb_results == 0)
+		{
+			search_end_alert(sr->search.expr.search_str);
+		}
+		else if (nb_results > sr->search.expr.actions_max)
+			max_results_alert();
+		else if (s->action == SA_REPLACEALL)
+			nb_results_alert(nb_results);
+
+		if ((s->range.direction == SD_BEGINNING) &&
+			((s->action == SA_SELECT) || (s->action == SA_REPLACE)) )
+		{
+			search_set_direction(SD_FORWARD);
+		}
 	}
+}
 
-	gtk_widget_set_sensitive (sr_get_gladewidget(STOP_BUTTON)->widget, FALSE);
-	
-	if (s->range.type == SR_BLOCK || s->range.type == SR_FUNCTION || 
-		s->range.type == SR_SELECTION)
-			flag_select = TRUE;
-	
-	free_search_entries  (entries);
-	
-	if (s->action == SA_FIND_PANE)
+static void
+on_search_get_next_process (AnjutaCommand *command, IAnjutaMessageView* view)
+{
+	GList * entries = search_get_next_get_entries (SEARCH_GET_NEXT (command));
+	Search *s = search_get_next_get_s (SEARCH_GET_NEXT (command));
+	gint nb_res = search_get_next_get_nb_result (SEARCH_GET_NEXT (command));
+	GList *work_data;
+	while (work_data = search_get_next_get_data (SEARCH_GET_NEXT (command)), work_data != NULL)
 	{
-		ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_INFO,
-									 _("Search complete"), "", NULL);
+		search_update_ui (work_data, view, entries, s, nb_res, FALSE);
+		while (g_main_context_pending (NULL))
+		{
+			g_main_context_iteration (NULL, FALSE);
+		}
 	}
-	
-	if (nb_results == 0)
+}
+
+static void
+on_search_get_next_complete (AnjutaCommand *command, guint return_code, IAnjutaMessageView* view)
+{
+	GList * entries = search_get_next_get_entries (SEARCH_GET_NEXT (command));
+	Search *s = search_get_next_get_s (SEARCH_GET_NEXT (command));
+	gint nb_res = search_get_next_get_nb_result (SEARCH_GET_NEXT (command));
+	GList *work_data;
+	while (work_data = search_get_next_get_data (SEARCH_GET_NEXT (command)), work_data != NULL)
 	{
-		search_end_alert(sr->search.expr.search_str);
+		search_update_ui (work_data, view, entries, s, nb_res, FALSE);
+		while (g_main_context_pending (NULL))
+		{
+			g_main_context_iteration (NULL, FALSE);
+		}
 	}
-	else if (nb_results > sr->search.expr.actions_max)
-		max_results_alert();
-	else if (s->action == SA_REPLACEALL)
-		nb_results_alert(nb_results);
-	
-	if ((s->range.direction == SD_BEGINNING) &&
-		((s->action == SA_SELECT) || (s->action == SA_REPLACE)) )
+	search_update_ui (NULL, view, entries, s, nb_res, TRUE);
+}
+
+void
+search_and_replace (void)
+{
+	GList *entries;
+	Search *s;
+	IAnjutaMessageManager* msgman;
+	IAnjutaMessageView* view = NULL;
+	gboolean backward;
+	SearchGetNext *command;
+
+	g_return_if_fail(sr);
+	s = &(sr->search);
+
+	if (s->expr.search_str == NULL)
+		return;
+
+	entries = create_search_entries(s);
+	if (!entries)
+		return;
+
+	end_activity = FALSE;
+	backward = (s->range.direction == SD_BACKWARD);
+
+	search_update_combos ();
+	if (s->action == SA_REPLACE || s->action == SA_REPLACEALL)
+		replace_update_combos ();
+
+	if (SA_FIND_PANE == s->action)
 	{
-		search_set_direction(SD_FORWARD);
+		/* Avoid space in translated string */
+		gchar* name = g_strconcat(_("Find:"), " ", s->expr.search_str, NULL);
+		AnjutaShell* shell;
+		g_object_get(G_OBJECT(sr->docman), "shell", &shell, NULL);
+		msgman = anjuta_shell_get_interface(shell,
+			IAnjutaMessageManager, NULL);
+		g_return_if_fail(msgman != NULL);
+
+		view = ianjuta_message_manager_get_view_by_name(msgman, name, NULL);
+		if (view == NULL)
+		{
+			view = ianjuta_message_manager_add_view(msgman, name,
+													GTK_STOCK_FIND_AND_REPLACE, NULL);
+			g_return_if_fail(view != NULL);
+			g_signal_connect (G_OBJECT(view), "buffer_flushed",
+			                  G_CALLBACK (on_message_buffer_flush), NULL);
+			g_signal_connect (G_OBJECT(view), "message_clicked",
+			                  G_CALLBACK (on_message_clicked), NULL);
+			g_object_weak_ref (G_OBJECT(view), on_message_view_destroyed, NULL);
+		}
+		else
+			ianjuta_message_view_clear(view, NULL);
+		ianjuta_message_manager_set_current_view(msgman, view, NULL);
 	}
+	gtk_widget_set_sensitive (sr_get_gladewidget(STOP_BUTTON)->widget, TRUE);
+
+	command = search_get_next_new (entries, s, end_activity, flag_select, interactive, sr);
+	g_signal_connect (command, "data-arrived", G_CALLBACK (on_search_get_next_process), view);
+	g_signal_connect (command, "command-finished", G_CALLBACK (on_search_get_next_complete), view);
+	anjuta_command_start (ANJUTA_COMMAND (command));
 }
 
 static void
Index: plugins/search/search-replace_backend.c
===================================================================
--- plugins/search/search-replace_backend.c	(revision 4699)
+++ plugins/search/search-replace_backend.c	(working copy)
@@ -139,6 +139,33 @@
 	return fb;
 }
 
+FileBuffer *
+file_buffer_dup (FileBuffer *in)
+{
+	GList *i;
+	FileBuffer *out;
+	if (in == NULL)
+		return NULL;
+	out = g_new (FileBuffer, 1);
+	out->len = in->len;
+
+	out->line = in->line;
+	out->pos = in->pos;
+	out->name = g_strdup (in->name);
+	out->path = g_strdup (in->path);
+	out->uri = g_strdup (in->uri);
+
+	out->buf = g_strdup (in->buf);
+	out->canonical = g_strdup (in->canonical);
+	out->canonical_p = g_strdup (in->canonical_p);
+
+	out->lines = NULL;
+	for (i = in->lines; i != NULL; i = g_list_next(i))
+		out->lines = g_list_append (out->lines, GINT_TO_POINTER(i->data));
+	out->te = in->te;
+	return out;
+}
+
 /* Only use the first 500 chars for validating (yes, I feel lucky...) */
 #define MAX_VALIDATE 500
 
@@ -507,6 +534,24 @@
 	return mi;
 }
 
+MatchInfo *match_info_dup(MatchInfo * in)
+{
+	GList *i;
+	MatchInfo *out = g_new (MatchInfo, 1);
+	out->len = in->len;
+	out->line = in->line;
+	out->pos = in->pos;
+	out->subs = NULL;
+	for (i = in->subs; i != NULL; i = g_list_next (i))
+	{
+		MatchSubStr *t = g_new (MatchSubStr, 1);
+		t->len = ((MatchSubStr *)(i->data))->len;
+		t->start = ((MatchSubStr *)(i->data))->start;
+		out->subs = g_list_append (out->subs, t);
+	}
+	return out;
+}
+
 static MatchInfo *match_info(FileBuffer *fb, gchar* match, gchar* match_end,
 							 SearchDirection direction)
 {
Index: plugins/search/Makefile.am
===================================================================
--- plugins/search/Makefile.am	(revision 4699)
+++ plugins/search/Makefile.am	(working copy)
@@ -44,7 +44,9 @@
 	search-replace_backend.c \
 	search-replace_backend.h \
 	search_preferences.c \
-	search_preferences.h
+	search_preferences.h \
+	search-get-next.c \
+	search-get-next.h
 
 EXTRA_DIST = \
 	$(plugin_in_files) \
Index: plugins/search/search-replace_backend.h
===================================================================
--- plugins/search/search-replace_backend.h	(revision 4699)
+++ plugins/search/search-replace_backend.h	(working copy)
@@ -215,9 +215,12 @@
 gchar *regex_backref(MatchInfo *mi, FileBuffer *fb);
 
 void match_info_free (MatchInfo *mi);
+MatchInfo *match_info_dup(MatchInfo * in);
 
 void file_buffer_free (FileBuffer *fb);
 
+FileBuffer* file_buffer_dup (FileBuffer *in);
+
 SearchReplace *create_search_replace_instance(IAnjutaDocumentManager *docman);
 
 #ifdef __cplusplus
