Revision: 581 Author: ntrel Date: 2006-07-18 07:09:01 -0700 (Tue, 18 Jul 2006) ViewCVS: http://svn.sourceforge.net/geany/?rev=581&view=rev
Log Message: ----------- Fix replacing the right length of text matched from a regex; Add support for back references when replacing with regex; Improve the speed of replace all/replace in selection; Don't lose the selection range after replacing in selection
Modified Paths: -------------- trunk/ChangeLog trunk/src/document.c trunk/src/sciwrappers.c trunk/src/sciwrappers.h Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2006-07-18 12:28:04 UTC (rev 580) +++ trunk/ChangeLog 2006-07-18 14:09:01 UTC (rev 581) @@ -1,3 +1,12 @@ +2006-07-18 Nick Treleaven nick.treleaven@btinternet.com + + * src/sciwrappers.c, src/sciwrappers.h, src/document.c: + Fix replacing the right length of text matched from a regex. + Add support for back references when replacing with regex. + Improve the speed of replace all/replace in selection. + Don't lose the selection range after replacing in selection. + + 2006-07-18 Enrico Tröger enrico.troeger@uvena.de
* src/dialogs.c, src/callbacks.c:
Modified: trunk/src/document.c =================================================================== --- trunk/src/document.c 2006-07-18 12:28:04 UTC (rev 580) +++ trunk/src/document.c 2006-07-18 14:09:01 UTC (rev 581) @@ -58,7 +58,13 @@ #include "notebook.h"
+/* Returns -1 if no text found or the new range endpoint after replacing. + * show_last is whether to select and scroll the last replacement in view. */ +static gint +document_replace_range(gint idx, const gchar *find_text, const gchar *replace_text, gint flags, + gint start, gint end, gboolean show_last);
+ /* returns the index of the notebook page which has the given filename * is_tm_filename is needed when passing TagManager filenames because they are * dereferenced, and would not match the link filename. */ @@ -765,9 +771,9 @@ void document_replace_text(gint idx, const gchar *find_text, const gchar *replace_text, gint flags, gboolean search_backwards) { gint selection_end, selection_start, search_pos; - gint find_text_len = strlen(find_text);
- if (idx == -1 || ! find_text_len) return; + g_return_if_fail(find_text != NULL && replace_text != NULL); + if (idx == -1 || ! *find_text) return;
selection_start = sci_get_selection_start(doc_list[idx].sci); selection_end = sci_get_selection_end(doc_list[idx].sci); @@ -787,12 +793,14 @@
if (search_pos != -1) { - sci_target_start(doc_list[idx].sci, search_pos); - sci_target_end(doc_list[idx].sci, search_pos + find_text_len); - sci_target_replace(doc_list[idx].sci, replace_text); + gint replace_len; + // search next/prev will select matching text, which we use to set the replace target + sci_target_from_selection(doc_list[idx].sci); + replace_len = sci_target_replace(doc_list[idx].sci, replace_text, flags & SCFIND_REGEXP); + // select the replacement and scroll in view + sci_set_selection_start(doc_list[idx].sci, search_pos); + sci_set_selection_end(doc_list[idx].sci, search_pos + replace_len); sci_scroll_caret(doc_list[idx].sci); - sci_set_selection_start(doc_list[idx].sci, search_pos); - sci_set_selection_end(doc_list[idx].sci, search_pos + strlen(replace_text)); } else { @@ -801,83 +809,106 @@ }
-void document_replace_sel(gint idx, const gchar *find_text, const gchar *replace_text, gint flags) +/* Returns -1 if no text found or the new range endpoint after replacing. + * show_last is whether to select and scroll the last replacement in view. */ +static gint +document_replace_range(gint idx, const gchar *find_text, const gchar *replace_text, gint flags, + gint start, gint end, gboolean show_last) { - gint selection_end, selection_start, search_pos; - gint anchor_pos; - gint find_text_len = strlen(find_text); - gint replace_text_len = strlen(replace_text); + gint search_pos; + gint find_len = 0, replace_len = 0; + gboolean match_found = FALSE; + struct TextToFind ttf;
- if (idx == -1 || ! find_text_len) return; + g_return_val_if_fail(find_text != NULL && replace_text != NULL, FALSE); + if (idx == -1 || ! *find_text) return FALSE;
- selection_start = sci_get_selection_start(doc_list[idx].sci); - selection_end = sci_get_selection_end(doc_list[idx].sci); - if ((selection_end - selection_start) == 0) - { - utils_beep(); - return; - } + sci_start_undo_action(doc_list[idx].sci); + ttf.chrg.cpMin = start; + ttf.chrg.cpMax = end; + ttf.lpstrText = (gchar*)find_text;
- sci_start_undo_action(doc_list[idx].sci); - anchor_pos = selection_start; while (TRUE) { - sci_goto_pos(doc_list[idx].sci, anchor_pos, TRUE); - sci_set_search_anchor(doc_list[idx].sci); - search_pos = sci_search_next(doc_list[idx].sci, flags, find_text); + search_pos = sci_find_text(doc_list[idx].sci, flags, &ttf); + if (search_pos == -1) break; + find_len = ttf.chrgText.cpMax - ttf.chrgText.cpMin;
- if (search_pos == -1 || - search_pos < selection_start || - search_pos + find_text_len > selection_end) break; + if (search_pos + find_len > end) + break; //found text is partly out of range else { + match_found = TRUE; sci_target_start(doc_list[idx].sci, search_pos); - sci_target_end(doc_list[idx].sci, search_pos + find_text_len); - sci_target_replace(doc_list[idx].sci, replace_text); - anchor_pos = search_pos + replace_text_len; //avoid rematch - // update selection end point for each replacement - selection_end += replace_text_len - find_text_len; + sci_target_end(doc_list[idx].sci, search_pos + find_len); + replace_len = sci_target_replace(doc_list[idx].sci, replace_text, + flags & SCFIND_REGEXP); + ttf.chrg.cpMin = search_pos + replace_len; //next search starts after replacement + end += replace_len - find_len; //update end of range now text has changed + ttf.chrg.cpMax = end; } } sci_end_undo_action(doc_list[idx].sci); - // set selection again, because it got lost and end may be moved - sci_set_selection_start(doc_list[idx].sci, selection_start); - sci_set_selection_end(doc_list[idx].sci, selection_end);
- sci_scroll_caret(doc_list[idx].sci); - gtk_widget_hide(app->replace_dialog); + if (match_found && show_last) + { + // select the last replacement + gint sel_start = ttf.chrg.cpMin - replace_len; + sci_set_selection_start(doc_list[idx].sci, sel_start); + sci_set_selection_end(doc_list[idx].sci, sel_start + replace_len); + sci_scroll_caret(doc_list[idx].sci); + } + if (match_found) + return end; + else + return -1; //no text was found }
-void document_replace_all(gint idx, const gchar *find_text, const gchar *replace_text, gint flags) +void document_replace_sel(gint idx, const gchar *find_text, const gchar *replace_text, gint flags) { - gint search_pos; - gint find_text_len = strlen(find_text); - gint replace_text_len = strlen(replace_text); + gint selection_end, selection_start;
- if (idx == -1 || ! find_text_len) return; + g_return_if_fail(find_text != NULL && replace_text != NULL); + if (idx == -1 || ! *find_text) return;
- sci_start_undo_action(doc_list[idx].sci); - sci_goto_pos(doc_list[idx].sci, 0, FALSE); - sci_set_search_anchor(doc_list[idx].sci); + selection_start = sci_get_selection_start(doc_list[idx].sci); + selection_end = sci_get_selection_end(doc_list[idx].sci); + if ((selection_end - selection_start) == 0) + { + utils_beep(); + return; + }
- search_pos = sci_search_next(doc_list[idx].sci, flags, find_text); - while (search_pos != -1) + selection_end = document_replace_range(idx, find_text, replace_text, flags, + selection_start, selection_end, FALSE); + if (selection_end == -1) + utils_beep(); + else { - sci_target_start(doc_list[idx].sci, search_pos); - sci_target_end(doc_list[idx].sci, search_pos + find_text_len); - sci_target_replace(doc_list[idx].sci, replace_text); - // next search starts after replaced text (avoids rematching): - sci_goto_pos(doc_list[idx].sci, search_pos + replace_text_len, TRUE); - sci_set_search_anchor(doc_list[idx].sci); - search_pos = sci_search_next(doc_list[idx].sci, flags, find_text); + //update the selection for the new endpoint + sci_set_selection_start(doc_list[idx].sci, selection_start); + sci_set_selection_end(doc_list[idx].sci, selection_end); } - sci_end_undo_action(doc_list[idx].sci); - sci_scroll_caret(doc_list[idx].sci); + gtk_widget_hide(app->replace_dialog); }
+void document_replace_all(gint idx, const gchar *find_text, const gchar *replace_text, gint flags) +{ + gint len; + g_return_if_fail(find_text != NULL && replace_text != NULL); + if (idx == -1 || ! *find_text) return; + + len = sci_get_length(doc_list[idx].sci); + if (document_replace_range(idx, find_text, replace_text, flags, 0, len, TRUE) == -1) + utils_beep(); + + gtk_widget_hide(app->replace_dialog); +} + + void document_set_font(gint idx, const gchar *font_name, gint size) { gint style; @@ -1240,7 +1271,7 @@ { sci_target_start(doc_list[idx].sci, i + 1); sci_target_end(doc_list[idx].sci, line_end); - sci_target_replace(doc_list[idx].sci, ""); + sci_target_replace(doc_list[idx].sci, "", FALSE); } } }
Modified: trunk/src/sciwrappers.c =================================================================== --- trunk/src/sciwrappers.c 2006-07-18 12:28:04 UTC (rev 580) +++ trunk/src/sciwrappers.c 2006-07-18 14:09:01 UTC (rev 581) @@ -772,9 +772,9 @@ }
-void sci_target_replace(ScintillaObject *sci, const gchar *text) +gint sci_target_replace(ScintillaObject *sci, const gchar *text, gboolean regex) { - SSM(sci, SCI_REPLACETARGET, -1, (sptr_t) text); + return SSM(sci, (regex) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET, -1, (sptr_t) text); }
Modified: trunk/src/sciwrappers.h =================================================================== --- trunk/src/sciwrappers.h 2006-07-18 12:28:04 UTC (rev 580) +++ trunk/src/sciwrappers.h 2006-07-18 14:09:01 UTC (rev 581) @@ -138,7 +138,7 @@ void sci_target_from_selection (ScintillaObject * sci); void sci_target_start (ScintillaObject * sci, gint start); void sci_target_end (ScintillaObject * sci, gint end); -void sci_target_replace (ScintillaObject * sci, const gchar *text); +gint sci_target_replace (ScintillaObject *sci, const gchar *text, gboolean regex); void sci_set_keywords (ScintillaObject * sci, gint k, gchar *text); void sci_scroll_lines (ScintillaObject * sci, gint lines); gint sci_get_lexer (ScintillaObject * sci);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.