Branch: refs/heads/document-messages Author: Nick Treleaven nick.treleaven@btinternet.com Committer: Nick Treleaven nick.treleaven@btinternet.com Date: Sun, 25 Dec 2011 13:23:06 Commit: c2481ccb9544c22258278dcb1b503c2e26baecd1 https://github.com/geany/geany/commit/c2481ccb9544c22258278dcb1b503c2e26baec...
Log Message: ----------- Use GRegex matching for Find & Replace commands
Modified Paths: -------------- src/search.c
Modified: src/search.c 106 files changed, 61 insertions(+), 45 deletions(-) =================================================================== @@ -51,12 +51,6 @@ # include <sys/wait.h> #endif
-#ifdef HAVE_REGEX_H -# include <regex.h> -#else -# include "gnuregex.h" -#endif -
enum { @@ -1822,84 +1816,106 @@ static void search_close_pid(GPid child_pid, gint status, gpointer user_data) }
-static gboolean compile_regex(regex_t *regex, const gchar *str, gint sflags) +static GRegex *compile_regex(const gchar *str, gint sflags) { - gint err; - gint rflags = REG_EXTENDED | REG_NEWLINE; + GRegex *regex; + GError *error = NULL; + gint rflags = G_REGEX_MULTILINE;
if (~sflags & SCFIND_MATCHCASE) - rflags |= REG_ICASE; + rflags |= G_REGEX_CASELESS; if (sflags & (SCFIND_WHOLEWORD | SCFIND_WORDSTART)) { geany_debug("%s: Unsupported regex flags found!", G_STRFUNC); }
- err = regcomp(regex, str, rflags); - if (err != 0) + regex = g_regex_new(str, rflags, 0, &error); + if (!regex) { - gchar buf[256]; - - regerror(err, regex, buf, sizeof buf); - ui_set_statusbar(FALSE, _("Bad regex: %s"), buf); - return FALSE; + ui_set_statusbar(FALSE, _("Bad regex: %s"), error->message); + g_error_free(error); } - return TRUE; + return regex; }
+typedef struct CharOffsets +{ + gint start, end; +} CharOffsets; + +static CharOffsets regex_matches[10]; + /* groups that don't exist are handled OK as len = end - start = (-1) - (-1) = 0 */ -static gchar *get_regex_match_string(const gchar *text, regmatch_t *pmatch, gint match_idx) +static gchar *get_regex_match_string(const gchar *text, CharOffsets *match) { - return g_strndup(&text[pmatch[match_idx].rm_so], - pmatch[match_idx].rm_eo - pmatch[match_idx].rm_so); + return g_strndup(&text[match->start], match->end - match->start); }
-static regmatch_t regex_matches[10]; -/* All matching text from regex_matches[0].rm_so to regex_matches[0].rm_eo */ +/* All matching text from regex_matches[0].start to regex_matches[0].end */ static gchar *regex_match_text = NULL;
-static gint find_regex(ScintillaObject *sci, guint pos, regex_t *regex) +static gint find_regex(ScintillaObject *sci, guint pos, GRegex *regex) { const gchar *text; gint flags = 0; + GMatchInfo *minfo; + gint ret = -1;
g_return_val_if_fail(pos <= (guint)sci_get_length(sci), FALSE);
+ /* clear old match */ + setptr(regex_match_text, NULL); + if (sci_get_col_from_position(sci, pos) != 0) - flags = REG_NOTBOL; + flags = G_REGEX_MATCH_NOTBOL; /* Warning: any SCI calls will invalidate 'text' after calling SCI_GETCHARACTERPOINTER */ text = (void*)scintilla_send_message(sci, SCI_GETCHARACTERPOINTER, 0, 0); text += pos;
- if (regexec(regex, text, G_N_ELEMENTS(regex_matches), regex_matches, flags) == 0) + /* Warning: minfo will become invalid when 'text' does! */ + if (g_regex_match(regex, text, flags, &minfo)) { - setptr(regex_match_text, get_regex_match_string(text, regex_matches, 0)); - return regex_matches[0].rm_so + pos; + gint i; + + /* copy whole match text and offsets before they become invalid */ + regex_match_text = g_match_info_fetch(minfo, 0); + + foreach_range(i, G_N_ELEMENTS(regex_matches)) + { + gint start = -1, end = -1; + + g_match_info_fetch_pos(minfo, i, &start, &end); + regex_matches[i].start = start; + regex_matches[i].end = end; + } + ret = regex_matches[0].start + pos; } - setptr(regex_match_text, NULL); - return -1; + g_match_info_free(minfo); + return ret; }
gint search_find_next(ScintillaObject *sci, const gchar *str, gint flags) { - regex_t regex; + GRegex *regex; gint ret = -1; gint pos;
if (~flags & SCFIND_REGEXP) return sci_search_next(sci, flags, str);
- if (!compile_regex(®ex, str, flags)) + regex = compile_regex(str, flags); + if (!regex) return -1;
pos = sci_get_current_position(sci); - ret = find_regex(sci, pos, ®ex); + ret = find_regex(sci, pos, regex); if (ret >= 0) - sci_set_selection(sci, ret, regex_matches[0].rm_eo + pos); + sci_set_selection(sci, ret, regex_matches[0].end + pos);
- regfree(®ex); + g_regex_unref(regex); return ret; }
@@ -1937,8 +1953,8 @@ gint search_replace_target(ScintillaObject *sci, const gchar *replace_text, /* digit escape */ g_string_erase(str, i, 2); /* fix match offsets by subtracting index of whole match start from the string */ - grp = get_regex_match_string(regex_match_text - regex_matches[0].rm_so, - regex_matches, c - '0'); + grp = get_regex_match_string(regex_match_text - regex_matches[0].start, + ®ex_matches[c - '0']); g_string_insert(str, i, grp); i += strlen(grp); g_free(grp); @@ -1951,27 +1967,27 @@ gint search_replace_target(ScintillaObject *sci, const gchar *replace_text,
gint search_find_text(ScintillaObject *sci, gint flags, struct Sci_TextToFind *ttf) { - regex_t regex; + GRegex *regex; gint pos; gint ret;
if (~flags & SCFIND_REGEXP) return sci_find_text(sci, flags, ttf);
- if (!compile_regex(®ex, ttf->lpstrText, flags)) + regex = compile_regex(ttf->lpstrText, flags); + if (!regex) return -1;
pos = ttf->chrg.cpMin; - ret = find_regex(sci, pos, ®ex); - regfree(®ex); + ret = find_regex(sci, pos, regex);
if (ret >= 0 && ret < ttf->chrg.cpMax) { - ttf->chrgText.cpMin = regex_matches[0].rm_so + pos; - ttf->chrgText.cpMax = regex_matches[0].rm_eo + pos; - return ret; + ttf->chrgText.cpMin = regex_matches[0].start + pos; + ttf->chrgText.cpMax = regex_matches[0].end + pos; } - return -1; + g_regex_unref(regex); + return ret; }
@@ Diff output truncated at 100000 characters. @@
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: TBD).