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