mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.0892: failure when closing a window when location list is in use
Problem: Failure when closing a window when location list is in use. Solution: Handle the situation gracefully. Make sure memory for 'switchbuf' is not freed at the wrong time. (Yegappan Lakshmanan, closes #3928)
This commit is contained in:
parent
d77aa4d22e
commit
eeb1b9c7ed
@ -8587,7 +8587,7 @@ find_win_by_nr_or_id(typval_T *vp)
|
|||||||
int nr = (int)tv_get_number_chk(vp, NULL);
|
int nr = (int)tv_get_number_chk(vp, NULL);
|
||||||
|
|
||||||
if (nr >= LOWEST_WIN_ID)
|
if (nr >= LOWEST_WIN_ID)
|
||||||
return win_id2wp(vp);
|
return win_id2wp(tv_get_number(vp));
|
||||||
return find_win_by_nr(vp, NULL);
|
return find_win_by_nr(vp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5800,7 +5800,7 @@ f_getwininfo(typval_T *argvars, typval_T *rettv)
|
|||||||
|
|
||||||
if (argvars[0].v_type != VAR_UNKNOWN)
|
if (argvars[0].v_type != VAR_UNKNOWN)
|
||||||
{
|
{
|
||||||
wparg = win_id2wp(argvars);
|
wparg = win_id2wp(tv_get_number(&argvars[0]));
|
||||||
if (wparg == NULL)
|
if (wparg == NULL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ int get_tab_number(tabpage_T *tp);
|
|||||||
int win_getid(typval_T *argvars);
|
int win_getid(typval_T *argvars);
|
||||||
int win_gotoid(typval_T *argvars);
|
int win_gotoid(typval_T *argvars);
|
||||||
void win_id2tabwin(typval_T *argvars, list_T *list);
|
void win_id2tabwin(typval_T *argvars, list_T *list);
|
||||||
win_T *win_id2wp(typval_T *argvars);
|
win_T *win_id2wp(int id);
|
||||||
int win_id2win(typval_T *argvars);
|
int win_id2win(typval_T *argvars);
|
||||||
void win_findbuf(typval_T *argvars, list_T *list);
|
void win_findbuf(typval_T *argvars, list_T *list);
|
||||||
void get_framelayout(frame_T *fr, list_T *l, int outer);
|
void get_framelayout(frame_T *fr, list_T *l, int outer);
|
||||||
|
@ -1899,23 +1899,24 @@ ll_free_all(qf_info_T **pqi)
|
|||||||
return;
|
return;
|
||||||
*pqi = NULL; // Remove reference to this list
|
*pqi = NULL; // Remove reference to this list
|
||||||
|
|
||||||
|
// If the location list is still in use, then queue the delete request
|
||||||
|
// to be processed later.
|
||||||
|
if (quickfix_busy > 0)
|
||||||
|
{
|
||||||
|
locstack_queue_delreq(qi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qi->qf_refcount--;
|
qi->qf_refcount--;
|
||||||
if (qi->qf_refcount < 1)
|
if (qi->qf_refcount < 1)
|
||||||
{
|
{
|
||||||
// No references to this location list.
|
// No references to this location list.
|
||||||
// If the location list is still in use, then queue the delete request
|
// If the quickfix window buffer is loaded, then wipe it
|
||||||
// to be processed later.
|
wipe_qf_buffer(qi);
|
||||||
if (quickfix_busy > 0)
|
|
||||||
locstack_queue_delreq(qi);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the quickfix window buffer is loaded, then wipe it
|
|
||||||
wipe_qf_buffer(qi);
|
|
||||||
|
|
||||||
for (i = 0; i < qi->qf_listcount; ++i)
|
for (i = 0; i < qi->qf_listcount; ++i)
|
||||||
qf_free(&qi->qf_lists[i]);
|
qf_free(&qi->qf_lists[i]);
|
||||||
vim_free(qi);
|
vim_free(qi);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3018,7 +3019,7 @@ qf_jump_edit_buffer(
|
|||||||
qf_info_T *qi,
|
qf_info_T *qi,
|
||||||
qfline_T *qf_ptr,
|
qfline_T *qf_ptr,
|
||||||
int forceit,
|
int forceit,
|
||||||
win_T *oldwin,
|
int prev_winid,
|
||||||
int *opened_window)
|
int *opened_window)
|
||||||
{
|
{
|
||||||
qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist];
|
qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist];
|
||||||
@ -3039,7 +3040,7 @@ qf_jump_edit_buffer(
|
|||||||
|
|
||||||
retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
|
retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
|
||||||
ECMD_HIDE + ECMD_SET_HELP,
|
ECMD_HIDE + ECMD_SET_HELP,
|
||||||
oldwin == curwin ? curwin : NULL);
|
prev_winid == curwin->w_id ? curwin : NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
retval = buflist_getfile(qf_ptr->qf_fnum,
|
retval = buflist_getfile(qf_ptr->qf_fnum,
|
||||||
@ -3047,11 +3048,15 @@ qf_jump_edit_buffer(
|
|||||||
|
|
||||||
// If a location list, check whether the associated window is still
|
// If a location list, check whether the associated window is still
|
||||||
// present.
|
// present.
|
||||||
if (qfl_type == QFLT_LOCATION && !win_valid_any_tab(oldwin))
|
if (qfl_type == QFLT_LOCATION)
|
||||||
{
|
{
|
||||||
emsg(_("E924: Current window was closed"));
|
win_T *wp = win_id2wp(prev_winid);
|
||||||
*opened_window = FALSE;
|
if (wp == NULL && curwin->w_llist != qi)
|
||||||
return NOTDONE;
|
{
|
||||||
|
emsg(_("E924: Current window was closed"));
|
||||||
|
*opened_window = FALSE;
|
||||||
|
return NOTDONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
|
if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
|
||||||
@ -3211,7 +3216,7 @@ qf_jump_to_buffer(
|
|||||||
int qf_index,
|
int qf_index,
|
||||||
qfline_T *qf_ptr,
|
qfline_T *qf_ptr,
|
||||||
int forceit,
|
int forceit,
|
||||||
win_T *oldwin,
|
int prev_winid,
|
||||||
int *opened_window,
|
int *opened_window,
|
||||||
int openfold,
|
int openfold,
|
||||||
int print_message)
|
int print_message)
|
||||||
@ -3227,7 +3232,7 @@ qf_jump_to_buffer(
|
|||||||
|
|
||||||
if (qf_ptr->qf_fnum != 0)
|
if (qf_ptr->qf_fnum != 0)
|
||||||
{
|
{
|
||||||
retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
|
retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid,
|
||||||
opened_window);
|
opened_window);
|
||||||
if (retval != OK)
|
if (retval != OK)
|
||||||
return retval;
|
return retval;
|
||||||
@ -3287,8 +3292,8 @@ qf_jump_newwin(qf_info_T *qi,
|
|||||||
int old_qf_index;
|
int old_qf_index;
|
||||||
char_u *old_swb = p_swb;
|
char_u *old_swb = p_swb;
|
||||||
unsigned old_swb_flags = swb_flags;
|
unsigned old_swb_flags = swb_flags;
|
||||||
|
int prev_winid;
|
||||||
int opened_window = FALSE;
|
int opened_window = FALSE;
|
||||||
win_T *oldwin = curwin;
|
|
||||||
int print_message = TRUE;
|
int print_message = TRUE;
|
||||||
#ifdef FEAT_FOLDING
|
#ifdef FEAT_FOLDING
|
||||||
int old_KeyTyped = KeyTyped; // getting file may reset it
|
int old_KeyTyped = KeyTyped; // getting file may reset it
|
||||||
@ -3304,6 +3309,8 @@ qf_jump_newwin(qf_info_T *qi,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
incr_quickfix_busy();
|
||||||
|
|
||||||
qfl = &qi->qf_lists[qi->qf_curlist];
|
qfl = &qi->qf_lists[qi->qf_curlist];
|
||||||
|
|
||||||
qf_ptr = qfl->qf_ptr;
|
qf_ptr = qfl->qf_ptr;
|
||||||
@ -3325,13 +3332,15 @@ qf_jump_newwin(qf_info_T *qi,
|
|||||||
// window
|
// window
|
||||||
print_message = FALSE;
|
print_message = FALSE;
|
||||||
|
|
||||||
|
prev_winid = curwin->w_id;
|
||||||
|
|
||||||
retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
|
retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
|
||||||
if (retval == FAIL)
|
if (retval == FAIL)
|
||||||
goto failed;
|
goto failed;
|
||||||
if (retval == NOTDONE)
|
if (retval == NOTDONE)
|
||||||
goto theend;
|
goto theend;
|
||||||
|
|
||||||
retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin,
|
retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
|
||||||
&opened_window, old_KeyTyped, print_message);
|
&opened_window, old_KeyTyped, print_message);
|
||||||
if (retval == NOTDONE)
|
if (retval == NOTDONE)
|
||||||
{
|
{
|
||||||
@ -3359,7 +3368,7 @@ theend:
|
|||||||
qfl->qf_ptr = qf_ptr;
|
qfl->qf_ptr = qf_ptr;
|
||||||
qfl->qf_index = qf_index;
|
qfl->qf_index = qf_index;
|
||||||
}
|
}
|
||||||
if (p_swb != old_swb && opened_window)
|
if (p_swb != old_swb)
|
||||||
{
|
{
|
||||||
// Restore old 'switchbuf' value, but not when an autocommand or
|
// Restore old 'switchbuf' value, but not when an autocommand or
|
||||||
// modeline has changed the value.
|
// modeline has changed the value.
|
||||||
@ -3371,6 +3380,7 @@ theend:
|
|||||||
else
|
else
|
||||||
free_string_option(old_swb);
|
free_string_option(old_swb);
|
||||||
}
|
}
|
||||||
|
decr_quickfix_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highlight attributes used for displaying entries from the quickfix list.
|
// Highlight attributes used for displaying entries from the quickfix list.
|
||||||
@ -4004,9 +4014,9 @@ qf_open_new_cwindow(qf_info_T *qi, int height)
|
|||||||
if (IS_LL_STACK(qi))
|
if (IS_LL_STACK(qi))
|
||||||
{
|
{
|
||||||
// For the location list window, create a reference to the
|
// For the location list window, create a reference to the
|
||||||
// location list from the window 'win'.
|
// location list stack from the window 'win'.
|
||||||
curwin->w_llist_ref = win->w_llist;
|
curwin->w_llist_ref = qi;
|
||||||
win->w_llist->qf_refcount++;
|
qi->qf_refcount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldwin != curwin)
|
if (oldwin != curwin)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
" Test for the quickfix commands.
|
" Test for the quickfix feature.
|
||||||
|
|
||||||
if !has('quickfix')
|
if !has('quickfix')
|
||||||
finish
|
finish
|
||||||
@ -1419,7 +1419,7 @@ func XquickfixSetListWithAct(cchar)
|
|||||||
\ {'filename': 'fnameD', 'text': 'D'},
|
\ {'filename': 'fnameD', 'text': 'D'},
|
||||||
\ {'filename': 'fnameE', 'text': 'E'}]
|
\ {'filename': 'fnameE', 'text': 'E'}]
|
||||||
|
|
||||||
" {action} is unspecified. Same as specifing ' '.
|
" {action} is unspecified. Same as specifying ' '.
|
||||||
new | only
|
new | only
|
||||||
silent! Xnewer 99
|
silent! Xnewer 99
|
||||||
call g:Xsetlist(list1)
|
call g:Xsetlist(list1)
|
||||||
@ -2348,7 +2348,7 @@ func Test_cwindow_jump()
|
|||||||
" Open a new window and create a location list
|
" Open a new window and create a location list
|
||||||
" Open the location list window and close the other window
|
" Open the location list window and close the other window
|
||||||
" Jump to an entry.
|
" Jump to an entry.
|
||||||
" Should create a new window and jump to the entry. The scrtach buffer
|
" Should create a new window and jump to the entry. The scratch buffer
|
||||||
" should not be used.
|
" should not be used.
|
||||||
enew | only
|
enew | only
|
||||||
set buftype=nofile
|
set buftype=nofile
|
||||||
@ -3831,7 +3831,7 @@ func Test_splitview()
|
|||||||
new | only
|
new | only
|
||||||
|
|
||||||
" When split opening files from a helpgrep location list window, a new help
|
" When split opening files from a helpgrep location list window, a new help
|
||||||
" window should be opend with a copy of the location list.
|
" window should be opened with a copy of the location list.
|
||||||
lhelpgrep window
|
lhelpgrep window
|
||||||
let locid = getloclist(0, {'id' : 0}).id
|
let locid = getloclist(0, {'id' : 0}).id
|
||||||
lwindow
|
lwindow
|
||||||
@ -3933,8 +3933,30 @@ func Xqfbuf_test(cchar)
|
|||||||
call assert_match(qfbnum . ' h- "\[Location List]"', execute('ls'))
|
call assert_match(qfbnum . ' h- "\[Location List]"', execute('ls'))
|
||||||
call assert_true(bufloaded(qfbnum))
|
call assert_true(bufloaded(qfbnum))
|
||||||
|
|
||||||
|
" When the location list is cleared for the window, the buffer should be
|
||||||
|
" removed
|
||||||
|
call setloclist(0, [], 'f')
|
||||||
|
call assert_false(bufexists(qfbnum))
|
||||||
|
|
||||||
|
" When the location list is freed with the location list window open, the
|
||||||
|
" location list buffer should not be lost. It should be reused when the
|
||||||
|
" location list is again populated.
|
||||||
|
lexpr "F1:10:Line10"
|
||||||
|
lopen
|
||||||
|
let wid = win_getid()
|
||||||
|
let qfbnum = bufnr('')
|
||||||
|
wincmd p
|
||||||
|
call setloclist(0, [], 'f')
|
||||||
|
lexpr "F1:10:Line10"
|
||||||
|
lopen
|
||||||
|
call assert_equal(wid, win_getid())
|
||||||
|
call assert_equal(qfbnum, bufnr(''))
|
||||||
|
lclose
|
||||||
|
|
||||||
|
" When the window with the location list is closed, the buffer should be
|
||||||
|
" removed
|
||||||
new | only
|
new | only
|
||||||
call assert_false(bufloaded(qfbnum))
|
call assert_false(bufexists(qfbnum))
|
||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@ -3942,3 +3964,29 @@ func Test_qfbuf()
|
|||||||
call Xqfbuf_test('c')
|
call Xqfbuf_test('c')
|
||||||
call Xqfbuf_test('l')
|
call Xqfbuf_test('l')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" If there is an autocmd to use only one window, then opening the location
|
||||||
|
" list window used to crash Vim.
|
||||||
|
func Test_winonly_autocmd()
|
||||||
|
call s:create_test_file('Xtest1')
|
||||||
|
" Autocmd to show only one Vim window at a time
|
||||||
|
autocmd WinEnter * only
|
||||||
|
new
|
||||||
|
" Load the location list
|
||||||
|
lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
|
||||||
|
let loclistid = getloclist(0, {'id' : 0}).id
|
||||||
|
" Open the location list window. Only this window will be shown and the file
|
||||||
|
" window is closed.
|
||||||
|
lopen
|
||||||
|
call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
|
||||||
|
" Jump to an entry in the location list and make sure that the cursor is
|
||||||
|
" positioned correctly.
|
||||||
|
ll 3
|
||||||
|
call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
|
||||||
|
call assert_equal('Xtest1', bufname(''))
|
||||||
|
call assert_equal(15, line('.'))
|
||||||
|
" Cleanup
|
||||||
|
autocmd! WinEnter
|
||||||
|
new | only
|
||||||
|
call delete('Xtest1')
|
||||||
|
endfunc
|
||||||
|
@ -783,6 +783,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 */
|
||||||
|
/**/
|
||||||
|
892,
|
||||||
/**/
|
/**/
|
||||||
891,
|
891,
|
||||||
/**/
|
/**/
|
||||||
|
@ -7193,11 +7193,10 @@ win_id2tabwin(typval_T *argvars, list_T *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
win_T *
|
win_T *
|
||||||
win_id2wp(typval_T *argvars)
|
win_id2wp(int id)
|
||||||
{
|
{
|
||||||
win_T *wp;
|
win_T *wp;
|
||||||
tabpage_T *tp;
|
tabpage_T *tp;
|
||||||
int id = tv_get_number(&argvars[0]);
|
|
||||||
|
|
||||||
FOR_ALL_TAB_WINDOWS(tp, wp)
|
FOR_ALL_TAB_WINDOWS(tp, wp)
|
||||||
if (wp->w_id == id)
|
if (wp->w_id == id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user