Compare commits

...

7 Commits

Author SHA1 Message Date
Bram Moolenaar
2459a5ecaa updated for version 7.4.609
Problem:    For complicated list and dict use the garbage collector can run
            out of stack space.
Solution:   Use a stack of dicts and lists to be marked, thus making it
            iterative instead of recursive. (Ben Fritz)
2015-02-03 12:55:18 +01:00
Bram Moolenaar
4ac163ae5f updated for version 7.4.608
Problem:    test_eval fails when the clipboard feature is missing.
Solution:   Skip part of the test. Reduce the text used.
2015-01-27 22:52:15 +01:00
Bram Moolenaar
73a156bf36 updated for version 7.4.607
Problem:    Compiler warnings for unused variables.
Solution:   Move them inside #ifdef. (Kazunobu Kuriyama)
2015-01-27 21:39:05 +01:00
Bram Moolenaar
7cc8ec4720 updated for version 7.4.606
Problem:    May crash when using a small window.
Solution:   Avoid dividing by zero. (Christian Brabandt)
2015-01-27 20:59:31 +01:00
Bram Moolenaar
3b3a9498d1 updated for version 7.4.605
Problem:    The # register is not writable, it cannot be restored after
            jumping around.
Solution:   Make the # register writable. (Marcin Szamotulski)
2015-01-27 18:44:16 +01:00
Bram Moolenaar
6bf7c523ad updated for version 7.4.604
Problem:    Running tests changes viminfo.
Solution:   Disable viminfo.
2015-01-27 17:12:00 +01:00
Bram Moolenaar
1c93429c48 updated for version 7.4.603
Problem:    'foldcolumn' may be set such that it fills the whole window, not
            leaving space for text.
Solution:   Reduce the foldcolumn width when there is not sufficient room.
            (idea by Christian Brabandt)
2015-01-27 16:39:29 +01:00
21 changed files with 356 additions and 126 deletions

View File

