[PATCH] Editor locking update



Hi. I'm attaching a patch to the editor locking scheme. First of all
it adds the most useful option to "Lock encountered" dialog called
'Abort'. It allows user to cancel editing keypress and rewind any
changes. Unfortunately it required a new flag in the edit widget,
which I called rewind.

Moreover the patch forces mc to check validity of it lock before any
save operation, so it can react if the lock was grabbed by sb else.

I tested it in a few different scenarios, but of course any feedback
is appreciated. Andrew please could you review and apply this patch,
if Pavel is unavaliable?

Regards
Adam

-- 
  __ _
 / _` |   Adam Byrtek -*- jid alpha.jabber.lfa.pl -*- pgp 0xB25952C0
 \__,_|   "Każdy ideał w ciele jest trywialny" - prawdy algebraiczne

Index: ChangeLog
===================================================================
RCS file: /cvsroot/mc/mc/edit/ChangeLog,v
retrieving revision 1.188
diff -u -p -r1.188 ChangeLog
--- ChangeLog	4 Feb 2004 23:09:22 -0000	1.188
+++ ChangeLog	25 Mar 2004 22:01:45 -0000
@@ -1,3 +1,20 @@
+2004-03-25  Adam Byrtek  <alpha debian org>
+
+        * edit-widget.h (strruct WEdit): New flag rewind. 
+	* edit.c (edit_init): Initialize rewind with 0.
+	(edit_modification): Change rewind flag to 1 when lock
+	encountered and user aborts. (edit_execute_key_command):
+	Rewind last keypress undo information if rewind flag 1.
+	* editcmd.c (edit_save_as_cmd): Check if lock still valid
+	before save. Abort when lock encountered and user aborts.
+ 	(edit_save_cmd): The same as above.
+	* editlock.c: Spelling fixes. Sanity check in every function.
+	(edit_lock_file): New dialog option 'Abort'. 'Ignore lock'
+	rephrased to 'Proceed'. (edit_unlock_file): Parts moved to new
+	function edit_lock_check. (edit_lock_check): New function.
+	Check if lock is still valid (eg. not grabbed by sb else).
+	* editlock.h: New prototype edit_lock_check.
+
 2004-02-04  Pavel Roskin  <proski gnu org>
 
 	* editcmddef.h: Split CK_No_Command into CK_Insert_Char and
Index: edit-widget.h
===================================================================
RCS file: /cvsroot/mc/mc/edit/edit-widget.h,v
retrieving revision 1.23
diff -u -p -r1.23 edit-widget.h
--- edit-widget.h	29 Oct 2003 08:54:47 -0000	1.23
+++ edit-widget.h	25 Mar 2004 22:01:45 -0000
@@ -56,6 +56,7 @@ struct WEdit {
     int modified:1;		/* File has been modified and needs saving */
     int loading_done:1;		/* File has been loaded into the editor */
     int locked:1;		/* We hold lock on current file */
+    int rewind:1;		/* Rewind changes on abort */
     int screen_modified:1;	/* File has been changed since the last screen draw */
     int delete_file:1;		/* New file, needs to be deleted unless modified */
     int highlight:1;		/* There is a selected block */
Index: edit.c
===================================================================
RCS file: /cvsroot/mc/mc/edit/edit.c,v
retrieving revision 1.87
diff -u -p -r1.87 edit.c
--- edit.c	4 Feb 2004 22:27:58 -0000	1.87
+++ edit.c	25 Mar 2004 22:01:59 -0000
@@ -551,6 +551,7 @@ edit_init (WEdit *edit, int lines, int c
     edit->loading_done = 1;
     edit->modified = 0;
     edit->locked = 0;
+    edit->rewind = 0;
     edit_load_syntax (edit, 0, 0);
     {
 	int color;
@@ -816,12 +817,24 @@ pop_action (WEdit * edit)
 /* is called whenever a modification is made by one of the four routines below */
 static inline void edit_modification (WEdit * edit)
 {
+    int lock;
+    
     edit->caches_valid = 0;
     edit->screen_modified = 1;
     
-    /* raise lock when file modified */
-    if (!edit->modified && !edit->delete_file)
-	edit->locked = edit_lock_file (edit->filename);
+    /* Raise lock when file modified */
+    if (!edit->modified && !edit->delete_file) {
+	lock = edit_lock_file (edit->filename);
+	
+	/* User decided to abort, rewind */
+	if (lock == -1) {
+	    edit->locked = 0;
+	    edit->rewind = 1;
+	    edit->modified = 1;
+	}
+	edit->locked = lock;
+    }
+    
     edit->modified = 1;
 }
 
@@ -2125,6 +2138,15 @@ void edit_execute_key_command (WEdit *ed
 	edit_push_key_press (edit);
 
     edit_execute_cmd (edit, command, char_for_insertion);
+    
+    /* User aborted (eg. because file is locked), rewind the stack */
+    if (edit->rewind) {
+	edit_do_undo (edit);
+	edit->rewind = 0;
+	/* TODO: Should be done by edit_do_undo */
+	edit->modified = 0;
+    }
+	
     if (column_highlighting)
 	edit->force |= REDRAW_PAGE;
 }
Index: editcmd.c
===================================================================
RCS file: /cvsroot/mc/mc/edit/editcmd.c,v
retrieving revision 1.102
diff -u -p -r1.102 editcmd.c
--- editcmd.c	27 Nov 2003 10:23:50 -0000	1.102
+++ editcmd.c	25 Mar 2004 22:01:59 -0000
@@ -465,6 +465,9 @@ edit_save_as_cmd (WEdit *edit)
     exp = edit_get_save_file (edit->filename, _(" Save As "));
     edit_push_action (edit, KEY_PRESS + edit->start_display);
 
+    /* Check if lock still valid */
+    edit->locked = edit_lock_check (edit->filename);
+    
     if (exp) {
 	if (!*exp) {
 	    g_free (exp);
@@ -475,7 +478,7 @@ edit_save_as_cmd (WEdit *edit)
 		int file;
 		different_filename = 1;
 		if ((file = mc_open (exp, O_RDONLY | O_BINARY)) != -1) {
-		    /* the file exists */
+		    /* The file exists */
 		    mc_close (file);
 		    /* Overwrite the current file or cancel the operation */
 		    if (edit_query_dialog2
@@ -488,10 +491,21 @@ edit_save_as_cmd (WEdit *edit)
 		    }
 		}
 		save_lock = edit_lock_file (exp);
+		/* User aborted */
+		if (save_lock == -1) {
+		    g_free (exp);
+		    return 0;
+		}
 	    } else {
-		/* filenames equal, check if already locked */
-		if (!edit->locked && !edit->delete_file)
+		/* Filenames equal, raise lock if not already raised */
+		if (!edit->locked && !edit->delete_file) {
 		    save_lock = edit_lock_file (exp);
+		    /* User aborted */
+		    if (save_lock == -1) {
+			g_free (exp);
+			return 0;
+		    }
+		}
 	    }
 		
 	    if (edit_save_file (edit, exp)) {
@@ -515,7 +529,7 @@ edit_save_as_cmd (WEdit *edit)
 		edit->force |= REDRAW_COMPLETELY;
 		return 1;
 	    } else {
-		/* Failed, so maintain modify (not save) lock */
+		/* On failure maintain lock if locked before */
 		if (strcmp (edit->filename, exp) && save_lock)
 		    edit_unlock_file (exp);
 		if (save_lock)
@@ -778,11 +792,20 @@ edit_save_cmd (WEdit *edit)
 {
     int res, save_lock = 0;
     
-    if (!edit->locked && !edit->delete_file)
+    /* Check if lock is still valid */
+    edit->locked = edit_lock_check (edit->filename);
+    
+    /* Try to fetch lock otherwise */
+    if (!edit->locked && !edit->delete_file) {
 	save_lock = edit_lock_file (edit->filename);
+	/* User aborted */
+	if (save_lock == -1)
+	    return 0;
+    }
+
     res = edit_save_file (edit, edit->filename);
     
-    /* Maintain modify (not save) lock on failure */
+    /* On failure maintain lock if locked before */
     if ((res && edit->locked) || save_lock)
 	edit->locked = edit_unlock_file (edit->filename);
     
Index: editlock.c
===================================================================
RCS file: /cvsroot/mc/mc/edit/editlock.c,v
retrieving revision 1.6
diff -u -p -r1.6 editlock.c
--- editlock.c	21 Nov 2003 03:17:18 -0000	1.6
+++ editlock.c	25 Mar 2004 22:01:59 -0000
@@ -66,7 +66,7 @@ lock_build_name (char *fname)
     return g_strdup_printf ("%s %s %d", user, host, getpid ());
 }
 
-/* Extract pid from user host domain pid string */
+/* Extract info from user host domain pid string */
 static struct lock_s *
 lock_extract_info (char *str)
 {
@@ -112,9 +112,9 @@ lock_get_info (char *lockfname)
 }
 
 
-/* Tries to raise file lock
-   Returns 1 on success,  0 on failure, -1 if abort 
-   Warning: Might do screen refresh and lose edit->force */
+/* Try to raise file lock
+   Return 1 if lock raised,  0 if lock ignored, -1 on abort
+   Note: Might do screen refresh and lose edit->force */
 int
 edit_lock_file (char *fname)
 {
@@ -122,12 +122,8 @@ edit_lock_file (char *fname)
     struct stat statbuf;
     struct lock_s *lockinfo;
 
-    /* Just to be sure (and don't lock new file) */
-    if (!fname || !*fname)
-	return 0;
-
-    /* Locking on VFS is not supported */
-    if (!vfs_file_is_local (fname))
+    /* Some sanity checks */
+    if (!fname || !*fname || !vfs_file_is_local (fname))
 	return 0;
 
     /* Check if already locked */
@@ -148,17 +144,19 @@ edit_lock_file (char *fname)
 				 ("File \"%s\" is already being edited\n"
 				  "User: %s\nProcess ID: %d"), fname,
 				 lockinfo->who, lockinfo->pid);
-	    /* TODO: Implement "Abort" - needs to rewind undo stack */
-	    switch (edit_query_dialog2
+	    switch (edit_query_dialog3
 		    (_("File locked"), msg, _("&Grab lock"),
-		     _("&Ignore lock"))) {
+		     _("&Proceed"), _("&Abort"))) {
 	    case 0:
 		break;
 	    case 1:
-	    case -1:
 		g_free (lockfname);
 		g_free (msg);
 		return 0;
+	    case 2: case -1:
+		g_free (lockfname);
+		g_free (msg);
+		return -1;
 	    }
 	    g_free (msg);
 	}
@@ -178,37 +176,50 @@ edit_lock_file (char *fname)
     return 1;
 }
 
-/* Lowers file lock if possible 
-   Always returns 0 to make 'lock = edit_unlock_file (f)' possible */
+/* Lower file lock if possible 
+   Always return 0 to make 'lock = edit_unlock_file (f)' possible */
 int
 edit_unlock_file (char *fname)
 {
+    char *lockfname;
+
+    /* Some sanity checks */
+    if (!fname || !*fname || !vfs_file_is_local (fname))
+	return 0;
+
+    /* If lock is ours, remove it */
+    if (edit_lock_check (fname)) {
+	lockfname = g_strconcat (".#", fname, NULL);
+	unlink (lockfname);
+	g_free (lockfname);
+    }
+    return 0;
+}
+
+/* Check if lock is still valid
+   Return 1 if lock is valid, 0 if no lock or lock grabbed */
+int
+edit_lock_check (char *fname)
+{
     char *lockfname, *lock;
     struct stat statbuf;
 
-    /* Just to be sure */
-    if (!fname || !*fname)
+    /* Some sanity checks */
+    if (!fname || !*fname || !vfs_file_is_local (fname))
 	return 0;
 
-    lockfname = g_strconcat (".#", fname, NULL);
-
     /* Check if lock exists */
+    lockfname = g_strconcat (".#", fname, NULL);
     if (lstat (lockfname, &statbuf) == -1) {
 	g_free (lockfname);
 	return 0;
     }
 
     lock = lock_get_info (lockfname);
-    if (lock) {
-	/* Don't touch if lock is not ours */
-	if (lock_extract_info (lock)->pid != getpid ()) {
-	    g_free (lockfname);
-	    return 0;
-	}
-    }
-
-    /* Remove lock */
-    unlink (lockfname);
     g_free (lockfname);
-    return 0;
+
+    /* Check if lock is ours */
+    if (strcmp (lock_build_name (fname), lock) != 0)
+	return 0;
+    return 1;
 }
Index: editlock.h
===================================================================
RCS file: /cvsroot/mc/mc/edit/editlock.h,v
retrieving revision 1.1
diff -u -p -r1.1 editlock.h
--- editlock.h	2 Apr 2003 19:36:10 -0000	1.1
+++ editlock.h	25 Mar 2004 22:01:59 -0000
@@ -3,5 +3,6 @@
 
 int edit_lock_file (char *fname);
 int edit_unlock_file (char *fname);
+int edit_lock_check (char *fname);
 
 #endif				/* !__EDIT_LOCK_H */


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