updated for version 7.0164
diff --git a/src/eval.c b/src/eval.c
index d127198..0477222 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -338,6 +338,8 @@
     {VV_NAME("beval_col",	 VAR_NUMBER), VV_RO},
     {VV_NAME("beval_text",	 VAR_STRING), VV_RO},
     {VV_NAME("scrollstart",	 VAR_STRING), 0},
+    {VV_NAME("swapname",	 VAR_STRING), VV_RO},
+    {VV_NAME("swapchoice",	 VAR_STRING), 0},
 };
 
 /* shorthand */
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index b6fab2c..d1d3ae1 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -3420,7 +3420,7 @@
 	topline = curwin->w_topline;
 	if (!oldbuf)			    /* need to read the file */
 	{
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
 	    swap_exists_action = SEA_DIALOG;
 #endif
 	    curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
@@ -3435,7 +3435,7 @@
 	    (void)open_buffer(FALSE, eap);
 #endif
 
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
 	    if (swap_exists_action == SEA_QUIT)
 		retval = FAIL;
 	    handle_swap_exists(old_curbuf);
diff --git a/src/main.c b/src/main.c
index 658f4e1..fd4f4e4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -116,7 +116,7 @@
 static void exe_commands __ARGS((mparm_T *parmp));
 static void source_startup_scripts __ARGS((mparm_T *parmp));
 static void main_start_gui __ARGS((void));
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
 static void check_swap_exists_action __ARGS((void));
 #endif
 #ifdef FEAT_CLIENTSERVER
@@ -2150,7 +2150,7 @@
 {
     int	    i;
 
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
     /* When getting the ATTENTION prompt here, use a dialog */
     swap_exists_action = SEA_DIALOG;
 #endif
@@ -2161,7 +2161,7 @@
     no_wait_return = FALSE;
     msg_didany = i;
     TIME_MSG("reading stdin");
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
     check_swap_exists_action();
 #endif
 #if !(defined(AMIGA) || defined(MACOS))
@@ -2245,14 +2245,14 @@
 		if (p_fdls >= 0)
 		    curwin->w_p_fdl = p_fdls;
 #endif
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
 		/* When getting the ATTENTION prompt here, use a dialog */
 		swap_exists_action = SEA_DIALOG;
 #endif
 		set_buflisted(TRUE);
 		(void)open_buffer(FALSE, NULL); /* create memfile, read file */
 
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
 		check_swap_exists_action();
 #endif
 #ifdef FEAT_AUTOCMD
@@ -2872,7 +2872,7 @@
 	mch_exit(0);
 }
 
-#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
+#if defined(HAS_SWAP_EXISTS_ACTION)
 /*
  * Check the result of the ATTENTION dialog:
  * When "Quit" selected, exit Vim.
diff --git a/src/memline.c b/src/memline.c
index a2ec5b2..a6ab42c 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -1595,7 +1595,7 @@
 #endif
 
 /*
- * Give information about an existing swap file
+ * Give information about an existing swap file.
  * Returns timestamp (0 when unknown).
  */
     static time_t
@@ -3494,6 +3494,93 @@
     return retval;
 }
 
