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