xref: /vim-8.2.3635/src/undo.c (revision 0ee8df9c)
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 #if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
85 # include "vimio.h"	/* for vim_read(), must be before vim.h */
86 #endif
87 
88 #include "vim.h"
89 
90 static void u_unch_branch __ARGS((u_header_T *uhp));
91 static u_entry_T *u_get_headentry __ARGS((void));
92 static void u_getbot __ARGS((void));
93 static void u_doit __ARGS((int count));
94 static void u_undoredo __ARGS((int undo));
95 static void u_undo_end __ARGS((int did_undo, int absolute));
96 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt));
97 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
98 static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
99 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
100 static void u_freeentry __ARGS((u_entry_T *, long));
101 #ifdef FEAT_PERSISTENT_UNDO
102 static void corruption_error __ARGS((char *mesg, char_u *file_name));
103 static void u_free_uhp __ARGS((u_header_T *uhp));
104 static size_t fwrite_crypt __ARGS((buf_T *buf UNUSED, char_u *ptr, size_t len, FILE *fp));
105 static char_u *read_string_decrypt __ARGS((buf_T *buf UNUSED, FILE *fd, int len));
106 static int serialize_header __ARGS((FILE *fp, buf_T *buf, char_u *hash));
107 static int serialize_uhp __ARGS((FILE *fp, buf_T *buf, u_header_T *uhp));
108 static u_header_T *unserialize_uhp __ARGS((FILE *fp, char_u *file_name));
109 static int serialize_uep __ARGS((FILE *fp, buf_T *buf, u_entry_T *uep));
110 static u_entry_T *unserialize_uep __ARGS((FILE *fp, int *error, char_u *file_name));
111 static void serialize_pos __ARGS((pos_T pos, FILE *fp));
112 static void unserialize_pos __ARGS((pos_T *pos, FILE *fp));
113 static void serialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp));
114 static void unserialize_visualinfo __ARGS((visualinfo_T *info, FILE *fp));
115 static void put_header_ptr __ARGS((FILE	*fp, u_header_T *uhp));
116 #endif
117 
118 #define U_ALLOC_LINE(size) lalloc((long_u)(size), FALSE)
119 static char_u *u_save_line __ARGS((linenr_T));
120 
121 /* used in undo_end() to report number of added and deleted lines */
122 static long	u_newcount, u_oldcount;
123 
124 /*
125  * When 'u' flag included in 'cpoptions', we behave like vi.  Need to remember
126  * the action that "u" should do.
127  */
128 static int	undo_undoes = FALSE;
129 
130 static int	lastmark = 0;
131 
132 #if defined(U_DEBUG) || defined(PROTO)
133 /*
134  * Check the undo structures for being valid.  Print a warning when something
135  * looks wrong.
136  */
137 static int seen_b_u_curhead;
138 static int seen_b_u_newhead;
139 static int header_count;
140 
141     static void
142 u_check_tree(u_header_T *uhp,
143 	u_header_T *exp_uh_next,
144 	u_header_T *exp_uh_alt_prev)
145 {
146     u_entry_T *uep;
147 
148     if (uhp == NULL)
149 	return;
150     ++header_count;
151     if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1)
152     {
153 	EMSG("b_u_curhead found twice (looping?)");
154 	return;
155     }
156     if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1)
157     {
158 	EMSG("b_u_newhead found twice (looping?)");
159 	return;
160     }
161 
162     if (uhp->uh_magic != UH_MAGIC)
163 	EMSG("uh_magic wrong (may be using freed memory)");
164     else
165     {
166 	/* Check pointers back are correct. */
167 	if (uhp->uh_next.ptr != exp_uh_next)
168 	{
169 	    EMSG("uh_next wrong");
170 	    smsg((char_u *)"expected: 0x%x, actual: 0x%x",
171 					       exp_uh_next, uhp->uh_next.ptr);
172 	}
173 	if (uhp->uh_alt_prev.ptr != exp_uh_alt_prev)
174 	{
175 	    EMSG("uh_alt_prev wrong");
176 	    smsg((char_u *)"expected: 0x%x, actual: 0x%x",
177 				       exp_uh_alt_prev, uhp->uh_alt_prev.ptr);
178 	}
179 
180 	/* Check the undo tree at this header. */
181 	for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
182 	{
183 	    if (uep->ue_magic != UE_MAGIC)
184 	    {
185 		EMSG("ue_magic wrong (may be using freed memory)");
186 		break;
187 	    }
188 	}
189 
190 	/* Check the next alt tree. */
191 	u_check_tree(uhp->uh_alt_next.ptr, uhp->uh_next.ptr, uhp);
192 
193 	/* Check the next header in this branch. */
194 	u_check_tree(uhp->uh_prev.ptr, uhp, NULL);
195     }
196 }
197 
198     static void
199 u_check(int newhead_may_be_NULL)
200 {
201     seen_b_u_newhead = 0;
202     seen_b_u_curhead = 0;
203     header_count = 0;
204 
205     u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
206 
207     if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
208 	    && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
209 	EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
210     if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
211 	EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
212     if (header_count != curbuf->b_u_numhead)
213     {
214 	EMSG("b_u_numhead invalid");
215 	smsg((char_u *)"expected: %ld, actual: %ld",
216 			       (long)header_count, (long)curbuf->b_u_numhead);
217     }
218 }
219 #endif
220 
221 /*
222  * Save the current line for both the "u" and "U" command.
223  * Returns OK or FAIL.
224  */
225     int
226 u_save_cursor()
227 {
228     return (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
229 				      (linenr_T)(curwin->w_cursor.lnum + 1)));
230 }
231 
232 /*
233  * Save the lines between "top" and "bot" for both the "u" and "U" command.
234  * "top" may be 0 and bot may be curbuf->b_ml.ml_line_count + 1.
235  * Careful: may trigger autocommands that reload the buffer.
236  * Returns FAIL when lines could not be saved, OK otherwise.
237  */
238     int
239 u_save(top, bot)
240     linenr_T top, bot;
241 {
242     if (undo_off)
243 	return OK;
244 
245     if (top > curbuf->b_ml.ml_line_count ||
246 			    top >= bot || bot > curbuf->b_ml.ml_line_count + 1)
247 	return FALSE;	/* rely on caller to do error messages */
248 
249     if (top + 2 == bot)
250 	u_saveline((linenr_T)(top + 1));
251 
252     return (u_savecommon(top, bot, (linenr_T)0, FALSE));
253 }
254 
255 /*
256  * Save the line "lnum" (used by ":s" and "~" command).
257  * The line is replaced, so the new bottom line is lnum + 1.
258  * Careful: may trigger autocommands that reload the buffer.
259  * Returns FAIL when lines could not be saved, OK otherwise.
260  */
261     int
262 u_savesub(lnum)
263     linenr_T	lnum;
264 {
265     if (undo_off)
266 	return OK;
267 
268     return (u_savecommon(lnum - 1, lnum + 1, lnum + 1, FALSE));
269 }
270 
271 /*
272  * A new line is inserted before line "lnum" (used by :s command).
273  * The line is inserted, so the new bottom line is lnum + 1.
274  * Careful: may trigger autocommands that reload the buffer.
275  * Returns FAIL when lines could not be saved, OK otherwise.
276  */
277     int
278 u_inssub(lnum)
279     linenr_T	lnum;
280 {
281     if (undo_off)
282 	return OK;
283 
284     return (u_savecommon(lnum - 1, lnum, lnum + 1, FALSE));
285 }
286 
287 /*
288  * Save the lines "lnum" - "lnum" + nlines (used by delete command).
289  * The lines are deleted, so the new bottom line is lnum, unless the buffer
290  * becomes empty.
291  * Careful: may trigger autocommands that reload the buffer.
292  * Returns FAIL when lines could not be saved, OK otherwise.
293  */
294     int
295 u_savedel(lnum, nlines)
296     linenr_T	lnum;
297     long	nlines;
298 {
299     if (undo_off)
300 	return OK;
301 
302     return (u_savecommon(lnum - 1, lnum + nlines,
303 		     nlines == curbuf->b_ml.ml_line_count ? 2 : lnum, FALSE));
304 }
305 
306 /*
307  * Return TRUE when undo is allowed.  Otherwise give an error message and
308  * return FALSE.
309  */
310     int
311 undo_allowed()
312 {
313     /* Don't allow changes when 'modifiable' is off.  */
314     if (!curbuf->b_p_ma)
315     {
316 	EMSG(_(e_modifiable));
317 	return FALSE;
318     }
319 
320 #ifdef HAVE_SANDBOX
321     /* In the sandbox it's not allowed to change the text. */
322     if (sandbox != 0)
323     {
324 	EMSG(_(e_sandbox));
325 	return FALSE;
326     }
327 #endif
328 
329     /* Don't allow changes in the buffer while editing the cmdline.  The
330      * caller of getcmdline() may get confused. */
331     if (textlock != 0)
332     {
333 	EMSG(_(e_secure));
334 	return FALSE;
335     }
336 
337     return TRUE;
338 }
339 
340 /*
341  * Common code for various ways to save text before a change.
342  * "top" is the line above the first changed line.
343  * "bot" is the line below the last changed line.
344  * "newbot" is the new bottom line.  Use zero when not known.
345  * "reload" is TRUE when saving for a buffer reload.
346  * Careful: may trigger autocommands that reload the buffer.
347  * Returns FAIL when lines could not be saved, OK otherwise.
348  */
349     int
350 u_savecommon(top, bot, newbot, reload)
351     linenr_T	top, bot;
352     linenr_T	newbot;
353     int		reload;
354 {
355     linenr_T	lnum;
356     long	i;
357     u_header_T	*uhp;
358     u_header_T	*old_curhead;
359     u_entry_T	*uep;
360     u_entry_T	*prev_uep;
361     long	size;
362 
363     if (!reload)
364     {
365 	/* When making changes is not allowed return FAIL.  It's a crude way
366 	 * to make all change commands fail. */
367 	if (!undo_allowed())
368 	    return FAIL;
369 
370 #ifdef FEAT_NETBEANS_INTG
371 	/*
372 	 * Netbeans defines areas that cannot be modified.  Bail out here when
373 	 * trying to change text in a guarded area.
374 	 */
375 	if (netbeans_active())
376 	{
377 	    if (netbeans_is_guarded(top, bot))
378 	    {
379 		EMSG(_(e_guarded));
380 		return FAIL;
381 	    }
382 	    if (curbuf->b_p_ro)
383 	    {
384 		EMSG(_(e_nbreadonly));
385 		return FAIL;
386 	    }
387 	}
388 #endif
389 
390 #ifdef FEAT_AUTOCMD
391 	/*
392 	 * Saving text for undo means we are going to make a change.  Give a
393 	 * warning for a read-only file before making the change, so that the
394 	 * FileChangedRO event can replace the buffer with a read-write version
395 	 * (e.g., obtained from a source control system).
396 	 */
397 	change_warning(0);
398 	if (bot > curbuf->b_ml.ml_line_count + 1)
399 	{
400 	    /* This happens when the FileChangedRO autocommand changes the
401 	     * file in a way it becomes shorter. */
402 	    EMSG(_("E834: Line count changed unexpectedly"));
403 	    return FAIL;
404 	}
405 #endif
406     }
407 
408 #ifdef U_DEBUG
409     u_check(FALSE);
410 #endif
411 
412     size = bot - top - 1;
413 
414     /*
415      * If curbuf->b_u_synced == TRUE make a new header.
416      */
417     if (curbuf->b_u_synced)
418     {
419 #ifdef FEAT_JUMPLIST
420 	/* Need to create new entry in b_changelist. */
421 	curbuf->b_new_change = TRUE;
422 #endif
423 
424 	if (p_ul >= 0)
425 	{
426 	    /*
427 	     * Make a new header entry.  Do this first so that we don't mess
428 	     * up the undo info when out of memory.
429 	     */
430 	    uhp = (u_header_T *)U_ALLOC_LINE(sizeof(u_header_T));
431 	    if (uhp == NULL)
432 		goto nomem;
433 #ifdef U_DEBUG
434 	    uhp->uh_magic = UH_MAGIC;
435 #endif
436 	}
437 	else
438 	    uhp = NULL;
439 
440 	/*
441 	 * If we undid more than we redid, move the entry lists before and
442 	 * including curbuf->b_u_curhead to an alternate branch.
443 	 */
444 	old_curhead = curbuf->b_u_curhead;
445 	if (old_curhead != NULL)
446 	{
447 	    curbuf->b_u_newhead = old_curhead->uh_next.ptr;
448 	    curbuf->b_u_curhead = NULL;
449 	}
450 
451 	/*
452 	 * free headers to keep the size right
453 	 */
454 	while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
455 	{
456 	    u_header_T	    *uhfree = curbuf->b_u_oldhead;
457 
458 	    if (uhfree == old_curhead)
459 		/* Can't reconnect the branch, delete all of it. */
460 		u_freebranch(curbuf, uhfree, &old_curhead);
461 	    else if (uhfree->uh_alt_next.ptr == NULL)
462 		/* There is no branch, only free one header. */
463 		u_freeheader(curbuf, uhfree, &old_curhead);
464 	    else
465 	    {
466 		/* Free the oldest alternate branch as a whole. */
467 		while (uhfree->uh_alt_next.ptr != NULL)
468 		    uhfree = uhfree->uh_alt_next.ptr;
469 		u_freebranch(curbuf, uhfree, &old_curhead);
470 	    }
471 #ifdef U_DEBUG
472 	    u_check(TRUE);
473 #endif
474 	}
475 
476 	if (uhp == NULL)		/* no undo at all */
477 	{
478 	    if (old_curhead != NULL)
479 		u_freebranch(curbuf, old_curhead, NULL);
480 	    curbuf->b_u_synced = FALSE;
481 	    return OK;
482 	}
483 
484 	uhp->uh_prev.ptr = NULL;
485 	uhp->uh_next.ptr = curbuf->b_u_newhead;
486 	uhp->uh_alt_next.ptr = old_curhead;
487 	if (old_curhead != NULL)
488 	{
489 	    uhp->uh_alt_prev.ptr = old_curhead->uh_alt_prev.ptr;
490 	    if (uhp->uh_alt_prev.ptr != NULL)
491 		uhp->uh_alt_prev.ptr->uh_alt_next.ptr = uhp;
492 	    old_curhead->uh_alt_prev.ptr = uhp;
493 	    if (curbuf->b_u_oldhead == old_curhead)
494 		curbuf->b_u_oldhead = uhp;
495 	}
496 	else
497 	    uhp->uh_alt_prev.ptr = NULL;
498 	if (curbuf->b_u_newhead != NULL)
499 	    curbuf->b_u_newhead->uh_prev.ptr = uhp;
500 
501 	uhp->uh_seq = ++curbuf->b_u_seq_last;
502 	curbuf->b_u_seq_cur = uhp->uh_seq;
503 	uhp->uh_time = time(NULL);
504 	uhp->uh_save_nr = 0;
505 	curbuf->b_u_time_cur = uhp->uh_time + 1;
506 
507 	uhp->uh_walk = 0;
508 	uhp->uh_entry = NULL;
509 	uhp->uh_getbot_entry = NULL;
510 	uhp->uh_cursor = curwin->w_cursor;	/* save cursor pos. for undo */
511 #ifdef FEAT_VIRTUALEDIT
512 	if (virtual_active() && curwin->w_cursor.coladd > 0)
513 	    uhp->uh_cursor_vcol = getviscol();
514 	else
515 	    uhp->uh_cursor_vcol = -1;
516 #endif
517 
518 	/* save changed and buffer empty flag for undo */
519 	uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
520 		       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
521 
522 	/* save named marks and Visual marks for undo */
523 	mch_memmove(uhp->uh_namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
524 #ifdef FEAT_VISUAL
525 	uhp->uh_visual = curbuf->b_visual;
526 #endif
527 
528 	curbuf->b_u_newhead = uhp;
529 	if (curbuf->b_u_oldhead == NULL)
530 	    curbuf->b_u_oldhead = uhp;
531 	++curbuf->b_u_numhead;
532     }
533     else
534     {
535 	if (p_ul < 0)		/* no undo at all */
536 	    return OK;
537 
538 	/*
539 	 * When saving a single line, and it has been saved just before, it
540 	 * doesn't make sense saving it again.  Saves a lot of memory when
541 	 * making lots of changes inside the same line.
542 	 * This is only possible if the previous change didn't increase or
543 	 * decrease the number of lines.
544 	 * Check the ten last changes.  More doesn't make sense and takes too
545 	 * long.
546 	 */
547 	if (size == 1)
548 	{
549 	    uep = u_get_headentry();
550 	    prev_uep = NULL;
551 	    for (i = 0; i < 10; ++i)
552 	    {
553 		if (uep == NULL)
554 		    break;
555 
556 		/* If lines have been inserted/deleted we give up.
557 		 * Also when the line was included in a multi-line save. */
558 		if ((curbuf->b_u_newhead->uh_getbot_entry != uep
559 			    ? (uep->ue_top + uep->ue_size + 1
560 				!= (uep->ue_bot == 0
561 				    ? curbuf->b_ml.ml_line_count + 1
562 				    : uep->ue_bot))
563 			    : uep->ue_lcount != curbuf->b_ml.ml_line_count)
564 			|| (uep->ue_size > 1
565 			    && top >= uep->ue_top
566 			    && top + 2 <= uep->ue_top + uep->ue_size + 1))
567 		    break;
568 
569 		/* If it's the same line we can skip saving it again. */
570 		if (uep->ue_size == 1 && uep->ue_top == top)
571 		{
572 		    if (i > 0)
573 		    {
574 			/* It's not the last entry: get ue_bot for the last
575 			 * entry now.  Following deleted/inserted lines go to
576 			 * the re-used entry. */
577 			u_getbot();
578 			curbuf->b_u_synced = FALSE;
579 
580 			/* Move the found entry to become the last entry.  The
581 			 * order of undo/redo doesn't matter for the entries
582 			 * we move it over, since they don't change the line
583 			 * count and don't include this line.  It does matter
584 			 * for the found entry if the line count is changed by
585 			 * the executed command. */
586 			prev_uep->ue_next = uep->ue_next;
587 			uep->ue_next = curbuf->b_u_newhead->uh_entry;
588 			curbuf->b_u_newhead->uh_entry = uep;
589 		    }
590 
591 		    /* The executed command may change the line count. */
592 		    if (newbot != 0)
593 			uep->ue_bot = newbot;
594 		    else if (bot > curbuf->b_ml.ml_line_count)
595 			uep->ue_bot = 0;
596 		    else
597 		    {
598 			uep->ue_lcount = curbuf->b_ml.ml_line_count;
599 			curbuf->b_u_newhead->uh_getbot_entry = uep;
600 		    }
601 		    return OK;
602 		}
603 		prev_uep = uep;
604 		uep = uep->ue_next;
605 	    }
606 	}
607 
608 	/* find line number for ue_bot for previous u_save() */
609 	u_getbot();
610     }
611 
612 #if !defined(UNIX) && !defined(DJGPP) && !defined(WIN32) && !defined(__EMX__)
613 	/*
614 	 * With Amiga and MSDOS 16 bit we can't handle big undo's, because
615 	 * then u_alloc_line would have to allocate a block larger than 32K
616 	 */
617     if (size >= 8000)
618 	goto nomem;
619 #endif
620 
621     /*
622      * add lines in front of entry list
623      */
624     uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T));
625     if (uep == NULL)
626 	goto nomem;
627     vim_memset(uep, 0, sizeof(u_entry_T));
628 #ifdef U_DEBUG
629     uep->ue_magic = UE_MAGIC;
630 #endif
631 
632     uep->ue_size = size;
633     uep->ue_top = top;
634     if (newbot != 0)
635 	uep->ue_bot = newbot;
636     /*
637      * Use 0 for ue_bot if bot is below last line.
638      * Otherwise we have to compute ue_bot later.
639      */
640     else if (bot > curbuf->b_ml.ml_line_count)
641 	uep->ue_bot = 0;
642     else
643     {
644 	uep->ue_lcount = curbuf->b_ml.ml_line_count;
645 	curbuf->b_u_newhead->uh_getbot_entry = uep;
646     }
647 
648     if (size > 0)
649     {
650 	if ((uep->ue_array = (char_u **)U_ALLOC_LINE(
651 					    sizeof(char_u *) * size)) == NULL)
652 	{
653 	    u_freeentry(uep, 0L);
654 	    goto nomem;
655 	}
656 	for (i = 0, lnum = top + 1; i < size; ++i)
657 	{
658 	    fast_breakcheck();
659 	    if (got_int)
660 	    {
661 		u_freeentry(uep, i);
662 		return FAIL;
663 	    }
664 	    if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL)
665 	    {
666 		u_freeentry(uep, i);
667 		goto nomem;
668 	    }
669 	}
670     }
671     else
672 	uep->ue_array = NULL;
673     uep->ue_next = curbuf->b_u_newhead->uh_entry;
674     curbuf->b_u_newhead->uh_entry = uep;
675     curbuf->b_u_synced = FALSE;
676     undo_undoes = FALSE;
677 
678 #ifdef U_DEBUG
679     u_check(FALSE);
680 #endif
681     return OK;
682 
683 nomem:
684     msg_silent = 0;	/* must display the prompt */
685     if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE)
686 								       == 'y')
687     {
688 	undo_off = TRUE;	    /* will be reset when character typed */
689 	return OK;
690     }
691     do_outofmem_msg((long_u)0);
692     return FAIL;
693 }
694 
695 #if defined(FEAT_PERSISTENT_UNDO) || defined(PROTO)
696 
697 # define UF_START_MAGIC	    "Vim\237UnDo\345"  /* magic at start of undofile */
698 # define UF_START_MAGIC_LEN	9
699 # define UF_HEADER_MAGIC	0x5fd0	/* magic at start of header */
700 # define UF_HEADER_END_MAGIC	0xe7aa	/* magic after last header */
701 # define UF_ENTRY_MAGIC		0xf518	/* magic at start of entry */
702 # define UF_ENTRY_END_MAGIC	0x3581	/* magic after last entry */
703 # define UF_VERSION		2	/* 2-byte undofile version number */
704 # define UF_VERSION_CRYPT	0x8002	/* idem, encrypted */
705 
706 /* extra fields for header */
707 # define UF_LAST_SAVE_NR	1
708 
709 /* extra fields for uhp */
710 # define UHP_SAVE_NR		1
711 
712 static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
713 
714 /*
715  * Compute the hash for the current buffer text into hash[UNDO_HASH_SIZE].
716  */
717     void
718 u_compute_hash(hash)
719     char_u *hash;
720 {
721     context_sha256_T	ctx;
722     linenr_T		lnum;
723     char_u		*p;
724 
725     sha256_start(&ctx);
726     for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum)
727     {
728 	p = ml_get(lnum);
729 	sha256_update(&ctx, p, (UINT32_T)(STRLEN(p) + 1));
730     }
731     sha256_finish(&ctx, hash);
732 }
733 
734 /*
735  * Return an allocated string of the full path of the target undofile.
736  * When "reading" is TRUE find the file to read, go over all directories in
737  * 'undodir'.
738  * When "reading" is FALSE use the first name where the directory exists.
739  * Returns NULL when there is no place to write or no file to read.
740  */
741     char_u *
742 u_get_undo_file_name(buf_ffname, reading)
743     char_u	*buf_ffname;
744     int		reading;
745 {
746     char_u	*dirp;
747     char_u	dir_name[IOSIZE + 1];
748     char_u	*munged_name = NULL;
749     char_u	*undo_file_name = NULL;
750     int		dir_len;
751     char_u	*p;
752     struct stat st;
753     char_u	*ffname = buf_ffname;
754 #ifdef HAVE_READLINK
755     char_u	fname_buf[MAXPATHL];
756 #endif
757 
758     if (ffname == NULL)
759 	return NULL;
760 
761 #ifdef HAVE_READLINK
762     /* Expand symlink in the file name, so that we put the undo file with the
763      * actual file instead of with the symlink. */
764     if (resolve_symlink(ffname, fname_buf) == OK)
765 	ffname = fname_buf;
766 #endif
767 
768     /* Loop over 'undodir'.  When reading find the first file that exists.
769      * When not reading use the first directory that exists or ".". */
770     dirp = p_udir;
771     while (*dirp != NUL)
772     {
773 	dir_len = copy_option_part(&dirp, dir_name, IOSIZE, ",");
774 	if (dir_len == 1 && dir_name[0] == '.')
775 	{
776 	    /* Use same directory as the ffname,
777 	     * "dir/name" -> "dir/.name.un~" */
778 	    undo_file_name = vim_strnsave(ffname, (int)(STRLEN(ffname) + 5));
779 	    if (undo_file_name == NULL)
780 		break;
781 	    p = gettail(undo_file_name);
782 	    mch_memmove(p + 1, p, STRLEN(p) + 1);
783 	    *p = '.';
784 	    STRCAT(p, ".un~");
785 	}
786 	else
787 	{
788 	    dir_name[dir_len] = NUL;
789 	    if (mch_isdir(dir_name))
790 	    {
791 		if (munged_name == NULL)
792 		{
793 		    munged_name = vim_strsave(ffname);
794 		    if (munged_name == NULL)
795 			return NULL;
796 		    for (p = munged_name; *p != NUL; mb_ptr_adv(p))
797 			if (vim_ispathsep(*p))
798 			    *p = '%';
799 		}
800 		undo_file_name = concat_fnames(dir_name, munged_name, TRUE);
801 	    }
802 	}
803 
804 	/* When reading check if the file exists. */
805 	if (undo_file_name != NULL && (!reading
806 			       || mch_stat((char *)undo_file_name, &st) >= 0))
807 	    break;
808 	vim_free(undo_file_name);
809 	undo_file_name = NULL;
810     }
811 
812     vim_free(munged_name);
813     return undo_file_name;
814 }
815 
816     static void
817 corruption_error(mesg, file_name)
818     char *mesg;
819     char_u *file_name;
820 {
821     EMSG3(_("E825: Corrupted undo file (%s): %s"), mesg, file_name);
822 }
823 
824     static void
825 u_free_uhp(uhp)
826     u_header_T	*uhp;
827 {
828     u_entry_T	*nuep;
829     u_entry_T	*uep;
830 
831     uep = uhp->uh_entry;
832     while (uep != NULL)
833     {
834 	nuep = uep->ue_next;
835 	u_freeentry(uep, uep->ue_size);
836 	uep = nuep;
837     }
838     vim_free(uhp);
839 }
840 
841 /*
842  * Like fwrite() but crypt the bytes when 'key' is set.
843  * Returns 1 if successful.
844  */
845     static size_t
846 fwrite_crypt(buf, ptr, len, fp)
847     buf_T	*buf UNUSED;
848     char_u	*ptr;
849     size_t	len;
850     FILE	*fp;
851 {
852 #ifdef FEAT_CRYPT
853     char_u  *copy;
854     char_u  small_buf[100];
855     size_t  i;
856 
857     if (*buf->b_p_key == NUL)
858 	return fwrite(ptr, len, (size_t)1, fp);
859     if (len < 100)
860 	copy = small_buf;  /* no malloc()/free() for short strings */
861     else
862     {
863 	copy = lalloc(len, FALSE);
864 	if (copy == NULL)
865 	    return 0;
866     }
867     crypt_encode(ptr, len, copy);
868     i = fwrite(copy, len, (size_t)1, fp);
869     if (copy != small_buf)
870 	vim_free(copy);
871     return i;
872 #else
873     return fwrite(ptr, len, (size_t)1, fp);
874 #endif
875 }
876 
877 /*
878  * Read a string of length "len" from "fd".
879  * When 'key' is set decrypt the bytes.
880  */
881     static char_u *
882 read_string_decrypt(buf, fd, len)
883     buf_T   *buf UNUSED;
884     FILE    *fd;
885     int	    len;
886 {
887     char_u  *ptr;
888 
889     ptr = read_string(fd, len);
890 #ifdef FEAT_CRYPT
891     if (ptr != NULL && *buf->b_p_key != NUL)
892 	crypt_decode(ptr, len);
893 #endif
894     return ptr;
895 }
896 
897     static int
898 serialize_header(fp, buf, hash)
899     FILE	*fp;
900     buf_T	*buf;
901     char_u	*hash;
902 {
903     int len;
904 
905     /* Start writing, first the magic marker and undo info version. */
906     if (fwrite(UF_START_MAGIC, (size_t)UF_START_MAGIC_LEN, (size_t)1, fp) != 1)
907 	return FAIL;
908 
909     /* If the buffer is encrypted then all text bytes following will be
910      * encrypted.  Numbers and other info is not crypted. */
911 #ifdef FEAT_CRYPT
912     if (*buf->b_p_key != NUL)
913     {
914 	char_u *header;
915 	int    header_len;
916 
917 	put_bytes(fp, (long_u)UF_VERSION_CRYPT, 2);
918 	header = prepare_crypt_write(buf, &header_len);
919 	if (header == NULL)
920 	    return FAIL;
921 	len = (int)fwrite(header, (size_t)header_len, (size_t)1, fp);
922 	vim_free(header);
923 	if (len != 1)
924 	{
925 	    crypt_pop_state();
926 	    return FAIL;
927 	}
928     }
929     else
930 #endif
931 	put_bytes(fp, (long_u)UF_VERSION, 2);
932 
933 
934     /* Write a hash of the buffer text, so that we can verify it is still the
935      * same when reading the buffer text. */
936     if (fwrite(hash, (size_t)UNDO_HASH_SIZE, (size_t)1, fp) != 1)
937 	return FAIL;
938 
939     /* buffer-specific data */
940     put_bytes(fp, (long_u)buf->b_ml.ml_line_count, 4);
941     len = buf->b_u_line_ptr != NULL ? (int)STRLEN(buf->b_u_line_ptr) : 0;
942     put_bytes(fp, (long_u)len, 4);
943     if (len > 0 && fwrite_crypt(buf, buf->b_u_line_ptr, (size_t)len, fp) != 1)
944 	return FAIL;
945     put_bytes(fp, (long_u)buf->b_u_line_lnum, 4);
946     put_bytes(fp, (long_u)buf->b_u_line_colnr, 4);
947 
948     /* Undo structures header data */
949     put_header_ptr(fp, buf->b_u_oldhead);
950     put_header_ptr(fp, buf->b_u_newhead);
951     put_header_ptr(fp, buf->b_u_curhead);
952 
953     put_bytes(fp, (long_u)buf->b_u_numhead, 4);
954     put_bytes(fp, (long_u)buf->b_u_seq_last, 4);
955     put_bytes(fp, (long_u)buf->b_u_seq_cur, 4);
956     put_time(fp, buf->b_u_time_cur);
957 
958     /* Optional fields. */
959     putc(4, fp);
960     putc(UF_LAST_SAVE_NR, fp);
961     put_bytes(fp, (long_u)buf->b_u_save_nr_last, 4);
962 
963     putc(0, fp);  /* end marker */
964 
965     return OK;
966 }
967 
968     static int
969 serialize_uhp(fp, buf, uhp)
970     FILE	*fp;
971     buf_T	*buf;
972     u_header_T	*uhp;
973 {
974     int		i;
975     u_entry_T	*uep;
976 
977     if (put_bytes(fp, (long_u)UF_HEADER_MAGIC, 2) == FAIL)
978 	return FAIL;
979 
980     put_header_ptr(fp, uhp->uh_next.ptr);
981     put_header_ptr(fp, uhp->uh_prev.ptr);
982     put_header_ptr(fp, uhp->uh_alt_next.ptr);
983     put_header_ptr(fp, uhp->uh_alt_prev.ptr);
984     put_bytes(fp, uhp->uh_seq, 4);
985     serialize_pos(uhp->uh_cursor, fp);
986 #ifdef FEAT_VIRTUALEDIT
987     put_bytes(fp, (long_u)uhp->uh_cursor_vcol, 4);
988 #else
989     put_bytes(fp, (long_u)0, 4);
990 #endif
991     put_bytes(fp, (long_u)uhp->uh_flags, 2);
992     /* Assume NMARKS will stay the same. */
993     for (i = 0; i < NMARKS; ++i)
994 	serialize_pos(uhp->uh_namedm[i], fp);
995 #ifdef FEAT_VISUAL
996     serialize_visualinfo(&uhp->uh_visual, fp);
997 #else
998     {
999 	visualinfo_T info;
1000 
1001 	memset(&info, 0, sizeof(visualinfo_T));
1002 	serialize_visualinfo(&info, fp);
1003     }
1004 #endif
1005     put_time(fp, uhp->uh_time);
1006 
1007     /* Optional fields. */
1008     putc(4, fp);
1009     putc(UHP_SAVE_NR, fp);
1010     put_bytes(fp, (long_u)uhp->uh_save_nr, 4);
1011 
1012     putc(0, fp);  /* end marker */
1013 
1014     /* Write all the entries. */
1015     for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
1016     {
1017 	put_bytes(fp, (long_u)UF_ENTRY_MAGIC, 2);
1018 	if (serialize_uep(fp, buf, uep) == FAIL)
1019 	    return FAIL;
1020     }
1021     put_bytes(fp, (long_u)UF_ENTRY_END_MAGIC, 2);
1022     return OK;
1023 }
1024 
1025     static u_header_T *
1026 unserialize_uhp(fp, file_name)
1027     FILE	*fp;
1028     char_u	*file_name;
1029 {
1030     u_header_T	*uhp;
1031     int		i;
1032     u_entry_T	*uep, *last_uep;
1033     int		c;
1034     int		error;
1035 
1036     uhp = (u_header_T *)U_ALLOC_LINE(sizeof(u_header_T));
1037     if (uhp == NULL)
1038 	return NULL;
1039     vim_memset(uhp, 0, sizeof(u_header_T));
1040 #ifdef U_DEBUG
1041     uhp->uh_magic = UH_MAGIC;
1042 #endif
1043     uhp->uh_next.seq = get4c(fp);
1044     uhp->uh_prev.seq = get4c(fp);
1045     uhp->uh_alt_next.seq = get4c(fp);
1046     uhp->uh_alt_prev.seq = get4c(fp);
1047     uhp->uh_seq = get4c(fp);
1048     if (uhp->uh_seq <= 0)
1049     {
1050 	corruption_error("uh_seq", file_name);
1051 	vim_free(uhp);
1052 	return NULL;
1053     }
1054     unserialize_pos(&uhp->uh_cursor, fp);
1055 #ifdef FEAT_VIRTUALEDIT
1056     uhp->uh_cursor_vcol = get4c(fp);
1057 #else
1058     (void)get4c(fp);
1059 #endif
1060     uhp->uh_flags = get2c(fp);
1061     for (i = 0; i < NMARKS; ++i)
1062 	unserialize_pos(&uhp->uh_namedm[i], fp);
1063 #ifdef FEAT_VISUAL
1064     unserialize_visualinfo(&uhp->uh_visual, fp);
1065 #else
1066     {
1067 	visualinfo_T info;
1068 	unserialize_visualinfo(&info, fp);
1069     }
1070 #endif
1071     uhp->uh_time = get8ctime(fp);
1072 
1073     /* Optional fields. */
1074     for (;;)
1075     {
1076 	int len = getc(fp);
1077 	int what;
1078 
1079 	if (len == 0)
1080 	    break;
1081 	what = getc(fp);
1082 	switch (what)
1083 	{
1084 	    case UHP_SAVE_NR:
1085 		uhp->uh_save_nr = get4c(fp);
1086 		break;
1087 	    default:
1088 		/* field not supported, skip */
1089 		while (--len >= 0)
1090 		    (void)getc(fp);
1091 	}
1092     }
1093 
1094     /* Unserialize the uep list. */
1095     last_uep = NULL;
1096     while ((c = get2c(fp)) == UF_ENTRY_MAGIC)
1097     {
1098 	error = FALSE;
1099 	uep = unserialize_uep(fp, &error, file_name);
1100 	if (last_uep == NULL)
1101 	    uhp->uh_entry = uep;
1102 	else
1103 	    last_uep->ue_next = uep;
1104 	last_uep = uep;
1105 	if (uep == NULL || error)
1106 	{
1107 	    u_free_uhp(uhp);
1108 	    return NULL;
1109 	}
1110     }
1111     if (c != UF_ENTRY_END_MAGIC)
1112     {
1113 	corruption_error("entry end", file_name);
1114 	u_free_uhp(uhp);
1115 	return NULL;
1116     }
1117 
1118     return uhp;
1119 }
1120 
1121 /*
1122  * Serialize "uep" to "fp".
1123  */
1124     static int
1125 serialize_uep(fp, buf, uep)
1126     FILE	*fp;
1127     buf_T	*buf;
1128     u_entry_T	*uep;
1129 {
1130     int		i;
1131     size_t	len;
1132 
1133     put_bytes(fp, (long_u)uep->ue_top, 4);
1134     put_bytes(fp, (long_u)uep->ue_bot, 4);
1135     put_bytes(fp, (long_u)uep->ue_lcount, 4);
1136     put_bytes(fp, (long_u)uep->ue_size, 4);
1137     for (i = 0; i < uep->ue_size; ++i)
1138     {
1139 	len = STRLEN(uep->ue_array[i]);
1140 	if (put_bytes(fp, (long_u)len, 4) == FAIL)
1141 	    return FAIL;
1142 	if (len > 0 && fwrite_crypt(buf, uep->ue_array[i], len, fp) != 1)
1143 	    return FAIL;
1144     }
1145     return OK;
1146 }
1147 
1148     static u_entry_T *
1149 unserialize_uep(fp, error, file_name)
1150     FILE	*fp;
1151     int		*error;
1152     char_u	*file_name;
1153 {
1154     int		i;
1155     u_entry_T	*uep;
1156     char_u	**array;
1157     char_u	*line;
1158     int		line_len;
1159 
1160     uep = (u_entry_T *)U_ALLOC_LINE(sizeof(u_entry_T));
1161     if (uep == NULL)
1162 	return NULL;
1163     vim_memset(uep, 0, sizeof(u_entry_T));
1164 #ifdef U_DEBUG
1165     uep->ue_magic = UE_MAGIC;
1166 #endif
1167     uep->ue_top = get4c(fp);
1168     uep->ue_bot = get4c(fp);
1169     uep->ue_lcount = get4c(fp);
1170     uep->ue_size = get4c(fp);
1171     if (uep->ue_size > 0)
1172     {
1173 	array = (char_u **)U_ALLOC_LINE(sizeof(char_u *) * uep->ue_size);
1174 	if (array == NULL)
1175 	{
1176 	    *error = TRUE;
1177 	    return uep;
1178 	}
1179 	vim_memset(array, 0, sizeof(char_u *) * uep->ue_size);
1180     }
1181     else
1182 	array = NULL;
1183     uep->ue_array = array;
1184 
1185     for (i = 0; i < uep->ue_size; ++i)
1186     {
1187 	line_len = get4c(fp);
1188 	if (line_len >= 0)
1189 	    line = read_string_decrypt(curbuf, fp, line_len);
1190 	else
1191 	{
1192 	    line = NULL;
1193 	    corruption_error("line length", file_name);
1194 	}
1195 	if (line == NULL)
1196 	{
1197 	    *error = TRUE;
1198 	    return uep;
1199 	}
1200 	array[i] = line;
1201     }
1202     return uep;
1203 }
1204 
1205 /*
1206  * Serialize "pos" to "fp".
1207  */
1208     static void
1209 serialize_pos(pos, fp)
1210     pos_T pos;
1211     FILE  *fp;
1212 {
1213     put_bytes(fp, (long_u)pos.lnum, 4);
1214     put_bytes(fp, (long_u)pos.col, 4);
1215 #ifdef FEAT_VIRTUALEDIT
1216     put_bytes(fp, (long_u)pos.coladd, 4);
1217 #else
1218     put_bytes(fp, (long_u)0, 4);
1219 #endif
1220 }
1221 
1222 /*
1223  * Unserialize the pos_T at the current position in fp.
1224  */
1225     static void
1226 unserialize_pos(pos, fp)
1227     pos_T *pos;
1228     FILE  *fp;
1229 {
1230     pos->lnum = get4c(fp);
1231     if (pos->lnum < 0)
1232 	pos->lnum = 0;
1233     pos->col = get4c(fp);
1234     if (pos->col < 0)
1235 	pos->col = 0;
1236 #ifdef FEAT_VIRTUALEDIT
1237     pos->coladd = get4c(fp);
1238     if (pos->coladd < 0)
1239 	pos->coladd = 0;
1240 #else
1241     (void)get4c(fp);
1242 #endif
1243 }
1244 
1245 /*
1246  * Serialize "info" to "fp".
1247  */
1248     static void
1249 serialize_visualinfo(info, fp)
1250     visualinfo_T    *info;
1251     FILE	    *fp;
1252 {
1253     serialize_pos(info->vi_start, fp);
1254     serialize_pos(info->vi_end, fp);
1255     put_bytes(fp, (long_u)info->vi_mode, 4);
1256     put_bytes(fp, (long_u)info->vi_curswant, 4);
1257 }
1258 
1259 /*
1260  * Unserialize the visualinfo_T at the current position in fp.
1261  */
1262     static void
1263 unserialize_visualinfo(info, fp)
1264     visualinfo_T    *info;
1265     FILE	    *fp;
1266 {
1267     unserialize_pos(&info->vi_start, fp);
1268     unserialize_pos(&info->vi_end, fp);
1269     info->vi_mode = get4c(fp);
1270     info->vi_curswant = get4c(fp);
1271 }
1272 
1273 /*
1274  * Write the pointer to an undo header.  Instead of writing the pointer itself
1275  * we use the sequence number of the header.  This is converted back to
1276  * pointers when reading. */
1277     static void
1278 put_header_ptr(fp, uhp)
1279     FILE	*fp;
1280     u_header_T	*uhp;
1281 {
1282     put_bytes(fp, (long_u)(uhp != NULL ? uhp->uh_seq : 0), 4);
1283 }
1284 
1285 /*
1286  * Write the undo tree in an undo file.
1287  * When "name" is not NULL, use it as the name of the undo file.
1288  * Otherwise use buf->b_ffname to generate the undo file name.
1289  * "buf" must never be null, buf->b_ffname is used to obtain the original file
1290  * permissions.
1291  * "forceit" is TRUE for ":wundo!", FALSE otherwise.
1292  * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
1293  */
1294     void
1295 u_write_undo(name, forceit, buf, hash)
1296     char_u	*name;
1297     int		forceit;
1298     buf_T	*buf;
1299     char_u	*hash;
1300 {
1301     u_header_T	*uhp;
1302     char_u	*file_name;
1303     int		mark;
1304 #ifdef U_DEBUG
1305     int		headers_written = 0;
1306 #endif
1307     int		fd;
1308     FILE	*fp = NULL;
1309     int		perm;
1310     int		write_ok = FALSE;
1311 #ifdef UNIX
1312     int		st_old_valid = FALSE;
1313     struct stat	st_old;
1314     struct stat	st_new;
1315 #endif
1316 #ifdef FEAT_CRYPT
1317     int		do_crypt = FALSE;
1318 #endif
1319 
1320     if (name == NULL)
1321     {
1322 	file_name = u_get_undo_file_name(buf->b_ffname, FALSE);
1323 	if (file_name == NULL)
1324 	{
1325 	    if (p_verbose > 0)
1326 	    {
1327 		verbose_enter();
1328 		smsg((char_u *)
1329 		   _("Cannot write undo file in any directory in 'undodir'"));
1330 		verbose_leave();
1331 	    }
1332 	    return;
1333 	}
1334     }
1335     else
1336 	file_name = name;
1337 
1338     /*
1339      * Decide about the permission to use for the undo file.  If the buffer
1340      * has a name use the permission of the original file.  Otherwise only
1341      * allow the user to access the undo file.
1342      */
1343     perm = 0600;
1344     if (buf->b_ffname != NULL)
1345     {
1346 #ifdef UNIX
1347 	if (mch_stat((char *)buf->b_ffname, &st_old) >= 0)
1348 	{
1349 	    perm = st_old.st_mode;
1350 	    st_old_valid = TRUE;
1351 	}
1352 #else
1353 	perm = mch_getperm(buf->b_ffname);
1354 	if (perm < 0)
1355 	    perm = 0600;
1356 #endif
1357     }
1358 
1359     /* strip any s-bit */
1360     perm = perm & 0777;
1361 
1362     /* If the undo file already exists, verify that it actually is an undo
1363      * file, and delete it. */
1364     if (mch_getperm(file_name) >= 0)
1365     {
1366 	if (name == NULL || !forceit)
1367 	{
1368 	    /* Check we can read it and it's an undo file. */
1369 	    fd = mch_open((char *)file_name, O_RDONLY|O_EXTRA, 0);
1370 	    if (fd < 0)
1371 	    {
1372 		if (name != NULL || p_verbose > 0)
1373 		{
1374 		    if (name == NULL)
1375 			verbose_enter();
1376 		    smsg((char_u *)
1377 		      _("Will not overwrite with undo file, cannot read: %s"),
1378 								   file_name);
1379 		    if (name == NULL)
1380 			verbose_leave();
1381 		}
1382 		goto theend;
1383 	    }
1384 	    else
1385 	    {
1386 		char_u	mbuf[UF_START_MAGIC_LEN];
1387 		int	len;
1388 
1389 		len = vim_read(fd, mbuf, UF_START_MAGIC_LEN);
1390 		close(fd);
1391 		if (len < UF_START_MAGIC_LEN
1392 		      || memcmp(mbuf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0)
1393 		{
1394 		    if (name != NULL || p_verbose > 0)
1395 		    {
1396 			if (name == NULL)
1397 			    verbose_enter();
1398 			smsg((char_u *)
1399 			_("Will not overwrite, this is not an undo file: %s"),
1400 								   file_name);
1401 			if (name == NULL)
1402 			    verbose_leave();
1403 		    }
1404 		    goto theend;
1405 		}
1406 	    }
1407 	}
1408 	mch_remove(file_name);
1409     }
1410 
1411     /* If there is no undo information at all, quit here after deleting any
1412      * existing undo file. */
1413     if (buf->b_u_numhead == 0 && buf->b_u_line_ptr == NULL)
1414     {
1415 	if (p_verbose > 0)
1416 	    verb_msg((char_u *)_("Skipping undo file write, nothing to undo"));
1417 	goto theend;
1418     }
1419 
1420     fd = mch_open((char *)file_name,
1421 			    O_CREAT|O_EXTRA|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
1422     if (fd < 0)
1423     {
1424 	EMSG2(_(e_not_open), file_name);
1425 	goto theend;
1426     }
1427     (void)mch_setperm(file_name, perm);
1428     if (p_verbose > 0)
1429     {
1430 	verbose_enter();
1431 	smsg((char_u *)_("Writing undo file: %s"), file_name);
1432 	verbose_leave();
1433     }
1434 
1435 #ifdef U_DEBUG
1436     /* Check there is no problem in undo info before writing. */
1437     u_check(FALSE);
1438 #endif
1439 
1440 #ifdef UNIX
1441     /*
1442      * Try to set the group of the undo file same as the original file. If
1443      * this fails, set the protection bits for the group same as the
1444      * protection bits for others.
1445      */
1446     if (st_old_valid
1447 	    && mch_stat((char *)file_name, &st_new) >= 0
1448 	    && st_new.st_gid != st_old.st_gid
1449 # ifdef HAVE_FCHOWN  /* sequent-ptx lacks fchown() */
1450 	    && fchown(fd, (uid_t)-1, st_old.st_gid) != 0
1451 # endif
1452        )
1453 	mch_setperm(file_name, (perm & 0707) | ((perm & 07) << 3));
1454 # ifdef HAVE_SELINUX
1455     if (buf->b_ffname != NULL)
1456 	mch_copy_sec(buf->b_ffname, file_name);
1457 # endif
1458 #endif
1459 
1460     fp = fdopen(fd, "w");
1461     if (fp == NULL)
1462     {
1463 	EMSG2(_(e_not_open), file_name);
1464 	close(fd);
1465 	mch_remove(file_name);
1466 	goto theend;
1467     }
1468 
1469     /* Undo must be synced. */
1470     u_sync(TRUE);
1471 
1472     /*
1473      * Write the header.
1474      */
1475     if (serialize_header(fp, buf, hash) == FAIL)
1476 	goto write_error;
1477 #ifdef FEAT_CRYPT
1478     if (*buf->b_p_key != NUL)
1479 	do_crypt = TRUE;
1480 #endif
1481 
1482     /*
1483      * Iteratively serialize UHPs and their UEPs from the top down.
1484      */
1485     mark = ++lastmark;
1486     uhp = buf->b_u_oldhead;
1487     while (uhp != NULL)
1488     {
1489 	/* Serialize current UHP if we haven't seen it */
1490 	if (uhp->uh_walk != mark)
1491 	{
1492 	    uhp->uh_walk = mark;
1493 #ifdef U_DEBUG
1494 	    ++headers_written;
1495 #endif
1496 	    if (serialize_uhp(fp, buf, uhp) == FAIL)
1497 		goto write_error;
1498 	}
1499 
1500 	/* Now walk through the tree - algorithm from undo_time(). */
1501 	if (uhp->uh_prev.ptr != NULL && uhp->uh_prev.ptr->uh_walk != mark)
1502 	    uhp = uhp->uh_prev.ptr;
1503 	else if (uhp->uh_alt_next.ptr != NULL
1504 				     && uhp->uh_alt_next.ptr->uh_walk != mark)
1505 	    uhp = uhp->uh_alt_next.ptr;
1506 	else if (uhp->uh_next.ptr != NULL && uhp->uh_alt_prev.ptr == NULL
1507 					 && uhp->uh_next.ptr->uh_walk != mark)
1508 	    uhp = uhp->uh_next.ptr;
1509 	else if (uhp->uh_alt_prev.ptr != NULL)
1510 	    uhp = uhp->uh_alt_prev.ptr;
1511 	else
1512 	    uhp = uhp->uh_next.ptr;
1513     }
1514 
1515     if (put_bytes(fp, (long_u)UF_HEADER_END_MAGIC, 2) == OK)
1516 	write_ok = TRUE;
1517 #ifdef U_DEBUG
1518     if (headers_written != buf->b_u_numhead)
1519 	EMSG3("Written %ld headers, but numhead is %ld",
1520 					   headers_written, buf->b_u_numhead);
1521 #endif
1522 
1523 write_error:
1524     fclose(fp);
1525     if (!write_ok)
1526 	EMSG2(_("E829: write error in undo file: %s"), file_name);
1527 
1528 #if defined(MACOS_CLASSIC) || defined(WIN3264)
1529     /* Copy file attributes; for systems where this can only be done after
1530      * closing the file. */
1531     if (buf->b_ffname != NULL)
1532 	(void)mch_copy_file_attribute(buf->b_ffname, file_name);
1533 #endif
1534 #ifdef HAVE_ACL
1535     if (buf->b_ffname != NULL)
1536     {
1537 	vim_acl_T	    acl;
1538 
1539 	/* For systems that support ACL: get the ACL from the original file. */
1540 	acl = mch_get_acl(buf->b_ffname);
1541 	mch_set_acl(file_name, acl);
1542     }
1543 #endif
1544 
1545 theend:
1546 #ifdef FEAT_CRYPT
1547     if (do_crypt)
1548 	crypt_pop_state();
1549 #endif
1550     if (file_name != name)
1551 	vim_free(file_name);
1552 }
1553 
1554 /*
1555  * Load the undo tree from an undo file.
1556  * If "name" is not NULL use it as the undo file name.  This also means being
1557  * a bit more verbose.
1558  * Otherwise use curbuf->b_ffname to generate the undo file name.
1559  * "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
1560  */
1561     void
1562 u_read_undo(name, hash, orig_name)
1563     char_u *name;
1564     char_u *hash;
1565     char_u *orig_name;
1566 {
1567     char_u	*file_name;
1568     FILE	*fp;
1569     long	version, str_len;
1570     char_u	*line_ptr = NULL;
1571     linenr_T	line_lnum;
1572     colnr_T	line_colnr;
1573     linenr_T	line_count;
1574     int		num_head = 0;
1575     long	old_header_seq, new_header_seq, cur_header_seq;
1576     long	seq_last, seq_cur;
1577     long	last_save_nr = 0;
1578     short	old_idx = -1, new_idx = -1, cur_idx = -1;
1579     long	num_read_uhps = 0;
1580     time_t	seq_time;
1581     int		i, j;
1582     int		c;
1583     u_header_T	*uhp;
1584     u_header_T	**uhp_table = NULL;
1585     char_u	read_hash[UNDO_HASH_SIZE];
1586     char_u	magic_buf[UF_START_MAGIC_LEN];
1587 #ifdef U_DEBUG
1588     int		*uhp_table_used;
1589 #endif
1590 #ifdef UNIX
1591     struct stat	st_orig;
1592     struct stat	st_undo;
1593 #endif
1594 #ifdef FEAT_CRYPT
1595     int		do_decrypt = FALSE;
1596 #endif
1597 
1598     if (name == NULL)
1599     {
1600 	file_name = u_get_undo_file_name(curbuf->b_ffname, TRUE);
1601 	if (file_name == NULL)
1602 	    return;
1603 
1604 #ifdef UNIX
1605 	/* For safety we only read an undo file if the owner is equal to the
1606 	 * owner of the text file. */
1607 	if (mch_stat((char *)orig_name, &st_orig) >= 0
1608 		&& mch_stat((char *)file_name, &st_undo) >= 0
1609 		&& st_orig.st_uid != st_undo.st_uid)
1610 	{
1611 	    if (p_verbose > 0)
1612 	    {
1613 		verbose_enter();
1614 		smsg((char_u *)_("Not reading undo file, owner differs: %s"),
1615 								   file_name);
1616 		verbose_leave();
1617 	    }
1618 	    return;
1619 	}
1620 #endif
1621     }
1622     else
1623 	file_name = name;
1624 
1625     if (p_verbose > 0)
1626     {
1627 	verbose_enter();
1628 	smsg((char_u *)_("Reading undo file: %s"), file_name);
1629 	verbose_leave();
1630     }
1631 
1632     fp = mch_fopen((char *)file_name, "r");
1633     if (fp == NULL)
1634     {
1635 	if (name != NULL || p_verbose > 0)
1636 	    EMSG2(_("E822: Cannot open undo file for reading: %s"), file_name);
1637 	goto error;
1638     }
1639 
1640     /*
1641      * Read the undo file header.
1642      */
1643     if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1
1644 		|| memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0)
1645     {
1646 	EMSG2(_("E823: Not an undo file: %s"), file_name);
1647 	goto error;
1648     }
1649     version = get2c(fp);
1650     if (version == UF_VERSION_CRYPT)
1651     {
1652 #ifdef FEAT_CRYPT
1653 	if (*curbuf->b_p_key == NUL)
1654 	{
1655 	    EMSG2(_("E832: Non-encrypted file has encrypted undo file: %s"),
1656 								   file_name);
1657 	    goto error;
1658 	}
1659 	if (prepare_crypt_read(fp) == FAIL)
1660 	{
1661 	    EMSG2(_("E826: Undo file decryption failed: %s"), file_name);
1662 	    goto error;
1663 	}
1664 	do_decrypt = TRUE;
1665 #else
1666 	EMSG2(_("E827: Undo file is encrypted: %s"), file_name);
1667 	goto error;
1668 #endif
1669     }
1670     else if (version != UF_VERSION)
1671     {
1672 	EMSG2(_("E824: Incompatible undo file: %s"), file_name);
1673 	goto error;
1674     }
1675 
1676     if (fread(read_hash, UNDO_HASH_SIZE, 1, fp) != 1)
1677     {
1678 	corruption_error("hash", file_name);
1679 	goto error;
1680     }
1681     line_count = (linenr_T)get4c(fp);
1682     if (memcmp(hash, read_hash, UNDO_HASH_SIZE) != 0
1683 				  || line_count != curbuf->b_ml.ml_line_count)
1684     {
1685 	if (p_verbose > 0 || name != NULL)
1686 	{
1687 	    if (name == NULL)
1688 		verbose_enter();
1689 	    give_warning((char_u *)
1690 		      _("File contents changed, cannot use undo info"), TRUE);
1691 	    if (name == NULL)
1692 		verbose_leave();
1693 	}
1694 	goto error;
1695     }
1696 
1697     /* Read undo data for "U" command. */
1698     str_len = get4c(fp);
1699     if (str_len < 0)
1700 	goto error;
1701     if (str_len > 0)
1702 	line_ptr = read_string_decrypt(curbuf, fp, str_len);
1703     line_lnum = (linenr_T)get4c(fp);
1704     line_colnr = (colnr_T)get4c(fp);
1705     if (line_lnum < 0 || line_colnr < 0)
1706     {
1707 	corruption_error("line lnum/col", file_name);
1708 	goto error;
1709     }
1710 
1711     /* Begin general undo data */
1712     old_header_seq = get4c(fp);
1713     new_header_seq = get4c(fp);
1714     cur_header_seq = get4c(fp);
1715     num_head = get4c(fp);
1716     seq_last = get4c(fp);
1717     seq_cur = get4c(fp);
1718     seq_time = get8ctime(fp);
1719 
1720     /* Optional header fields. */
1721     for (;;)
1722     {
1723 	int len = getc(fp);
1724 	int what;
1725 
1726 	if (len == 0 || len == EOF)
1727 	    break;
1728 	what = getc(fp);
1729 	switch (what)
1730 	{
1731 	    case UF_LAST_SAVE_NR:
1732 		last_save_nr = get4c(fp);
1733 		break;
1734 	    default:
1735 		/* field not supported, skip */
1736 		while (--len >= 0)
1737 		    (void)getc(fp);
1738 	}
1739     }
1740 
1741     /* uhp_table will store the freshly created undo headers we allocate
1742      * until we insert them into curbuf. The table remains sorted by the
1743      * sequence numbers of the headers.
1744      * When there are no headers uhp_table is NULL. */
1745     if (num_head > 0)
1746     {
1747 	uhp_table = (u_header_T **)U_ALLOC_LINE(
1748 					     num_head * sizeof(u_header_T *));
1749 	if (uhp_table == NULL)
1750 	    goto error;
1751     }
1752 
1753     while ((c = get2c(fp)) == UF_HEADER_MAGIC)
1754     {
1755 	if (num_read_uhps >= num_head)
1756 	{
1757 	    corruption_error("num_head too small", file_name);
1758 	    goto error;
1759 	}
1760 
1761 	uhp = unserialize_uhp(fp, file_name);
1762 	if (uhp == NULL)
1763 	    goto error;
1764 	uhp_table[num_read_uhps++] = uhp;
1765     }
1766 
1767     if (num_read_uhps != num_head)
1768     {
1769 	corruption_error("num_head", file_name);
1770 	goto error;
1771     }
1772     if (c != UF_HEADER_END_MAGIC)
1773     {
1774 	corruption_error("end marker", file_name);
1775 	goto error;
1776     }
1777 
1778 #ifdef U_DEBUG
1779     uhp_table_used = (int *)alloc_clear(
1780 				     (unsigned)(sizeof(int) * num_head + 1));
1781 # define SET_FLAG(j) ++uhp_table_used[j]
1782 #else
1783 # define SET_FLAG(j)
1784 #endif
1785 
1786     /* We have put all of the headers into a table. Now we iterate through the
1787      * table and swizzle each sequence number we have stored in uh_*_seq into
1788      * a pointer corresponding to the header with that sequence number. */
1789     for (i = 0; i < num_head; i++)
1790     {
1791 	uhp = uhp_table[i];
1792 	if (uhp == NULL)
1793 	    continue;
1794 	for (j = 0; j < num_head; j++)
1795 	    if (uhp_table[j] != NULL && i != j
1796 			      && uhp_table[i]->uh_seq == uhp_table[j]->uh_seq)
1797 	    {
1798 		corruption_error("duplicate uh_seq", file_name);
1799 		goto error;
1800 	    }
1801 	for (j = 0; j < num_head; j++)
1802 	    if (uhp_table[j] != NULL
1803 				  && uhp_table[j]->uh_seq == uhp->uh_next.seq)
1804 	    {
1805 		uhp->uh_next.ptr = uhp_table[j];
1806 		SET_FLAG(j);
1807 		break;
1808 	    }
1809 	for (j = 0; j < num_head; j++)
1810 	    if (uhp_table[j] != NULL
1811 				  && uhp_table[j]->uh_seq == uhp->uh_prev.seq)
1812 	    {
1813 		uhp->uh_prev.ptr = uhp_table[j];
1814 		SET_FLAG(j);
1815 		break;
1816 	    }
1817 	for (j = 0; j < num_head; j++)
1818 	    if (uhp_table[j] != NULL
1819 			      && uhp_table[j]->uh_seq == uhp->uh_alt_next.seq)
1820 	    {
1821 		uhp->uh_alt_next.ptr = uhp_table[j];
1822 		SET_FLAG(j);
1823 		break;
1824 	    }
1825 	for (j = 0; j < num_head; j++)
1826 	    if (uhp_table[j] != NULL
1827 			      && uhp_table[j]->uh_seq == uhp->uh_alt_prev.seq)
1828 	    {
1829 		uhp->uh_alt_prev.ptr = uhp_table[j];
1830 		SET_FLAG(j);
1831 		break;
1832 	    }
1833 	if (old_header_seq > 0 && old_idx < 0 && uhp->uh_seq == old_header_seq)
1834 	{
1835 	    old_idx = i;
1836 	    SET_FLAG(i);
1837 	}
1838 	if (new_header_seq > 0 && new_idx < 0 && uhp->uh_seq == new_header_seq)
1839 	{
1840 	    new_idx = i;
1841 	    SET_FLAG(i);
1842 	}
1843 	if (cur_header_seq > 0 && cur_idx < 0 && uhp->uh_seq == cur_header_seq)
1844 	{
1845 	    cur_idx = i;
1846 	    SET_FLAG(i);
1847 	}
1848     }
1849 
1850     /* Now that we have read the undo info successfully, free the current undo
1851      * info and use the info from the file. */
1852     u_blockfree(curbuf);
1853     curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx];
1854     curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx];
1855     curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx];
1856     curbuf->b_u_line_ptr = line_ptr;
1857     curbuf->b_u_line_lnum = line_lnum;
1858     curbuf->b_u_line_colnr = line_colnr;
1859     curbuf->b_u_numhead = num_head;
1860     curbuf->b_u_seq_last = seq_last;
1861     curbuf->b_u_seq_cur = seq_cur;
1862     curbuf->b_u_time_cur = seq_time;
1863     curbuf->b_u_save_nr_last = 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) < 32)
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  time            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 	(void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
2883     }
2884     else
2885 #endif
2886 	vim_snprintf((char *)buf, buflen, _("%ld seconds ago"),
2887 						     (long)(time(NULL) - tt));
2888 }
2889 
2890 /*
2891  * ":undojoin": continue adding to the last entry list
2892  */
2893     void
2894 ex_undojoin(eap)
2895     exarg_T *eap UNUSED;
2896 {
2897     if (curbuf->b_u_newhead == NULL)
2898 	return;		    /* nothing changed before */
2899     if (curbuf->b_u_curhead != NULL)
2900     {
2901 	EMSG(_("E790: undojoin is not allowed after undo"));
2902 	return;
2903     }
2904     if (!curbuf->b_u_synced)
2905 	return;		    /* already unsynced */
2906     if (p_ul < 0)
2907 	return;		    /* no entries, nothing to do */
2908     else
2909     {
2910 	/* Go back to the last entry */
2911 	curbuf->b_u_curhead = curbuf->b_u_newhead;
2912 	curbuf->b_u_synced = FALSE;  /* no entries, nothing to do */
2913     }
2914 }
2915 
2916 /*
2917  * Called after writing or reloading the file and setting b_changed to FALSE.
2918  * Now an undo means that the buffer is modified.
2919  */
2920     void
2921 u_unchanged(buf)
2922     buf_T	*buf;
2923 {
2924     u_unch_branch(buf->b_u_oldhead);
2925     buf->b_did_warn = FALSE;
2926 }
2927 
2928 /*
2929  * After reloading a buffer which was saved for 'undoreload': Find the first
2930  * line that was changed and set the cursor there.
2931  */
2932     void
2933 u_find_first_changed()
2934 {
2935     u_header_T	*uhp = curbuf->b_u_newhead;
2936     u_entry_T   *uep;
2937     linenr_T	lnum;
2938 
2939     if (curbuf->b_u_curhead != NULL || uhp == NULL)
2940 	return;  /* undid something in an autocmd? */
2941 
2942     /* Check that the last undo block was for the whole file. */
2943     uep = uhp->uh_entry;
2944     if (uep->ue_top != 0 || uep->ue_bot != 0)
2945 	return;
2946 
2947     for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
2948 					      && lnum <= uep->ue_size; ++lnum)
2949 	if (STRCMP(ml_get_buf(curbuf, lnum, FALSE),
2950 						uep->ue_array[lnum - 1]) != 0)
2951 	{
2952 	    clearpos(&(uhp->uh_cursor));
2953 	    uhp->uh_cursor.lnum = lnum;
2954 	    return;
2955 	}
2956     if (curbuf->b_ml.ml_line_count != uep->ue_size)
2957     {
2958 	/* lines added or deleted at the end, put the cursor there */
2959 	clearpos(&(uhp->uh_cursor));
2960 	uhp->uh_cursor.lnum = lnum;
2961     }
2962 }
2963 
2964 /*
2965  * Increase the write count, store it in the last undo header, what would be
2966  * used for "u".
2967  */
2968     void
2969 u_update_save_nr(buf)
2970     buf_T *buf;
2971 {
2972     u_header_T	*uhp;
2973 
2974     ++buf->b_u_save_nr_last;
2975     buf->b_u_save_nr_cur = buf->b_u_save_nr_last;
2976     uhp = buf->b_u_curhead;
2977     if (uhp != NULL)
2978 	uhp = uhp->uh_next.ptr;
2979     else
2980 	uhp = buf->b_u_newhead;
2981     if (uhp != NULL)
2982 	uhp->uh_save_nr = buf->b_u_save_nr_last;
2983 }
2984 
2985     static void
2986 u_unch_branch(uhp)
2987     u_header_T	*uhp;
2988 {
2989     u_header_T	*uh;
2990 
2991     for (uh = uhp; uh != NULL; uh = uh->uh_prev.ptr)
2992     {
2993 	uh->uh_flags |= UH_CHANGED;
2994 	if (uh->uh_alt_next.ptr != NULL)
2995 	    u_unch_branch(uh->uh_alt_next.ptr);	    /* recursive */
2996     }
2997 }
2998 
2999 /*
3000  * Get pointer to last added entry.
3001  * If it's not valid, give an error message and return NULL.
3002  */
3003     static u_entry_T *
3004 u_get_headentry()
3005 {
3006     if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL)
3007     {
3008 	EMSG(_("E439: undo list corrupt"));
3009 	return NULL;
3010     }
3011     return curbuf->b_u_newhead->uh_entry;
3012 }
3013 
3014 /*
3015  * u_getbot(): compute the line number of the previous u_save
3016  *		It is called only when b_u_synced is FALSE.
3017  */
3018     static void
3019 u_getbot()
3020 {
3021     u_entry_T	*uep;
3022     linenr_T	extra;
3023 
3024     uep = u_get_headentry();	/* check for corrupt undo list */
3025     if (uep == NULL)
3026 	return;
3027 
3028     uep = curbuf->b_u_newhead->uh_getbot_entry;
3029     if (uep != NULL)
3030     {
3031 	/*
3032 	 * the new ue_bot is computed from the number of lines that has been
3033 	 * inserted (0 - deleted) since calling u_save. This is equal to the
3034 	 * old line count subtracted from the current line count.
3035 	 */
3036 	extra = curbuf->b_ml.ml_line_count - uep->ue_lcount;
3037 	uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra;
3038 	if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count)
3039 	{
3040 	    EMSG(_("E440: undo line missing"));
3041 	    uep->ue_bot = uep->ue_top + 1;  /* assume all lines deleted, will
3042 					     * get all the old lines back
3043 					     * without deleting the current
3044 					     * ones */
3045 	}
3046 
3047 	curbuf->b_u_newhead->uh_getbot_entry = NULL;
3048     }
3049 
3050     curbuf->b_u_synced = TRUE;
3051 }
3052 
3053 /*
3054  * Free one header "uhp" and its entry list and adjust the pointers.
3055  */
3056     static void
3057 u_freeheader(buf, uhp, uhpp)
3058     buf_T	    *buf;
3059     u_header_T	    *uhp;
3060     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
3061 {
3062     u_header_T	    *uhap;
3063 
3064     /* When there is an alternate redo list free that branch completely,
3065      * because we can never go there. */
3066     if (uhp->uh_alt_next.ptr != NULL)
3067 	u_freebranch(buf, uhp->uh_alt_next.ptr, uhpp);
3068 
3069     if (uhp->uh_alt_prev.ptr != NULL)
3070 	uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL;
3071 
3072     /* Update the links in the list to remove the header. */
3073     if (uhp->uh_next.ptr == NULL)
3074 	buf->b_u_oldhead = uhp->uh_prev.ptr;
3075     else
3076 	uhp->uh_next.ptr->uh_prev.ptr = uhp->uh_prev.ptr;
3077 
3078     if (uhp->uh_prev.ptr == NULL)
3079 	buf->b_u_newhead = uhp->uh_next.ptr;
3080     else
3081 	for (uhap = uhp->uh_prev.ptr; uhap != NULL;
3082 						 uhap = uhap->uh_alt_next.ptr)
3083 	    uhap->uh_next.ptr = uhp->uh_next.ptr;
3084 
3085     u_freeentries(buf, uhp, uhpp);
3086 }
3087 
3088 /*
3089  * Free an alternate branch and any following alternate branches.
3090  */
3091     static void
3092 u_freebranch(buf, uhp, uhpp)
3093     buf_T	    *buf;
3094     u_header_T	    *uhp;
3095     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
3096 {
3097     u_header_T	    *tofree, *next;
3098 
3099     /* If this is the top branch we may need to use u_freeheader() to update
3100      * all the pointers. */
3101     if (uhp == buf->b_u_oldhead)
3102     {
3103 	u_freeheader(buf, uhp, uhpp);
3104 	return;
3105     }
3106 
3107     if (uhp->uh_alt_prev.ptr != NULL)
3108 	uhp->uh_alt_prev.ptr->uh_alt_next.ptr = NULL;
3109 
3110     next = uhp;
3111     while (next != NULL)
3112     {
3113 	tofree = next;
3114 	if (tofree->uh_alt_next.ptr != NULL)
3115 	    u_freebranch(buf, tofree->uh_alt_next.ptr, uhpp);   /* recursive */
3116 	next = tofree->uh_prev.ptr;
3117 	u_freeentries(buf, tofree, uhpp);
3118     }
3119 }
3120 
3121 /*
3122  * Free all the undo entries for one header and the header itself.
3123  * This means that "uhp" is invalid when returning.
3124  */
3125     static void
3126 u_freeentries(buf, uhp, uhpp)
3127     buf_T	    *buf;
3128     u_header_T	    *uhp;
3129     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
3130 {
3131     u_entry_T	    *uep, *nuep;
3132 
3133     /* Check for pointers to the header that become invalid now. */
3134     if (buf->b_u_curhead == uhp)
3135 	buf->b_u_curhead = NULL;
3136     if (buf->b_u_newhead == uhp)
3137 	buf->b_u_newhead = NULL;  /* freeing the newest entry */
3138     if (uhpp != NULL && uhp == *uhpp)
3139 	*uhpp = NULL;
3140 
3141     for (uep = uhp->uh_entry; uep != NULL; uep = nuep)
3142     {
3143 	nuep = uep->ue_next;
3144 	u_freeentry(uep, uep->ue_size);
3145     }
3146 
3147 #ifdef U_DEBUG
3148     uhp->uh_magic = 0;
3149 #endif
3150     vim_free((char_u *)uhp);
3151     --buf->b_u_numhead;
3152 }
3153 
3154 /*
3155  * free entry 'uep' and 'n' lines in uep->ue_array[]
3156  */
3157     static void
3158 u_freeentry(uep, n)
3159     u_entry_T	*uep;
3160     long	    n;
3161 {
3162     while (n > 0)
3163 	vim_free(uep->ue_array[--n]);
3164     vim_free((char_u *)uep->ue_array);
3165 #ifdef U_DEBUG
3166     uep->ue_magic = 0;
3167 #endif
3168     vim_free((char_u *)uep);
3169 }
3170 
3171 /*
3172  * invalidate the undo buffer; called when storage has already been released
3173  */
3174     void
3175 u_clearall(buf)
3176     buf_T	*buf;
3177 {
3178     buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
3179     buf->b_u_synced = TRUE;
3180     buf->b_u_numhead = 0;
3181     buf->b_u_line_ptr = NULL;
3182     buf->b_u_line_lnum = 0;
3183 }
3184 
3185 /*
3186  * save the line "lnum" for the "U" command
3187  */
3188     void
3189 u_saveline(lnum)
3190     linenr_T lnum;
3191 {
3192     if (lnum == curbuf->b_u_line_lnum)	    /* line is already saved */
3193 	return;
3194     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */
3195 	return;
3196     u_clearline();
3197     curbuf->b_u_line_lnum = lnum;
3198     if (curwin->w_cursor.lnum == lnum)
3199 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
3200     else
3201 	curbuf->b_u_line_colnr = 0;
3202     if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL)
3203 	do_outofmem_msg((long_u)0);
3204 }
3205 
3206 /*
3207  * clear the line saved for the "U" command
3208  * (this is used externally for crossing a line while in insert mode)
3209  */
3210     void
3211 u_clearline()
3212 {
3213     if (curbuf->b_u_line_ptr != NULL)
3214     {
3215 	vim_free(curbuf->b_u_line_ptr);
3216 	curbuf->b_u_line_ptr = NULL;
3217 	curbuf->b_u_line_lnum = 0;
3218     }
3219 }
3220 
3221 /*
3222  * Implementation of the "U" command.
3223  * Differentiation from vi: "U" can be undone with the next "U".
3224  * We also allow the cursor to be in another line.
3225  * Careful: may trigger autocommands that reload the buffer.
3226  */
3227     void
3228 u_undoline()
3229 {
3230     colnr_T t;
3231     char_u  *oldp;
3232 
3233     if (undo_off)
3234 	return;
3235 
3236     if (curbuf->b_u_line_ptr == NULL
3237 			|| curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
3238     {
3239 	beep_flush();
3240 	return;
3241     }
3242 
3243     /* first save the line for the 'u' command */
3244     if (u_savecommon(curbuf->b_u_line_lnum - 1,
3245 		       curbuf->b_u_line_lnum + 1, (linenr_T)0, FALSE) == FAIL)
3246 	return;
3247     oldp = u_save_line(curbuf->b_u_line_lnum);
3248     if (oldp == NULL)
3249     {
3250 	do_outofmem_msg((long_u)0);
3251 	return;
3252     }
3253     ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
3254     changed_bytes(curbuf->b_u_line_lnum, 0);
3255     vim_free(curbuf->b_u_line_ptr);
3256     curbuf->b_u_line_ptr = oldp;
3257 
3258     t = curbuf->b_u_line_colnr;
3259     if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum)
3260 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
3261     curwin->w_cursor.col = t;
3262     curwin->w_cursor.lnum = curbuf->b_u_line_lnum;
3263     check_cursor_col();
3264 }
3265 
3266 /*
3267  * Free all allocated memory blocks for the buffer 'buf'.
3268  */
3269     void
3270 u_blockfree(buf)
3271     buf_T	*buf;
3272 {
3273     while (buf->b_u_oldhead != NULL)
3274 	u_freeheader(buf, buf->b_u_oldhead, NULL);
3275     vim_free(buf->b_u_line_ptr);
3276 }
3277 
3278 /*
3279  * u_save_line(): allocate memory and copy line 'lnum' into it.
3280  * Returns NULL when out of memory.
3281  */
3282     static char_u *
3283 u_save_line(lnum)
3284     linenr_T	lnum;
3285 {
3286     return vim_strsave(ml_get(lnum));
3287 }
3288 
3289 /*
3290  * Check if the 'modified' flag is set, or 'ff' has changed (only need to
3291  * check the first character, because it can only be "dos", "unix" or "mac").
3292  * "nofile" and "scratch" type buffers are considered to always be unchanged.
3293  */
3294     int
3295 bufIsChanged(buf)
3296     buf_T	*buf;
3297 {
3298     return
3299 #ifdef FEAT_QUICKFIX
3300 	    !bt_dontwrite(buf) &&
3301 #endif
3302 	    (buf->b_changed || file_ff_differs(buf));
3303 }
3304 
3305     int
3306 curbufIsChanged()
3307 {
3308     return
3309 #ifdef FEAT_QUICKFIX
3310 	!bt_dontwrite(curbuf) &&
3311 #endif
3312 	(curbuf->b_changed || file_ff_differs(curbuf));
3313 }
3314 
3315 #if defined(FEAT_EVAL) || defined(PROTO)
3316 /*
3317  * For undotree(): Append the list of undo blocks at "first_uhp" to "list".
3318  * Recursive.
3319  */
3320     void
3321 u_eval_tree(first_uhp, list)
3322     u_header_T  *first_uhp;
3323     list_T	*list;
3324 {
3325     u_header_T  *uhp = first_uhp;
3326     dict_T	*dict;
3327 
3328     while (uhp != NULL)
3329     {
3330 	dict = dict_alloc();
3331 	if (dict == NULL)
3332 	    return;
3333 	dict_add_nr_str(dict, "seq", uhp->uh_seq, NULL);
3334 	dict_add_nr_str(dict, "time", (long)uhp->uh_time, NULL);
3335 	if (uhp == curbuf->b_u_newhead)
3336 	    dict_add_nr_str(dict, "newhead", 1, NULL);
3337 	if (uhp == curbuf->b_u_curhead)
3338 	    dict_add_nr_str(dict, "curhead", 1, NULL);
3339 	if (uhp->uh_save_nr > 0)
3340 	    dict_add_nr_str(dict, "save", uhp->uh_save_nr, NULL);
3341 
3342 	if (uhp->uh_alt_next.ptr != NULL)
3343 	{
3344 	    list_T	*alt_list = list_alloc();
3345 
3346 	    if (alt_list != NULL)
3347 	    {
3348 		/* Recursive call to add alternate undo tree. */
3349 		u_eval_tree(uhp->uh_alt_next.ptr, alt_list);
3350 		dict_add_list(dict, "alt", alt_list);
3351 	    }
3352 	}
3353 
3354 	list_append_dict(list, dict);
3355 	uhp = uhp->uh_prev.ptr;
3356     }
3357 }
3358 #endif
3359