mirror of
https://github.com/vim/vim.git
synced 2025-08-24 19:45:50 -04:00
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.
This commit is contained in:
parent
fe6e7618b4
commit
00b0d6d8dc
51
src/buffer.c
51
src/buffer.c
@ -62,9 +62,21 @@ static char *msg_qflist = N_("[Quickfix List]");
|
|||||||
#endif
|
#endif
|
||||||
static char *e_auabort = N_("E855: Autocommands caused command to abort");
|
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 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.
|
* Read data from buffer for retrying.
|
||||||
*/
|
*/
|
||||||
@ -470,6 +482,7 @@ can_unload_buffer(buf_T *buf)
|
|||||||
* DOBUF_UNLOAD buffer is unloaded
|
* DOBUF_UNLOAD buffer is unloaded
|
||||||
* DOBUF_DELETE buffer is unloaded and removed from buffer list
|
* DOBUF_DELETE buffer is unloaded and removed from buffer list
|
||||||
* DOBUF_WIPE buffer is unloaded and really deleted
|
* 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
|
* When doing all but the first one on the current buffer, the caller should
|
||||||
* get a new buffer very soon!
|
* get a new buffer very soon!
|
||||||
*
|
*
|
||||||
@ -493,8 +506,8 @@ close_buffer(
|
|||||||
win_T *the_curwin = curwin;
|
win_T *the_curwin = curwin;
|
||||||
tabpage_T *the_curtab = curtab;
|
tabpage_T *the_curtab = curtab;
|
||||||
int unload_buf = (action != 0);
|
int unload_buf = (action != 0);
|
||||||
int del_buf = (action == DOBUF_DEL || action == DOBUF_WIPE);
|
int wipe_buf = (action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE);
|
||||||
int wipe_buf = (action == DOBUF_WIPE);
|
int del_buf = (action == DOBUF_DEL || wipe_buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force unloading or deleting when 'bufhidden' says so.
|
* Force unloading or deleting when 'bufhidden' says so.
|
||||||
@ -686,6 +699,14 @@ aucmd_abort:
|
|||||||
*/
|
*/
|
||||||
if (wipe_buf)
|
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)
|
if (buf->b_sfname != buf->b_ffname)
|
||||||
VIM_CLEAR(buf->b_sfname);
|
VIM_CLEAR(buf->b_sfname);
|
||||||
else
|
else
|
||||||
@ -1184,7 +1205,8 @@ do_bufdel(
|
|||||||
if (!VIM_ISDIGIT(*arg))
|
if (!VIM_ISDIGIT(*arg))
|
||||||
{
|
{
|
||||||
p = skiptowhite_esc(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);
|
FALSE, FALSE);
|
||||||
if (bnr < 0) /* failed */
|
if (bnr < 0) /* failed */
|
||||||
break;
|
break;
|
||||||
@ -1275,6 +1297,7 @@ empty_curbuf(
|
|||||||
* action == DOBUF_UNLOAD unload specified buffer(s)
|
* action == DOBUF_UNLOAD unload specified buffer(s)
|
||||||
* action == DOBUF_DEL delete specified buffer(s) from buffer list
|
* action == DOBUF_DEL delete specified buffer(s) from buffer list
|
||||||
* action == DOBUF_WIPE delete specified buffer(s) really
|
* 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_CURRENT go to "count" buffer from current buffer
|
||||||
* start == DOBUF_FIRST go to "count" buffer from first buffer
|
* start == DOBUF_FIRST go to "count" buffer from first buffer
|
||||||
@ -1294,7 +1317,7 @@ do_buffer(
|
|||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
buf_T *bp;
|
buf_T *bp;
|
||||||
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|
||||||
|| action == DOBUF_WIPE);
|
|| action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE);
|
||||||
|
|
||||||
switch (start)
|
switch (start)
|
||||||
{
|
{
|
||||||
@ -1395,7 +1418,8 @@ do_buffer(
|
|||||||
|
|
||||||
/* When unloading or deleting a buffer that's already unloaded and
|
/* When unloading or deleting a buffer that's already unloaded and
|
||||||
* unlisted: fail silently. */
|
* 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;
|
return FAIL;
|
||||||
|
|
||||||
if (!forceit && bufIsChanged(buf))
|
if (!forceit && bufIsChanged(buf))
|
||||||
@ -1631,13 +1655,14 @@ do_buffer(
|
|||||||
* DOBUF_UNLOAD unload it
|
* DOBUF_UNLOAD unload it
|
||||||
* DOBUF_DEL delete it
|
* DOBUF_DEL delete it
|
||||||
* DOBUF_WIPE wipe it out
|
* DOBUF_WIPE wipe it out
|
||||||
|
* DOBUF_WIPE_REUSE wipe it out and add to "buf_reuse"
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
set_curbuf(buf_T *buf, int action)
|
set_curbuf(buf_T *buf, int action)
|
||||||
{
|
{
|
||||||
buf_T *prevbuf;
|
buf_T *prevbuf;
|
||||||
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|
||||||
|| action == DOBUF_WIPE);
|
|| action == DOBUF_WIPE || action == DOBUF_WIPE_REUSE);
|
||||||
#ifdef FEAT_SYN_HL
|
#ifdef FEAT_SYN_HL
|
||||||
long old_tw = curbuf->b_p_tw;
|
long old_tw = curbuf->b_p_tw;
|
||||||
#endif
|
#endif
|
||||||
@ -1861,8 +1886,6 @@ no_write_message_nobang(buf_T *buf UNUSED)
|
|||||||
* functions for dealing with the buffer list
|
* 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
|
* Return TRUE if the current buffer is empty, unnamed, unmodified and used in
|
||||||
* only one window. That means it can be re-used.
|
* 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_NEW) is TRUE, don't use an existing buffer.
|
||||||
* If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer
|
* If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer
|
||||||
* if the buffer already exists.
|
* 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.
|
* This is the ONLY way to create a new buffer.
|
||||||
*/
|
*/
|
||||||
buf_T *
|
buf_T *
|
||||||
@ -2065,6 +2089,15 @@ buflist_new(
|
|||||||
}
|
}
|
||||||
lastbuf = buf;
|
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++;
|
buf->b_fnum = top_file_num++;
|
||||||
if (top_file_num < 0) /* wrap around (may cause duplicates) */
|
if (top_file_num < 0) /* wrap around (may cause duplicates) */
|
||||||
{
|
{
|
||||||
|
@ -4633,8 +4633,9 @@ invalid_range(exarg_T *eap)
|
|||||||
return _(e_invrange);
|
return _(e_invrange);
|
||||||
break;
|
break;
|
||||||
case ADDR_BUFFERS:
|
case ADDR_BUFFERS:
|
||||||
if (eap->line1 < firstbuf->b_fnum
|
// Only a boundary check, not whether the buffers actually
|
||||||
|| eap->line2 > lastbuf->b_fnum)
|
// exist.
|
||||||
|
if (eap->line1 < 1 || eap->line2 > get_highest_fnum())
|
||||||
return _(e_invrange);
|
return _(e_invrange);
|
||||||
break;
|
break;
|
||||||
case ADDR_LOADED_BUFFERS:
|
case ADDR_LOADED_BUFFERS:
|
||||||
|
@ -1550,8 +1550,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
|
|||||||
{
|
{
|
||||||
// create a new buffer associated with the popup
|
// create a new buffer associated with the popup
|
||||||
new_buffer = TRUE;
|
new_buffer = TRUE;
|
||||||
buf = buflist_new(NULL, NULL, (linenr_T)0,
|
buf = buflist_new(NULL, NULL, (linenr_T)0, BLN_NEW|BLN_DUMMY|BLN_REUSE);
|
||||||
BLN_NEW|BLN_LISTED|BLN_DUMMY);
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
ml_open(buf);
|
ml_open(buf);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* buffer.c */
|
/* buffer.c */
|
||||||
|
int get_highest_fnum(void);
|
||||||
void buffer_ensure_loaded(buf_T *buf);
|
void buffer_ensure_loaded(buf_T *buf);
|
||||||
int open_buffer(int read_stdin, exarg_T *eap, int flags);
|
int open_buffer(int read_stdin, exarg_T *eap, int flags);
|
||||||
void set_bufref(bufref_T *bufref, buf_T *buf);
|
void set_bufref(bufref_T *bufref, buf_T *buf);
|
||||||
|
@ -2331,4 +2331,13 @@ func Test_popupmenu_info_align_menu()
|
|||||||
call delete('XtestInfoPopupNb')
|
call delete('XtestInfoPopupNb')
|
||||||
endfunc
|
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: shiftwidth=2 sts=2
|
||||||
|
@ -761,6 +761,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1908,
|
||||||
/**/
|
/**/
|
||||||
1907,
|
1907,
|
||||||
/**/
|
/**/
|
||||||
|
28
src/vim.h
28
src/vim.h
@ -922,13 +922,14 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
|||||||
#define GETFILE_UNUSED 8
|
#define GETFILE_UNUSED 8
|
||||||
#define GETFILE_SUCCESS(x) ((x) <= 0)
|
#define GETFILE_SUCCESS(x) ((x) <= 0)
|
||||||
|
|
||||||
/* Values for buflist_new() flags */
|
// Values for buflist_new() flags
|
||||||
#define BLN_CURBUF 1 /* may re-use curbuf for new buffer */
|
#define BLN_CURBUF 1 // may re-use curbuf for new buffer
|
||||||
#define BLN_LISTED 2 /* put new buffer in buffer list */
|
#define BLN_LISTED 2 // put new buffer in buffer list
|
||||||
#define BLN_DUMMY 4 /* allocating dummy buffer */
|
#define BLN_DUMMY 4 // allocating dummy buffer
|
||||||
#define BLN_NEW 8 /* create a new buffer */
|
#define BLN_NEW 8 // create a new buffer
|
||||||
#define BLN_NOOPT 16 /* don't copy options to existing 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_DUMMY_OK 32 // also find an existing dummy buffer
|
||||||
|
#define BLN_REUSE 64 // may re-use number from buf_reuse
|
||||||
|
|
||||||
/* Values for in_cinkeys() */
|
/* Values for in_cinkeys() */
|
||||||
#define KEY_OPEN_FORW 0x101
|
#define KEY_OPEN_FORW 0x101
|
||||||
@ -977,12 +978,13 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
|||||||
#define FM_BLOCKSTOP 0x04 /* stop at start/end of block */
|
#define FM_BLOCKSTOP 0x04 /* stop at start/end of block */
|
||||||
#define FM_SKIPCOMM 0x08 /* skip comments */
|
#define FM_SKIPCOMM 0x08 /* skip comments */
|
||||||
|
|
||||||
/* Values for action argument for do_buffer() */
|
// Values for action argument for do_buffer() and close_buffer()
|
||||||
#define DOBUF_GOTO 0 /* go to specified buffer */
|
#define DOBUF_GOTO 0 // go to specified buffer
|
||||||
#define DOBUF_SPLIT 1 /* split window and 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_UNLOAD 2 // unload specified buffer(s)
|
||||||
#define DOBUF_DEL 3 /* delete specified buffer(s) from buflist */
|
#define DOBUF_DEL 3 // delete specified buffer(s) from buflist
|
||||||
#define DOBUF_WIPE 4 /* delete specified buffer(s) really */
|
#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() */
|
/* Values for start argument for do_buffer() */
|
||||||
#define DOBUF_CURRENT 0 /* "count" buffer from current buffer */
|
#define DOBUF_CURRENT 0 /* "count" buffer from current buffer */
|
||||||
|
@ -4970,7 +4970,7 @@ win_unlisted(win_T *wp)
|
|||||||
win_free_popup(win_T *win)
|
win_free_popup(win_T *win)
|
||||||
{
|
{
|
||||||
if (bt_popup(win->w_buffer))
|
if (bt_popup(win->w_buffer))
|
||||||
win_close_buffer(win, DOBUF_WIPE, FALSE);
|
win_close_buffer(win, DOBUF_WIPE_REUSE, FALSE);
|
||||||
else
|
else
|
||||||
close_buffer(win, win->w_buffer, 0, FALSE);
|
close_buffer(win, win->w_buffer, 0, FALSE);
|
||||||
# if defined(FEAT_TIMERS)
|
# if defined(FEAT_TIMERS)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user