Hello, here is a better version of the previous patch, fixed and separated.
1) copy.patch - fixes the event handling in copy file dialog 2) findfile.patch - adds additional event checking into the grepping function to make the dialog react during grepping inside a file (I agree this is a bit hackish but seems to work and without threads it's hard to make a better solution) 3) vfsopen.patch - makes it possible to interrupt file load operation on vfs (typically slow ftp & accidentally pressing f3 on a large file) 4) viewintr.patch - Ctrl-G during file load without MMAP reverts to growing view (test - eg. NTFS partition); get_bottom_first in growing view can be interrupted (test - M-! ls -lR on root and pressing End); search can be interrupted 5) viewsearch.patch - block_search modified to use a lookup table to lower comparison count Regards, -- Jindrich Makovicka
diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/file.c mc-4.6.0-pre1/src/file.c --- vanilla/mc-4.6.0-pre1/src/file.c Fri Jul 5 06:04:41 2002 +++ mc-4.6.0-pre1/src/file.c Tue Sep 24 19:14:44 2002 @@ -733,7 +733,11 @@ } file_progress_set_stalled_label (ctx, stalled_msg); - file_progress_show_bytes (ctx, *progress_bytes + n_read_total, ctx->progress_bytes); + return_status = file_progress_show_bytes (ctx, *progress_bytes + +n_read_total, ctx->progress_bytes); + if (return_status != FILE_CONT) { + mc_refresh (); + goto ret; + } return_status = file_progress_show (ctx, n_read_total, file_size); mc_refresh (); if (return_status != FILE_CONT)
diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/dlg.c mc-4.6.0-pre1/src/dlg.c --- vanilla/mc-4.6.0-pre1/src/dlg.c Fri Aug 2 06:36:04 2002 +++ mc-4.6.0-pre1/src/dlg.c Tue Sep 24 19:16:40 2002 @@ -833,6 +833,9 @@ (*h->callback) (h, 0, DLG_IDLE); } } + + /* to allow terminating the dlg from idle handler */ + if (!h->running) break; update_cursor (h); (*h->callback)(h, 0, DLG_PRE_EVENT); diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/find.c mc-4.6.0-pre1/src/find.c --- vanilla/mc-4.6.0-pre1/src/find.c Wed Aug 21 09:31:20 2002 +++ mc-4.6.0-pre1/src/find.c Tue Sep 24 19:29:11 2002 @@ -44,6 +44,7 @@ #include "wtools.h" #include "cmd.h" /* view_file_at_line */ #include "boxes.h" +#include "key.h" #include "../vfs/vfs.h" /* Size of the find parameters window */ @@ -79,6 +80,11 @@ static int is_start; /* Status of the start/stop toggle button */ static char *old_dir; +/* Where did we stop */ +static int resuming; +static int last_line; +static int last_pos; + static Dlg_head *find_dlg; /* The dialog */ static WButton *stop_button; /* pointer to the stop button */ @@ -420,27 +426,31 @@ * * Search the global (FIXME) regexp compiled content_pattern string in the * DIRECTORY/FILE. It will add the found entries to the find listbox. + * + * returns 0 if do_search should look for another file + * 1 if do_search should exit and proceed to the event handler */ -static void +static int search_content (Dlg_head *h, char *directory, char *filename) { struct stat s; char buffer [BUF_SMALL]; char *fname; int file_fd; + int ret_val = 0; fname = concat_dir_and_file (directory, filename); if (mc_stat (fname, &s) != 0 || !S_ISREG (s.st_mode)){ g_free (fname); - return; + return 0; } file_fd = mc_open (fname, O_RDONLY); g_free (fname); if (file_fd == -1) - return; + return 0; g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE)); @@ -457,6 +467,15 @@ int has_newline; char *p; int found = 0; + Gpm_Event event; + int c; + + if (resuming) { + /* We've been previously suspended, start from the previous position */ + resuming = 0; + line = last_line; + pos = last_pos; + } while ((p = get_line_at (file_fd, buffer, &pos, &n_read, sizeof (buffer), &has_newline))){ if (found == 0){ /* Search in binary line once */ @@ -472,10 +491,37 @@ found = 0; } g_free (p); + + /* check for events */ + if ((line & 0x3f) == 0) { + c = get_event (&event, h->mouse_status == MOU_REPEAT, 0); + if (c != EV_NONE) { + dlg_process_event (h, c, &event); + if (h->ret_value == B_ENTER + || h->ret_value == B_CANCEL + || h->ret_value == B_AGAIN + || h->ret_value == B_PANELIZE) { + /* closing events */ + stop_idle (h); + ret_val = 1; + break; + } + if (!h->send_idle_msg) { + /* suspended */ + resuming = 1; + last_line = line; + last_pos = pos; + ret_val = 1; + break; + } + } + } + } } disable_interrupt_key (); mc_close (file_fd); + return ret_val; } static int @@ -571,9 +617,12 @@ } if (regexp_match (find_pattern, dp->d_name, match_file)){ - if (content_pattern) - search_content (h, directory, dp->d_name); - else + if (content_pattern) { + if (search_content (h, directory, dp->d_name)) { + g_free (tmp_name); + return 1; + } + } else find_add_match (h, directory, dp->d_name); } @@ -817,6 +866,7 @@ static int run_process (void) { + resuming = 0; set_idle_proc (find_dlg, 1); run_dlg (find_dlg); return find_dlg->ret_value;
diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/ext.c mc-4.6.0-pre1/src/ext.c --- vanilla/mc-4.6.0-pre1/src/ext.c Tue Aug 20 04:57:25 2002 +++ mc-4.6.0-pre1/src/ext.c Tue Sep 24 19:14:44 2002 @@ -482,7 +482,9 @@ content_string [hasread] = 0; } mc_close (remotehandle); - } + } else { + ret = 1; + } #endif /* _OS_NT */ } asked_file = 1; diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/vfs/direntry.c mc-4.6.0-pre1/vfs/direntry.c --- vanilla/mc-4.6.0-pre1/vfs/direntry.c Tue Aug 20 04:57:26 2002 +++ mc-4.6.0-pre1/vfs/direntry.c Tue Sep 24 19:14:44 2002 @@ -949,7 +949,9 @@ goto error_3; /* Clear the interrupt status */ - + got_interrupt(); + enable_interrupt_key(); + while ((n = MEDATA->linear_read (me, &fh, buffer, sizeof(buffer)))) { if (n < 0) @@ -957,6 +959,9 @@ total += n; vfs_print_stats (me->name, _("Getting file"), ino->ent->name, total, stat_size); + + if (got_interrupt()) + goto error_1; if (write(handle, buffer, n) < 0) { me->verrno = errno;
diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/view.c mc-4.6.0-pre1/src/view.c --- vanilla/mc-4.6.0-pre1/src/view.c Wed Aug 21 09:31:29 2002 +++ mc-4.6.0-pre1/src/view.c Tue Sep 24 20:02:32 2002 @@ -207,6 +207,23 @@ delete_hook (&select_file_hook, view_hook); } +/* check if the event is an interrupt key + * unfortunately we cannot enable SIGINT because then CTRL-C can + * stop the page reading in the middle and viewer gets confused + */ +static int int_key() +{ + Gpm_Event event; + int c; + + c = get_event (&event, 0, 0); + if (c == XCTRL('g') || c == ESC_CHAR || c == KEY_F(10) || c == XCTRL('c')) { + return 1; + } + return 0; +} + + static int get_byte (WView *view, unsigned int byte_index) { @@ -241,7 +258,7 @@ view->last_byte = view->first + view->bytes_read; } /* To force loading the next page */ - if (n == VIEW_PAGE_SIZE && view->reading_pipe){ + if (n == VIEW_PAGE_SIZE && (view->reading_pipe || view->partial)){ view->last_byte++; } } @@ -424,6 +441,7 @@ { view->growing_buffer = 0; view->reading_pipe = 0; + view->partial = 0; view->first = 0; view->last_byte = 0; if (msg){ @@ -433,6 +451,45 @@ return 0; } +/* read a file into memory, can be interrupted */ +#define READ_PAGE_SIZE 32768 +ssize_t +mc_read_interruptible (WView *view) +{ + int w = view->widget.cols - view->have_frame + 1; + int fd = view->file; + void *buf = view->data; + size_t count = view->s.st_size; + ssize_t to_read, res; + ssize_t total = 0; + Dlg_head *d = 0; + + if (verbose) { + d = message (D_INSERT, _(" View "), _("Reading %s"), view->filename); + mc_refresh (); + } + + while (count) { + to_read = count > READ_PAGE_SIZE ? READ_PAGE_SIZE : count; + res = mc_read(fd, buf, to_read); + total += res; + if (res != to_read) + break; + if (int_key ()) break; + if (verbose) { + view_percent (view, total, w, TRUE); + mc_refresh (); + } + buf += to_read; + count -= to_read; + } + if (verbose) { + dlg_run_done (d); + destroy_dlg (d); + } + return total; +} + /* return values: NULL for success, else points to error message */ static char * init_growing_view (WView *view, char *name, char *filename) @@ -473,6 +530,8 @@ */ static char *load_view_file (WView *view, int fd) { + int intr_flag = 0; + view->file = fd; if (view->s.st_size == 0){ @@ -500,12 +559,17 @@ view->data = (unsigned char*) g_malloc (view->s.st_size); if (view->data == NULL || mc_lseek(view->file, 0, SEEK_SET) != 0 - || mc_read(view->file, view->data, view->s.st_size) != view->s.st_size){ + || (intr_flag = mc_read_interruptible(view) != view->s.st_size)){ if (view->data != NULL) g_free (view->data); close_view_file (view); + if (intr_flag) { + view->partial = 1; + view->s.st_size = 0; + } return init_growing_view (view, 0, view->filename); } + view->first = 0; view->bytes_read = view->s.st_size; return NULL; @@ -528,6 +592,7 @@ view->data = NULL; view->growing_buffer = 0; view->reading_pipe = 0; + view->partial = 0; view->mmapping = 0; view->blocks = 0; view->block_ptr = 0; @@ -721,7 +786,9 @@ } if (w > 70){ printw (" "); - if (view->growing_buffer) + if (view->growing_buffer && view->growing_loading) + addstr (_(" [loading]")); + else if (view->growing_buffer) addstr (_(" [grow]")); } if (w > 26) { @@ -1252,11 +1319,27 @@ if (view->growing_buffer){ int old_last_byte; + view->growing_loading = 1; old_last_byte = -1; while (old_last_byte != view->last_byte){ old_last_byte = view->last_byte; + if (verbose) { + view_status(view, TRUE); + mc_refresh (); + } + attrset (NORMAL_COLOR); + get_byte (view, view->last_byte+VIEW_PAGE_SIZE); + if (int_key()) break; } + view->growing_loading = 0; + + if (verbose) { + view_status(view, TRUE); + mc_refresh (); + } + attrset (NORMAL_COLOR); + } bottom_first = move_backward2 (view, view->last_byte, vheight - 1); @@ -1265,7 +1348,7 @@ bottom_first = (bottom_first + view->bytes_per_line - 1) / view->bytes_per_line * view->bytes_per_line; view->bottom_first = bottom_first; - + return view->bottom_first; } @@ -1475,8 +1558,6 @@ long forward_line_start; long reverse_line_start; long t; - /* Clear interrupt status */ - got_interrupt (); if (verbose){ d = message (D_INSERT, _(" Search "), _("Searching %s"), text); @@ -1504,14 +1585,11 @@ view_percent (view, p, w, TRUE); mc_refresh (); } - if (got_interrupt ()) - break; + if (int_key()) break; } forward_line_start = p; - disable_interrupt_key (); s = get_line_at (view, &p, &t); reverse_line_start = p; - enable_interrupt_key (); if (!s) break; @@ -1552,7 +1630,6 @@ g_free (s); break; } - disable_interrupt_key (); if (verbose) { dlg_run_done (d); destroy_dlg (d); diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/view.h mc-4.6.0-pre1/src/view.h --- vanilla/mc-4.6.0-pre1/src/view.h Sat Jul 20 04:54:52 2002 +++ mc-4.6.0-pre1/src/view.h Tue Sep 24 19:37:36 2002 @@ -28,6 +28,8 @@ int file; /* File descriptor (for mmap and munmap) */ FILE *stdfile; /* Stdio struct for reading file in parts */ int reading_pipe; /* Flag: Reading from pipe(use popen/pclose) */ + int partial; /* Flag: File reading was interrupted, + reverted to growing view */ unsigned long bytes_read; /* How much of file is read */ int mmapping; /* Did we use mmap on the file? */ @@ -60,6 +62,7 @@ /* Growing buffers information */ int growing_buffer; /* Use the growing buffers? */ + int growing_loading; /* Loading additional blocks NOW */ block_ptr_t *block_ptr; /* Pointer to the block pointers */ int blocks; /* The number of blocks in *block_ptr */
diff --exclude-from dontdiff -urN vanilla/mc-4.6.0-pre1/src/view.c mc-4.6.0-pre1/src/view.c --- vanilla/mc-4.6.0-pre1/src/view.c Wed Aug 21 09:31:29 2002 +++ mc-4.6.0-pre1/src/view.c Tue Sep 24 19:51:40 2002 @@ -1571,40 +1651,51 @@ int w = view->widget.cols - view->have_frame + 1; char *d = buffer, b; + int lookup[256]; + int i, step; unsigned long e; - /* clear interrupt status */ - got_interrupt (); - enable_interrupt_key (); e = view->found_len ? view->search_start + 1 : view->search_start; search_update_steps (view); update_activate = 0; + + for (i = 0; i < 256; i++) + lookup[i] = len; + for (i = len-1; i >= 0; i--, d++) + lookup[(unsigned char)*d] = i; + + d = buffer; - while (e < view->last_byte){ + while (e+len-1 < view->last_byte){ if (e >= update_activate){ update_activate += update_steps; if (verbose){ view_percent (view, e, w, TRUE); mc_refresh (); } - if (got_interrupt ()) - break; + if (int_key()) break; } - b = get_byte (view, e++); - - if (*d == b){ - d++; - if (d - buffer == len){ - disable_interrupt_key (); - return e - len; - } - } else { - e -= d - buffer; + + b = get_byte(view, e+len-1); + step = lookup[(unsigned char)b]; + + if (step == 0) { + /* possible match, need to compare whole string */ d = buffer; + while (1) { + b = get_byte (view, e++); + if (*d != b) break; + d++; + if (d - buffer == len) { + /* match */ + return e - len; + } + } + step = 1; } + e += step; } - disable_interrupt_key (); return -1; }