xref: /vim-8.2.3635/src/undo.c (revision 84a05acc)
1 /* vi:set ts=8 sts=4 sw=4:
2  *
3  * VIM - Vi IMproved	by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 /*
11  * undo.c: multi level undo facility
12  *
13  * The saved lines are stored in a list of lists (one for each buffer):
14  *
15  * b_u_oldhead------------------------------------------------+
16  *							      |
17  *							      V
18  *		  +--------------+    +--------------+	  +--------------+
19  * b_u_newhead--->| u_header	 |    | u_header     |	  | u_header	 |
20  *		  |	uh_next------>|     uh_next------>|	uh_next---->NULL
21  *	   NULL<--------uh_prev  |<---------uh_prev  |<---------uh_prev  |
22  *		  |	uh_entry |    |     uh_entry |	  |	uh_entry |
23  *		  +--------|-----+    +--------|-----+	  +--------|-----+
24  *			   |		       |		   |
25  *			   V		       V		   V
26  *		  +--------------+    +--------------+	  +--------------+
27  *		  | u_entry	 |    | u_entry      |	  | u_entry	 |
28  *		  |	ue_next  |    |     ue_next  |	  |	ue_next  |
29  *		  +--------|-----+    +--------|-----+	  +--------|-----+
30  *			   |		       |		   |
31  *			   V		       V		   V
32  *		  +--------------+	      NULL		  NULL
33  *		  | u_entry	 |
34  *		  |	ue_next  |
35  *		  +--------|-----+
36  *			   |
37  *			   V
38  *			  etc.
39  *
40  * Each u_entry list contains the information for one undo or redo.
41  * curbuf->b_u_curhead points to the header of the last undo (the next redo),
42  * or is NULL if nothing has been undone (end of the branch).
43  *
44  * For keeping alternate undo/redo branches the uh_alt field is used.  Thus at
45  * each point in the list a branch may appear for an alternate to redo.  The
46  * uh_seq field is numbered sequentially to be able to find a newer or older
47  * branch.
48  *
49  *		   +---------------+	+---------------+
50  * b_u_oldhead --->| u_header	   |	| u_header	|
51  *		   |   uh_alt_next ---->|   uh_alt_next ----> NULL
52  *	   NULL <----- uh_alt_prev |<------ uh_alt_prev |
53  *		   |   uh_prev	   |	|   uh_prev	|
54  *		   +-----|---------+	+-----|---------+
55  *			 |		      |
56  *			 V		      V
57  *		   +---------------+	+---------------+
58  *		   | u_header	   |	| u_header	|
59  *		   |   uh_alt_next |	|   uh_alt_next |
60  * b_u_newhead --->|   uh_alt_prev |	|   uh_alt_prev |
61  *		   |   uh_prev	   |	|   uh_prev	|
62  *		   +-----|---------+	+-----|---------+
63  *			 |		      |
64  *			 V		      V
65  *		       NULL		+---------------+    +---------------+
66  *					| u_header	|    | u_header      |
67  *					|   uh_alt_next ---->|	 uh_alt_next |
68  *					|   uh_alt_prev |<------ uh_alt_prev |
69  *					|   uh_prev	|    |	 uh_prev     |
70  *					+-----|---------+    +-----|---------+
71  *					      |			   |
72  *					     etc.		  etc.
73  *
74  *
75  * All data is allocated and will all be freed when the buffer is unloaded.
76  */
77 
78 /* Uncomment the next line for including the u_check() function.  This warns
79  * for errors in the debug information. */
80 /* #define U_DEBUG 1 */
81 #define UH_MAGIC 0x18dade	/* value for uh_magic when in use */
82 #define UE_MAGIC 0xabc123	/* value for ue_magic when in use */
83 
84 #include "vim.h"
85 
86 static void u_unch_branch __ARGS((u_header_T *uhp));
87 static u_entry_T *u_get_headentry __ARGS((void));
88 static void u_getbot __ARGS((void));
89 static void u_doit __ARGS((int count));
90 static void u_undoredo __ARGS((int undo));
91 static void u_undo_end __ARGS((int did_undo, int absolute));
92 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt));
93 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
94 static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
95 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
96 static void u_freeentry __ARGS((u_entry_T *, long));
97 #ifdef FEAT_PERSISTENT_UNDO
98 static void corruption_error __ARGS((char *mesg, char_u *file_name));
99 static void u_free_uhp __ARGS((u_header_T *uhp));
100 static size_t fwrite_crypt __ARGS((buf_T *buf UNUSED, char_u *ptr, size_t len, FILE *fp));
101 static char_u *read_string_decrypt __ARGS((buf_T *buf UNUSED, FILE *fd, int len));
102 static int serialize_header __ARGS((FILE *fp, buf_T *buf, char_u *hash));
103 static int serialize_uhp __ARGS((FILE *fp, buf_T *buf, u_header_T *uhp));
104 static u_header_T *unserialize_uhp __ARGS((FILE *fp, char_u *file_name));
105 static int serialize_uep __ARGS((FILE *fp, buf_T *buf, u_entry_T *uep));
106 static u_entry_T *unserialize_uep __ARGS((FILE *fp, int *error, char_u *file_name));
107 static void serialize_pos __ARGS((pos_T pos, FILE *fp));
108 static void unserialize_pos __ARGS((pos_T *pos, FILE *fp));
109 static void serialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp));
110 static void unserialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp));
111 static void put_header_ptr __ARGS((FILE	*fp, u_header_T *uhp));
112 #endif
113 
114 #define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE)
115 static char_u *u_save_line __ARGS((linenr_T));
116 
117 /* used in undo_end() to report number of added and deleted lines */
118 static long	u_newcount, u_oldcount;
119 
120 /*
121  * When 'u' flag included in 'cpoptions', we behave like vi.  Need to remember
122  * the action that "u" should do.
123  */
124 static int	undo_undoes = FALSE;
125 
126 static int	lastmark = 0;
127 
128 #if defined(U_DEBUG) || defined(PROTO)
129 /*
130  * Check the undo structures for being valid.  Print a warning when something
131  * looks wrong.
132  */
133 static int seen_b_u_curhead;
134 static int seen_b_u_newhead;
135 static int header_count;
136 
137     static void
138 u_check_tree(u_header_T *uhp,
139 	u_header_T *exp_uh_next,
140 	u_header_T *exp_uh_alt_prev)
141 {
142     u_entry_T *uep;
143 
144     if (uhp == NULL)
145 	return;
146     ++header_count;
147     if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1)
148     {
149 	EMSG("b_u_curhead found twice (looping?)");
150 	return;
151     }
152     if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1)
153     {
154 	EMSG("b_u_newhead found twice (looping?)");
155 	return;
156     }
157 
158     if (uhp->uh_magic != UH_MAGIC)
159 	EMSG("uh_magic wrong (may be using freed memory)");
160     else
161     {
162 	/* Check pointers back are correct. */
163 	if (uhp->uh_next.ptr != exp_uh_next)
164 	{
165 	    EMSG("uh_next wrong");
166 	    smsg((char_u *)"expected: 0x%x, actual: 0x%x",
167 					       exp_uh_next, uhp->uh_next.ptr);
168 	}
169 	if (uhp->uh_alt_prev.ptr != exp_uh_alt_prev)
170 	{
171 	    EMSG("uh_alt_prev wrong");
172 	    smsg((char_u *)"expected: 0x%x, actual: 0x%x",
173 				       exp_uh_alt_prev, uhp->uh_alt_prev.ptr);
174 	}
175 
176 	/* Check the undo tree at this header. */
177 	for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
178 	{
179 	    if (uep->ue_magic != UE_MAGIC)
180 	    {
181 		EMSG("ue_magic wrong (may be using freed memory)");
182 		break;
183 	    }
184 	}
185 
186 	/* Check the next alt tree. */
187 	u_check_tree(uhp->uh_alt_next.ptr, uhp->uh_next.ptr, uhp);
188 
189 	/* Check the next header in this branch. */
190 	u_check_tree(uhp->uh_prev.ptr, uhp, NULL);
191     }
192 }
193 
194     static void
195 u_check(int newhead_may_be_NULL)
196 {
197     seen_b_u_newhead = 0;
198     seen_b_u_curhead = 0;
199     header_count = 0;
200 
201     u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
202 
203     if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
204 	    && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
205 	EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
206     if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
207 	EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
208     if (header_count != curbuf->b_u_numhead)
209     {
210 	EMSG("b_u_numhead invalid");
211 	smsg((char_u *)"expected: %ld, actual: %ld",
212 			       (long)header_count, (long)curbuf->b_u_numhead);
213     }
214 }
215 #endif
216 
217 /*
218  * Save the current line for both the "u" and "U" command.
219  * Careful: may trigger autocommands that reload the buffer.
220  * Returns OK or FAIL.
221  */
222     int
223 u_save_cursor()
224 {
225     return (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
226 				      (linenr_T)(curwin->w_cursor.lnum + 1)));
227 }
228 
229 /*
230  * Save the lines between "top" and "bot" for both the "u" and "U" command.
231  * "top" may be 0 and bot may be curbuf->b_ml.ml_line_count + 1.
232  * Careful: may trigger autocommands that reload the buffer.
233  * Returns FAIL when lines could not be saved, OK otherwise.
234  */
235     int
236 u_save(top, bot)
237     linenr_T top, bot;
238 {
239     if (undo_off)
240 	return OK;
241 
242     if (top > curbuf->b_ml.ml_line_count
243 	    || top >= bot
244 	    || bot > curbuf->b_ml.ml_line_count + 1)
245 	return FALSE;	/* rely on caller to do error messages */
246 
247     if (top + 2 == bot)
248 	u_saveline((linenr_T)(top + 1));
249 
250     return (u_savecommon(top, bot, (linenr_T)0, FALSE));
251 }
252 
253 /*
254  * Save the line "lnum" (used by ":s" and "~" command).
255  * The line is replaced, so the new bottom line is lnum + 1.
256  * Careful: may trigger autocommands that reload the buffer.
257  * Returns FAIL when lines could not be saved, OK otherwise.
258  */
259     int
260 u_savesub(lnum)
261     linenr_T	lnum;
262 {
263     if (undo_off)
264 	return OK;
265 
266     return (u_savecommon(lnum - 1, lnum + 1, lnum + 1, FALSE));
267 }
268 
269 /*
270  * A new line is inserted before line "lnum" (used by :s command).
271  * The line is inserted, so the new bottom line is lnum + 1.
272  * Careful: may trigger autocommands that reload the buffer.
273  * Returns FAIL when lines could not be saved, OK otherwise.
274  */
275     int
276 u_inssub(lnum)
277     linenr_T	lnum;
278 {
279     if (undo_off)
280 	return OK;
281 
282     return (u_savecommon(lnum - 1, lnum, lnum + 1, FALSE));
283 }
284 
285 /*
286  * Save the lines "lnum" - "lnum" + nlines (used by delete command).
287  * The lines are deleted, so the new bottom line is lnum, unless the buffer
288  * becomes empty.
289  * Careful: may trigger autocommands that reload the buffer.
290  * Returns FAIL when lines could not be saved, OK otherwise.
291  */
292     int
293 u_savedel(lnum, nlines)
294     linenr_T	lnum;
295     long	nlines;
296 {
297     if (undo_off)
298 	return OK;
299 
300     return (u_savecommon(lnum - 1, lnum + nlines,
301 		     nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE));
302 }
303 
304 /*
305  * Return TRUE when undo is allowed.  Otherwise give an error message and
306  * return FALSE.
307  */
308     int
309 undo_allowed()
310 {
311     /* Don't allow changes when 'modifiable' is off.  */
312     if (!curbuf->b_p_ma)
313     {
314 	EMSG(_(e_modifiable));
315 	return FALSE;
316     }
317 
318 #ifdef HAVE_SANDBOX
319     /* In the sandbox it's not allowed to change the text. */
320     if (sandbox != 0)
321     {
322 	EMSG(_(e_sandbox));
323 	return FALSE;
324     }
325 #endif
326 
327     /* Don't allow changes in the buffer while editing the cmdline.  The
328      * caller of getcmdline() may get confused. */
329     if (textlock != 0)
330     {
331 	EMSG(_(e_secure));
332 	return FALSE;
333     }
334 
335     return TRUE;
336 }
337 
338 /*
339  * Common code for various ways to save text before a change.
340  * "top" is the line above the first changed line.
341  * "bot" is the line below the last changed line.
342  * "newbot" is the new bottom line.  Use zero when not known.
343  * "reload" is TRUE when saving for a buffer reload.
344  * Careful: may trigger autocommands that reload the buffer.
345  * Returns FAIL when lines could not be saved, OK otherwise.
346  */
347     int
348 u_savecommon(top, bot, newbot, reload)
349     linenr_T	top, bot;
350     linenr_T	newbot;
351     int		reload;
352 {
353     linenr_T	lnum;
354     long	i;
355     u_header_T	*uhp;
356     u_header_T	*old_curhead;
357     u_entry_T	*uep;
358     u_entry_T	*prev_uep;
359     long	size;
360 
361     if (!reload)
362     {
363 	/* When making changes is not allowed return FAIL.  It's a crude way
364 	 * to make all change commands fail. */
365 	if (!undo_allowed())
366 	    return FAIL;
367 
368 #ifdef FEAT_NETBEANS_INTG
369 	/*
370 	 * Netbeans defines areas that cannot be modified.  Bail out here when
371 	 * trying to change text in a guarded area.
372 	 */
373 	if (netbeans_active())
374 	{
375 	    if (netbeans_is_guarded(top, bot))
376 	    {
377 		EMSG(_(e_guarded));
378 		return FAIL;
379 	    }
380 	    if (curbuf->b_p_ro)
381 	    {
382 		EMSG(_(e_nbreadonly));
383 		return FAIL;
384 	    }
385 	}
386 #endif
387 
388 #ifdef FEAT_AUTOCMD
389 	/*
390 	 * Saving text for undo means we are going to make a change.  Give a
391 	 * warning for a read-only file before making the change, so that the
392 	 * FileChangedRO event can replace the buffer with a read-write version
393 	 * (e.g., obtained from a source control system).
394 	 */
395 	change_warning(0);
396 	if (bot > curbuf->b_ml.ml_line_count + 1)
397 	{
398 	    /* This happens when the FileChangedRO autocommand changes the
399 	     * file in a way it becomes shorter. */
400 	    EMSG(_("E834: Line count changed unexpectedly"));
401 	    return FAIL;
402 	}
403 #endif
404     }
405 
406 #ifdef U_DEBUG
407     u_check(FALSE);
408 #endif
409 
410     size = bot - top - 1;
411 
412     /*
413      * If curbuf->b_u_synced == TRUE make a new header.
414      */
415     if (curbuf->b_u_synced)
416     {
417 #ifdef FEAT_JUMPLIST
418 	/* Need to create new entry in b_changelist. */
419 	curbuf->b_new_change = TRUE;
420 #endif
421 
422 	if (p_ul >= 0)
423 	{
424 	    /*
425 	     * Make a new header entry.  Do this first so that we don't mess
426 	     * up the undo info when out of memory.
427 	     */
428 	    uhp = (u_header_T *)U_ALLOC_LINE(sizeof(u_header_T));
429 	    if (uhp == NULL)
430 		goto nomem;
431 #ifdef U_DEBUG
432 	    uhp->uh_magic = UH_MAGIC;
433 #endif
434 	}
435 	else
436 	    uhp = NULL;
437 
438 	/*
439 	 * If we undid more than we redid, move the entry lists before and
440 	 * including curbuf->b_u_curhead to an alternate branch.
441 	 */
442 	old_curhead = curbuf->b_u_curhead;
443 	if (old_curhead != NULL)
444 	{
445 	    curbuf->b_u_newhead = old_curhead->uh_next.ptr;
446 	    curbuf->b_u_curhead = NULL;
447 	}
448 
449 	/*
450 	 * free headers to keep the size right
451 	 */
452 	while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
453 	{
454 	    u_header_T	    *uhfree = curbuf->b_u_oldhead;
455 
456 	    if (uhfree == old_curhead)
457 		/* Can't reconnect the branch, delete all of it. */
458 		u_freebranch(curbuf, uhfree, &old_curhead);
459 	    else if (uhfree->uh_alt_next.ptr == NULL)
460 		/* There is no branch, only free one header. */
461 		u_freeheader(curbuf, uhfree, &old_curhead);
462 	    else
463 	    {
464 		/* Free the oldest alternate branch as a whole. */
465 		while (uhfree->uh_alt_next.ptr != NULL)
466 		    uhfree = uhfree->uh_alt_next.ptr;
467 		u_freebranch(curbuf, uhfree, &old_curhead);
468 	    }
469 #ifdef U_DEBUG
470 	    u_check(TRUE);
471 #endif
472 	}
473 
474 	if (uhp == NULL)		/* no undo at all */
475 	{
476 	    if (old_curhead != NULL)
477 		u_freebranch(curbuf, old_curhead, NULL);
478 	    curbuf->b_u_synced = FALSE;
479 	    return OK;
480 	}
481 
482 	uhp->uh_prev.ptr = NULL;
483 	uhp->uh_next.ptr = curbuf->b_u_newhead;
484 	uhp->uh_alt_next.ptr = old_curhead;
485 	if (old_curhead != NULL)
486 	{
487 	    uhp->uh_alt_prev.ptr = old_curhead->uh_alt_prev.ptr;
488 	    if (uhp->uh_alt_prev.ptr != NULL)
489 		uhp->uh_alt_prev.ptr->uh_alt_next.ptr = uhp;
490 	    old_curhead->uh_alt_prev.ptr = uhp;
491 	    if (curbuf->b_u_oldhead == old_curhead)
492 		curbuf->b_u_oldhead = uhp;
493 	}
494 	else
495 	    uhp->uh_alt_prev.ptr = NULL;
496 	if (curbuf->b_u_newhead != NULL)
497 	    curbuf->b_u_newhead->uh_prev.ptr = uhp;
498 
499 	uhp->uh_seq = ++curbuf->b_u_seq_last;
500 	curbuf->b_u_seq_cur = uhp->uh_seq;
501 	uhp->uh_time = time(NULL);
502 	uhp->uh_save_nr = 0;
503 	curbuf->b_u_time_cur = uhp->uh_time + 1;
504 
505 	uhp->uh_walk = 0;
506 	uhp->uh_entry = NULL;
507 	uhp->uh_getbot_entry = NULL;
508 	uhp->uh_cursor = curwin->w_cursor;	/* save cursor pos. for undo */
509 #ifdef FEAT_VIRTUALEDIT
510 	if (virtual_active() && curwin->w_cursor.coladd > 0)
511 	    uhp->uh_cursor_vcol = getviscol();
512 	else
513 	    uhp->uh_cursor_vcol = -1;
514 #endif
515 
516 	/* save changed and buffer empty flag for undo */
517 	uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
518 		       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
519 
520 	/* save named marks and Visual marks for undo */
521 	mch_memmove(uhp->uh_namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
522 #ifdef FEAT_VISUAL
523 	uhp->uh_visual = curbuf->b_visual;
524 #endif
525 
526 	curbuf->b_u_newhead = uhp;
527 	if (curbuf->b_u_oldhead == NULL)
528 	    curbuf->b_u_oldhead = uhp;
529 	++curbuf->b_u_numhead;
530     }
531     else
532     {
533 	if (p_ul < 0)		/* no undo at all */
534 	    return OK;
535 
536 	/*
537 	 * When saving a single line, and it has been saved just before, it
538 	 * doesn't make sense saving it again.  Saves a lot of memory when
539 	 * making lots of changes inside the same line.
540 	 * This is only possible if the previous change didn't increase or
541 	 * decrease the number of lines.
542 	 * Check the ten last changes.  More doesn't make sense and takes too
543 	 * long.
544 	 */
545 	if (size == 1)
546 	{
547 	    uep = u_get_headentry();
548 	    prev_uep = NULL;
549 	    for (i = 0; i < 10; ++i)
550 	    {
551 		if (uep == NULL)
552 		    break;
553 
554 		/* If lines have been inserted/deleted we give up.
555 		 * Also when the line was included in a multi-line save. */
556 		if ((curbuf->b_u_newhead->uh_getbot_entry != uep
557 			    ? (uep->ue_top + uep->ue_size + 1
558 				!= (uep->ue_bot == 0
559 				    ? curbuf->b_ml.ml_line_count + 1
560 				    : uep->ue_bot))
561 			    : uep->ue_lcount != curbuf->b_ml.ml_line_count)
562 			|| (uep->ue_size > 1
563 			    && top >= uep->ue_top
564 			    && top + 2 <= uep->ue_top + uep->ue_size + 1))
565 		    break;
566 
567 		/* If it's the same line we can skip saving it again. */
568 		if (uep->ue_size == 1 && uep->ue_top == top)
569 		{
570 		    if (i > 0)
571 		    {
572 			/* It's not the last entry: get ue_bot for the last
573 			 * entry now.  Following deleted/inserted lines go to
574 			 * the re-used entry. */
575 			u_getbot();
576 			curbuf->b_u_synced = FALSE;
577 
578 			/* Move the found entry to become the last entry.  The
579 			 * order of undo/redo doesn't matter for the entries
580 			 * we move it over, since they don't change the line
581 			 * count and don't include this line.  It does matter
582 			 * for the found entry if the line count is changed by
583 			 * the executed command. */
584 			prev_uep->ue_next = uep->ue_next;
585 			uep->ue_next = curbuf->b_u_newhead->uh_entry;
586 			curbuf->b_u_newhead->uh_entry = uep;
587 		    }
588 
589 		    /* The executed command may change the line count. */
590 		    if (newbot != 0)
591 			uep->ue_bot = newbot;
592 		    else if (bot > curbuf->b_ml.ml_line_count)
593 			uep->ue_bot = 0;
594 		    else
595 		    {
596 			uep->ue_lcount = curbuf->b_ml.ml_line_count;
597 			curbuf->b_u_newhead->uh_getbot_entry = uep;
598 		    }
599 		    return OK;
600 		}
601 		prev_uep = uep;
602 		uep = uep->ue_next;
603 	    }
604 	}
605 
606 	/* find line number for ue_bot for previous u_save() */
607 	u_getbot();
608     }
609 
610 #if !defined(UNIX) && !defined(DJGPP) && !defined(WIN32) && !defined(__EMX__)
611 	/*
612 	 * With Amiga and MSDOS 16 bit we can't handle big undo's, because
613 	 * then u_alloc_line would have to allocate a block larger than 32K
614 	 */
615     if (size >= 8000)
616 	goto nomem;
617 #endif
618 
619     /*
620      * add lines in front of entry list
621      */
622     uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T));
623     if (uep == NULL)
624 	goto nomem;
625     vim_memset(uep, 0, sizeof(u_entry_T));
626 #ifdef U_DEBUG
627     uep->ue_magic = UE_MAGIC;
628 #endif
629 
630     uep->ue_size = size;
631     uep->ue_top = top;
632     if (newbot != 0)
633 	uep->ue_bot = newbot;
634     /*
635      * Use 0 for ue_bot if bot is below last line.
636      * Otherwise we have to compute ue_bot later.
637      */
638     else if (bot > curbuf->b_ml.ml_line_count)
639 	uep->ue_bot = 0;
640     else
641     {
642 	uep->ue_lcount = curbuf->b_ml.ml_line_count;
643 	curbuf->b_u_newhead->uh_getbot_entry = uep;
644     }
645 
646     if (size > 0)
647     {
648 	if ((uep->ue_array = (char_u **)U_ALLOC_LINE(
649 					    sizeof(char_u *) * size)) == NULL)
650 	{
651 	    u_freeentry(uep, 0L);
652 	    goto nomem;
653 	}
654 	for (i = 0, lnum = top + 1; i < size; ++i)
655 	{
656 	    fast_breakcheck();
657 	    if (got_int)
658 	    {
659 		u_freeentry(uep, i);
660 		return FAIL;
661 	    }
662 	    if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL)
663 	    {
664 		u_freeentry(uep, i);
665 		goto nomem;
666 	    }
667 	}
668     }
669     else
670 	uep->ue_array = NULL;
671     uep->ue_next = curbuf->b_u_newhead->uh_entry;
672     curbuf->b_u_newhead->uh_entry = uep;
673     curbuf->b_u_synced = FALSE;
674     undo_undoes = FALSE;
675 
676 #ifdef U_DEBUG
677     u_check(FALSE);
678 #endif
679     return OK;
680 
681 nomem:
682     msg_silent = 0;	/* must display the prompt */
683     if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE)
684 								       == 'y')
685     {
686 	undo_off = TRUE;	    /* will be reset when character typed */
687 	return OK;
688     }
689     do_outofmem_msg((long_u)0);
690     return FAIL;
691 }
692 
693 #if defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
694 
695 # define UF_START_MAGIC	    "Vim\237UnDo\345"  /* magic at start of undofile */
696 # define UF_START_MAGIC_LEN	9
697 # define UF_HEADER_MAGIC	0x5fd0	/* magic at start of header */
698 # define UF_HEADER_END_MAGIC	0xe7aa	/* magic after last header */
699 # define UF_ENTRY_MAGIC		0xf518	/* magic at start of entry */
700 # define UF_ENTRY_END_MAGIC	0x3581	/* magic after last entry */
701 # define UF_VERSION		2	/* 2-byte undofile version number */
702 # define UF_VERSION_CRYPT	0x8002	/* idem, encrypted */
703 
704 /* extra fields for header */
705 # define UF_LAST_SAVE_NR	1
706 
707 /* extra fields for uhp */
708 # define UHP_SAVE_NR		1
709 
710 static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
711 
712 /*
713  * Compute the hash for the current buffer text into hash[UNDO_HASH_SIZE].
714  */
715     void
716 u_compute_hash(hash)
717     char_u *hash;
718 {
719     context_sha256_T	ctx;
720     linenr_T		lnum;
721     char_u		*p;
722 
723     sha256_start(&ctx);
724     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
725     {
726 	p = ml_get(lnum);
727 	sha256_update(&ctx, p, (UINT32_T)(STRLEN(p) + 1));
728     }
729     sha256_finish(&ctx, hash);
730 }
731 
732 /*
733  * Return an allocated string of the full path of the target undofile.
734  * When "reading" is TRUE find the file to read, go over all directories in
735  * 'undodir'.
736  * When "reading" is FALSE use the first name where the directory exists.
737  * Returns NULL when there is no place to write or no file to read.
738  */
739     char_u *
740 u_get_undo_file_name(buf_ffname, reading)
741     char_u	*buf_ffname;
742     int		reading;
743 {
744     char_u	*dirp;
745     char_u	dir_name[IOSIZE + 1];
746     char_u	*munged_name = NULL;
747     char_u	*undo_file_name = NULL;
748     int		dir_len;
749     char_u	*p;
750     struct stat st;
751     char_u	*ffname = buf_ffname;
752 #ifdef HAVE_READLINK
753     char_u	fname_buf[MAXPATHL];
754 #endif
755 
756     if (ffname == NULL)
757 	return NULL;
758 
759 #ifdef HAVE_READLINK
760     /* Expand symlink in the file name, so that we put the undo file with the
761      * actual file instead of with the symlink. */
762     if (resolve_symlink(ffname, fname_buf) == OK)
763 	ffname = fname_buf;
764 #endif
765 
766     /* Loop over 'undodir'.  When reading find the first file that exists.
767      * When not reading use the first directory that exists or ".". */
768     dirp = p_udir;
769     while (*dirp != NUL)
770     {
771 	dir_len = copy_option_part(&dirp, dir_name, IOSIZE, ",");
772 	if (dir_len == 1 && dir_name[0] == '.')
773 	{
774 	    /* Use same directory as the ffname,
775 	     * "dir/name" -> "dir/.name.un~" */
776 	    undo_file_name = vim_strnsave(ffname, (int)(STRLEN(ffname) + 5));
777 	    if (undo_file_name == NULL)
778 		break;
779 	    p = gettail(undo_file_name);
780 	    mch_memmove(p + 1, p, STRLEN(p) + 1);
781 	    *p = '.';
782 	    STRCAT(p, ".un~");
783 	}
784 	else
785 	{
786 	    dir_name[dir_len] = NUL;
787 	    if (mch_isdir(dir_name))
788 	    {
789 		if (munged_name == NULL)
790 		{
791 		    munged_name = vim_strsave(ffname);
792 		    if (munged_name == NULL)
793 			return NULL;
794 		    for (p = munged_name; *p != NUL; mb_ptr_adv(p))
795 			if (vim_ispathsep(*p))
796 			    *p = '%';
797 		}
798 		undo_file_name = concat_fnames(dir_name, munged_name, TRUE);
799 	    }
800 	}
801 
802 	/* When reading check if the file exists. */
803 	if (undo_file_name != NULL && (!reading
804 			       || mch_stat((char *)undo_file_name, &st) >= 0))
805 	    break;
806 	vim_free(undo_file_name);
807 	undo_file_name = NULL;
808     }
809 
810     vim_free(munged_name);
811     return undo_file_name;
812 }
813 
814     static void
815 corruption_error(mesg, file_name)
816     char *mesg;
817     char_u *file_name;
818 {
819     EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name);
820 }
821 
822     static void
823 u_free_uhp(uhp)
824     u_header_T	*uhp;
825 {
826     u_entry_T	*nuep;
827     u_entry_T	*uep;
828 
829     uep = uhp->uh_entry;
830     while (uep != NULL)
831     {
832 	nuep = uep->ue_next;
833 	u_freeentry(uep, uep->ue_size);
834 	uep = nuep;
835     }
836     vim_free(uhp);
837 }
838 
839 /*
840  * Like fwrite() but crypt the bytes when 'key' is set.
841  * Returns 1 if successful.
842  */
843     static size_t
844 fwrite_crypt(buf, ptr, len, fp)
845     buf_T	*buf UNUSED;
846     char_u	*ptr;
847     size_t	len;
848     FILE	*fp;
849 {
850 #ifdef FEAT_CRYPT
851     char_u  *copy;
852     char_u  small_buf[100];
853     size_t  i;
854 
855     if (*buf->b_p_key == NUL)
856 	return fwrite(ptr, len, (size_t)1, fp);
857     if (len < 100)
858 	copy = small_buf;  /* no malloc()/free() for short strings */
859     else
860     {
861 	copy = lalloc(len, FALSE);
862 	if (copy == NULL)
863 	    return 0;
864     }
865     crypt_encode(ptr, len, copy);
866     i = fwrite(copy, len, (size_t)1, fp);
867     if (copy != small_buf)
868 	vim_free(copy);
869     return i;
870 #else
871     return fwrite(ptr, len, (size_t)1, fp);
872 #endif
873 }
874 
875 /*
876  * Read a string of length "len" from "fd".
877  * When 'key' is set decrypt the bytes.
878  */
879     static char_u *
880 read_string_decrypt(buf, fd, len)
881     buf_T   *buf UNUSED;
882     FILE    *fd;
883     int	    len;
884 {
885     char_u  *ptr;
886 
887     ptr = read_string(fd, len);
888 #ifdef FEAT_CRYPT
889     if (ptr != NULL && *buf->b_p_key != NUL)
890 	crypt_decode(ptr, len);
891 #endif
892     return ptr;
893 }
894 
895     static int
896 serialize_header(fp, buf, hash)
897     FILE	*fp;
898     buf_T	*buf;
899     char_u	*hash;
900 {
901     int len;
902 
903     /* Start writing, first the magic marker and undo info version. */
904     if (fwrite(UF_START_MAGIC, (size_t)UF_START_MAGIC_LEN, (size_t)1, fp) != 1)
905 	return FAIL;
906 
907     /* If the buffer is encrypted then all text bytes following will be
908      * encrypted.  Numbers and other info is not crypted. */
909 #ifdef FEAT_CRYPT
910     if (*buf->b_p_key != NUL)
911     {
912 	char_u *header;
913 	int    header_len;
914 
915 	put_bytes(fp, (long_u)UF_VERSION_CRYPT, 2);
916 	header = prepare_crypt_write(buf, &header_len);
917 	if (header == NULL)
918 	    return FAIL;
919 	len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp);
920 	vim_free(header);
921 	if (len != 1)
922 	{
923 	    crypt_pop_state();
924 	    return FAIL;
925 	}
926     }
927     else
928 #endif
929 	put_bytes(fp, (long_u)UF_VERSION, 2);
930 
931 
932     /* Write a hash of the buffer text, so that we can verify it is still the
933      * same when reading the buffer text. */
934     if (fwrite(hash, (size_t)UNDO_HASH_SIZE, (size_t)1, fp) != 1)
935 	return FAIL;
936 
937     /* buffer-specific data */
938     put_bytes(fp, (long_u)buf->b_ml.ml_line_count, 4);
939     len = buf->b_u_line_ptr != NULL ? (int)STRLEN(buf->b_u_line_ptr) : 0;
940     put_bytes(fp, (long_u)len, 4);
941     if (len > 0 && fwrite_crypt(buf, buf->b_u_line_ptr, (size_t)len, fp) != 1)
942 	return FAIL;
943     put_bytes(fp, (long_u)buf->b_u_line_lnum, 4);
944     put_bytes(fp, (long_u)buf->b_u_line_colnr, 4);
945 
946     /* Undo structures header data */
947     put_header_ptr(fp, buf->b_u_oldhead);
948     put_header_ptr(fp, buf->b_u_newhead);
949     put_header_ptr(fp, buf->b_u_curhead);
950 
951     put_bytes(fp, (long_u)buf->b_u_numhead, 4);
952     put_bytes(fp, (long_u)buf->b_u_seq_last, 4);
953     put_bytes(fp, (long_u)buf->b_u_seq_cur, 4);
954     put_time(fp, buf->b_u_time_cur);
955 
956     /* Optional fields. */
957     putc(4, fp);
958     putc(UF_LAST_SAVE_NR, fp);
959     put_bytes(fp, (long_u)buf->b_u_save_nr_last, 4);
960 
961     putc(0, fp);  /* end marker */
962 
963     return OK;
964 }
965 
966     static int
967 serialize_uhp(fp, buf, uhp)
968     FILE	*fp;
969     buf_T	*buf;
970     u_header_T	*uhp;
971 {
972     int		i;
973     u_entry_T	*uep;
974 
975     if (put_bytes(fp, (long_u)UF_HEADER_MAGIC, 2) == FAIL)
976 	return FAIL;
977 
978     put_header_ptr(fp, uhp->uh_next.ptr);
979     put_header_ptr(fp, uhp->uh_prev.ptr);
980     put_header_ptr(fp, uhp->uh_alt_next.ptr);
981     put_header_ptr(fp, uhp->uh_alt_prev.ptr);
982     put_bytes(fp, uhp->uh_seq, 4);
983     serialize_pos(uhp->uh_cursor, fp);
984 #ifdef FEAT_VIRTUALEDIT
985     put_bytes(fp, (long_u)uhp->uh_cursor_vcol, 4);
986 #else
987     put_bytes(fp, (long_u)0, 4);
988 #endif
989     put_bytes(fp, (long_u)uhp->uh_flags, 2);
990     /* Assume NMARKS will stay the same. */
991     for (i = 0; i < NMARKS; ++i)
992 	serialize_pos(uhp->uh_namedm[i], fp);
993 #ifdef FEAT_VISUAL
994     serialize_visualinfo(&uhp->uh_visual, fp);
995 #else
996     {
997 	visualinfo_T info;
998 
999 	memset(&info, 0, sizeof(visualinfo_T));
1000 	serialize_visualinfo(&info, fp);
1001     }
1002 #endif
1003     put_time(fp, uhp->uh_time);
1004 
1005     /* Optional fields. */
1006     putc(4, fp);
1007     putc(UHP_SAVE_NR, fp);
1008     put_bytes(fp, (long_u)uhp->uh_save_nr, 4);
1009 
1010     putc(0, fp);  /* end marker */
1011 
1012     /* Write all the entries. */
1013     for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
1014     {
1015 	put_bytes(fp, (long_u)UF_ENTRY_MAGIC, 2);
1016 	if (serialize_uep(fp, buf, uep) == FAIL)
1017 	    return FAIL;
1018     }
1019     put_bytes(fp, (long_u)UF_ENTRY_END_MAGIC, 2);
1020     return OK;
1021 }
1022 
1023     static u_header_T *
1024 unserialize_uhp(fp, file_name)
1025     FILE	*fp;
1026     char_u	*file_name;
1027 {
1028     u_header_T	*uhp;
1029     int		i;
1030     u_entry_T	*uep, *last_uep;
1031     int		c;
1032     int		error;
1033 
1034     uhp = (u_header_T *)U_ALLOC_LINE(sizeof(u_header_T));
1035     if (uhp == NULL)
1036 	return NULL;
1037     vim_memset(uhp, 0, sizeof(u_header_T));
1038 #ifdef U_DEBUG
1039     uhp->uh_magic = UH_MAGIC;
1040 #endif
1041     uhp->uh_next.seq = get4c(fp);
1042     uhp->uh_prev.seq = get4c(fp);
1043     uhp->uh_alt_next.seq = get4c(fp);
1044     uhp->uh_alt_prev.seq = get4c(fp);
1045     uhp->uh_seq = get4c(fp);
1046     if (uhp->uh_seq <= 0)
1047     {
1048 	corruption_error("uh_seq", file_name);
1049 	vim_free(uhp);
1050 	return NULL;
1051     }
1052     unserialize_pos(&uhp->uh_cursor, fp);
1053 #ifdef FEAT_VIRTUALEDIT
1054     uhp->uh_cursor_vcol = get4c(fp);
1055 #else
1056     (void)get4c(fp);
1057 #endif
1058     uhp->uh_flags = get2c(fp);
1059     for (i = 0; i < NMARKS; ++i)
1060 	unserialize_pos(&uhp->uh_namedm[i], fp);
1061 #ifdef FEAT_VISUAL
1062     unserialize_visualinfo(&uhp->uh_visual, fp);
1063 #else
1064     {
1065 	visualinfo_T info;
1066 	unserialize_visualinfo(&info, fp);
1067     }
1068 #endif
1069     uhp->uh_time = get8ctime(fp);
1070 
1071     /* Optional fields. */
1072     for (;;)
1073     {
1074 	int len = getc(fp);
1075 	int what;
1076 
1077 	if (len == 0)
1078 	    break;
1079 	what = getc(fp);
1080 	switch (what)
1081 	{
1082 	    case UHP_SAVE_NR:
1083 		uhp->uh_save_nr = get4c(fp);
1084 		break;
1085 	    default:
1086 		/* field not supported, skip */
1087 		while (--len >= 0)
1088 		    (void)getc(fp);
1089 	}
1090     }
1091 
1092     /* Unserialize the uep list. */
1093     last_uep = NULL;
1094     while ((c = get2c(fp)) == UF_ENTRY_MAGIC)
1095     {
1096 	error = FALSE;
1097 	uep = unserialize_uep(fp, &error, file_name);
1098 	if (last_uep == NULL)
1099 	    uhp->uh_entry = uep;
1100 	else
1101 	    last_uep->ue_next = uep;
1102 	last_uep = uep;
1103 	if (uep == NULL || error)
1104 	{
1105 	    u_free_uhp(uhp);
1106 	    return NULL;
1107 	}
1108     }
1109     if (c != UF_ENTRY_END_MAGIC)
1110     {
1111 	corruption_error("entry end", file_name);
1112 	u_free_uhp(uhp);
1113 	return NULL;
1114     }
1115 
1116     return uhp;
1117 }
1118 
1119 /*
1120  * Serialize "uep" to "fp".
1121  */
1122     static int
1123 serialize_uep(fp, buf, uep)
1124     FILE	*fp;
1125     buf_T	*buf;
1126     u_entry_T	*uep;
1127 {
1128     int		i;
1129     size_t	len;
1130 
1131     put_bytes(fp, (long_u)uep->ue_top, 4);
1132     put_bytes(fp, (long_u)uep->ue_bot, 4);
1133     put_bytes(fp, (long_u)uep->ue_lcount, 4);
1134     put_bytes(fp, (long_u)uep->ue_size, 4);
1135     for (i = 0; i < uep->ue_size; ++i)
1136     {
1137 	len = STRLEN(uep->ue_array[i]);
1138 	if (put_bytes(fp, (long_u)len, 4) == FAIL)
1139 	    return FAIL;
1140 	if (len > 0 && fwrite_crypt(buf, uep->ue_array[i], len, fp) != 1)
1141 	    return FAIL;
1142     }
1143     return OK;
1144 }
1145 
1146     static u_entry_T *
1147 unserialize_uep(fp, error, file_name)
1148     FILE	*fp;
1149     int		*error;
1150     char_u	*file_name;
1151 {
1152     int		i;
1153     u_entry_T	*uep;
1154     char_u	**array;
1155     char_u	*line;
1156     int		line_len;
1157 
1158     uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T));
1159     if (uep == NULL)
1160 	return NULL;
1161     vim_memset(uep, 0, sizeof(u_entry_T));
1162 #ifdef U_DEBUG
1163     uep->ue_magic = UE_MAGIC;
1164 #endif
1165     uep->ue_top = get4c(fp);
1166     uep->ue_bot = get4c(fp);
1167     uep->ue_lcount = get4c(fp);
1168     uep->ue_size = get4c(fp);
1169     if (uep->ue_size > 0)
1170     {
1171 	array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size);
1172 	if (array == NULL)
1173 	{
1174 	    *error = TRUE;
1175 	    return uep;
1176 	}
1177 	vim_memset(array, 0, sizeof(char_u *) * uep->ue_size);
1178     }
1179     else
1180 	array = NULL;
1181     uep->ue_array = array;
1182 
1183     for (i = 0; i < uep->ue_size; ++i)
1184     {
1185 	line_len = get4c(fp);
1186 	if (line_len >= 0)
1187 	    line = read_string_decrypt(curbuf, fp, line_len);
1188 	else
1189 	{
1190 	    line = NULL;
1191 	    corruption_error("line length", file_name);
1192 	}
1193 	if (line == NULL)
1194 	{
1195 	    *error = TRUE;
1196 	    return uep;
1197 	}
1198 	array[i] = line;
1199     }
1200     return uep;
1201 }
1202 
1203 /*
1204  * Serialize "pos" to "fp".
1205  */
1206     static void
1207 serialize_pos(pos, fp)
1208     pos_T pos;
1209     FILE  *fp;
1210 {
1211     put_bytes(fp, (long_u)pos.lnum, 4);
1212     put_bytes(fp, (long_u)pos.col, 4);
1213 #ifdef FEAT_VIRTUALEDIT
1214     put_bytes(fp, (long_u)pos.coladd, 4);
1215 #else
1216     put_bytes(fp, (long_u)0, 4);
1217 #endif
1218 }
1219 
1220 /*
1221  * Unserialize the pos_T at the current position in fp.
1222  */
1223     static void
1224 unserialize_pos(pos, fp)
1225     pos_T *pos;
1226     FILE  *fp;
1227 {
1228     pos->lnum = get4c(fp);
1229     if (pos->lnum < 0)
1230 	pos->lnum = 0;
1231     pos->col = get4c(fp);
1232     if (pos->col < 0)
1233 	pos->col = 0;
1234 #ifdef FEAT_VIRTUALEDIT
1235     pos->coladd = get4c(fp);
1236     if (pos->coladd < 0)
1237 	pos->coladd = 0;
1238 #else
1239     (void)get4c(fp);
1240 #endif
1241 }
1242 
1243 /*
1244  * Serialize "info" to "fp".
1245  */
1246     static void
1247 serialize_visualinfo(info, fp)
1248     visualinfo_T    *info;
1249     FILE	    *fp;
1250 {
1251     serialize_pos(info->vi_start, fp);
1252     serialize_pos(info->vi_end, fp);
1253     put_bytes(fp, (long_u)info->vi_mode, 4);
1254     put_bytes(fp, (long_u)info->vi_curswant, 4);
1255 }
1256 
1257 /*
1258  * Unserialize the visualinfo_T at the current position in fp.
1259  */
1260     static void
1261 unserialize_visualinfo(info, fp)
1262     visualinfo_T    *info;
1263     FILE	    *fp;
1264 {
1265     unserialize_pos(&info->vi_start, fp);
1266     unserialize_pos(&info->vi_end, fp);
1267     info->vi_mode = get4c(fp);
1268     info->vi_curswant = get4c(fp);
1269 }
1270 
1271 /*
1272  * Write the pointer to an undo header.  Instead of writing the pointer itself
1273  * we use the sequence number of the header.  This is converted back to
1274  * pointers when reading. */
1275     static void
1276 put_header_ptr(fp, uhp)
1277     FILE	*fp;
1278     u_header_T	*uhp;
1279 {
1280     put_bytes(fp, (long_u)(uhp != NULL ? uhp->uh_seq : 0), 4);
1281 }
1282 
1283 /*
1284  * Write the undo tree in an undo file.
1285  * When "name" is not NULL, use it as the name of the undo file.
1286  * Otherwise use buf->b_ffname to generate the undo file name.
1287  * "buf" must never be null, buf->b_ffname is used to obtain the original file
1288  * permissions.
1289  * "forceit" is TRUE for ":wundo!", FALSE otherwise.
1290  * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
1291  */
1292     void
1293 u_write_undo(name, forceit, buf, hash)
1294     char_u	*name;
1295     int		forceit;
1296     buf_T	*buf;
1297     char_u	*hash;
1298 {
1299     u_header_T	*uhp;
1300     char_u	*file_name;
1301     int		mark;
1302 #ifdef U_DEBUG
1303     int		headers_written = 0;
1304 #endif
1305     int		fd;
1306     FILE	*fp = NULL;
1307     int		perm;
1308     int		write_ok = FALSE;
1309 #ifdef UNIX
1310     int		st_old_valid = FALSE;
1311     struct stat	st_old;
1312     struct stat	st_new;
1313 #endif
1314 #ifdef FEAT_CRYPT
1315     int		do_crypt = FALSE;
1316 #endif
1317 
1318     if (name == NULL)
1319     {
1320 	file_name = u_get_undo_file_name(buf->b_ffname, FALSE);
1321 	if (file_name == NULL)
1322 	{
1323 	    if (p_verbose > 0)
1324 	    {
1325 		verbose_enter();
1326 		smsg((char_u *)
1327 		   _("Cannot write undo file in any directory in 'undodir'"));
1328 		verbose_leave();
1329 	    }
1330 	    return;
1331 	}
1332     }
1333     else
1334 	file_name = name;
1335 
1336     /*
1337      * Decide about the permission to use for the undo file.  If the buffer
1338      * has a name use the permission of the original file.  Otherwise only
1339      * allow the user to access the undo file.
1340      */
1341     perm = 0600;
1342     if (buf->b_ffname != NULL)
1343     {
1344 #ifdef UNIX
1345 	if (mch_stat((char *)buf->b_ffname, &st_old) >= 0)
1346 	{
1347 	    perm = st_old.st_mode;
1348 	    st_old_valid = TRUE;
1349 	}
1350 #else
1351 	perm = mch_getperm(buf->b_ffname);
1352 	if (perm < 0)
1353 	    perm = 0600;
1354 #endif
1355     }
1356 
1357     /* strip any s-bit */
1358     perm = perm & 0777;
1359 
1360     /* If the undo file already exists, verify that it actually is an undo
1361      * file, and delete it. */
1362     if (mch_getperm(file_name) >= 0)
1363     {
1364 	if (name == NULL || !forceit)
1365 	{
1366 	    /* Check we can read it and it's an undo file. */
1367 	    fd = mch_open((char *)file_name, O_RDONLY|O_EXTRA, 0);
1368 	    if (fd < 0)
1369 	    {
1370 		if (name != NULL || p_verbose > 0)
1371 		{
1372 		    if (name == NULL)
1373 			verbose_enter();
1374 		    smsg((char_u *)
1375 		      _("Will not overwrite with undo file, cannot read: %s"),
1376 								   file_name);
1377 		    if (name == NULL)
1378 			verbose_leave();
1379 		}
1380 		goto theend;
1381 	    }
1382 	    else
1383 	    {
1384 		char_u	mbuf[UF_START_MAGIC_LEN];
1385 		int	len;
1386 
1387 		len = read_eintr(fd, mbuf, UF_START_MAGIC_LEN);
1388 		close(fd);
1389 		if (len < UF_START_MAGIC_LEN
1390 		      || memcmp(mbuf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0)
1391 		{
1392 		    if (name != NULL || p_verbose > 0)
1393 		    {
1394 			if (name == NULL)
1395 			    verbose_enter();
1396 			smsg((char_u *)
1397 			_("Will not overwrite, this is not an undo file: %s"),
1398 								   file_name);
1399 			if (name == NULL)
1400 			    verbose_leave();
1401 		    }
1402 		    goto theend;
1403 		}
1404 	    }
1405 	}
1406 	mch_remove(file_name);
1407     }
1408 
1409     /* If there is no undo information at all, quit here after deleting any
1410      * existing undo file. */
1411     if (buf->b_u_numhead == 0 && buf->b_u_line_ptr == NULL)
1412     {
1413 	if (p_verbose > 0)
1414 	    verb_msg((char_u *)_("Skipping undo file write, nothing to undo"));
1415 	goto theend;
1416     }
1417 
1418     fd = mch_open((char *)file_name,
1419 			    O_CREAT|O_EXTRA|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
1420     if (fd < 0)
1421     {
1422 	EMSG2(_(e_not_open), file_name);
1423 	goto theend;
1424     }
1425     (void)mch_setperm(file_name, perm);
1426     if (p_verbose > 0)
1427     {
1428 	verbose_enter();
1429 	smsg((char_u *)_("Writing undo file: %s"), file_name);
1430 	verbose_leave();
1431     }
1432 
1433 #ifdef U_DEBUG
1434     /* Check there is no problem in undo info before writing. */
1435     u_check(FALSE);
1436 #endif
1437 
1438 #ifdef UNIX
1439     /*
1440      * Try to set the group of the undo file same as the original file. If
1441      * this fails, set the protection bits for the group same as the
1442      * protection bits for others.
1443      */
1444     if (st_old_valid
1445 	    && mch_stat((char *)file_name, &st_new) >= 0
1446 	    && st_new.st_gid != st_old.st_gid
1447 # ifdef HAVE_FCHOWN  /* sequent-ptx lacks fchown() */
1448 	    && fchown(fd, (uid_t)-1, st_old.st_gid) != 0
1449 # endif
1450        )
1451 	mch_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
1452 # ifdef HAVE_SELINUX
1453     if (buf->b_ffname != NULL)
1454 	mch_copy_sec(buf->b_ffname, file_name);
1455 # endif
1456 #endif
1457 
1458     fp = fdopen(fd, "w");
1459     if (fp == NULL)
1460     {
1461 	EMSG2(_(e_not_open), file_name);
1462 	close(fd);
1463 	mch_remove(file_name);
1464 	goto theend;
1465     }
1466 
1467     /* Undo must be synced. */
1468     u_sync(TRUE);
1469 
1470     /*
1471      * Write the header.
1472      */
1473     if (serialize_header(fp, buf, hash) == FAIL)
1474 	goto write_error;
1475 #ifdef FEAT_CRYPT
1476     if (*buf->b_p_key != NUL)
1477 	do_crypt = TRUE;
1478 #endif
1479 
1480     /*
1481      * Iteratively serialize UHPs and their UEPs from the top down.
1482      */
1483     mark = ++lastmark;
1484     uhp = buf->b_u_oldhead;
1485     while (uhp != NULL)
1486     {
1487 	/* Serialize current UHP if we haven't seen it */
1488 	if (uhp->uh_walk != mark)
1489 	{
1490 	    uhp->uh_walk = mark;
1491 #ifdef U_DEBUG
1492 	    ++headers_written;
1493 #endif
1494 	    if (serialize_uhp(fp, buf, uhp) == FAIL)
1495 		goto write_error;
1496 	}
1497 
1498 	/* Now walk through the tree - algorithm from undo_time(). */
1499 	if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark)
1500 	    uhp = uhp->uh_prev.ptr;
1501 	else if (uhp->uh_alt_next.ptr != NULL
1502 				     && uhp->uh_alt_next.ptr->uh_walk != mark)
1503 	    uhp = uhp->uh_alt_next.ptr;
1504 	else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
1505 					 && uhp->uh_next.ptr->uh_walk != mark)
1506 	    uhp = uhp->uh_next.ptr;
1507 	else if (uhp->uh_alt_prev.ptr != NULL)
1508 	    uhp = uhp->uh_alt_prev.ptr;
1509 	else
1510 	    uhp = uhp->uh_next.ptr;
1511     }
1512 
1513     if (put_bytes(fp, (long_u)UF_HEADER_END_MAGIC, 2) == OK)
1514 	write_ok = TRUE;
1515 #ifdef U_DEBUG
1516     if (headers_written != buf->b_u_numhead)
1517 	EMSG3("Written %ld headers, but numhead is %ld",
1518 					   headers_written, buf->b_u_numhead);
1519 #endif
1520 
1521 write_error:
1522     fclose(fp);
1523     if (!write_ok)
1524 	EMSG2(_("E829: write error in undo file: %s"), file_name);
1525 
1526 #if defined(MACOS_CLASSIC) || defined(WIN3264)
1527     /* Copy file attributes; for systems where this can only be done after
1528      * closing the file. */
1529     if (buf->b_ffname != NULL)
1530 	(void)mch_copy_file_attribute(buf->b_ffname, file_name);
1531 #endif
1532 #ifdef HAVE_ACL
1533     if (buf->b_ffname != NULL)
1534     {
1535 	vim_acl_T	    acl;
1536 
1537 	/* For systems that support ACL: get the ACL from the original file. */
1538 	acl = mch_get_acl(buf->b_ffname);
1539 	mch_set_acl(file_name, acl);
1540 	mch_free_acl(acl);
1541     }
1542 #endif
1543 
1544 theend:
1545 #ifdef FEAT_CRYPT
1546     if (do_crypt)
1547 	crypt_pop_state();
1548 #endif
1549     if (file_name != name)
1550 	vim_free(file_name);
1551 }
1552 
1553 /*
1554  * Load the undo tree from an undo file.
1555  * If "name" is not NULL use it as the undo file name.  This also means being
1556  * a bit more verbose.
1557  * Otherwise use curbuf->b_ffname to generate the undo file name.
1558  * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
1559  */
1560     void
1561 u_read_undo(name, hash, orig_name)
1562     char_u *name;
1563     char_u *hash;
1564     char_u *orig_name;
1565 {
1566     char_u	*file_name;
1567     FILE	*fp;
1568     long	version, str_len;
1569     char_u	*line_ptr = NULL;
1570     linenr_T	line_lnum;
1571     colnr_T	line_colnr;
1572     linenr_T	line_count;
1573     int		num_head = 0;
1574     long	old_header_seq, new_header_seq, cur_header_seq;
1575     long	seq_last, seq_cur;
1576     long	last_save_nr = 0;
1577     short	old_idx = -1, new_idx = -1, cur_idx = -1;
1578     long	num_read_uhps = 0;
1579     time_t	seq_time;
1580     int		i, j;
1581     int		c;
1582     u_header_T	*uhp;
1583     u_header_T	**uhp_table = NULL;
1584     char_u	read_hash[UNDO_HASH_SIZE];
1585     char_u	magic_buf[UF_START_MAGIC_LEN];
1586 #ifdef U_DEBUG
1587     int		*uhp_table_used;
1588 #endif
1589 #ifdef UNIX
1590     struct stat	st_orig;
1591     struct stat	st_undo;
1592 #endif
1593 #ifdef FEAT_CRYPT
1594     int		do_decrypt = FALSE;
1595 #endif
1596 
1597     if (name == NULL)
1598     {
1599 	file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE);
1600 	if (file_name == NULL)
1601 	    return;
1602 
1603 #ifdef UNIX
1604 	/* For safety we only read an undo file if the owner is equal to the
1605 	 * owner of the text file. */
1606 	if (mch_stat((char *)orig_name, &st_orig) >= 0
1607 		&& mch_stat((char *)file_name, &st_undo) >= 0
1608 		&& st_orig.st_uid != st_undo.st_uid)
1609 	{
1610 	    if (p_verbose > 0)
1611 	    {
1612 		verbose_enter();
1613 		smsg((char_u *)_("Not reading undo file, owner differs: %s"),
1614 								   file_name);
1615 		verbose_leave();
1616 	    }
1617 	    return;
1618 	}
1619 #endif
1620     }
1621     else
1622 	file_name = name;
1623 
1624     if (p_verbose > 0)
1625     {
1626 	verbose_enter();
1627 	smsg((char_u *)_("Reading undo file: %s"), file_name);
1628 	verbose_leave();
1629     }
1630 
1631     fp = mch_fopen((char *)file_name, "r");
1632     if (fp == NULL)
1633     {
1634 	if (name != NULL || p_verbose > 0)
1635 	    EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name);
1636 	goto error;
1637     }
1638 
1639     /*
1640      * Read the undo file header.
1641      */
1642     if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1
1643 		|| memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0)
1644     {
1645 	EMSG2(_("E823: Not an undo file: %s"), file_name);
1646 	goto error;
1647     }
1648     version = get2c(fp);
1649     if (version == UF_VERSION_CRYPT)
1650     {
1651 #ifdef FEAT_CRYPT
1652 	if (*curbuf->b_p_key == NUL)
1653 	{
1654 	    EMSG2(_("E832: Non-encrypted file has encrypted undo file: %s"),
1655 								   file_name);
1656 	    goto error;
1657 	}
1658 	if (prepare_crypt_read(fp) == FAIL)
1659 	{
1660 	    EMSG2(_("E826: Undo file decryption failed: %s"), file_name);
1661 	    goto error;
1662 	}
1663 	do_decrypt = TRUE;
1664 #else
1665 	EMSG2(_("E827: Undo file is encrypted: %s"), file_name);
1666 	goto error;
1667 #endif
1668     }
1669     else if (version != UF_VERSION)
1670     {
1671 	EMSG2(_("E824: Incompatible undo file: %s"), file_name);
1672 	goto error;
1673     }
1674 
1675     if (fread(read_hash, UNDO_HASH_SIZE, 1, fp) != 1)
1676     {
1677 	corruption_error("hash", file_name);
1678 	goto error;
1679     }
1680     line_count = (linenr_T)get4c(fp);
1681     if (memcmp(hash, read_hash, UNDO_HASH_SIZE) != 0
1682 				  || line_count != curbuf->b_ml.ml_line_count)
1683     {
1684 	if (p_verbose > 0 || name != NULL)
1685 	{
1686 	    if (name == NULL)
1687 		verbose_enter();
1688 	    give_warning((char_u *)
1689 		      _("File contents changed, cannot use undo info"), TRUE);
1690 	    if (name == NULL)
1691 		verbose_leave();
1692 	}
1693 	goto error;
1694     }
1695 
1696     /* Read undo data for "U" command. */
1697     str_len = get4c(fp);
1698     if (str_len < 0)
1699 	goto error;
1700     if (str_len > 0)
1701 	line_ptr = read_string_decrypt(curbuf, fp, str_len);
1702     line_lnum = (linenr_T)get4c(fp);
1703     line_colnr = (colnr_T)get4c(fp);
1704     if (line_lnum < 0 || line_colnr < 0)
1705     {
1706 	corruption_error("line lnum/col", file_name);
1707 	goto error;
1708     }
1709 
1710     /* Begin general undo data */
1711     old_header_seq = get4c(fp);
1712     new_header_seq = get4c(fp);
1713     cur_header_seq = get4c(fp);
1714     num_head = get4c(fp);
1715     seq_last = get4c(fp);
1716     seq_cur = get4c(fp);
1717     seq_time = get8ctime(fp);
1718 
1719     /* Optional header fields. */
1720     for (;;)
1721     {
1722 	int len = getc(fp);
1723 	int what;
1724 
1725 	if (len == 0 || len == EOF)
1726 	    break;
1727 	what = getc(fp);
1728 	switch (what)
1729 	{
1730 	    case UF_LAST_SAVE_NR:
1731 		last_save_nr = get4c(fp);
1732 		break;
1733 	    default:
1734 		/* field not supported, skip */
1735 		while (--len >= 0)
1736 		    (void)getc(fp);
1737 	}
1738     }
1739 
1740     /* uhp_table will store the freshly created undo headers we allocate
1741      * until we insert them into curbuf. The table remains sorted by the
1742      * sequence numbers of the headers.
1743      * When there are no headers uhp_table is NULL. */
1744     if (num_head > 0)
1745     {
1746 	uhp_table = (u_header_T **)U_ALLOC_LINE(
1747 					     num_head * sizeof(u_header_T *));
1748 	if (uhp_table == NULL)
1749 	    goto error;
1750     }
1751 
1752     while ((c = get2c(fp)) == UF_HEADER_MAGIC)
1753     {
1754 	if (num_read_uhps >= num_head)
1755 	{
1756 	    corruption_error("num_head too small", file_name);
1757 	    goto error;
1758 	}
1759 
1760 	uhp = unserialize_uhp(fp, file_name);
1761 	if (uhp == NULL)
1762 	    goto error;
1763 	uhp_table[num_read_uhps++] = uhp;
1764     }
1765 
1766     if (num_read_uhps != num_head)
1767     {
1768 	corruption_error("num_head", file_name);
1769 	goto error;
1770     }
1771     if (c != UF_HEADER_END_MAGIC)
1772     {
1773 	corruption_error("end marker", file_name);
1774 	goto error;
1775     }
1776 
1777 #ifdef U_DEBUG
1778     uhp_table_used = (int *)alloc_clear(
1779 				     (unsigned)(sizeof(int) * num_head + 1));
1780 # define SET_FLAG(j) ++uhp_table_used[j]
1781 #else
1782 # define SET_FLAG(j)
1783 #endif
1784 
1785     /* We have put all of the headers into a table. Now we iterate through the
1786      * table and swizzle each sequence number we have stored in uh_*_seq into
1787      * a pointer corresponding to the header with that sequence number. */
1788     for (i = 0; i < num_head; i++)
1789     {
1790 	uhp = uhp_table[i];
1791 	if (uhp == NULL)
1792 	    continue;
1793 	for (j = 0; j < num_head; j++)
1794 	    if (uhp_table[j] != NULL && i != j
1795 			      && uhp_table[i]->uh_seq == uhp_table[j]->uh_seq)
1796 	    {
1797 		corruption_error("duplicate uh_seq", file_name);
1798 		goto error;
1799 	    }
1800 	for (j = 0; j < num_head; j++)
1801 	    if (uhp_table[j] != NULL
1802 				  && uhp_table[j]->uh_seq == uhp->uh_next.seq)
1803 	    {
1804 		uhp->uh_next.ptr = uhp_table[j];
1805 		SET_FLAG(j);
1806 		break;
1807 	    }
1808 	for (j = 0; j < num_head; j++)
1809 	    if (uhp_table[j] != NULL
1810 				  && uhp_table[j]->uh_seq == uhp->uh_prev.seq)
1811 	    {
1812 		uhp->uh_prev.ptr = uhp_table[j];
1813 		SET_FLAG(j);
1814 		break;
1815 	    }
1816 	for (j = 0; j < num_head; j++)
1817 	    if (uhp_table[j] != NULL
1818 			      && uhp_table[j]->uh_seq == uhp->uh_alt_next.seq)
1819 	    {
1820 		uhp->uh_alt_next.ptr = uhp_table[j];
1821 		SET_FLAG(j);
1822 		break;
1823 	    }
1824 	for (j = 0; j < num_head; j++)
1825 	    if (uhp_table[j] != NULL
1826 			      && uhp_table[j]->uh_seq == uhp->uh_alt_prev.seq)
1827 	    {
1828 		uhp->uh_alt_prev.ptr = uhp_table[j];
1829 		SET_FLAG(j);
1830 		break;
1831 	    }
1832 	if (old_header_seq > 0 && old_idx < 0 && uhp->uh_seq == old_header_seq)
1833 	{
1834 	    old_idx = i;
1835 	    SET_FLAG(i);
1836 	}
1837 	if (new_header_seq > 0 && new_idx < 0 && uhp->uh_seq == new_header_seq)
1838 	{
1839 	    new_idx = i;
1840 	    SET_FLAG(i);
1841 	}
1842 	if (cur_header_seq > 0 && cur_idx < 0 && uhp->uh_seq == cur_header_seq)
1843 	{
1844 	    cur_idx = i;
1845 	    SET_FLAG(i);
1846 	}
1847     }
1848 
1849     /* Now that we have read the undo info successfully, free the current undo
1850      * info and use the info from the file. */
1851     u_blockfree(curbuf);
1852     curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx];
1853     curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx];
1854     curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx];
1855     curbuf->b_u_line_ptr = line_ptr;
1856     curbuf->b_u_line_lnum = line_lnum;
1857     curbuf->b_u_line_colnr = line_colnr;
1858     curbuf->b_u_numhead = num_head;
1859     curbuf->b_u_seq_last = seq_last;
1860     curbuf->b_u_seq_cur = seq_cur;
1861     curbuf->b_u_time_cur = seq_time;
1862     curbuf->b_u_save_nr_last = last_save_nr;
1863     curbuf->b_u_save_nr_cur = last_save_nr;
1864 
1865     curbuf->b_u_synced = TRUE;
1866     vim_free(uhp_table);
1867 
1868 #ifdef U_DEBUG
1869     for (i = 0; i < num_head; ++i)
1870 	if (uhp_table_used[i] == 0)
1871 	    EMSGN("uhp_table entry %ld not used, leaking memory", i);
1872     vim_free(uhp_table_used);
1873     u_check(TRUE);
1874 #endif
1875 
1876     if (name != NULL)
1877 	smsg((char_u *)_("Finished reading undo file %s"), file_name);
1878     goto theend;
1879 
1880 error:
1881     vim_free(line_ptr);
1882     if (uhp_table != NULL)
1883     {
1884 	for (i = 0; i < num_read_uhps; i++)
1885 	    if (uhp_table[i] != NULL)
1886 		u_free_uhp(uhp_table[i]);
1887 	vim_free(uhp_table);
1888     }
1889 
1890 theend:
1891 #ifdef FEAT_CRYPT
1892     if (do_decrypt)
1893 	crypt_pop_state();
1894 #endif
1895     if (fp != NULL)
1896 	fclose(fp);
1897     if (file_name != name)
1898 	vim_free(file_name);
1899     return;
1900 }
1901 
1902 #endif /* FEAT_PERSISTENT_UNDO */
1903 
1904 
1905 /*
1906  * If 'cpoptions' contains 'u': Undo the previous undo or redo (vi compatible).
1907  * If 'cpoptions' does not contain 'u': Always undo.
1908  */
1909     void
1910 u_undo(count)
1911     int count;
1912 {
1913     /*
1914      * If we get an undo command while executing a macro, we behave like the
1915      * original vi. If this happens twice in one macro the result will not
1916      * be compatible.
1917      */
1918     if (curbuf->b_u_synced == FALSE)
1919     {
1920 	u_sync(TRUE);
1921 	count = 1;
1922     }
1923 
1924     if (vim_strchr(p_cpo, CPO_UNDO) == NULL)
1925 	undo_undoes = TRUE;
1926     else
1927 	undo_undoes = !undo_undoes;
1928     u_doit(count);
1929 }
1930 
1931 /*
1932  * If 'cpoptions' contains 'u': Repeat the previous undo or redo.
1933  * If 'cpoptions' does not contain 'u': Always redo.
1934  */
1935     void
1936 u_redo(count)
1937     int count;
1938 {
1939     if (vim_strchr(p_cpo, CPO_UNDO) == NULL)
1940 	undo_undoes = FALSE;
1941     u_doit(count);
1942 }
1943 
1944 /*
1945  * Undo or redo, depending on 'undo_undoes', 'count' times.
1946  */
1947     static void
1948 u_doit(startcount)
1949     int startcount;
1950 {
1951     int count = startcount;
1952 
1953     if (!undo_allowed())
1954 	return;
1955 
1956     u_newcount = 0;
1957     u_oldcount = 0;
1958     if (curbuf->b_ml.ml_flags & ML_EMPTY)
1959 	u_oldcount = -1;
1960     while (count--)
1961     {
1962 	/* Do the change warning now, so that it triggers FileChangedRO when
1963 	 * needed.  This may cause the file to be reloaded, that must happen
1964 	 * before we do anything, because it may change curbuf->b_u_curhead
1965 	 * and more. */
1966 	change_warning(0);
1967 
1968 	if (undo_undoes)
1969 	{
1970 	    if (curbuf->b_u_curhead == NULL)		/* first undo */
1971 		curbuf->b_u_curhead = curbuf->b_u_newhead;
1972 	    else if (p_ul > 0)				/* multi level undo */
1973 		/* get next undo */
1974 		curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next.ptr;
1975 	    /* nothing to undo */
1976 	    if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL)
1977 	    {
1978 		/* stick curbuf->b_u_curhead at end */
1979 		curbuf->b_u_curhead = curbuf->b_u_oldhead;
1980 		beep_flush();
1981 		if (count == startcount - 1)
1982 		{
1983 		    MSG(_("Already at oldest change"));
1984 		    return;
1985 		}
1986 		break;
1987 	    }
1988 
1989 	    u_undoredo(TRUE);
1990 	}
1991 	else
1992 	{
1993 	    if (curbuf->b_u_curhead == NULL || p_ul <= 0)
1994 	    {
1995 		beep_flush();	/* nothing to redo */
1996 		if (count == startcount - 1)
1997 		{
1998 		    MSG(_("Already at newest change"));
1999 		    return;
2000 		}
2001 		break;
2002 	    }
2003 
2004 	    u_undoredo(FALSE);
2005 
2006 	    /* Advance for next redo.  Set "newhead" when at the end of the
2007 	     * redoable changes. */
2008 	    if (curbuf->b_u_curhead->uh_prev.ptr == NULL)
2009 		curbuf->b_u_newhead = curbuf->b_u_curhead;
2010 	    curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev.ptr;
2011 	}
2012     }
2013     u_undo_end(undo_undoes, FALSE);
2014 }
2015 
2016 /*
2017  * Undo or redo over the timeline.
2018  * When "step" is negative go back in time, otherwise goes forward in time.
2019  * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as
2020  * seconds.
2021  * When "file" is TRUE use "step" as a number of file writes.
2022  * When "absolute" is TRUE use "step" as the sequence number to jump to.
2023  * "sec" must be FALSE then.
2024  */
2025     void
2026 undo_time(step, sec, file, absolute)
2027     long	step;
2028     int		sec;
2029     int		file;
2030     int		absolute;
2031 {
2032     long	    target;
2033     long	    closest;
2034     long	    closest_start;
2035     long	    closest_seq = 0;
2036     long	    val;
2037     u_header_T	    *uhp;
2038     u_header_T	    *last;
2039     int		    mark;
2040     int		    nomark;
2041     int		    round;
2042     int		    dosec = sec;
2043     int		    dofile = file;
2044     int		    above = FALSE;
2045     int		    did_undo = TRUE;
2046 
2047     /* First make sure the current undoable change is synced. */
2048     if (curbuf->b_u_synced == FALSE)
2049 	u_sync(TRUE);
2050 
2051     u_newcount = 0;
2052     u_oldcount = 0;
2053     if (curbuf->b_ml.ml_flags & ML_EMPTY)
2054 	u_oldcount = -1;
2055 
2056     /* "target" is the node below which we want to be.
2057      * Init "closest" to a value we can't reach. */
2058     if (absolute)
2059     {
2060 	target = step;
2061 	closest = -1;
2062     }
2063     else
2064     {
2065 	/* When doing computations with time_t subtract starttime, because
2066 	 * time_t converted to a long may result in a wrong number. */
2067 	if (dosec)
2068 	    target = (long)(curbuf->b_u_time_cur - starttime) + step;
2069 	else if (dofile)
2070 	{
2071 	    if (step < 0)
2072 	    {
2073 		/* Going back to a previous write. If there were changes after
2074 		 * the last write, count that as moving one file-write, so
2075 		 * that ":earlier 1f" undoes all changes since the last save. */
2076 		uhp = curbuf->b_u_curhead;
2077 		if (uhp != NULL)
2078 		    uhp = uhp->uh_next.ptr;
2079 		else
2080 		    uhp = curbuf->b_u_newhead;
2081 		if (uhp != NULL && uhp->uh_save_nr != 0)
2082 		    /* "uh_save_nr" was set in the last block, that means
2083 		     * there were no changes since the last write */
2084 		    target = curbuf->b_u_save_nr_cur + step;
2085 		else
2086 		    /* count the changes since the last write as one step */
2087 		    target = curbuf->b_u_save_nr_cur + step + 1;
2088 		if (target <= 0)
2089 		    /* Go to before first write: before the oldest change. Use
2090 		     * the sequence number for that. */
2091 		    dofile = FALSE;
2092 	    }
2093 	    else
2094 	    {
2095 		/* Moving forward to a newer write. */
2096 		target = curbuf->b_u_save_nr_cur + step;
2097 		if (target > curbuf->b_u_save_nr_last)
2098 		{
2099 		    /* Go to after last write: after the latest change. Use
2100 		     * the sequence number for that. */
2101 		    target = curbuf->b_u_seq_last + 1;
2102 		    dofile = FALSE;
2103 		}
2104 	    }
2105 	}
2106 	else
2107 	    target = curbuf->b_u_seq_cur + step;
2108 	if (step < 0)
2109 	{
2110 	    if (target < 0)
2111 		target = 0;
2112 	    closest = -1;
2113 	}
2114 	else
2115 	{
2116 	    if (dosec)
2117 		closest = (long)(time(NULL) - starttime + 1);
2118 	    else if (dofile)
2119 		closest = curbuf->b_u_save_nr_last + 2;
2120 	    else
2121 		closest = curbuf->b_u_seq_last + 2;
2122 	    if (target >= closest)
2123 		target = closest - 1;
2124 	}
2125     }
2126     closest_start = closest;
2127     closest_seq = curbuf->b_u_seq_cur;
2128 
2129     /*
2130      * May do this twice:
2131      * 1. Search for "target", update "closest" to the best match found.
2132      * 2. If "target" not found search for "closest".
2133      *
2134      * When using the closest time we use the sequence number in the second
2135      * round, because there may be several entries with the same time.
2136      */
2137     for (round = 1; round <= 2; ++round)
2138     {
2139 	/* Find the path from the current state to where we want to go.  The
2140 	 * desired state can be anywhere in the undo tree, need to go all over
2141 	 * it.  We put "nomark" in uh_walk where we have been without success,
2142 	 * "mark" where it could possibly be. */
2143 	mark = ++lastmark;
2144 	nomark = ++lastmark;
2145 
2146 	if (curbuf->b_u_curhead == NULL)	/* at leaf of the tree */
2147 	    uhp = curbuf->b_u_newhead;
2148 	else
2149 	    uhp = curbuf->b_u_curhead;
2150 
2151 	while (uhp != NULL)
2152 	{
2153 	    uhp->uh_walk = mark;
2154 	    if (dosec)
2155 		val = (long)(uhp->uh_time - starttime);
2156 	    else if (dofile)
2157 		val = uhp->uh_save_nr;
2158 	    else
2159 		val = uhp->uh_seq;
2160 
2161 	    if (round == 1 && !(dofile && val == 0))
2162 	    {
2163 		/* Remember the header that is closest to the target.
2164 		 * It must be at least in the right direction (checked with
2165 		 * "b_u_seq_cur").  When the timestamp is equal find the
2166 		 * highest/lowest sequence number. */
2167 		if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur
2168 			      : uhp->uh_seq > curbuf->b_u_seq_cur)
2169 			&& ((dosec && val == closest)
2170 			    ? (step < 0
2171 				? uhp->uh_seq < closest_seq
2172 				: uhp->uh_seq > closest_seq)
2173 			    : closest == closest_start
2174 				|| (val > target
2175 				    ? (closest > target
2176 					? val - target <= closest - target
2177 					: val - target <= target - closest)
2178 				    : (closest > target
2179 					? target - val <= closest - target
2180 					: target - val <= target - closest))))
2181 		{
2182 		    closest = val;
2183 		    closest_seq = uhp->uh_seq;
2184 		}
2185 	    }
2186 
2187 	    /* Quit searching when we found a match.  But when searching for a
2188 	     * time we need to continue looking for the best uh_seq. */
2189 	    if (target == val && !dosec)
2190 	    {
2191 		target = uhp->uh_seq;
2192 		break;
2193 	    }
2194 
2195 	    /* go down in the tree if we haven't been there */
2196 	    if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark
2197 					 && uhp->uh_prev.ptr->uh_walk != mark)
2198 		uhp = uhp->uh_prev.ptr;
2199 
2200 	    /* go to alternate branch if we haven't been there */
2201 	    else if (uhp->uh_alt_next.ptr != NULL
2202 		    && uhp->uh_alt_next.ptr->uh_walk != nomark
2203 		    && uhp->uh_alt_next.ptr->uh_walk != mark)
2204 		uhp = uhp->uh_alt_next.ptr;
2205 
2206 	    /* go up in the tree if we haven't been there and we are at the
2207 	     * start of alternate branches */
2208 	    else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
2209 		    && uhp->uh_next.ptr->uh_walk != nomark
2210 		    && uhp->uh_next.ptr->uh_walk != mark)
2211 	    {
2212 		/* If still at the start we don't go through this change. */
2213 		if (uhp == curbuf->b_u_curhead)
2214 		    uhp->uh_walk = nomark;
2215 		uhp = uhp->uh_next.ptr;
2216 	    }
2217 
2218 	    else
2219 	    {
2220 		/* need to backtrack; mark this node as useless */
2221 		uhp->uh_walk = nomark;
2222 		if (uhp->uh_alt_prev.ptr != NULL)
2223 		    uhp = uhp->uh_alt_prev.ptr;
2224 		else
2225 		    uhp = uhp->uh_next.ptr;
2226 	    }
2227 	}
2228 
2229 	if (uhp != NULL)    /* found it */
2230 	    break;
2231 
2232 	if (absolute)
2233 	{
2234 	    EMSGN(_("E830: Undo number %ld not found"), step);
2235 	    return;
2236 	}
2237 
2238 	if (closest == closest_start)
2239 	{
2240 	    if (step < 0)
2241 		MSG(_("Already at oldest change"));
2242 	    else
2243 		MSG(_("Already at newest change"));
2244 	    return;
2245 	}
2246 
2247 	target = closest_seq;
2248 	dosec = FALSE;
2249 	dofile = FALSE;
2250 	if (step < 0)
2251 	    above = TRUE;	/* stop above the header */
2252     }
2253 
2254     /* If we found it: Follow the path to go to where we want to be. */
2255     if (uhp != NULL)
2256     {
2257 	/*
2258 	 * First go up the tree as much as needed.
2259 	 */
2260 	while (!got_int)
2261 	{
2262 	    /* Do the change warning now, for the same reason as above. */
2263 	    change_warning(0);
2264 
2265 	    uhp = curbuf->b_u_curhead;
2266 	    if (uhp == NULL)
2267 		uhp = curbuf->b_u_newhead;
2268 	    else
2269 		uhp = uhp->uh_next.ptr;
2270 	    if (uhp == NULL || uhp->uh_walk != mark
2271 					 || (uhp->uh_seq == target && !above))
2272 		break;
2273 	    curbuf->b_u_curhead = uhp;
2274 	    u_undoredo(TRUE);
2275 	    uhp->uh_walk = nomark;	/* don't go back down here */
2276 	}
2277 
2278 	/*
2279 	 * And now go down the tree (redo), branching off where needed.
2280 	 */
2281 	while (!got_int)
2282 	{
2283 	    /* Do the change warning now, for the same reason as above. */
2284 	    change_warning(0);
2285 
2286 	    uhp = curbuf->b_u_curhead;
2287 	    if (uhp == NULL)
2288 		break;
2289 
2290 	    /* Go back to the first branch with a mark. */
2291 	    while (uhp->uh_alt_prev.ptr != NULL
2292 				     && uhp->uh_alt_prev.ptr->uh_walk == mark)
2293 		uhp = uhp->uh_alt_prev.ptr;
2294 
2295 	    /* Find the last branch with a mark, that's the one. */
2296 	    last = uhp;
2297 	    while (last->uh_alt_next.ptr != NULL
2298 				    && last->uh_alt_next.ptr->uh_walk == mark)
2299 		last = last->uh_alt_next.ptr;
2300 	    if (last != uhp)
2301 	    {
2302 		/* Make the used branch the first entry in the list of
2303 		 * alternatives to make "u" and CTRL-R take this branch. */
2304 		while (uhp->uh_alt_prev.ptr != NULL)
2305 		    uhp = uhp->uh_alt_prev.ptr;
2306 		if (last->uh_alt_next.ptr != NULL)
2307 		    last->uh_alt_next.ptr->uh_alt_prev.ptr =
2308 							last->uh_alt_prev.ptr;
2309 		last->uh_alt_prev.ptr->uh_alt_next.ptr = last->uh_alt_next.ptr;
2310 		last->uh_alt_prev.ptr = NULL;
2311 		last->uh_alt_next.ptr = uhp;
2312 		uhp->uh_alt_prev.ptr = last;
2313 
2314 		if (curbuf->b_u_oldhead == uhp)
2315 		    curbuf->b_u_oldhead = last;
2316 		uhp = last;
2317 		if (uhp->uh_next.ptr != NULL)
2318 		    uhp->uh_next.ptr->uh_prev.ptr = uhp;
2319 	    }
2320 	    curbuf->b_u_curhead = uhp;
2321 
2322 	    if (uhp->uh_walk != mark)
2323 		break;	    /* must have reached the target */
2324 
2325 	    /* Stop when going backwards in time and didn't find the exact
2326 	     * header we were looking for. */
2327 	    if (uhp->uh_seq == target && above)
2328 	    {
2329 		curbuf->b_u_seq_cur = target - 1;
2330 		break;
2331 	    }
2332 
2333 	    u_undoredo(FALSE);
2334 
2335 	    /* Advance "curhead" to below the header we last used.  If it
2336 	     * becomes NULL then we need to set "newhead" to this leaf. */
2337 	    if (uhp->uh_prev.ptr == NULL)
2338 		curbuf->b_u_newhead = uhp;
2339 	    curbuf->b_u_curhead = uhp->uh_prev.ptr;
2340 	    did_undo = FALSE;
2341 
2342 	    if (uhp->uh_seq == target)	/* found it! */
2343 		break;
2344 
2345 	    uhp = uhp->uh_prev.ptr;
2346 	    if (uhp == NULL || uhp->uh_walk != mark)
2347 	    {
2348 		/* Need to redo more but can't find it... */
2349 		EMSG2(_(e_intern2), "undo_time()");
2350 		break;
2351 	    }
2352 	}
2353     }
2354     u_undo_end(did_undo, absolute);
2355 }
2356 
2357 /*
2358  * u_undoredo: common code for undo and redo
2359  *
2360  * The lines in the file are replaced by the lines in the entry list at
2361  * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry
2362  * list for the next undo/redo.
2363  *
2364  * When "undo" is TRUE we go up in the tree, when FALSE we go down.
2365  */
2366     static void
2367 u_undoredo(undo)
2368     int		undo;
2369 {
2370     char_u	**newarray = NULL;
2371     linenr_T	oldsize;
2372     linenr_T	newsize;
2373     linenr_T	top, bot;
2374     linenr_T	lnum;
2375     linenr_T	newlnum = MAXLNUM;
2376     long	i;
2377     u_entry_T	*uep, *nuep;
2378     u_entry_T	*newlist = NULL;
2379     int		old_flags;
2380     int		new_flags;
2381     pos_T	namedm[NMARKS];
2382 #ifdef FEAT_VISUAL
2383     visualinfo_T visualinfo;
2384 #endif
2385     int		empty_buffer;		    /* buffer became empty */
2386     u_header_T	*curhead = curbuf->b_u_curhead;
2387 
2388 #ifdef FEAT_AUTOCMD
2389     /* Don't want autocommands using the undo structures here, they are
2390      * invalid till the end. */
2391     block_autocmds();
2392 #endif
2393 
2394 #ifdef U_DEBUG
2395     u_check(FALSE);
2396 #endif
2397     old_flags = curhead->uh_flags;
2398     new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
2399 	       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
2400     setpcmark();
2401 
2402     /*
2403      * save marks before undo/redo
2404      */
2405     mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
2406 #ifdef FEAT_VISUAL
2407     visualinfo = curbuf->b_visual;
2408 #endif
2409     curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
2410     curbuf->b_op_start.col = 0;
2411     curbuf->b_op_end.lnum = 0;
2412     curbuf->b_op_end.col = 0;
2413 
2414     for (uep = curhead->uh_entry; uep != NULL; uep = nuep)
2415     {
2416 	top = uep->ue_top;
2417 	bot = uep->ue_bot;
2418 	if (bot == 0)
2419 	    bot = curbuf->b_ml.ml_line_count + 1;
2420 	if (top > curbuf->b_ml.ml_line_count || top >= bot
2421 				      || bot > curbuf->b_ml.ml_line_count + 1)
2422 	{
2423 #ifdef FEAT_AUTOCMD
2424 	    unblock_autocmds();
2425 #endif
2426 	    EMSG(_("E438: u_undo: line numbers wrong"));
2427 	    changed();		/* don't want UNCHANGED now */
2428 	    return;
2429 	}
2430 
2431 	oldsize = bot - top - 1;    /* number of lines before undo */
2432 	newsize = uep->ue_size;	    /* number of lines after undo */
2433 
2434 	if (top < newlnum)
2435 	{
2436 	    /* If the saved cursor is somewhere in this undo block, move it to
2437 	     * the remembered position.  Makes "gwap" put the cursor back
2438 	     * where it was. */
2439 	    lnum = curhead->uh_cursor.lnum;
2440 	    if (lnum >= top && lnum <= top + newsize + 1)
2441 	    {
2442 		curwin->w_cursor = curhead->uh_cursor;
2443 		newlnum = curwin->w_cursor.lnum - 1;
2444 	    }
2445 	    else
2446 	    {
2447 		/* Use the first line that actually changed.  Avoids that
2448 		 * undoing auto-formatting puts the cursor in the previous
2449 		 * line. */
2450 		for (i = 0; i < newsize && i < oldsize; ++i)
2451 		    if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0)
2452 			break;
2453 		if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL)
2454 		{
2455 		    newlnum = top;
2456 		    curwin->w_cursor.lnum = newlnum + 1;
2457 		}
2458 		else if (i < newsize)
2459 		{
2460 		    newlnum = top + i;
2461 		    curwin->w_cursor.lnum = newlnum + 1;
2462 		}
2463 	    }
2464 	}
2465 
2466 	empty_buffer = FALSE;
2467 
2468 	/* delete the lines between top and bot and save them in newarray */
2469 	if (oldsize > 0)
2470 	{
2471 	    if ((newarray = (char_u **)U_ALLOC_LINE(
2472 					 sizeof(char_u *) * oldsize)) == NULL)
2473 	    {
2474 		do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize));
2475 		/*
2476 		 * We have messed up the entry list, repair is impossible.
2477 		 * we have to free the rest of the list.
2478 		 */
2479 		while (uep != NULL)
2480 		{
2481 		    nuep = uep->ue_next;
2482 		    u_freeentry(uep, uep->ue_size);
2483 		    uep = nuep;
2484 		}
2485 		break;
2486 	    }
2487 	    /* delete backwards, it goes faster in most cases */
2488 	    for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum)
2489 	    {
2490 		/* what can we do when we run out of memory? */
2491 		if ((newarray[i] = u_save_line(lnum)) == NULL)
2492 		    do_outofmem_msg((long_u)0);
2493 		/* remember we deleted the last line in the buffer, and a
2494 		 * dummy empty line will be inserted */
2495 		if (curbuf->b_ml.ml_line_count == 1)
2496 		    empty_buffer = TRUE;
2497 		ml_delete(lnum, FALSE);
2498 	    }
2499 	}
2500 	else
2501 	    newarray = NULL;
2502 
2503 	/* insert the lines in u_array between top and bot */
2504 	if (newsize)
2505 	{
2506 	    for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
2507 	    {
2508 		/*
2509 		 * If the file is empty, there is an empty line 1 that we
2510 		 * should get rid of, by replacing it with the new line
2511 		 */
2512 		if (empty_buffer && lnum == 0)
2513 		    ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
2514 		else
2515 		    ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
2516 		vim_free(uep->ue_array[i]);
2517 	    }
2518 	    vim_free((char_u *)uep->ue_array);
2519 	}
2520 
2521 	/* adjust marks */
2522 	if (oldsize != newsize)
2523 	{
2524 	    mark_adjust(top + 1, top + oldsize, (long)MAXLNUM,
2525 					       (long)newsize - (long)oldsize);
2526 	    if (curbuf->b_op_start.lnum > top + oldsize)
2527 		curbuf->b_op_start.lnum += newsize - oldsize;
2528 	    if (curbuf->b_op_end.lnum > top + oldsize)
2529 		curbuf->b_op_end.lnum += newsize - oldsize;
2530 	}
2531 
2532 	changed_lines(top + 1, 0, bot, newsize - oldsize);
2533 
2534 	/* set '[ and '] mark */
2535 	if (top + 1 < curbuf->b_op_start.lnum)
2536 	    curbuf->b_op_start.lnum = top + 1;
2537 	if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum)
2538 	    curbuf->b_op_end.lnum = top + 1;
2539 	else if (top + newsize > curbuf->b_op_end.lnum)
2540 	    curbuf->b_op_end.lnum = top + newsize;
2541 
2542 	u_newcount += newsize;
2543 	u_oldcount += oldsize;
2544 	uep->ue_size = oldsize;
2545 	uep->ue_array = newarray;
2546 	uep->ue_bot = top + newsize + 1;
2547 
2548 	/*
2549 	 * insert this entry in front of the new entry list
2550 	 */
2551 	nuep = uep->ue_next;
2552 	uep->ue_next = newlist;
2553 	newlist = uep;
2554     }
2555 
2556     curhead->uh_entry = newlist;
2557     curhead->uh_flags = new_flags;
2558     if ((old_flags & UH_EMPTYBUF) && bufempty())
2559 	curbuf->b_ml.ml_flags |= ML_EMPTY;
2560     if (old_flags & UH_CHANGED)
2561 	changed();
2562     else
2563 #ifdef FEAT_NETBEANS_INTG
2564 	/* per netbeans undo rules, keep it as modified */
2565 	if (!isNetbeansModified(curbuf))
2566 #endif
2567 	unchanged(curbuf, FALSE);
2568 
2569     /*
2570      * restore marks from before undo/redo
2571      */
2572     for (i = 0; i < NMARKS; ++i)
2573 	if (curhead->uh_namedm[i].lnum != 0)
2574 	{
2575 	    curbuf->b_namedm[i] = curhead->uh_namedm[i];
2576 	    curhead->uh_namedm[i] = namedm[i];
2577 	}
2578 #ifdef FEAT_VISUAL
2579     if (curhead->uh_visual.vi_start.lnum != 0)
2580     {
2581 	curbuf->b_visual = curhead->uh_visual;
2582 	curhead->uh_visual = visualinfo;
2583     }
2584 #endif
2585 
2586     /*
2587      * If the cursor is only off by one line, put it at the same position as
2588      * before starting the change (for the "o" command).
2589      * Otherwise the cursor should go to the first undone line.
2590      */
2591     if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum
2592 						 && curwin->w_cursor.lnum > 1)
2593 	--curwin->w_cursor.lnum;
2594     if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count)
2595     {
2596 	if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum)
2597 	{
2598 	    curwin->w_cursor.col = curhead->uh_cursor.col;
2599 #ifdef FEAT_VIRTUALEDIT
2600 	    if (virtual_active() && curhead->uh_cursor_vcol >= 0)
2601 		coladvance((colnr_T)curhead->uh_cursor_vcol);
2602 	    else
2603 		curwin->w_cursor.coladd = 0;
2604 #endif
2605 	}
2606 	else
2607 	    beginline(BL_SOL | BL_FIX);
2608     }
2609     else
2610     {
2611 	/* We get here with the current cursor line being past the end (eg
2612 	 * after adding lines at the end of the file, and then undoing it).
2613 	 * check_cursor() will move the cursor to the last line.  Move it to
2614 	 * the first column here. */
2615 	curwin->w_cursor.col = 0;
2616 #ifdef FEAT_VIRTUALEDIT
2617 	curwin->w_cursor.coladd = 0;
2618 #endif
2619     }
2620 
2621     /* Make sure the cursor is on an existing line and column. */
2622     check_cursor();
2623 
2624     /* Remember where we are for "g-" and ":earlier 10s". */
2625     curbuf->b_u_seq_cur = curhead->uh_seq;
2626     if (undo)
2627 	/* We are below the previous undo.  However, to make ":earlier 1s"
2628 	 * work we compute this as being just above the just undone change. */
2629 	--curbuf->b_u_seq_cur;
2630 
2631     /* Remember where we are for ":earlier 1f" and ":later 1f". */
2632     if (curhead->uh_save_nr != 0)
2633     {
2634 	if (undo)
2635 	    curbuf->b_u_save_nr_cur = curhead->uh_save_nr - 1;
2636 	else
2637 	    curbuf->b_u_save_nr_cur = curhead->uh_save_nr;
2638     }
2639 
2640     /* The timestamp can be the same for multiple changes, just use the one of
2641      * the undone/redone change. */
2642     curbuf->b_u_time_cur = curhead->uh_time;
2643 
2644 #ifdef FEAT_AUTOCMD
2645     unblock_autocmds();
2646 #endif
2647 #ifdef U_DEBUG
2648     u_check(FALSE);
2649 #endif
2650 }
2651 
2652 /*
2653  * If we deleted or added lines, report the number of less/more lines.
2654  * Otherwise, report the number of changes (this may be incorrect
2655  * in some cases, but it's better than nothing).
2656  */
2657     static void
2658 u_undo_end(did_undo, absolute)
2659     int		did_undo;	/* just did an undo */
2660     int		absolute;	/* used ":undo N" */
2661 {
2662     char	*msgstr;
2663     u_header_T	*uhp;
2664     char_u	msgbuf[80];
2665 
2666 #ifdef FEAT_FOLDING
2667     if ((fdo_flags & FDO_UNDO) && KeyTyped)
2668 	foldOpenCursor();
2669 #endif
2670 
2671     if (global_busy	    /* no messages now, wait until global is finished */
2672 	    || !messaging())  /* 'lazyredraw' set, don't do messages now */
2673 	return;
2674 
2675     if (curbuf->b_ml.ml_flags & ML_EMPTY)
2676 	--u_newcount;
2677 
2678     u_oldcount -= u_newcount;
2679     if (u_oldcount == -1)
2680 	msgstr = N_("more line");
2681     else if (u_oldcount < 0)
2682 	msgstr = N_("more lines");
2683     else if (u_oldcount == 1)
2684 	msgstr = N_("line less");
2685     else if (u_oldcount > 1)
2686 	msgstr = N_("fewer lines");
2687     else
2688     {
2689 	u_oldcount = u_newcount;
2690 	if (u_newcount == 1)
2691 	    msgstr = N_("change");
2692 	else
2693 	    msgstr = N_("changes");
2694     }
2695 
2696     if (curbuf->b_u_curhead != NULL)
2697     {
2698 	/* For ":undo N" we prefer a "after #N" message. */
2699 	if (absolute && curbuf->b_u_curhead->uh_next.ptr != NULL)
2700 	{
2701 	    uhp = curbuf->b_u_curhead->uh_next.ptr;
2702 	    did_undo = FALSE;
2703 	}
2704 	else if (did_undo)
2705 	    uhp = curbuf->b_u_curhead;
2706 	else
2707 	    uhp = curbuf->b_u_curhead->uh_next.ptr;
2708     }
2709     else
2710 	uhp = curbuf->b_u_newhead;
2711 
2712     if (uhp == NULL)
2713 	*msgbuf = NUL;
2714     else
2715 	u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
2716 
2717 #ifdef FEAT_CONCEAL
2718     {
2719 	win_T	*wp;
2720 
2721 	FOR_ALL_WINDOWS(wp)
2722 	{
2723 	    if (wp->w_buffer == curbuf && wp->w_p_cole > 0)
2724 		redraw_win_later(wp, NOT_VALID);
2725 	}
2726     }
2727 #endif
2728 
2729     smsg((char_u *)_("%ld %s; %s #%ld  %s"),
2730 	    u_oldcount < 0 ? -u_oldcount : u_oldcount,
2731 	    _(msgstr),
2732 	    did_undo ? _("before") : _("after"),
2733 	    uhp == NULL ? 0L : uhp->uh_seq,
2734 	    msgbuf);
2735 }
2736 
2737 /*
2738  * u_sync: stop adding to the current entry list
2739  */
2740     void
2741 u_sync(force)
2742     int	    force;	/* Also sync when no_u_sync is set. */
2743 {
2744     /* Skip it when already synced or syncing is disabled. */
2745     if (curbuf->b_u_synced || (!force && no_u_sync > 0))
2746 	return;
2747 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
2748     if (im_is_preediting())
2749 	return;		    /* XIM is busy, don't break an undo sequence */
2750 #endif
2751     if (p_ul < 0)
2752 	curbuf->b_u_synced = TRUE;  /* no entries, nothing to do */
2753     else
2754     {
2755 	u_getbot();		    /* compute ue_bot of previous u_save */
2756 	curbuf->b_u_curhead = NULL;
2757     }
2758 }
2759 
2760 /*
2761  * ":undolist": List the leafs of the undo tree
2762  */
2763     void
2764 ex_undolist(eap)
2765     exarg_T *eap UNUSED;
2766 {
2767     garray_T	ga;
2768     u_header_T	*uhp;
2769     int		mark;
2770     int		nomark;
2771     int		changes = 1;
2772     int		i;
2773 
2774     /*
2775      * 1: walk the tree to find all leafs, put the info in "ga".
2776      * 2: sort the lines
2777      * 3: display the list
2778      */
2779     mark = ++lastmark;
2780     nomark = ++lastmark;
2781     ga_init2(&ga, (int)sizeof(char *), 20);
2782 
2783     uhp = curbuf->b_u_oldhead;
2784     while (uhp != NULL)
2785     {
2786 	if (uhp->uh_prev.ptr == NULL && uhp->uh_walk != nomark
2787 						      && uhp->uh_walk != mark)
2788 	{
2789 	    if (ga_grow(&ga, 1) == FAIL)
2790 		break;
2791 	    vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7ld  ",
2792 							uhp->uh_seq, changes);
2793 	    u_add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
2794 								uhp->uh_time);
2795 	    if (uhp->uh_save_nr > 0)
2796 	    {
2797 		while (STRLEN(IObuff) < 33)
2798 		    STRCAT(IObuff, " ");
2799 		vim_snprintf_add((char *)IObuff, IOSIZE,
2800 						   "  %3ld", uhp->uh_save_nr);
2801 	    }
2802 	    ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strsave(IObuff);
2803 	}
2804 
2805 	uhp->uh_walk = mark;
2806 
2807 	/* go down in the tree if we haven't been there */
2808 	if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != nomark
2809 					 && uhp->uh_prev.ptr->uh_walk != mark)
2810 	{
2811 	    uhp = uhp->uh_prev.ptr;
2812 	    ++changes;
2813 	}
2814 
2815 	/* go to alternate branch if we haven't been there */
2816 	else if (uhp->uh_alt_next.ptr != NULL
2817 		&& uhp->uh_alt_next.ptr->uh_walk != nomark
2818 		&& uhp->uh_alt_next.ptr->uh_walk != mark)
2819 	    uhp = uhp->uh_alt_next.ptr;
2820 
2821 	/* go up in the tree if we haven't been there and we are at the
2822 	 * start of alternate branches */
2823 	else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
2824 		&& uhp->uh_next.ptr->uh_walk != nomark
2825 		&& uhp->uh_next.ptr->uh_walk != mark)
2826 	{
2827 	    uhp = uhp->uh_next.ptr;
2828 	    --changes;
2829 	}
2830 
2831 	else
2832 	{
2833 	    /* need to backtrack; mark this node as done */
2834 	    uhp->uh_walk = nomark;
2835 	    if (uhp->uh_alt_prev.ptr != NULL)
2836 		uhp = uhp->uh_alt_prev.ptr;
2837 	    else
2838 	    {
2839 		uhp = uhp->uh_next.ptr;
2840 		--changes;
2841 	    }
2842 	}
2843     }
2844 
2845     if (ga.ga_len == 0)
2846 	MSG(_("Nothing to undo"));
2847     else
2848     {
2849 	sort_strings((char_u **)ga.ga_data, ga.ga_len);
2850 
2851 	msg_start();
2852 	msg_puts_attr((char_u *)_("number changes  when               saved"),
2853 							      hl_attr(HLF_T));
2854 	for (i = 0; i < ga.ga_len && !got_int; ++i)
2855 	{
2856 	    msg_putchar('\n');
2857 	    if (got_int)
2858 		break;
2859 	    msg_puts(((char_u **)ga.ga_data)[i]);
2860 	}
2861 	msg_end();
2862 
2863 	ga_clear_strings(&ga);
2864     }
2865 }
2866 
2867 /*
2868  * Put the timestamp of an undo header in "buf[buflen]" in a nice format.
2869  */
2870     static void
2871 u_add_time(buf, buflen, tt)
2872     char_u	*buf;
2873     size_t	buflen;
2874     time_t	tt;
2875 {
2876 #ifdef HAVE_STRFTIME
2877     struct tm	*curtime;
2878 
2879     if (time(NULL) - tt >= 100)
2880     {
2881 	curtime = localtime(&tt);
2882 	if (time(NULL) - tt < (60L * 60L * 12L))
2883 	    /* within 12 hours */
2884 	    (void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
2885 	else
2886 	    /* longer ago */
2887 	    (void)strftime((char *)buf, buflen, "%Y/%m/%d %H:%M:%S", curtime);
2888     }
2889     else
2890 #endif
2891 	vim_snprintf((char *)buf, buflen, _("%ld seconds ago"),
2892 						     (long)(time(NULL) - tt));
2893 }
2894 
2895 /*
2896  * ":undojoin": continue adding to the last entry list
2897  */
2898     void
2899 ex_undojoin(eap)
2900     exarg_T *eap UNUSED;
2901 {
2902     if (curbuf->b_u_newhead == NULL)
2903 	return;		    /* nothing changed before */
2904     if (curbuf->b_u_curhead != NULL)
2905     {
2906 	EMSG(_("E790: undojoin is not allowed after undo"));
2907 	return;
2908     }
2909     if (!curbuf->b_u_synced)
2910 	return;		    /* already unsynced */
2911     if (p_ul < 0)
2912 	return;		    /* no entries, nothing to do */
2913     else
2914     {
2915 	/* Go back to the last entry */
2916 	curbuf->b_u_curhead = curbuf->b_u_newhead;
2917 	curbuf->b_u_synced = FALSE;  /* no entries, nothing to do */
2918     }
2919 }
2920 
2921 /*
2922  * Called after writing or reloading the file and setting b_changed to FALSE.
2923  * Now an undo means that the buffer is modified.
2924  */
2925     void
2926 u_unchanged(buf)
2927     buf_T	*buf;
2928 {
2929     u_unch_branch(buf->b_u_oldhead);
2930     buf->b_did_warn = FALSE;
2931 }
2932 
2933 /*
2934  * After reloading a buffer which was saved for 'undoreload': Find the first
2935  * line that was changed and set the cursor there.
2936  */
2937     void
2938 u_find_first_changed()
2939 {
2940     u_header_T	*uhp = curbuf->b_u_newhead;
2941     u_entry_T   *uep;
2942     linenr_T	lnum;
2943 
2944     if (curbuf->b_u_curhead != NULL || uhp == NULL)
2945 	return;  /* undid something in an autocmd? */
2946 
2947     /* Check that the last undo block was for the whole file. */
2948     uep = uhp->uh_entry;
2949     if (uep->ue_top != 0 || uep->ue_bot != 0)
2950 	return;
2951 
2952     for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
2953 					      && lnum <= uep->ue_size; ++lnum)
2954 	if (STRCMP(ml_get_buf(curbuf, lnum, FALSE),
2955 						uep->ue_array[lnum - 1]) != 0)
2956 	{
2957 	    clearpos(&(uhp->uh_cursor));
2958 	    uhp->uh_cursor.lnum = lnum;
2959 	    return;
2960 	}
2961     if (curbuf->b_ml.ml_line_count != uep->ue_size)
2962     {
2963 	/* lines added or deleted at the end, put the cursor there */
2964 	clearpos(&(uhp->uh_cursor));
2965 	uhp->uh_cursor.lnum = lnum;
2966     }
2967 }
2968 
2969 /*
2970  * Increase the write count, store it in the last undo header, what would be
2971  * used for "u".
2972  */
2973     void
2974 u_update_save_nr(buf)
2975     buf_T *buf;
2976 {
2977     u_header_T	*uhp;
2978 
2979     ++buf->b_u_save_nr_last;
2980     buf->b_u_save_nr_cur = buf->b_u_save_nr_last;
2981     uhp = buf->b_u_curhead;
2982     if (uhp != NULL)
2983 	uhp = uhp->uh_next.ptr;
2984     else
2985 	uhp = buf->b_u_newhead;
2986     if (uhp != NULL)
2987 	uhp->uh_save_nr = buf->b_u_save_nr_last;
2988 }
2989 
2990     static void
2991 u_unch_branch(uhp)
2992     u_header_T	*uhp;
2993 {
2994     u_header_T	*uh;
2995 
2996     for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr)
2997     {
2998 	uh->uh_flags |= UH_CHANGED;
2999 	if (uh->uh_alt_next.ptr != NULL)
3000 	    u_unch_branch(uh->uh_alt_next.ptr);	    /* recursive */
3001     }
3002 }
3003 
3004 /*
3005  * Get pointer to last added entry.
3006  * If it's not valid, give an error message and return NULL.
3007  */
3008     static u_entry_T *
3009 u_get_headentry()
3010 {
3011     if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL)
3012     {
3013 	EMSG(_("E439: undo list corrupt"));
3014 	return NULL;
3015     }
3016     return curbuf->b_u_newhead->uh_entry;
3017 }
3018 
3019 /*
3020  * u_getbot(): compute the line number of the previous u_save
3021  *		It is called only when b_u_synced is FALSE.
3022  */
3023     static void
3024 u_getbot()
3025 {
3026     u_entry_T	*uep;
3027     linenr_T	extra;
3028 
3029     uep = u_get_headentry();	/* check for corrupt undo list */
3030     if (uep == NULL)
3031 	return;
3032 
3033     uep = curbuf->b_u_newhead->uh_getbot_entry;
3034     if (uep != NULL)
3035     {
3036 	/*
3037 	 * the new ue_bot is computed from the number of lines that has been
3038 	 * inserted (0 - deleted) since calling u_save. This is equal to the
3039 	 * old line count subtracted from the current line count.
3040 	 */
3041 	extra = curbuf->b_ml.ml_line_count - uep->ue_lcount;
3042 	uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra;
3043 	if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count)
3044 	{
3045 	    EMSG(_("E440: undo line missing"));
3046 	    uep->ue_bot = uep->ue_top + 1;  /* assume all lines deleted, will
3047 					     * get all the old lines back
3048 					     * without deleting the current
3049 					     * ones */
3050 	}
3051 
3052 	curbuf->b_u_newhead->uh_getbot_entry = NULL;
3053     }
3054 
3055     curbuf->b_u_synced = TRUE;
3056 }
3057 
3058 /*
3059  * Free one header "uhp" and its entry list and adjust the pointers.
3060  */
3061     static void
3062 u_freeheader(buf, uhp, uhpp)
3063     buf_T	    *buf;
3064     u_header_T	    *uhp;
3065     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
3066 {
3067     u_header_T	    *uhap;
3068 
3069     /* When there is an alternate redo list free that branch completely,
3070      * because we can never go there. */
3071     if (uhp->uh_alt_next.ptr != NULL)
3072 	u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp);
3073 
3074     if (uhp->uh_alt_prev.ptr != NULL)
3075 	uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL;
3076 
3077     /* Update the links in the list to remove the header. */
3078     if (uhp->uh_next.ptr == NULL)
3079 	buf->b_u_oldhead = uhp->uh_prev.ptr;
3080     else
3081 	uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr;
3082 
3083     if (uhp->uh_prev.ptr == NULL)
3084 	buf->b_u_newhead = uhp->uh_next.ptr;
3085     else
3086 	for (uhap = uhp->uh_prev.ptr; uhap != NULL;
3087 						 uhap = uhap->uh_alt_next.ptr)
3088 	    uhap->uh_next.ptr = uhp->uh_next.ptr;
3089 
3090     u_freeentries(buf, uhp, uhpp);
3091 }
3092 
3093 /*
3094  * Free an alternate branch and any following alternate branches.
3095  */
3096     static void
3097 u_freebranch(buf, uhp, uhpp)
3098     buf_T	    *buf;
3099     u_header_T	    *uhp;
3100     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
3101 {
3102     u_header_T	    *tofree, *next;
3103 
3104     /* If this is the top branch we may need to use u_freeheader() to update
3105      * all the pointers. */
3106     if (uhp == buf->b_u_oldhead)
3107     {
3108 	u_freeheader(buf, uhp, uhpp);
3109 	return;
3110     }
3111 
3112     if (uhp->uh_alt_prev.ptr != NULL)
3113 	uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL;
3114 
3115     next = uhp;
3116     while (next != NULL)
3117     {
3118 	tofree = next;
3119 	if (tofree->uh_alt_next.ptr != NULL)
3120 	    u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp);   /* recursive */
3121 	next = tofree->uh_prev.ptr;
3122 	u_freeentries(buf, tofree, uhpp);
3123     }
3124 }
3125 
3126 /*
3127  * Free all the undo entries for one header and the header itself.
3128  * This means that "uhp" is invalid when returning.
3129  */
3130     static void
3131 u_freeentries(buf, uhp, uhpp)
3132     buf_T	    *buf;
3133     u_header_T	    *uhp;
3134     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
3135 {
3136     u_entry_T	    *uep, *nuep;
3137 
3138     /* Check for pointers to the header that become invalid now. */
3139     if (buf->b_u_curhead == uhp)
3140 	buf->b_u_curhead = NULL;
3141     if (buf->b_u_newhead == uhp)
3142 	buf->b_u_newhead = NULL;  /* freeing the newest entry */
3143     if (uhpp != NULL && uhp == *uhpp)
3144 	*uhpp = NULL;
3145 
3146     for (uep = uhp->uh_entry; uep != NULL; uep = nuep)
3147     {
3148 	nuep = uep->ue_next;
3149 	u_freeentry(uep, uep->ue_size);
3150     }
3151 
3152 #ifdef U_DEBUG
3153     uhp->uh_magic = 0;
3154 #endif
3155     vim_free((char_u *)uhp);
3156     --buf->b_u_numhead;
3157 }
3158 
3159 /*
3160  * free entry 'uep' and 'n' lines in uep->ue_array[]
3161  */
3162     static void
3163 u_freeentry(uep, n)
3164     u_entry_T	*uep;
3165     long	    n;
3166 {
3167     while (n > 0)
3168 	vim_free(uep->ue_array[--n]);
3169     vim_free((char_u *)uep->ue_array);
3170 #ifdef U_DEBUG
3171     uep->ue_magic = 0;
3172 #endif
3173     vim_free((char_u *)uep);
3174 }
3175 
3176 /*
3177  * invalidate the undo buffer; called when storage has already been released
3178  */
3179     void
3180 u_clearall(buf)
3181     buf_T	*buf;
3182 {
3183     buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
3184     buf->b_u_synced = TRUE;
3185     buf->b_u_numhead = 0;
3186     buf->b_u_line_ptr = NULL;
3187     buf->b_u_line_lnum = 0;
3188 }
3189 
3190 /*
3191  * save the line "lnum" for the "U" command
3192  */
3193     void
3194 u_saveline(lnum)
3195     linenr_T lnum;
3196 {
3197     if (lnum == curbuf->b_u_line_lnum)	    /* line is already saved */
3198 	return;
3199     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */
3200 	return;
3201     u_clearline();
3202     curbuf->b_u_line_lnum = lnum;
3203     if (curwin->w_cursor.lnum == lnum)
3204 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
3205     else
3206 	curbuf->b_u_line_colnr = 0;
3207     if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL)
3208 	do_outofmem_msg((long_u)0);
3209 }
3210 
3211 /*
3212  * clear the line saved for the "U" command
3213  * (this is used externally for crossing a line while in insert mode)
3214  */
3215     void
3216 u_clearline()
3217 {
3218     if (curbuf->b_u_line_ptr != NULL)
3219     {
3220 	vim_free(curbuf->b_u_line_ptr);
3221 	curbuf->b_u_line_ptr = NULL;
3222 	curbuf->b_u_line_lnum = 0;
3223     }
3224 }
3225 
3226 /*
3227  * Implementation of the "U" command.
3228  * Differentiation from vi: "U" can be undone with the next "U".
3229  * We also allow the cursor to be in another line.
3230  * Careful: may trigger autocommands that reload the buffer.
3231  */
3232     void
3233 u_undoline()
3234 {
3235     colnr_T t;
3236     char_u  *oldp;
3237 
3238     if (undo_off)
3239 	return;
3240 
3241     if (curbuf->b_u_line_ptr == NULL
3242 			|| curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
3243     {
3244 	beep_flush();
3245 	return;
3246     }
3247 
3248     /* first save the line for the 'u' command */
3249     if (u_savecommon(curbuf->b_u_line_lnum - 1,
3250 		       curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
3251 	return;
3252     oldp = u_save_line(curbuf->b_u_line_lnum);
3253     if (oldp == NULL)
3254     {
3255 	do_outofmem_msg((long_u)0);
3256 	return;
3257     }
3258     ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
3259     changed_bytes(curbuf->b_u_line_lnum, 0);
3260     vim_free(curbuf->b_u_line_ptr);
3261     curbuf->b_u_line_ptr = oldp;
3262 
3263     t = curbuf->b_u_line_colnr;
3264     if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum)
3265 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
3266     curwin->w_cursor.col = t;
3267     curwin->w_cursor.lnum = curbuf->b_u_line_lnum;
3268     check_cursor_col();
3269 }
3270 
3271 /*
3272  * Free all allocated memory blocks for the buffer 'buf'.
3273  */
3274     void
3275 u_blockfree(buf)
3276     buf_T	*buf;
3277 {
3278     while (buf->b_u_oldhead != NULL)
3279 	u_freeheader(buf, buf->b_u_oldhead, NULL);
3280     vim_free(buf->b_u_line_ptr);
3281 }
3282 
3283 /*
3284  * u_save_line(): allocate memory and copy line 'lnum' into it.
3285  * Returns NULL when out of memory.
3286  */
3287     static char_u *
3288 u_save_line(lnum)
3289     linenr_T	lnum;
3290 {
3291     return vim_strsave(ml_get(lnum));
3292 }
3293 
3294 /*
3295  * Check if the 'modified' flag is set, or 'ff' has changed (only need to
3296  * check the first character, because it can only be "dos", "unix" or "mac").
3297  * "nofile" and "scratch" type buffers are considered to always be unchanged.
3298  */
3299     int
3300 bufIsChanged(buf)
3301     buf_T	*buf;
3302 {
3303     return
3304 #ifdef FEAT_QUICKFIX
3305 	    !bt_dontwrite(buf) &&
3306 #endif
3307 	    (buf->b_changed || file_ff_differs(buf, TRUE));
3308 }
3309 
3310     int
3311 curbufIsChanged()
3312 {
3313     return
3314 #ifdef FEAT_QUICKFIX
3315 	!bt_dontwrite(curbuf) &&
3316 #endif
3317 	(curbuf->b_changed || file_ff_differs(curbuf, TRUE));
3318 }
3319 
3320 #if defined(FEAT_EVAL) || defined(PROTO)
3321 /*
3322  * For undotree(): Append the list of undo blocks at "first_uhp" to "list".
3323  * Recursive.
3324  */
3325     void
3326 u_eval_tree(first_uhp, list)
3327     u_header_T  *first_uhp;
3328     list_T	*list;
3329 {
3330     u_header_T  *uhp = first_uhp;
3331     dict_T	*dict;
3332 
3333     while (uhp != NULL)
3334     {
3335 	dict = dict_alloc();
3336 	if (dict == NULL)
3337 	    return;
3338 	dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL);
3339 	dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL);
3340 	if (uhp == curbuf->b_u_newhead)
3341 	    dict_add_nr_str(dict, "newhead", 1, NULL);
3342 	if (uhp == curbuf->b_u_curhead)
3343 	    dict_add_nr_str(dict, "curhead", 1, NULL);
3344 	if (uhp->uh_save_nr > 0)
3345 	    dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL);
3346 
3347 	if (uhp->uh_alt_next.ptr != NULL)
3348 	{
3349 	    list_T	*alt_list = list_alloc();
3350 
3351 	    if (alt_list != NULL)
3352 	    {
3353 		/* Recursive call to add alternate undo tree. */
3354 		u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
3355 		dict_add_list(dict, "alt", alt_list);
3356 	    }
3357 	}
3358 
3359 	list_append_dict(list, dict);
3360 	uhp = uhp->uh_prev.ptr;
3361     }
3362 }
3363 #endif
3364