@@ -1,4 +1,4 @@
*change.txt* For Vim version 7.4. Last change: 2014 Jun 26
*change.txt* For Vim version 7.4. Last change: 2015 Jan 27
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1103,11 +1103,12 @@ There are nine types of registers: *registers* *E354*
2. 10 numbered registers "0 to "9
3. The small delete register "-
4. 26 named registers "a to "z or "A to "Z
5. four read-only registers ":, "., "% and "#
6. the expression register "=
7. The selection and drop registers "*, "+ and "~
8. The black hole register "_
9. Last search pattern register "/
5. three read-only registers ":, "., "%
7. alternate buffer register "#
7. the expression register "=
8. The selection and drop registers "*, "+ and "~
9. The black hole register "_
10. Last search pattern register "/
1. Unnamed register "" *quote_quote* *quotequote*
Vim fills this register with text deleted with the "d", "c", "s", "x" commands
@@ -1153,7 +1154,7 @@ letters to replace their previous contents or as uppercase letters to append
to their previous contents. When the '>' flag is present in 'cpoptions' then
a line break is inserted before the appended text.
5. Read-only registers ":, "., "% and "#
5. Read-only registers ":, ". and "%
These are '%', '#', ':' and '.'. You can use them only with the "p", "P",
and ":put" commands and with CTRL-R. {not in Vi}
*quote_.* *quote.* *E29*
@@ -1164,8 +1165,6 @@ and ":put" commands and with CTRL-R. {not in Vi}
('textwidth' and other options affect what is inserted).
*quote_%* *quote%*
"% Contains the name of the current file.
*quote_#* *quote#*
"# Contains the name of the alternate file.
*quote_:* *quote:* *E30*
": Contains the most recent executed command-line. Example: Use
"@:" to repeat the previous command-line command.
@@ -1174,8 +1173,23 @@ and ":put" commands and with CTRL-R. {not in Vi}
the command was completely from a mapping.
{not available when compiled without the |+cmdline_hist|
feature}
*quote_#* *quote#*
6. Alternate file register "#
Contains the name of the alternate file for the current window. It will
change how the |CTRL-^| command works.
This register is writable, mainly to allow for restoring it after a plugin has
changed it. It accepts buffer number: >
let altbuf = bufnr(@#)
...
let @# = altbuf
It will give error |E86| if you pass buffer number and this buffer does not
exist.
It can also accept a match with an existing buffer name: >
let @# = 'buffer_name'
Error |E93| if there is more than one buffer matching the given name or |E94|
if none of buffers matches the given name.
6. Expression register "= *quote_=* *quote=* *@=*
7. Expression register "= *quote_=* *quote=* *@=*
This is not really a register that stores text, but is a way to use an
expression in commands which use a register. The expression register is
read-only; you cannot put text into it. After the '=', the cursor moves to
@@ -1196,7 +1210,7 @@ If the "= register is used for the "p" command, the String is split up at <NL>
characters. If the String ends in a <NL>, it is regarded as a linewise
register. {not in Vi}
7. Selection and drop registers "*, "+ and "~
8. Selection and drop registers "*, "+ and "~
Use these registers for storing and retrieving the selected text for the GUI.
See |quotestar| and |quoteplus|. When the clipboard is not available or not
working, the unnamed register is used instead. For Unix systems the clipboard
@@ -1218,12 +1232,12 @@ GTK GUI}
Note: The "~ register is only used when dropping plain text onto Vim.
Drag'n'drop of URI lists is handled internally.
8. Black hole register "_ *quote_*
9. Black hole register "_ *quote_*
When writing to this register, nothing happens. This can be used to delete
text without affecting the normal registers. When reading from this register,
nothing is returned. {not in Vi}
9. Last search pattern register "/ *quote_/* *quote/*
10. Last search pattern register "/ *quote_/* *quote/*
Contains the most recent search-pattern. This is used for "n" and 'hlsearch'.
It is writable with `:let`, you can change it to have 'hlsearch' highlight
other matches without actually searching. You can't yank or delete into this

View File

@@ -1150,7 +1150,7 @@ do_buffer(action, start, dir, count, forceit)
{
/* don't warn when deleting */
if (!unload)
EMSGN(_("E86: Buffer %ld does not exist"), count);
EMSGN(_(e_nobufnr), count);
}
else if (dir == FORWARD)
EMSG(_("E87: Cannot go beyond last buffer"));

View File

