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