Permalink
Browse files

Fix crash with bulk pattern replacements (introduced with c83a93e)

"regex_match_text" and "regex_matches" being globals, performing
several searches and then the replacements separately lead to them
having unexpected values, resulting in incorrect behavior and crash.

Fix this by removing the globals and instead make the search functions
return match details.  Not only this fixes the issue, but also make the
code a lot more maintainable by not having globals introducing side
effects (proof of them being an issue is that c83a93e inadvertently
broke things bad).
  • Loading branch information...
b4n committed Apr 12, 2013
1 parent 920969e commit 5412a244ba903624053cdaf7393732bc3af689ea
Showing with 157 additions and 82 deletions.
  1. +15 −11 src/document.c
  2. +3 −1 src/document.h
  3. +116 −66 src/search.c
  4. +23 −4 src/search.h
View
@@ -1378,7 +1378,7 @@ static void replace_header_filename(GeanyDocument *doc)
ttf.chrg.cpMax = sci_get_position_from_line(doc->editor->sci, 4);
ttf.lpstrText = filebase;
- if (search_find_text(doc->editor->sci, SCFIND_MATCHCASE | SCFIND_REGEXP, &ttf) != -1)
+ if (search_find_text(doc->editor->sci, SCFIND_MATCHCASE | SCFIND_REGEXP, &ttf, NULL) != -1)
{
sci_set_target_start(doc->editor->sci, ttf.chrgText.cpMin);
sci_set_target_end(doc->editor->sci, ttf.chrgText.cpMax);
@@ -1894,7 +1894,8 @@ gboolean document_search_bar_find(GeanyDocument *doc, const gchar *text, gint fl
* @param original_text Text as it was entered by user, or @c NULL to use @c text
*/
gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *original_text,
- gint flags, gboolean search_backwards, gboolean scroll, GtkWidget *parent)
+ gint flags, gboolean search_backwards, GeanyMatchInfo **match_,
+ gboolean scroll, GtkWidget *parent)
{
gint selection_end, selection_start, search_pos;
@@ -1921,9 +1922,9 @@ gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *orig
sci_set_search_anchor(doc->editor->sci);
if (search_backwards)
- search_pos = sci_search_prev(doc->editor->sci, flags, text);
+ search_pos = search_find_prev(doc->editor->sci, text, flags, match_);
else
- search_pos = search_find_next(doc->editor->sci, text, flags);
+ search_pos = search_find_next(doc->editor->sci, text, flags, match_);
if (search_pos != -1)
{
@@ -1954,7 +1955,7 @@ gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *orig
gint ret;
sci_set_current_position(doc->editor->sci, (search_backwards) ? sci_len : 0, FALSE);
- ret = document_find_text(doc, text, original_text, flags, search_backwards, scroll, parent);
+ ret = document_find_text(doc, text, original_text, flags, search_backwards, match_, scroll, parent);
if (ret == -1)
{ /* return to original cursor position if not found */
sci_set_current_position(doc->editor->sci, selection_start, FALSE);
@@ -1976,6 +1977,7 @@ gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gch
const gchar *replace_text, gint flags, gboolean search_backwards)
{
gint selection_end, selection_start, search_pos;
+ GeanyMatchInfo *match = NULL;
g_return_val_if_fail(doc != NULL && find_text != NULL && replace_text != NULL, -1);
@@ -1994,7 +1996,7 @@ gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gch
if (selection_end == selection_start)
{
/* no selection so just find the next match */
- document_find_text(doc, find_text, original_find_text, flags, search_backwards, TRUE, NULL);
+ document_find_text(doc, find_text, original_find_text, flags, search_backwards, NULL, TRUE, NULL);
return -1;
}
/* there's a selection so go to the start before finding to search through it
@@ -2004,20 +2006,22 @@ gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gch
else
sci_goto_pos(doc->editor->sci, selection_start, TRUE);
- search_pos = document_find_text(doc, find_text, original_find_text, flags, search_backwards, TRUE, NULL);
+ search_pos = document_find_text(doc, find_text, original_find_text, flags, search_backwards, &match, TRUE, NULL);
/* return if the original selected text did not match (at the start of the selection) */
if (search_pos != selection_start)
+ {
+ if (search_pos != -1)
+ geany_match_info_free(match);
return -1;
+ }
if (search_pos != -1)
{
- gint replace_len;
- /* search next/prev will select matching text, which we use to set the replace target */
- sci_target_from_selection(doc->editor->sci);
- replace_len = search_replace_target(doc->editor->sci, replace_text, flags & SCFIND_REGEXP);
+ gint replace_len = search_replace_match(doc->editor->sci, match, replace_text);
/* select the replacement - find text will skip past the selected text */
sci_set_selection_start(doc->editor->sci, search_pos);
sci_set_selection_end(doc->editor->sci, search_pos + replace_len);
+ geany_match_info_free(match);
}
else
{
View
@@ -34,6 +34,7 @@ G_BEGIN_DECLS
#include "Scintilla.h"
#include "ScintillaWidget.h"
#include "editor.h"
+#include "search.h"
#if defined(G_OS_WIN32)
# define GEANY_DEFAULT_EOL_CHARACTER SC_EOL_CRLF
@@ -222,7 +223,8 @@ gboolean document_search_bar_find(GeanyDocument *doc, const gchar *text, gint fl
gboolean backwards);
gint document_find_text(GeanyDocument *doc, const gchar *text, const gchar *original_text,
- gint flags, gboolean search_backwards, gboolean scroll, GtkWidget *parent);
+ gint flags, gboolean search_backwards, GeanyMatchInfo **match_,
+ gboolean scroll, GtkWidget *parent);
gint document_replace_text(GeanyDocument *doc, const gchar *find_text, const gchar *original_find_text,
const gchar *replace_text, gint flags, gboolean search_backwards);
Oops, something went wrong.

0 comments on commit 5412a24

Please sign in to comment.