Compare commits

...

5 Commits

Author SHA1 Message Date
Bram Moolenaar
4b974d5443 patch 8.0.0610: the screen is redrawn when default 'background' is detected
Problem:    The screen is redrawn when t_BG is set and used to detect the
            value for 'background'.
Solution:   Don't redraw when the value of 'background' didn't change.
2017-06-04 15:37:46 +02:00
Bram Moolenaar
28a8193e31 patch 8.0.0609: some people still don't know how to quit
Problem:    For some people the hint about quitting is not sufficient.
Solution:   Put <Enter> separately.  Also use ":qa!" to get out even when
            there are changes.
2017-06-04 15:33:48 +02:00
Bram Moolenaar
a3921f48c6 patch 8.0.0608: cannot manipulate other than the current quickfix list
Problem:    Cannot manipulate other than the current quickfix list.
Solution:   Pass the list index to quickfix functions. (Yegappan Lakshmanan)
2017-06-04 15:30:34 +02:00
Bram Moolenaar
45e5fd135d patch 8.0.0607: after :bwipe + :new bufref might still be valid
Problem:    When creating a bufref, then using :bwipe and :new it might get
            the same memory and bufref_valid() returns true.
Solution:   Add br_fnum to check the buffer number didn't change.
2017-06-04 14:58:02 +02:00
Bram Moolenaar
6e62da3e14 patch 8.0.0606: cannot set the context for a specified quickfix list
Problem:    Cannot set the context for a specified quickfix list.
Solution:   Use the list index instead of the current list. (Yegappan
            Lakshmanan)
2017-05-28 08:16:25 +02:00
9 changed files with 135 additions and 53 deletions

View File

