mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-08 20:41:59 +03:00
Merge branch '393_damn_slow_search_viewer'
* 393_damn_slow_search_viewer: Ticket #393 (slow search in viewer)
This commit is contained in:
commit
944d1cf961
@ -252,7 +252,7 @@ mc_search__regex_found_cond_one (mc_search_t * mc_search, mc_search_regex_t * re
|
||||
mc_search->num_rezults = g_match_info_get_match_count (mc_search->regex_match_info);
|
||||
#else /* SEARCH_TYPE_GLIB */
|
||||
mc_search->num_rezults = pcre_exec (regex, mc_search->regex_match_info,
|
||||
search_str->str, search_str->len, 0, 0, mc_search->iovector,
|
||||
search_str->str, search_str->len - 1, 0, 0, mc_search->iovector,
|
||||
MC_SEARCH__NUM_REPLACE_ARGS);
|
||||
if (mc_search->num_rezults < 0) {
|
||||
return COND__NOT_FOUND;
|
||||
@ -527,7 +527,7 @@ gboolean
|
||||
mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
|
||||
gsize start_search, gsize end_search, gsize * found_len)
|
||||
{
|
||||
gsize current_pos, start_buffer;
|
||||
gsize current_pos, virtual_pos;
|
||||
int current_chr = 0;
|
||||
gint start_pos;
|
||||
gint end_pos;
|
||||
@ -537,30 +537,33 @@ mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
|
||||
|
||||
mc_search->regex_buffer = g_string_new ("");
|
||||
|
||||
current_pos = start_search;
|
||||
while (current_pos <= end_search) {
|
||||
virtual_pos = current_pos = start_search;
|
||||
while (virtual_pos <= end_search) {
|
||||
g_string_set_size (mc_search->regex_buffer, 0);
|
||||
start_buffer = current_pos;
|
||||
mc_search->start_buffer = current_pos;
|
||||
|
||||
while (1) {
|
||||
current_chr = mc_search__get_char (mc_search, user_data, current_pos);
|
||||
if (current_chr == -1)
|
||||
if (current_chr == MC_SEARCH_CB_ABORT)
|
||||
break;
|
||||
|
||||
current_pos++;
|
||||
|
||||
if (current_chr == MC_SEARCH_CB_SKIP)
|
||||
continue;
|
||||
|
||||
virtual_pos++;
|
||||
|
||||
g_string_append_c (mc_search->regex_buffer, (char) current_chr);
|
||||
|
||||
current_pos++;
|
||||
|
||||
if (current_chr == 0 || (char) current_chr == '\n')
|
||||
break;
|
||||
|
||||
if (current_pos > end_search)
|
||||
if (virtual_pos > end_search)
|
||||
break;
|
||||
|
||||
}
|
||||
if (current_chr == -1)
|
||||
break;
|
||||
|
||||
switch (mc_search__regex_found_cond (mc_search, mc_search->regex_buffer)) {
|
||||
case COND__FOUND_OK:
|
||||
#ifdef SEARCH_TYPE_GLIB
|
||||
@ -571,7 +574,7 @@ mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
|
||||
#endif /* SEARCH_TYPE_GLIB */
|
||||
if (found_len)
|
||||
*found_len = end_pos - start_pos;
|
||||
mc_search->normal_offset = start_buffer + start_pos;
|
||||
mc_search->normal_offset = mc_search->start_buffer + start_pos;
|
||||
return TRUE;
|
||||
break;
|
||||
case COND__NOT_ALL_FOUND:
|
||||
@ -582,6 +585,17 @@ mc_search__run_regex (mc_search_t * mc_search, const void *user_data,
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
if (mc_search->update_fn != NULL) {
|
||||
if ((mc_search->update_fn) (user_data, current_pos) == MC_SEARCH_CB_SKIP) {
|
||||
g_string_free (mc_search->regex_buffer, TRUE);
|
||||
mc_search->regex_buffer = NULL;
|
||||
mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
mc_search->error_str = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (current_chr == MC_SEARCH_CB_ABORT)
|
||||
break;
|
||||
}
|
||||
g_string_free (mc_search->regex_buffer, TRUE);
|
||||
mc_search->regex_buffer = NULL;
|
||||
@ -599,7 +613,7 @@ mc_search_regex_prepare_replace_str (mc_search_t * mc_search, GString * replace_
|
||||
|
||||
int num_replace_tokens, index;
|
||||
gsize loop;
|
||||
gsize len;
|
||||
gsize len = 0;
|
||||
gchar *prev_str;
|
||||
replace_transform_type_t replace_flags = REPLACE_T_NO_TRANSFORM;
|
||||
|
||||
|
@ -39,6 +39,11 @@ typedef enum {
|
||||
MC_SEARCH_T_GLOB
|
||||
} mc_search_type_t;
|
||||
|
||||
typedef enum {
|
||||
MC_SEARCH_CB_ABORT = -1,
|
||||
MC_SEARCH_CB_SKIP = -2
|
||||
} mc_search_cbret_t;
|
||||
|
||||
|
||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||
|
||||
@ -61,6 +66,9 @@ typedef struct mc_search_struct {
|
||||
/* function, used for getting data. NULL if not used */
|
||||
mc_search_fn search_fn;
|
||||
|
||||
/* function, used for updatin current search status. NULL if not used */
|
||||
mc_search_fn update_fn;
|
||||
|
||||
/* type of search */
|
||||
mc_search_type_t search_type;
|
||||
|
||||
@ -70,6 +78,7 @@ typedef struct mc_search_struct {
|
||||
/* some data for normal */
|
||||
gsize normal_offset;
|
||||
|
||||
gsize start_buffer;
|
||||
/* some data for regexp */
|
||||
int num_rezults;
|
||||
mc_search_matchinfo_t *regex_match_info;
|
||||
@ -109,7 +118,7 @@ void mc_search_free (mc_search_t * mc_search);
|
||||
gboolean mc_search_prepare (mc_search_t * mc_search);
|
||||
|
||||
gboolean mc_search_run (mc_search_t * mc_search, const void *user_data, gsize start_search,
|
||||
gsize end_search, gsize * founded_len);
|
||||
gsize end_search, gsize * found_len);
|
||||
|
||||
gboolean mc_search_is_type_avail (mc_search_type_t);
|
||||
|
||||
|
321
src/view.c
321
src/view.c
@ -139,6 +139,20 @@ struct cache_line {
|
||||
screen_dimen left;
|
||||
};
|
||||
|
||||
/* this structure and view_read_* functions make reading text simpler
|
||||
* view need remeber 4 following charsets: actual, next and two previous */
|
||||
struct read_info {
|
||||
char ch[4][MB_LEN_MAX + 1];
|
||||
char *cnxt;
|
||||
char *cact;
|
||||
char *chi1;
|
||||
char *chi2;
|
||||
offset_type next;
|
||||
offset_type actual;
|
||||
int result;
|
||||
};
|
||||
|
||||
|
||||
struct WView {
|
||||
Widget widget;
|
||||
|
||||
@ -248,6 +262,9 @@ struct WView {
|
||||
gboolean search_all_codepages;
|
||||
gboolean search_case;
|
||||
gboolean search_backwards;
|
||||
|
||||
int search_numNeedSkipChar;
|
||||
struct read_info search_onechar_info;
|
||||
};
|
||||
|
||||
|
||||
@ -361,18 +378,6 @@ view_get_char (WView *view, offset_type from, char *ch, int size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* this structure and view_read_* functions make reading text simpler
|
||||
* view need remeber 4 following charsets: actual, next and two previous */
|
||||
struct read_info {
|
||||
char ch[4][MB_LEN_MAX + 1];
|
||||
char *cnxt;
|
||||
char *cact;
|
||||
char *chi1;
|
||||
char *chi2;
|
||||
offset_type next;
|
||||
offset_type actual;
|
||||
int result;
|
||||
};
|
||||
|
||||
/* set read_info into initial state and read first character to cnxt
|
||||
* return how many bytes was read or -1 if end of text */
|
||||
@ -2742,66 +2747,6 @@ my_define (Dlg_head *h, int idx, const char *text, void (*fn) (WView *),
|
||||
|
||||
/* {{{ Searching }}} */
|
||||
|
||||
/* read one whole line into buffer, return where line start and end */
|
||||
static int
|
||||
view_get_line_at (WView *view, offset_type from, GString * buffer,
|
||||
offset_type *buff_start, offset_type *buff_end)
|
||||
{
|
||||
#define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
|
||||
struct read_info info;
|
||||
struct cache_line *line;
|
||||
offset_type start;
|
||||
offset_type end;
|
||||
|
||||
line = view_get_first_showed_line (view);
|
||||
|
||||
line = view_offset_to_line_from (view, from, line);
|
||||
|
||||
if (!view->search_backwards) {
|
||||
start = from;
|
||||
end = view_get_end_of_whole_line (view, line)->end;
|
||||
if (start >= end) return 0;
|
||||
} else {
|
||||
start = view_get_start_of_whole_line (view, line)->start;
|
||||
end = from;
|
||||
}
|
||||
|
||||
(*buff_start) = start;
|
||||
(*buff_end) = end;
|
||||
|
||||
g_string_set_size(buffer,0);
|
||||
|
||||
view_read_start (view, &info, start);
|
||||
while ((info.result != -1) && (info.next < end)) {
|
||||
view_read_continue (view, &info);
|
||||
|
||||
/* if text contains '\0' */
|
||||
if (cmp (info.cact, "")) {
|
||||
if (info.actual < from) {
|
||||
/* '\0' before start offset, continue */
|
||||
g_string_set_size(buffer,0);
|
||||
(*buff_start) = info.next;
|
||||
continue;
|
||||
} else {
|
||||
/* '\0' after start offset, end */
|
||||
(*buff_end) = info.next;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (view_read_test_new_line (view, &info))
|
||||
continue;
|
||||
|
||||
if (view_read_test_nroff_back (view, &info)) {
|
||||
g_string_truncate (buffer, buffer->len-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_string_append(buffer,info.cact);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* map search result positions to offsets in text */
|
||||
void
|
||||
@ -3104,10 +3049,24 @@ view__get_nroff_real_len(WView *view, offset_type start, offset_type length)
|
||||
struct read_info info;
|
||||
|
||||
view_read_start (view, &info, start);
|
||||
while((loop1 < length ) && (info.result != -1))
|
||||
{
|
||||
while((loop1 < length ) && (info.result != -1)) {
|
||||
view_read_continue (view, &info);
|
||||
if (*info.cnxt == '\b')
|
||||
if (view_read_test_nroff_back (view, &info)) {
|
||||
|
||||
if (cmp (info.chi1, "_") && (!cmp (info.cnxt, "_") || !cmp (info.chi2, "\b")))
|
||||
{
|
||||
view_read_continue (view, &info);
|
||||
view_read_continue (view, &info);
|
||||
view_read_continue (view, &info);
|
||||
view_read_continue (view, &info);
|
||||
nroff_seq+=4;
|
||||
} else {
|
||||
view_read_continue (view, &info);
|
||||
view_read_continue (view, &info);
|
||||
nroff_seq+=2;
|
||||
}
|
||||
}
|
||||
if (*info.cact == '_' && *info.cnxt == 0x8)
|
||||
{
|
||||
view_read_continue (view, &info);
|
||||
view_read_continue (view, &info);
|
||||
@ -3118,17 +3077,100 @@ view__get_nroff_real_len(WView *view, offset_type start, offset_type length)
|
||||
return nroff_seq;
|
||||
}
|
||||
|
||||
static int
|
||||
view_search_update_cmd_callback(const void *user_data, gsize char_offset)
|
||||
{
|
||||
WView *view = (WView *) user_data;
|
||||
|
||||
if (char_offset >= view->update_activate) {
|
||||
view->update_activate += view->update_steps;
|
||||
if (verbose) {
|
||||
view_percent (view, char_offset);
|
||||
mc_refresh ();
|
||||
}
|
||||
if (got_interrupt ())
|
||||
return MC_SEARCH_CB_ABORT;
|
||||
}
|
||||
/* may be in future return from this callback will change current position
|
||||
* in searching block. Now this just constant return value.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
view_search_cmd_callback(const void *user_data, gsize char_offset)
|
||||
{
|
||||
int byte;
|
||||
WView *view = (WView *) user_data;
|
||||
|
||||
byte = get_byte (view, char_offset);
|
||||
if (byte == -1)
|
||||
return MC_SEARCH_CB_ABORT;
|
||||
view_read_continue (view, &view->search_onechar_info);
|
||||
|
||||
if (view->search_numNeedSkipChar) {
|
||||
view->search_numNeedSkipChar--;
|
||||
if (view->search_numNeedSkipChar){
|
||||
return byte;
|
||||
}
|
||||
return MC_SEARCH_CB_SKIP;
|
||||
}
|
||||
|
||||
if (view_read_test_nroff_back (view, &view->search_onechar_info)) {
|
||||
if (
|
||||
cmp (view->search_onechar_info.chi1, "_") &&
|
||||
(!cmp (view->search_onechar_info.cnxt, "_") || !cmp (view->search_onechar_info.chi2, "\b"))
|
||||
)
|
||||
view->search_numNeedSkipChar = 2;
|
||||
else
|
||||
view->search_numNeedSkipChar = 1;
|
||||
|
||||
return MC_SEARCH_CB_SKIP;
|
||||
}
|
||||
if (byte == '_' && *view->search_onechar_info.cnxt == 0x8)
|
||||
{
|
||||
view->search_numNeedSkipChar = 1;
|
||||
return MC_SEARCH_CB_SKIP;
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
view_find (WView *view, gsize search_start, gsize *len)
|
||||
{
|
||||
gsize search_end;
|
||||
|
||||
view->search_numNeedSkipChar = 0;
|
||||
|
||||
if (view->search_backwards) {
|
||||
search_end = view_get_filesize (view);
|
||||
while ((int) search_start >= 0) {
|
||||
if (search_end - search_start > view->search->original_len && mc_search_is_fixed_search_str(view->search))
|
||||
search_end = search_start + view->search->original_len;
|
||||
|
||||
view_read_start (view, &view->search_onechar_info, search_start);
|
||||
|
||||
if ( mc_search_run(view->search, (void *) view, search_start, search_end, len))
|
||||
return TRUE;
|
||||
|
||||
search_start--;
|
||||
}
|
||||
view->search->error_str = g_strdup(_(" Search string not found "));
|
||||
return FALSE;
|
||||
}
|
||||
view_read_start (view, &view->search_onechar_info, search_start);
|
||||
return mc_search_run(view->search, (void *) view, search_start, view_get_filesize (view), len);
|
||||
}
|
||||
|
||||
static void
|
||||
do_search (WView *view)
|
||||
{
|
||||
GString *buffer;
|
||||
offset_type search_start;
|
||||
int search_status;
|
||||
gboolean isFound = FALSE;
|
||||
|
||||
Dlg_head *d = NULL;
|
||||
|
||||
offset_type line_start;
|
||||
offset_type line_end;
|
||||
size_t match_len;
|
||||
|
||||
if (verbose) {
|
||||
@ -3136,9 +3178,19 @@ do_search (WView *view)
|
||||
mc_refresh ();
|
||||
}
|
||||
|
||||
buffer = g_string_new ("");
|
||||
/*for avoid infinite search loop we need to increase or decrease start offset of search */
|
||||
|
||||
if (view->search_start)
|
||||
{
|
||||
search_start = (view->search_backwards) ? -2 : 2;
|
||||
search_start = view->search_start + search_start +
|
||||
view__get_nroff_real_len(view, view->search_start, 2) * search_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
search_start = view->search_start;
|
||||
}
|
||||
|
||||
search_start = (view->search_backwards) ? view->search_start-1 : view->search_end;
|
||||
if (view->search_backwards && (int) search_start < 0 )
|
||||
search_start = 0;
|
||||
|
||||
@ -3147,81 +3199,56 @@ do_search (WView *view)
|
||||
view->update_activate = 0;
|
||||
|
||||
enable_interrupt_key ();
|
||||
search_status = -1;
|
||||
|
||||
while(1){
|
||||
if (search_start >= view->update_activate) {
|
||||
view->update_activate += view->update_steps;
|
||||
do
|
||||
{
|
||||
if (view_find(view, search_start, &match_len))
|
||||
{
|
||||
view->search_start = view->search->normal_offset +
|
||||
view__get_nroff_real_len(view,
|
||||
view->search->start_buffer,
|
||||
view->search->normal_offset - view->search->start_buffer);
|
||||
|
||||
view->search_end = view->search_start + match_len +
|
||||
view__get_nroff_real_len(view, view->search_start, match_len + 1);
|
||||
|
||||
if (view->hex_mode){
|
||||
view->hex_cursor = view->search_start;
|
||||
view->hexedit_lownibble = FALSE;
|
||||
view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
|
||||
view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
view_percent (view, search_start);
|
||||
dlg_run_done (d);
|
||||
destroy_dlg (d);
|
||||
d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
|
||||
mc_refresh ();
|
||||
}
|
||||
if (got_interrupt ())
|
||||
break;
|
||||
}
|
||||
|
||||
if (!view_get_line_at (view, search_start, buffer, &line_start, &line_end))
|
||||
view_moveto_match (view);
|
||||
isFound = TRUE;
|
||||
break;
|
||||
|
||||
if (! mc_search_run( view->search, buffer->str, 0, buffer->len, &match_len )){
|
||||
if (view->search->error != MC_SEARCH_E_NOTFOUND) {
|
||||
search_status = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! view->search_backwards) {
|
||||
search_start = line_end;
|
||||
} else {
|
||||
if (line_start > 0) search_start = line_start - 1;
|
||||
else break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
search_status = 1;
|
||||
if (view->search_backwards){
|
||||
search_start = line_start;
|
||||
}
|
||||
} while (view_may_still_grow(view));
|
||||
|
||||
view->search_start = search_start + view->search->normal_offset +
|
||||
view__get_nroff_real_len(view, search_start, view->search->normal_offset);
|
||||
|
||||
view->search_end = view->search_start + match_len +
|
||||
view__get_nroff_real_len(view, view->search_start, match_len);
|
||||
|
||||
if (view->hex_mode){
|
||||
view->hex_cursor = view->search_start;
|
||||
view->hexedit_lownibble = FALSE;
|
||||
view->dpy_start = view->search_start - view->search_start % view->bytes_per_line;
|
||||
view->dpy_end = view->search_end - view->search_end % view->bytes_per_line;
|
||||
}
|
||||
|
||||
view_moveto_match (view);
|
||||
|
||||
break;
|
||||
if (!isFound){
|
||||
if (view->search->error_str)
|
||||
message (D_NORMAL, _("Search"), view->search->error_str);
|
||||
}
|
||||
|
||||
view->dirty++;
|
||||
view_update (view);
|
||||
|
||||
|
||||
disable_interrupt_key ();
|
||||
if (verbose) {
|
||||
dlg_run_done (d);
|
||||
destroy_dlg (d);
|
||||
}
|
||||
switch (search_status)
|
||||
{
|
||||
case -1:
|
||||
message (D_NORMAL, _("Search"), _(" Search string not found "));
|
||||
view->search_end = view->search_start;
|
||||
break;
|
||||
case -2:
|
||||
message (D_NORMAL, _("Search"), "%s", view->search->error_str);
|
||||
view->search_end = view->search_start;
|
||||
break;
|
||||
}
|
||||
g_string_free (buffer, TRUE);
|
||||
|
||||
view->dirty++;
|
||||
view_update (view);
|
||||
}
|
||||
|
||||
|
||||
/* Both views */
|
||||
static void
|
||||
view_search_cmd (WView *view)
|
||||
@ -3234,6 +3261,7 @@ view_search_cmd (WView *view)
|
||||
|
||||
char *defval = g_strdup (view->last_search_string != NULL ? view->last_search_string : "");
|
||||
char *exp = NULL;
|
||||
GString *tmp;
|
||||
|
||||
int ttype_of_search = (int) view->search_type;
|
||||
int tall_codepages = (int) view->search_all_codepages;
|
||||
@ -3295,7 +3323,14 @@ view_search_cmd (WView *view)
|
||||
if (exp == NULL || exp[0] == '\0')
|
||||
goto cleanup;
|
||||
|
||||
convert_from_input (exp);
|
||||
g_free (defval);
|
||||
defval = NULL;
|
||||
tmp = str_convert_to_input (exp);
|
||||
|
||||
if (tmp)
|
||||
defval = tmp->str;
|
||||
|
||||
g_string_free (tmp, FALSE);
|
||||
|
||||
g_free (view->last_search_string);
|
||||
view->last_search_string = exp;
|
||||
@ -3304,13 +3339,15 @@ view_search_cmd (WView *view)
|
||||
if (view->search)
|
||||
mc_search_free(view->search);
|
||||
|
||||
view->search = mc_search_new(view->last_search_string, -1);
|
||||
view->search = mc_search_new(defval, -1);
|
||||
if (! view->search)
|
||||
return;
|
||||
goto cleanup;
|
||||
|
||||
view->search->search_type = view->search_type;
|
||||
view->search->is_all_charsets = view->search_all_codepages;
|
||||
view->search->is_case_sentitive = view->search_case;
|
||||
view->search->search_fn = view_search_cmd_callback;
|
||||
view->search->update_fn = view_search_update_cmd_callback;
|
||||
|
||||
do_search (view);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user