@@ -93,7 +93,6 @@ typedef struct lval_S
char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
} lval_T;
static char *e_letunexp = N_("E18: Unexpected characters in :let");
static char *e_listidx = N_("E684: list index out of range: %ld");
static char *e_undefvar = N_("E121: Undefined variable: %s");
@@ -6811,6 +6810,7 @@ list_join(gap, l, sep, echo_style, copyID)
garbage_collect()
{
int copyID;
int abort = FALSE;
buf_T *buf;
win_T *wp;
int i;
@@ -6841,82 +6841,95 @@ garbage_collect()
* the item is referenced elsewhere the funccal must not be freed. */
for (fc = previous_funccal; fc != NULL; fc = fc->caller)
{
set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1);
set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1);
abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1,
NULL);
abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1,
NULL);
}
/* script-local variables */
for (i = 1; i <= ga_scripts.ga_len; ++i)
set_ref_in_ht(&SCRIPT_VARS(i), copyID);
abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL);
/* buffer-local variables */
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
set_ref_in_item(&buf->b_bufvar.di_tv, copyID);
abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID,
NULL, NULL);
/* window-local variables */
FOR_ALL_TAB_WINDOWS(tp, wp)
set_ref_in_item(&wp->w_winvar.di_tv, copyID);
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
NULL, NULL);
#ifdef FEAT_AUTOCMD
if (aucmd_win != NULL)
set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID);
abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
NULL, NULL);
#endif
#ifdef FEAT_WINDOWS
/* tabpage-local variables */
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
set_ref_in_item(&tp->tp_winvar.di_tv, copyID);
abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID,
NULL, NULL);
#endif
/* global variables */
set_ref_in_ht(&globvarht, copyID);
abort = abort || set_ref_in_ht(&globvarht, copyID, NULL);
/* function-local variables */
for (fc = current_funccal; fc != NULL; fc = fc->caller)
{
set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL);
abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL);
}
/* v: vars */
set_ref_in_ht(&vimvarht, copyID);
abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL);
#ifdef FEAT_LUA
set_ref_in_lua(copyID);
abort = abort || set_ref_in_lua(copyID);
#endif
#ifdef FEAT_PYTHON
set_ref_in_python(copyID);
abort = abort || set_ref_in_python(copyID);
#endif
#ifdef FEAT_PYTHON3
set_ref_in_python3(copyID);
abort = abort || set_ref_in_python3(copyID);
#endif
/*
* 2. Free lists and dictionaries that are not referenced.
*/
did_free = free_unref_items(copyID);
/*
* 3. Check if any funccal can be freed now.
*/
for (pfc = &previous_funccal; *pfc != NULL; )
if (!abort)
{
if (can_free_funccal(*pfc, copyID))
/*
* 2. Free lists and dictionaries that are not referenced.
*/
did_free = free_unref_items(copyID);
/*
* 3. Check if any funccal can be freed now.
*/
for (pfc = &previous_funccal; *pfc != NULL; )
{
fc = *pfc;
*pfc = fc->caller;
free_funccal(fc, TRUE);
did_free = TRUE;
did_free_funccal = TRUE;
if (can_free_funccal(*pfc, copyID))
{
fc = *pfc;
*pfc = fc->caller;
free_funccal(fc, TRUE);
did_free = TRUE;
did_free_funccal = TRUE;
}
else
pfc = &(*pfc)->caller;
}
else
pfc = &(*pfc)->caller;
if (did_free_funccal)
/* When a funccal was freed some more items might be garbage
* collected, so run again. */
(void)garbage_collect();
}
else if (p_verbose > 0)
{
verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!"));
}
if (did_free_funccal)
/* When a funccal was freed some more items might be garbage
* collected, so run again. */
(void)garbage_collect();
return did_free;
}
@@ -6976,48 +6989,112 @@ free_unref_items(copyID)
/*
* Mark all lists and dicts referenced through hashtab "ht" with "copyID".
* "list_stack" is used to add lists to be marked. Can be NULL.
*
* Returns TRUE if setting references failed somehow.
*/
void
set_ref_in_ht(ht, copyID)
hashtab_T *ht;
int copyID;
int
set_ref_in_ht(ht, copyID, list_stack)
hashtab_T *ht;
int copyID;
list_stack_T **list_stack;
{
int todo;
int abort = FALSE;
hashitem_T *hi;
hashtab_T *cur_ht;
ht_stack_T *ht_stack = NULL;
ht_stack_T *tempitem;
todo = (int)ht->ht_used;
for (hi = ht->ht_array; todo > 0; ++hi)
if (!HASHITEM_EMPTY(hi))
cur_ht = ht;
for (;;)
{
if (!abort)
{
--todo;
set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
/* Mark each item in the hashtab. If the item contains a hashtab
* it is added to ht_stack, if it contains a list it is added to
* list_stack. */
todo = (int)cur_ht->ht_used;
for (hi = cur_ht->ht_array; todo > 0; ++hi)
if (!HASHITEM_EMPTY(hi))
{
--todo;
abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID,
&ht_stack, list_stack);
}
}
if (ht_stack == NULL)
break;
/* take an item from the stack */
cur_ht = ht_stack->ht;
tempitem = ht_stack;
ht_stack = ht_stack->prev;
free(tempitem);
}
return abort;
}
/*
* Mark all lists and dicts referenced through list "l" with "copyID".
* "ht_stack" is used to add hashtabs to be marked. Can be NULL.
*
* Returns TRUE if setting references failed somehow.
*/
void
set_ref_in_list(l, copyID)
int
set_ref_in_list(l, copyID, ht_stack)
list_T *l;
int copyID;
ht_stack_T **ht_stack;
{
listitem_T *li;
listitem_T *li;
int abort = FALSE;
list_T *cur_l;
list_stack_T *list_stack = NULL;
list_stack_T *tempitem;
for (li = l->lv_first; li != NULL; li = li->li_next)
set_ref_in_item(&li->li_tv, copyID);
cur_l = l;
for (;;)
{
if (!abort)
/* Mark each item in the list. If the item contains a hashtab
* it is added to ht_stack, if it contains a list it is added to
* list_stack. */
for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next)
abort = abort || set_ref_in_item(&li->li_tv, copyID,
ht_stack, &list_stack);
if (list_stack == NULL)
break;
/* take an item from the stack */
cur_l = list_stack->list;
tempitem = list_stack;
list_stack = list_stack->prev;
free(tempitem);
}
return abort;
}
/*
* Mark all lists and dicts referenced through typval "tv" with "copyID".
* "list_stack" is used to add lists to be marked. Can be NULL.
* "ht_stack" is used to add hashtabs to be marked. Can be NULL.
*
* Returns TRUE if setting references failed somehow.
*/
void
set_ref_in_item(tv, copyID)
typval_T *tv;
int copyID;
int
set_ref_in_item(tv, copyID, ht_stack, list_stack)
typval_T *tv;
int copyID;
ht_stack_T **ht_stack;
list_stack_T **list_stack;
{
dict_T *dd;
list_T *ll;
int abort = FALSE;
switch (tv->v_type)
{
@@ -7027,7 +7104,23 @@ set_ref_in_item(tv, copyID)
{
/* Didn't see this dict yet. */
dd->dv_copyID = copyID;
set_ref_in_ht(&dd->dv_hashtab, copyID);
if (ht_stack == NULL)
{
abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack);
}
else
{
ht_stack_T *newitem = (ht_stack_T*)malloc(
sizeof(ht_stack_T));
if (newitem == NULL)
abort = TRUE;
else
{
newitem->ht = &dd->dv_hashtab;
newitem->prev = *ht_stack;
*ht_stack = newitem;
}
}
}
break;
@@ -7037,11 +7130,27 @@ set_ref_in_item(tv, copyID)
{
/* Didn't see this list yet. */
ll->lv_copyID = copyID;
set_ref_in_list(ll, copyID);
if (list_stack == NULL)
{
abort = set_ref_in_list(ll, copyID, ht_stack);
}
else
{
list_stack_T *newitem = (list_stack_T*)malloc(
sizeof(list_stack_T));
if (newitem == NULL)
abort = TRUE;
else
{
newitem->list = ll;
newitem->prev = *list_stack;
*list_stack = newitem;
}
}
}
break;
}
return;
return abort;
}
/*

View File

@@ -1571,6 +1571,7 @@ EXTERN char_u e_nbreadonly[] INIT(= N_("E744: NetBeans does not allow changes in
EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
EXTERN char_u e_maxmempat[] INIT(= N_("E363: pattern uses more memory than 'maxmempattern'"));
EXTERN char_u e_emptybuf[] INIT(= N_("E749: empty buffer"));
EXTERN char_u e_nobufnr[] INIT(= N_("E86: Buffer %ld does not exist"));
#ifdef FEAT_EX_EXTRA
EXTERN char_u e_invalpat[] INIT(= N_("E682: Invalid search pattern or delimiter"));

View File

@@ -1523,12 +1523,14 @@ luaV_luaeval (lua_State *L)
static int
luaV_setref (lua_State *L)
{
int copyID = lua_tointeger(L, 1);
typval_T tv;
int copyID = lua_tointeger(L, 1);
int abort = FALSE;
typval_T tv;
luaV_getfield(L, LUAVIM_LIST);
luaV_getfield(L, LUAVIM_DICT);
lua_pushnil(L);
while (lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
while (!abort && lua_next(L, lua_upvalueindex(1)) != 0) /* traverse cache table */
{
lua_getmetatable(L, -1);
if (lua_rawequal(L, -1, 2)) /* list? */
@@ -1542,9 +1544,9 @@ luaV_setref (lua_State *L)
tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
}
lua_pop(L, 2); /* metatable and value */
set_ref_in_item(&tv, copyID);
abort = set_ref_in_item(&tv, copyID, NULL, NULL);
}
return 0;
lua_pushinteger(L, abort);
}
static int
@@ -1770,13 +1772,23 @@ do_luaeval (char_u *str, typval_T *arg, typval_T *rettv)
lua_call(L, 3, 0);
}
void
int
set_ref_in_lua (int copyID)
{
if (!lua_isopen()) return;
luaV_getfield(L, LUAVIM_SETREF);
lua_pushinteger(L, copyID);
lua_call(L, 1, 0);
int aborted = 0;
if (lua_isopen())
{
luaV_getfield(L, LUAVIM_SETREF);
/* call the function with 1 arg, getting 1 result back */
lua_pushinteger(L, copyID);
lua_call(L, 1, 1);
/* get the result */
aborted = lua_tointeger(L, -1);
/* pop result off the stack */
lua_pop(L, 1);
}
return aborted;
}
#endif

