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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220404160009.E23171C0561%40moolenaar.net.

Raspunde prin e-mail lui