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:
Slava Zanko 2009-12-14 11:01:28 +02:00
parent 0ad310c1c6
commit 46f6c4d1b7
5 changed files with 95 additions and 70 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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. */

View File

@ -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);