View File

@@ -5502,34 +5502,41 @@ run_eval(const char *cmd, typval_T *rettv
PyErr_Clear();
}
static void
static int
set_ref_in_py(const int copyID)
{
pylinkedlist_T *cur;
dict_T *dd;
list_T *ll;
int abort = FALSE;
if (lastdict != NULL)
for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
{
for(cur = lastdict ; !abort && cur != NULL ; cur = cur->pll_prev)
{
dd = ((DictionaryObject *) (cur->pll_obj))->dict;
if (dd->dv_copyID != copyID)
{
dd->dv_copyID = copyID;
set_ref_in_ht(&dd->dv_hashtab, copyID);
abort = abort || set_ref_in_ht(&dd->dv_hashtab, copyID, NULL);
}
}
}
if (lastlist != NULL)
for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
{
for(cur = lastlist ; !abort && cur != NULL ; cur = cur->pll_prev)
{
ll = ((ListObject *) (cur->pll_obj))->list;
if (ll->lv_copyID != copyID)
{
ll->lv_copyID = copyID;
set_ref_in_list(ll, copyID);
abort = abort || set_ref_in_list(ll, copyID, NULL);
}
}
}
return abort;
}
static int

View File

@@ -1567,8 +1567,8 @@ Py_GetProgramName(void)
}
#endif /* Python 1.4 */
void
int
set_ref_in_python (int copyID)
{
set_ref_in_py(copyID);
return set_ref_in_py(copyID);
}

