Patch 8.2.4685
Problem: When a swap file is found for a popup there is no dialog and the
buffer is loaded anyway.
Solution: Silently load the buffer read-only. (closes #10073)
Files: runtime/doc/popup.txt, src/memline.c, src/popupwin.c, src/vim.h,
src/buffer.c, src/testdir/test_popupwin.vim
*** ../vim-8.2.4684/runtime/doc/popup.txt 2021-11-29 17:37:38.059265225 +0000
--- runtime/doc/popup.txt 2022-04-04 16:42:17.060508340 +0100
***************
*** 260,267 ****
Can also be used as a |method|: >
GetPopup()->popup_close()
popup_create({what}, {options}) *popup_create()*
! Open a popup window showing {what}, which is either:
- a buffer number
- a string
- a list of strings
--- 260,268 ----
Can also be used as a |method|: >
GetPopup()->popup_close()
+
popup_create({what}, {options}) *popup_create()*
! Open a popup window showing {what}, which is either: *E450*
- a buffer number
- a string
- a list of strings
***************
*** 270,275 ****
--- 271,281 ----
'buftype' set to "popup". That buffer will be wiped out once
the popup closes.
+ if {what} is a buffer number and loading the buffer runs into
+ an existing swap file, it is silently opened read-only, as if
+ a |SwapExists| autocommand had set |v:swapchoice| to 'o'.
+ This is because we assume the buffer is only used for viewing.
+
{options} is a dictionary with many possible entries.
See |popup_create-arguments| for details.
*** ../vim-8.2.4684/src/memline.c 2022-03-23 13:54:47.968796508 +0000
--- src/memline.c 2022-04-04 16:29:37.610753055 +0100
***************
*** 4631,4649 ****
--no_wait_return;
}
#if defined(FEAT_EVAL)
/*
* 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_T *buf, char_u *fname)
{
set_vim_var_string(VV_SWAPNAME, fname, -1);
--- 4631,4652 ----
--no_wait_return;
}
+ typedef enum {
+ SEA_CHOICE_NONE = 0,
+ SEA_CHOICE_READONLY = 1,
+ SEA_CHOICE_EDIT = 2,
+ SEA_CHOICE_RECOVER = 3,
+ SEA_CHOICE_DELETE = 4,
+ SEA_CHOICE_QUIT = 5,
+ SEA_CHOICE_ABORT = 6
+ } sea_choice_T;
+
#if defined(FEAT_EVAL)
/*
* Trigger the SwapExists autocommands.
! * Returns a value for equivalent to do_dialog().
*/
! static sea_choice_T
do_swapexists(buf_T *buf, char_u *fname)
{
set_vim_var_string(VV_SWAPNAME, fname, -1);
***************
*** 4659,4673 ****
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
--- 4662,4676 ----
switch (*get_vim_var_str(VV_SWAPCHOICE))
{
! case 'o': return SEA_CHOICE_READONLY;
! case 'e': return SEA_CHOICE_EDIT;
! case 'r': return SEA_CHOICE_RECOVER;
! case 'd': return SEA_CHOICE_DELETE;
! case 'q': return SEA_CHOICE_QUIT;
! case 'a': return SEA_CHOICE_ABORT;
}
! return SEA_CHOICE_NONE;
}
#endif
***************
*** 4986,4995 ****
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;
// Avoid getting a warning for the file being created
// outside of Vim, it was created at the start of this
--- 4989,4998 ----
if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
{
! sea_choice_T choice = SEA_CHOICE_NONE;
! stat_T st;
#ifdef CREATE_DUMMY_FILE
! int did_use_dummy = FALSE;
// Avoid getting a warning for the file being created
// outside of Vim, it was created at the start of this
***************
*** 5013,5019 ****
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"));
}
--- 5016,5022 ----
if (mch_stat((char *)buf->b_fname, &st) == 0
&& swapfile_unchanged(fname))
{
! choice = SEA_CHOICE_DELETE;
if (p_verbose > 0)
verb_msg(_("Found a swap file that is not useful, deleting it"));
}
***************
*** 5024,5036 ****
* 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);
-
- if (choice == 0)
#endif
{
#ifdef FEAT_GUI
// If we are supposed to start the GUI but it wasn't
--- 5027,5046 ----
* the response, trigger it. It may return 0 to ask the
* user anyway.
*/
! if (choice == SEA_CHOICE_NONE
&& swap_exists_action != SEA_NONE
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
choice = do_swapexists(buf, fname);
#endif
+
+ if (choice == SEA_CHOICE_NONE
+ && swap_exists_action == SEA_READONLY)
+ {
+ // always open readonly.
+ choice = SEA_CHOICE_READONLY;
+ }
+
+ if (choice == SEA_CHOICE_NONE)
{
#ifdef FEAT_GUI
// If we are supposed to start the GUI but it wasn't
***************
*** 5053,5061 ****
}
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
! if (swap_exists_action != SEA_NONE && choice == 0)
{
char_u *name;
name = alloc(STRLEN(fname)
+ STRLEN(_("Swap file \""))
--- 5063,5073 ----
}
#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
! if (swap_exists_action != SEA_NONE
! && choice == SEA_CHOICE_NONE)
{
char_u *name;
+ int dialog_result;
name = alloc(STRLEN(fname)
+ STRLEN(_("Swap file \""))
***************
*** 5067,5073 ****
1000, TRUE);
STRCAT(name, _("\" already exists!"));
}
! choice = do_dialog(VIM_WARNING,
(char_u *)_("VIM - ATTENTION"),
name == NULL
? (char_u *)_("Swap file already exists!")
--- 5079,5085 ----
1000, TRUE);
STRCAT(name, _("\" already exists!"));
}
! dialog_result = do_dialog(VIM_WARNING,
(char_u *)_("VIM - ATTENTION"),
name == NULL
? (char_u *)_("Swap file already exists!")
***************
*** 5079,5087 ****
(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL, FALSE);
# ifdef HAVE_PROCESS_STILL_RUNNING
! if (process_still_running && choice >= 4)
! choice++; // Skip missing "Delete it" button
# endif
vim_free(name);
// pretend screen didn't scroll, need redraw anyway
--- 5091,5101 ----
(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL, FALSE);
# ifdef HAVE_PROCESS_STILL_RUNNING
! if (process_still_running && dialog_result >= 4)
! // compensate for missing "Delete it" button
! dialog_result++;
# endif
+ choice = dialog_result;
vim_free(name);
// pretend screen didn't scroll, need redraw anyway
***************
*** 5090,5130 ****
}
#endif
! if (choice > 0)
{
! switch (choice)
! {
! case 1:
! buf->b_p_ro = TRUE;
! break;
! case 2:
! break;
! case 3:
! swap_exists_action = SEA_RECOVER;
! break;
! case 4:
! mch_remove(fname);
! break;
! case 5:
! swap_exists_action = SEA_QUIT;
! break;
! case 6:
! swap_exists_action = SEA_QUIT;
! got_int = TRUE;
! break;
! }
!
! // If the file was deleted this fname can be used.
! if (mch_getperm(fname) < 0)
break;
}
! else
! {
! msg_puts("\n");
! if (msg_silent == 0)
! // call wait_return() later
! need_wait_return = TRUE;
! }
#ifdef CREATE_DUMMY_FILE
// Going to try another name, need the dummy file again.
--- 5104,5140 ----
}
#endif
! switch (choice)
{
! case SEA_CHOICE_READONLY:
! buf->b_p_ro = TRUE;
! break;
! case SEA_CHOICE_EDIT:
! break;
! case SEA_CHOICE_RECOVER:
! swap_exists_action = SEA_RECOVER;
! break;
! case SEA_CHOICE_DELETE:
! mch_remove(fname);
! break;
! case SEA_CHOICE_QUIT:
! swap_exists_action = SEA_QUIT;
! break;
! case SEA_CHOICE_ABORT:
! swap_exists_action = SEA_QUIT;
! got_int = TRUE;
! break;
! case SEA_CHOICE_NONE:
! msg_puts("\n");
! if (msg_silent == 0)
! // call wait_return() later
! need_wait_return = TRUE;
break;
}
!
! // If the file was deleted this fname can be used.
! if (choice != SEA_CHOICE_NONE && mch_getperm(fname) < 0)
! break;
#ifdef CREATE_DUMMY_FILE
// Going to try another name, need the dummy file again.
*** ../vim-8.2.4684/src/popupwin.c 2022-04-04 15:16:50.738014123 +0100
--- src/popupwin.c 2022-04-04 16:22:28.453341176 +0100
***************
*** 1989,1995 ****
--- 1989,1997 ----
new_buffer = FALSE;
win_init_popup_win(wp, buf);
set_local_options_default(wp, FALSE);
+ swap_exists_action = SEA_READONLY;
buffer_ensure_loaded(buf);
+ swap_exists_action = SEA_NONE;
}
else
{
*** ../vim-8.2.4684/src/vim.h 2022-04-03 18:01:39.659574455 +0100
--- src/vim.h 2022-04-04 16:23:03.313062173 +0100
***************
*** 1250,1255 ****
--- 1250,1256 ----
#define SEA_DIALOG 1 // use dialog when possible
#define SEA_QUIT 2 // quit editing the file
#define SEA_RECOVER 3 // recover the file
+ #define SEA_READONLY 4 // no dialog, mark buffer as read-only
/*
* Minimal size for block 0 of a swap file.
*** ../vim-8.2.4684/src/buffer.c 2022-04-03 11:22:33.524172298 +0100
--- src/buffer.c 2022-04-04 16:37:25.485185250 +0100
***************
*** 150,156 ****
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
! swap_exists_action = SEA_NONE;
open_buffer(FALSE, NULL, 0);
aucmd_restbuf(&aco);
}
--- 150,157 ----
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
! if (swap_exists_action != SEA_READONLY)
! swap_exists_action = SEA_NONE;
open_buffer(FALSE, NULL, 0);
aucmd_restbuf(&aco);
}
***************
*** 1053,1062 ****
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')
--- 1054,1065 ----
int count)
{
bufref_T old_curbuf;
+ int save_sea = swap_exists_action;
set_bufref(&old_curbuf, curbuf);
! if (swap_exists_action == SEA_NONE)
! 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')
***************
*** 1071,1077 ****
// 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)
--- 1074,1080 ----
// Quitting means closing the split window, nothing else.
win_close(curwin, TRUE);
! swap_exists_action = save_sea;
swap_exists_did_quit = TRUE;
#if defined(FEAT_EVAL)
*** ../vim-8.2.4684/src/testdir/test_popupwin.vim 2022-04-02 15:31:48.301003446 +0100
--- src/testdir/test_popupwin.vim 2022-04-04 16:48:55.207757192 +0100
***************
*** 2775,2780 ****
--- 2775,2800 ----
call delete('XsomeFile')
endfunc
+ func Test_popupwin_buffer_with_swapfile()
+ call writefile(['some text', 'in a buffer'], 'XopenFile')
+ call writefile([''], '.XopenFile.swp')
+ let g:ignoreSwapExists = 1
+
+ let bufnr = bufadd('XopenFile')
+ call assert_equal(0, bufloaded(bufnr))
+ let winid = popup_create(bufnr, {'hidden': 1})
+ call assert_equal(1, bufloaded(bufnr))
+ call popup_close(winid)
+
+ exe 'buffer ' .. bufnr
+ call assert_equal(1, &readonly)
+ bwipe!
+
+ call delete('XopenFile')
+ call delete('.XopenFile.swp')
+ unlet g:ignoreSwapExists
+ endfunc
+
func Test_popupwin_terminal_buffer()
CheckFeature terminal
CheckUnix
*** ../vim-8.2.4684/src/version.c 2022-04-04 15:46:37.606126838 +0100
--- src/version.c 2022-04-04 16:41:56.460551672 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 4685,
/**/
--
If an elephant is left tied to a parking meter, the parking fee has to be paid
just as it would for a vehicle.
[real standing law in Florida, United States of America]
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///