summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.1231
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.1231')
-rw-r--r--data/vim/patches/8.1.1231943
1 files changed, 943 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.1231 b/data/vim/patches/8.1.1231
new file mode 100644
index 000000000..d7365dffd
--- /dev/null
+++ b/data/vim/patches/8.1.1231
@@ -0,0 +1,943 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 8.1.1231
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 8.1.1231
+Problem: Asking about existing swap file unnecessarily.
+Solution: When it is safe, delete the swap file. Remove
+ HAS_SWAP_EXISTS_ACTION, it is always defined. (closes #1237)
+Files: src/memline.c, src/globals.h, src/buffer.c, src/ex_cmds.c,
+ src/fileio.c, src/main.c, src/testdir/test_swap.vim,
+ runtime/doc/usr_11.txt, src/os_win32.c, src/proto/os_win32.pro,
+ src/os_unix.c, src/proto/os_unix.pro
+
+
+*** ../vim-8.1.1230/src/memline.c 2019-04-28 19:46:17.030060105 +0200
+--- src/memline.c 2019-04-28 22:22:42.217091959 +0200
+***************
+*** 2159,2167 ****
+ {
+ msg_puts(_("\n process ID: "));
+ msg_outnum(char_to_long(b0.b0_pid));
+! #if defined(UNIX)
+! /* EMX kill() not working correctly, it seems */
+! if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
+ {
+ msg_puts(_(" (STILL RUNNING)"));
+ # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+--- 2159,2166 ----
+ {
+ msg_puts(_("\n process ID: "));
+ msg_outnum(char_to_long(b0.b0_pid));
+! #if defined(UNIX) || defined(MSWIN)
+! if (mch_process_running((pid_t)char_to_long(b0.b0_pid)))
+ {
+ msg_puts(_(" (STILL RUNNING)"));
+ # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+***************
+*** 2193,2198 ****
+--- 2192,2248 ----
+ return x;
+ }
+
++ /*
++ * Return TRUE if the swap file looks OK and there are no changes, thus it can
++ * be safely deleted.
++ */
++ static time_t
++ swapfile_unchanged(char_u *fname)
++ {
++ stat_T st;
++ int fd;
++ struct block0 b0;
++ int ret = TRUE;
++ #ifdef UNIX
++ long pid;
++ #endif
++
++ // must be able to stat the swap file
++ if (mch_stat((char *)fname, &st) == -1)
++ return FALSE;
++
++ // must be able to read the first block
++ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
++ if (fd < 0)
++ return FALSE;
++ if (read_eintr(fd, &b0, sizeof(b0)) != sizeof(b0))
++ {
++ close(fd);
++ return FALSE;
++ }
++
++ // the ID and magic number must be correct
++ if (ml_check_b0_id(&b0) == FAIL|| b0_magic_wrong(&b0))
++ ret = FALSE;
++
++ // must be unchanged
++ if (b0.b0_dirty)
++ ret = FALSE;
++
++ #if defined(UNIX) || defined(MSWIN)
++ // process must known and not be running
++ pid = char_to_long(b0.b0_pid);
++ if (pid == 0L || mch_process_running((pid_t)pid))
++ ret = FALSE;
++ #endif
++
++ // TODO: Should we check if the swap file was created on the current
++ // system? And the current user?
++
++ close(fd);
++ return ret;
++ }
++
+ static int
+ recov_file_names(char_u **names, char_u *path, int prepend_dot)
+ {
+***************
+*** 4757,4765 ****
+ if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
+ && vim_strchr(p_shm, SHM_ATTENTION) == NULL)
+ {
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ int choice = 0;
+! #endif
+ #ifdef CREATE_DUMMY_FILE
+ int did_use_dummy = FALSE;
+
+--- 4807,4814 ----
+ if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
+ && vim_strchr(p_shm, SHM_ATTENTION) == NULL)
+ {
+ int choice = 0;
+! stat_T st;
+ #ifdef CREATE_DUMMY_FILE
+ int did_use_dummy = FALSE;
+
+***************
+*** 4779,4791 ****
+ #if (defined(UNIX) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
+ process_still_running = FALSE;
+ #endif
+ #if defined(FEAT_EVAL)
+ /*
+ * If there is an SwapExists autocommand and we can handle
+ * the response, trigger it. It may return 0 to ask the
+ * user anyway.
+ */
+! if (swap_exists_action != SEA_NONE
+ && has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
+ choice = do_swapexists(buf, fname);
+
+--- 4828,4852 ----
+ #if (defined(UNIX) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
+ process_still_running = FALSE;
+ #endif
++ // It's safe to delete the swap file if all these are true:
++ // - the edited file exists
++ // - the swap file has no changes and looks OK
++ if (mch_stat((char *)buf->b_fname, &st) == 0
++ && swapfile_unchanged(fname))
++ {
++ choice = 4;
++ if (p_verbose > 0)
++ verb_msg(_("Found a swap file that is not useful, deleting it"));
++ }
++
+ #if defined(FEAT_EVAL)
+ /*
+ * If there is an SwapExists autocommand and we can handle
+ * the response, trigger it. It may return 0 to ask the
+ * user anyway.
+ */
+! if (choice == 0
+! && swap_exists_action != SEA_NONE
+ && has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
+ choice = do_swapexists(buf, fname);
+
+***************
+*** 4850,4856 ****
+ }
+ #endif
+
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ if (choice > 0)
+ {
+ switch (choice)
+--- 4911,4916 ----
+***************
+*** 4880,4886 ****
+ break;
+ }
+ else
+- #endif
+ {
+ msg_puts("\n");
+ if (msg_silent == 0)
+--- 4940,4945 ----
+*** ../vim-8.1.1230/src/globals.h 2019-04-28 19:46:17.026060122 +0200
+--- src/globals.h 2019-04-28 22:14:01.975212661 +0200
+***************
+*** 966,972 ****
+ EXTERN int emsg_noredir INIT(= 0); /* don't redirect error messages */
+ EXTERN int cmd_silent INIT(= FALSE); /* don't echo the command line */
+
+- # define HAS_SWAP_EXISTS_ACTION
+ EXTERN int swap_exists_action INIT(= SEA_NONE);
+ /* For dialog when swap file already
+ * exists. */
+--- 966,971 ----
+***************
+*** 1644,1649 ****
+--- 1643,1651 ----
+ #endif
+
+ #ifdef MSWIN
++ # ifdef PROTO
++ typedef int HINSTANCE;
++ # endif
+ EXTERN int ctrl_break_was_pressed INIT(= FALSE);
+ EXTERN HINSTANCE g_hinst INIT(= NULL);
+ #endif
+*** ../vim-8.1.1230/src/buffer.c 2019-04-28 18:04:56.054492198 +0200
+--- src/buffer.c 2019-04-28 20:19:17.859717974 +0200
+***************
+*** 972,1014 ****
+ int dir,
+ int count)
+ {
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ bufref_T old_curbuf;
+
+ set_bufref(&old_curbuf, curbuf);
+
+ swap_exists_action = SEA_DIALOG;
+- #endif
+ (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
+ start, dir, count, eap->forceit);
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ if (swap_exists_action == SEA_QUIT && *eap->cmd == 's')
+ {
+! # if defined(FEAT_EVAL)
+ cleanup_T cs;
+
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a window. */
+ enter_cleanup(&cs);
+! # endif
+
+ /* Quitting means closing the split window, nothing else. */
+ win_close(curwin, TRUE);
+ swap_exists_action = SEA_NONE;
+ swap_exists_did_quit = TRUE;
+
+! # if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not discarded by a
+ * new aborting error, interrupt, or uncaught exception. */
+ leave_cleanup(&cs);
+! # endif
+ }
+ else
+ handle_swap_exists(&old_curbuf);
+- #endif
+ }
+
+- #if defined(HAS_SWAP_EXISTS_ACTION) || defined(PROTO)
+ /*
+ * Handle the situation of swap_exists_action being set.
+ * It is allowed for "old_curbuf" to be NULL or invalid.
+--- 972,1009 ----
+ int dir,
+ int count)
+ {
+ bufref_T old_curbuf;
+
+ set_bufref(&old_curbuf, curbuf);
+
+ swap_exists_action = SEA_DIALOG;
+ (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
+ start, dir, count, eap->forceit);
+ if (swap_exists_action == SEA_QUIT && *eap->cmd == 's')
+ {
+! #if defined(FEAT_EVAL)
+ cleanup_T cs;
+
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a window. */
+ enter_cleanup(&cs);
+! #endif
+
+ /* Quitting means closing the split window, nothing else. */
+ win_close(curwin, TRUE);
+ swap_exists_action = SEA_NONE;
+ swap_exists_did_quit = TRUE;
+
+! #if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not discarded by a
+ * new aborting error, interrupt, or uncaught exception. */
+ leave_cleanup(&cs);
+! #endif
+ }
+ else
+ handle_swap_exists(&old_curbuf);
+ }
+
+ /*
+ * Handle the situation of swap_exists_action being set.
+ * It is allowed for "old_curbuf" to be NULL or invalid.
+***************
+*** 1016,1036 ****
+ void
+ handle_swap_exists(bufref_T *old_curbuf)
+ {
+! # if defined(FEAT_EVAL)
+ cleanup_T cs;
+! # endif
+! # ifdef FEAT_SYN_HL
+ long old_tw = curbuf->b_p_tw;
+! # endif
+ buf_T *buf;
+
+ if (swap_exists_action == SEA_QUIT)
+ {
+! # if defined(FEAT_EVAL)
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a buffer. */
+ enter_cleanup(&cs);
+! # endif
+
+ /* User selected Quit at ATTENTION prompt. Go back to previous
+ * buffer. If that buffer is gone or the same as the current one,
+--- 1011,1031 ----
+ void
+ handle_swap_exists(bufref_T *old_curbuf)
+ {
+! #if defined(FEAT_EVAL)
+ cleanup_T cs;
+! #endif
+! #ifdef FEAT_SYN_HL
+ long old_tw = curbuf->b_p_tw;
+! #endif
+ buf_T *buf;
+
+ if (swap_exists_action == SEA_QUIT)
+ {
+! #if defined(FEAT_EVAL)
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a buffer. */
+ enter_cleanup(&cs);
+! #endif
+
+ /* User selected Quit at ATTENTION prompt. Go back to previous
+ * buffer. If that buffer is gone or the same as the current one,
+***************
+*** 1053,1078 ****
+ // restore msg_silent, so that the command line will be shown
+ msg_silent = old_msg_silent;
+
+! # ifdef FEAT_SYN_HL
+ if (old_tw != curbuf->b_p_tw)
+ check_colorcolumn(curwin);
+! # endif
+ }
+ /* If "old_curbuf" is NULL we are in big trouble here... */
+
+! # if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not discarded by a
+ * new aborting error, interrupt, or uncaught exception. */
+ leave_cleanup(&cs);
+! # endif
+ }
+ else if (swap_exists_action == SEA_RECOVER)
+ {
+! # if defined(FEAT_EVAL)
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a buffer. */
+ enter_cleanup(&cs);
+! # endif
+
+ /* User selected Recover at ATTENTION prompt. */
+ msg_scroll = TRUE;
+--- 1048,1073 ----
+ // restore msg_silent, so that the command line will be shown
+ msg_silent = old_msg_silent;
+
+! #ifdef FEAT_SYN_HL
+ if (old_tw != curbuf->b_p_tw)
+ check_colorcolumn(curwin);
+! #endif
+ }
+ /* If "old_curbuf" is NULL we are in big trouble here... */
+
+! #if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not discarded by a
+ * new aborting error, interrupt, or uncaught exception. */
+ leave_cleanup(&cs);
+! #endif
+ }
+ else if (swap_exists_action == SEA_RECOVER)
+ {
+! #if defined(FEAT_EVAL)
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a buffer. */
+ enter_cleanup(&cs);
+! #endif
+
+ /* User selected Recover at ATTENTION prompt. */
+ msg_scroll = TRUE;
+***************
+*** 1081,1095 ****
+ cmdline_row = msg_row;
+ do_modelines(0);
+
+! # if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not discarded by a
+ * new aborting error, interrupt, or uncaught exception. */
+ leave_cleanup(&cs);
+! # endif
+ }
+ swap_exists_action = SEA_NONE;
+ }
+- #endif
+
+ /*
+ * do_bufdel() - delete or unload buffer(s)
+--- 1076,1089 ----
+ cmdline_row = msg_row;
+ do_modelines(0);
+
+! #if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not discarded by a
+ * new aborting error, interrupt, or uncaught exception. */
+ leave_cleanup(&cs);
+! #endif
+ }
+ swap_exists_action = SEA_NONE;
+ }
+
+ /*
+ * do_bufdel() - delete or unload buffer(s)
+***************
+*** 5259,5286 ****
+ continue;
+
+ /* Open the buffer in this window. */
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ swap_exists_action = SEA_DIALOG;
+- #endif
+ set_curbuf(buf, DOBUF_GOTO);
+ if (!bufref_valid(&bufref))
+ {
+ /* autocommands deleted the buffer!!! */
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ swap_exists_action = SEA_NONE;
+- #endif
+ break;
+ }
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ if (swap_exists_action == SEA_QUIT)
+ {
+! # if defined(FEAT_EVAL)
+ cleanup_T cs;
+
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a window. */
+ enter_cleanup(&cs);
+! # endif
+
+ /* User selected Quit at ATTENTION prompt; close this window. */
+ win_close(curwin, TRUE);
+--- 5253,5275 ----
+ continue;
+
+ /* Open the buffer in this window. */
+ swap_exists_action = SEA_DIALOG;
+ set_curbuf(buf, DOBUF_GOTO);
+ if (!bufref_valid(&bufref))
+ {
+ /* autocommands deleted the buffer!!! */
+ swap_exists_action = SEA_NONE;
+ break;
+ }
+ if (swap_exists_action == SEA_QUIT)
+ {
+! #if defined(FEAT_EVAL)
+ cleanup_T cs;
+
+ /* Reset the error/interrupt/exception state here so that
+ * aborting() returns FALSE when closing a window. */
+ enter_cleanup(&cs);
+! #endif
+
+ /* User selected Quit at ATTENTION prompt; close this window. */
+ win_close(curwin, TRUE);
+***************
+*** 5288,5303 ****
+ swap_exists_action = SEA_NONE;
+ swap_exists_did_quit = TRUE;
+
+! # if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not
+ * discarded by a new aborting error, interrupt, or uncaught
+ * exception. */
+ leave_cleanup(&cs);
+! # endif
+ }
+ else
+ handle_swap_exists(NULL);
+- #endif
+ }
+
+ ui_breakcheck();
+--- 5277,5291 ----
+ swap_exists_action = SEA_NONE;
+ swap_exists_did_quit = TRUE;
+
+! #if defined(FEAT_EVAL)
+ /* Restore the error/interrupt/exception state if not
+ * discarded by a new aborting error, interrupt, or uncaught
+ * exception. */
+ leave_cleanup(&cs);
+! #endif
+ }
+ else
+ handle_swap_exists(NULL);
+ }
+
+ ui_breakcheck();
+*** ../vim-8.1.1230/src/ex_cmds.c 2019-04-28 19:46:17.022060143 +0200
+--- src/ex_cmds.c 2019-04-28 20:19:31.859649114 +0200
+***************
+*** 4258,4266 ****
+ topline = curwin->w_topline;
+ if (!oldbuf) /* need to read the file */
+ {
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ swap_exists_action = SEA_DIALOG;
+- #endif
+ curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
+
+ /*
+--- 4258,4264 ----
+***************
+*** 4273,4283 ****
+ (void)open_buffer(FALSE, eap, readfile_flags);
+ #endif
+
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ if (swap_exists_action == SEA_QUIT)
+ retval = FAIL;
+ handle_swap_exists(&old_curbuf);
+- #endif
+ }
+ else
+ {
+--- 4271,4279 ----
+*** ../vim-8.1.1230/src/fileio.c 2019-04-28 19:46:17.026060122 +0200
+--- src/fileio.c 2019-04-28 20:19:41.807600177 +0200
+***************
+*** 684,698 ****
+ #endif
+ }
+
+! #if defined(HAS_SWAP_EXISTS_ACTION)
+! /* If "Quit" selected at ATTENTION dialog, don't load the file */
+ if (swap_exists_action == SEA_QUIT)
+ {
+ if (!read_buffer && !read_stdin)
+ close(fd);
+ return FAIL;
+ }
+- #endif
+
+ ++no_wait_return; /* don't wait for return yet */
+
+--- 684,696 ----
+ #endif
+ }
+
+! // If "Quit" selected at ATTENTION dialog, don't load the file
+ if (swap_exists_action == SEA_QUIT)
+ {
+ if (!read_buffer && !read_stdin)
+ close(fd);
+ return FAIL;
+ }
+
+ ++no_wait_return; /* don't wait for return yet */
+
+*** ../vim-8.1.1230/src/main.c 2019-04-28 19:46:17.030060105 +0200
+--- src/main.c 2019-04-28 20:21:01.743207196 +0200
+***************
+*** 50,58 ****
+ static void exe_commands(mparm_T *parmp);
+ static void source_startup_scripts(mparm_T *parmp);
+ static void main_start_gui(void);
+- # if defined(HAS_SWAP_EXISTS_ACTION)
+ static void check_swap_exists_action(void);
+- # endif
+ # ifdef FEAT_EVAL
+ static void set_progpath(char_u *argv0);
+ # endif
+--- 50,56 ----
+***************
+*** 784,802 ****
+ */
+ if (params.tagname != NULL)
+ {
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ swap_exists_did_quit = FALSE;
+- #endif
+
+ vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
+ do_cmdline_cmd(IObuff);
+ TIME_MSG("jumping to tag");
+
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ /* If the user doesn't want to edit the file then we quit here. */
+ if (swap_exists_did_quit)
+ getout(1);
+- #endif
+ }
+
+ /* Execute any "+", "-c" and "-S" arguments. */
+--- 782,796 ----
+***************
+*** 2625,2644 ****
+ {
+ int i;
+
+! #if defined(HAS_SWAP_EXISTS_ACTION)
+! /* When getting the ATTENTION prompt here, use a dialog */
+ swap_exists_action = SEA_DIALOG;
+! #endif
+ no_wait_return = TRUE;
+ i = msg_didany;
+ set_buflisted(TRUE);
+! (void)open_buffer(TRUE, NULL, 0); /* create memfile and read file */
+ no_wait_return = FALSE;
+ msg_didany = i;
+ TIME_MSG("reading stdin");
+! #if defined(HAS_SWAP_EXISTS_ACTION)
+ check_swap_exists_action();
+- #endif
+ #if !(defined(AMIGA) || defined(MACOS_X))
+ /*
+ * Close stdin and dup it from stderr. Required for GPM to work
+--- 2619,2636 ----
+ {
+ int i;
+
+! // When getting the ATTENTION prompt here, use a dialog
+ swap_exists_action = SEA_DIALOG;
+!
+ no_wait_return = TRUE;
+ i = msg_didany;
+ set_buflisted(TRUE);
+! (void)open_buffer(TRUE, NULL, 0); // create memfile and read file
+ no_wait_return = FALSE;
+ msg_didany = i;
+ TIME_MSG("reading stdin");
+!
+ check_swap_exists_action();
+ #if !(defined(AMIGA) || defined(MACOS_X))
+ /*
+ * Close stdin and dup it from stderr. Required for GPM to work
+***************
+*** 2741,2756 ****
+ if (p_fdls >= 0)
+ curwin->w_p_fdl = p_fdls;
+ #endif
+! #if defined(HAS_SWAP_EXISTS_ACTION)
+! /* When getting the ATTENTION prompt here, use a dialog */
+ swap_exists_action = SEA_DIALOG;
+! #endif
+ set_buflisted(TRUE);
+
+ /* create memfile, read file */
+ (void)open_buffer(FALSE, NULL, 0);
+
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ if (swap_exists_action == SEA_QUIT)
+ {
+ if (got_int || only_one_window())
+--- 2733,2746 ----
+ if (p_fdls >= 0)
+ curwin->w_p_fdl = p_fdls;
+ #endif
+! // When getting the ATTENTION prompt here, use a dialog
+ swap_exists_action = SEA_DIALOG;
+!
+ set_buflisted(TRUE);
+
+ /* create memfile, read file */
+ (void)open_buffer(FALSE, NULL, 0);
+
+ if (swap_exists_action == SEA_QUIT)
+ {
+ if (got_int || only_one_window())
+***************
+*** 2768,2774 ****
+ }
+ else
+ handle_swap_exists(NULL);
+- #endif
+ dorewind = TRUE; /* start again */
+ }
+ ui_breakcheck();
+--- 2758,2763 ----
+***************
+*** 2865,2877 ****
+ curwin->w_arg_idx = arg_idx;
+ /* Edit file from arg list, if there is one. When "Quit" selected
+ * at the ATTENTION prompt close the window. */
+- # ifdef HAS_SWAP_EXISTS_ACTION
+ swap_exists_did_quit = FALSE;
+- # endif
+ (void)do_ecmd(0, arg_idx < GARGCOUNT
+ ? alist_name(&GARGLIST[arg_idx]) : NULL,
+ NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
+- # ifdef HAS_SWAP_EXISTS_ACTION
+ if (swap_exists_did_quit)
+ {
+ /* abort or quit selected */
+--- 2854,2863 ----
+***************
+*** 2884,2890 ****
+ win_close(curwin, TRUE);
+ advance = FALSE;
+ }
+- # endif
+ if (arg_idx == GARGCOUNT - 1)
+ arg_had_last = TRUE;
+ ++arg_idx;
+--- 2870,2875 ----
+***************
+*** 3485,3491 ****
+ mch_exit(0);
+ }
+
+- #if defined(HAS_SWAP_EXISTS_ACTION)
+ /*
+ * Check the result of the ATTENTION dialog:
+ * When "Quit" selected, exit Vim.
+--- 3470,3475 ----
+***************
+*** 3498,3504 ****
+ getout(1);
+ handle_swap_exists(NULL);
+ }
+- #endif
+
+ #endif /* NO_VIM_MAIN */
+
+--- 3482,3487 ----
+*** ../vim-8.1.1230/src/testdir/test_swap.vim 2019-01-27 14:29:20.724544960 +0100
+--- src/testdir/test_swap.vim 2019-04-28 21:50:37.397318520 +0200
+***************
+*** 164,166 ****
+--- 164,222 ----
+ call delete('Xtest2')
+ call delete('Xtest3')
+ endfunc
++
++ func Test_swapfile_delete()
++ autocmd! SwapExists
++ function s:swap_exists()
++ let v:swapchoice = s:swap_choice
++ let s:swapname = v:swapname
++ let s:filename = expand('<afile>')
++ endfunc
++ augroup test_swapfile_delete
++ autocmd!
++ autocmd SwapExists * call s:swap_exists()
++ augroup END
++
++
++ " Create a valid swapfile by editing a file.
++ split XswapfileText
++ call setline(1, ['one', 'two', 'three'])
++ write " file is written, not modified
++ " read the swapfile as a Blob
++ let swapfile_name = swapname('%')
++ let swapfile_bytes = readfile(swapfile_name, 'B')
++
++ " Close the file and recreate the swap file.
++ " Now editing the file will run into the process still existing
++ quit
++ call writefile(swapfile_bytes, swapfile_name)
++ let s:swap_choice = 'e'
++ let s:swapname = ''
++ split XswapfileText
++ quit
++ call assert_equal(swapfile_name, s:swapname)
++
++ " Write the swapfile with a modified PID, now it will be automatically
++ " deleted. Process one should never be Vim.
++ let swapfile_bytes[24:27] = 0z01000000
++ call writefile(swapfile_bytes, swapfile_name)
++ let s:swapname = ''
++ split XswapfileText
++ quit
++ call assert_equal('', s:swapname)
++
++ " Now set the modified flag, the swap file will not be deleted
++ let swapfile_bytes[28 + 80 + 899] = 0x55
++ call writefile(swapfile_bytes, swapfile_name)
++ let s:swapname = ''
++ split XswapfileText
++ quit
++ call assert_equal(swapfile_name, s:swapname)
++
++ call delete('XswapfileText')
++ call delete(swapfile_name)
++ augroup test_swapfile_delete
++ autocmd!
++ augroup END
++ augroup! test_swapfile_delete
++ endfunc
+*** ../vim-8.1.1230/runtime/doc/usr_11.txt 2018-05-17 13:42:03.000000000 +0200
+--- runtime/doc/usr_11.txt 2019-04-28 21:58:09.667057415 +0200
+***************
+*** 120,126 ****
+ USING A SPECIFIC SWAP FILE
+
+ If you know which swap file needs to be used, you can recover by giving the
+! swap file name. Vim will then finds out the name of the original file from
+ the swap file.
+
+ Example: >
+--- 120,126 ----
+ USING A SPECIFIC SWAP FILE
+
+ If you know which swap file needs to be used, you can recover by giving the
+! swap file name. Vim will then find out the name of the original file from
+ the swap file.
+
+ Example: >
+***************
+*** 205,210 ****
+--- 205,217 ----
+ NEWER than swap file! ~
+
+
++ NOTE that in the following situation Vim knows the swap file is not useful and
++ will automatically delete it:
++ - The file is a valid swap file (Magic number is correct).
++ - The flag that the file was modified is not set.
++ - The process is not running.
++
++
+ UNREADABLE SWAP FILE
+
+ Sometimes the line
+***************
+*** 284,289 ****
+--- 291,297 ----
+ 'shortmess' option. But it's very unusual that you need this.
+
+ For remarks about encryption and the swap file, see |:recover-crypt|.
++ For programatic access to the swap file, see |swapinfo()|.
+
+ ==============================================================================
+ *11.4* Further reading
+*** ../vim-8.1.1230/src/os_win32.c 2019-04-28 19:46:17.034060084 +0200
+--- src/os_win32.c 2019-04-28 22:11:28.811767431 +0200
+***************
+*** 2903,2908 ****
+--- 2903,2925 ----
+ return (long)GetCurrentProcessId();
+ }
+
++ /*
++ * return TRUE if process "pid" is still running
++ */
++ int
++ mch_process_running(pid_t pid)
++ {
++ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, (DWORD)pid);
++ DWORD status = 0;
++ int ret = FALSE;
++
++ if (hProcess == NULL)
++ return FALSE; // might not have access
++ if (GetExitCodeProcess(hProcess, &status) )
++ ret = status == STILL_ACTIVE;
++ CloseHandle(hProcess);
++ return ret;
++ }
+
+ /*
+ * Get name of current directory into buffer 'buf' of length 'len' bytes.
+*** ../vim-8.1.1230/src/proto/os_win32.pro 2019-04-28 19:46:17.034060084 +0200
+--- src/proto/os_win32.pro 2019-04-28 22:14:17.599153672 +0200
+***************
+*** 19,24 ****
+--- 19,25 ----
+ int mch_get_user_name(char_u *s, int len);
+ void mch_get_host_name(char_u *s, int len);
+ long mch_get_pid(void);
++ int mch_process_running(pid_t pid);
+ int mch_dirname(char_u *buf, int len);
+ long mch_getperm(char_u *name);
+ int mch_setperm(char_u *name, long perm);
+*** ../vim-8.1.1230/src/os_unix.c 2019-04-04 20:13:06.001014760 +0200
+--- src/os_unix.c 2019-04-28 22:19:41.013860198 +0200
+***************
+*** 2393,2398 ****
+--- 2393,2408 ----
+ return (long)getpid();
+ }
+
++ /*
++ * return TRUE if process "pid" is still running
++ */
++ int
++ mch_process_running(pid_t pid)
++ {
++ // EMX kill() not working correctly, it seems
++ return kill(pid, 0) == 0;
++ }
++
+ #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
+ static char *
+ strerror(int err)
+*** ../vim-8.1.1230/src/proto/os_unix.pro 2019-01-20 15:30:36.893328693 +0100
+--- src/proto/os_unix.pro 2019-04-28 22:19:14.453970686 +0200
+***************
+*** 27,32 ****
+--- 27,33 ----
+ int mch_get_uname(uid_t uid, char_u *s, int len);
+ void mch_get_host_name(char_u *s, int len);
+ long mch_get_pid(void);
++ int mch_process_running(pid_t pid);
+ int mch_dirname(char_u *buf, int len);
+ int mch_FullName(char_u *fname, char_u *buf, int len, int force);
+ int mch_isFullName(char_u *fname);
+*** ../vim-8.1.1230/src/version.c 2019-04-28 19:46:17.034060084 +0200
+--- src/version.c 2019-04-28 22:20:54.909549767 +0200
+***************
+*** 769,770 ****
+--- 769,772 ----
+ { /* Add new patch number below this line */
++ /**/
++ 1231,
+ /**/
+
+--
+ARTHUR: What?
+BLACK KNIGHT: None shall pass.
+ARTHUR: I have no quarrel with you, good Sir knight, but I must cross
+ this bridge.
+BLACK KNIGHT: Then you shall die.
+ The Quest for the Holy Grail (Monty Python)
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
+/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
+\\\ an exciting new programming language -- http://www.Zimbu.org ///
+ \\\ help me help AIDS victims -- http://ICCF-Holland.org ///