To: vim_dev@googlegroups.com Subject: Patch 8.1.1908 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.1908 Problem: Every popup window consumes a buffer number. Solution: Recycle buffers only used for popup windows. Do not list popup window buffers. Files: src/popupwin.c, src/window.c, src/vim.h, src/buffer.c, src/proto/buffer.pro, src/ex_docmd.c, src/testdir/test_popupwin.vim *** ../vim-8.1.1907/src/popupwin.c 2019-08-21 20:57:02.860627886 +0200 --- src/popupwin.c 2019-08-21 21:34:56.643728544 +0200 *************** *** 1550,1557 **** { // 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); --- 1550,1556 ---- { // create a new buffer associated with the popup new_buffer = TRUE; ! buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_DUMMY|BLN_REUSE); if (buf == NULL) return NULL; ml_open(buf); *** ../vim-8.1.1907/src/window.c 2019-08-20 20:13:40.334821916 +0200 --- src/window.c 2019-08-21 21:34:27.183894258 +0200 *************** *** 4970,4976 **** win_free_popup(win_T *win) { 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) --- 4970,4976 ---- win_free_popup(win_T *win) { if (bt_popup(win->w_buffer)) ! win_close_buffer(win, DOBUF_WIPE_REUSE, FALSE); else close_buffer(win, win->w_buffer, 0, FALSE); # if defined(FEAT_TIMERS) *** ../vim-8.1.1907/src/vim.h 2019-08-21 17:29:08.034793106 +0200 --- src/vim.h 2019-08-21 21:35:31.659531624 +0200 *************** *** 922,934 **** #define GETFILE_UNUSED 8 #define GETFILE_SUCCESS(x) ((x) <= 0) ! /* Values for buflist_new() flags */ ! #define BLN_CURBUF 1 /* may re-use curbuf for new buffer */ ! #define BLN_LISTED 2 /* put new buffer in buffer list */ ! #define BLN_DUMMY 4 /* allocating dummy buffer */ ! #define BLN_NEW 8 /* create a new buffer */ ! #define BLN_NOOPT 16 /* don't copy options to existing buffer */ ! #define BLN_DUMMY_OK 32 /* also find an existing dummy buffer */ /* Values for in_cinkeys() */ #define KEY_OPEN_FORW 0x101 --- 922,935 ---- #define GETFILE_UNUSED 8 #define GETFILE_SUCCESS(x) ((x) <= 0) ! // Values for buflist_new() flags ! #define BLN_CURBUF 1 // may re-use curbuf for new buffer ! #define BLN_LISTED 2 // put new buffer in buffer list ! #define BLN_DUMMY 4 // allocating dummy buffer ! #define BLN_NEW 8 // create a new buffer ! #define BLN_NOOPT 16 // don't copy options to existing buffer ! #define BLN_DUMMY_OK 32 // also find an existing dummy buffer ! #define BLN_REUSE 64 // may re-use number from buf_reuse /* Values for in_cinkeys() */ #define KEY_OPEN_FORW 0x101 *************** *** 977,988 **** #define FM_BLOCKSTOP 0x04 /* stop at start/end of block */ #define FM_SKIPCOMM 0x08 /* skip comments */ ! /* Values for action argument for do_buffer() */ ! #define DOBUF_GOTO 0 /* go to specified buffer */ ! #define DOBUF_SPLIT 1 /* split window and go to specified buffer */ ! #define DOBUF_UNLOAD 2 /* unload specified buffer(s) */ ! #define DOBUF_DEL 3 /* delete specified buffer(s) from buflist */ ! #define DOBUF_WIPE 4 /* delete specified buffer(s) really */ /* Values for start argument for do_buffer() */ #define DOBUF_CURRENT 0 /* "count" buffer from current buffer */ --- 978,990 ---- #define FM_BLOCKSTOP 0x04 /* stop at start/end of block */ #define FM_SKIPCOMM 0x08 /* skip comments */ ! // Values for action argument for do_buffer() and close_buffer() ! #define DOBUF_GOTO 0 // go to specified buffer ! #define DOBUF_SPLIT 1 // split window and go to specified buffer ! #define DOBUF_UNLOAD 2 // unload specified buffer(s) ! #define DOBUF_DEL 3 // delete specified buffer(s) from buflist ! #define DOBUF_WIPE 4 // delete specified buffer(s) really ! #define DOBUF_WIPE_REUSE 5 // like DOBUF_WIPE an keep number for reuse /* Values for start argument for do_buffer() */ #define DOBUF_CURRENT 0 /* "count" buffer from current buffer */ *** ../vim-8.1.1907/src/buffer.c 2019-08-21 14:36:29.383376114 +0200 --- src/buffer.c 2019-08-21 22:16:51.444339503 +0200 *************** *** 62,70 **** #endif static char *e_auabort = N_("E855: Autocommands caused command to abort"); ! /* Number of times free_buffer() was called. */ static int buf_free_count = 0; /* * Read data from buffer for retrying. */ --- 62,82 ---- #endif static char *e_auabort = N_("E855: Autocommands caused command to abort"); ! // Number of times free_buffer() was called. static int buf_free_count = 0; + static int top_file_num = 1; // highest file number + static garray_T buf_reuse = GA_EMPTY; // file numbers to recycle + + /* + * Return the highest possible buffer number. + */ + int + get_highest_fnum(void) + { + return top_file_num - 1; + } + /* * Read data from buffer for retrying. */ *************** *** 470,475 **** --- 482,488 ---- * DOBUF_UNLOAD buffer is unloaded * DOBUF_DELETE buffer is unloaded and removed from buffer list * DOBUF_WIPE buffer is unloaded and really deleted + * DOBUF_WIPE_REUSE idem, and add to buf_reuse list * When doing all but the first one on the current buffer, the caller should * get a new buffer very soon! * *************** *** 493,500 **** win_T *the_curwin = curwin; tabpage_T *the_curtab = curtab; int unload_buf = (action != 0); ! int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE); ! int wipe_buf = (action == DOBUF_WIPE); /* * Force unloading or deleting when 'bufhidden' says so. --- 506,513 ---- win_T *the_curwin = curwin; tabpage_T *the_curtab = curtab; int unload_buf = (action != 0); ! int wipe_buf = (action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE); ! int del_buf = (action == DOBUF_DEL || wipe_buf); /* * Force unloading or deleting when 'bufhidden' says so. *************** *** 686,691 **** --- 699,712 ---- */ if (wipe_buf) { + if (action == DOBUF_WIPE_REUSE) + { + // we can re-use this buffer number, store it + if (buf_reuse.ga_itemsize == 0) + ga_init2(&buf_reuse, sizeof(int), 50); + if (ga_grow(&buf_reuse, 1) == OK) + ((int *)buf_reuse.ga_data)[buf_reuse.ga_len++] = buf->b_fnum; + } if (buf->b_sfname != buf->b_ffname) VIM_CLEAR(buf->b_sfname); else *************** *** 1184,1190 **** if (!VIM_ISDIGIT(*arg)) { p = skiptowhite_esc(arg); ! bnr = buflist_findpat(arg, p, command == DOBUF_WIPE, FALSE, FALSE); if (bnr < 0) /* failed */ break; --- 1205,1212 ---- if (!VIM_ISDIGIT(*arg)) { p = skiptowhite_esc(arg); ! bnr = buflist_findpat(arg, p, ! command == DOBUF_WIPE || command == DOBUF_WIPE_REUSE, FALSE, FALSE); if (bnr < 0) /* failed */ break; *************** *** 1275,1280 **** --- 1297,1303 ---- * action == DOBUF_UNLOAD unload specified buffer(s) * action == DOBUF_DEL delete specified buffer(s) from buffer list * action == DOBUF_WIPE delete specified buffer(s) really + * action == DOBUF_WIPE_REUSE idem, and add number to "buf_reuse" * * start == DOBUF_CURRENT go to "count" buffer from current buffer * start == DOBUF_FIRST go to "count" buffer from first buffer *************** *** 1294,1300 **** buf_T *buf; buf_T *bp; int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL ! || action == DOBUF_WIPE); switch (start) { --- 1317,1323 ---- buf_T *buf; buf_T *bp; int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL ! || action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE); switch (start) { *************** *** 1395,1401 **** /* When unloading or deleting a buffer that's already unloaded and * unlisted: fail silently. */ ! if (action != DOBUF_WIPE && buf->b_ml.ml_mfp == NULL && !buf->b_p_bl) return FAIL; if (!forceit && bufIsChanged(buf)) --- 1418,1425 ---- /* When unloading or deleting a buffer that's already unloaded and * unlisted: fail silently. */ ! if (action != DOBUF_WIPE && action != DOBUF_WIPE_REUSE ! && buf->b_ml.ml_mfp == NULL && !buf->b_p_bl) return FAIL; if (!forceit && bufIsChanged(buf)) *************** *** 1631,1643 **** * DOBUF_UNLOAD unload it * DOBUF_DEL delete it * DOBUF_WIPE wipe it out */ void set_curbuf(buf_T *buf, int action) { buf_T *prevbuf; int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL ! || action == DOBUF_WIPE); #ifdef FEAT_SYN_HL long old_tw = curbuf->b_p_tw; #endif --- 1655,1668 ---- * DOBUF_UNLOAD unload it * DOBUF_DEL delete it * DOBUF_WIPE wipe it out + * DOBUF_WIPE_REUSE wipe it out and add to "buf_reuse" */ void set_curbuf(buf_T *buf, int action) { buf_T *prevbuf; int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL ! || action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE); #ifdef FEAT_SYN_HL long old_tw = curbuf->b_p_tw; #endif *************** *** 1861,1868 **** * functions for dealing with the buffer list */ - static int top_file_num = 1; /* highest file number */ - /* * Return TRUE if the current buffer is empty, unnamed, unmodified and used in * only one window. That means it can be re-used. --- 1886,1891 ---- *************** *** 1890,1895 **** --- 1913,1919 ---- * If (flags & BLN_NEW) is TRUE, don't use an existing buffer. * If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer * if the buffer already exists. + * If (flags & BLN_REUSE) is TRUE, may use buffer number from "buf_reuse". * This is the ONLY way to create a new buffer. */ buf_T * *************** *** 2065,2071 **** } lastbuf = buf; ! buf->b_fnum = top_file_num++; if (top_file_num < 0) /* wrap around (may cause duplicates) */ { emsg(_("W14: Warning: List of file names overflow")); --- 2089,2104 ---- } lastbuf = buf; ! if ((flags & BLN_REUSE) && buf_reuse.ga_len > 0) ! { ! // Recycle a previously used buffer number. Used for buffers which ! // are normally hidden, e.g. in a popup window. Avoids that the ! // buffer number grows rapidly. ! --buf_reuse.ga_len; ! buf->b_fnum = ((int *)buf_reuse.ga_data)[buf_reuse.ga_len]; ! } ! else ! buf->b_fnum = top_file_num++; if (top_file_num < 0) /* wrap around (may cause duplicates) */ { emsg(_("W14: Warning: List of file names overflow")); *** ../vim-8.1.1907/src/proto/buffer.pro 2019-08-20 20:13:40.330821936 +0200 --- src/proto/buffer.pro 2019-08-21 22:17:27.860172902 +0200 *************** *** 1,4 **** --- 1,5 ---- /* buffer.c */ + int get_highest_fnum(void); 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); *** ../vim-8.1.1907/src/ex_docmd.c 2019-08-21 18:30:58.882719474 +0200 --- src/ex_docmd.c 2019-08-21 22:20:27.471356851 +0200 *************** *** 4633,4640 **** return _(e_invrange); break; case ADDR_BUFFERS: ! if (eap->line1 < firstbuf->b_fnum ! || eap->line2 > lastbuf->b_fnum) return _(e_invrange); break; case ADDR_LOADED_BUFFERS: --- 4633,4641 ---- return _(e_invrange); break; case ADDR_BUFFERS: ! // Only a boundary check, not whether the buffers actually ! // exist. ! if (eap->line1 < 1 || eap->line2 > get_highest_fnum()) return _(e_invrange); break; case ADDR_LOADED_BUFFERS: *** ../vim-8.1.1907/src/testdir/test_popupwin.vim 2019-08-21 20:57:02.864627863 +0200 --- src/testdir/test_popupwin.vim 2019-08-21 22:03:02.559778871 +0200 *************** *** 2331,2334 **** --- 2331,2343 ---- call delete('XtestInfoPopupNb') endfunc + func Test_popupwin_recycle_bnr() + let winid = popup_notification('nothing wrong', {}) + let bufnr = winbufnr(winid) + call popup_clear() + let winid = popup_notification('nothing wrong', {}) + call assert_equal(bufnr, winbufnr(winid)) + call popup_clear() + endfunc + " vim: shiftwidth=2 sts=2 *** ../vim-8.1.1907/src/version.c 2019-08-21 20:57:02.864627863 +0200 --- src/version.c 2019-08-21 22:24:24.450291926 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 1908, /**/ -- From "know your smileys": :-| :-| Deja' vu! /// 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 ///