+static void attention_message __ARGS((buf_T *buf, char_u *fname));
+
+/*
+ * Print the ATTENTION message: info about an existing swap file.
+ */
+    static void
+attention_message(buf, fname)
+    buf_T   *buf;	/* buffer being edited */
+    char_u  *fname;	/* swap file name */
+{
+    struct stat st;
+    time_t	x, sx;
+
+    ++no_wait_return;
+    (void)EMSG(_("E325: ATTENTION"));
+    MSG_PUTS(_("\nFound a swap file by the name \""));
+    msg_home_replace(fname);
+    MSG_PUTS("\"\n");
+    sx = swapfile_info(fname);
+    MSG_PUTS(_("While opening file \""));
+    msg_outtrans(buf->b_fname);
+    MSG_PUTS("\"\n");
+    if (mch_stat((char *)buf->b_fname, &st) != -1)
+    {
+	MSG_PUTS(_("             dated: "));
+	x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
+	MSG_PUTS(ctime(&x));
+	if (sx != 0 && x > sx)
+	    MSG_PUTS(_("      NEWER than swap file!\n"));
+    }
+    /* Some of these messages are long to allow translation to
+     * other languages. */
+    MSG_PUTS(_("\n(1) Another program may be editing the same file.\n    If this is the case, be careful not to end up with two\n    different instances of the same file when making changes.\n"));
+    MSG_PUTS(_("    Quit, or continue with caution.\n"));
+    MSG_PUTS(_("\n(2) An edit session for this file crashed.\n"));
+    MSG_PUTS(_("    If this is the case, use \":recover\" or \"vim -r "));
+    msg_outtrans(buf->b_fname);
+    MSG_PUTS(_("\"\n    to recover the changes (see \":help recovery\").\n"));
+    MSG_PUTS(_("    If you did this already, delete the swap file \""));
+    msg_outtrans(fname);
+    MSG_PUTS(_("\"\n    to avoid this message.\n"));
+    cmdline_row = msg_row;
+    --no_wait_return;
+}
+
+#ifdef FEAT_AUTOCMD
+static int do_swapexists __ARGS((buf_T *buf, char_u *fname));
+
+/*
+ * Trigger the SwapExists autocommands.
+ * Returns a value for equivalent to do_dialog() (see below):
+ * 0: still need to ask for a choice
+ * 1: open read-only
+ * 2: edit anyway
+ * 3: recover
+ * 4: delete it
+ * 5: quit
+ * 6: abort
+ */
+    static int
+do_swapexists(buf, fname)
+    buf_T	*buf;
+    char_u	*fname;
+{
+    set_vim_var_string(VV_SWAPNAME, fname, -1);
+    set_vim_var_string(VV_SWAPCHOICE, NULL, -1);
+
+    /* Trigger SwapExists autocommands with <afile> set to the file being
+     * edited. */
+    apply_autocmds(EVENT_SWAPEXISTS, buf->b_fname, NULL, FALSE, NULL);
+
+    set_vim_var_string(VV_SWAPNAME, NULL, -1);
+
+    switch (*get_vim_var_str(VV_SWAPCHOICE))
+    {
+	case 'o': return 1;
+	case 'e': return 2;
+	case 'r': return 3;
+	case 'd': return 4;
+	case 'q': return 5;
+	case 'a': return 6;
+    }
+
+    return 0;
+}
+#endif
+
 /*
  * Find out what name to use for the swap file for buffer 'buf'.
  *
@@ -3511,7 +3598,6 @@
 {
     char_u	*fname;
     int		n;
-    time_t	x, sx;
     char_u	*dir_name;
 #ifdef AMIGA
     BPTR	fh;
@@ -3797,7 +3883,9 @@
 		if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
 			&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
 		{
-		    struct stat st;
+#if defined(HAS_SWAP_EXISTS_ACTION)
+		    int		choice = 0;
+#endif
 #ifdef CREATE_DUMMY_FILE
 		    int		did_use_dummy = FALSE;
 
@@ -3813,55 +3901,41 @@
 			did_use_dummy = TRUE;
 		    }
 #endif
-#ifdef FEAT_GUI
-		    /* If we are supposed to start the GUI but it wasn't
-		     * completely started yet, start it now.  This makes the
-		     * messages displayed in the Vim window when loading a
-		     * session from the .gvimrc file. */
-		    if (gui.starting && !gui.in_use)
-			gui_start();
-#endif
 
 #if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
 		    process_still_running = FALSE;
 #endif
