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