changeset 777:f664cc974a7a

updated for version 7.0227
author vimboss
date Fri, 17 Mar 2006 23:19:38 +0000
parents 5a5a080c2776
children c3f63ed316b6
files runtime/doc/eval.txt runtime/doc/help.txt runtime/doc/options.txt runtime/doc/tags runtime/doc/todo.txt runtime/doc/usr_toc.txt runtime/doc/various.txt runtime/doc/version7.txt src/globals.h src/gui_w32.c src/main.c src/misc1.c src/ops.c src/proto/mbyte.pro src/screen.c src/structs.h src/undo.c src/version.h
diffstat 18 files changed, 217 insertions(+), 118 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Mar 10
+*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1510,6 +1510,7 @@ byte2line( {byte})		Number	line number a
 byteidx( {expr}, {nr})		Number	byte index of {nr}'th char in {expr}
 call( {func}, {arglist} [, {dict}])
 				any	call {func} with arguments {arglist}
+changenr()			Number  current change number
 char2nr( {expr})		Number	ASCII value of first char in {expr}
 cindent( {lnum})		Number	C indent for line {lnum}
 col( {expr})			Number	column nr of cursor or mark
@@ -1914,6 +1915,14 @@ call({func}, {arglist} [, {dict}])			*ca
 		{dict} is for functions with the "dict" attribute.  It will be
 		used to set the local variable "self". |Dictionary-function|
 
+changenr()						*changenr()*
+		Return the number of the most recent change.  This is the same
+		number as what is displayed with |:undolist| and can be used
+		with the |:undo| command.
+		When a change was made it is the number of that change.  After
+		redo it is the number of the redone change.  After undo it is
+		one less than the number of the undone change.
+
 char2nr({expr})						*char2nr()*
 		Return number value of the first char in {expr}.  Examples: >
 			char2nr(" ")		returns 32
@@ -5574,9 +5583,11 @@ 7. Commands						*expression-commands*
 :let {var-name}	..	List the value of variable {var-name}.  Multiple
 			variable names may be given.  Special names recognized
 			here:				*E738*
-			  g:	global variables.
-			  b:	local buffer variables.
-			  w:	local window variables.
+			  g:	global variables
+			  b:	local buffer variables
+			  w:	local window variables
+			  s:	script-local variables
+			  l:	local function variables
 			  v:	Vim variables.
 
 :let			List the values of all variables.  The type of the
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -1,4 +1,4 @@
-*help.txt*	For Vim version 7.0aa.  Last change: 2006 Feb 27
+*help.txt*	For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 			VIM - main help file
 									 k
@@ -84,7 +84,7 @@ Making Vim Run ~
 |usr_90.txt|  Installing Vim
 
 
-REFERENCE MANUAL: These files explain every detail of Vim.
+REFERENCE MANUAL: These files explain every detail of Vim.	*ref-toc*
 
 General subjects ~
 |intro.txt|	general introduction to Vim; notation used in help files
@@ -194,6 +194,13 @@ Standard plugins ~
 |pi_zip.txt|	Zip archive explorer
 
 LOCAL ADDITIONS:				*local-additions*
+|cecutil.txt|	DrChip's Utilities				Jun 11, 2004
+|engspchk.txt|	English Spelling Checker   (v61)	Mar 14, 2005
+|example.txt|	Example for a locally added help file
+|matchit.txt|   Extended "%" matching
+|test.txt|	Testing the hélp cömmånd nôw
+|typecorr.txt|	Plugin for correcting typing mistakes
+|helpp.txt|	Dummy line to avoid an error message
 
 ------------------------------------------------------------------------------
 *bars*		Bars example
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.0aa.  Last change: 2006 Mar 16
+*options.txt*	For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -2557,6 +2557,9 @@ A jump table for the options with a shor
 	environment.  This is the default value for 'encoding'.  It is useful
 	when 'encoding' is set to "utf-8" and your environment uses a
 	non-latin1 encoding, such as Russian.
