xref: /vim-8.2.3635/src/undo.c (revision 4c3f536f)
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 with U_ALLOC_LINE(), it will be freed as soon as the
76  * buffer is unloaded.
77  */
78 
79 #include "vim.h"
80 
81 /* See below: use malloc()/free() for memory management. */
82 #define U_USE_MALLOC 1
83 
84 static void u_unch_branch __ARGS((u_header_T *uhp));
85 static u_entry_T *u_get_headentry __ARGS((void));
86 static void u_getbot __ARGS((void));
87 static int undo_allowed __ARGS((void));
88 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T));
89 static void u_doit __ARGS((int count));
90 static void u_undoredo __ARGS((int undo));
91 static void u_undo_end __ARGS((int did_undo, int absolute));
92 static void u_add_time __ARGS((char_u *buf, size_t buflen, time_t tt));
93 static void u_freeheader __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
94 static void u_freebranch __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
95 static void u_freeentries __ARGS((buf_T *buf, u_header_T *uhp, u_header_T **uhpp));
96 static void u_freeentry __ARGS((u_entry_T *, long));
97 
98 #ifdef U_USE_MALLOC
99 # define U_FREE_LINE(ptr) vim_free(ptr)
100 # define U_ALLOC_LINE(size) lalloc((long_u)((size) + 1), FALSE)
101 #else
102 static void u_free_line __ARGS((char_u *ptr, int keep));
103 static char_u *u_alloc_line __ARGS((unsigned size));
104 # define U_FREE_LINE(ptr) u_free_line((ptr), FALSE)
105 # define U_ALLOC_LINE(size) u_alloc_line(size)
106 #endif
107 static char_u *u_save_line __ARGS((linenr_T));
108 
109 static long	u_newcount, u_oldcount;
110 
111 /*
112  * When 'u' flag included in 'cpoptions', we behave like vi.  Need to remember
113  * the action that "u" should do.
114  */
115 static int	undo_undoes = FALSE;
116 
117 /*
118  * Save the current line for both the "u" and "U" command.
119  * Returns OK or FAIL.
120  */
121     int
122 u_save_cursor()
123 {
124     return (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
125 				      (linenr_T)(curwin->w_cursor.lnum + 1)));
126 }
127 
128 /*
129  * Save the lines between "top" and "bot" for both the "u" and "U" command.
130  * "top" may be 0 and bot may be curbuf->b_ml.ml_line_count + 1.
131  * Returns FAIL when lines could not be saved, OK otherwise.
132  */
133     int
134 u_save(top, bot)
135     linenr_T top, bot;
136 {
137     if (undo_off)
138 	return OK;
139 
140     if (top > curbuf->b_ml.ml_line_count ||
141 			    top >= bot || bot > curbuf->b_ml.ml_line_count + 1)
142 	return FALSE;	/* rely on caller to do error messages */
143 
144     if (top + 2 == bot)
145 	u_saveline((linenr_T)(top + 1));
146 
147     return (u_savecommon(top, bot, (linenr_T)0));
148 }
149 
150 /*
151  * save the line "lnum" (used by ":s" and "~" command)
152  * The line is replaced, so the new bottom line is lnum + 1.
153  */
154     int
155 u_savesub(lnum)
156     linenr_T	lnum;
157 {
158     if (undo_off)
159 	return OK;
160 
161     return (u_savecommon(lnum - 1, lnum + 1, lnum + 1));
162 }
163 
164 /*
165  * a new line is inserted before line "lnum" (used by :s command)
166  * The line is inserted, so the new bottom line is lnum + 1.
167  */
168     int
169 u_inssub(lnum)
170     linenr_T	lnum;
171 {
172     if (undo_off)
173 	return OK;
174 
175     return (u_savecommon(lnum - 1, lnum, lnum + 1));
176 }
177 
178 /*
179  * save the lines "lnum" - "lnum" + nlines (used by delete command)
180  * The lines are deleted, so the new bottom line is lnum, unless the buffer
181  * becomes empty.
182  */
183     int
184 u_savedel(lnum, nlines)
185     linenr_T	lnum;
186     long	nlines;
187 {
188     if (undo_off)
189 	return OK;
190 
191     return (u_savecommon(lnum - 1, lnum + nlines,
192 			nlines == curbuf->b_ml.ml_line_count ? 2 : lnum));
193 }
194 
195 /*
196  * Return TRUE when undo is allowed.  Otherwise give an error message and
197  * return FALSE.
198  */
199     static int
200 undo_allowed()
201 {
202     /* Don't allow changes when 'modifiable' is off.  */
203     if (!curbuf->b_p_ma)
204     {
205 	EMSG(_(e_modifiable));
206 	return FALSE;
207     }
208 
209 #ifdef HAVE_SANDBOX
210     /* In the sandbox it's not allowed to change the text. */
211     if (sandbox != 0)
212     {
213 	EMSG(_(e_sandbox));
214 	return FALSE;
215     }
216 #endif
217 
218     /* Don't allow changes in the buffer while editing the cmdline.  The
219      * caller of getcmdline() may get confused. */
220     if (textlock != 0)
221     {
222 	EMSG(_(e_secure));
223 	return FALSE;
224     }
225 
226     return TRUE;
227 }
228 
229     static int
230 u_savecommon(top, bot, newbot)
231     linenr_T	top, bot;
232     linenr_T	newbot;
233 {
234     linenr_T	lnum;
235     long	i;
236     u_header_T	*uhp;
237     u_header_T	*old_curhead;
238     u_entry_T	*uep;
239     u_entry_T	*prev_uep;
240     long	size;
241 
242     /* When making changes is not allowed return FAIL.  It's a crude way to
243      * make all change commands fail. */
244     if (!undo_allowed())
245 	return FAIL;
246 
247 #ifdef FEAT_NETBEANS_INTG
248     /*
249      * Netbeans defines areas that cannot be modified.  Bail out here when
250      * trying to change text in a guarded area.
251      */
252     if (usingNetbeans)
253     {
254 	if (netbeans_is_guarded(top, bot))
255 	{
256 	    EMSG(_(e_guarded));
257 	    return FAIL;
258 	}
259 	if (curbuf->b_p_ro)
260 	{
261 	    EMSG(_(e_nbreadonly));
262 	    return FAIL;
263 	}
264     }
265 #endif
266 
267 #ifdef FEAT_AUTOCMD
268     /*
269      * Saving text for undo means we are going to make a change.  Give a
270      * warning for a read-only file before making the change, so that the
271      * FileChangedRO event can replace the buffer with a read-write version
272      * (e.g., obtained from a source control system).
273      */
274     change_warning(0);
275 #endif
276 
277     size = bot - top - 1;
278 
279     /*
280      * if curbuf->b_u_synced == TRUE make a new header
281      */
282     if (curbuf->b_u_synced)
283     {
284 #ifdef FEAT_JUMPLIST
285 	/* Need to create new entry in b_changelist. */
286 	curbuf->b_new_change = TRUE;
287 #endif
288 
289 	if (p_ul >= 0)
290 	{
291 	    /*
292 	     * Make a new header entry.  Do this first so that we don't mess
293 	     * up the undo info when out of memory.
294 	     */
295 	    uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
296 	    if (uhp == NULL)
297 		goto nomem;
298 	}
299 	else
300 	    uhp = NULL;
301 
302 	/*
303 	 * If we undid more than we redid, move the entry lists before and
304 	 * including curbuf->b_u_curhead to an alternate branch.
305 	 */
306 	old_curhead = curbuf->b_u_curhead;
307 	if (old_curhead != NULL)
308 	{
309 	    curbuf->b_u_newhead = old_curhead->uh_next;
310 	    curbuf->b_u_curhead = NULL;
311 	}
312 
313 	/*
314 	 * free headers to keep the size right
315 	 */
316 	while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
317 	{
318 	    u_header_T	    *uhfree = curbuf->b_u_oldhead;
319 
320 	    /* If there is no branch only free one header. */
321 	    if (uhfree->uh_alt_next == NULL)
322 		u_freeheader(curbuf, uhfree, &old_curhead);
323 	    else
324 	    {
325 		/* Free the oldest alternate branch as a whole. */
326 		while (uhfree->uh_alt_next != NULL)
327 		    uhfree = uhfree->uh_alt_next;
328 		u_freebranch(curbuf, uhfree, &old_curhead);
329 	    }
330 	}
331 
332 	if (uhp == NULL)		/* no undo at all */
333 	{
334 	    if (old_curhead != NULL)
335 		u_freebranch(curbuf, old_curhead, NULL);
336 	    curbuf->b_u_synced = FALSE;
337 	    return OK;
338 	}
339 
340 	uhp->uh_prev = NULL;
341 	uhp->uh_next = curbuf->b_u_newhead;
342 	uhp->uh_alt_next = old_curhead;
343 	if (old_curhead != NULL)
344 	{
345 	    old_curhead->uh_alt_prev = uhp;
346 	    if (curbuf->b_u_oldhead == old_curhead)
347 		curbuf->b_u_oldhead = uhp;
348 	}
349 	uhp->uh_alt_prev = NULL;
350 	if (curbuf->b_u_newhead != NULL)
351 	    curbuf->b_u_newhead->uh_prev = uhp;
352 
353 	uhp->uh_seq = ++curbuf->b_u_seq_last;
354 	curbuf->b_u_seq_cur = uhp->uh_seq;
355 	uhp->uh_time = time(NULL);
356 	curbuf->b_u_seq_time = uhp->uh_time + 1;
357 
358 	uhp->uh_walk = 0;
359 	uhp->uh_entry = NULL;
360 	uhp->uh_getbot_entry = NULL;
361 	uhp->uh_cursor = curwin->w_cursor;	/* save cursor pos. for undo */
362 #ifdef FEAT_VIRTUALEDIT
363 	if (virtual_active() && curwin->w_cursor.coladd > 0)
364 	    uhp->uh_cursor_vcol = getviscol();
365 	else
366 	    uhp->uh_cursor_vcol = -1;
367 #endif
368 
369 	/* save changed and buffer empty flag for undo */
370 	uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
371 		       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
372 
373 	/* save named marks and Visual marks for undo */
374 	mch_memmove(uhp->uh_namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
375 #ifdef FEAT_VISUAL
376 	uhp->uh_visual = curbuf->b_visual;
377 #endif
378 
379 	curbuf->b_u_newhead = uhp;
380 	if (curbuf->b_u_oldhead == NULL)
381 	    curbuf->b_u_oldhead = uhp;
382 	++curbuf->b_u_numhead;
383     }
384     else
385     {
386 	if (p_ul < 0)		/* no undo at all */
387 	    return OK;
388 
389 	/*
390 	 * When saving a single line, and it has been saved just before, it
391 	 * doesn't make sense saving it again.  Saves a lot of memory when
392 	 * making lots of changes inside the same line.
393 	 * This is only possible if the previous change didn't increase or
394 	 * decrease the number of lines.
395 	 * Check the ten last changes.  More doesn't make sense and takes too
396 	 * long.
397 	 */
398 	if (size == 1)
399 	{
400 	    uep = u_get_headentry();
401 	    prev_uep = NULL;
402 	    for (i = 0; i < 10; ++i)
403 	    {
404 		if (uep == NULL)
405 		    break;
406 
407 		/* If lines have been inserted/deleted we give up.
408 		 * Also when the line was included in a multi-line save. */
409 		if ((curbuf->b_u_newhead->uh_getbot_entry != uep
410 			    ? (uep->ue_top + uep->ue_size + 1
411 				!= (uep->ue_bot == 0
412 				    ? curbuf->b_ml.ml_line_count + 1
413 				    : uep->ue_bot))
414 			    : uep->ue_lcount != curbuf->b_ml.ml_line_count)
415 			|| (uep->ue_size > 1
416 			    && top >= uep->ue_top
417 			    && top + 2 <= uep->ue_top + uep->ue_size + 1))
418 		    break;
419 
420 		/* If it's the same line we can skip saving it again. */
421 		if (uep->ue_size == 1 && uep->ue_top == top)
422 		{
423 		    if (i > 0)
424 		    {
425 			/* It's not the last entry: get ue_bot for the last
426 			 * entry now.  Following deleted/inserted lines go to
427 			 * the re-used entry. */
428 			u_getbot();
429 			curbuf->b_u_synced = FALSE;
430 
431 			/* Move the found entry to become the last entry.  The
432 			 * order of undo/redo doesn't matter for the entries
433 			 * we move it over, since they don't change the line
434 			 * count and don't include this line.  It does matter
435 			 * for the found entry if the line count is changed by
436 			 * the executed command. */
437 			prev_uep->ue_next = uep->ue_next;
438 			uep->ue_next = curbuf->b_u_newhead->uh_entry;
439 			curbuf->b_u_newhead->uh_entry = uep;
440 		    }
441 
442 		    /* The executed command may change the line count. */
443 		    if (newbot != 0)
444 			uep->ue_bot = newbot;
445 		    else if (bot > curbuf->b_ml.ml_line_count)
446 			uep->ue_bot = 0;
447 		    else
448 		    {
449 			uep->ue_lcount = curbuf->b_ml.ml_line_count;
450 			curbuf->b_u_newhead->uh_getbot_entry = uep;
451 		    }
452 		    return OK;
453 		}
454 		prev_uep = uep;
455 		uep = uep->ue_next;
456 	    }
457 	}
458 
459 	/* find line number for ue_bot for previous u_save() */
460 	u_getbot();
461     }
462 
463 #if !defined(UNIX) && !defined(DJGPP) && !defined(WIN32) && !defined(__EMX__)
464 	/*
465 	 * With Amiga and MSDOS 16 bit we can't handle big undo's, because
466 	 * then u_alloc_line would have to allocate a block larger than 32K
467 	 */
468     if (size >= 8000)
469 	goto nomem;
470 #endif
471 
472     /*
473      * add lines in front of entry list
474      */
475     uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
476     if (uep == NULL)
477 	goto nomem;
478 
479     uep->ue_size = size;
480     uep->ue_top = top;
481     if (newbot != 0)
482 	uep->ue_bot = newbot;
483     /*
484      * Use 0 for ue_bot if bot is below last line.
485      * Otherwise we have to compute ue_bot later.
486      */
487     else if (bot > curbuf->b_ml.ml_line_count)
488 	uep->ue_bot = 0;
489     else
490     {
491 	uep->ue_lcount = curbuf->b_ml.ml_line_count;
492 	curbuf->b_u_newhead->uh_getbot_entry = uep;
493     }
494 
495     if (size > 0)
496     {
497 	if ((uep->ue_array = (char_u **)U_ALLOC_LINE(
498 				(unsigned)(sizeof(char_u *) * size))) == NULL)
499 	{
500 	    u_freeentry(uep, 0L);
501 	    goto nomem;
502 	}
503 	for (i = 0, lnum = top + 1; i < size; ++i)
504 	{
505 	    fast_breakcheck();
506 	    if (got_int)
507 	    {
508 		u_freeentry(uep, i);
509 		return FAIL;
510 	    }
511 	    if ((uep->ue_array[i] = u_save_line(lnum++)) == NULL)
512 	    {
513 		u_freeentry(uep, i);
514 		goto nomem;
515 	    }
516 	}
517     }
518     else
519 	uep->ue_array = NULL;
520     uep->ue_next = curbuf->b_u_newhead->uh_entry;
521     curbuf->b_u_newhead->uh_entry = uep;
522     curbuf->b_u_synced = FALSE;
523     undo_undoes = FALSE;
524 
525     return OK;
526 
527 nomem:
528     msg_silent = 0;	/* must display the prompt */
529     if (ask_yesno((char_u *)_("No undo possible; continue anyway"), TRUE)
530 								       == 'y')
531     {
532 	undo_off = TRUE;	    /* will be reset when character typed */
533 	return OK;
534     }
535     do_outofmem_msg((long_u)0);
536     return FAIL;
537 }
538 
539 /*
540  * If 'cpoptions' contains 'u': Undo the previous undo or redo (vi compatible).
541  * If 'cpoptions' does not contain 'u': Always undo.
542  */
543     void
544 u_undo(count)
545     int count;
546 {
547     /*
548      * If we get an undo command while executing a macro, we behave like the
549      * original vi. If this happens twice in one macro the result will not
550      * be compatible.
551      */
552     if (curbuf->b_u_synced == FALSE)
553     {
554 	u_sync(TRUE);
555 	count = 1;
556     }
557 
558     if (vim_strchr(p_cpo, CPO_UNDO) == NULL)
559 	undo_undoes = TRUE;
560     else
561 	undo_undoes = !undo_undoes;
562     u_doit(count);
563 }
564 
565 /*
566  * If 'cpoptions' contains 'u': Repeat the previous undo or redo.
567  * If 'cpoptions' does not contain 'u': Always redo.
568  */
569     void
570 u_redo(count)
571     int count;
572 {
573     if (vim_strchr(p_cpo, CPO_UNDO) == NULL)
574 	undo_undoes = FALSE;
575     u_doit(count);
576 }
577 
578 /*
579  * Undo or redo, depending on 'undo_undoes', 'count' times.
580  */
581     static void
582 u_doit(startcount)
583     int startcount;
584 {
585     int count = startcount;
586 
587     if (!undo_allowed())
588 	return;
589 
590     u_newcount = 0;
591     u_oldcount = 0;
592     if (curbuf->b_ml.ml_flags & ML_EMPTY)
593 	u_oldcount = -1;
594     while (count--)
595     {
596 	if (undo_undoes)
597 	{
598 	    if (curbuf->b_u_curhead == NULL)		/* first undo */
599 		curbuf->b_u_curhead = curbuf->b_u_newhead;
600 	    else if (p_ul > 0)				/* multi level undo */
601 		/* get next undo */
602 		curbuf->b_u_curhead = curbuf->b_u_curhead->uh_next;
603 	    /* nothing to undo */
604 	    if (curbuf->b_u_numhead == 0 || curbuf->b_u_curhead == NULL)
605 	    {
606 		/* stick curbuf->b_u_curhead at end */
607 		curbuf->b_u_curhead = curbuf->b_u_oldhead;
608 		beep_flush();
609 		if (count == startcount - 1)
610 		{
611 		    MSG(_("Already at oldest change"));
612 		    return;
613 		}
614 		break;
615 	    }
616 
617 	    u_undoredo(TRUE);
618 	}
619 	else
620 	{
621 	    if (curbuf->b_u_curhead == NULL || p_ul <= 0)
622 	    {
623 		beep_flush();	/* nothing to redo */
624 		if (count == startcount - 1)
625 		{
626 		    MSG(_("Already at newest change"));
627 		    return;
628 		}
629 		break;
630 	    }
631 
632 	    u_undoredo(FALSE);
633 
634 	    /* Advance for next redo.  Set "newhead" when at the end of the
635 	     * redoable changes. */
636 	    if (curbuf->b_u_curhead->uh_prev == NULL)
637 		curbuf->b_u_newhead = curbuf->b_u_curhead;
638 	    curbuf->b_u_curhead = curbuf->b_u_curhead->uh_prev;
639 	}
640     }
641     u_undo_end(undo_undoes, FALSE);
642 }
643 
644 static int lastmark = 0;
645 
646 /*
647  * Undo or redo over the timeline.
648  * When "step" is negative go back in time, otherwise goes forward in time.
649  * When "sec" is FALSE make "step" steps, when "sec" is TRUE use "step" as
650  * seconds.
651  * When "absolute" is TRUE use "step" as the sequence number to jump to.
652  * "sec" must be FALSE then.
653  */
654     void
655 undo_time(step, sec, absolute)
656     long	step;
657     int		sec;
658     int		absolute;
659 {
660     long	    target;
661     long	    closest;
662     long	    closest_start;
663     long	    closest_seq = 0;
664     long	    val;
665     u_header_T	    *uhp;
666     u_header_T	    *last;
667     int		    mark;
668     int		    nomark;
669     int		    round;
670     int		    dosec = sec;
671     int		    above = FALSE;
672     int		    did_undo = TRUE;
673 
674     /* First make sure the current undoable change is synced. */
675     if (curbuf->b_u_synced == FALSE)
676 	u_sync(TRUE);
677 
678     u_newcount = 0;
679     u_oldcount = 0;
680     if (curbuf->b_ml.ml_flags & ML_EMPTY)
681 	u_oldcount = -1;
682 
683     /* "target" is the node below which we want to be.
684      * Init "closest" to a value we can't reach. */
685     if (absolute)
686     {
687 	target = step;
688 	closest = -1;
689     }
690     else
691     {
692 	/* When doing computations with time_t subtract starttime, because
693 	 * time_t converted to a long may result in a wrong number. */
694 	if (sec)
695 	    target = (long)(curbuf->b_u_seq_time - starttime) + step;
696 	else
697 	    target = curbuf->b_u_seq_cur + step;
698 	if (step < 0)
699 	{
700 	    if (target < 0)
701 		target = 0;
702 	    closest = -1;
703 	}
704 	else
705 	{
706 	    if (sec)
707 		closest = (long)(time(NULL) - starttime + 1);
708 	    else
709 		closest = curbuf->b_u_seq_last + 2;
710 	    if (target >= closest)
711 		target = closest - 1;
712 	}
713     }
714     closest_start = closest;
715     closest_seq = curbuf->b_u_seq_cur;
716 
717     /*
718      * May do this twice:
719      * 1. Search for "target", update "closest" to the best match found.
720      * 2. If "target" not found search for "closest".
721      *
722      * When using the closest time we use the sequence number in the second
723      * round, because there may be several entries with the same time.
724      */
725     for (round = 1; round <= 2; ++round)
726     {
727 	/* Find the path from the current state to where we want to go.  The
728 	 * desired state can be anywhere in the undo tree, need to go all over
729 	 * it.  We put "nomark" in uh_walk where we have been without success,
730 	 * "mark" where it could possibly be. */
731 	mark = ++lastmark;
732 	nomark = ++lastmark;
733 
734 	if (curbuf->b_u_curhead == NULL)	/* at leaf of the tree */
735 	    uhp = curbuf->b_u_newhead;
736 	else
737 	    uhp = curbuf->b_u_curhead;
738 
739 	while (uhp != NULL)
740 	{
741 	    uhp->uh_walk = mark;
742 	    val = (long)(dosec ? (uhp->uh_time - starttime) : uhp->uh_seq);
743 
744 	    if (round == 1)
745 	    {
746 		/* Remember the header that is closest to the target.
747 		 * It must be at least in the right direction (checked with
748 		 * "b_u_seq_cur").  When the timestamp is equal find the
749 		 * highest/lowest sequence number. */
750 		if ((step < 0 ? uhp->uh_seq <= curbuf->b_u_seq_cur
751 			      : uhp->uh_seq > curbuf->b_u_seq_cur)
752 			&& ((dosec && val == closest)
753 			    ? (step < 0
754 				? uhp->uh_seq < closest_seq
755 				: uhp->uh_seq > closest_seq)
756 			    : closest == closest_start
757 				|| (val > target
758 				    ? (closest > target
759 					? val - target <= closest - target
760 					: val - target <= target - closest)
761 				    : (closest > target
762 					? target - val <= closest - target
763 					: target - val <= target - closest))))
764 		{
765 		    closest = val;
766 		    closest_seq = uhp->uh_seq;
767 		}
768 	    }
769 
770 	    /* Quit searching when we found a match.  But when searching for a
771 	     * time we need to continue looking for the best uh_seq. */
772 	    if (target == val && !dosec)
773 		break;
774 
775 	    /* go down in the tree if we haven't been there */
776 	    if (uhp->uh_prev != NULL && uhp->uh_prev->uh_walk != nomark
777 					     && uhp->uh_prev->uh_walk != mark)
778 		uhp = uhp->uh_prev;
779 
780 	    /* go to alternate branch if we haven't been there */
781 	    else if (uhp->uh_alt_next != NULL
782 		    && uhp->uh_alt_next->uh_walk != nomark
783 		    && uhp->uh_alt_next->uh_walk != mark)
784 		uhp = uhp->uh_alt_next;
785 
786 	    /* go up in the tree if we haven't been there and we are at the
787 	     * start of alternate branches */
788 	    else if (uhp->uh_next != NULL && uhp->uh_alt_prev == NULL
789 		    && uhp->uh_next->uh_walk != nomark
790 		    && uhp->uh_next->uh_walk != mark)
791 	    {
792 		/* If still at the start we don't go through this change. */
793 		if (uhp == curbuf->b_u_curhead)
794 		    uhp->uh_walk = nomark;
795 		uhp = uhp->uh_next;
796 	    }
797 
798 	    else
799 	    {
800 		/* need to backtrack; mark this node as useless */
801 		uhp->uh_walk = nomark;
802 		if (uhp->uh_alt_prev != NULL)
803 		    uhp = uhp->uh_alt_prev;
804 		else
805 		    uhp = uhp->uh_next;
806 	    }
807 	}
808 
809 	if (uhp != NULL)    /* found it */
810 	    break;
811 
812 	if (absolute)
813 	{
814 	    EMSGN(_("Undo number %ld not found"), step);
815 	    return;
816 	}
817 
818 	if (closest == closest_start)
819 	{
820 	    if (step < 0)
821 		MSG(_("Already at oldest change"));
822 	    else
823 		MSG(_("Already at newest change"));
824 	    return;
825 	}
826 
827 	target = closest_seq;
828 	dosec = FALSE;
829 	if (step < 0)
830 	    above = TRUE;	/* stop above the header */
831     }
832 
833     /* If we found it: Follow the path to go to where we want to be. */
834     if (uhp != NULL)
835     {
836 	/*
837 	 * First go up the tree as much as needed.
838 	 */
839 	for (;;)
840 	{
841 	    uhp = curbuf->b_u_curhead;
842 	    if (uhp == NULL)
843 		uhp = curbuf->b_u_newhead;
844 	    else
845 		uhp = uhp->uh_next;
846 	    if (uhp == NULL || uhp->uh_walk != mark
847 					 || (uhp->uh_seq == target && !above))
848 		break;
849 	    curbuf->b_u_curhead = uhp;
850 	    u_undoredo(TRUE);
851 	    uhp->uh_walk = nomark;	/* don't go back down here */
852 	}
853 
854 	/*
855 	 * And now go down the tree (redo), branching off where needed.
856 	 */
857 	uhp = curbuf->b_u_curhead;
858 	while (uhp != NULL)
859 	{
860 	    /* Find the last branch with a mark, that's the one. */
861 	    last = uhp;
862 	    while (last->uh_alt_next != NULL
863 					&& last->uh_alt_next->uh_walk == mark)
864 		last = last->uh_alt_next;
865 	    if (last != uhp)
866 	    {
867 		/* Make the used branch the first entry in the list of
868 		 * alternatives to make "u" and CTRL-R take this branch. */
869 		if (last->uh_alt_next != NULL)
870 		    last->uh_alt_next->uh_alt_prev = last->uh_alt_prev;
871 		last->uh_alt_prev->uh_alt_next = last->uh_alt_next;
872 		last->uh_alt_prev = NULL;
873 		last->uh_alt_next = uhp;
874 		uhp->uh_alt_prev = last;
875 
876 		uhp = last;
877 		if (uhp->uh_next != NULL)
878 		    uhp->uh_next->uh_prev = uhp;
879 	    }
880 	    curbuf->b_u_curhead = uhp;
881 
882 	    if (uhp->uh_walk != mark)
883 		break;	    /* must have reached the target */
884 
885 	    /* Stop when going backwards in time and didn't find the exact
886 	     * header we were looking for. */
887 	    if (uhp->uh_seq == target && above)
888 	    {
889 		curbuf->b_u_seq_cur = target - 1;
890 		break;
891 	    }
892 
893 	    u_undoredo(FALSE);
894 
895 	    /* Advance "curhead" to below the header we last used.  If it
896 	     * becomes NULL then we need to set "newhead" to this leaf. */
897 	    if (uhp->uh_prev == NULL)
898 		curbuf->b_u_newhead = uhp;
899 	    curbuf->b_u_curhead = uhp->uh_prev;
900 	    did_undo = FALSE;
901 
902 	    if (uhp->uh_seq == target)	/* found it! */
903 		break;
904 
905 	    uhp = uhp->uh_prev;
906 	    if (uhp == NULL || uhp->uh_walk != mark)
907 	    {
908 		/* Need to redo more but can't find it... */
909 		EMSG2(_(e_intern2), "undo_time()");
910 		break;
911 	    }
912 	}
913     }
914     u_undo_end(did_undo, absolute);
915 }
916 
917 /*
918  * u_undoredo: common code for undo and redo
919  *
920  * The lines in the file are replaced by the lines in the entry list at
921  * curbuf->b_u_curhead. The replaced lines in the file are saved in the entry
922  * list for the next undo/redo.
923  *
924  * When "undo" is TRUE we go up in the tree, when FALSE we go down.
925  */
926     static void
927 u_undoredo(undo)
928     int		undo;
929 {
930     char_u	**newarray = NULL;
931     linenr_T	oldsize;
932     linenr_T	newsize;
933     linenr_T	top, bot;
934     linenr_T	lnum;
935     linenr_T	newlnum = MAXLNUM;
936     long	i;
937     u_entry_T	*uep, *nuep;
938     u_entry_T	*newlist = NULL;
939     int		old_flags;
940     int		new_flags;
941     pos_T	namedm[NMARKS];
942 #ifdef FEAT_VISUAL
943     visualinfo_T visualinfo;
944 #endif
945     int		empty_buffer;		    /* buffer became empty */
946     u_header_T	*curhead = curbuf->b_u_curhead;
947 
948     old_flags = curhead->uh_flags;
949     new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
950 	       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
951     setpcmark();
952 
953     /*
954      * save marks before undo/redo
955      */
956     mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
957 #ifdef FEAT_VISUAL
958     visualinfo = curbuf->b_visual;
959 #endif
960     curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
961     curbuf->b_op_start.col = 0;
962     curbuf->b_op_end.lnum = 0;
963     curbuf->b_op_end.col = 0;
964 
965     for (uep = curhead->uh_entry; uep != NULL; uep = nuep)
966     {
967 	top = uep->ue_top;
968 	bot = uep->ue_bot;
969 	if (bot == 0)
970 	    bot = curbuf->b_ml.ml_line_count + 1;
971 	if (top > curbuf->b_ml.ml_line_count || top >= bot
972 				      || bot > curbuf->b_ml.ml_line_count + 1)
973 	{
974 	    EMSG(_("E438: u_undo: line numbers wrong"));
975 	    changed();		/* don't want UNCHANGED now */
976 	    return;
977 	}
978 
979 	oldsize = bot - top - 1;    /* number of lines before undo */
980 	newsize = uep->ue_size;	    /* number of lines after undo */
981 
982 	if (top < newlnum)
983 	{
984 	    /* If the saved cursor is somewhere in this undo block, move it to
985 	     * the remembered position.  Makes "gwap" put the cursor back
986 	     * where it was. */
987 	    lnum = curhead->uh_cursor.lnum;
988 	    if (lnum >= top && lnum <= top + newsize + 1)
989 	    {
990 		curwin->w_cursor = curhead->uh_cursor;
991 		newlnum = curwin->w_cursor.lnum - 1;
992 	    }
993 	    else
994 	    {
995 		/* Use the first line that actually changed.  Avoids that
996 		 * undoing auto-formatting puts the cursor in the previous
997 		 * line. */
998 		for (i = 0; i < newsize && i < oldsize; ++i)
999 		    if (STRCMP(uep->ue_array[i], ml_get(top + 1 + i)) != 0)
1000 			break;
1001 		if (i == newsize && newlnum == MAXLNUM && uep->ue_next == NULL)
1002 		{
1003 		    newlnum = top;
1004 		    curwin->w_cursor.lnum = newlnum + 1;
1005 		}
1006 		else if (i < newsize)
1007 		{
1008 		    newlnum = top + i;
1009 		    curwin->w_cursor.lnum = newlnum + 1;
1010 		}
1011 	    }
1012 	}
1013 
1014 	empty_buffer = FALSE;
1015 
1016 	/* delete the lines between top and bot and save them in newarray */
1017 	if (oldsize > 0)
1018 	{
1019 	    if ((newarray = (char_u **)U_ALLOC_LINE(
1020 			    (unsigned)(sizeof(char_u *) * oldsize))) == NULL)
1021 	    {
1022 		do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize));
1023 		/*
1024 		 * We have messed up the entry list, repair is impossible.
1025 		 * we have to free the rest of the list.
1026 		 */
1027 		while (uep != NULL)
1028 		{
1029 		    nuep = uep->ue_next;
1030 		    u_freeentry(uep, uep->ue_size);
1031 		    uep = nuep;
1032 		}
1033 		break;
1034 	    }
1035 	    /* delete backwards, it goes faster in most cases */
1036 	    for (lnum = bot - 1, i = oldsize; --i >= 0; --lnum)
1037 	    {
1038 		/* what can we do when we run out of memory? */
1039 		if ((newarray[i] = u_save_line(lnum)) == NULL)
1040 		    do_outofmem_msg((long_u)0);
1041 		/* remember we deleted the last line in the buffer, and a
1042 		 * dummy empty line will be inserted */
1043 		if (curbuf->b_ml.ml_line_count == 1)
1044 		    empty_buffer = TRUE;
1045 		ml_delete(lnum, FALSE);
1046 	    }
1047 	}
1048 	else
1049 	    newarray = NULL;
1050 
1051 	/* insert the lines in u_array between top and bot */
1052 	if (newsize)
1053 	{
1054 	    for (lnum = top, i = 0; i < newsize; ++i, ++lnum)
1055 	    {
1056 		/*
1057 		 * If the file is empty, there is an empty line 1 that we
1058 		 * should get rid of, by replacing it with the new line
1059 		 */
1060 		if (empty_buffer && lnum == 0)
1061 		    ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
1062 		else
1063 		    ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
1064 		U_FREE_LINE(uep->ue_array[i]);
1065 	    }
1066 	    U_FREE_LINE((char_u *)uep->ue_array);
1067 	}
1068 
1069 	/* adjust marks */
1070 	if (oldsize != newsize)
1071 	{
1072 	    mark_adjust(top + 1, top + oldsize, (long)MAXLNUM,
1073 					       (long)newsize - (long)oldsize);
1074 	    if (curbuf->b_op_start.lnum > top + oldsize)
1075 		curbuf->b_op_start.lnum += newsize - oldsize;
1076 	    if (curbuf->b_op_end.lnum > top + oldsize)
1077 		curbuf->b_op_end.lnum += newsize - oldsize;
1078 	}
1079 
1080 	changed_lines(top + 1, 0, bot, newsize - oldsize);
1081 
1082 	/* set '[ and '] mark */
1083 	if (top + 1 < curbuf->b_op_start.lnum)
1084 	    curbuf->b_op_start.lnum = top + 1;
1085 	if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum)
1086 	    curbuf->b_op_end.lnum = top + 1;
1087 	else if (top + newsize > curbuf->b_op_end.lnum)
1088 	    curbuf->b_op_end.lnum = top + newsize;
1089 
1090 	u_newcount += newsize;
1091 	u_oldcount += oldsize;
1092 	uep->ue_size = oldsize;
1093 	uep->ue_array = newarray;
1094 	uep->ue_bot = top + newsize + 1;
1095 
1096 	/*
1097 	 * insert this entry in front of the new entry list
1098 	 */
1099 	nuep = uep->ue_next;
1100 	uep->ue_next = newlist;
1101 	newlist = uep;
1102     }
1103 
1104     curhead->uh_entry = newlist;
1105     curhead->uh_flags = new_flags;
1106     if ((old_flags & UH_EMPTYBUF) && bufempty())
1107 	curbuf->b_ml.ml_flags |= ML_EMPTY;
1108     if (old_flags & UH_CHANGED)
1109 	changed();
1110     else
1111 #ifdef FEAT_NETBEANS_INTG
1112 	/* per netbeans undo rules, keep it as modified */
1113 	if (!isNetbeansModified(curbuf))
1114 #endif
1115 	unchanged(curbuf, FALSE);
1116 
1117     /*
1118      * restore marks from before undo/redo
1119      */
1120     for (i = 0; i < NMARKS; ++i)
1121 	if (curhead->uh_namedm[i].lnum != 0)
1122 	{
1123 	    curbuf->b_namedm[i] = curhead->uh_namedm[i];
1124 	    curhead->uh_namedm[i] = namedm[i];
1125 	}
1126 #ifdef FEAT_VISUAL
1127     if (curhead->uh_visual.vi_start.lnum != 0)
1128     {
1129 	curbuf->b_visual = curhead->uh_visual;
1130 	curhead->uh_visual = visualinfo;
1131     }
1132 #endif
1133 
1134     /*
1135      * If the cursor is only off by one line, put it at the same position as
1136      * before starting the change (for the "o" command).
1137      * Otherwise the cursor should go to the first undone line.
1138      */
1139     if (curhead->uh_cursor.lnum + 1 == curwin->w_cursor.lnum
1140 						 && curwin->w_cursor.lnum > 1)
1141 	--curwin->w_cursor.lnum;
1142     if (curhead->uh_cursor.lnum == curwin->w_cursor.lnum)
1143     {
1144 	curwin->w_cursor.col = curhead->uh_cursor.col;
1145 #ifdef FEAT_VIRTUALEDIT
1146 	if (virtual_active() && curhead->uh_cursor_vcol >= 0)
1147 	    coladvance((colnr_T)curhead->uh_cursor_vcol);
1148 	else
1149 	    curwin->w_cursor.coladd = 0;
1150 #endif
1151     }
1152     else if (curwin->w_cursor.lnum <= curbuf->b_ml.ml_line_count)
1153 	beginline(BL_SOL | BL_FIX);
1154     else
1155     {
1156 	/* We get here with the current cursor line being past the end (eg
1157 	 * after adding lines at the end of the file, and then undoing it).
1158 	 * check_cursor() will move the cursor to the last line.  Move it to
1159 	 * the first column here. */
1160 	curwin->w_cursor.col = 0;
1161 #ifdef FEAT_VIRTUALEDIT
1162 	curwin->w_cursor.coladd = 0;
1163 #endif
1164     }
1165 
1166     /* Make sure the cursor is on an existing line and column. */
1167     check_cursor();
1168 
1169     /* Remember where we are for "g-" and ":earlier 10s". */
1170     curbuf->b_u_seq_cur = curhead->uh_seq;
1171     if (undo)
1172 	/* We are below the previous undo.  However, to make ":earlier 1s"
1173 	 * work we compute this as being just above the just undone change. */
1174 	--curbuf->b_u_seq_cur;
1175 
1176     /* The timestamp can be the same for multiple changes, just use the one of
1177      * the undone/redone change. */
1178     curbuf->b_u_seq_time = curhead->uh_time;
1179 }
1180 
1181 /*
1182  * If we deleted or added lines, report the number of less/more lines.
1183  * Otherwise, report the number of changes (this may be incorrect
1184  * in some cases, but it's better than nothing).
1185  */
1186     static void
1187 u_undo_end(did_undo, absolute)
1188     int		did_undo;	/* just did an undo */
1189     int		absolute;	/* used ":undo N" */
1190 {
1191     char	*msg;
1192     u_header_T	*uhp;
1193     char_u	msgbuf[80];
1194 
1195 #ifdef FEAT_FOLDING
1196     if ((fdo_flags & FDO_UNDO) && KeyTyped)
1197 	foldOpenCursor();
1198 #endif
1199 
1200     if (global_busy	    /* no messages now, wait until global is finished */
1201 	    || !messaging())  /* 'lazyredraw' set, don't do messages now */
1202 	return;
1203 
1204     if (curbuf->b_ml.ml_flags & ML_EMPTY)
1205 	--u_newcount;
1206 
1207     u_oldcount -= u_newcount;
1208     if (u_oldcount == -1)
1209 	msg = N_("more line");
1210     else if (u_oldcount < 0)
1211 	msg = N_("more lines");
1212     else if (u_oldcount == 1)
1213 	msg = N_("line less");
1214     else if (u_oldcount > 1)
1215 	msg = N_("fewer lines");
1216     else
1217     {
1218 	u_oldcount = u_newcount;
1219 	if (u_newcount == 1)
1220 	    msg = N_("change");
1221 	else
1222 	    msg = N_("changes");
1223     }
1224 
1225     if (curbuf->b_u_curhead != NULL)
1226     {
1227 	/* For ":undo N" we prefer a "after #N" message. */
1228 	if (absolute && curbuf->b_u_curhead->uh_next != NULL)
1229 	{
1230 	    uhp = curbuf->b_u_curhead->uh_next;
1231 	    did_undo = FALSE;
1232 	}
1233 	else if (did_undo)
1234 	    uhp = curbuf->b_u_curhead;
1235 	else
1236 	    uhp = curbuf->b_u_curhead->uh_next;
1237     }
1238     else
1239 	uhp = curbuf->b_u_newhead;
1240 
1241     if (uhp == NULL)
1242 	*msgbuf = NUL;
1243     else
1244 	u_add_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
1245 
1246     smsg((char_u *)_("%ld %s; %s #%ld  %s"),
1247 	    u_oldcount < 0 ? -u_oldcount : u_oldcount,
1248 	    _(msg),
1249 	    did_undo ? _("before") : _("after"),
1250 	    uhp == NULL ? 0L : uhp->uh_seq,
1251 	    msgbuf);
1252 }
1253 
1254 /*
1255  * u_sync: stop adding to the current entry list
1256  */
1257     void
1258 u_sync(force)
1259     int	    force;	/* Also sync when no_u_sync is set. */
1260 {
1261     /* Skip it when already synced or syncing is disabled. */
1262     if (curbuf->b_u_synced || (!force && no_u_sync > 0))
1263 	return;
1264 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
1265     if (im_is_preediting())
1266 	return;		    /* XIM is busy, don't break an undo sequence */
1267 #endif
1268     if (p_ul < 0)
1269 	curbuf->b_u_synced = TRUE;  /* no entries, nothing to do */
1270     else
1271     {
1272 	u_getbot();		    /* compute ue_bot of previous u_save */
1273 	curbuf->b_u_curhead = NULL;
1274     }
1275 }
1276 
1277 /*
1278  * ":undolist": List the leafs of the undo tree
1279  */
1280 /*ARGSUSED*/
1281     void
1282 ex_undolist(eap)
1283     exarg_T *eap;
1284 {
1285     garray_T	ga;
1286     u_header_T	*uhp;
1287     int		mark;
1288     int		nomark;
1289     int		changes = 1;
1290     int		i;
1291 
1292     /*
1293      * 1: walk the tree to find all leafs, put the info in "ga".
1294      * 2: sort the lines
1295      * 3: display the list
1296      */
1297     mark = ++lastmark;
1298     nomark = ++lastmark;
1299     ga_init2(&ga, (int)sizeof(char *), 20);
1300 
1301     uhp = curbuf->b_u_oldhead;
1302     while (uhp != NULL)
1303     {
1304 	if (uhp->uh_prev == NULL && uhp->uh_walk != nomark
1305 						      && uhp->uh_walk != mark)
1306 	{
1307 	    if (ga_grow(&ga, 1) == FAIL)
1308 		break;
1309 	    vim_snprintf((char *)IObuff, IOSIZE, "%6ld %7ld  ",
1310 							uhp->uh_seq, changes);
1311 	    u_add_time(IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
1312 								uhp->uh_time);
1313 	    ((char_u **)(ga.ga_data))[ga.ga_len++] = vim_strsave(IObuff);
1314 	}
1315 
1316 	uhp->uh_walk = mark;
1317 
1318 	/* go down in the tree if we haven't been there */
1319 	if (uhp->uh_prev != NULL && uhp->uh_prev->uh_walk != nomark
1320 					 && uhp->uh_prev->uh_walk != mark)
1321 	{
1322 	    uhp = uhp->uh_prev;
1323 	    ++changes;
1324 	}
1325 
1326 	/* go to alternate branch if we haven't been there */
1327 	else if (uhp->uh_alt_next != NULL
1328 		&& uhp->uh_alt_next->uh_walk != nomark
1329 		&& uhp->uh_alt_next->uh_walk != mark)
1330 	    uhp = uhp->uh_alt_next;
1331 
1332 	/* go up in the tree if we haven't been there and we are at the
1333 	 * start of alternate branches */
1334 	else if (uhp->uh_next != NULL && uhp->uh_alt_prev == NULL
1335 		&& uhp->uh_next->uh_walk != nomark
1336 		&& uhp->uh_next->uh_walk != mark)
1337 	{
1338 	    uhp = uhp->uh_next;
1339 	    --changes;
1340 	}
1341 
1342 	else
1343 	{
1344 	    /* need to backtrack; mark this node as done */
1345 	    uhp->uh_walk = nomark;
1346 	    if (uhp->uh_alt_prev != NULL)
1347 		uhp = uhp->uh_alt_prev;
1348 	    else
1349 	    {
1350 		uhp = uhp->uh_next;
1351 		--changes;
1352 	    }
1353 	}
1354     }
1355 
1356     if (ga.ga_len == 0)
1357 	MSG(_("Nothing to undo"));
1358     else
1359     {
1360 	sort_strings((char_u **)ga.ga_data, ga.ga_len);
1361 
1362 	msg_start();
1363 	msg_puts_attr((char_u *)_("number changes  time"), hl_attr(HLF_T));
1364 	for (i = 0; i < ga.ga_len && !got_int; ++i)
1365 	{
1366 	    msg_putchar('\n');
1367 	    if (got_int)
1368 		break;
1369 	    msg_puts(((char_u **)ga.ga_data)[i]);
1370 	}
1371 	msg_end();
1372 
1373 	ga_clear_strings(&ga);
1374     }
1375 }
1376 
1377 /*
1378  * Put the timestamp of an undo header in "buf[buflen]" in a nice format.
1379  */
1380     static void
1381 u_add_time(buf, buflen, tt)
1382     char_u	*buf;
1383     size_t	buflen;
1384     time_t	tt;
1385 {
1386 #ifdef HAVE_STRFTIME
1387     struct tm	*curtime;
1388 
1389     if (time(NULL) - tt >= 100)
1390     {
1391 	curtime = localtime(&tt);
1392 	(void)strftime((char *)buf, buflen, "%H:%M:%S", curtime);
1393     }
1394     else
1395 #endif
1396 	vim_snprintf((char *)buf, buflen, "%ld seconds ago",
1397 						     (long)(time(NULL) - tt));
1398 }
1399 
1400 /*
1401  * ":undojoin": continue adding to the last entry list
1402  */
1403 /*ARGSUSED*/
1404     void
1405 ex_undojoin(eap)
1406     exarg_T *eap;
1407 {
1408     if (!curbuf->b_u_synced)
1409 	return;		    /* already unsynced */
1410     if (curbuf->b_u_newhead == NULL)
1411 	return;		    /* nothing changed before */
1412     if (p_ul < 0)
1413 	return;		    /* no entries, nothing to do */
1414     else
1415     {
1416 	/* Go back to the last entry */
1417 	curbuf->b_u_curhead = curbuf->b_u_newhead;
1418 	curbuf->b_u_synced = FALSE;  /* no entries, nothing to do */
1419     }
1420 }
1421 
1422 /*
1423  * Called after writing the file and setting b_changed to FALSE.
1424  * Now an undo means that the buffer is modified.
1425  */
1426     void
1427 u_unchanged(buf)
1428     buf_T	*buf;
1429 {
1430     u_unch_branch(buf->b_u_oldhead);
1431     buf->b_did_warn = FALSE;
1432 }
1433 
1434     static void
1435 u_unch_branch(uhp)
1436     u_header_T	*uhp;
1437 {
1438     u_header_T	*uh;
1439 
1440     for (uh = uhp; uh != NULL; uh = uh->uh_prev)
1441     {
1442 	uh->uh_flags |= UH_CHANGED;
1443 	if (uh->uh_alt_next != NULL)
1444 	    u_unch_branch(uh->uh_alt_next);	    /* recursive */
1445     }
1446 }
1447 
1448 /*
1449  * Get pointer to last added entry.
1450  * If it's not valid, give an error message and return NULL.
1451  */
1452     static u_entry_T *
1453 u_get_headentry()
1454 {
1455     if (curbuf->b_u_newhead == NULL || curbuf->b_u_newhead->uh_entry == NULL)
1456     {
1457 	EMSG(_("E439: undo list corrupt"));
1458 	return NULL;
1459     }
1460     return curbuf->b_u_newhead->uh_entry;
1461 }
1462 
1463 /*
1464  * u_getbot(): compute the line number of the previous u_save
1465  *		It is called only when b_u_synced is FALSE.
1466  */
1467     static void
1468 u_getbot()
1469 {
1470     u_entry_T	*uep;
1471     linenr_T	extra;
1472 
1473     uep = u_get_headentry();	/* check for corrupt undo list */
1474     if (uep == NULL)
1475 	return;
1476 
1477     uep = curbuf->b_u_newhead->uh_getbot_entry;
1478     if (uep != NULL)
1479     {
1480 	/*
1481 	 * the new ue_bot is computed from the number of lines that has been
1482 	 * inserted (0 - deleted) since calling u_save. This is equal to the
1483 	 * old line count subtracted from the current line count.
1484 	 */
1485 	extra = curbuf->b_ml.ml_line_count - uep->ue_lcount;
1486 	uep->ue_bot = uep->ue_top + uep->ue_size + 1 + extra;
1487 	if (uep->ue_bot < 1 || uep->ue_bot > curbuf->b_ml.ml_line_count)
1488 	{
1489 	    EMSG(_("E440: undo line missing"));
1490 	    uep->ue_bot = uep->ue_top + 1;  /* assume all lines deleted, will
1491 					     * get all the old lines back
1492 					     * without deleting the current
1493 					     * ones */
1494 	}
1495 
1496 	curbuf->b_u_newhead->uh_getbot_entry = NULL;
1497     }
1498 
1499     curbuf->b_u_synced = TRUE;
1500 }
1501 
1502 /*
1503  * Free one header and its entry list and adjust the pointers.
1504  */
1505     static void
1506 u_freeheader(buf, uhp, uhpp)
1507     buf_T	    *buf;
1508     u_header_T	    *uhp;
1509     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
1510 {
1511     /* When there is an alternate redo list free that branch completely,
1512      * because we can never go there. */
1513     if (uhp->uh_alt_next != NULL)
1514 	u_freebranch(buf, uhp->uh_alt_next, uhpp);
1515 
1516     if (uhp->uh_alt_prev != NULL)
1517 	uhp->uh_alt_prev->uh_alt_next = NULL;
1518 
1519     /* Update the links in the list to remove the header. */
1520     if (uhp->uh_next == NULL)
1521 	buf->b_u_oldhead = uhp->uh_prev;
1522     else
1523 	uhp->uh_next->uh_prev = uhp->uh_prev;
1524 
1525     if (uhp->uh_prev == NULL)
1526 	buf->b_u_newhead = uhp->uh_next;
1527     else
1528 	uhp->uh_prev->uh_next = uhp->uh_next;
1529 
1530     u_freeentries(buf, uhp, uhpp);
1531 }
1532 
1533 /*
1534  * Free an alternate branch and any following alternate branches.
1535  */
1536     static void
1537 u_freebranch(buf, uhp, uhpp)
1538     buf_T	    *buf;
1539     u_header_T	    *uhp;
1540     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
1541 {
1542     u_header_T	    *tofree, *next;
1543 
1544     if (uhp->uh_alt_prev != NULL)
1545 	uhp->uh_alt_prev->uh_alt_next = NULL;
1546 
1547     next = uhp;
1548     while (next != NULL)
1549     {
1550 	tofree = next;
1551 	if (tofree->uh_alt_next != NULL)
1552 	    u_freebranch(buf, tofree->uh_alt_next, uhpp);   /* recursive */
1553 	next = tofree->uh_prev;
1554 	u_freeentries(buf, tofree, uhpp);
1555     }
1556 }
1557 
1558 /*
1559  * Free all the undo entries for one header and the header itself.
1560  * This means that "uhp" is invalid when returning.
1561  */
1562     static void
1563 u_freeentries(buf, uhp, uhpp)
1564     buf_T	    *buf;
1565     u_header_T	    *uhp;
1566     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
1567 {
1568     u_entry_T	    *uep, *nuep;
1569 
1570     /* Check for pointers to the header that become invalid now. */
1571     if (buf->b_u_curhead == uhp)
1572 	buf->b_u_curhead = NULL;
1573     if (uhpp != NULL && uhp == *uhpp)
1574 	*uhpp = NULL;
1575 
1576     for (uep = uhp->uh_entry; uep != NULL; uep = nuep)
1577     {
1578 	nuep = uep->ue_next;
1579 	u_freeentry(uep, uep->ue_size);
1580     }
1581 
1582     U_FREE_LINE((char_u *)uhp);
1583     --buf->b_u_numhead;
1584 }
1585 
1586 /*
1587  * free entry 'uep' and 'n' lines in uep->ue_array[]
1588  */
1589     static void
1590 u_freeentry(uep, n)
1591     u_entry_T	*uep;
1592     long	    n;
1593 {
1594     while (n > 0)
1595 	U_FREE_LINE(uep->ue_array[--n]);
1596     U_FREE_LINE((char_u *)uep->ue_array);
1597     U_FREE_LINE((char_u *)uep);
1598 }
1599 
1600 /*
1601  * invalidate the undo buffer; called when storage has already been released
1602  */
1603     void
1604 u_clearall(buf)
1605     buf_T	*buf;
1606 {
1607     buf->b_u_newhead = buf->b_u_oldhead = buf->b_u_curhead = NULL;
1608     buf->b_u_synced = TRUE;
1609     buf->b_u_numhead = 0;
1610     buf->b_u_line_ptr = NULL;
1611     buf->b_u_line_lnum = 0;
1612 }
1613 
1614 /*
1615  * save the line "lnum" for the "U" command
1616  */
1617     void
1618 u_saveline(lnum)
1619     linenr_T lnum;
1620 {
1621     if (lnum == curbuf->b_u_line_lnum)	    /* line is already saved */
1622 	return;
1623     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) /* should never happen */
1624 	return;
1625     u_clearline();
1626     curbuf->b_u_line_lnum = lnum;
1627     if (curwin->w_cursor.lnum == lnum)
1628 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
1629     else
1630 	curbuf->b_u_line_colnr = 0;
1631     if ((curbuf->b_u_line_ptr = u_save_line(lnum)) == NULL)
1632 	do_outofmem_msg((long_u)0);
1633 }
1634 
1635 /*
1636  * clear the line saved for the "U" command
1637  * (this is used externally for crossing a line while in insert mode)
1638  */
1639     void
1640 u_clearline()
1641 {
1642     if (curbuf->b_u_line_ptr != NULL)
1643     {
1644 	U_FREE_LINE(curbuf->b_u_line_ptr);
1645 	curbuf->b_u_line_ptr = NULL;
1646 	curbuf->b_u_line_lnum = 0;
1647     }
1648 }
1649 
1650 /*
1651  * Implementation of the "U" command.
1652  * Differentiation from vi: "U" can be undone with the next "U".
1653  * We also allow the cursor to be in another line.
1654  */
1655     void
1656 u_undoline()
1657 {
1658     colnr_T t;
1659     char_u  *oldp;
1660 
1661     if (undo_off)
1662 	return;
1663 
1664     if (curbuf->b_u_line_ptr == NULL ||
1665 			curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
1666     {
1667 	beep_flush();
1668 	return;
1669     }
1670 	/* first save the line for the 'u' command */
1671     if (u_savecommon(curbuf->b_u_line_lnum - 1,
1672 				curbuf->b_u_line_lnum + 1, (linenr_T)0) == FAIL)
1673 	return;
1674     oldp = u_save_line(curbuf->b_u_line_lnum);
1675     if (oldp == NULL)
1676     {
1677 	do_outofmem_msg((long_u)0);
1678 	return;
1679     }
1680     ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
1681     changed_bytes(curbuf->b_u_line_lnum, 0);
1682     U_FREE_LINE(curbuf->b_u_line_ptr);
1683     curbuf->b_u_line_ptr = oldp;
1684 
1685     t = curbuf->b_u_line_colnr;
1686     if (curwin->w_cursor.lnum == curbuf->b_u_line_lnum)
1687 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
1688     curwin->w_cursor.col = t;
1689     curwin->w_cursor.lnum = curbuf->b_u_line_lnum;
1690 }
1691 
1692 /*
1693  * There are two implementations of the memory management for undo:
1694  * 1. Use the standard malloc()/free() functions.
1695  *    This should be fast for allocating memory, but when a buffer is
1696  *    abandoned every single allocated chunk must be freed, which may be slow.
1697  * 2. Allocate larger blocks of memory and keep track of chunks ourselves.
1698  *    This is fast for abandoning, but the use of linked lists is slow for
1699  *    finding a free chunk.  Esp. when a lot of lines are changed or deleted.
1700  * A bit of profiling showed that the first method is faster, especially when
1701  * making a large number of changes, under the condition that malloc()/free()
1702  * is implemented efficiently.
1703  */
1704 #ifdef U_USE_MALLOC
1705 /*
1706  * Version of undo memory allocation using malloc()/free()
1707  *
1708  * U_FREE_LINE() and U_ALLOC_LINE() are macros that invoke vim_free() and
1709  * lalloc() directly.
1710  */
1711 
1712 /*
1713  * Free all allocated memory blocks for the buffer 'buf'.
1714  */
1715     void
1716 u_blockfree(buf)
1717     buf_T	*buf;
1718 {
1719     while (buf->b_u_oldhead != NULL)
1720 	u_freeheader(buf, buf->b_u_oldhead, NULL);
1721     U_FREE_LINE(buf->b_u_line_ptr);
1722 }
1723 
1724 #else
1725 /*
1726  * Storage allocation for the undo lines and blocks of the current file.
1727  * Version where Vim keeps track of the available memory.
1728  */
1729 
1730 /*
1731  * Memory is allocated in relatively large blocks. These blocks are linked
1732  * in the allocated block list, headed by curbuf->b_block_head. They are all
1733  * freed when abandoning a file, so we don't have to free every single line.
1734  * The list is kept sorted on memory address.
1735  * block_alloc() allocates a block.
1736  * m_blockfree() frees all blocks.
1737  *
1738  * The available chunks of memory are kept in free chunk lists. There is
1739  * one free list for each block of allocated memory. The list is kept sorted
1740  * on memory address.
1741  * u_alloc_line() gets a chunk from the free lists.
1742  * u_free_line() returns a chunk to the free lists.
1743  * curbuf->b_m_search points to the chunk before the chunk that was
1744  * freed/allocated the last time.
1745  * curbuf->b_mb_current points to the b_head where curbuf->b_m_search
1746  * points into the free list.
1747  *
1748  *
1749  *  b_block_head     /---> block #1	/---> block #2
1750  *	 mb_next ---/	    mb_next ---/       mb_next ---> NULL
1751  *	 mb_info	    mb_info	       mb_info
1752  *	    |		       |		  |
1753  *	    V		       V		  V
1754  *	  NULL		free chunk #1.1      free chunk #2.1
1755  *			       |		  |
1756  *			       V		  V
1757  *			free chunk #1.2		 NULL
1758  *			       |
1759  *			       V
1760  *			      NULL
1761  *
1762  * When a single free chunk list would have been used, it could take a lot
1763  * of time in u_free_line() to find the correct place to insert a chunk in the
1764  * free list. The single free list would become very long when many lines are
1765  * changed (e.g. with :%s/^M$//).
1766  */
1767 
1768  /*
1769   * this blocksize is used when allocating new lines
1770   */
1771 #define MEMBLOCKSIZE 2044
1772 
1773 /*
1774  * The size field contains the size of the chunk, including the size field
1775  * itself.
1776  *
1777  * When the chunk is not in-use it is preceded with the m_info structure.
1778  * The m_next field links it in one of the free chunk lists.
1779  *
1780  * On most unix systems structures have to be longword (32 or 64 bit) aligned.
1781  * On most other systems they are short (16 bit) aligned.
1782  */
1783 
1784 /* the structure definitions are now in structs.h */
1785 
1786 #ifdef ALIGN_LONG
1787     /* size of m_size */
1788 # define M_OFFSET (sizeof(long_u))
1789 #else
1790     /* size of m_size */
1791 # define M_OFFSET (sizeof(short_u))
1792 #endif
1793 
1794 static char_u *u_blockalloc __ARGS((long_u));
1795 
1796 /*
1797  * Allocate a block of memory and link it in the allocated block list.
1798  */
1799     static char_u *
1800 u_blockalloc(size)
1801     long_u	size;
1802 {
1803     mblock_T	*p;
1804     mblock_T	*mp, *next;
1805 
1806     p = (mblock_T *)lalloc(size + sizeof(mblock_T), FALSE);
1807     if (p != NULL)
1808     {
1809 	 /* Insert the block into the allocated block list, keeping it
1810 		    sorted on address. */
1811 	for (mp = &curbuf->b_block_head;
1812 		(next = mp->mb_next) != NULL && next < p;
1813 			mp = next)
1814 	    ;
1815 	p->mb_next = next;		/* link in block list */
1816 	p->mb_size = size;
1817 	p->mb_maxsize = 0;		/* nothing free yet */
1818 	mp->mb_next = p;
1819 	p->mb_info.m_next = NULL;	/* clear free list */
1820 	p->mb_info.m_size = 0;
1821 	curbuf->b_mb_current = p;	/* remember current block */
1822 	curbuf->b_m_search = NULL;
1823 	p++;				/* return usable memory */
1824     }
1825     return (char_u *)p;
1826 }
1827 
1828 /*
1829  * free all allocated memory blocks for the buffer 'buf'
1830  */
1831     void
1832 u_blockfree(buf)
1833     buf_T	*buf;
1834 {
1835     mblock_T	*p, *np;
1836 
1837     for (p = buf->b_block_head.mb_next; p != NULL; p = np)
1838     {
1839 	np = p->mb_next;
1840 	vim_free(p);
1841     }
1842     buf->b_block_head.mb_next = NULL;
1843     buf->b_m_search = NULL;
1844     buf->b_mb_current = NULL;
1845 }
1846 
1847 /*
1848  * Free a chunk of memory for the current buffer.
1849  * Insert the chunk into the correct free list, keeping it sorted on address.
1850  */
1851     static void
1852 u_free_line(ptr, keep)
1853     char_u	*ptr;
1854     int		keep;	/* don't free the block when it's empty */
1855 {
1856     minfo_T	*next;
1857     minfo_T	*prev, *curr;
1858     minfo_T	*mp;
1859     mblock_T	*nextb;
1860     mblock_T	*prevb;
1861     long_u	maxsize;
1862 
1863     if (ptr == NULL || ptr == IObuff)
1864 	return;	/* illegal address can happen in out-of-memory situations */
1865 
1866     mp = (minfo_T *)(ptr - M_OFFSET);
1867 
1868     /* find block where chunk could be a part off */
1869     /* if we change curbuf->b_mb_current, curbuf->b_m_search is set to NULL */
1870     if (curbuf->b_mb_current == NULL || mp < (minfo_T *)curbuf->b_mb_current)
1871     {
1872 	curbuf->b_mb_current = curbuf->b_block_head.mb_next;
1873 	curbuf->b_m_search = NULL;
1874     }
1875     if ((nextb = curbuf->b_mb_current->mb_next) != NULL
1876 						     && (minfo_T *)nextb < mp)
1877     {
1878 	curbuf->b_mb_current = nextb;
1879 	curbuf->b_m_search = NULL;
1880     }
1881     while ((nextb = curbuf->b_mb_current->mb_next) != NULL
1882 						     && (minfo_T *)nextb < mp)
1883 	curbuf->b_mb_current = nextb;
1884 
1885     curr = NULL;
1886     /*
1887      * If mp is smaller than curbuf->b_m_search->m_next go to the start of
1888      * the free list
1889      */
1890     if (curbuf->b_m_search == NULL || mp < (curbuf->b_m_search->m_next))
1891 	next = &(curbuf->b_mb_current->mb_info);
1892     else
1893 	next = curbuf->b_m_search;
1894     /*
1895      * The following loop is executed very often.
1896      * Therefore it has been optimized at the cost of readability.
1897      * Keep it fast!
1898      */
1899 #ifdef SLOW_BUT_EASY_TO_READ
1900     do
1901     {
1902 	prev = curr;
1903 	curr = next;
1904 	next = next->m_next;
1905     }
1906     while (mp > next && next != NULL);
1907 #else
1908     do					    /* first, middle, last */
1909     {
1910 	prev = next->m_next;		    /* curr, next, prev */
1911 	if (prev == NULL || mp <= prev)
1912 	{
1913 	    prev = curr;
1914 	    curr = next;
1915 	    next = next->m_next;
1916 	    break;
1917 	}
1918 	curr = prev->m_next;		    /* next, prev, curr */
1919 	if (curr == NULL || mp <= curr)
1920 	{
1921 	    prev = next;
1922 	    curr = prev->m_next;
1923 	    next = curr->m_next;
1924 	    break;
1925 	}
1926 	next = curr->m_next;		    /* prev, curr, next */
1927     }
1928     while (mp > next && next != NULL);
1929 #endif
1930 
1931     /* if *mp and *next are concatenated, join them into one chunk */
1932     if ((char_u *)mp + mp->m_size == (char_u *)next)
1933     {
1934 	mp->m_size += next->m_size;
1935 	mp->m_next = next->m_next;
1936     }
1937     else
1938 	mp->m_next = next;
1939     maxsize = mp->m_size;
1940 
1941     /* if *curr and *mp are concatenated, join them */
1942     if (prev != NULL && (char_u *)curr + curr->m_size == (char_u *)mp)
1943     {
1944 	curr->m_size += mp->m_size;
1945 	maxsize = curr->m_size;
1946 	curr->m_next = mp->m_next;
1947 	curbuf->b_m_search = prev;
1948     }
1949     else
1950     {
1951 	curr->m_next = mp;
1952 	curbuf->b_m_search = curr;  /* put curbuf->b_m_search before freed
1953 				       chunk */
1954     }
1955 
1956     /*
1957      * If the block only containes free memory now, release it.
1958      */
1959     if (!keep && curbuf->b_mb_current->mb_size
1960 			      == curbuf->b_mb_current->mb_info.m_next->m_size)
1961     {
1962 	/* Find the block before the current one to be able to unlink it from
1963 	 * the list of blocks. */
1964 	prevb = &curbuf->b_block_head;
1965 	for (nextb = prevb->mb_next; nextb != curbuf->b_mb_current;
1966 						       nextb = nextb->mb_next)
1967 	    prevb = nextb;
1968 	prevb->mb_next = nextb->mb_next;
1969 	vim_free(nextb);
1970 	curbuf->b_mb_current = NULL;
1971 	curbuf->b_m_search = NULL;
1972     }
1973     else if (curbuf->b_mb_current->mb_maxsize < maxsize)
1974 	curbuf->b_mb_current->mb_maxsize = maxsize;
1975 }
1976 
1977 /*
1978  * Allocate and initialize a new line structure with room for at least
1979  * 'size' characters plus a terminating NUL.
1980  */
1981     static char_u *
1982 u_alloc_line(size)
1983     unsigned	size;
1984 {
1985     minfo_T	*mp, *mprev, *mp2;
1986     mblock_T	*mbp;
1987     int		size_align;
1988 
1989     /*
1990      * Add room for size field and trailing NUL byte.
1991      * Adjust for minimal size (must be able to store minfo_T
1992      * plus a trailing NUL, so the chunk can be released again)
1993      */
1994     size += M_OFFSET + 1;
1995     if (size < sizeof(minfo_T) + 1)
1996 	size = sizeof(minfo_T) + 1;
1997 
1998     /*
1999      * round size up for alignment
2000      */
2001     size_align = (size + ALIGN_MASK) & ~ALIGN_MASK;
2002 
2003     /*
2004      * If curbuf->b_m_search is NULL (uninitialized free list) start at
2005      * curbuf->b_block_head
2006      */
2007     if (curbuf->b_mb_current == NULL || curbuf->b_m_search == NULL)
2008     {
2009 	curbuf->b_mb_current = &curbuf->b_block_head;
2010 	curbuf->b_m_search = &(curbuf->b_block_head.mb_info);
2011     }
2012 
2013     /* Search for a block with enough space. */
2014     mbp = curbuf->b_mb_current;
2015     while (mbp->mb_maxsize < size_align)
2016     {
2017 	if (mbp->mb_next != NULL)
2018 	    mbp = mbp->mb_next;
2019 	else
2020 	    mbp = &curbuf->b_block_head;
2021 	if (mbp == curbuf->b_mb_current)
2022 	{
2023 	    int	n = (size_align > (MEMBLOCKSIZE / 4)
2024 					     ? size_align : MEMBLOCKSIZE);
2025 
2026 	    /* Back where we started in block list: need to add a new block
2027 	     * with enough space. */
2028 	    mp = (minfo_T *)u_blockalloc((long_u)n);
2029 	    if (mp == NULL)
2030 		return (NULL);
2031 	    mp->m_size = n;
2032 	    u_free_line((char_u *)mp + M_OFFSET, TRUE);
2033 	    mbp = curbuf->b_mb_current;
2034 	    break;
2035 	}
2036     }
2037     if (mbp != curbuf->b_mb_current)
2038 	curbuf->b_m_search = &(mbp->mb_info);
2039 
2040     /* In this block find a chunk with enough space. */
2041     mprev = curbuf->b_m_search;
2042     mp = curbuf->b_m_search->m_next;
2043     for (;;)
2044     {
2045 	if (mp == NULL)			    /* at end of the list */
2046 	    mp = &(mbp->mb_info);	    /* wrap around to begin */
2047 	if (mp->m_size >= size)
2048 	    break;
2049 	if (mp == curbuf->b_m_search)
2050 	{
2051 	    /* back where we started in free chunk list: "cannot happen" */
2052 	    EMSG2(_(e_intern2), "u_alloc_line()");
2053 	    return NULL;
2054 	}
2055 	mprev = mp;
2056 	mp = mp->m_next;
2057     }
2058 
2059     /* when using the largest chunk adjust mb_maxsize */
2060     if (mp->m_size >= mbp->mb_maxsize)
2061 	mbp->mb_maxsize = 0;
2062 
2063     /* if the chunk we found is large enough, split it up in two */
2064     if ((long)mp->m_size - size_align >= (long)(sizeof(minfo_T) + 1))
2065     {
2066 	mp2 = (minfo_T *)((char_u *)mp + size_align);
2067 	mp2->m_size = mp->m_size - size_align;
2068 	mp2->m_next = mp->m_next;
2069 	mprev->m_next = mp2;
2070 	mp->m_size = size_align;
2071     }
2072     else		    /* remove *mp from the free list */
2073     {
2074 	mprev->m_next = mp->m_next;
2075     }
2076     curbuf->b_m_search = mprev;
2077     curbuf->b_mb_current = mbp;
2078 
2079     /* If using the largest chunk need to find the new largest chunk */
2080     if (mbp->mb_maxsize == 0)
2081 	for (mp2 = &(mbp->mb_info); mp2 != NULL; mp2 = mp2->m_next)
2082 	    if (mbp->mb_maxsize < mp2->m_size)
2083 		mbp->mb_maxsize = mp2->m_size;
2084 
2085     mp = (minfo_T *)((char_u *)mp + M_OFFSET);
2086     *(char_u *)mp = NUL;		    /* set the first byte to NUL */
2087 
2088     return ((char_u *)mp);
2089 }
2090 #endif
2091 
2092 /*
2093  * u_save_line(): allocate memory with u_alloc_line() and copy line 'lnum'
2094  * into it.
2095  */
2096     static char_u *
2097 u_save_line(lnum)
2098     linenr_T	lnum;
2099 {
2100     char_u	*src;
2101     char_u	*dst;
2102     unsigned	len;
2103 
2104     src = ml_get(lnum);
2105     len = (unsigned)STRLEN(src);
2106     if ((dst = U_ALLOC_LINE(len)) != NULL)
2107 	mch_memmove(dst, src, (size_t)(len + 1));
2108     return (dst);
2109 }
2110 
2111 /*
2112  * Check if the 'modified' flag is set, or 'ff' has changed (only need to
2113  * check the first character, because it can only be "dos", "unix" or "mac").
2114  * "nofile" and "scratch" type buffers are considered to always be unchanged.
2115  */
2116     int
2117 bufIsChanged(buf)
2118     buf_T	*buf;
2119 {
2120     return
2121 #ifdef FEAT_QUICKFIX
2122 	    !bt_dontwrite(buf) &&
2123 #endif
2124 	    (buf->b_changed || file_ff_differs(buf));
2125 }
2126 
2127     int
2128 curbufIsChanged()
2129 {
2130     return
2131 #ifdef FEAT_QUICKFIX
2132 	!bt_dontwrite(curbuf) &&
2133 #endif
2134 	(curbuf->b_changed || file_ff_differs(curbuf));
2135 }
2136