View File

@@ -1649,8 +1649,8 @@ do_py3eval (char_u *str, typval_T *rettv)
}
}
void
int
set_ref_in_python3 (int copyID)
{
set_ref_in_py(copyID);
int set_ref_in_py(copyID);
}

View File

@@ -4457,6 +4457,8 @@ nv_screengo(oap, dir, dist)
col_off2 = col_off1 - curwin_col_off2();
width1 = W_WIDTH(curwin) - col_off1;
width2 = W_WIDTH(curwin) - col_off2;
if (width2 == 0)
width2 = 1; /* avoid divide by zero */
#ifdef FEAT_VERTSPLIT
if (curwin->w_width != 0)

View File

@@ -856,11 +856,12 @@ valid_yank_reg(regname, writing)
if ( (regname > 0 && ASCII_ISALNUM(regname))
|| (!writing && vim_strchr((char_u *)
#ifdef FEAT_EVAL
"/.%#:="
"/.%:="
#else
"/.%#:"
"/.%:"
#endif
, regname) != NULL)
|| regname == '#'
|| regname == '"'
|| regname == '-'
|| regname == '_'
@@ -6514,6 +6515,27 @@ write_reg_contents_ex(name, str, maxlen, must_append, yank_type, block_len)
return;
}
if (name == '#')
{
buf_T *buf;
if (VIM_ISDIGIT(*str))
{
int num = atoi((char *)str);
buf = buflist_findnr(num);
if (buf == NULL)
EMSGN(_(e_nobufnr), (long)num);
}
else
buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
TRUE, FALSE, FALSE));
if (buf == NULL)
return;
curwin->w_alt_fnum = buf->b_fnum;
return;
}
#ifdef FEAT_EVAL
if (name == '=')
{

View File

@@ -62,9 +62,9 @@ int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
void list_insert __ARGS((list_T *l, listitem_T *ni, listitem_T *item));
void vimlist_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
int garbage_collect __ARGS((void));
void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
void set_ref_in_list __ARGS((list_T *l, int copyID));
void set_ref_in_item __ARGS((typval_T *tv, int copyID));
int set_ref_in_ht __ARGS((hashtab_T *ht, int copyID, list_stack_T **list_stack));
int set_ref_in_list __ARGS((list_T *l, int copyID, ht_stack_T **ht_stack));
int set_ref_in_item __ARGS((typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack));
dict_T *dict_alloc __ARGS((void));
void dict_unref __ARGS((dict_T *d));
void dict_free __ARGS((dict_T *d, int recurse));

View File

@@ -7,5 +7,5 @@ void ex_luafile __ARGS((exarg_T *eap));
void lua_buffer_free __ARGS((buf_T *buf));
void lua_window_free __ARGS((win_T *win));
void do_luaeval __ARGS((char_u *str, typval_T *arg, typval_T *rettv));
void set_ref_in_lua __ARGS((int copyID));
int set_ref_in_lua __ARGS((int copyID));
/* vim: set ft=c : */

View File

@@ -9,5 +9,5 @@ void python_buffer_free __ARGS((buf_T *buf));
void python_window_free __ARGS((win_T *win));
void python_tabpage_free __ARGS((tabpage_T *tab));
void do_pyeval __ARGS((char_u *str, typval_T *rettv));
void set_ref_in_python __ARGS((int copyID));
int set_ref_in_python __ARGS((int copyID));
/* vim: set ft=c : */

View File

@@ -9,5 +9,5 @@ void python3_buffer_free __ARGS((buf_T *buf));
void python3_window_free __ARGS((win_T *win));
void python3_tabpage_free __ARGS((tabpage_T *tab));
void do_py3eval __ARGS((char_u *str, typval_T *rettv));
void set_ref_in_python3 __ARGS((int copyID));
int set_ref_in_python3 __ARGS((int copyID));
/* vim: set ft=c : */

View File

@@ -109,6 +109,7 @@ static match_T search_hl; /* used for 'hlsearch' highlight matching */
#ifdef FEAT_FOLDING
static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
static int compute_foldcolumn __ARGS((win_T *wp, int col));
#endif
/*
@@ -1202,7 +1203,7 @@ win_update(wp)
lnumb = wp->w_lines[i].wl_lnum;
/* When there is a fold column it might need updating
* in the next line ("J" just above an open fold). */
if (wp->w_p_fdc > 0)
if (compute_foldcolumn(wp, 0) > 0)
++lnumb;
}
}
@@ -2238,13 +2239,16 @@ win_draw_end(wp, c1, c2, row, endrow, hl)
#else
# define FDC_OFF 0
#endif
#ifdef FEAT_FOLDING
int fdc = compute_foldcolumn(wp, 0);
#endif
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
{
/* No check for cmdline window: should never be right-left. */
# ifdef FEAT_FOLDING
n = wp->w_p_fdc;
n = fdc;
if (n > 0)
{
@@ -2293,9 +2297,9 @@ win_draw_end(wp, c1, c2, row, endrow, hl)
}
#endif
#ifdef FEAT_FOLDING
if (wp->w_p_fdc > 0)
if (fdc > 0)
{
int nn = n + wp->w_p_fdc;
int nn = n + fdc;
/* draw the fold column at the left */
if (nn > W_WIDTH(wp))
@@ -2345,6 +2349,24 @@ advance_color_col(vcol, color_cols)
#endif
#ifdef FEAT_FOLDING
/*
* Compute the width of the foldcolumn. Based on 'foldcolumn' and how much
* space is available for window "wp", minus "col".
*/
static int
compute_foldcolumn(wp, col)
win_T *wp;
int col;
{
int fdc = wp->w_p_fdc;
int wmw = wp == curwin && p_wmw == 0 ? 1 : p_wmw;
int wwidth = W_WIDTH(wp);
if (fdc > wwidth - (col + wmw))
fdc = wwidth - (col + wmw);
return fdc;
}
/*
* Display one folded line.
*/
@@ -2396,10 +2418,9 @@ fold_line(wp, fold_count, foldinfo, lnum, row)
/*
* 2. Add the 'foldcolumn'
* Reduce the width when there is not enough space.
*/
fdc = wp->w_p_fdc;
if (fdc > W_WIDTH(wp) - col)
fdc = W_WIDTH(wp) - col;
fdc = compute_foldcolumn(wp, col);
if (fdc > 0)
{
fill_foldcolumn(buf, wp, TRUE, lnum);
@@ -2787,23 +2808,24 @@ fill_foldcolumn(p, wp, closed, lnum)
int level;
int first_level;
int empty;
int fdc = compute_foldcolumn(wp, 0);
/* Init to all spaces. */
copy_spaces(p, (size_t)wp->w_p_fdc);
copy_spaces(p, (size_t)fdc);
level = win_foldinfo.fi_level;
if (level > 0)
{
/* If there is only one column put more info in it. */
empty = (wp->w_p_fdc == 1) ? 0 : 1;
empty = (fdc == 1) ? 0 : 1;
/* If the column is too narrow, we start at the lowest level that
* fits and use numbers to indicated the depth. */
first_level = level - wp->w_p_fdc - closed + 1 + empty;
first_level = level - fdc - closed + 1 + empty;
if (first_level < 1)
first_level = 1;
for (i = 0; i + empty < wp->w_p_fdc; ++i)
for (i = 0; i + empty < fdc; ++i)
{
if (win_foldinfo.fi_lnum == lnum
&& first_level + i >= win_foldinfo.fi_low_level)
@@ -2819,7 +2841,7 @@ fill_foldcolumn(p, wp, closed, lnum)
}
}
if (closed)
p[i >= wp->w_p_fdc ? i - 1 : i] = '+';
p[i >= fdc ? i - 1 : i] = '+';
}
#endif /* FEAT_FOLDING */
@@ -3556,12 +3578,14 @@ win_line(wp, lnum, startrow, endrow, nochange)
#ifdef FEAT_FOLDING
if (draw_state == WL_FOLD - 1 && n_extra == 0)
{
int fdc = compute_foldcolumn(wp, 0);
draw_state = WL_FOLD;
if (wp->w_p_fdc > 0)
if (fdc > 0)
{
/* Draw the 'foldcolumn'. */
fill_foldcolumn(extra, wp, FALSE, lnum);
n_extra = wp->w_p_fdc;
n_extra = fdc;
p_extra = extra;
p_extra[n_extra] = NUL;
c_extra = NUL;

View File

@@ -1223,6 +1223,20 @@ struct dictvar_S
dict_T *dv_used_prev; /* previous dict in used dicts list */
};
/* structure used for explicit stack while garbage collecting hash tables */
typedef struct ht_stack_S
{
hashtab_T *ht;
struct ht_stack_S *prev;
} ht_stack_T;
/* structure used for explicit stack while garbage collecting lists */
typedef struct list_stack_S
{
list_T *list;
struct list_stack_S *prev;
} list_stack_T;
/* values for b_syn_spell: what to do with toplevel text */
#define SYNSPL_DEFAULT 0 /* spell check if @Spell not defined */
#define SYNSPL_TOP 1 /* spell check toplevel text */

View File

@@ -100,7 +100,7 @@ fygjyl:let line2 = @0
:$put =line2
:"
:let g:test="Test 14: breakindent + visual blockwise delete #1"
:set all& breakindent
:set all& breakindent viminfo+=nviminfo
:30vnew
:normal! 3a1234567890
:normal! a abcde

View File

@@ -2,13 +2,19 @@ Test for various eval features. vim: set ft=vim :
Note: system clipboard is saved, changed and restored.
clipboard contents
something else
STARTTEST
:so small.vim
:set encoding=latin1
:set noswapfile
:lang C
:fun AppendRegContents(reg)
call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', a:reg, getregtype(a:reg), getreg(a:reg), string(getreg(a:reg, 0, 1)), getreg(a:reg, 1), string(getreg(a:reg, 1, 1))))
call AppendRegParts(a:reg, getregtype(a:reg), getreg(a:reg), string(getreg(a:reg, 0, 1)), getreg(a:reg, 1), string(getreg(a:reg, 1, 1)))
:endfun
:fun AppendRegParts(reg, type, cont, strcont, cont1, strcont1)
call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', a:reg, a:type, a:cont, a:strcont, a:cont1, a:strcont1))
endfun
:command -nargs=? AR :call AppendRegContents(<q-args>)
:fun SetReg(...)
@@ -122,18 +128,23 @@ call SetReg('/', ["abc/\n"])
call SetReg('=', ['"abc/"'])
call SetReg('=', ["\"abc/\n\""])
$put ='{{{1 System clipboard'
if has('clipboard')
" Save and restore system clipboard.
" If no connection to X-Server is possible, test should succeed.
:let _clipreg = ['+', getreg('+'), getregtype('+')]
:let _clipopt = &cb
:let &cb='unnamedplus'
:1y
:AR +
:tabdo :windo :echo "hi"
:3y
:AR +
:let &cb=_clipopt
:call call('setreg', _clipreg)
let _clipreg = ['+', getreg('+'), getregtype('+')]
let _clipopt = &cb
let &cb='unnamedplus'
5y
AR +
tabdo :windo :echo "hi"
6y
AR +
let &cb=_clipopt
call call('setreg', _clipreg)
else
call AppendRegParts('+', 'V', "clipboard contents\n", "['clipboard contents']", "clipboard contents\n", "['clipboard contents']")
call AppendRegParts('+', 'V', "something else\n", "['something else']", "something else\n", "['something else']")
endif
$put ='{{{1 Errors'
call ErrExe('call setreg()')
call ErrExe('call setreg(1)')

Binary file not shown.

View File

@@ -73,8 +73,6 @@ ui_write(s, len)
static char_u *ta_str = NULL;
static int ta_off; /* offset for next char to use when ta_str != NULL */
static int ta_len; /* length of ta_str when it's not NULL*/
static int clipboard_needs_update; /* clipboard needs to be updated */
static int global_change_count = 0; /* if set, inside a start_global_changes */
void
ui_inchar_undo(s, len)
@@ -564,6 +562,8 @@ clip_copy_selection(clip)
* prevents accessing the clipboard very often which might slow down Vim
* considerably.
*/
static int global_change_count = 0; /* if set, inside a start_global_changes */
static int clipboard_needs_update; /* clipboard needs to be updated */
/*
* Save clip_unnamed and reset it.

View File

@@ -741,6 +741,20 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
609,
/**/
608,
/**/
607,
/**/
606,
/**/
605,
/**/
604,
/**/
603,
/**/
602,
/**/