+	When 'encoding' is "utf-8" and a file contains an illegal byte
+	sequence it won't be recognized as UTF-8.  You can use the |8g8|
+	command to find the illegal byte sequence.
 	WRONG VALUES:			WHAT'S WRONG:
 		latin1,utf-8		"latin1" will always be used
 		utf-8,ucs-bom,latin1	BOM won't be recognized in an utf-8
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -1647,6 +1647,7 @@ 45.3	usr_45.txt	/*45.3*
 45.4	usr_45.txt	/*45.4*
 45.5	usr_45.txt	/*45.5*
 755	spell.txt	/*755*
+8g8	various.txt	/*8g8*
 90.1	usr_90.txt	/*90.1*
 90.2	usr_90.txt	/*90.2*
 90.3	usr_90.txt	/*90.3*
@@ -4602,6 +4603,7 @@ changed-6.3	version6.txt	/*changed-6.3*
 changed-6.4	version6.txt	/*changed-6.4*
 changelist	motion.txt	/*changelist*
 changelog.vim	syntax.txt	/*changelog.vim*
+changenr()	eval.txt	/*changenr()*
 changetick	eval.txt	/*changetick*
 changing	change.txt	/*changing*
 char2nr()	eval.txt	/*char2nr()*
@@ -6522,6 +6524,7 @@ recursive_mapping	map.txt	/*recursive_ma
 redo	undo.txt	/*redo*
 redo-register	undo.txt	/*redo-register*
 ref	intro.txt	/*ref*
+ref-toc	help.txt	/*ref-toc*
 reference	intro.txt	/*reference*
 regexp	pattern.txt	/*regexp*
 regexp-changes-5.4	version5.txt	/*regexp-changes-5.4*
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Mar 16
+*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -44,13 +44,9 @@ 8   Add patch from Muraoka Taro (Mar 16)
 EMBEDDING: Make it possible to run Vim inside a window of another program.
 For GTK Neil Bird has a patch to use Vim like a widget.
 
-Win32: Patch for Korean IME. (Yusung, 2005 March 21)
-
 Support ":set syntax=cpp.doxygen"?  Suggested patch by Michael Geddes (9 Aug
 2004).  Should also work for 'filetype'.
 
-Add command to search for illegal utf-8 byte sequence.
-
 Add strtol() to avoid the problems with leading zero causing octal conversion.
 
 Add a 'tool' window: behaves like a preview window but there can be several.
--- a/runtime/doc/usr_toc.txt
+++ b/runtime/doc/usr_toc.txt
@@ -1,4 +1,4 @@
-*usr_toc.txt*	For Vim version 7.0aa.  Last change: 2005 Feb 22
+*usr_toc.txt*	For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 		     VIM USER MANUAL - by Bram Moolenaar
 
@@ -47,6 +47,8 @@ Making Vim Run
 |usr_90.txt|  Installing Vim
 
 
+More detailed information in the reference manual: |ref-toc|
+
 The user manual is available as a single, ready to print HTML and PDF file
 here:
 	http://vimdoc.sf.net
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -1,4 +1,4 @@
-*various.txt*   For Vim version 7.0aa.  Last change: 2006 Mar 05
+*various.txt*   For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -66,7 +66,24 @@ g8			Print the hex values of the bytes u
 			value of 'maxcombine' doesn't matter.
 			Example of a character with two composing characters:
 				e0 b8 81 + e0 b8 b9 + e0 b9 89 ~
-			{not in Vi}
+			{not in Vi} {only when compiled with the |+multi_byte|
+			feature}
+
+							*8g8*
+8g8			Find an illegal UTF-8 byte sequence at or after the
+			cursor.  This works in two situations:
+			1. when 'encoding' is any 8-bit encoding
+			2. when 'encoding' is "utf-8" and 'fileencoding' is
+			   any 8-bit encoding
+			Thus it can be used when editing a file that was
+			supposed to be UTF-8 but was read as if it is an 8-bit
+			encoding because it contains illegal bytes.
+			Does not wrap around the end of the file.
+			Note that when the cursor is on an illegal byte or the
+			cursor is halfway a multi-byte character the command
+			won't move the cursor.
+			{not in Vi} {only when compiled with the |+multi_byte|
+			feature}
 
 							*:p* *:pr* *:print*
 :[range]p[rint] [flags]
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Mar 16
+*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Mar 17
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -285,7 +285,8 @@ was about ten minutes earlier.
 
 The |:undolist| command can be used to get an idea of which undo branches
 exist.  The |:undo| command now takes an argument to directly jump to a
-specific position in this list.
+specific position in this list.  The |changenr()| function can be used to
+obtain the change number.
 
 There is no graphical display of the tree with changes, navigation can be
 quite confusing.
@@ -307,6 +308,8 @@ compile time.
 For pattern matching it is now possible to search for individual composing
 characters. |patterns-composing|
 
+The |8g8| command searches for an illegal UTF-8 byte sequence.
+
 
 More highlighting				*new-more-highlighting*
 -----------------
@@ -2006,4 +2009,8 @@ E.g., when using ":match" to highlight a
 Added SOME_VALID: Redraw the whole window but also try to scroll to minimize
 redrawing.
 
+Win32: When using Korean IME making it active didn't work properly. (Moon,
+Yu-sung, 2005 March 21)
+
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/src/globals.h
+++ b/src/globals.h
@@ -1504,6 +1504,9 @@ EXTERN char bot_top_msg[] INIT(= N_("sea
 EXTERN int xsmp_icefd INIT(= -1);   /* The actual connection */
 #endif
 
