]> granicus.if.org Git - vim/commitdiff
patch 8.1.1612: cannot show an existing buffer in a popup window v8.1.1612
authorBram Moolenaar <Bram@vim.org>
Sun, 30 Jun 2019 20:16:10 +0000 (22:16 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 30 Jun 2019 20:16:10 +0000 (22:16 +0200)
Problem:    Cannot show an existing buffer in a popup window.
Solution:   Support buffer number argument in popup_create().

12 files changed:
runtime/doc/popup.txt
src/buffer.c
src/evalfunc.c
src/normal.c
src/popupwin.c
src/proto/buffer.pro
src/screen.c
src/testdir/test_popupwin.vim
src/ui.c
src/version.c
src/vim.h
src/window.c

index 99af0a52eb707db77e1f8c1df774030db013f5cd..cfa84d7fe7724307348cbcb2807dd536227ecd55 100644 (file)
@@ -98,9 +98,6 @@ or by clicking anywhere inside the popup.  This must be enabled with the
 
 
 TODO:
-- Currently 'buftype' is set to "popup", but all the specifics are on the
-  window.  Can we use a "normal" buffer and put the type on the window? (#4595)
-  What if it's modified and the window closes?
 - Add test for when popup with mask is off the left and off the right of the
   screen.
 - check padding/border when popup is off the left and right of the screen.
@@ -164,10 +161,10 @@ Other:
 
 [functions help to be moved to eval.txt later]
 
-popup_atcursor({text}, {options})                       *popup_atcursor()*
-               Show the {text} above the cursor, and close it when the cursor
+popup_atcursor({what}, {options})                       *popup_atcursor()*
+               Show the {what} above the cursor, and close it when the cursor
                moves.  This works like: >
-                       call popup_create({text}, {
+                       call popup_create({what}, {
                                \ 'pos': 'botleft',
                                \ 'line': 'cursor-1',
                                \ 'col': 'cursor',
@@ -191,11 +188,15 @@ popup_close({id} [, {result}])                            *popup_close()*
                Otherwise zero is passed to the callback.
 
 
-popup_create({text}, {options})                                *popup_create()*
-               Open a popup window showing {text}, which is either:
+popup_create({what}, {options})                                *popup_create()*
+               Open a popup window showing {what}, which is either:
+               - a buffer number
                - a string
                - a list of strings
                - a list of text lines with text properties
+               When {what} is not a buffer number, a buffer is created with
+               'buftype' set to "popup".  That buffer will be wiped out once
+               the popup closes.
 
                {options} is a dictionary with many possible entries.
                See |popup_create-usage| for details.
@@ -209,9 +210,9 @@ popup_create({text}, {options})                             *popup_create()*
 <              In case of failure zero is returned.
 
 
-popup_dialog({text}, {options})                                *popup_dialog()*
+popup_dialog({what}, {options})                                *popup_dialog()*
                Just like |popup_create()| but with these default options: >
-                       call popup_create({text}, {
+                       call popup_create({what}, {
                                \ 'pos': 'center',
                                \ 'zindex': 200,
                                \ 'drag': 1,
@@ -312,12 +313,12 @@ popup_hide({id})                                          *popup_hide()*
                exists but is not a popup window an error is given. *E993*
 
 
-popup_menu({text}, {options})                           *popup_menu()*
-               Show the {text} near the cursor, handle selecting one of the
+popup_menu({what}, {options})                           *popup_menu()*
+               Show the {what} near the cursor, handle selecting one of the
                items with cursorkeys, and close it an item is selected with
-               Space or Enter. {text} should have multiple lines to make this
+               Space or Enter. {what} should have multiple lines to make this
                useful.  This works like: >
-                       call popup_create({text}, {
+                       call popup_create({what}, {
                                \ 'pos': 'center',
                                \ 'zindex': 200,
                                \ 'drag': 1,
@@ -349,10 +350,10 @@ popup_move({id}, {options})                                       *popup_move()*
                For other options see |popup_setoptions()|.
 
 
-popup_notification({text}, {options})                   *popup_notification()*
-               Show the {text} for 3 seconds at the top of the Vim window.
+popup_notification({what}, {options})                   *popup_notification()*
+               Show the {what} for 3 seconds at the top of the Vim window.
                This works like: >
-                       call popup_create({text}, {
+                       call popup_create({what}, {
                                \ 'line': 1,
                                \ 'col': 10,
                                \ 'minwidth': 20,
@@ -410,7 +411,8 @@ popup_setoptions({id}, {options})                   *popup_setoptions()*
 
 popup_settext({id}, {text})                            *popup_settext()*
                Set the text of the buffer in poup win {id}. {text} is the
-               same as supplied to |popup_create()|.
+               same as supplied to |popup_create()|, except that a buffer
+               number is not allowed.
                Does not change the window size or position, other than caused
                by the different text.
 
@@ -450,7 +452,8 @@ POPUP_CREATE() ARGUMENTS                            *popup_create-usage*
 
 The first argument of |popup_create()| (and the second argument to
 |popup_settext()|) specifies the text to be displayed, and optionally text
-properties.  It is in one of three forms:
+properties.  It is in one of four forms:
+- a buffer number
 - a string
 - a list of strings
 - a list of dictionaries, where each dictionary has these entries:
index ee68bc955a76aed812cd9dba90dbd3ac185c7004..74e0ea6d01f43ccc84c76b515d8fceb5b59d42e6 100644 (file)
@@ -121,6 +121,23 @@ read_buffer(
     return retval;
 }
 
+/*
+ * Ensure buffer "buf" is loaded.  Does not trigger the swap-exists action.
+ */
+    void
+buffer_ensure_loaded(buf_T *buf)
+{
+    if (buf->b_ml.ml_mfp == NULL)
+    {
+       aco_save_T      aco;
+
+       aucmd_prepbuf(&aco, buf);
+       swap_exists_action = SEA_NONE;
+       open_buffer(FALSE, NULL, 0);
+       aucmd_restbuf(&aco);
+    }
+}
+
 /*
  * Open current buffer, that is: open the memfile and read the file into
  * memory.
index 01afa3d4aa3029a9086082211f58b2d387ecfcbb..f87fd1f99a079aa03436967ec3b06341b95ca0ac 100644 (file)
@@ -1963,15 +1963,8 @@ f_bufload(typval_T *argvars, typval_T *rettv UNUSED)
 {
     buf_T      *buf = get_buf_arg(&argvars[0]);
 
-    if (buf != NULL && buf->b_ml.ml_mfp == NULL)
-    {
-       aco_save_T      aco;
-
-       aucmd_prepbuf(&aco, buf);
-       swap_exists_action = SEA_NONE;
-       open_buffer(FALSE, NULL, 0);
-       aucmd_restbuf(&aco);
-    }
+    if (buf != NULL)
+       buffer_ensure_loaded(buf);
 }
 
 /*
@@ -4905,7 +4898,7 @@ f_getchar(typval_T *argvars, typval_T *rettv)
                    return;
                (void)mouse_comp_pos(win, &row, &col, &lnum);
 # ifdef FEAT_TEXT_PROP
-               if (bt_popup(win->w_buffer))
+               if (WIN_IS_POPUP(win))
                    winnr = 0;
                else
 # endif
index 2015fd8dc9b22fbe8ff29613a08f811fad20a0c5..5c9f929d55a9a2229c5cdee3a5adb8799611288c 100644 (file)
@@ -4525,7 +4525,7 @@ nv_mousescroll(cmdarg_T *cap)
        if (wp == NULL)
            return;
 #ifdef FEAT_TEXT_PROP
-       if (bt_popup(wp->w_buffer) && !wp->w_has_scrollbar)
+       if (WIN_IS_POPUP(wp) && !wp->w_has_scrollbar)
            return;
 #endif
        curwin = wp;
@@ -4560,7 +4560,7 @@ nv_mousescroll(cmdarg_T *cap)
            nv_scroll_line(cap);
        }
 #ifdef FEAT_TEXT_PROP
-       if (bt_popup(curwin->w_buffer))
+       if (WIN_IS_POPUP(curwin))
            popup_set_firstline(curwin);
 #endif
     }
index a10d4e0a2f61611d981a316ffb6726a4ebb50871..3af35b6f05597630f07d15ceb1c62e25827a2eee 100644 (file)
@@ -997,14 +997,26 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
     win_T      *wp;
     tabpage_T  *tp = NULL;
     int                tabnr;
-    buf_T      *buf;
+    int                new_buffer;
+    buf_T      *buf = NULL;
     dict_T     *d;
     int                nr;
     int                i;
 
     // Check arguments look OK.
-    if (!(argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL)
-       && !(argvars[0].v_type == VAR_LIST && argvars[0].vval.v_list != NULL))
+    if (argvars[0].v_type == VAR_NUMBER)
+    {
+       buf = buflist_findnr( argvars[0].vval.v_number);
+       if (buf == NULL)
+       {
+           semsg(_(e_nobufnr), argvars[0].vval.v_number);
+           return NULL;
+       }
+    }
+    else if (!(argvars[0].v_type == VAR_STRING
+                   && argvars[0].vval.v_string != NULL)
+               && !(argvars[0].v_type == VAR_LIST
+                   && argvars[0].vval.v_list != NULL))
     {
        emsg(_(e_listreq));
        return NULL;
@@ -1038,27 +1050,42 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
        return NULL;
     rettv->vval.v_number = wp->w_id;
     wp->w_popup_pos = POPPOS_TOPLEFT;
+    wp->w_popup_flags = POPF_IS_POPUP;
 
-    buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_LISTED|BLN_DUMMY);
-    if (buf == NULL)
-       return NULL;
-    ml_open(buf);
+    if (buf != NULL)
+    {
+       // use existing buffer
+       new_buffer = FALSE;
+       wp->w_buffer = buf;
+       ++buf->b_nwindows;
+       buffer_ensure_loaded(buf);
+    }
+    else
+    {
+       // create a new buffer associated with the popup
+       new_buffer = TRUE;
+       buf = buflist_new(NULL, NULL, (linenr_T)0,
+                                                BLN_NEW|BLN_LISTED|BLN_DUMMY);
+       if (buf == NULL)
+           return NULL;
+       ml_open(buf);
 
-    win_init_popup_win(wp, buf);
+       win_init_popup_win(wp, buf);
 
-    set_local_options_default(wp);
-    set_string_option_direct_in_buf(buf, (char_u *)"buftype", -1,
+       set_local_options_default(wp);
+       set_string_option_direct_in_buf(buf, (char_u *)"buftype", -1,
                                     (char_u *)"popup", OPT_FREE|OPT_LOCAL, 0);
-    set_string_option_direct_in_buf(buf, (char_u *)"bufhidden", -1,
-                                    (char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
-    buf->b_p_ul = -1;      // no undo
-    buf->b_p_swf = FALSE;   // no swap file
-    buf->b_p_bl = FALSE;    // unlisted buffer
-    buf->b_locked = TRUE;
-    wp->w_p_wrap = TRUE;  // 'wrap' is default on
+       set_string_option_direct_in_buf(buf, (char_u *)"bufhidden", -1,
+                                     (char_u *)"hide", OPT_FREE|OPT_LOCAL, 0);
+       buf->b_p_ul = -1;       // no undo
+       buf->b_p_swf = FALSE;   // no swap file
+       buf->b_p_bl = FALSE;    // unlisted buffer
+       buf->b_locked = TRUE;
+       wp->w_p_wrap = TRUE;    // 'wrap' is default on
 
-    // Avoid that 'buftype' is reset when this buffer is entered.
-    buf->b_p_initialized = TRUE;
+       // Avoid that 'buftype' is reset when this buffer is entered.
+       buf->b_p_initialized = TRUE;
+    }
 
     if (tp != NULL)
     {
@@ -1088,7 +1115,8 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
        }
     }
 
-    popup_set_buffer_text(buf, argvars[0]);
+    if (new_buffer)
+       popup_set_buffer_text(buf, argvars[0]);
 
     if (type == TYPE_ATCURSOR)
     {
@@ -1456,7 +1484,7 @@ find_popup_win(int id)
 {
     win_T *wp = win_id2wp(id);
 
-    if (wp != NULL && !bt_popup(wp->w_buffer))
+    if (wp != NULL && !WIN_IS_POPUP(wp))
     {
        semsg(_("E993: window %d is not a popup window"), id);
        return NULL;
@@ -1524,8 +1552,13 @@ f_popup_settext(typval_T *argvars, typval_T *rettv UNUSED)
 
     if (wp != NULL)
     {
-       popup_set_buffer_text(wp->w_buffer, argvars[1]);
-       popup_adjust_position(wp);
+       if (argvars[1].v_type != VAR_STRING && argvars[1].v_type != VAR_LIST)
+           semsg(_(e_invarg2), tv_get_string(&argvars[1]));
+       else
+       {
+           popup_set_buffer_text(wp->w_buffer, argvars[1]);
+           popup_adjust_position(wp);
+       }
     }
 }
 
@@ -1880,7 +1913,7 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv)
     int
 error_if_popup_window()
 {
-    if (bt_popup(curwin->w_buffer))
+    if (WIN_IS_POPUP(curwin))
     {
        emsg(_("E994: Not allowed in a popup window"));
        return TRUE;
index 45fcf2b56ede609b144c86dd0d53f6be1ba4bc4d..010be9c4d749a51a594fbd2e4a3c4195482c954e 100644 (file)
@@ -1,4 +1,5 @@
 /* buffer.c */
+void buffer_ensure_loaded(buf_T *buf);
 int open_buffer(int read_stdin, exarg_T *eap, int flags);
 void set_bufref(bufref_T *bufref, buf_T *buf);
 int bufref_valid(bufref_T *bufref);
index 4c3ded2ca3a4a2303c68911f87340f63fc645f4a..75413451f56dc1a822eb64d6e6b760bdc13c7065 100644 (file)
@@ -1005,7 +1005,7 @@ get_wcr_attr(win_T *wp)
     if (*wp->w_p_wcr != NUL)
        wcr_attr = syn_name2attr(wp->w_p_wcr);
 #ifdef FEAT_TEXT_PROP
-    if (bt_popup(wp->w_buffer) && wcr_attr == 0)
+    if (WIN_IS_POPUP(wp) && wcr_attr == 0)
        wcr_attr = HL_ATTR(HLF_PNI);
 #endif
     return wcr_attr;
@@ -1555,11 +1555,7 @@ win_update(win_T *wp)
        if (mid_start == 0)
        {
            mid_end = wp->w_height;
-           if (ONE_WINDOW
-#ifdef FEAT_TEXT_PROP
-                   && !bt_popup(wp->w_buffer)
-#endif
-                   )
+           if (ONE_WINDOW && !WIN_IS_POPUP(wp))
            {
                /* Clear the screen when it was not done by win_del_lines() or
                 * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE
@@ -2085,9 +2081,7 @@ win_update(win_T *wp)
                    && wp->w_lines[idx].wl_lnum == lnum
                    && lnum > wp->w_topline
                    && !(dy_flags & (DY_LASTLINE | DY_TRUNCATE))
-#ifdef FEAT_TEXT_PROP
-                   && !bt_popup(wp->w_buffer)
-#endif
+                   && !WIN_IS_POPUP(wp)
                    && srow + wp->w_lines[idx].wl_size > wp->w_height
 #ifdef FEAT_DIFF
                    && diff_check_fill(wp, lnum) == 0
@@ -2244,7 +2238,7 @@ win_update(win_T *wp)
        }
 #endif
 #ifdef FEAT_TEXT_PROP
-       else if (bt_popup(wp->w_buffer))
+       else if (WIN_IS_POPUP(wp))
        {
            // popup line that doesn't fit is left as-is
            wp->w_botline = lnum;
@@ -2310,11 +2304,8 @@ win_update(win_T *wp)
 
        // Make sure the rest of the screen is blank
        // put '~'s on rows that aren't part of the file.
-       win_draw_end(wp,
-#ifdef FEAT_TEXT_PROP
-               bt_popup(wp->w_buffer) ? ' ' :
-#endif
-                                 '~', ' ', FALSE, row, wp->w_height, HLF_EOB);
+       win_draw_end(wp, WIN_IS_POPUP(wp) ? ' ' : '~',
+                                      ' ', FALSE, row, wp->w_height, HLF_EOB);
     }
 
 #ifdef SYN_TIME_LIMIT
@@ -3673,7 +3664,7 @@ win_line(
        area_highlighting = TRUE;
     }
 #ifdef FEAT_TEXT_PROP
-    if (bt_popup(wp->w_buffer))
+    if (WIN_IS_POPUP(wp))
        screen_line_flags |= SLF_POPUP;
 #endif
 
index a3e6acc5c3a2fec01da676bb108566414af21891..32ce96be1120d5a70efbb99593c21e345748091c 100644 (file)
@@ -559,7 +559,7 @@ func Test_popup_valid_arguments()
 endfunc
 
 func Test_popup_invalid_arguments()
-  call assert_fails('call popup_create(666, {})', 'E714:')
+  call assert_fails('call popup_create(666, {})', 'E86:')
   call popup_clear()
   call assert_fails('call popup_create("text", "none")', 'E715:')
   call popup_clear()
@@ -1654,3 +1654,18 @@ func Test_popupwin_garbage_collect()
   call popup_close(winid)
   delfunc MyPopupFilter
 endfunc
+
+func Test_popupwin_with_buffer()
+  call writefile(['some text', 'in a buffer'], 'XsomeFile')
+  let buf = bufadd('XsomeFile')
+  call assert_equal(0, bufloaded(buf))
+  let winid = popup_create(buf, {})
+  call assert_notequal(0, winid)
+  let pos = popup_getpos(winid)
+  call assert_equal(2, pos.height)
+  call assert_equal(1, bufloaded(buf))
+  call popup_close(winid)
+  call assert_equal({}, popup_getpos(winid))
+  call assert_equal(1, bufloaded(buf))
+  exe 'bwipe! ' .. buf
+endfunc
index 1732fe8ff7d92001687256d2e90a47275b41a648..1e6c1464a3c1f5f4f7bdcddbf320b907b02f9763 100644 (file)
--- a/src/ui.c
+++ b/src/ui.c
@@ -1078,7 +1078,7 @@ clip_start_selection(int col, int row, int repeated_click)
        int         col_cp = col;
 
        wp = mouse_find_win(&row_cp, &col_cp, FIND_POPUP);
-       if (wp != NULL && bt_popup(wp->w_buffer))
+       if (wp != NULL && WIN_IS_POPUP(wp))
        {
            // Click in a popup window restricts selection to that window,
            // excluding the border.
@@ -3052,7 +3052,7 @@ retnomove:
 #ifdef FEAT_TEXT_PROP
        // Click in a popup window may start dragging or modeless selection,
        // but not much else.
-       if (bt_popup(wp->w_buffer))
+       if (WIN_IS_POPUP(wp))
        {
            on_sep_line = 0;
            in_popup_win = TRUE;
index a1c5f88a89884b1755cf8d575f14bf0674134865..7bd2327369b9f2a18e84dc1c2300c97c2ca66b60 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1612,
 /**/
     1611,
 /**/
index cb1d38938ffb4bcd5db60283516b46e8f0fbab10..410d9d7e3cd4eaae8048b0c1b511ea2f30aa2a11 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -614,8 +614,14 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define VALID_TOPLINE  0x80    // w_topline is valid (for cursor position)
 
 // Values for w_popup_flags.
-#define POPF_HIDDEN    1       // popup is not displayed
-#define POPF_HANDLED   2       // popup was just redrawn or filtered
+#define POPF_IS_POPUP  1       // this is a popup window
+#define POPF_HIDDEN    2       // popup is not displayed
+#define POPF_HANDLED   4       // popup was just redrawn or filtered
+#ifdef FEAT_TEXT_PROP
+# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
+#else
+# define WIN_IS_POPUP(wp) 0
+#endif
 
 /*
  * Terminal highlighting attribute bits.
index d40b06096600301fb43a0c79dba64f52b9028c88..b40aae6b2baf570ffe4f85c8e0601b207d9c977d 100644 (file)
@@ -4887,7 +4887,7 @@ win_free(
     int
 win_unlisted(win_T *wp)
 {
-    return wp == aucmd_win || bt_popup(wp->w_buffer);
+    return wp == aucmd_win || WIN_IS_POPUP(wp);
 }
 
 #if defined(FEAT_TEXT_PROP) || defined(PROTO)
@@ -4898,7 +4898,10 @@ win_unlisted(win_T *wp)
     void
 win_free_popup(win_T *win)
 {
-    win_close_buffer(win, DOBUF_WIPE, FALSE);
+    if (bt_popup(win->w_buffer))
+       win_close_buffer(win, DOBUF_WIPE, FALSE);
+    else
+       close_buffer(win, win->w_buffer, 0, FALSE);
 # if defined(FEAT_TIMERS)
     if (win->w_popup_timer != NULL)
        stop_timer(win->w_popup_timer);
@@ -6605,7 +6608,7 @@ restore_win_noblock(
        curbuf = curwin->w_buffer;
     }
 #ifdef FEAT_TEXT_PROP
-    else if (bt_popup(curwin->w_buffer))
+    else if (WIN_IS_POPUP(curwin))
        // original window was closed and now we're in a popup window: Go
        // to the first valid window.
        win_goto(firstwin);