# HG changeset patch # User Bram Moolenaar # Date 1383711975 -3600 # Node ID d0595545e98a3b7b6fe1a96ab0106d8afd63c31e # Parent 75c7eef1de70880f7a2653f49e53f5317e6b12c5 updated for version 7.4.073 Problem: Setting undolevels for one buffer changes undo in another. Solution: Make 'undolevels' a global-local option. (Christian Brabandt) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7594,7 +7594,7 @@ A jump table for the options with a shor *'undolevels'* *'ul'* 'undolevels' 'ul' number (default 100, 1000 for Unix, VMS, Win32 and OS/2) - global + global or local to buffer |global-local| {not in Vi} Maximum number of changes that can be undone. Since undo information is kept in memory, higher numbers will cause more memory to be used @@ -7605,8 +7605,9 @@ A jump table for the options with a shor < But you can also get Vi compatibility by including the 'u' flag in 'cpoptions', and still be able to use CTRL-R to repeat undo. Also see |undo-two-ways|. - Set to a negative number for no undo at all: > - set ul=-1 + Set to -1 for no undo at all. You might want to do this only for the + current buffer: > + setlocal ul=-1 < This helps when you run out of memory for a single change. Also see |clear-undo|. diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -1949,6 +1949,7 @@ free_buf_options(buf, free_p_ff) clear_string_option(&buf->b_p_qe); #endif buf->b_p_ar = -1; + buf->b_p_ul = NO_LOCAL_UNDOLEVEL; } /* diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -234,6 +234,7 @@ #ifdef FEAT_STL_OPT # define PV_STL OPT_BOTH(OPT_WIN(WV_STL)) #endif +#define PV_UL OPT_BOTH(OPT_BUF(BV_UL)) #ifdef FEAT_WINDOWS # define PV_WFH OPT_WIN(WV_WFH) #endif @@ -2683,7 +2684,7 @@ static struct vimoption #endif {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {"undolevels", "ul", P_NUM|P_VI_DEF, - (char_u *)&p_ul, PV_NONE, + (char_u *)&p_ul, PV_UL, { #if defined(UNIX) || defined(WIN3264) || defined(OS2) || defined(VMS) (char_u *)1000L, @@ -3313,6 +3314,7 @@ set_init_1() curbuf->b_p_initialized = TRUE; curbuf->b_p_ar = -1; /* no local 'autoread' value */ + curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL; check_buf_options(curbuf); check_win_options(curwin); check_options(); @@ -4512,8 +4514,16 @@ do_set(arg, opt_flags) ((flags & P_VI_DEF) || cp_val) ? VI_DEFAULT : VIM_DEFAULT]; else if (nextchar == '<') - value = *(long *)get_varp_scope(&(options[opt_idx]), - OPT_GLOBAL); + { + /* For 'undolevels' NO_LOCAL_UNDOLEVEL means to + * use the global value. */ + if ((long *)varp == &curbuf->b_p_ul + && opt_flags == OPT_LOCAL) + value = NO_LOCAL_UNDOLEVEL; + else + value = *(long *)get_varp_scope( + &(options[opt_idx]), OPT_GLOBAL); + } else if (((long *)varp == &p_wc || (long *)varp == &p_wcm) && (*arg == '<' @@ -8487,6 +8497,13 @@ set_num_option(opt_idx, varp, value, err u_sync(TRUE); p_ul = value; } + else if (pp == &curbuf->b_p_ul) + { + /* use the old value, otherwise u_sync() may not work properly */ + curbuf->b_p_ul = old_value; + u_sync(TRUE); + curbuf->b_p_ul = value; + } #ifdef FEAT_LINEBREAK /* 'numberwidth' must be positive */ @@ -9720,7 +9737,6 @@ comp_col() /* * Unset local option value, similar to ":set opt<". */ - void unset_global_local_option(name, from) char_u *name; @@ -9793,6 +9809,9 @@ unset_global_local_option(name, from) clear_string_option(&((win_T *)from)->w_p_stl); break; #endif + case PV_UL: + buf->b_p_ul = NO_LOCAL_UNDOLEVEL; + break; } } @@ -9841,6 +9860,7 @@ get_varp_scope(p, opt_flags) #ifdef FEAT_STL_OPT case PV_STL: return (char_u *)&(curwin->w_p_stl); #endif + case PV_UL: return (char_u *)&(curbuf->b_p_ul); } return NULL; /* "cannot happen" */ } @@ -9905,6 +9925,8 @@ get_varp(p) case PV_STL: return *curwin->w_p_stl != NUL ? (char_u *)&(curwin->w_p_stl) : p->var; #endif + case PV_UL: return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL + ? (char_u *)&(curbuf->b_p_ul) : p->var; #ifdef FEAT_ARABIC case PV_ARAB: return (char_u *)&(curwin->w_p_arab); @@ -10445,6 +10467,7 @@ buf_copy_options(buf, flags) /* options that are normally global but also have a local value * are not copied, start using the global value */ buf->b_p_ar = -1; + buf->b_p_ul = NO_LOCAL_UNDOLEVEL; #ifdef FEAT_QUICKFIX buf->b_p_gp = empty_option; buf->b_p_mp = empty_option; diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -1031,6 +1031,7 @@ enum , BV_TW , BV_TX , BV_UDF + , BV_UL , BV_WM , BV_COUNT /* must be the last one */ }; @@ -1109,3 +1110,6 @@ enum , WV_WRAP , WV_COUNT /* must be the last one */ }; + +/* Value for b_p_ul indicating the global value must be used. */ +#define NO_LOCAL_UNDOLEVEL -123456 diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1627,6 +1627,7 @@ struct file_buffer char_u *b_p_dict; /* 'dictionary' local value */ char_u *b_p_tsr; /* 'thesaurus' local value */ #endif + long b_p_ul; /* 'undolevels' local value */ #ifdef FEAT_PERSISTENT_UNDO int b_p_udf; /* 'undofile' */ #endif diff --git a/src/undo.c b/src/undo.c --- a/src/undo.c +++ b/src/undo.c @@ -83,6 +83,7 @@ #include "vim.h" +static long get_undolevel __ARGS((void)); static void u_unch_branch __ARGS((u_header_T *uhp)); static u_entry_T *u_get_headentry __ARGS((void)); static void u_getbot __ARGS((void)); @@ -336,6 +337,17 @@ undo_allowed() } /* + * Get the undolevle value for the current buffer. + */ + static long +get_undolevel() +{ + if (curbuf->b_p_ul == NO_LOCAL_UNDOLEVEL) + return p_ul; + return curbuf->b_p_ul; +} + +/* * Common code for various ways to save text before a change. * "top" is the line above the first changed line. * "bot" is the line below the last changed line. @@ -419,7 +431,7 @@ u_savecommon(top, bot, newbot, reload) curbuf->b_new_change = TRUE; #endif - if (p_ul >= 0) + if (get_undolevel() >= 0) { /* * Make a new header entry. Do this first so that we don't mess @@ -449,7 +461,8 @@ u_savecommon(top, bot, newbot, reload) /* * free headers to keep the size right */ - while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL) + while (curbuf->b_u_numhead > get_undolevel() + && curbuf->b_u_oldhead != NULL) { u_header_T *uhfree = curbuf->b_u_oldhead; @@ -530,7 +543,7 @@ u_savecommon(top, bot, newbot, reload) } else { - if (p_ul < 0) /* no undo at all */ + if (get_undolevel() < 0) /* no undo at all */ return OK; /* @@ -1972,7 +1985,7 @@ u_doit(startcount) { if (curbuf->b_u_curhead == NULL) /* first undo */ curbuf->b_u_curhead = curbuf->b_u_newhead; - else if (p_ul > 0) /* multi level undo */ + else if (get_undolevel() > 0) /* multi level undo */ /* get next undo */ curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr; /* nothing to undo */ @@ -1993,7 +2006,7 @@ u_doit(startcount) } else { - if (curbuf->b_u_curhead == NULL || p_ul <= 0) + if (curbuf->b_u_curhead == NULL || get_undolevel() <= 0) { beep_flush(); /* nothing to redo */ if (count == startcount - 1) @@ -2751,7 +2764,7 @@ u_sync(force) if (im_is_preediting()) return; /* XIM is busy, don't break an undo sequence */ #endif - if (p_ul < 0) + if (get_undolevel() < 0) curbuf->b_u_synced = TRUE; /* no entries, nothing to do */ else { @@ -2911,7 +2924,7 @@ ex_undojoin(eap) } if (!curbuf->b_u_synced) return; /* already unsynced */ - if (p_ul < 0) + if (get_undolevel() < 0) return; /* no entries, nothing to do */ else { diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 73, +/**/ 72, /**/ 71,