mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 12:32:40 +03:00
Merge branch '1868_replace_regexp_hangup'
* 1868_replace_regexp_hangup: Code optimization: memory allocation and free moved outside of loop. Ticket #1868: mcedit hang up on replace with regexp.
This commit is contained in:
commit
c8c8c0da11
@ -16,6 +16,16 @@
|
||||
|
||||
/*** enums ***************************************************************************************/
|
||||
|
||||
/**
|
||||
enum for store the search conditions check results.
|
||||
(if search condition have BOL(^) or EOL ($) regexp checial characters).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
AT_START_LINE = (1 << 0),
|
||||
AT_END_LINE = (1 << 1)
|
||||
} edit_search_line_t;
|
||||
|
||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||
|
||||
struct _book_mark
|
||||
@ -55,6 +65,8 @@ struct WEdit
|
||||
/* search handler */
|
||||
mc_search_t *search;
|
||||
int replace_mode;
|
||||
/* is search conditions should be started from BOL(^) or ended with EOL($) */
|
||||
edit_search_line_t search_line_type;
|
||||
|
||||
char *last_search_string; /* String that have been searched */
|
||||
long search_start; /* First character to start searching from */
|
||||
|
@ -710,6 +710,167 @@ edit_block_delete (WEdit * edit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Get EOL symbol for searching.
|
||||
*
|
||||
* @param edit editor object
|
||||
* @return EOL symbol
|
||||
*/
|
||||
|
||||
static inline char
|
||||
edit_search_get_current_end_line_char (const WEdit * edit)
|
||||
{
|
||||
switch (edit->lb)
|
||||
{
|
||||
case LB_MAC:
|
||||
return '\r';
|
||||
default:
|
||||
return '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Checking if search condition have BOL(^) or EOL ($) regexp special characters.
|
||||
*
|
||||
* @param search search object
|
||||
* @return result of checks.
|
||||
*/
|
||||
|
||||
static edit_search_line_t
|
||||
edit_get_search_line_type (mc_search_t * search)
|
||||
{
|
||||
edit_search_line_t search_line_type = 0;
|
||||
|
||||
if (search->search_type != MC_SEARCH_T_REGEX)
|
||||
return search_line_type;
|
||||
|
||||
if (*search->original == '^')
|
||||
search_line_type |= AT_START_LINE;
|
||||
|
||||
if (search->original[search->original_len - 1] == '$')
|
||||
search_line_type |= AT_END_LINE;
|
||||
return search_line_type;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Calculating the start position of next line.
|
||||
*
|
||||
* @param edit editor object
|
||||
* @param current_pos current position
|
||||
* @param max_pos max position
|
||||
* @param end_string_symbol end of line symbol
|
||||
* @return start position of next line
|
||||
*/
|
||||
|
||||
static off_t
|
||||
edit_calculate_start_of_next_line (WEdit * edit, off_t current_pos, off_t max_pos,
|
||||
char end_string_symbol)
|
||||
{
|
||||
off_t i;
|
||||
|
||||
for (i = current_pos; i < max_pos; i++)
|
||||
{
|
||||
current_pos++;
|
||||
if (edit_get_byte (edit, i) == end_string_symbol)
|
||||
break;
|
||||
}
|
||||
|
||||
return current_pos;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Calculating the end position of previous line.
|
||||
*
|
||||
* @param edit editor object
|
||||
* @param current_pos current position
|
||||
* @param end_string_symbol end of line symbol
|
||||
* @return end position of previous line
|
||||
*/
|
||||
|
||||
static off_t
|
||||
edit_calculate_end_of_previous_line (WEdit * edit, off_t current_pos, char end_string_symbol)
|
||||
{
|
||||
off_t i;
|
||||
|
||||
for (i = current_pos - 1; i >= 0; i--)
|
||||
if (edit_get_byte (edit, i) == end_string_symbol)
|
||||
break;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Calculating the start position of previous line.
|
||||
*
|
||||
* @param edit editor object
|
||||
* @param current_pos current position
|
||||
* @param end_string_symbol end of line symbol
|
||||
* @return start position of previous line
|
||||
*/
|
||||
|
||||
static inline off_t
|
||||
edit_calculate_start_of_previous_line (WEdit * edit, off_t current_pos, char end_string_symbol)
|
||||
{
|
||||
current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
|
||||
current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
|
||||
|
||||
return (current_pos + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Calculating the start position of current line.
|
||||
*
|
||||
* @param edit editor object
|
||||
* @param current_pos current position
|
||||
* @param end_string_symbol end of line symbol
|
||||
* @return start position of current line
|
||||
*/
|
||||
|
||||
static inline off_t
|
||||
edit_calculate_start_of_current_line (WEdit * edit, off_t current_pos, char end_string_symbol)
|
||||
{
|
||||
current_pos = edit_calculate_end_of_previous_line (edit, current_pos, end_string_symbol);
|
||||
|
||||
return (current_pos + 1);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Fixing (if needed) search start position if 'only in selection' option present.
|
||||
*
|
||||
* @param edit editor object
|
||||
*/
|
||||
|
||||
static void
|
||||
edit_search_fix_search_start_if_selection (WEdit * edit)
|
||||
{
|
||||
long start_mark = 0;
|
||||
long end_mark = 0;
|
||||
|
||||
if (!edit_search_options.only_in_selection)
|
||||
return;
|
||||
|
||||
if (eval_marks (edit, &start_mark, &end_mark) != 0)
|
||||
return;
|
||||
|
||||
if (edit_search_options.backwards)
|
||||
{
|
||||
if (edit->search_start > end_mark || edit->search_start <= start_mark)
|
||||
edit->search_start = end_mark;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edit->search_start < start_mark || edit->search_start >= end_mark)
|
||||
edit->search_start = start_mark;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static gboolean
|
||||
@ -720,7 +881,11 @@ editcmd_find (WEdit * edit, gsize * len)
|
||||
long start_mark = 0;
|
||||
long end_mark = edit->last_byte;
|
||||
int mark_res = 0;
|
||||
char end_string_symbol;
|
||||
|
||||
end_string_symbol = edit_search_get_current_end_line_char (edit);
|
||||
|
||||
/* prepare for search */
|
||||
if (edit_search_options.only_in_selection)
|
||||
{
|
||||
mark_res = eval_marks (edit, &start_mark, &end_mark);
|
||||
@ -730,19 +895,26 @@ editcmd_find (WEdit * edit, gsize * len)
|
||||
edit->search->error_str = g_strdup (_("Search string not found"));
|
||||
return FALSE;
|
||||
}
|
||||
if (edit_search_options.backwards)
|
||||
|
||||
/* fix the start and the end of search block positions */
|
||||
if ((edit->search_line_type & AT_START_LINE) != 0
|
||||
&& (start_mark != 0 || edit_get_byte (edit, start_mark - 1) != end_string_symbol))
|
||||
{
|
||||
if (search_start > end_mark || search_start <= start_mark)
|
||||
{
|
||||
search_start = end_mark;
|
||||
}
|
||||
start_mark =
|
||||
edit_calculate_start_of_next_line (edit, start_mark, edit->last_byte,
|
||||
end_string_symbol);
|
||||
}
|
||||
else
|
||||
if ((edit->search_line_type & AT_END_LINE) != 0
|
||||
&& (end_mark - 1 != edit->last_byte
|
||||
|| edit_get_byte (edit, end_mark) != end_string_symbol))
|
||||
{
|
||||
if (search_start < start_mark || search_start >= end_mark)
|
||||
{
|
||||
search_start = start_mark;
|
||||
}
|
||||
end_mark = edit_calculate_end_of_previous_line (edit, end_mark, end_string_symbol);
|
||||
}
|
||||
if (start_mark >= end_mark)
|
||||
{
|
||||
edit->search->error = MC_SEARCH_E_NOTFOUND;
|
||||
edit->search->error_str = g_strdup (_("Search string not found"));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -750,13 +922,21 @@ editcmd_find (WEdit * edit, gsize * len)
|
||||
if (edit_search_options.backwards)
|
||||
end_mark = max (1, edit->curs1) - 1;
|
||||
}
|
||||
|
||||
/* search */
|
||||
if (edit_search_options.backwards)
|
||||
{
|
||||
/* backward search */
|
||||
search_end = end_mark;
|
||||
|
||||
if ((edit->search_line_type & AT_START_LINE) != 0)
|
||||
search_start =
|
||||
edit_calculate_start_of_current_line (edit, search_start, end_string_symbol);
|
||||
|
||||
while ((int) search_start >= start_mark)
|
||||
{
|
||||
if (search_end > (off_t) (search_start + edit->search->original_len) &&
|
||||
mc_search_is_fixed_search_str (edit->search))
|
||||
if (search_end > (off_t) (search_start + edit->search->original_len)
|
||||
&& mc_search_is_fixed_search_str (edit->search))
|
||||
{
|
||||
search_end = search_start + edit->search->original_len;
|
||||
}
|
||||
@ -765,12 +945,22 @@ editcmd_find (WEdit * edit, gsize * len)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
search_start--;
|
||||
|
||||
|
||||
if ((edit->search_line_type & AT_START_LINE) != 0)
|
||||
search_start =
|
||||
edit_calculate_start_of_previous_line (edit, search_start, end_string_symbol);
|
||||
else
|
||||
search_start--;
|
||||
}
|
||||
edit->search->error_str = g_strdup (_("Search string not found"));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* forward search */
|
||||
if ((edit->search_line_type & AT_START_LINE) != 0 && search_start != start_mark)
|
||||
search_start =
|
||||
edit_calculate_start_of_next_line (edit, search_start, end_mark, end_string_symbol);
|
||||
return mc_search_run (edit->search, (void *) edit, search_start, end_mark, len);
|
||||
}
|
||||
return FALSE;
|
||||
@ -897,7 +1087,11 @@ static void
|
||||
edit_search (WEdit * edit)
|
||||
{
|
||||
if (editcmd_dialog_search_show (edit))
|
||||
{
|
||||
edit->search_line_type = edit_get_search_line_type (edit->search);
|
||||
edit_search_fix_search_start_if_selection (edit);
|
||||
edit_do_search (edit);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -2272,6 +2466,7 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
static char *saved2 = NULL;
|
||||
char *input1 = NULL; /* user input from the dialog */
|
||||
char *input2 = NULL;
|
||||
GString *input2_str = NULL;
|
||||
char *disp1 = NULL;
|
||||
char *disp2 = NULL;
|
||||
long times_replaced = 0;
|
||||
@ -2297,6 +2492,7 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
else
|
||||
{
|
||||
char *tmp_inp1, *tmp_inp2;
|
||||
|
||||
disp1 = edit_replace_cmd__conv_to_display (saved1 ? saved1 : (char *) "");
|
||||
disp2 = edit_replace_cmd__conv_to_display (saved2 ? saved2 : (char *) "");
|
||||
|
||||
@ -2327,6 +2523,8 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
edit->search = NULL;
|
||||
}
|
||||
|
||||
input2_str = g_string_new (input2);
|
||||
|
||||
if (!edit->search)
|
||||
{
|
||||
edit->search = mc_search_new (input1, -1);
|
||||
@ -2340,6 +2538,8 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
edit->search->is_case_sensitive = edit_search_options.case_sens;
|
||||
edit->search->whole_words = edit_search_options.whole_words;
|
||||
edit->search->search_fn = edit_search_cmd_callback;
|
||||
edit->search_line_type = edit_get_search_line_type (edit->search);
|
||||
edit_search_fix_search_start_if_selection (edit);
|
||||
}
|
||||
|
||||
if (edit->found_len && edit->search_start == edit->found_start + 1
|
||||
@ -2371,7 +2571,7 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
if ((edit->search_start >= 0) && (edit->search_start < edit->last_byte))
|
||||
{
|
||||
gsize i;
|
||||
GString *tmp_str, *repl_str;
|
||||
GString *repl_str;
|
||||
|
||||
edit->found_start = edit->search_start;
|
||||
i = edit->found_len = len;
|
||||
@ -2420,10 +2620,7 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
}
|
||||
}
|
||||
|
||||
/* don't process string each time */
|
||||
tmp_str = g_string_new (input2);
|
||||
repl_str = mc_search_prepare_replace_str (edit->search, tmp_str);
|
||||
g_string_free (tmp_str, TRUE);
|
||||
repl_str = mc_search_prepare_replace_str (edit->search, input2_str);
|
||||
|
||||
if (edit->search->error != MC_SEARCH_E_OK)
|
||||
{
|
||||
@ -2445,10 +2642,12 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
|
||||
/* so that we don't find the same string again */
|
||||
if (edit_search_options.backwards)
|
||||
{
|
||||
edit->search_start--;
|
||||
}
|
||||
else
|
||||
{
|
||||
edit->search_start += edit->found_len;
|
||||
edit->search_start += edit->found_len + (len == 0 ? 1 : 0);
|
||||
|
||||
if (edit->search_start >= edit->last_byte)
|
||||
break;
|
||||
@ -2482,6 +2681,8 @@ edit_replace_cmd (WEdit * edit, int again)
|
||||
cleanup:
|
||||
g_free (input1);
|
||||
g_free (input2);
|
||||
if (input2_str != NULL)
|
||||
g_string_free (input2_str, TRUE);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -2497,6 +2698,7 @@ edit_search_cmd_callback (const void *user_data, gsize char_offset)
|
||||
void
|
||||
edit_search_cmd (WEdit * edit, gboolean again)
|
||||
{
|
||||
|
||||
if (edit == NULL)
|
||||
return;
|
||||
|
||||
@ -2533,6 +2735,7 @@ edit_search_cmd (WEdit * edit, gboolean again)
|
||||
edit->search->is_case_sensitive = edit_search_options.case_sens;
|
||||
edit->search->whole_words = edit_search_options.whole_words;
|
||||
edit->search->search_fn = edit_search_cmd_callback;
|
||||
edit->search_line_type = edit_get_search_line_type (edit->search);
|
||||
edit_do_search (edit);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user