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