+/* For undo we need to know the lowest time possible. */
+EXTERN time_t starttime;
+
 /*
  * Optional Farsi support.  Include it here, so EXTERN and INIT are defined.
  */
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -323,6 +323,7 @@ static BOOL (WINAPI *pImmGetCompositionF
 static BOOL (WINAPI *pImmSetCompositionFont)(HIMC, LPLOGFONTA);
 static BOOL (WINAPI *pImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
 static BOOL (WINAPI *pImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
+static BOOL (WINAPI *pImmSetConversionStatus)(HIMC, DWORD, DWORD);
 static void dyn_imm_load(void);
 #else
 # define pImmGetCompositionStringA ImmGetCompositionStringA
@@ -336,6 +337,7 @@ static void dyn_imm_load(void);
 # define pImmSetCompositionFont   ImmSetCompositionFontA
 # define pImmSetCompositionWindow ImmSetCompositionWindow
 # define pImmGetConversionStatus  ImmGetConversionStatus
+# define pImmSetConversionStatus  ImmSetConversionStatus
 #endif
 
 #ifndef ETO_IGNORELANGUAGE
@@ -1714,6 +1716,39 @@ im_set_active(int active)
 	hImc = pImmGetContext(s_hwnd);
 	if (hImc)
 	{
+	    /*
+	     * for Korean ime
+	     */
+	    HKL hKL = GetKeyboardLayout(0);
+
+	    if (LOWORD(hKL) == MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN))
+	    {
+		static DWORD dwConversionSaved = 0, dwSentenceSaved = 0;
+		static BOOL bSaved = FALSE;
+
+		if (active)
+		{
+		    /* if we have a saved conversion status, restore it */
+		    if (bSaved)
+			pImmSetConversionStatus(hImc, dwConversionSaved,
+							     dwSentenceSaved);
+		    bSaved = FALSE;
+		}
+		else
+		{
+		    /* save conversion status and disable korean */
+		    if (pImmGetConversionStatus(hImc, &dwConversionSaved,
+							    &dwSentenceSaved))
+		    {
+			bSaved = TRUE;
+			pImmSetConversionStatus(hImc,
+				dwConversionSaved & ~(IME_CMODE_NATIVE
+						       | IME_CMODE_FULLSHAPE),
+				dwSentenceSaved);
+		    }
+		}
+	    }
+
 	    pImmSetOpenStatus(hImc, active);
 	    pImmReleaseContext(s_hwnd, hImc);
 	}
@@ -1785,7 +1820,7 @@ latin9_to_ucs(char_u *text, int len, WCH
 {
     int		c;
 
-    while (len-- >= 0)
+    while (--len >= 0)
     {
 	c = *text++;
 	switch (c)
@@ -2021,28 +2056,28 @@ gui_mch_draw_string(
     {
 	/* Output UTF-8 characters.  Caller has already separated
 	 * composing characters. */
-	int		i = 0;
-	int		clen;	/* string length up to composing char */
+	int		i;
+	int		wlen;	/* string length in words */
+	int		clen;	/* string length in characters */
 	int		cells;	/* cell width of string up to composing char */
 	int		cw;	/* width of current cell */
 	int		c;
-	int		xtra;
-
+
+	wlen = 0
+	clen = 0;
 	cells = 0;
-	for (clen = 0; i < len; )
+	for (i = 0; i < len; )
 	{
 	    c = utf_ptr2char(text + i);
 	    if (c >= 0x10000)
 	    {
 		/* Turn into UTF-16 encoding. */
-		unicodebuf[clen] = ((c - 0x10000) >> 10) + 0xD800;
-		unicodebuf[clen + 1] = ((c - 0x10000) & 0x3ff) + 0xDC00;
-		xtra = 1;
+		unicodebuf[wlen++] = ((c - 0x10000) >> 10) + 0xD800;
+		unicodebuf[wlen++] = ((c - 0x10000) & 0x3ff) + 0xDC00;
 	    }
 	    else
 	    {
-		unicodebuf[clen] = c;
-		xtra = 0;
+		unicodebuf[wlen++] = c;
 	    }
 	    cw = utf_char2cells(c);
 	    if (cw > 2)		/* don't use 4 for unprintable char */
@@ -2053,15 +2088,13 @@ gui_mch_draw_string(
 		 * when the font uses different widths (e.g., bold character
 		 * is wider).  */
 		unicodepdy[clen] = cw * gui.char_width;
-		if (xtra == 1)
-		    unicodepdy[clen + 1] = cw * gui.char_width;
 	    }
 	    cells += cw;
 	    i += utfc_ptr2len_len(text + i, len - i);
-	    clen += xtra + 1;
+	    ++clen;
 	}
 	ExtTextOutW(s_hdc, TEXT_X(col), TEXT_Y(row),
-			   foptions, pcliprect, unicodebuf, clen, unicodepdy);
+			   foptions, pcliprect, unicodebuf, wlen, unicodepdy);
 	len = cells;	/* used for underlining */
     }
     else if ((enc_codepage > 0 && (int)GetACP() != enc_codepage) || enc_latin9)
@@ -3894,6 +3927,8 @@ dyn_imm_load(void)
 	    = (void *)GetProcAddress(hLibImm, "ImmSetCompositionWindow");
     pImmGetConversionStatus
 	    = (void *)GetProcAddress(hLibImm, "ImmGetConversionStatus");
+    pImmSetConversionStatus
+	    = (void *)GetProcAddress(hLibImm, "ImmSetConversionStatus");
 
     if (       pImmGetCompositionStringA == NULL
 	    || pImmGetCompositionStringW == NULL
@@ -3905,7 +3940,8 @@ dyn_imm_load(void)
 	    || pImmGetCompositionFont == NULL
 	    || pImmSetCompositionFont == NULL
 	    || pImmSetCompositionWindow == NULL
-	    || pImmGetConversionStatus == NULL)
+	    || pImmGetConversionStatus == NULL
+	    || pImmSetConversionStatus == NULL)
     {
 	FreeLibrary(hLibImm);
 	hLibImm = NULL;
--- a/src/main.c
+++ b/src/main.c
@@ -208,6 +208,7 @@ main
     time_fd = mch_fopen(STARTUPTIME, "a");
     TIME_MSG("--- VIM STARTING ---");
 #endif
+    starttime = time(NULL);
 
 #ifdef __EMX__
     _wildcard(&params.argc, &params.argv);
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -2147,9 +2147,9 @@ del_chars(count, fixpos)
  */
 /*ARGSUSED*/
     int
-del_bytes(count, fixpos, use_delcombine)
+del_bytes(count, fixpos_arg, use_delcombine)
     long	count;
-    int		fixpos;
+    int		fixpos_arg;
     int		use_delcombine;	    /* 'delcombine' option applies */
 {
     char_u	*oldp, *newp;
@@ -2158,6 +2158,7 @@ del_bytes(count, fixpos, use_delcombine)
     colnr_T	col = curwin->w_cursor.col;
     int		was_alloced;
     long	movelen;
+    int		fixpos = fixpos_arg;
 
     oldp = ml_get(lnum);
     oldlen = (int)STRLEN(oldp);
@@ -2201,9 +2202,14 @@ del_bytes(count, fixpos, use_delcombine)
     {
 	/*
 	 * If we just took off the last character of a non-blank line, and
-	 * fixpos is TRUE, we don't want to end up positioned at the NUL.
+	 * fixpos is TRUE, we don't want to end up positioned at the NUL,
+	 * unless "restart_edit" is set or 'virtualedit' contains "onemore".
 	 */
-	if (col > 0 && fixpos)
+	if (col > 0 && fixpos && restart_edit == 0
+#ifdef FEAT_VIRTUALEDIT
+					      && (ve_flags & VE_ONEMORE) == 0
+#endif
+					      )
 	{
 	    --curwin->w_cursor.col;
 #ifdef FEAT_VIRTUALEDIT
--- a/src/ops.c
+++ b/src/ops.c
@@ -1843,8 +1843,7 @@ op_delete(oap)
 		    curwin->w_cursor.coladd = 0;
 	    }
 #endif
-	    (void)del_bytes((long)n, restart_edit == NUL && !virtual_op,
-				oap->op_type == OP_DELETE
+	    (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE
 #ifdef FEAT_VISUAL
 				    && !oap->is_VIsual
 #endif
@@ -1868,8 +1867,7 @@ op_delete(oap)
 	    /* delete from start of line until op_end */
 	    curwin->w_cursor.col = 0;
 	    (void)del_bytes((long)(oap->end.col + 1 - !oap->inclusive),
-					   restart_edit == NUL && !virtual_op,
-				oap->op_type == OP_DELETE
+					!virtual_op, oap->op_type == OP_DELETE
 #ifdef FEAT_VISUAL
 					&& !oap->is_VIsual
 #endif
--- a/src/proto/mbyte.pro
+++ b/src/proto/mbyte.pro
@@ -49,6 +49,7 @@ int utf_head_off __ARGS((char_u *base, c
 void mb_copy_char __ARGS((char_u **fp, char_u **tp));
 int mb_off_next __ARGS((char_u *base, char_u *p));
 int mb_tail_off __ARGS((char_u *base, char_u *p));
+void utf_find_illegal __ARGS((void));
 int utf_valid_string __ARGS((char_u *s, char_u *end));
 int dbcs_screen_tail_off __ARGS((char_u *base, char_u *p));
 void mb_adjust_cursor __ARGS((void));
--- a/src/screen.c
+++ b/src/screen.c
@@ -4296,7 +4296,7 @@ win_line(wp, lnum, startrow, endrow, noc
 			ScreenLinesUC[off] = 0;
 #endif
 		    ++col;
-		    if (vcol == wp->w_virtcol)
+		    if (vcol == (long)wp->w_virtcol)
 		    {
 			ScreenAttrs[off] = hl_attr(HLF_CUC);
 			break;
@@ -4360,7 +4360,7 @@ win_line(wp, lnum, startrow, endrow, noc
 #ifdef FEAT_SYN_HL
 	/* Highlight the cursor column if 'cursorcolumn' is set.  But don't
 	 * highlight the cursor position itself. */
-	if (wp->w_p_cuc && vcol == wp->w_virtcol
+	if (wp->w_p_cuc && vcol == (long)wp->w_virtcol
 		&& lnum != wp->w_cursor.lnum
 		&& draw_state == WL_LINE)
 	{
--- a/src/structs.h
+++ b/src/structs.h
@@ -1254,11 +1254,9 @@ struct file_buffer
     u_header_T	*b_u_curhead;	/* pointer to current header */
     int		b_u_numhead;	/* current number of headers */
     int		b_u_synced;	/* entry lists are synced */
-    long	b_u_seq_last;	/* last used undo sequence number plus 1 */
-    long	b_u_seq_cur;	/* undo sequence number of last header used
-				   plus 1 */
-    time_t	b_u_seq_time;	/* uh_time of the last header used plus 1 or
-				   uh_time of current header */
+    long	b_u_seq_last;	/* last used undo sequence number */
+    long	b_u_seq_cur;	/* hu_seq of header below which we are now */
+    time_t	b_u_seq_time;	/* uh_time of header below which we are now */
 
     /*
      * variables for "U" command in undo.c
--- a/src/undo.c
+++ b/src/undo.c
@@ -87,7 +87,7 @@ static void u_getbot __ARGS((void));
 static int undo_allowed __ARGS((void));
 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T));
 static void u_doit __ARGS((int count));
-static void u_undoredo __ARGS((void));
+static void u_undoredo __ARGS((int undo));
 static void u_undo_end __ARGS((void));
 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt));
 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
@@ -350,8 +350,8 @@ u_savecommon(top, bot, newbot)
 	if (curbuf->b_u_newhead != NULL)
 	    curbuf->b_u_newhead->uh_prev = uhp;
 
-	uhp->uh_seq = curbuf->b_u_seq_last++;
-	curbuf->b_u_seq_cur = curbuf->b_u_seq_last;
+	uhp->uh_seq = ++curbuf->b_u_seq_last;
+	curbuf->b_u_seq_cur = uhp->uh_seq;
 	uhp->uh_time = time(NULL);
 	curbuf->b_u_seq_time = uhp->uh_time + 1;
 
@@ -579,9 +579,11 @@ u_redo(count)
  * Undo or redo, depending on 'undo_undoes', 'count' times.
  */
     static void
-u_doit(count)
-    int count;
+u_doit(startcount)
+    int startcount;
 {
+    int count = startcount;
+
     if (!undo_allowed())
 	return;
 
@@ -604,22 +606,30 @@ u_doit(count)
 		/* stick curbuf->b_u_curhead at end */
 		curbuf->b_u_curhead = curbuf->b_u_oldhead;
 		beep_flush();
+		if (count == startcount - 1)
+		{
+		    MSG(_("Already at oldest change"));
+		    return;
+		}
 		break;
 	    }
 
-	    u_undoredo();
+	    u_undoredo(TRUE);
 	}
 	else
 	{
 	    if (curbuf->b_u_curhead == NULL || p_ul <= 0)
 	    {
 		beep_flush();	/* nothing to redo */
+		if (count == startcount - 1)
+		{
+		    MSG(_("Already at newest change"));
+		    return;
+		}
 		break;
 	    }
 
-	    u_undoredo();
-	    ++curbuf->b_u_seq_cur;
-	    ++curbuf->b_u_seq_time;
+	    u_undoredo(FALSE);
 
 	    /* Advance for next redo.  Set "newhead" when at the end of the
 	     * redoable changes. */
@@ -652,7 +662,6 @@ undo_time(step, sec, absolute)
     long	    closest_start;
     long	    closest_seq = 0;
     long	    val;
-    long	    limit;
     u_header_T	    *uhp;
     u_header_T	    *last;
     int		    mark;
@@ -670,43 +679,39 @@ undo_time(step, sec, absolute)
     if (curbuf->b_ml.ml_flags & ML_EMPTY)
 	u_oldcount = -1;
 
-    /* "target" is the node below which we want to be.  When going forward
-     * the current one also counts, thus do one less. */
+    /* "target" is the node below which we want to be.
+     * Init "closest" to a value we can't reach. */
     if (absolute)
     {
 	target = step;
-	closest = -2;
-    }
-    else if (step < 0)
-    {
-	if (sec)
-	    target = (long)curbuf->b_u_seq_time + step;
-	else
-	    target = curbuf->b_u_seq_cur + step;
-	if (target < 0)
-	    target = -1;
-	closest = -2;
+	closest = -1;
     }
     else
     {
+	/* When doing computations with time_t subtract starttime, because
+	 * time_t converted to a long may result in a wrong number. */
 	if (sec)
+	    target = (long)(curbuf->b_u_seq_time - starttime) + step;
+	else
+	    target = curbuf->b_u_seq_cur + step;
+	if (step < 0)
 	{
-	    target = curbuf->b_u_seq_time + step - 1;
-	    closest = time(NULL) + 1;
+	    if (target < 0)
+		target = 0;
+	    closest = -1;
 	}
 	else
 	{
-	    target = curbuf->b_u_seq_cur + step - 1;
-	    closest = curbuf->b_u_seq_last + 1;
+	    if (sec)
+		closest = time(NULL) - starttime + 1;
+	    else
+		closest = curbuf->b_u_seq_last + 2;
+	    if (target >= closest)
+		target = closest - 1;
 	}
-	if (target >= closest)
-	    target = closest - 1;
     }
     closest_start = closest;
-    if (sec)
-	limit = curbuf->b_u_seq_time + (step > 0 ? -1 : 1);
-    else
-	limit = curbuf->b_u_seq_cur;
+    closest_seq = curbuf->b_u_seq_cur;
 
     /*
      * May do this twice:
@@ -733,27 +738,28 @@ undo_time(step, sec, absolute)
 	while (uhp != NULL)
 	{
 	    uhp->uh_walk = mark;
-	    val = (dosec ? uhp->uh_time : uhp->uh_seq);
+	    val = (dosec ? (uhp->uh_time - starttime) : uhp->uh_seq);
 
 	    if (round == 1)
 	    {
 		/* Remember the header that is closest to the target.
 		 * It must be at least in the right direction (checked with
-		 * "limit").  When the timestamp is equal find the
+		 * "b_u_seq_cur").  When the timestamp is equal find the
 		 * highest/lowest sequence number. */
-		if ((dosec && val == closest)
-			? (step < 0
-			    ? uhp->uh_seq < closest_seq
-			    : uhp->uh_seq > closest_seq)
-			: (step < 0
-			    ? (val < limit
-				&& (closest > target
-				    ? (val <= closest)
-				    : (val >= closest)))
-			    : (val > limit
-				&& (closest < target
-				    ? val >= closest
-				    : val <= closest))))
+		if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur
+			      : uhp->uh_seq > curbuf->b_u_seq_cur)
+			&& ((dosec && val == closest)
+			    ? (step < 0
+				? uhp->uh_seq < closest_seq
+				: uhp->uh_seq > closest_seq)
+			    : closest == closest_start
+				|| (val > target
+				    ? (closest > target
+					? val - target <= closest - target
+					: val - target <= target - closest)
+				    : (closest > target
+					? target - val <= closest - target
+					: target - val <= target - closest))))
 		{
 		    closest = val;
 		    closest_seq = uhp->uh_seq;
@@ -830,19 +836,12 @@ undo_time(step, sec, absolute)
 	    if (uhp == NULL)
 		uhp = curbuf->b_u_newhead;
 	    else
-	    {
-		while (uhp->uh_alt_prev != NULL
-					 && uhp->uh_alt_prev->uh_walk == mark)
-		{
-		    uhp->uh_walk = nomark;
-		    uhp = uhp->uh_alt_prev;
-		}
 		uhp = uhp->uh_next;
-	    }
-	    if (uhp == NULL || uhp->uh_walk != mark)
+	    if (uhp == NULL || uhp->uh_walk != mark
+					 || (uhp->uh_seq == target && !above))
 		break;
 	    curbuf->b_u_curhead = uhp;
-	    u_undoredo();
+	    u_undoredo(TRUE);
 	    uhp->uh_walk = nomark;	/* don't go back down here */
 	}
 
@@ -850,7 +849,7 @@ undo_time(step, sec, absolute)
 	 * And now go down the tree (redo), branching off where needed.
 	 */
 	uhp = curbuf->b_u_curhead;
-	for (;;)
+	while (uhp != NULL)
 	{
 	    /* Find the last branch with a mark, that's the one. */
 	    last = uhp;
@@ -869,10 +868,10 @@ undo_time(step, sec, absolute)
 		uhp->uh_alt_prev = last;
 
 		uhp = last;
+		if (uhp->uh_next != NULL)
+		    uhp->uh_next->uh_prev = uhp;
 	    }
 	    curbuf->b_u_curhead = uhp;
-	    curbuf->b_u_seq_cur = uhp->uh_seq;
-	    curbuf->b_u_seq_time = uhp->uh_time;
 
 	    if (uhp->uh_walk != mark)
 		break;	    /* must have reached the target */
@@ -882,9 +881,7 @@ undo_time(step, sec, absolute)
 	    if (uhp->uh_seq == target && above)
 		break;
 
-	    u_undoredo();
-	    ++curbuf->b_u_seq_cur;
-	    ++curbuf->b_u_seq_time;
+	    u_undoredo(FALSE);
 
 	    /* Advance "curhead" to below the header we last used.  If it
 	     * becomes NULL then we need to set "newhead" to this leaf. */
@@ -898,6 +895,7 @@ undo_time(step, sec, absolute)
 	    uhp = uhp->uh_prev;
 	    if (uhp == NULL || uhp->uh_walk != mark)
 	    {
+		/* Need to redo more but can't find it... */
 		EMSG2(_(e_intern2), "undo_time()");
 		break;
 	    }
@@ -912,9 +910,12 @@ undo_time(step, sec, absolute)
  * The lines in the file are replaced by the lines in the entry list at
  * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry
  * list for the next undo/redo.
+ *
+ * When "undo" is TRUE we go up in the tree, when FALSE we go down.
  */
     static void
-u_undoredo()
+u_undoredo(undo)
+    int		undo;
 {
     char_u	**newarray = NULL;
     linenr_T	oldsize;
@@ -1157,6 +1158,13 @@ u_undoredo()
 
     /* Remember where we are for "g-" and ":earlier 10s". */
     curbuf->b_u_seq_cur = curhead->uh_seq;
+    if (undo)
+	/* We are below the previous undo.  However, to make ":earlier 1s"
+	 * work we compute this as being just above the just undone change. */
+	--curbuf->b_u_seq_cur;
+
+    /* The timestamp can be the same for multiple changes, just use the one of
+     * the undone/redone change. */
     curbuf->b_u_seq_time = curhead->uh_time;
 }
 
@@ -1212,8 +1220,9 @@ u_undo_end()
     else
 	u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
 
-    smsg((char_u *)_("%ld %s; #%ld  %s"), u_oldcount, _(msg),
-				      uhp == NULL ? 0L : uhp->uh_seq, msgbuf);
+    smsg((char_u *)_("%ld %s; #%ld  %s"),
+	    u_oldcount < 0 ? -u_oldcount : u_oldcount,
+	    _(msg), uhp == NULL ? 0L : uhp->uh_seq, msgbuf);
 }
 
 /*
@@ -1264,7 +1273,8 @@ ex_undolist(eap)
     uhp = curbuf->b_u_oldhead;
     while (uhp != NULL)
     {
-	if (uhp->uh_prev == NULL)
+	if (uhp->uh_prev == NULL && uhp->uh_walk != nomark
+						      && uhp->uh_walk != mark)
 	{
 	    if (ga_grow(&ga, 1) == FAIL)
 		break;
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
 #define VIM_VERSION_NODOT	"vim70aa"
 #define VIM_VERSION_SHORT	"7.0aa"
 #define VIM_VERSION_MEDIUM	"7.0aa ALPHA"
-#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Mar 16)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Mar 16, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Mar 17)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Mar 17, compiled "