diff src/buffer.c @ 17823:7e6b7a4f13bc v8.1.1908

patch 8.1.1908: every popup window consumes a buffer number Commit: https://github.com/vim/vim/commit/00b0d6d8dc2c04b3cb26ea3c3d58527939f01af6 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Aug 21 22:25:30 2019 +0200 patch 8.1.1908: every popup window consumes a buffer number Problem: Every popup window consumes a buffer number. Solution: Recycle buffers only used for popup windows. Do not list popup window buffers.
author Bram Moolenaar <Bram@vim.org>
date Wed, 21 Aug 2019 22:30:04 +0200
parents 59f8948b7590
children bb0e25a8b5d7
line wrap: on
line diff
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -62,9 +62,21 @@ static char *msg_qflist = N_("[Quickfix 
 #endif
 static char *e_auabort = N_("E855: Autocommands caused command to abort");
 
-/* Number of times free_buffer() was called. */
+// 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,6 +482,7 @@ can_unload_buffer(buf_T *buf)
  * 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,8 +506,8 @@ close_buffer(
     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);
+    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,6 +699,14 @@ aucmd_abort:
      */
     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,7 +1205,8 @@ do_bufdel(
 		if (!VIM_ISDIGIT(*arg))
 		{
 		    p = skiptowhite_esc(arg);
-		    bnr = buflist_findpat(arg, p, command == DOBUF_WIPE,
+		    bnr = buflist_findpat(arg, p,
+			  command == DOBUF_WIPE || command == DOBUF_WIPE_REUSE,
 								FALSE, FALSE);
 		    if (bnr < 0)	    /* failed */
 			break;
@@ -1275,6 +1297,7 @@ empty_curbuf(
  * 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,7 +1317,7 @@ do_buffer(
     buf_T	*buf;
     buf_T	*bp;
     int		unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
-						     || action == DOBUF_WIPE);
+			|| action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE);
 
     switch (start)
     {
@@ -1395,7 +1418,8 @@ do_buffer(
 
 	/* 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)
+	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,13 +1655,14 @@ do_buffer(
  * 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 || action == DOBUF_WIPE_REUSE);
 #ifdef FEAT_SYN_HL
     long	old_tw = curbuf->b_p_tw;
 #endif
@@ -1861,8 +1886,6 @@ no_write_message_nobang(buf_T *buf UNUSE
  * 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.
@@ -1890,6 +1913,7 @@ curbuf_reusable(void)
  * 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,7 +2089,16 @@ buflist_new(
 	}
 	lastbuf = buf;
 
-	buf->b_fnum = top_file_num++;
+	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"));