-		    ++no_wait_return;
-		    (void)EMSG(_("E325: ATTENTION"));
-		    MSG_PUTS(_("\nFound a swap file by the name \""));
-		    msg_home_replace(fname);
-		    MSG_PUTS("\"\n");
-		    sx = swapfile_info(fname);
-		    MSG_PUTS(_("While opening file \""));
-		    msg_outtrans(buf->b_fname);
-		    MSG_PUTS("\"\n");
-		    if (mch_stat((char *)buf->b_fname, &st) != -1)
-		    {
-			MSG_PUTS(_("             dated: "));
-			x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
-			MSG_PUTS(ctime(&x));
-			if (sx != 0 && x > sx)
-			    MSG_PUTS(_("      NEWER than swap file!\n"));
-		    }
-		    /* Some of these messages are long to allow translation to
-		     * other languages. */
-		    MSG_PUTS(_("\n(1) Another program may be editing the same file.\n    If this is the case, be careful not to end up with two\n    different instances of the same file when making changes.\n"));
-		    MSG_PUTS(_("    Quit, or continue with caution.\n"));
-		    MSG_PUTS(_("\n(2) An edit session for this file crashed.\n"));
-		    MSG_PUTS(_("    If this is the case, use \":recover\" or \"vim -r "));
-		    msg_outtrans(buf->b_fname);
-		    MSG_PUTS(_("\"\n    to recover the changes (see \":help recovery\").\n"));
-		    MSG_PUTS(_("    If you did this already, delete the swap file \""));
-		    msg_outtrans(fname);
-		    MSG_PUTS(_("\"\n    to avoid this message.\n"));
-		    cmdline_row = msg_row;
-		    --no_wait_return;
+#ifdef FEAT_AUTOCMD
+		    /*
+		     * 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->b_fname, buf))
+			choice = do_swapexists(buf, fname);
 
-		    /* We don't want a 'q' typed at the more-prompt interrupt
-		     * loading a file. */
-		    got_int = FALSE;
+		    if (choice == 0)
+#endif
+		    {
+#ifdef FEAT_GUI
+			/* If we are supposed to start the GUI but it wasn't
+			 * completely started yet, start it now.  This makes
+			 * the messages displayed in the Vim window when
+			 * loading a session from the .gvimrc file. */
+			if (gui.starting && !gui.in_use)
+			    gui_start();
+#endif
+			/* Show info about the existing swap file. */
+			attention_message(buf, fname);
+
+			/* We don't want a 'q' typed at the more-prompt
+			 * interrupt loading a file. */
+			got_int = FALSE;
+		    }
 
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
-		    if (swap_exists_action)
+		    if (swap_exists_action != SEA_NONE && choice == 0)
 		    {
 			char_u	*name;
 
@@ -3875,7 +3949,7 @@
 								  1000, TRUE);
 			    STRCAT(name, _("\" already exists!"));
 			}
-			switch (do_dialog(VIM_WARNING,
+			choice = do_dialog(VIM_WARNING,
 				    (char_u *)_("VIM - ATTENTION"),
 				    name == NULL
 					?  (char_u *)_("Swap file already exists!")
@@ -3884,7 +3958,24 @@
 				    process_still_running
 					? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") :
 # endif
-					(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort\n&Delete it"), 1, NULL))
+					(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL);
+
+# if defined(UNIX) || defined(__EMX__) || defined(VMS)
+			if (process_still_running && choice >= 4)
+			    choice++;	/* Skip missing "Delete it" button */
+# endif
+			vim_free(name);
+
+			/* pretend screen didn't scroll, need redraw anyway */
+			msg_scrolled = 0;
+			redraw_all_later(NOT_VALID);
+		    }
+#endif
+
+#if defined(HAS_SWAP_EXISTS_ACTION)
+		    if (choice > 0)
+		    {
+			switch (choice)
 			{
 			    case 1:
 				buf->b_p_ro = TRUE;
@@ -3895,21 +3986,16 @@
 				swap_exists_action = SEA_RECOVER;
 				break;
 			    case 4:
-				swap_exists_action = SEA_QUIT;
+				mch_remove(fname);
 				break;
 			    case 5:
 				swap_exists_action = SEA_QUIT;
-				got_int = TRUE;
 				break;
 			    case 6:
-				mch_remove(fname);
+				swap_exists_action = SEA_QUIT;
+				got_int = TRUE;
 				break;
 			}
-			vim_free(name);
-
-			/* pretend screen didn't scroll, need redraw anyway */
-			msg_scrolled = 0;
-			redraw_all_later(NOT_VALID);
 
 			/* If the file was deleted this fname can be used. */
 			if (mch_getperm(fname) < 0)