[patch] interruptible file search & viewer operations



This is a reincarnation of patches I sent some time ago, but they weren't accepted due to code freeze before 4.6.0. I ported them to the current CVS and still hope you can find them useful.

find.diff modifies file search so it handles events during searching the file contents, which results in much greater responsiveness of the interface.

view.diff adds event checks to various places where the execution can get stuck - searching and file loading at the beginning and file loading in the growing view. There already were some checks in the search functions, but this patch allows using other keys than Ctrl-C, too (2xESC, Ctrl-G, F10).

--
Jindrich Makovicka
Index: dlg.c
===================================================================
RCS file: /cvs/gnome/mc/src/dlg.c,v
retrieving revision 1.66
diff -u -b -B -r1.66 dlg.c
--- dlg.c	24 Dec 2002 11:28:26 -0000	1.66
+++ dlg.c	4 May 2003 07:34:31 -0000
@@ -802,6 +802,9 @@
 	    if (!h->running)
 		break;
 	}
+	
+	/* to allow terminating the dlg from idle handler */
+	if (!h->running) break;
 
 	update_cursor (h);
 	(*h->callback) (h, 0, DLG_PRE_EVENT);
Index: find.c
===================================================================
RCS file: /cvs/gnome/mc/src/find.c,v
retrieving revision 1.62
diff -u -b -B -r1.62 find.c
--- find.c	16 Apr 2003 15:26:29 -0000	1.62
+++ find.c	4 May 2003 07:34:32 -0000
@@ -43,6 +43,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 */
@@ -64,6 +65,12 @@
     B_VIEW
 };
 
+typedef enum {
+    FIND_CONT,
+    FIND_SUSPEND,
+    FIND_ABORT
+} FindProgressStatus;
+
 /* List of directories to be ignored, separated by ':' */
 char *find_ignore_dirs = 0;
 
@@ -80,6 +87,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 */
@@ -437,32 +449,61 @@
     return buffer;
 }
 
+static FindProgressStatus
+check_find_events(Dlg_head *h)
+{
+    Gpm_Event event;
+    int c;
+    
+    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) {
+	    /* dialog terminated */
+	    return FIND_ABORT;
+	}
+	if (!h->send_idle_msg) {
+	    /* searching suspended */
+	    return FIND_SUSPEND;
+	}
+    }
+
+    return FIND_CONT;
+}
+
 /* 
  * search_content:
  *
  * 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));
 
@@ -480,7 +521,14 @@
 	char *p;
 	int found = 0;
 
-	while ((p = get_line_at (file_fd, buffer, &pos, &n_read, sizeof (buffer), &has_newline))){
+	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)) && (ret_val == 0)){
 	    if (found == 0){	/* Search in binary line once */
 		if (regexec (r, p, 1, 0, 0) == 0){
 		    g_free (p);
@@ -494,10 +542,31 @@
 		found = 0;
 	    }
 	    g_free (p);
+ 
+ 	    if ((line & 0xff) == 0) {
+		FindProgressStatus res;
+		res = check_find_events(h);
+		switch (res) {
+		case FIND_ABORT:
+		    stop_idle (h);
+		    ret_val = 1;
+		    break;
+		case FIND_SUSPEND:
+		    resuming = 1;
+		    last_line = line;
+		    last_pos = pos;
+		    ret_val = 1;
+		    break;
+		default:
+		    break;
+		}
+	    }
+ 
 	}
     }
     disable_interrupt_key ();
     mc_close (file_fd);
+    return ret_val;
 }
 
 static int
@@ -593,9 +662,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);
     }
     
@@ -849,6 +921,7 @@
 static int
 run_process (void)
 {
+    resuming = 0;
     set_idle_proc (find_dlg, 1);
     run_dlg (find_dlg);
     return find_dlg->ret_value;
Index: view.c
===================================================================
RCS file: /cvs/gnome/mc/src/view.c,v
retrieving revision 1.119
diff -u -b -B -r1.119 view.c
--- view.c	24 Mar 2003 18:52:02 -0000	1.119
+++ view.c	4 May 2003 08:37:30 -0000
@@ -109,6 +109,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? */
 
@@ -141,6 +143,7 @@
     
     /* Growing buffers information */
     int growing_buffer;		/* Use the growing buffers? */
+    int growing_loading;        /* Loading additional blocks NOW */
     struct block_ptr_t *block_ptr;	/* Pointer to the block pointers */
     int          blocks;	/* The number of blocks in *block_ptr */
 
@@ -210,6 +213,7 @@
 static void view_labels (WView * view);
 static void set_monitor (WView * view, int set_on);
 static void view_update (WView * view, gboolean update_gui);
+static void view_percent (WView *view, int p, int w, gboolean update_gui);
 
 
 static void
@@ -296,6 +300,24 @@
 	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;
+
+    if (got_interrupt()) return 1;
+    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)
 {
@@ -330,7 +352,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++;
 		}
 	    }
@@ -509,6 +531,7 @@
 {
     view->growing_buffer = 0;
     view->reading_pipe = 0;
+    view->partial = 0;
     view->first = 0;
     view->last_byte = 0;
     if (msg) {
@@ -518,6 +541,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)
@@ -565,6 +627,8 @@
 static char *
 load_view_file (WView *view, int fd)
 {
+    int intr_flag = 0;
+    
     view->file = fd;
 
     if (view->s.st_size == 0) {
@@ -596,10 +660,13 @@
 	view->data = NULL;
 
     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)) {
 	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;
@@ -625,6 +692,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;
@@ -834,7 +902,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) {
@@ -1374,11 +1444,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);
@@ -1626,6 +1712,7 @@
     long t;
     /* Clear interrupt status */
     got_interrupt ();
+    enable_interrupt_key ();
 
     if (verbose) {
 	d = message (D_INSERT, _("Search"), _("Searching %s"), text);
@@ -1653,8 +1740,7 @@
 		view_percent (view, p, w, TRUE);
 		mc_refresh ();
 	    }
-	    if (got_interrupt ())
-		break;
+	    if (int_key()) break;
 	}
 	forward_line_start = p;
 	disable_interrupt_key ();
@@ -1743,7 +1829,7 @@
 		    view_percent (view, e, w, TRUE);
 		    mc_refresh ();
 		}
-		if (got_interrupt ())
+		if (int_key ())
 		    break;
 	    }
 	    b = get_byte (view, e);
@@ -1769,7 +1855,7 @@
 		    view_percent (view, e, w, TRUE);
 		    mc_refresh ();
 		}
-		if (got_interrupt ())
+		if (int_key ())
 		    break;
 	    }
 	    b = get_byte (view, e++);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]