@@ -372,18 +372,23 @@ open_buffer(
set_bufref(bufref_T *bufref, buf_T *buf)
{
bufref->br_buf = buf;
bufref->br_fnum = buf->b_fnum;
bufref->br_buf_free_count = buf_free_count;
}
/*
* Return TRUE if "bufref->br_buf" points to a valid buffer.
* Return TRUE if "bufref->br_buf" points to the same buffer as when
* set_bufref() was called and it is a valid buffer.
* Only goes through the buffer list if buf_free_count changed.
* Also checks if b_fnum is still the same, a :bwipe followed by :new might get
* the same allocated memory, but it's a different buffer.
*/
int
bufref_valid(bufref_T *bufref)
{
return bufref->br_buf_free_count == buf_free_count
? TRUE : buf_valid(bufref->br_buf);
? TRUE : buf_valid(bufref->br_buf)
&& bufref->br_fnum == bufref->br_buf->b_fnum;
}
/*
@@ -2261,14 +2266,14 @@ free_buf_options(
}
/*
* get alternate file n
* set linenr to lnum or altfpos.lnum if lnum == 0
* also set cursor column to altfpos.col if 'startofline' is not set.
* Get alternate file "n".
* Set linenr to "lnum" or altfpos.lnum if "lnum" == 0.
* Also set cursor column to altfpos.col if 'startofline' is not set.
* if (options & GETF_SETMARK) call setpcmark()
* if (options & GETF_ALT) we are jumping to an alternate file.
* if (options & GETF_SWITCH) respect 'switchbuf' settings when jumping
*
* return FAIL for failure, OK for success
* Return FAIL for failure, OK for success.
*/
int
buflist_getfile(
@@ -2999,7 +3004,7 @@ buflist_findlnum(buf_T *buf)
#if defined(FEAT_LISTCMDS) || defined(PROTO)
/*
* List all know file names (for :files and :buffers command).
* List all known file names (for :files and :buffers command).
*/
void
buflist_list(exarg_T *eap)

View File

@@ -385,7 +385,7 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
/* When deleting the current buffer, another one must be loaded. If we know
* which one is preferred, au_new_curbuf is set to it */
EXTERN bufref_T au_new_curbuf INIT(= {NULL COMMA 0});
EXTERN bufref_T au_new_curbuf INIT(= {NULL COMMA 0 COMMA 0});
/* When deleting a buffer/window and autocmd_busy is TRUE, do not free the
* buffer/window. but link it in the list starting with

View File

@@ -4311,7 +4311,7 @@ restore_win_for_buf(
static int
SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
{
bufref_T save_curbuf = {NULL, 0};
bufref_T save_curbuf = {NULL, 0, 0};
win_T *save_curwin = NULL;
tabpage_T *save_curtab = NULL;
@@ -4415,7 +4415,7 @@ SetBufferLineList(
PyObject *list,
PyInt *len_change)
{
bufref_T save_curbuf = {NULL, 0};
bufref_T save_curbuf = {NULL, 0, 0};
win_T *save_curwin = NULL;
tabpage_T *save_curtab = NULL;
@@ -4616,7 +4616,7 @@ SetBufferLineList(
static int
InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
{
bufref_T save_curbuf = {NULL, 0};
bufref_T save_curbuf = {NULL, 0, 0};
win_T *save_curwin = NULL;
tabpage_T *save_curtab = NULL;

View File

@@ -8986,7 +8986,7 @@ nv_esc(cmdarg_T *cap)
#endif
&& !VIsual_active
&& no_reason)
MSG(_("Type :quit<Enter> to exit Vim"));
MSG(_("Type :qa! and press <Enter> to abandon all changes and exit Vim"));
/* Don't reset "restart_edit" when 'insertmode' is set, it won't be
* set again below when halfway a mapping. */

View File

@@ -118,10 +118,10 @@ struct efm_S
static efm_T *fmt_start = NULL; /* cached across qf_parse_line() calls */
static int qf_init_ext(qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc);
static void qf_store_title(qf_info_T *qi, char_u *title);
static void qf_store_title(qf_info_T *qi, int qf_idx, char_u *title);
static void qf_new_list(qf_info_T *qi, char_u *qf_title);
static void ll_free_all(qf_info_T **pqi);
static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid);
static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid);
static qf_info_T *ll_new_list(void);
static void qf_free(qf_info_T *qi, int idx);
static char_u *qf_types(int, int);
@@ -161,8 +161,8 @@ static qf_info_T *ll_get_or_alloc_list(win_T *);
* Looking up a buffer can be slow if there are many. Remember the last one
* to make this a lot faster if there are multiple matches in the same file.
*/
static char_u *qf_last_bufname = NULL;
static bufref_T qf_last_bufref = {NULL, 0};
static char_u *qf_last_bufname = NULL;
static bufref_T qf_last_bufref = {NULL, 0, 0};
/*
* Read the errorfile "efile" into memory, line by line, building the error
@@ -1277,6 +1277,7 @@ qf_init_ext(
continue;
if (qf_add_entry(qi,
qi->qf_curlist,
qi->qf_directory,
(*fields.namebuf || qi->qf_directory != NULL)
? fields.namebuf
@@ -1344,13 +1345,13 @@ qf_init_end:
}
static void
qf_store_title(qf_info_T *qi, char_u *title)
qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
{
if (title != NULL)
{
char_u *p = alloc((int)STRLEN(title) + 2);
qi->qf_lists[qi->qf_curlist].qf_title = p;
qi->qf_lists[qf_idx].qf_title = p;
if (p != NULL)
sprintf((char *)p, ":%s", (char *)title);
}
@@ -1386,7 +1387,7 @@ qf_new_list(qf_info_T *qi, char_u *qf_title)
else
qi->qf_curlist = qi->qf_listcount++;
vim_memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T)));
qf_store_title(qi, qf_title);
qf_store_title(qi, qi->qf_curlist, qf_title);
}
/*
@@ -1438,6 +1439,7 @@ qf_free_all(win_T *wp)
static int
qf_add_entry(
qf_info_T *qi, /* quickfix list */
int qf_idx, /* list index */
char_u *dir, /* optional directory name */
char_u *fname, /* file name or NULL */
int bufnum, /* buffer number or zero */
@@ -1488,13 +1490,13 @@ qf_add_entry(
qfp->qf_type = type;
qfp->qf_valid = valid;
lastp = &qi->qf_lists[qi->qf_curlist].qf_last;
if (qi->qf_lists[qi->qf_curlist].qf_count == 0)
lastp = &qi->qf_lists[qf_idx].qf_last;
if (qi->qf_lists[qf_idx].qf_count == 0)
/* first element in the list */
{
qi->qf_lists[qi->qf_curlist].qf_start = qfp;
qi->qf_lists[qi->qf_curlist].qf_ptr = qfp;
qi->qf_lists[qi->qf_curlist].qf_index = 0;
qi->qf_lists[qf_idx].qf_start = qfp;
qi->qf_lists[qf_idx].qf_ptr = qfp;
qi->qf_lists[qf_idx].qf_index = 0;
qfp->qf_prev = NULL;
}
else
@@ -1505,13 +1507,13 @@ qf_add_entry(
qfp->qf_next = NULL;
qfp->qf_cleared = FALSE;
*lastp = qfp;
++qi->qf_lists[qi->qf_curlist].qf_count;
if (qi->qf_lists[qi->qf_curlist].qf_index == 0 && qfp->qf_valid)
++qi->qf_lists[qf_idx].qf_count;
if (qi->qf_lists[qf_idx].qf_index == 0 && qfp->qf_valid)
/* first valid entry */
{
qi->qf_lists[qi->qf_curlist].qf_index =
qi->qf_lists[qi->qf_curlist].qf_count;
qi->qf_lists[qi->qf_curlist].qf_ptr = qfp;
qi->qf_lists[qf_idx].qf_index =
qi->qf_lists[qf_idx].qf_count;
qi->qf_lists[qf_idx].qf_ptr = qfp;
}
return OK;
@@ -1628,6 +1630,7 @@ copy_loclist(win_T *from, win_T *to)
++i, from_qfp = from_qfp->qf_next)
{
if (qf_add_entry(to->w_llist,
to->w_llist->qf_curlist,
NULL,
NULL,
0,
@@ -2732,7 +2735,7 @@ qf_history(exarg_T *eap)
}
/*
* Free error list "idx".
* Free all the entries in the error list "idx".
*/
static void
qf_free(qf_info_T *qi, int idx)
@@ -4240,6 +4243,7 @@ ex_vimgrep(exarg_T *eap)
* dummy buffer, unless duplicate_name is set, then the
* buffer will be wiped out below. */
if (qf_add_entry(qi,
qi->qf_curlist,
NULL, /* dir */
fname,
duplicate_name ? 0 : buf->b_fnum,
@@ -4744,6 +4748,7 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
static int
qf_add_entries(
qf_info_T *qi,
int qf_idx,
list_T *list,
char_u *title,
int action)
@@ -4762,18 +4767,21 @@ qf_add_entries(
int retval = OK;
int did_bufnr_emsg = FALSE;
if (action == ' ' || qi->qf_curlist == qi->qf_listcount)
if (action == ' ' || qf_idx == qi->qf_listcount)
{
/* make place for a new list */
qf_new_list(qi, title);
qf_idx = qi->qf_curlist;
}
#ifdef FEAT_WINDOWS
else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0)
else if (action == 'a' && qi->qf_lists[qf_idx].qf_count > 0)
/* Adding to existing list, use last entry. */
old_last = qi->qf_lists[qi->qf_curlist].qf_last;
old_last = qi->qf_lists[qf_idx].qf_last;
#endif
else if (action == 'r')
{
qf_free(qi, qi->qf_curlist);
qf_store_title(qi, title);
qf_free(qi, qf_idx);
qf_store_title(qi, qf_idx, title);
}
for (li = list->lv_first; li != NULL; li = li->li_next)
@@ -4819,6 +4827,7 @@ qf_add_entries(
valid = (int)get_dict_number(d, (char_u *)"valid");
status = qf_add_entry(qi,
qf_idx,
NULL, /* dir */
filename,
bufnum,
@@ -4843,17 +4852,17 @@ qf_add_entries(
}
}
if (qi->qf_lists[qi->qf_curlist].qf_index == 0)
if (qi->qf_lists[qf_idx].qf_index == 0)
/* no valid entry */
qi->qf_lists[qi->qf_curlist].qf_nonevalid = TRUE;
qi->qf_lists[qf_idx].qf_nonevalid = TRUE;
else
qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
qi->qf_lists[qf_idx].qf_nonevalid = FALSE;
if (action != 'a')
{
qi->qf_lists[qi->qf_curlist].qf_ptr =
qi->qf_lists[qi->qf_curlist].qf_start;
if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
qi->qf_lists[qi->qf_curlist].qf_index = 1;
qi->qf_lists[qf_idx].qf_ptr =
qi->qf_lists[qf_idx].qf_start;
if (qi->qf_lists[qf_idx].qf_count > 0)
qi->qf_lists[qf_idx].qf_index = 1;
}
#ifdef FEAT_WINDOWS
@@ -4881,7 +4890,9 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action)
/* Use the specified quickfix/location list */
if (di->di_tv.v_type == VAR_NUMBER)
{
qf_idx = di->di_tv.vval.v_number - 1;
/* for zero use the current list */
if (di->di_tv.vval.v_number != 0)
qf_idx = di->di_tv.vval.v_number - 1;
if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
return FAIL;
}
@@ -4912,11 +4923,11 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action)
if ((di = dict_find(what, (char_u *)"context", -1)) != NULL)
{
typval_T *ctx;
free_tv(qi->qf_lists[qi->qf_curlist].qf_ctx);
free_tv(qi->qf_lists[qf_idx].qf_ctx);
ctx = alloc_tv();
if (ctx != NULL)
copy_tv(&di->di_tv, ctx);
qi->qf_lists[qi->qf_curlist].qf_ctx = ctx;
qi->qf_lists[qf_idx].qf_ctx = ctx;
}
return retval;
@@ -5022,7 +5033,7 @@ set_errorlist(
else if (what != NULL)
retval = qf_set_properties(qi, what, action);
else
retval = qf_add_entries(qi, list, title, action);
retval = qf_add_entries(qi, qi->qf_curlist, list, title, action);
return retval;
}
@@ -5385,6 +5396,7 @@ ex_helpgrep(exarg_T *eap)
line[--l] = NUL;
if (qf_add_entry(qi,
qi->qf_curlist,
NULL, /* dir */
fnames[fi],
0,

View File

@@ -69,11 +69,13 @@ typedef struct frame_S frame_T;
typedef int scid_T; /* script ID */
typedef struct file_buffer buf_T; /* forward declaration */
/* Reference to a buffer that stores the value of buf_free_count.
/*
* Reference to a buffer that stores the value of buf_free_count.
* bufref_valid() only needs to check "buf" when the count differs.
*/
typedef struct {
buf_T *br_buf;
int br_fnum;
int br_buf_free_count;
} bufref_T;

View File

@@ -4385,14 +4385,20 @@ check_termcode(
if (i - j >= 21 && STRNCMP(tp + j + 3, "rgb:", 4) == 0
&& tp[j + 11] == '/' && tp[j + 16] == '/'
&& !option_was_set((char_u *)"bg"))
{/* TODO: don't set option when already the right value */
{
char *newval = (3 * '6' < tp[j+7] + tp[j+12]
+ tp[j+17]) ? "light" : "dark";
LOG_TR("Received RBG");
rbg_status = RBG_GOT;
set_option_value((char_u *)"bg", 0L, (char_u *)(
(3 * '6' < tp[j+7] + tp[j+12] + tp[j+17])
? "light" : "dark"), 0);
reset_option_was_set((char_u *)"bg");
redraw_asap(CLEAR);
if (STRCMP(p_bg, newval) != 0)
{
/* value differs, apply it */
set_option_value((char_u *)"bg", 0L,
(char_u *)newval, 0);
reset_option_was_set((char_u *)"bg");
redraw_asap(CLEAR);
}
}
/* got finished code: consume it */

View File

@@ -1804,6 +1804,37 @@ func Xproperty_tests(cchar)
call setloclist(0, [], 'f')
call assert_equal({}, getloclist(0, {'context':1}))
endif
" Test for changing the context of previous quickfix lists
call g:Xsetlist([], 'f')
Xexpr "One"
Xexpr "Two"
Xexpr "Three"
call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1})
call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2})
" Also, check for setting the context using quickfix list number zero.
call g:Xsetlist([], ' ', {'context' : [3], 'nr' : 0})
call test_garbagecollect_now()
let l = g:Xgetlist({'nr' : 1, 'context' : 1})
call assert_equal([1], l.context)
let l = g:Xgetlist({'nr' : 2, 'context' : 1})
call assert_equal([2], l.context)
let l = g:Xgetlist({'nr' : 3, 'context' : 1})
call assert_equal([3], l.context)
" Test for changing the context through reference and for garbage
" collection of quickfix context
let l = ["red"]
call g:Xsetlist([], ' ', {'context' : l})
call add(l, "blue")
let x = g:Xgetlist({'context' : 1})
call add(x.context, "green")
call assert_equal(["red", "blue", "green"], l)
call assert_equal(["red", "blue", "green"], x.context)
unlet l
call test_garbagecollect_now()
let m = g:Xgetlist({'context' : 1})
call assert_equal(["red", "blue", "green"], m.context)
endfunc
func Test_qf_property()
@@ -2073,3 +2104,19 @@ func Test_qf_free()
call XfreeTests('c')
call XfreeTests('l')
endfunc
" Test for buffer overflow when parsing lines and adding new entries to
" the quickfix list.
func Test_bufoverflow()
set efm=%f:%l:%m
cgetexpr ['File1:100:' . repeat('x', 1025)]
set efm=%+GCompiler:\ %.%#,%f:%l:%m
cgetexpr ['Compiler: ' . repeat('a', 1015), 'File1:10:Hello World']
set efm=%DEntering\ directory\ %f,%f:%l:%m
cgetexpr ['Entering directory ' . repeat('a', 1006),
\ 'File1:10:Hello World']
set efm&vim
endfunc

View File

@@ -764,6 +764,16 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
610,
/**/
609,
/**/
608,
/**/
607,
/**/
606,
/**/
605,
/**/