mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
Ticket #1873: Viewer: hangup after search in archive
viewer hangup after search in archive Test case: * download ftp://ftp.slackware-brasil.com.br/slackware-12.0/testing/MANIFEST.bz2 or any slackware MANIFEST.bz2 from internet * F3 under MANIFEST.bz2 * F7 "fortunes-o.tar.gz"<enter> * hangup Fix issue: * Change growbuff from owm implementation into g_ptr_array * Fixed calculating of search_start position * Search module: fixed checking for return code from update callback * Search module: Added return code MC_SEARCH_CB_OK for search callbacks * Added exit on keyboard break * Fixed search in last grow'ed block Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
parent
0ad310c1c6
commit
46f6c4d1b7
@ -585,22 +585,22 @@ mc_search__run_regex (mc_search_t * lc_mc_search, const void *user_data,
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
if (lc_mc_search->update_fn != NULL) {
|
||||
if ((lc_mc_search->update_fn) (user_data, current_pos) == MC_SEARCH_CB_SKIP) {
|
||||
g_string_free (lc_mc_search->regex_buffer, TRUE);
|
||||
lc_mc_search->regex_buffer = NULL;
|
||||
lc_mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
lc_mc_search->error_str = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (( lc_mc_search->update_fn != NULL ) &&
|
||||
( (lc_mc_search->update_fn) (user_data, current_pos) == MC_SEARCH_CB_ABORT))
|
||||
current_chr = MC_SEARCH_CB_ABORT;
|
||||
|
||||
if (current_chr == MC_SEARCH_CB_ABORT)
|
||||
break;
|
||||
}
|
||||
g_string_free (lc_mc_search->regex_buffer, TRUE);
|
||||
lc_mc_search->regex_buffer = NULL;
|
||||
lc_mc_search->error = MC_SEARCH_E_NOTFOUND;
|
||||
lc_mc_search->error_str = g_strdup (_(STR_E_NOTFOUND));
|
||||
|
||||
if (current_chr != MC_SEARCH_CB_ABORT)
|
||||
lc_mc_search->error_str = g_strdup (_(STR_E_NOTFOUND));
|
||||
else
|
||||
lc_mc_search->error_str = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ typedef enum {
|
||||
} mc_search_type_t;
|
||||
|
||||
typedef enum {
|
||||
MC_SEARCH_CB_OK = 0,
|
||||
MC_SEARCH_CB_ABORT = -1,
|
||||
MC_SEARCH_CB_SKIP = -2
|
||||
} mc_search_cbret_t;
|
||||
|
@ -63,8 +63,7 @@ void
|
||||
mcview_growbuf_init (mcview_t * view)
|
||||
{
|
||||
view->growbuf_in_use = TRUE;
|
||||
view->growbuf_blockptr = NULL;
|
||||
view->growbuf_blocks = 0;
|
||||
view->growbuf_blockptr = g_ptr_array_new ();
|
||||
view->growbuf_lastindex = VIEW_PAGE_SIZE;
|
||||
view->growbuf_finished = FALSE;
|
||||
}
|
||||
@ -74,13 +73,12 @@ mcview_growbuf_init (mcview_t * view)
|
||||
void
|
||||
mcview_growbuf_free (mcview_t * view)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
for (i = 0; i < view->growbuf_blocks; i++)
|
||||
g_free (view->growbuf_blockptr[i]);
|
||||
g_free (view->growbuf_blockptr);
|
||||
g_ptr_array_foreach (view->growbuf_blockptr, (GFunc) g_free, NULL);
|
||||
|
||||
(void) g_ptr_array_free (view->growbuf_blockptr, TRUE);
|
||||
|
||||
view->growbuf_blockptr = NULL;
|
||||
view->growbuf_in_use = FALSE;
|
||||
}
|
||||
@ -92,10 +90,10 @@ mcview_growbuf_filesize (mcview_t * view)
|
||||
{
|
||||
assert (view->growbuf_in_use);
|
||||
|
||||
if (view->growbuf_blocks == 0)
|
||||
if (view->growbuf_blockptr->len == 0)
|
||||
return 0;
|
||||
else
|
||||
return ((off_t) view->growbuf_blocks - 1) * VIEW_PAGE_SIZE + view->growbuf_lastindex;
|
||||
return ((off_t) view->growbuf_blockptr->len - 1) * VIEW_PAGE_SIZE + view->growbuf_lastindex;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -121,19 +119,17 @@ mcview_growbuf_read_until (mcview_t * view, off_t ofs)
|
||||
if (view->growbuf_lastindex == VIEW_PAGE_SIZE) {
|
||||
/* Append a new block to the growing buffer */
|
||||
byte *newblock = g_try_malloc (VIEW_PAGE_SIZE);
|
||||
byte **newblocks = g_try_malloc (sizeof (*newblocks) * (view->growbuf_blocks + 1));
|
||||
if (!newblock || !newblocks) {
|
||||
g_free (newblock);
|
||||
g_free (newblocks);
|
||||
if (newblock == NULL)
|
||||
return;
|
||||
}
|
||||
memcpy (newblocks, view->growbuf_blockptr, sizeof (*newblocks) * view->growbuf_blocks);
|
||||
g_free (view->growbuf_blockptr);
|
||||
view->growbuf_blockptr = newblocks;
|
||||
view->growbuf_blockptr[view->growbuf_blocks++] = newblock;
|
||||
|
||||
g_ptr_array_add (view->growbuf_blockptr, newblock);
|
||||
view->growbuf_lastindex = 0;
|
||||
}
|
||||
p = view->growbuf_blockptr[view->growbuf_blocks - 1] + view->growbuf_lastindex;
|
||||
p = g_ptr_array_index(
|
||||
view->growbuf_blockptr,
|
||||
view->growbuf_blockptr->len - 1)
|
||||
+ view->growbuf_lastindex;
|
||||
|
||||
bytesfree = VIEW_PAGE_SIZE - view->growbuf_lastindex;
|
||||
|
||||
if (view->datasource == DS_STDIO_PIPE) {
|
||||
@ -147,7 +143,7 @@ mcview_growbuf_read_until (mcview_t * view, off_t ofs)
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
assert (view->datasource == DS_VFS_PIPE);
|
||||
assert (view->datasource == DS_VFS_PIPE);
|
||||
do {
|
||||
nread = mc_read (view->ds_vfs_pipe, p, bytesfree);
|
||||
} while (nread == -1 && errno == EINTR);
|
||||
@ -183,16 +179,16 @@ mcview_get_byte_growing_buffer (mcview_t * view, off_t byte_index, int *retval)
|
||||
return FALSE;
|
||||
|
||||
mcview_growbuf_read_until (view, byte_index + 1);
|
||||
if (view->growbuf_blocks == 0)
|
||||
if (view->growbuf_blockptr->len == 0)
|
||||
return FALSE;
|
||||
if (pageno < view->growbuf_blocks - 1) {
|
||||
if (pageno < view->growbuf_blockptr->len - 1) {
|
||||
if (retval)
|
||||
*retval = view->growbuf_blockptr[pageno][pageindex];
|
||||
*retval = *((byte *) (g_ptr_array_index(view->growbuf_blockptr, pageno) + pageindex));
|
||||
return TRUE;
|
||||
}
|
||||
if (pageno == view->growbuf_blocks - 1 && pageindex < view->growbuf_lastindex) {
|
||||
if (pageno == view->growbuf_blockptr->len - 1 && pageindex < view->growbuf_lastindex) {
|
||||
if (retval)
|
||||
*retval = view->growbuf_blockptr[pageno][pageindex];
|
||||
*retval = *((byte *) (g_ptr_array_index(view->growbuf_blockptr, pageno) + pageindex));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -212,12 +208,12 @@ mcview_get_ptr_growing_buffer (mcview_t * view, off_t byte_index)
|
||||
return NULL;
|
||||
|
||||
mcview_growbuf_read_until (view, byte_index + 1);
|
||||
if (view->growbuf_blocks == 0)
|
||||
if (view->growbuf_blockptr->len == 0)
|
||||
return NULL;
|
||||
if (pageno < view->growbuf_blocks - 1)
|
||||
return (char *) (view->growbuf_blockptr[pageno] + pageindex);
|
||||
if (pageno == view->growbuf_blocks - 1 && pageindex < view->growbuf_lastindex)
|
||||
return (char *) (view->growbuf_blockptr[pageno] + pageindex);
|
||||
if (pageno < view->growbuf_blockptr->len - 1)
|
||||
return (char *) (g_ptr_array_index(view->growbuf_blockptr, pageno) + pageindex);
|
||||
if (pageno == view->growbuf_blockptr->len - 1 && pageindex < view->growbuf_lastindex)
|
||||
return (char *) (g_ptr_array_index(view->growbuf_blockptr, pageno) + pageindex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -107,8 +107,7 @@ typedef struct mcview_struct {
|
||||
|
||||
/* Growing buffers information */
|
||||
gboolean growbuf_in_use; /* Use the growing buffers? */
|
||||
byte **growbuf_blockptr; /* Pointer to the block pointers */
|
||||
size_t growbuf_blocks; /* The number of blocks in *block_ptr */
|
||||
GPtrArray *growbuf_blockptr; /* Pointer to the block pointers */
|
||||
size_t growbuf_lastindex; /* Number of bytes in the last page of the
|
||||
growing buffer */
|
||||
gboolean growbuf_finished; /* TRUE when all data has been read. */
|
||||
|
@ -106,6 +106,41 @@ mcview_find (mcview_t * view, gsize search_start, gsize * len)
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
mcview_search_show_result(mcview_t * view, Dlg_head **d, size_t match_len)
|
||||
{
|
||||
|
||||
view->search_start = view->search->normal_offset +
|
||||
mcview__get_nroff_real_len (view,
|
||||
view->search->start_buffer,
|
||||
view->search->normal_offset -
|
||||
view->search->start_buffer);
|
||||
|
||||
if (!view->hex_mode)
|
||||
view->search_start++;
|
||||
|
||||
view->search_end = view->search_start + match_len +
|
||||
mcview__get_nroff_real_len (view, view->search_start - 1, 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;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
dlg_run_done (*d);
|
||||
destroy_dlg (*d);
|
||||
*d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
|
||||
tty_refresh ();
|
||||
}
|
||||
mcview_moveto_match (view);
|
||||
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/*** public functions ****************************************************************************/
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -161,7 +196,7 @@ mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
|
||||
/* may be in future return from this callback will change current position
|
||||
* in searching block. Now this just constant return value.
|
||||
*/
|
||||
return 1;
|
||||
return MC_SEARCH_CB_OK;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -169,7 +204,7 @@ mcview_search_update_cmd_callback (const void *user_data, gsize char_offset)
|
||||
void
|
||||
mcview_do_search (mcview_t * view)
|
||||
{
|
||||
off_t search_start;
|
||||
off_t search_start, growbufsize;
|
||||
gboolean isFound = FALSE;
|
||||
|
||||
Dlg_head *d = NULL;
|
||||
@ -201,39 +236,33 @@ mcview_do_search (mcview_t * view)
|
||||
tty_enable_interrupt_key ();
|
||||
|
||||
do {
|
||||
if (mcview_find (view, search_start, &match_len)) {
|
||||
view->search_start = view->search->normal_offset +
|
||||
mcview__get_nroff_real_len (view,
|
||||
view->search->start_buffer,
|
||||
view->search->normal_offset -
|
||||
view->search->start_buffer);
|
||||
if (view->growbuf_in_use)
|
||||
growbufsize = mcview_growbuf_filesize (view);
|
||||
else
|
||||
growbufsize = view->search->original_len;
|
||||
|
||||
if (!view->hex_mode)
|
||||
view->search_start++;
|
||||
if (! mcview_find (view, search_start, &match_len)) {
|
||||
|
||||
view->search_end = view->search_start + match_len +
|
||||
mcview__get_nroff_real_len (view, view->search_start - 1, match_len);
|
||||
if (view->search->error_str == NULL)
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
search_start = growbufsize - view->search->original_len;
|
||||
if (search_start < 0 )
|
||||
search_start = 0;
|
||||
|
||||
if (verbose) {
|
||||
dlg_run_done (d);
|
||||
destroy_dlg (d);
|
||||
d = create_message (D_NORMAL, _("Search"), _("Seeking to search result"));
|
||||
tty_refresh ();
|
||||
}
|
||||
|
||||
mcview_moveto_match (view);
|
||||
isFound = TRUE;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
mcview_search_show_result(view, &d, match_len);
|
||||
isFound = TRUE;
|
||||
break;
|
||||
} while (mcview_may_still_grow (view));
|
||||
|
||||
if (!isFound && view->search->error_str != NULL && mcview_find (view, search_start, &match_len)) {
|
||||
mcview_search_show_result(view, &d, match_len);
|
||||
isFound = TRUE;
|
||||
}
|
||||
|
||||
if (!isFound) {
|
||||
if (view->search->error_str)
|
||||
message (D_NORMAL, _("Search"), "%s", view->search->error_str);
|
||||
|
Loading…
Reference in New Issue
Block a user