From a00fea679dd3fd76ada4b261339047e2e979333a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 30 May 2010 13:26:21 +0200 Subject: [PATCH 1/5] A few more fixes for undo file. Split test in two parts so that it doesn't fail with tiny features. --HG-- branch : vim73 --- runtime/doc/todo.txt | 1 + src/auto/configure | 43 +++++++++++++++++++++++++++ src/config.h.in | 3 ++ src/configure.in | 23 +++++++++++++++ src/misc2.c | 17 ++++++----- src/testdir/Make_amiga.mak | 6 +++- src/testdir/Make_dos.mak | 2 +- src/testdir/Make_ming.mak | 2 +- src/testdir/Make_os2.mak | 3 +- src/testdir/Make_vms.mms | 3 +- src/testdir/Makefile | 2 +- src/testdir/test61.in | 47 ----------------------------- src/testdir/test61.ok | 9 ------ src/testdir/test72.in | 60 ++++++++++++++++++++++++++++++++++++++ src/testdir/test72.ok | 9 ++++++ src/undo.c | 5 ++-- 16 files changed, 163 insertions(+), 72 deletions(-) create mode 100644 src/testdir/test72.in create mode 100644 src/testdir/test72.ok diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index bde8146be0..9dc6a022f4 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1093,6 +1093,7 @@ Vim 7.3: Use register_shell_extension()? (George Reilly, 2010 May 26) Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi - Persistent undo bugs / fixes: + - check for sizeof(time_t) results in compiler warning in misc2.c - Memory leak reproduced by Dominique Pelle, 2010 May 28. - When there is no undo info (undolevels negative), delete the undo file. - Need to check all values for evil manipulation. diff --git a/src/auto/configure b/src/auto/configure index 34de4f3c50..77dea5de99 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -11238,6 +11238,49 @@ cat >>confdefs.h <<_ACEOF _ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 +$as_echo_n "checking size of time_t... " >&6; } +if test "${ac_cv_sizeof_time_t+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + as_fn_error "failed to compile test program" "$LINENO" 5 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#if STDC_HEADERS +# include +# include +#endif +#include +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", (int)sizeof(time_t)); + exit(0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_sizeof_time_t=`cat conftestval` +else + as_fn_error "failed to determine sizeof(time_t)" "$LINENO" 5 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 +$as_echo "$ac_cv_sizeof_time_t" >&6; } +cat >>confdefs.h <<_ACEOF +#define SIZEOF_TIME_T $ac_cv_sizeof_time_t +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking uint32_t is 32 bits" >&5 $as_echo_n "checking uint32_t is 32 bits... " >&6; } if test "$cross_compiling" = yes; then : diff --git a/src/config.h.in b/src/config.h.in index c57cd2fa48..1099531513 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -39,6 +39,9 @@ /* Defined to the size of an int */ #undef SIZEOF_INT +/* Defined to the size of time_t */ +#undef SIZEOF_TIME_T + /* Define when wchar_t is only 2 bytes. */ #undef SMALL_WCHAR_T diff --git a/src/configure.in b/src/configure.in index 1d8cb09e1b..35ecde3b82 100644 --- a/src/configure.in +++ b/src/configure.in @@ -2988,6 +2988,29 @@ main() AC_MSG_RESULT($ac_cv_sizeof_int) AC_DEFINE_UNQUOTED(SIZEOF_INT, $ac_cv_sizeof_int) +dnl Figure out sizeof(time_t) so that it can be used in #ifdef. +AC_MSG_CHECKING(size of time_t) +AC_CACHE_VAL(ac_cv_sizeof_time_t, + [AC_TRY_RUN([ +#include +#if STDC_HEADERS +# include +# include +#endif +#include +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", (int)sizeof(time_t)); + exit(0); +}], + ac_cv_sizeof_time_t=`cat conftestval`, + AC_MSG_ERROR([failed to determine sizeof(time_t)]), + AC_MSG_ERROR([failed to compile test program]))]) +AC_MSG_RESULT($ac_cv_sizeof_time_t) +AC_DEFINE_UNQUOTED(SIZEOF_TIME_T, $ac_cv_sizeof_time_t) + dnl Make sure that uint32_t is really 32 bits unsigned. AC_MSG_CHECKING([uint32_t is 32 bits]) AC_TRY_RUN([ diff --git a/src/misc2.c b/src/misc2.c index f5bad9c871..f35019df67 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -6260,9 +6260,10 @@ put_time(fd, the_time) /* time_t can be up to 8 bytes in size, more than long_u, thus we * can't use put_bytes() here. * Another problem is that ">>" may do an arithmetic shift that keeps the - * sign. A cast to long_u may truncate if time_t is 8 bytes. So only use - * a cast when it is 4 bytes, it's safe to assume that long_u is 4 bytes - * or more and when using 8 bytes the top bit won't be set. */ + * sign. This happens for large values of wtime. A cast to long_u may + * truncate if time_t is 8 bytes. So only use a cast when it is 4 bytes, + * it's safe to assume that long_u is 4 bytes or more and when using 8 + * bytes the top bit won't be set. */ for (i = 7; i >= 0; --i) { if (i + 1 > (int)sizeof(time_t)) @@ -6270,11 +6271,11 @@ put_time(fd, the_time) putc(0, fd); else { - /* use "i" in condition to avoid compiler warning */ - if (i >= 0 && sizeof(time_t) > 4) - c = wtime >> (i * 8); - else - c = (long_u)wtime >> (i * 8); +#if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4 + c = wtime >> (i * 8); +#else + c = (long_u)wtime >> (i * 8); +#endif putc(c, fd); } } diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak index 96215c00a0..bc9638c2f6 100644 --- a/src/testdir/Make_amiga.mak +++ b/src/testdir/Make_amiga.mak @@ -26,7 +26,8 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \ test48.out test51.out test53.out test54.out test55.out \ test56.out test57.out test58.out test59.out test60.out \ test61.out test62.out test63.out test64.out test65.out \ - test66.out test67.out test68.out test69.out + test66.out test67.out test68.out test69.out test70.out \ + test71.out test72.out .SUFFIXES: .in .out @@ -115,3 +116,6 @@ test66.out: test66.in test67.out: test67.in test68.out: test68.in test69.out: test69.in +test70.out: test70.in +test71.out: test71.in +test72.out: test72.in diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak index 4b1af5f861..6deca3d640 100644 --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -27,7 +27,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \ test30.out test31.out test32.out test33.out test34.out \ test37.out test38.out test39.out test40.out test41.out \ test42.out test52.out test65.out test66.out test67.out \ - test68.out test69.out test71.out + test68.out test69.out test71.out test72.out SCRIPTS32 = test50.out test70.out diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak index 960f5b209a..0024a4eeb1 100644 --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -46,7 +46,7 @@ SCRIPTS = test3.out test4.out test5.out test6.out test7.out \ test30.out test31.out test32.out test33.out test34.out \ test37.out test38.out test39.out test40.out test41.out \ test42.out test52.out test65.out test66.out test67.out \ - test68.out test69.out test71.out + test68.out test69.out test71.out test72.out SCRIPTS32 = test50.out test70.out diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak index 426fb23325..ccbdb3e911 100644 --- a/src/testdir/Make_os2.mak +++ b/src/testdir/Make_os2.mak @@ -26,7 +26,8 @@ SCRIPTS = test1.out test3.out test4.out test5.out test6.out \ test48.out test51.out test53.out test54.out test55.out \ test56.out test57.out test58.out test59.out test60.out \ test61.out test62.out test63.out test64.out test65.out \ - test66.out test67.out test68.out test69.out + test66.out test67.out test68.out test69.out test70.out \ + test71.out test72.out .SUFFIXES: .in .out diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index acd5c658e0..afeb9fad84 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -69,7 +69,8 @@ SCRIPT = test1.out test2.out test3.out test4.out test5.out \ test48.out test51.out test53.out test54.out test55.out \ test56.out test57.out test60.out \ test61.out test62.out test63.out test64.out test65.out \ - test66.out test67.out test68.out test69.out + test66.out test67.out test68.out test69.out test70.out \ + test71.out test72.out .IFDEF WANT_GUI SCRIPT_GUI = test16.out diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 53e085469e..f970b26b82 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -23,7 +23,7 @@ SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \ test54.out test55.out test56.out test57.out test58.out \ test59.out test60.out test61.out test62.out test63.out \ test64.out test65.out test66.out test67.out test68.out \ - test69.out test70.out test71.out + test69.out test70.out test71.out test72.out SCRIPTS_GUI = test16.out diff --git a/src/testdir/test61.in b/src/testdir/test61.in index 909d1230c2..7ce72e627f 100644 --- a/src/testdir/test61.in +++ b/src/testdir/test61.in @@ -50,53 +50,6 @@ obbbbu:.w >>test.out obbbb:set ul=100 :undojoin occccu:.w >>test.out -:" -:" Test 'undofile': first a simple one-line change. -:set nocp ul=100 undofile -:e! Xtestfile -ggdGithis is one line:set ul=100 -:s/one/ONE/ -:set ul=100 -:w -:bwipe! -:e Xtestfile -u:.w >>test.out -:" -:" Test 'undofile', change in original file fails check -:set noundofile -:e! Xtestfile -:s/line/Line/ -:w -:set undofile -:bwipe! -:e Xtestfile -u:.w >>test.out -:" -:" Test 'undofile', add 10 lines, delete 6 lines, undo 3 -:set undofile -ggdGione -two -three -four -five -six -seven -eight -nine -ten:set ul=100 -3Gdd:set ul=100 -dd:set ul=100 -dd:set ul=100 -dd:set ul=100 -dd:set ul=100 -dd:set ul=100 -:w -:bwipe! -:e Xtestfile -uuu:w >>test.out -:" -:" Rename the undo file so that it gets cleaned up. -:call rename(".Xtestfile.un~", "Xtestundo") :qa! ENDTEST diff --git a/src/testdir/test61.ok b/src/testdir/test61.ok index ea88c07c36..020dd5383b 100644 --- a/src/testdir/test61.ok +++ b/src/testdir/test61.ok @@ -22,12 +22,3 @@ 123456abc aaaa aaaa -this is one line -this is ONE Line -one -two -six -seven -eight -nine -ten diff --git a/src/testdir/test72.in b/src/testdir/test72.in new file mode 100644 index 0000000000..a5674b5272 --- /dev/null +++ b/src/testdir/test72.in @@ -0,0 +1,60 @@ +Tests for undo file. +Since this script is sourced we need to explicitly break changes up in +undo-able pieces. Do that by setting 'undolevels'. + +STARTTEST +:so small.vim +:" +:" Test 'undofile': first a simple one-line change. +:set nocp ul=100 undofile +:e! Xtestfile +ggdGithis is one line:set ul=100 +:s/one/ONE/ +:set ul=100 +:w +:bwipe! +:e Xtestfile +u:.w! test.out +:" +:" Test 'undofile', change in original file fails check +:set noundofile +:e! Xtestfile +:s/line/Line/ +:w +:set undofile +:bwipe! +:e Xtestfile +u:.w >>test.out +:" +:" Test 'undofile', add 10 lines, delete 6 lines, undo 3 +:set undofile +ggdGione +two +three +four +five +six +seven +eight +nine +ten:set ul=100 +3Gdd:set ul=100 +dd:set ul=100 +dd:set ul=100 +dd:set ul=100 +dd:set ul=100 +dd:set ul=100 +:w +:bwipe! +:e Xtestfile +uuu:w >>test.out +:" +:" Rename the undo file so that it gets cleaned up. +:call rename(".Xtestfile.un~", "Xtestundo") +:qa! +ENDTEST + +1111 ----- +2222 ----- + +123456789 diff --git a/src/testdir/test72.ok b/src/testdir/test72.ok new file mode 100644 index 0000000000..66e7250df6 --- /dev/null +++ b/src/testdir/test72.ok @@ -0,0 +1,9 @@ +this is one line +this is ONE Line +one +two +six +seven +eight +nine +ten diff --git a/src/undo.c b/src/undo.c index 958c6d2dea..5b04986250 100644 --- a/src/undo.c +++ b/src/undo.c @@ -858,6 +858,8 @@ unserialize_uep(fp, error, file_name) } vim_memset(array, 0, sizeof(char_u *) * uep->ue_size); } + else + array = NULL; uep->ue_array = array; for (i = 0; i < uep->ue_size; ++i) @@ -1365,7 +1367,6 @@ u_read_undo(name, hash) if (num_read_uhps >= num_head) { corruption_error("num_head", file_name); - u_free_uhp(uhp); goto error; } @@ -1442,7 +1443,7 @@ u_read_undo(name, hash) * culling was done at undofile write time, and there can be uh_seq * gaps in the uhps. */ - for (i = num_read_uhps - 1; i >= -1; i--) + for (i = num_read_uhps - 1; ; --i) { /* if i == -1, we've hit the leftmost side of the table, so insert * at uhp_table[0]. */ From b98973fcbc7d9b63f51c12c8b23f8de4f4380e98 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 30 May 2010 16:01:37 +0200 Subject: [PATCH 2/5] A bit of cleanup and simplification for undofile. --HG-- branch : vim73 --- runtime/doc/message.txt | 2 +- runtime/doc/todo.txt | 2 +- src/feature.h | 2 +- src/structs.h | 20 ------------ src/undo.c | 69 ++++++++++++++++++----------------------- 5 files changed, 34 insertions(+), 61 deletions(-) diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index 32689d81d8..1026815405 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -19,7 +19,7 @@ The ":messages" command can be used to view previously given messages. This is especially useful when messages have been overwritten or truncated. This depends on the 'shortmess' option. -The number of remembered messages is fixed at 20 for the tiny version and 100 +The number of remembered messages is fixed at 20 for the tiny version and 200 for other versions. *g<* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 9dc6a022f4..dd55ae3e95 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1093,9 +1093,9 @@ Vim 7.3: Use register_shell_extension()? (George Reilly, 2010 May 26) Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi - Persistent undo bugs / fixes: - - check for sizeof(time_t) results in compiler warning in misc2.c - Memory leak reproduced by Dominique Pelle, 2010 May 28. - When there is no undo info (undolevels negative), delete the undo file. + Already done? - Need to check all values for evil manipulation. - Add undofile(name): get undo file name for buffer "name". - patch for unused functions. (Dominique Pelle, 2010 May 29) diff --git a/src/feature.h b/src/feature.h index 61fe3345bb..e786e282ef 100644 --- a/src/feature.h +++ b/src/feature.h @@ -130,7 +130,7 @@ * Message history is fixed at 100 message, 20 for the tiny version. */ #ifdef FEAT_SMALL -# define MAX_MSG_HIST_LEN 100 +# define MAX_MSG_HIST_LEN 200 #else # define MAX_MSG_HIST_LEN 20 #endif diff --git a/src/structs.h b/src/structs.h index a7632b8517..2ec02f3db7 100644 --- a/src/structs.h +++ b/src/structs.h @@ -341,18 +341,6 @@ struct m_info minfo_T *m_next; /* pointer to next free chunk in the list */ }; -/* - * structure used to link blocks in the list of allocated blocks. - */ -typedef struct m_block mblock_T; -struct m_block -{ - mblock_T *mb_next; /* pointer to next allocated block */ - size_t mb_size; /* total size of all chunks in this block */ - size_t mb_maxsize; /* size of largest fee chunk */ - minfo_T mb_info; /* head of free chunk list for this block */ -}; - /* * things used in memfile.c */ @@ -1286,14 +1274,6 @@ struct file_buffer linenr_T b_u_line_lnum; /* line number of line in u_line */ colnr_T b_u_line_colnr; /* optional column number */ - /* - * The following only used in undo.c - */ - mblock_T b_block_head; /* head of allocated memory block list */ - minfo_T *b_m_search; /* pointer to chunk before previously - allocated/freed chunk */ - mblock_T *b_mb_current; /* block where m_search points in */ - #ifdef FEAT_INS_EXPAND int b_scanned; /* ^N/^P have scanned this buffer */ #endif diff --git a/src/undo.c b/src/undo.c index 5b04986250..7f1aa8ad87 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1075,6 +1075,11 @@ u_write_undo(name, forceit, buf, hash) if (p_verbose > 0) smsg((char_u *)_("Writing undo file: %s"), file_name); +#ifdef U_DEBUG + /* Check if there already is a problem before writing. */ + u_check(FALSE); +#endif + #ifdef UNIX /* * Try to set the group of the undo file same as the original file. If @@ -1103,6 +1108,9 @@ u_write_undo(name, forceit, buf, hash) goto theend; } + /* Undo must be synced. */ + u_sync(TRUE); + /* Start writing, first the undo file header. */ if (fwrite(UF_START_MAGIC, (size_t)UF_START_MAGIC_LEN, (size_t)1, fp) != 1) goto write_error; @@ -1359,7 +1367,6 @@ u_read_undo(name, hash) num_head * sizeof(u_header_T *)); if (uhp_table == NULL) goto error; - vim_memset(uhp_table, 0, num_head * sizeof(u_header_T *)); } while ((c = get2c(fp)) == UF_HEADER_MAGIC) @@ -1436,37 +1443,13 @@ u_read_undo(name, hash) goto error; } - /* Insertion sort the uhp into the table by its uh_seq. This is - * required because, while the number of uhps is limited to - * num_head, and the uh_seq order is monotonic with respect to - * creation time, the starting uh_seq can be > 0 if any undolevel - * culling was done at undofile write time, and there can be uh_seq - * gaps in the uhps. - */ - for (i = num_read_uhps - 1; ; --i) - { - /* if i == -1, we've hit the leftmost side of the table, so insert - * at uhp_table[0]. */ - if (i == -1 || uhp->uh_seq > uhp_table[i]->uh_seq) - { - /* If we've had to move from the rightmost side of the table, - * we have to shift everything to the right by one spot. */ - if (num_read_uhps - i - 1 > 0) - { - memmove(uhp_table + i + 2, uhp_table + i + 1, - (num_read_uhps - i - 1) * sizeof(u_header_T *)); - } - uhp_table[i + 1] = uhp; - break; - } - else if (uhp->uh_seq == uhp_table[i]->uh_seq) - { - corruption_error("duplicate uh_seq", file_name); - u_free_uhp(uhp); - goto error; - } - } - num_read_uhps++; + uhp_table[num_read_uhps++] = uhp; + } + + if (num_read_uhps != num_head) + { + corruption_error("num_head", file_name); + goto error; } if (c != UF_HEADER_END_MAGIC) @@ -1483,11 +1466,9 @@ u_read_undo(name, hash) # define SET_FLAG(j) #endif - /* We've organized all of the uhps into a table sorted by uh_seq. Now we - * iterate through the table and swizzle each sequence number we've - * stored in uh_* into a pointer corresponding to the header with that - * sequence number. Then free curbuf's old undo structure, give curbuf - * the updated {old,new,cur}head pointers, and then free the table. */ + /* We have put all of the uhps into a table. Now we iterate through the + * table and swizzle each sequence number we've stored in uh_* into a + * pointer corresponding to the header with that sequence number. */ for (i = 0; i < num_head; i++) { uhp = uhp_table[i]; @@ -1497,6 +1478,12 @@ u_read_undo(name, hash) { if (uhp_table[j] == NULL) continue; + if (i != j && uhp_table[i]->uh_seq == uhp_table[j]->uh_seq) + { + corruption_error("duplicate uh_seq", file_name); + goto error; + } + if (uhp_table[j]->uh_seq == (long)uhp->uh_next) { uhp->uh_next = uhp_table[j]; @@ -1541,6 +1528,10 @@ u_read_undo(name, hash) curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx]; curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx]; curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx]; +#ifdef U_DEBUG + if (curbuf->b_u_curhead != NULL) + corruption_error("curhead not NULL", file_name); +#endif curbuf->b_u_line_ptr = line_ptr; curbuf->b_u_line_lnum = line_lnum; curbuf->b_u_line_colnr = line_colnr; @@ -1548,6 +1539,8 @@ u_read_undo(name, hash) curbuf->b_u_seq_last = seq_last; curbuf->b_u_seq_cur = seq_cur; curbuf->b_u_seq_time = seq_time; + + curbuf->b_u_synced = TRUE; vim_free(uhp_table); #ifdef U_DEBUG @@ -1566,7 +1559,7 @@ error: vim_free(line_ptr); if (uhp_table != NULL) { - for (i = 0; i < num_head; i++) + for (i = 0; i < num_read_uhps; i++) if (uhp_table[i] != NULL) u_free_uhp(uhp_table[i]); vim_free(uhp_table); From f2ba195bf575518b460318dc05f088e800b9e2e2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 30 May 2010 16:55:22 +0200 Subject: [PATCH 3/5] updated for version 7.2.441 Problem: When using ":earlier" undo information may be wrong. Solution: When changing alternate branches also adjust b_u_oldhead. --HG-- branch : vim73 --- src/undo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/undo.c b/src/undo.c index 7f1aa8ad87..cb51c996c2 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1918,6 +1918,8 @@ undo_time(step, sec, absolute) last->uh_alt_next = uhp; uhp->uh_alt_prev = last; + if (curbuf->b_u_oldhead == uhp) + curbuf->b_u_oldhead = last; uhp = last; if (uhp->uh_next != NULL) uhp->uh_next->uh_prev = uhp; From 65d77852bcfcd3854b5c462abbec35816d61bb40 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 30 May 2010 17:17:42 +0200 Subject: [PATCH 4/5] Do not write an undo file if there is nothing to undo. --HG-- branch : vim73 --- runtime/doc/todo.txt | 3 --- src/undo.c | 47 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index dd55ae3e95..f79148f7aa 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1093,9 +1093,6 @@ Vim 7.3: Use register_shell_extension()? (George Reilly, 2010 May 26) Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi - Persistent undo bugs / fixes: - - Memory leak reproduced by Dominique Pelle, 2010 May 28. - - When there is no undo info (undolevels negative), delete the undo file. - Already done? - Need to check all values for evil manipulation. - Add undofile(name): get undo file name for buffer "name". - patch for unused functions. (Dominique Pelle, 2010 May 29) diff --git a/src/undo.c b/src/undo.c index cb51c996c2..88c030565f 100644 --- a/src/undo.c +++ b/src/undo.c @@ -998,7 +998,12 @@ u_write_undo(name, forceit, buf, hash) if (file_name == NULL) { if (p_verbose > 0) - smsg((char_u *)_("Cannot write undo file in any directory in 'undodir'")); + { + verbose_enter(); + smsg((char_u *) + _("Cannot write undo file in any directory in 'undodir'")); + verbose_leave(); + } return; } } @@ -1040,8 +1045,15 @@ u_write_undo(name, forceit, buf, hash) if (fd < 0) { if (name != NULL || p_verbose > 0) - smsg((char_u *)_("Will not overwrite with undo file, cannot read: %s"), + { + if (name == NULL) + verbose_enter(); + smsg((char_u *) + _("Will not overwrite with undo file, cannot read: %s"), file_name); + if (name == NULL) + verbose_leave(); + } goto theend; } else @@ -1055,8 +1067,14 @@ u_write_undo(name, forceit, buf, hash) || memcmp(buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) { if (name != NULL || p_verbose > 0) + { + if (name == NULL) + verbose_enter(); smsg((char_u *)_("Will not overwrite, this is not an undo file: %s"), file_name); + if (name == NULL) + verbose_leave(); + } goto theend; } } @@ -1064,6 +1082,15 @@ u_write_undo(name, forceit, buf, hash) mch_remove(file_name); } + /* If there is no undo information at all, quit here after deleting any + * existing undo file. */ + if (buf->b_u_numhead == 0) + { + if (p_verbose > 0) + verb_msg((char_u *)_("Skipping undo file write, noting to undo")); + goto theend; + } + fd = mch_open((char *)file_name, O_CREAT|O_EXTRA|O_WRONLY|O_EXCL|O_NOFOLLOW, perm); if (fd < 0) @@ -1073,10 +1100,14 @@ u_write_undo(name, forceit, buf, hash) } (void)mch_setperm(file_name, perm); if (p_verbose > 0) + { + verbose_enter(); smsg((char_u *)_("Writing undo file: %s"), file_name); + verbose_leave(); + } #ifdef U_DEBUG - /* Check if there already is a problem before writing. */ + /* Check there is no problem in undo info before writing. */ u_check(FALSE); #endif @@ -1290,7 +1321,11 @@ u_read_undo(name, hash) file_name = name; if (p_verbose > 0) + { + verbose_enter(); smsg((char_u *)_("Reading undo file: %s"), file_name); + verbose_leave(); + } fp = mch_fopen((char *)file_name, "r"); if (fp == NULL) { @@ -1326,9 +1361,11 @@ u_read_undo(name, hash) { if (p_verbose > 0 || name != NULL) { - verbose_enter(); + if (name == NULL) + verbose_enter(); give_warning((char_u *)_("File contents changed, cannot use undo info"), TRUE); - verbose_leave(); + if (name == NULL) + verbose_leave(); } goto error; } From cc32c43b5eb10d4c317235bb99800d8b90ebb563 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 30 May 2010 18:30:36 +0200 Subject: [PATCH 5/5] Added the undofile() function. Updated runtime files. --HG-- branch : vim73 --- runtime/compiler/gcc.vim | 6 +++++- runtime/doc/eval.txt | 10 ++++++++++ runtime/doc/mbyte.txt | 6 +++--- runtime/doc/message.txt | 1 + runtime/doc/os_os2.txt | 3 ++- runtime/doc/print.txt | 2 +- runtime/doc/syntax.txt | 3 ++- runtime/doc/tags | 1 + runtime/doc/todo.txt | 5 ----- runtime/doc/undo.txt | 20 +++++++++++++++++--- runtime/doc/workshop.txt | 10 +++++----- runtime/syntax/yaml.vim | 4 ++-- src/eval.c | 19 +++++++++++++++++++ src/proto/undo.pro | 3 ++- src/undo.c | 3 +-- 15 files changed, 71 insertions(+), 25 deletions(-) diff --git a/runtime/compiler/gcc.vim b/runtime/compiler/gcc.vim index 75c596c7ef..776bdee292 100644 --- a/runtime/compiler/gcc.vim +++ b/runtime/compiler/gcc.vim @@ -1,7 +1,7 @@ " Vim compiler file " Compiler: GNU C Compiler " Maintainer: Nikolai Weibull -" Latest Revision: 2009-05-01 +" Latest Revision: 2010-05-30 if exists("current_compiler") finish @@ -18,7 +18,11 @@ CompilerSet errorformat= \\"%f\"%*\\D%l:\ %m, \%-G%f:%l:\ %trror:\ (Each\ undeclared\ identifier\ is\ reported\ only\ once, \%-G%f:%l:\ %trror:\ for\ each\ function\ it\ appears\ in.), + \%f:%l:%c:\ %terror:\ %m, + \%f:%l:%c:\ %tarning:\ %m, \%f:%l:%c:\ %m, + \%f:%l:\ %terror:\ %m, + \%f:%l:\ %tarning:\ %m, \%f:%l:\ %m, \\"%f\"\\,\ line\ %l%*\\D%c%*[^\ ]\ %m, \%D%*\\a[%*\\d]:\ Entering\ directory\ `%f', diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 08b79bb784..4d983bfba3 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1943,6 +1943,7 @@ tr( {src}, {fromstr}, {tostr}) String translate chars of {src} in {fromstr} to chars in {tostr} trunc( {expr} Float truncate Float {expr} type( {name}) Number type of variable {name} +undofile( {name}) String undo file name for {name} values( {dict}) List values in {dict} virtcol( {expr}) Number screen column of cursor or mark visualmode( [expr]) String last visual mode used @@ -5767,6 +5768,15 @@ type({expr}) The result is a Number, depending on the type of {expr}: :if type(myvar) == type({}) :if type(myvar) == type(0.0) +undofile({name}) *undofile()* + Return the name of the undo file that would be used for a file + with name {name} when writing. This uses the 'undodir' + option, finding directories that exist. It does not check if + the undo file exist. + Useful in combination with |:wundo| and |:rundo|. + When compiled without the +persistent_undo option this always + returns an empty string. + values({dict}) *values()* Return a |List| with all the values of {dict}. The |List| is in arbitrary order. diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt index 13dfc5973b..96b5b4dd0e 100644 --- a/runtime/doc/mbyte.txt +++ b/runtime/doc/mbyte.txt @@ -775,7 +775,7 @@ is suitable for complex input, such as CJK. For Chinese, there's a great XIM server named "xcin", you can input both Traditional and Simplified Chinese characters. And it can accept other locale if you make a correct input table. Xcin can be found at: - http://xcin.linux.org.tw/ + http://cle.linux.org.tw/xcin/ Others are scim: http://scim.freedesktop.org/ and fcitx: http://www.fcitx.org/ @@ -963,10 +963,10 @@ WHAT IS GLOBAL IME *global-ime* language version of Global IME at same place. - Global IME detailed information. - http://www.microsoft.com/windows/ie/features/ime.asp + http://search.microsoft.com/results.aspx?q=global+ime - Active Input Method Manager (Global IME) - http://msdn.microsoft.com/workshop/misc/AIMM/aimm.asp + http://msdn.microsoft.com/en-us/library/aa741221(v=VS.85).aspx Support for Global IME is an experimental feature. diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index 1026815405..6bf8580fed 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -585,6 +585,7 @@ when using ":w"), therefore Vim requires using a ! after the command, e.g.: Messages like this appear when starting up. This is not a Vim problem, your X11 configuration is wrong. You can find a hint on how to solve this here: http://groups.yahoo.com/group/solarisonintel/message/12179. +[this URL is no longer valid] *W10* > Warning: Changing a readonly file diff --git a/runtime/doc/os_os2.txt b/runtime/doc/os_os2.txt index b262d6d102..a6c0cf3a98 100644 --- a/runtime/doc/os_os2.txt +++ b/runtime/doc/os_os2.txt @@ -183,7 +183,8 @@ anyway you need an additional tool which gives you access to the clipboard from within a vio application. The freeware package clipbrd.zip by Stefan Gruendel can be used for this purpose. You might download the package including precompiled binaries and all sources from: - http://www.stellarcom.org/vim/index.html + http://www.os2site.com/sw/util/clipboard/index.html + http://download.uni-hd.de/ftp/pub/os2/pmtools/ Installation of this package is straight forward: just put the two executables that come with this package into a directory within your PATH for Vim should diff --git a/runtime/doc/print.txt b/runtime/doc/print.txt index 49b7dfc02d..73a3182a11 100644 --- a/runtime/doc/print.txt +++ b/runtime/doc/print.txt @@ -490,7 +490,7 @@ Traditional Chinese fonts available at: You can find descriptions of the various fonts in the read me file at - http://examples.oreilly.com/cjkvinfo/adobe/00README + http://examples.oreilly.de/english_examples/cjkvinfo/adobe/00README Please read your printer documentation on how to install new fonts. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 229fdd602b..109276f40d 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -828,7 +828,8 @@ startup vimrc: > DESKTOP *desktop.vim* *ft-desktop-syntax* Primary goal of this syntax file is to highlight .desktop and .directory files -according to freedesktop.org standard: http://pdx.freedesktop.org/Standards/ +according to freedesktop.org standard: +http://standards.freedesktop.org/desktop-entry-spec/latest/ But actually almost none implements this standard fully. Thus it will highlight all Unix ini files. But you can force strict highlighting according to standard by placing this in your vimrc file: > diff --git a/runtime/doc/tags b/runtime/doc/tags index 66cc0332dd..7ecb985c89 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7867,6 +7867,7 @@ undo-tree undo.txt /*undo-tree* undo-two-ways undo.txt /*undo-two-ways* undo.txt undo.txt /*undo.txt* undo_ftplugin usr_41.txt /*undo_ftplugin* +undofile() eval.txt /*undofile()* unicode mbyte.txt /*unicode* unix os_unix.txt /*unix* unlisted-buffer windows.txt /*unlisted-buffer* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index f79148f7aa..169d0fb6b1 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -30,10 +30,6 @@ be worked on, but only if you sponsor Vim development. See |sponsor|. *known-bugs* -------------------- Known bugs and current work ----------------------- -Fixes for broken URLs: - Benjamin Haskell, 2010 May 25 - Christian Brabandt, 2010 May 26, two messages - Cursor positioning wrong with 0x200e character. (John Becket, 2010 May 6) E315 when trying to change a file in FileChangedRO autocommand event. @@ -1094,7 +1090,6 @@ Vim 7.3: Ron's version: http://dev.ronware.org/p/vim/finfo?name=gvim.nsi - Persistent undo bugs / fixes: - Need to check all values for evil manipulation. - - Add undofile(name): get undo file name for buffer "name". - patch for unused functions. (Dominique Pelle, 2010 May 29) - Also crypt the undo file. - Also crypt the swap file, each block separately. Change mf_write() and diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt index a7ae1736c3..4dbe69394f 100644 --- a/runtime/doc/undo.txt +++ b/runtime/doc/undo.txt @@ -243,12 +243,26 @@ respectively: You can use these in autocommands to explicitly specify the name of the history file. E.g.: > - au BufReadPost * rundo %:h/UNDO/%:t - au BufWritePost * wundo %:h/UNDO/%:t + au BufReadPost * call ReadUndo() + au BufWritePost * call WriteUndo() + func ReadUndo() + if filereadable(expand('%:h'). '/UNDO/' . expand('%:t')) + rundo %:h/UNDO/%:t + endif + endfunc + func WriteUndo() + let dirname = expand('%:h') . '/UNDO' + if !isdirectory(dirname) + call mkdir(dirname) + endif + wundo %:h/UNDO/%:t + endfunc You should keep 'undofile' off, otherwise you end up with two undo files for every write. -Note: I did not verify this always works! + +You can use the |undofile()| function to find out the file name that Vim would +use. Note that while reading/writing files and 'undofile' is set most errors will be silent, unless 'verbose' is set. With :wundo and :rundo you will get more diff --git a/runtime/doc/workshop.txt b/runtime/doc/workshop.txt index e4cc91a47a..ae676de2be 100644 --- a/runtime/doc/workshop.txt +++ b/runtime/doc/workshop.txt @@ -89,10 +89,10 @@ Without it the toolbar and signs will be disabled. The XPM library is provide by Arnaud Le Hors of the French National Institute for Research in Computer Science and Control. It can be downloaded from -http://koala.ilog.fr/ftp/pub/xpm. The current release, as of this writing, is -xpm-3.4k-solaris.tgz, which is a gzip'ed tar file. If you create the directory -/usr/local/xpm and untar the file there you can use the uncommented lines in -the Makefile without changing them. If you use another xpm directory you will -need to change the XPM_DIR in src/Makefile. +http://cgit.freedesktop.org/xorg/lib/libXpm. The current release, as of this +writing, is xpm-3.4k-solaris.tgz, which is a gzip'ed tar file. If you create +the directory /usr/local/xpm and untar the file there you can use the +uncommented lines in the Makefile without changing them. If you use another +xpm directory you will need to change the XPM_DIR in src/Makefile. vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/syntax/yaml.vim b/runtime/syntax/yaml.vim index 9ebab70689..4e93d67c7a 100644 --- a/runtime/syntax/yaml.vim +++ b/runtime/syntax/yaml.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: YAML (YAML Ain't Markup Language) " Maintainer: Nikolai Weibull -" Latest Revision: 2006-04-19 +" Latest Revision: 2010-05-30 if exists("b:current_syntax") finish @@ -17,7 +17,7 @@ syn region yamlComment display oneline start='\%(^\|\s\)#' end='$' syn match yamlNodeProperty '!\%(![^\\^% ]\+\|[^!][^:/ ]*\)' -syn match yamlAnchor '&.\+' +syn match yamlAnchor '&[^ \t]\+' syn match yamlAlias '\*.\+' diff --git a/src/eval.c b/src/eval.c index 06615ae906..865dc3a7da 100644 --- a/src/eval.c +++ b/src/eval.c @@ -731,6 +731,7 @@ static void f_tr __ARGS((typval_T *argvars, typval_T *rettv)); static void f_trunc __ARGS((typval_T *argvars, typval_T *rettv)); #endif static void f_type __ARGS((typval_T *argvars, typval_T *rettv)); +static void f_undofile __ARGS((typval_T *argvars, typval_T *rettv)); static void f_values __ARGS((typval_T *argvars, typval_T *rettv)); static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv)); static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv)); @@ -7825,6 +7826,7 @@ static struct fst {"trunc", 1, 1, f_trunc}, #endif {"type", 1, 1, f_type}, + {"undofile", 1, 1, f_undofile}, {"values", 1, 1, f_values}, {"virtcol", 1, 1, f_virtcol}, {"visualmode", 0, 1, f_visualmode}, @@ -17583,6 +17585,23 @@ f_type(argvars, rettv) rettv->vval.v_number = n; } +/* + * "undofile(name)" function + */ + static void +f_undofile(argvars, rettv) + typval_T *argvars; + typval_T *rettv; +{ + rettv->v_type = VAR_STRING; +#ifdef FEAT_PERSISTENT_UNDO + rettv->vval.v_string = u_get_undo_file_name(get_tv_string(&argvars[0]), + FALSE); +#else + rettv->vval.v_string = NULL; +#endif +} + /* * "values(dict)" function */ diff --git a/src/proto/undo.pro b/src/proto/undo.pro index 90e11d2bb1..cea7d49c51 100644 --- a/src/proto/undo.pro +++ b/src/proto/undo.pro @@ -7,8 +7,9 @@ int u_inssub __ARGS((linenr_T lnum)); int u_savedel __ARGS((linenr_T lnum, long nlines)); int undo_allowed __ARGS((void)); void u_compute_hash __ARGS((char_u *hash)); -void u_read_undo __ARGS((char_u *name, char_u *hash)); +char_u *u_get_undo_file_name __ARGS((char_u *buf_ffname, int reading)); void u_write_undo __ARGS((char_u *name, int forceit, buf_T *buf, char_u *hash)); +void u_read_undo __ARGS((char_u *name, char_u *hash)); void u_undo __ARGS((int count)); void u_redo __ARGS((int count)); void undo_time __ARGS((long step, int sec, int absolute)); diff --git a/src/undo.c b/src/undo.c index 88c030565f..34140f2a88 100644 --- a/src/undo.c +++ b/src/undo.c @@ -100,7 +100,6 @@ static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp) static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp)); static void u_freeentry __ARGS((u_entry_T *, long)); #ifdef FEAT_PERSISTENT_UNDO -static char_u *u_get_undo_file_name __ARGS((char_u *, int reading)); static void corruption_error __ARGS((char *msg, char_u *file_name)); static void u_free_uhp __ARGS((u_header_T *uhp)); static int serialize_uep __ARGS((u_entry_T *uep, FILE *fp)); @@ -698,7 +697,7 @@ u_compute_hash(hash) * When "reading" is FALSE use the first name where the directory exists. * Returns NULL when there is no place to write or no file to read. */ - static char_u * + char_u * u_get_undo_file_name(buf_ffname, reading) char_u *buf_ffname; int reading;