xref: /vim-8.2.3635/src/memline.c (revision 592e0a2a)
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 /* for debugging */
11 /* #define CHECK(c, s)	if (c) EMSG(s) */
12 #define CHECK(c, s)
13 
14 /*
15  * memline.c: Contains the functions for appending, deleting and changing the
16  * text lines. The memfile functions are used to store the information in blocks
17  * of memory, backed up by a file. The structure of the information is a tree.
18  * The root of the tree is a pointer block. The leaves of the tree are data
19  * blocks. In between may be several layers of pointer blocks, forming branches.
20  *
21  * Three types of blocks are used:
22  * - Block nr 0 contains information for recovery
23  * - Pointer blocks contain list of pointers to other blocks.
24  * - Data blocks contain the actual text.
25  *
26  * Block nr 0 contains the block0 structure (see below).
27  *
28  * Block nr 1 is the first pointer block. It is the root of the tree.
29  * Other pointer blocks are branches.
30  *
31  *  If a line is too big to fit in a single page, the block containing that
32  *  line is made big enough to hold the line. It may span several pages.
33  *  Otherwise all blocks are one page.
34  *
35  *  A data block that was filled when starting to edit a file and was not
36  *  changed since then, can have a negative block number. This means that it
37  *  has not yet been assigned a place in the file. When recovering, the lines
38  *  in this data block can be read from the original file. When the block is
39  *  changed (lines appended/deleted/changed) or when it is flushed it gets a
40  *  positive number. Use mf_trans_del() to get the new number, before calling
41  *  mf_get().
42  */
43 
44 #if defined(MSDOS) || defined(WIN32) || defined(_WIN64)
45 # include <io.h>
46 #endif
47 
48 #include "vim.h"
49 
50 #ifdef HAVE_FCNTL_H
51 # include <fcntl.h>
52 #endif
53 #ifndef UNIX		/* it's in os_unix.h for Unix */
54 # include <time.h>
55 #endif
56 
57 #ifdef SASC
58 # include <proto/dos.h>	    /* for Open() and Close() */
59 #endif
60 
61 typedef struct block0		ZERO_BL;    /* contents of the first block */
62 typedef struct pointer_block	PTR_BL;	    /* contents of a pointer block */
63 typedef struct data_block	DATA_BL;    /* contents of a data block */
64 typedef struct pointer_entry	PTR_EN;	    /* block/line-count pair */
65 
66 #define DATA_ID	    (('d' << 8) + 'a')	    /* data block id */
67 #define PTR_ID	    (('p' << 8) + 't')	    /* pointer block id */
68 #define BLOCK0_ID0  'b'			    /* block 0 id 0 */
69 #define BLOCK0_ID1  '0'			    /* block 0 id 1 */
70 
71 /*
72  * pointer to a block, used in a pointer block
73  */
74 struct pointer_entry
75 {
76     blocknr_T	pe_bnum;	/* block number */
77     linenr_T	pe_line_count;	/* number of lines in this branch */
78     linenr_T	pe_old_lnum;	/* lnum for this block (for recovery) */
79     int		pe_page_count;	/* number of pages in block pe_bnum */
80 };
81 
82 /*
83  * A pointer block contains a list of branches in the tree.
84  */
85 struct pointer_block
86 {
87     short_u	pb_id;		/* ID for pointer block: PTR_ID */
88     short_u	pb_count;	/* number of pointer in this block */
89     short_u	pb_count_max;	/* maximum value for pb_count */
90     PTR_EN	pb_pointer[1];	/* list of pointers to blocks (actually longer)
91 				 * followed by empty space until end of page */
92 };
93 
94 /*
95  * A data block is a leaf in the tree.
96  *
97  * The text of the lines is at the end of the block. The text of the first line
98  * in the block is put at the end, the text of the second line in front of it,
99  * etc. Thus the order of the lines is the opposite of the line number.
100  */
101 struct data_block
102 {
103     short_u	db_id;		/* ID for data block: DATA_ID */
104     unsigned	db_free;	/* free space available */
105     unsigned	db_txt_start;	/* byte where text starts */
106     unsigned	db_txt_end;	/* byte just after data block */
107     linenr_T	db_line_count;	/* number of lines in this block */
108     unsigned	db_index[1];	/* index for start of line (actually bigger)
109 				 * followed by empty space upto db_txt_start
110 				 * followed by the text in the lines until
111 				 * end of page */
112 };
113 
114 /*
115  * The low bits of db_index hold the actual index. The topmost bit is
116  * used for the global command to be able to mark a line.
117  * This method is not clean, but otherwise there would be at least one extra
118  * byte used for each line.
119  * The mark has to be in this place to keep it with the correct line when other
120  * lines are inserted or deleted.
121  */
122 #define DB_MARKED	((unsigned)1 << ((sizeof(unsigned) * 8) - 1))
123 #define DB_INDEX_MASK	(~DB_MARKED)
124 
125 #define INDEX_SIZE  (sizeof(unsigned))	    /* size of one db_index entry */
126 #define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE)  /* size of data block header */
127 
128 #define B0_FNAME_SIZE	900
129 #define B0_UNAME_SIZE	40
130 #define B0_HNAME_SIZE	40
131 /*
132  * Restrict the numbers to 32 bits, otherwise most compilers will complain.
133  * This won't detect a 64 bit machine that only swaps a byte in the top 32
134  * bits, but that is crazy anyway.
135  */
136 #define B0_MAGIC_LONG	0x30313233L
137 #define B0_MAGIC_INT	0x20212223L
138 #define B0_MAGIC_SHORT	0x10111213L
139 #define B0_MAGIC_CHAR	0x55
140 
141 /*
142  * Block zero holds all info about the swap file.
143  *
144  * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
145  * swap files unusable!
146  *
147  * If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
148  *
149  * This block is built up of single bytes, to make it portable accros
150  * different machines. b0_magic_* is used to check the byte order and size of
151  * variables, because the rest of the swap file is not portable.
152  */
153 struct block0
154 {
155     char_u	b0_id[2];	/* id for block 0: BLOCK0_ID0 and BLOCK0_ID1 */
156     char_u	b0_version[10];	/* Vim version string */
157     char_u	b0_page_size[4];/* number of bytes per page */
158     char_u	b0_mtime[4];	/* last modification time of file */
159     char_u	b0_ino[4];	/* inode of b0_fname */
160     char_u	b0_pid[4];	/* process id of creator (or 0) */
161     char_u	b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
162     char_u	b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
163     char_u	b0_fname[B0_FNAME_SIZE]; /* name of file being edited */
164     long	b0_magic_long;	/* check for byte order of long */
165     int		b0_magic_int;	/* check for byte order of int */
166     short	b0_magic_short;	/* check for byte order of short */
167     char_u	b0_magic_char;	/* check for last char */
168 };
169 #define   b0_dirty b0_fname[B0_FNAME_SIZE-1]
170 
171 #define STACK_INCR	5	/* nr of entries added to ml_stack at a time */
172 
173 /*
174  * The line number where the first mark may be is remembered.
175  * If it is 0 there are no marks at all.
176  * (always used for the current buffer only, no buffer change possible while
177  * executing a global command).
178  */
179 static linenr_T	lowest_marked = 0;
180 
181 /*
182  * arguments for ml_find_line()
183  */
184 #define ML_DELETE	0x11	    /* delete line */
185 #define ML_INSERT	0x12	    /* insert line */
186 #define ML_FIND		0x13	    /* just find the line */
187 #define ML_FLUSH	0x02	    /* flush locked block */
188 #define ML_SIMPLE(x)	(x & 0x10)  /* DEL, INS or FIND */
189 
190 static void set_b0_fname __ARGS((ZERO_BL *, buf_T *buf));
191 static time_t swapfile_info __ARGS((char_u *));
192 static int recov_file_names __ARGS((char_u **, char_u *, int prepend_dot));
193 static int ml_append_int __ARGS((buf_T *, linenr_T, char_u *, colnr_T, int, int));
194 static int ml_delete_int __ARGS((buf_T *, linenr_T, int));
195 static char_u *findswapname __ARGS((buf_T *, char_u **, char_u *));
196 static void ml_flush_line __ARGS((buf_T *));
197 static bhdr_T *ml_new_data __ARGS((memfile_T *, int, int));
198 static bhdr_T *ml_new_ptr __ARGS((memfile_T *));
199 static bhdr_T *ml_find_line __ARGS((buf_T *, linenr_T, int));
200 static int ml_add_stack __ARGS((buf_T *));
201 static char_u *makeswapname __ARGS((buf_T *, char_u *));
202 static void ml_lineadd __ARGS((buf_T *, int));
203 static int b0_magic_wrong __ARGS((ZERO_BL *));
204 #ifdef CHECK_INODE
205 static int fnamecmp_ino __ARGS((char_u *, char_u *, long));
206 #endif
207 static void long_to_char __ARGS((long, char_u *));
208 static long char_to_long __ARGS((char_u *));
209 #if defined(UNIX) || defined(WIN3264)
210 static char_u *make_percent_swname __ARGS((char_u *dir, char_u *name));
211 #endif
212 #ifdef FEAT_BYTEOFF
213 static void ml_updatechunk __ARGS((buf_T *buf, long line, long len, int updtype));
214 #endif
215 
216 /*
217  * open a new memline for 'curbuf'
218  *
219  * return FAIL for failure, OK otherwise
220  */
221     int
222 ml_open()
223 {
224     memfile_T	*mfp;
225     bhdr_T	*hp = NULL;
226     ZERO_BL	*b0p;
227     PTR_BL	*pp;
228     DATA_BL	*dp;
229 
230 /*
231  * init fields in memline struct
232  */
233     curbuf->b_ml.ml_stack_size = 0;	/* no stack yet */
234     curbuf->b_ml.ml_stack = NULL;	/* no stack yet */
235     curbuf->b_ml.ml_stack_top = 0;	/* nothing in the stack */
236     curbuf->b_ml.ml_locked = NULL;	/* no cached block */
237     curbuf->b_ml.ml_line_lnum = 0;	/* no cached line */
238 #ifdef FEAT_BYTEOFF
239     curbuf->b_ml.ml_chunksize = NULL;
240 #endif
241 
242 /*
243  * When 'updatecount' is non-zero, flag that a swap file may be opened later.
244  */
245     if (p_uc && curbuf->b_p_swf)
246 	curbuf->b_may_swap = TRUE;
247     else
248 	curbuf->b_may_swap = FALSE;
249 
250 /*
251  * Open the memfile.  No swap file is created yet.
252  */
253     mfp = mf_open(NULL, 0);
254     if (mfp == NULL)
255 	goto error;
256 
257     curbuf->b_ml.ml_mfp = mfp;
258     curbuf->b_ml.ml_flags = ML_EMPTY;
259     curbuf->b_ml.ml_line_count = 1;
260 #ifdef FEAT_LINEBREAK
261     curwin->w_nrwidth_line_count = 0;
262 #endif
263 
264 #if defined(MSDOS) && !defined(DJGPP)
265     /* for 16 bit MS-DOS create a swapfile now, because we run out of
266      * memory very quickly */
267     if (p_uc != 0)
268 	ml_open_file(curbuf);
269 #endif
270 
271 /*
272  * fill block0 struct and write page 0
273  */
274     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
275 	goto error;
276     if (hp->bh_bnum != 0)
277     {
278 	EMSG(_("E298: Didn't get block nr 0?"));
279 	goto error;
280     }
281     b0p = (ZERO_BL *)(hp->bh_data);
282 
283     b0p->b0_id[0] = BLOCK0_ID0;
284     b0p->b0_id[1] = BLOCK0_ID1;
285     b0p->b0_dirty = curbuf->b_changed ? 0x55 : 0;
286     b0p->b0_magic_long = (long)B0_MAGIC_LONG;
287     b0p->b0_magic_int = (int)B0_MAGIC_INT;
288     b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
289     b0p->b0_magic_char = B0_MAGIC_CHAR;
290 
291     STRNCPY(b0p->b0_version, "VIM ", 4);
292     STRNCPY(b0p->b0_version + 4, Version, 6);
293     set_b0_fname(b0p, curbuf);
294     long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
295     (void)get_user_name(b0p->b0_uname, B0_UNAME_SIZE);
296     b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL;
297     mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
298     b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
299     long_to_char(mch_get_pid(), b0p->b0_pid);
300 
301     /*
302      * Always sync block number 0 to disk, so we can check the file name in
303      * the swap file in findswapname(). Don't do this for help files though.
304      * Only works when there's a swapfile, otherwise it's done when the file
305      * is created.
306      */
307     mf_put(mfp, hp, TRUE, FALSE);
308     if (!curbuf->b_help)
309 	(void)mf_sync(mfp, 0);
310 
311 /*
312  * fill in root pointer block and write page 1
313  */
314     if ((hp = ml_new_ptr(mfp)) == NULL)
315 	goto error;
316     if (hp->bh_bnum != 1)
317     {
318 	EMSG(_("E298: Didn't get block nr 1?"));
319 	goto error;
320     }
321     pp = (PTR_BL *)(hp->bh_data);
322     pp->pb_count = 1;
323     pp->pb_pointer[0].pe_bnum = 2;
324     pp->pb_pointer[0].pe_page_count = 1;
325     pp->pb_pointer[0].pe_old_lnum = 1;
326     pp->pb_pointer[0].pe_line_count = 1;    /* line count after insertion */
327     mf_put(mfp, hp, TRUE, FALSE);
328 
329 /*
330  * allocate first data block and create an empty line 1.
331  */
332     if ((hp = ml_new_data(mfp, FALSE, 1)) == NULL)
333 	goto error;
334     if (hp->bh_bnum != 2)
335     {
336 	EMSG(_("E298: Didn't get block nr 2?"));
337 	goto error;
338     }
339 
340     dp = (DATA_BL *)(hp->bh_data);
341     dp->db_index[0] = --dp->db_txt_start;	/* at end of block */
342     dp->db_free -= 1 + INDEX_SIZE;
343     dp->db_line_count = 1;
344     *((char_u *)dp + dp->db_txt_start) = NUL;	/* emtpy line */
345 
346     return OK;
347 
348 error:
349     if (mfp != NULL)
350     {
351 	if (hp)
352 	    mf_put(mfp, hp, FALSE, FALSE);
353 	mf_close(mfp, TRUE);	    /* will also free(mfp->mf_fname) */
354     }
355     curbuf->b_ml.ml_mfp = NULL;
356     return FAIL;
357 }
358 
359 /*
360  * ml_setname() is called when the file name of "buf" has been changed.
361  * It may rename the swap file.
362  */
363     void
364 ml_setname(buf)
365     buf_T	*buf;
366 {
367     int		success = FALSE;
368     memfile_T	*mfp;
369     char_u	*fname;
370     char_u	*dirp;
371 #if defined(MSDOS) || defined(MSWIN)
372     char_u	*p;
373 #endif
374 
375     mfp = buf->b_ml.ml_mfp;
376     if (mfp->mf_fd < 0)		    /* there is no swap file yet */
377     {
378 	/*
379 	 * When 'updatecount' is 0 and 'noswapfile' there is no swap file.
380 	 * For help files we will make a swap file now.
381 	 */
382 	if (p_uc != 0)
383 	    ml_open_file(buf);	    /* create a swap file */
384 	return;
385     }
386 
387     /*
388      * Try all directories in the 'directory' option.
389      */
390     dirp = p_dir;
391     for (;;)
392     {
393 	if (*dirp == NUL)	    /* tried all directories, fail */
394 	    break;
395 	fname = findswapname(buf, &dirp, mfp->mf_fname); /* alloc's fname */
396 	if (fname == NULL)	    /* no file name found for this dir */
397 	    continue;
398 
399 #if defined(MSDOS) || defined(MSWIN)
400 	/*
401 	 * Set full pathname for swap file now, because a ":!cd dir" may
402 	 * change directory without us knowing it.
403 	 */
404 	p = FullName_save(fname, FALSE);
405 	vim_free(fname);
406 	fname = p;
407 	if (fname == NULL)
408 	    continue;
409 #endif
410 	/* if the file name is the same we don't have to do anything */
411 	if (fnamecmp(fname, mfp->mf_fname) == 0)
412 	{
413 	    vim_free(fname);
414 	    success = TRUE;
415 	    break;
416 	}
417 	/* need to close the swap file before renaming */
418 	if (mfp->mf_fd >= 0)
419 	{
420 	    close(mfp->mf_fd);
421 	    mfp->mf_fd = -1;
422 	}
423 
424 	/* try to rename the swap file */
425 	if (vim_rename(mfp->mf_fname, fname) == 0)
426 	{
427 	    success = TRUE;
428 	    vim_free(mfp->mf_fname);
429 	    mfp->mf_fname = fname;
430 	    vim_free(mfp->mf_ffname);
431 #if defined(MSDOS) || defined(MSWIN)
432 	    mfp->mf_ffname = NULL;  /* mf_fname is full pathname already */
433 #else
434 	    mf_set_ffname(mfp);
435 #endif
436 	    break;
437 	}
438 	vim_free(fname);	    /* this fname didn't work, try another */
439     }
440 
441     if (mfp->mf_fd == -1)	    /* need to (re)open the swap file */
442     {
443 	mfp->mf_fd = mch_open((char *)mfp->mf_fname, O_RDWR | O_EXTRA, 0);
444 	if (mfp->mf_fd < 0)
445 	{
446 	    /* could not (re)open the swap file, what can we do???? */
447 	    EMSG(_("E301: Oops, lost the swap file!!!"));
448 	    return;
449 	}
450     }
451     if (!success)
452 	EMSG(_("E302: Could not rename swap file"));
453 }
454 
455 /*
456  * Open a file for the memfile for all buffers that are not readonly or have
457  * been modified.
458  * Used when 'updatecount' changes from zero to non-zero.
459  */
460     void
461 ml_open_files()
462 {
463     buf_T	*buf;
464 
465     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
466 	if (!buf->b_p_ro || buf->b_changed)
467 	    ml_open_file(buf);
468 }
469 
470 /*
471  * Open a swap file for an existing memfile, if there is no swap file yet.
472  * If we are unable to find a file name, mf_fname will be NULL
473  * and the memfile will be in memory only (no recovery possible).
474  */
475     void
476 ml_open_file(buf)
477     buf_T	*buf;
478 {
479     memfile_T	*mfp;
480     char_u	*fname;
481     char_u	*dirp;
482 
483     mfp = buf->b_ml.ml_mfp;
484     if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf)
485 	return;		/* nothing to do */
486 
487     /*
488      * Try all directories in 'directory' option.
489      */
490     dirp = p_dir;
491     for (;;)
492     {
493 	if (*dirp == NUL)
494 	    break;
495 	/* There is a small chance that between chosing the swap file name and
496 	 * creating it, another Vim creates the file.  In that case the
497 	 * creation will fail and we will use another directory. */
498 	fname = findswapname(buf, &dirp, NULL);	/* allocates fname */
499 	if (fname == NULL)
500 	    continue;
501 	if (mf_open_file(mfp, fname) == OK)	/* consumes fname! */
502 	{
503 #if defined(MSDOS) || defined(MSWIN) || defined(RISCOS)
504 	    /*
505 	     * set full pathname for swap file now, because a ":!cd dir" may
506 	     * change directory without us knowing it.
507 	     */
508 	    mf_fullname(mfp);
509 #endif
510 	    /* Flush block zero, so others can read it */
511 	    if (mf_sync(mfp, MFS_ZERO) == OK)
512 		break;
513 	    /* Writing block 0 failed: close the file and try another dir */
514 	    mf_close_file(buf, FALSE);
515 	}
516     }
517 
518     if (mfp->mf_fname == NULL)		/* Failed! */
519     {
520 	need_wait_return = TRUE;	/* call wait_return later */
521 	++no_wait_return;
522 	(void)EMSG2(_("E303: Unable to open swap file for \"%s\", recovery impossible"),
523 		    buf_spname(buf) != NULL
524 			? (char_u *)buf_spname(buf)
525 			: buf->b_fname);
526 	--no_wait_return;
527     }
528 
529     /* don't try to open a swap file again */
530     buf->b_may_swap = FALSE;
531 }
532 
533 /*
534  * If still need to create a swap file, and starting to edit a not-readonly
535  * file, or reading into an existing buffer, create a swap file now.
536  */
537     void
538 check_need_swap(newfile)
539     int	    newfile;		/* reading file into new buffer */
540 {
541     if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile))
542 	ml_open_file(curbuf);
543 }
544 
545 /*
546  * Close memline for buffer 'buf'.
547  * If 'del_file' is TRUE, delete the swap file
548  */
549     void
550 ml_close(buf, del_file)
551     buf_T	*buf;
552     int		del_file;
553 {
554     if (buf->b_ml.ml_mfp == NULL)		/* not open */
555 	return;
556     mf_close(buf->b_ml.ml_mfp, del_file);	/* close the .swp file */
557     if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
558 	vim_free(buf->b_ml.ml_line_ptr);
559     vim_free(buf->b_ml.ml_stack);
560 #ifdef FEAT_BYTEOFF
561     vim_free(buf->b_ml.ml_chunksize);
562     buf->b_ml.ml_chunksize = NULL;
563 #endif
564     buf->b_ml.ml_mfp = NULL;
565 
566     /* Reset the "recovered" flag, give the ATTENTION prompt the next time
567      * this buffer is loaded. */
568     buf->b_flags &= ~BF_RECOVERED;
569 }
570 
571 /*
572  * Close all existing memlines and memfiles.
573  * Only used when exiting.
574  * When 'del_file' is TRUE, delete the memfiles.
575  */
576     void
577 ml_close_all(del_file)
578     int		del_file;
579 {
580     buf_T	*buf;
581 
582     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
583 	ml_close(buf, del_file);
584 #ifdef TEMPDIRNAMES
585     vim_deltempdir();	    /* delete created temp directory */
586 #endif
587 }
588 
589 /*
590  * Close all memfiles for not modified buffers.
591  * Only use just before exiting!
592  */
593     void
594 ml_close_notmod()
595 {
596     buf_T	*buf;
597 
598     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
599 	if (!bufIsChanged(buf))
600 	    ml_close(buf, TRUE);    /* close all not-modified buffers */
601 }
602 
603 /*
604  * Update the timestamp in the .swp file.
605  * Used when the file has been written.
606  */
607     void
608 ml_timestamp(buf)
609     buf_T	*buf;
610 {
611     memfile_T	*mfp;
612     bhdr_T	*hp;
613     ZERO_BL	*b0p;
614 
615     mfp = buf->b_ml.ml_mfp;
616 
617     if (mfp == NULL || (hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
618 	return;
619     b0p = (ZERO_BL *)(hp->bh_data);
620     if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
621 	EMSG(_("E304: ml_timestamp: Didn't get block 0??"));
622     else
623 	set_b0_fname(b0p, buf);
624     mf_put(mfp, hp, TRUE, FALSE);
625 }
626 
627 /*
628  * Write file name and timestamp into block 0 of a swap file.
629  * Also set buf->b_mtime.
630  * Don't use NameBuff[]!!!
631  */
632     static void
633 set_b0_fname(b0p, buf)
634     ZERO_BL	*b0p;
635     buf_T	*buf;
636 {
637     struct stat	st;
638 
639     if (buf->b_ffname == NULL)
640 	b0p->b0_fname[0] = NUL;
641     else
642     {
643 #if defined(MSDOS) || defined(MSWIN) || defined(AMIGA) || defined(RISCOS)
644 	/* systems that cannot translate "~user" back into a path: copy the
645 	 * file name unmodified */
646 	STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE);
647 #else
648 	size_t	flen, ulen;
649 	char_u	uname[B0_UNAME_SIZE];
650 
651 	/*
652 	 * For a file under the home directory of the current user, we try to
653 	 * replace the home directory path with "~user". This helps when
654 	 * editing the same file on different machines over a network.
655 	 * First replace home dir path with "~/" with home_replace().
656 	 * Then insert the user name to get "~user/".
657 	 */
658 	home_replace(NULL, buf->b_ffname, b0p->b0_fname, B0_FNAME_SIZE, TRUE);
659 	if (b0p->b0_fname[0] == '~')
660 	{
661 	    flen = STRLEN(b0p->b0_fname);
662 	    /* If there is no user name or it is too long, don't use "~/" */
663 	    if (get_user_name(uname, B0_UNAME_SIZE) == FAIL
664 			 || (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE - 1)
665 		STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE);
666 	    else
667 	    {
668 		mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
669 		mch_memmove(b0p->b0_fname + 1, uname, ulen);
670 	    }
671 	}
672 #endif
673 	if (mch_stat((char *)buf->b_ffname, &st) >= 0)
674 	{
675 	    long_to_char((long)st.st_mtime, b0p->b0_mtime);
676 #ifdef CHECK_INODE
677 	    long_to_char((long)st.st_ino, b0p->b0_ino);
678 #endif
679 	    buf_store_time(buf, &st, buf->b_ffname);
680 	    buf->b_mtime_read = buf->b_mtime;
681 	}
682 	else
683 	{
684 	    long_to_char(0L, b0p->b0_mtime);
685 #ifdef CHECK_INODE
686 	    long_to_char(0L, b0p->b0_ino);
687 #endif
688 	    buf->b_mtime = 0;
689 	    buf->b_mtime_read = 0;
690 	    buf->b_orig_size = 0;
691 	    buf->b_orig_mode = 0;
692 	}
693     }
694 }
695 
696 /*
697  * try to recover curbuf from the .swp file
698  */
699     void
700 ml_recover()
701 {
702     buf_T	*buf = NULL;
703     memfile_T	*mfp = NULL;
704     char_u	*fname;
705     bhdr_T	*hp = NULL;
706     ZERO_BL	*b0p;
707     PTR_BL	*pp;
708     DATA_BL	*dp;
709     infoptr_T	*ip;
710     blocknr_T	bnum;
711     int		page_count;
712     struct stat	org_stat, swp_stat;
713     int		len;
714     int		directly;
715     linenr_T	lnum;
716     char_u	*p;
717     int		i;
718     long	error;
719     int		cannot_open;
720     linenr_T	line_count;
721     int		has_error;
722     int		idx;
723     int		top;
724     int		txt_start;
725     off_t	size;
726     int		called_from_main;
727     int		serious_error = TRUE;
728     long	mtime;
729     int		attr;
730 
731     recoverymode = TRUE;
732     called_from_main = (curbuf->b_ml.ml_mfp == NULL);
733     attr = hl_attr(HLF_E);
734 /*
735  * If the file name ends in ".sw?" we use it directly.
736  * Otherwise a search is done to find the swap file(s).
737  */
738     fname = curbuf->b_fname;
739     if (fname == NULL)		    /* When there is no file name */
740 	fname = (char_u *)"";
741     len = (int)STRLEN(fname);
742     if (len >= 4 &&
743 #if defined(VMS) || defined(RISCOS)
744 	    STRNICMP(fname + len - 4, "_sw" , 3)
745 #else
746 	    STRNICMP(fname + len - 4, ".sw" , 3)
747 #endif
748 		== 0)
749     {
750 	directly = TRUE;
751 	fname = vim_strsave(fname); /* make a copy for mf_open() */
752     }
753     else
754     {
755 	directly = FALSE;
756 
757 	/* count the number of matching swap files */
758 	len = recover_names(&fname, FALSE, 0);
759 	if (len == 0)		    /* no swap files found */
760 	{
761 	    EMSG2(_("E305: No swap file found for %s"), fname);
762 	    goto theend;
763 	}
764 	if (len == 1)		    /* one swap file found, use it */
765 	    i = 1;
766 	else			    /* several swap files found, choose */
767 	{
768 	    /* list the names of the swap files */
769 	    (void)recover_names(&fname, TRUE, 0);
770 	    msg_putchar('\n');
771 	    MSG_PUTS(_("Enter number of swap file to use (0 to quit): "));
772 	    i = get_number(FALSE);
773 	    if (i < 1 || i > len)
774 		goto theend;
775 	}
776 	/* get the swap file name that will be used */
777 	(void)recover_names(&fname, FALSE, i);
778     }
779     if (fname == NULL)
780 	goto theend;			/* out of memory */
781 
782     /* When called from main() still need to initialize storage structure */
783     if (called_from_main && ml_open() == FAIL)
784 	getout(1);
785 
786 /*
787  * allocate a buffer structure (only the memline in it is really used)
788  */
789     buf = (buf_T *)alloc((unsigned)sizeof(buf_T));
790     if (buf == NULL)
791     {
792 	vim_free(fname);
793 	goto theend;
794     }
795 
796 /*
797  * init fields in memline struct
798  */
799     buf->b_ml.ml_stack_size = 0;	/* no stack yet */
800     buf->b_ml.ml_stack = NULL;		/* no stack yet */
801     buf->b_ml.ml_stack_top = 0;		/* nothing in the stack */
802     buf->b_ml.ml_line_lnum = 0;		/* no cached line */
803     buf->b_ml.ml_locked = NULL;		/* no locked block */
804     buf->b_ml.ml_flags = 0;
805 
806 /*
807  * open the memfile from the old swap file
808  */
809     p = vim_strsave(fname);		/* save fname for the message
810 					   (mf_open() may free fname) */
811     mfp = mf_open(fname, O_RDONLY);	/* consumes fname! */
812     if (mfp == NULL || mfp->mf_fd < 0)
813     {
814 	if (p != NULL)
815 	{
816 	    EMSG2(_("E306: Cannot open %s"), p);
817 	    vim_free(p);
818 	}
819 	goto theend;
820     }
821     vim_free(p);
822     buf->b_ml.ml_mfp = mfp;
823 
824     /*
825      * The page size set in mf_open() might be different from the page size
826      * used in the swap file, we must get it from block 0.  But to read block
827      * 0 we need a page size.  Use the minimal size for block 0 here, it will
828      * be set to the real value below.
829      */
830     mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
831 
832 /*
833  * try to read block 0
834  */
835     if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
836     {
837 	msg_start();
838 	MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST);
839 	msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
840 	MSG_PUTS_ATTR(
841 	   _("\nMaybe no changes were made or Vim did not update the swap file."),
842 		attr | MSG_HIST);
843 	msg_end();
844 	goto theend;
845     }
846     b0p = (ZERO_BL *)(hp->bh_data);
847     if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0)
848     {
849 	msg_start();
850 	msg_outtrans_attr(mfp->mf_fname, MSG_HIST);
851 	MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"),
852 								    MSG_HIST);
853 	MSG_PUTS_ATTR(_("Use Vim version 3.0.\n"), MSG_HIST);
854 	msg_end();
855 	goto theend;
856     }
857     if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
858     {
859 	EMSG2(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname);
860 	goto theend;
861     }
862     if (b0_magic_wrong(b0p))
863     {
864 	msg_start();
865 	msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
866 #if defined(MSDOS) || defined(MSWIN)
867 	if (STRNCMP(b0p->b0_hname, "PC ", 3) == 0)
868 	    MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"),
869 							     attr | MSG_HIST);
870 	else
871 #endif
872 	    MSG_PUTS_ATTR(_(" cannot be used on this computer.\n"),
873 							     attr | MSG_HIST);
874 	MSG_PUTS_ATTR(_("The file was created on "), attr | MSG_HIST);
875 	/* avoid going past the end of a currupted hostname */
876 	b0p->b0_fname[0] = NUL;
877 	MSG_PUTS_ATTR(b0p->b0_hname, attr | MSG_HIST);
878 	MSG_PUTS_ATTR(_(",\nor the file has been damaged."), attr | MSG_HIST);
879 	msg_end();
880 	goto theend;
881     }
882     /*
883      * If we guessed the wrong page size, we have to recalculate the
884      * highest block number in the file.
885      */
886     if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size))
887     {
888 	mf_new_page_size(mfp, (unsigned)char_to_long(b0p->b0_page_size));
889 	if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
890 	    mfp->mf_blocknr_max = 0;	    /* no file or empty file */
891 	else
892 	    mfp->mf_blocknr_max = (blocknr_T)(size / mfp->mf_page_size);
893 	mfp->mf_infile_count = mfp->mf_blocknr_max;
894     }
895 
896 /*
897  * If .swp file name given directly, use name from swap file for buffer.
898  */
899     if (directly)
900     {
901 	expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
902 	if (setfname(curbuf, NameBuff, NULL, TRUE) == FAIL)
903 	    goto theend;
904     }
905 
906     home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, TRUE);
907     msg_str((char_u *)_("Using swap file \"%s\""), NameBuff);
908 
909     if (buf_spname(curbuf) != NULL)
910 	STRCPY(NameBuff, buf_spname(curbuf));
911     else
912 	home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, TRUE);
913     msg_str((char_u *)_("Original file \"%s\""), NameBuff);
914     msg_putchar('\n');
915 
916 /*
917  * check date of swap file and original file
918  */
919     mtime = char_to_long(b0p->b0_mtime);
920     if (curbuf->b_ffname != NULL
921 	    && mch_stat((char *)curbuf->b_ffname, &org_stat) != -1
922 	    && ((mch_stat((char *)mfp->mf_fname, &swp_stat) != -1
923 		    && org_stat.st_mtime > swp_stat.st_mtime)
924 		|| org_stat.st_mtime != mtime))
925     {
926 	EMSG(_("E308: Warning: Original file may have been changed"));
927     }
928     out_flush();
929     mf_put(mfp, hp, FALSE, FALSE);	/* release block 0 */
930     hp = NULL;
931 
932     /*
933      * Now that we are sure that the file is going to be recovered, clear the
934      * contents of the current buffer.
935      */
936     while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
937 	ml_delete((linenr_T)1, FALSE);
938 
939     /*
940      * Try reading the original file to obtain the values of 'fileformat',
941      * 'fileencoding', etc.  Ignore errors.  The text itself is not used.
942      */
943     if (curbuf->b_ffname != NULL)
944     {
945 	(void)readfile(curbuf->b_ffname, NULL, (linenr_T)0,
946 			      (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW);
947 	while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
948 	    ml_delete((linenr_T)1, FALSE);
949     }
950 
951     bnum = 1;		/* start with block 1 */
952     page_count = 1;	/* which is 1 page */
953     lnum = 0;		/* append after line 0 in curbuf */
954     line_count = 0;
955     idx = 0;		/* start with first index in block 1 */
956     error = 0;
957     buf->b_ml.ml_stack_top = 0;
958     buf->b_ml.ml_stack = NULL;
959     buf->b_ml.ml_stack_size = 0;	/* no stack yet */
960 
961     if (curbuf->b_ffname == NULL)
962 	cannot_open = TRUE;
963     else
964 	cannot_open = FALSE;
965 
966     serious_error = FALSE;
967     for ( ; !got_int; line_breakcheck())
968     {
969 	if (hp != NULL)
970 	    mf_put(mfp, hp, FALSE, FALSE);	/* release previous block */
971 
972 	/*
973 	 * get block
974 	 */
975 	if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL)
976 	{
977 	    if (bnum == 1)
978 	    {
979 		EMSG2(_("E309: Unable to read block 1 from %s"), mfp->mf_fname);
980 		goto theend;
981 	    }
982 	    ++error;
983 	    ml_append(lnum++, (char_u *)_("???MANY LINES MISSING"),
984 							    (colnr_T)0, TRUE);
985 	}
986 	else		/* there is a block */
987 	{
988 	    pp = (PTR_BL *)(hp->bh_data);
989 	    if (pp->pb_id == PTR_ID)		/* it is a pointer block */
990 	    {
991 		/* check line count when using pointer block first time */
992 		if (idx == 0 && line_count != 0)
993 		{
994 		    for (i = 0; i < (int)pp->pb_count; ++i)
995 			line_count -= pp->pb_pointer[i].pe_line_count;
996 		    if (line_count != 0)
997 		    {
998 			++error;
999 			ml_append(lnum++, (char_u *)_("???LINE COUNT WRONG"),
1000 							    (colnr_T)0, TRUE);
1001 		    }
1002 		}
1003 
1004 		if (pp->pb_count == 0)
1005 		{
1006 		    ml_append(lnum++, (char_u *)_("???EMPTY BLOCK"),
1007 							    (colnr_T)0, TRUE);
1008 		    ++error;
1009 		}
1010 		else if (idx < (int)pp->pb_count)	/* go a block deeper */
1011 		{
1012 		    if (pp->pb_pointer[idx].pe_bnum < 0)
1013 		    {
1014 			/*
1015 			 * Data block with negative block number.
1016 			 * Try to read lines from the original file.
1017 			 * This is slow, but it works.
1018 			 */
1019 			if (!cannot_open)
1020 			{
1021 			    line_count = pp->pb_pointer[idx].pe_line_count;
1022 			    if (readfile(curbuf->b_ffname, NULL, lnum,
1023 					pp->pb_pointer[idx].pe_old_lnum - 1,
1024 					line_count, NULL, 0) == FAIL)
1025 				cannot_open = TRUE;
1026 			    else
1027 				lnum += line_count;
1028 			}
1029 			if (cannot_open)
1030 			{
1031 			    ++error;
1032 			    ml_append(lnum++, (char_u *)_("???LINES MISSING"),
1033 							    (colnr_T)0, TRUE);
1034 			}
1035 			++idx;	    /* get same block again for next index */
1036 			continue;
1037 		    }
1038 
1039 		    /*
1040 		     * going one block deeper in the tree
1041 		     */
1042 		    if ((top = ml_add_stack(buf)) < 0)	/* new entry in stack */
1043 		    {
1044 			++error;
1045 			break;		    /* out of memory */
1046 		    }
1047 		    ip = &(buf->b_ml.ml_stack[top]);
1048 		    ip->ip_bnum = bnum;
1049 		    ip->ip_index = idx;
1050 
1051 		    bnum = pp->pb_pointer[idx].pe_bnum;
1052 		    line_count = pp->pb_pointer[idx].pe_line_count;
1053 		    page_count = pp->pb_pointer[idx].pe_page_count;
1054 		    continue;
1055 		}
1056 	    }
1057 	    else	    /* not a pointer block */
1058 	    {
1059 		dp = (DATA_BL *)(hp->bh_data);
1060 		if (dp->db_id != DATA_ID)	/* block id wrong */
1061 		{
1062 		    if (bnum == 1)
1063 		    {
1064 			EMSG2(_("E310: Block 1 ID wrong (%s not a .swp file?)"),
1065 							       mfp->mf_fname);
1066 			goto theend;
1067 		    }
1068 		    ++error;
1069 		    ml_append(lnum++, (char_u *)_("???BLOCK MISSING"),
1070 							    (colnr_T)0, TRUE);
1071 		}
1072 		else
1073 		{
1074 		    /*
1075 		     * it is a data block
1076 		     * Append all the lines in this block
1077 		     */
1078 		    has_error = FALSE;
1079 			/*
1080 			 * check length of block
1081 			 * if wrong, use length in pointer block
1082 			 */
1083 		    if (page_count * mfp->mf_page_size != dp->db_txt_end)
1084 		    {
1085 			ml_append(lnum++, (char_u *)_("??? from here until ???END lines may be messed up"),
1086 							    (colnr_T)0, TRUE);
1087 			++error;
1088 			has_error = TRUE;
1089 			dp->db_txt_end = page_count * mfp->mf_page_size;
1090 		    }
1091 
1092 			/* make sure there is a NUL at the end of the block */
1093 		    *((char_u *)dp + dp->db_txt_end - 1) = NUL;
1094 
1095 			/*
1096 			 * check number of lines in block
1097 			 * if wrong, use count in data block
1098 			 */
1099 		    if (line_count != dp->db_line_count)
1100 		    {
1101 			ml_append(lnum++, (char_u *)_("??? from here until ???END lines may have been inserted/deleted"),
1102 							    (colnr_T)0, TRUE);
1103 			++error;
1104 			has_error = TRUE;
1105 		    }
1106 
1107 		    for (i = 0; i < dp->db_line_count; ++i)
1108 		    {
1109 			txt_start = (dp->db_index[i] & DB_INDEX_MASK);
1110 			if (txt_start <= HEADER_SIZE
1111 					  || txt_start >= (int)dp->db_txt_end)
1112 			{
1113 			    p = (char_u *)"???";
1114 			    ++error;
1115 			}
1116 			else
1117 			    p = (char_u *)dp + txt_start;
1118 			ml_append(lnum++, p, (colnr_T)0, TRUE);
1119 		    }
1120 		    if (has_error)
1121 			ml_append(lnum++, (char_u *)_("???END"), (colnr_T)0, TRUE);
1122 		}
1123 	    }
1124 	}
1125 
1126 	if (buf->b_ml.ml_stack_top == 0)	/* finished */
1127 	    break;
1128 
1129 	/*
1130 	 * go one block up in the tree
1131 	 */
1132 	ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
1133 	bnum = ip->ip_bnum;
1134 	idx = ip->ip_index + 1;	    /* go to next index */
1135 	page_count = 1;
1136     }
1137 
1138     /*
1139      * The dummy line from the empty buffer will now be after the last line in
1140      * the buffer. Delete it.
1141      */
1142     ml_delete(curbuf->b_ml.ml_line_count, FALSE);
1143     curbuf->b_flags |= BF_RECOVERED;
1144 
1145     recoverymode = FALSE;
1146     if (got_int)
1147 	EMSG(_("E311: Recovery Interrupted"));
1148     else if (error)
1149     {
1150 	++no_wait_return;
1151 	MSG(">>>>>>>>>>>>>");
1152 	EMSG(_("E312: Errors detected while recovering; look for lines starting with ???"));
1153 	--no_wait_return;
1154 	MSG(_("See \":help E312\" for more information."));
1155 	MSG(">>>>>>>>>>>>>");
1156     }
1157     else
1158     {
1159 	MSG(_("Recovery completed. You should check if everything is OK."));
1160 	MSG_PUTS(_("\n(You might want to write out this file under another name\n"));
1161 	MSG_PUTS(_("and run diff with the original file to check for changes)\n"));
1162 	MSG_PUTS(_("Delete the .swp file afterwards.\n\n"));
1163 	cmdline_row = msg_row;
1164     }
1165     redraw_curbuf_later(NOT_VALID);
1166 
1167 theend:
1168     recoverymode = FALSE;
1169     if (mfp != NULL)
1170     {
1171 	if (hp != NULL)
1172 	    mf_put(mfp, hp, FALSE, FALSE);
1173 	mf_close(mfp, FALSE);	    /* will also vim_free(mfp->mf_fname) */
1174     }
1175     vim_free(buf);
1176     if (serious_error && called_from_main)
1177 	ml_close(curbuf, TRUE);
1178 #ifdef FEAT_AUTOCMD
1179     else
1180     {
1181 	apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf);
1182 	apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, FALSE, curbuf);
1183     }
1184 #endif
1185     return;
1186 }
1187 
1188 /*
1189  * Find the names of swap files in current directory and the directory given
1190  * with the 'directory' option.
1191  *
1192  * Used to:
1193  * - list the swap files for "vim -r"
1194  * - count the number of swap files when recovering
1195  * - list the swap files when recovering
1196  * - find the name of the n'th swap file when recovering
1197  */
1198     int
1199 recover_names(fname, list, nr)
1200     char_u	**fname;    /* base for swap file name */
1201     int		list;	    /* when TRUE, list the swap file names */
1202     int		nr;	    /* when non-zero, return nr'th swap file name */
1203 {
1204     int		num_names;
1205     char_u	*(names[6]);
1206     char_u	*tail;
1207     char_u	*p;
1208     int		num_files;
1209     int		file_count = 0;
1210     char_u	**files;
1211     int		i;
1212     char_u	*dirp;
1213     char_u	*dir_name;
1214 
1215     if (list)
1216     {
1217 	    /* use msg() to start the scrolling properly */
1218 	msg((char_u *)_("Swap files found:"));
1219 	msg_putchar('\n');
1220     }
1221 
1222     /*
1223      * Do the loop for every directory in 'directory'.
1224      * First allocate some memory to put the directory name in.
1225      */
1226     dir_name = alloc((unsigned)STRLEN(p_dir) + 1);
1227     dirp = p_dir;
1228     while (dir_name != NULL && *dirp)
1229     {
1230 	/*
1231 	 * Isolate a directory name from *dirp and put it in dir_name (we know
1232 	 * it is large enough, so use 31000 for length).
1233 	 * Advance dirp to next directory name.
1234 	 */
1235 	(void)copy_option_part(&dirp, dir_name, 31000, ",");
1236 
1237 	if (dir_name[0] == '.' && dir_name[1] == NUL)	/* check current dir */
1238 	{
1239 	    if (fname == NULL || *fname == NULL)
1240 	    {
1241 #ifdef VMS
1242 		names[0] = vim_strsave((char_u *)"*_sw%");
1243 #else
1244 # ifdef RISCOS
1245 		names[0] = vim_strsave((char_u *)"*_sw#");
1246 # else
1247 		names[0] = vim_strsave((char_u *)"*.sw?");
1248 # endif
1249 #endif
1250 #ifdef UNIX
1251 		/* for Unix names starting with a dot are special */
1252 		names[1] = vim_strsave((char_u *)".*.sw?");
1253 		names[2] = vim_strsave((char_u *)".sw?");
1254 		num_names = 3;
1255 #else
1256 # ifdef VMS
1257 		names[1] = vim_strsave((char_u *)".*_sw%");
1258 		num_names = 2;
1259 # else
1260 		num_names = 1;
1261 # endif
1262 #endif
1263 	    }
1264 	    else
1265 		num_names = recov_file_names(names, *fname, TRUE);
1266 	}
1267 	else			    /* check directory dir_name */
1268 	{
1269 	    if (fname == NULL || *fname == NULL)
1270 	    {
1271 #ifdef VMS
1272 		names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE);
1273 #else
1274 # ifdef RISCOS
1275 		names[0] = concat_fnames(dir_name, (char_u *)"*_sw#", TRUE);
1276 # else
1277 		names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE);
1278 # endif
1279 #endif
1280 #ifdef UNIX
1281 		/* for Unix names starting with a dot are special */
1282 		names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE);
1283 		names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE);
1284 		num_names = 3;
1285 #else
1286 # ifdef VMS
1287 		names[1] = concat_fnames(dir_name, (char_u *)".*_sw%", TRUE);
1288 		num_names = 2;
1289 # else
1290 		num_names = 1;
1291 # endif
1292 #endif
1293 	    }
1294 	    else
1295 	    {
1296 #if defined(UNIX) || defined(WIN3264)
1297 		p = dir_name + STRLEN(dir_name);
1298 		if (vim_ispathsep(p[-1]) && p[-1] == p[-2])
1299 		{
1300 		    /* Ends with '//', Use Full path for swap name */
1301 		    tail = make_percent_swname(dir_name, *fname);
1302 		}
1303 		else
1304 #endif
1305 		{
1306 		    tail = gettail(*fname);
1307 		    tail = concat_fnames(dir_name, tail, TRUE);
1308 		}
1309 		if (tail == NULL)
1310 		    num_names = 0;
1311 		else
1312 		{
1313 		    num_names = recov_file_names(names, tail, FALSE);
1314 		    vim_free(tail);
1315 		}
1316 	    }
1317 	}
1318 
1319 	    /* check for out-of-memory */
1320 	for (i = 0; i < num_names; ++i)
1321 	{
1322 	    if (names[i] == NULL)
1323 	    {
1324 		for (i = 0; i < num_names; ++i)
1325 		    vim_free(names[i]);
1326 		num_names = 0;
1327 	    }
1328 	}
1329 	if (num_names == 0)
1330 	    num_files = 0;
1331 	else if (expand_wildcards(num_names, names, &num_files, &files,
1332 					EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL)
1333 	    num_files = 0;
1334 
1335 	/*
1336 	 * When no swap file found, wildcard expansion might have failed (e.g.
1337 	 * not able to execute the shell).
1338 	 * Try finding a swap file by simply adding ".swp" to the file name.
1339 	 */
1340 	if (*dirp == NUL && file_count + num_files == 0
1341 					   && fname != NULL && *fname != NULL)
1342 	{
1343 	    struct stat	    st;
1344 	    char_u	    *swapname;
1345 
1346 #if defined(VMS) || defined(RISCOS)
1347 	    swapname = modname(*fname, (char_u *)"_swp", FALSE);
1348 #else
1349 	    swapname = modname(*fname, (char_u *)".swp", TRUE);
1350 #endif
1351 	    if (swapname != NULL)
1352 	    {
1353 		if (mch_stat((char *)swapname, &st) != -1)	    /* It exists! */
1354 		{
1355 		    files = (char_u **)alloc((unsigned)sizeof(char_u *));
1356 		    if (files != NULL)
1357 		    {
1358 			files[0] = swapname;
1359 			swapname = NULL;
1360 			num_files = 1;
1361 		    }
1362 		}
1363 		vim_free(swapname);
1364 	    }
1365 	}
1366 
1367 	/*
1368 	 * remove swapfile name of the current buffer, it must be ignored
1369 	 */
1370 	if (curbuf->b_ml.ml_mfp != NULL
1371 			       && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
1372 	{
1373 	    for (i = 0; i < num_files; ++i)
1374 		if (fullpathcmp(p, files[i], TRUE) & FPC_SAME)
1375 		{
1376 		    vim_free(files[i]);
1377 		    --num_files;
1378 		    for ( ; i < num_files; ++i)
1379 			files[i] = files[i + 1];
1380 		}
1381 	}
1382 	if (nr)
1383 	{
1384 	    file_count += num_files;
1385 	    if (nr <= file_count)
1386 	    {
1387 		*fname = vim_strsave(files[nr - 1 + num_files - file_count]);
1388 		dirp = (char_u *)"";		    /* stop searching */
1389 	    }
1390 	}
1391 	else if (list)
1392 	{
1393 	    if (dir_name[0] == '.' && dir_name[1] == NUL)
1394 	    {
1395 		if (fname == NULL || *fname == NULL)
1396 		    MSG_PUTS(_("   In current directory:\n"));
1397 		else
1398 		    MSG_PUTS(_("   Using specified name:\n"));
1399 	    }
1400 	    else
1401 	    {
1402 		MSG_PUTS(_("   In directory "));
1403 		msg_home_replace(dir_name);
1404 		MSG_PUTS(":\n");
1405 	    }
1406 
1407 	    if (num_files)
1408 	    {
1409 		for (i = 0; i < num_files; ++i)
1410 		{
1411 		    /* print the swap file name */
1412 		    msg_outnum((long)++file_count);
1413 		    MSG_PUTS(".    ");
1414 		    msg_puts(gettail(files[i]));
1415 		    msg_putchar('\n');
1416 		    (void)swapfile_info(files[i]);
1417 		}
1418 	    }
1419 	    else
1420 		MSG_PUTS(_("      -- none --\n"));
1421 	    out_flush();
1422 	}
1423 	else
1424 	    file_count += num_files;
1425 
1426 	for (i = 0; i < num_names; ++i)
1427 	    vim_free(names[i]);
1428 	FreeWild(num_files, files);
1429     }
1430     vim_free(dir_name);
1431     return file_count;
1432 }
1433 
1434 #if defined(UNIX) || defined(WIN3264)  /* Need _very_ long file names */
1435 /*
1436  * Append the full path to name with path separators made into percent
1437  * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
1438  */
1439     static char_u *
1440 make_percent_swname(dir, name)
1441     char_u	*dir;
1442     char_u	*name;
1443 {
1444     char_u *d, *s, *f, *p;
1445 
1446     f = fix_fname(name != NULL ? name : (char_u *) "");
1447     d = NULL;
1448     if (f != NULL)
1449     {
1450 	s = alloc((unsigned)(STRLEN(f) + 1));
1451 	if (s != NULL)
1452 	{
1453 	    for (d = s, p = f; *p; p++, d++)
1454 		*d = vim_ispathsep(*p) ? '%' : *p;
1455 	    *d = 0;
1456 	    d = concat_fnames(dir, s, TRUE);
1457 	    vim_free(s);
1458 	}
1459 	vim_free(f);
1460     }
1461     return d;
1462 }
1463 #endif
1464 
1465 #if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
1466 static int process_still_running;
1467 #endif
1468 
1469 /*
1470  * Give information about an existing swap file
1471  * Returns timestamp (0 when unknown).
1472  */
1473     static time_t
1474 swapfile_info(fname)
1475     char_u	*fname;
1476 {
1477     struct stat	    st;
1478     int		    fd;
1479     struct block0   b0;
1480     time_t	    x = (time_t)0;
1481 #ifdef UNIX
1482     char_u	    uname[B0_UNAME_SIZE];
1483 #endif
1484 
1485     /* print the swap file date */
1486     if (mch_stat((char *)fname, &st) != -1)
1487     {
1488 #ifdef UNIX
1489 	/* print name of owner of the file */
1490 	if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK)
1491 	{
1492 	    MSG_PUTS(_("          owned by: "));
1493 	    msg_outtrans(uname);
1494 	    MSG_PUTS(_("   dated: "));
1495 	}
1496 	else
1497 #endif
1498 	    MSG_PUTS(_("             dated: "));
1499 	x = st.st_mtime;		    /* Manx C can't do &st.st_mtime */
1500 	MSG_PUTS(ctime(&x));		    /* includes '\n' */
1501 
1502     }
1503 
1504     /*
1505      * print the original file name
1506      */
1507     fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
1508     if (fd >= 0)
1509     {
1510 	if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
1511 	{
1512 	    if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0)
1513 	    {
1514 		MSG_PUTS(_("         [from Vim version 3.0]"));
1515 	    }
1516 	    else if (b0.b0_id[0] != BLOCK0_ID0 || b0.b0_id[1] != BLOCK0_ID1)
1517 	    {
1518 		MSG_PUTS(_("         [does not look like a Vim swap file]"));
1519 	    }
1520 	    else
1521 	    {
1522 		MSG_PUTS(_("         file name: "));
1523 		if (b0.b0_fname[0] == NUL)
1524 		    MSG_PUTS(_("[No Name]"));
1525 		else
1526 		    msg_outtrans(b0.b0_fname);
1527 
1528 		MSG_PUTS(_("\n          modified: "));
1529 		MSG_PUTS(b0.b0_dirty ? _("YES") : _("no"));
1530 
1531 		if (*(b0.b0_uname) != NUL)
1532 		{
1533 		    MSG_PUTS(_("\n         user name: "));
1534 		    msg_outtrans(b0.b0_uname);
1535 		}
1536 
1537 		if (*(b0.b0_hname) != NUL)
1538 		{
1539 		    if (*(b0.b0_uname) != NUL)
1540 			MSG_PUTS(_("   host name: "));
1541 		    else
1542 			MSG_PUTS(_("\n         host name: "));
1543 		    msg_outtrans(b0.b0_hname);
1544 		}
1545 
1546 		if (char_to_long(b0.b0_pid) != 0L)
1547 		{
1548 		    MSG_PUTS(_("\n        process ID: "));
1549 		    msg_outnum(char_to_long(b0.b0_pid));
1550 #if defined(UNIX) || defined(__EMX__)
1551 		    /* EMX kill() not working correctly, it seems */
1552 		    if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
1553 		    {
1554 			MSG_PUTS(_(" (still running)"));
1555 # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
1556 			process_still_running = TRUE;
1557 # endif
1558 		    }
1559 #endif
1560 		}
1561 
1562 		if (b0_magic_wrong(&b0))
1563 		{
1564 #if defined(MSDOS) || defined(MSWIN)
1565 		    if (STRNCMP(b0.b0_hname, "PC ", 3) == 0)
1566 			MSG_PUTS(_("\n         [not usable with this version of Vim]"));
1567 		    else
1568 #endif
1569 			MSG_PUTS(_("\n         [not usable on this computer]"));
1570 		}
1571 	    }
1572 	}
1573 	else
1574 	    MSG_PUTS(_("         [cannot be read]"));
1575 	close(fd);
1576     }
1577     else
1578 	MSG_PUTS(_("         [cannot be opened]"));
1579     msg_putchar('\n');
1580 
1581     return x;
1582 }
1583 
1584     static int
1585 recov_file_names(names, path, prepend_dot)
1586     char_u	**names;
1587     char_u	*path;
1588     int		prepend_dot;
1589 {
1590     int		num_names;
1591 
1592 #ifdef SHORT_FNAME
1593     /*
1594      * (MS-DOS) always short names
1595      */
1596     names[0] = modname(path, (char_u *)".sw?", FALSE);
1597     num_names = 1;
1598 #else /* !SHORT_FNAME */
1599     /*
1600      * (Win32 and Win64) never short names, but do prepend a dot.
1601      * (Not MS-DOS or Win32 or Win64) maybe short name, maybe not: Try both.
1602      * Only use the short name if it is different.
1603      */
1604     char_u	*p;
1605     int		i;
1606 # ifndef WIN3264
1607     int	    shortname = curbuf->b_shortname;
1608 
1609     curbuf->b_shortname = FALSE;
1610 # endif
1611 
1612     num_names = 0;
1613 
1614     /*
1615      * May also add the file name with a dot prepended, for swap file in same
1616      * dir as original file.
1617      */
1618     if (prepend_dot)
1619     {
1620 	names[num_names] = modname(path, (char_u *)".sw?", TRUE);
1621 	if (names[num_names] == NULL)
1622 	    goto end;
1623 	++num_names;
1624     }
1625 
1626     /*
1627      * Form the normal swap file name pattern by appending ".sw?".
1628      */
1629 #ifdef VMS
1630     names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE);
1631 #else
1632 # ifdef RISCOS
1633     names[num_names] = concat_fnames(path, (char_u *)"_sw#", FALSE);
1634 # else
1635     names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE);
1636 # endif
1637 #endif
1638     if (names[num_names] == NULL)
1639 	goto end;
1640     if (num_names >= 1)	    /* check if we have the same name twice */
1641     {
1642 	p = names[num_names - 1];
1643 	i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]);
1644 	if (i > 0)
1645 	    p += i;	    /* file name has been expanded to full path */
1646 
1647 	if (STRCMP(p, names[num_names]) != 0)
1648 	    ++num_names;
1649 	else
1650 	    vim_free(names[num_names]);
1651     }
1652     else
1653 	++num_names;
1654 
1655 # ifndef WIN3264
1656     /*
1657      * Also try with 'shortname' set, in case the file is on a DOS filesystem.
1658      */
1659     curbuf->b_shortname = TRUE;
1660 #ifdef VMS
1661     names[num_names] = modname(path, (char_u *)"_sw%", FALSE);
1662 #else
1663 # ifdef RISCOS
1664     names[num_names] = modname(path, (char_u *)"_sw#", FALSE);
1665 # else
1666     names[num_names] = modname(path, (char_u *)".sw?", FALSE);
1667 # endif
1668 #endif
1669     if (names[num_names] == NULL)
1670 	goto end;
1671 
1672     /*
1673      * Remove the one from 'shortname', if it's the same as with 'noshortname'.
1674      */
1675     p = names[num_names];
1676     i = STRLEN(names[num_names]) - STRLEN(names[num_names - 1]);
1677     if (i > 0)
1678 	p += i;		/* file name has been expanded to full path */
1679     if (STRCMP(names[num_names - 1], p) == 0)
1680 	vim_free(names[num_names]);
1681     else
1682 	++num_names;
1683 # endif
1684 
1685 end:
1686 # ifndef WIN3264
1687     curbuf->b_shortname = shortname;
1688 # endif
1689 
1690 #endif /* !SHORT_FNAME */
1691 
1692     return num_names;
1693 }
1694 
1695 /*
1696  * sync all memlines
1697  *
1698  * If 'check_file' is TRUE, check if original file exists and was not changed.
1699  * If 'check_char' is TRUE, stop syncing when character becomes available, but
1700  * always sync at least one block.
1701  */
1702     void
1703 ml_sync_all(check_file, check_char)
1704     int	    check_file;
1705     int	    check_char;
1706 {
1707     buf_T		*buf;
1708     struct stat		st;
1709 
1710     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
1711     {
1712 	if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
1713 	    continue;			    /* no file */
1714 
1715 	ml_flush_line(buf);		    /* flush buffered line */
1716 					    /* flush locked block */
1717 	(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);
1718 	if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
1719 						     && buf->b_ffname != NULL)
1720 	{
1721 	    /*
1722 	     * If the original file does not exist anymore or has been changed
1723 	     * call ml_preserve() to get rid of all negative numbered blocks.
1724 	     */
1725 	    if (mch_stat((char *)buf->b_ffname, &st) == -1
1726 		    || st.st_mtime != buf->b_mtime_read
1727 		    || (size_t)st.st_size != buf->b_orig_size)
1728 	    {
1729 		ml_preserve(buf, FALSE);
1730 		did_check_timestamps = FALSE;
1731 		need_check_timestamps = TRUE;	/* give message later */
1732 	    }
1733 	}
1734 	if (buf->b_ml.ml_mfp->mf_dirty)
1735 	{
1736 	    (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
1737 					| (bufIsChanged(buf) ? MFS_FLUSH : 0));
1738 	    if (check_char && ui_char_avail())	/* character available now */
1739 		break;
1740 	}
1741     }
1742 }
1743 
1744 /*
1745  * sync one buffer, including negative blocks
1746  *
1747  * after this all the blocks are in the swap file
1748  *
1749  * Used for the :preserve command and when the original file has been
1750  * changed or deleted.
1751  *
1752  * when message is TRUE the success of preserving is reported
1753  */
1754     void
1755 ml_preserve(buf, message)
1756     buf_T	*buf;
1757     int		message;
1758 {
1759     bhdr_T	*hp;
1760     linenr_T	lnum;
1761     memfile_T	*mfp = buf->b_ml.ml_mfp;
1762     int		status;
1763     int		got_int_save = got_int;
1764 
1765     if (mfp == NULL || mfp->mf_fname == NULL)
1766     {
1767 	if (message)
1768 	    EMSG(_("E313: Cannot preserve, there is no swap file"));
1769 	return;
1770     }
1771 
1772     /* We only want to stop when interrupted here, not when interrupted
1773      * before. */
1774     got_int = FALSE;
1775 
1776     ml_flush_line(buf);				    /* flush buffered line */
1777     (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */
1778     status = mf_sync(mfp, MFS_ALL | MFS_FLUSH);
1779 
1780     /* stack is invalid after mf_sync(.., MFS_ALL) */
1781     buf->b_ml.ml_stack_top = 0;
1782 
1783     /*
1784      * Some of the data blocks may have been changed from negative to
1785      * positive block number. In that case the pointer blocks need to be
1786      * updated.
1787      *
1788      * We don't know in which pointer block the references are, so we visit
1789      * all data blocks until there are no more translations to be done (or
1790      * we hit the end of the file, which can only happen in case a write fails,
1791      * e.g. when file system if full).
1792      * ml_find_line() does the work by translating the negative block numbers
1793      * when getting the first line of each data block.
1794      */
1795     if (mf_need_trans(mfp) && !got_int)
1796     {
1797 	lnum = 1;
1798 	while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count)
1799 	{
1800 	    hp = ml_find_line(buf, lnum, ML_FIND);
1801 	    if (hp == NULL)
1802 	    {
1803 		status = FAIL;
1804 		goto theend;
1805 	    }
1806 	    CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
1807 	    lnum = buf->b_ml.ml_locked_high + 1;
1808 	}
1809 	(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);	/* flush locked block */
1810 	/* sync the updated pointer blocks */
1811 	if (mf_sync(mfp, MFS_ALL | MFS_FLUSH) == FAIL)
1812 	    status = FAIL;
1813 	buf->b_ml.ml_stack_top = 0;	    /* stack is invalid now */
1814     }
1815 theend:
1816     got_int |= got_int_save;
1817 
1818     if (message)
1819     {
1820 	if (status == OK)
1821 	    MSG(_("File preserved"));
1822 	else
1823 	    EMSG(_("E314: Preserve failed"));
1824     }
1825 }
1826 
1827 /*
1828  * NOTE: The pointer returned by the ml_get_*() functions only remains valid
1829  * until the next call!
1830  *  line1 = ml_get(1);
1831  *  line2 = ml_get(2);	// line1 is now invalid!
1832  * Make a copy of the line if necessary.
1833  */
1834 /*
1835  * get a pointer to a (read-only copy of a) line
1836  *
1837  * On failure an error message is given and IObuff is returned (to avoid
1838  * having to check for error everywhere).
1839  */
1840     char_u  *
1841 ml_get(lnum)
1842     linenr_T	lnum;
1843 {
1844     return ml_get_buf(curbuf, lnum, FALSE);
1845 }
1846 
1847 /*
1848  * ml_get_pos: get pointer to position 'pos'
1849  */
1850     char_u *
1851 ml_get_pos(pos)
1852     pos_T	*pos;
1853 {
1854     return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
1855 }
1856 
1857 /*
1858  * ml_get_curline: get pointer to cursor line.
1859  */
1860     char_u *
1861 ml_get_curline()
1862 {
1863     return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE);
1864 }
1865 
1866 /*
1867  * ml_get_cursor: get pointer to cursor position
1868  */
1869     char_u *
1870 ml_get_cursor()
1871 {
1872     return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
1873 							curwin->w_cursor.col);
1874 }
1875 
1876 /*
1877  * get a pointer to a line in a specific buffer
1878  *
1879  * "will_change": if TRUE mark the buffer dirty (chars in the line will be
1880  * changed)
1881  */
1882     char_u  *
1883 ml_get_buf(buf, lnum, will_change)
1884     buf_T	*buf;
1885     linenr_T	lnum;
1886     int		will_change;		/* line will be changed */
1887 {
1888     bhdr_T    *hp;
1889     DATA_BL *dp;
1890     char_u  *ptr;
1891 
1892     if (lnum > buf->b_ml.ml_line_count)	/* invalid line number */
1893     {
1894 	EMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum);
1895 errorret:
1896 	STRCPY(IObuff, "???");
1897 	return IObuff;
1898     }
1899     if (lnum <= 0)			/* pretend line 0 is line 1 */
1900 	lnum = 1;
1901 
1902     if (buf->b_ml.ml_mfp == NULL)	/* there are no lines */
1903 	return (char_u *)"";
1904 
1905 /*
1906  * See if it is the same line as requested last time.
1907  * Otherwise may need to flush last used line.
1908  */
1909     if (buf->b_ml.ml_line_lnum != lnum)
1910     {
1911 	ml_flush_line(buf);
1912 
1913 	/*
1914 	 * Find the data block containing the line.
1915 	 * This also fills the stack with the blocks from the root to the data
1916 	 * block and releases any locked block.
1917 	 */
1918 	if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
1919 	{
1920 	    EMSGN(_("E316: ml_get: cannot find line %ld"), lnum);
1921 	    goto errorret;
1922 	}
1923 
1924 	dp = (DATA_BL *)(hp->bh_data);
1925 
1926 	ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
1927 	buf->b_ml.ml_line_ptr = ptr;
1928 	buf->b_ml.ml_line_lnum = lnum;
1929 	buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
1930     }
1931     if (will_change)
1932 	buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
1933 
1934     return buf->b_ml.ml_line_ptr;
1935 }
1936 
1937 /*
1938  * Check if a line that was just obtained by a call to ml_get
1939  * is in allocated memory.
1940  */
1941     int
1942 ml_line_alloced()
1943 {
1944     return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
1945 }
1946 
1947 /*
1948  * Append a line after lnum (may be 0 to insert a line in front of the file).
1949  * "line" does not need to be allocated, but can't be another line in a
1950  * buffer, unlocking may make it invalid.
1951  *
1952  *   newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
1953  *		will be set for recovery
1954  * Check: The caller of this function should probably also call
1955  * appended_lines().
1956  *
1957  * return FAIL for failure, OK otherwise
1958  */
1959     int
1960 ml_append(lnum, line, len, newfile)
1961     linenr_T	lnum;		/* append after this line (can be 0) */
1962     char_u	*line;		/* text of the new line */
1963     colnr_T	len;		/* length of new line, including NUL, or 0 */
1964     int		newfile;	/* flag, see above */
1965 {
1966     /* When starting up, we might still need to create the memfile */
1967     if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
1968 	return FAIL;
1969 
1970     if (curbuf->b_ml.ml_line_lnum != 0)
1971 	ml_flush_line(curbuf);
1972     return ml_append_int(curbuf, lnum, line, len, newfile, FALSE);
1973 }
1974 
1975     static int
1976 ml_append_int(buf, lnum, line, len, newfile, mark)
1977     buf_T	*buf;
1978     linenr_T	lnum;		/* append after this line (can be 0) */
1979     char_u	*line;		/* text of the new line */
1980     colnr_T	len;		/* length of line, including NUL, or 0 */
1981     int		newfile;	/* flag, see above */
1982     int		mark;		/* mark the new line */
1983 {
1984     int		i;
1985     int		line_count;	/* number of indexes in current block */
1986     int		offset;
1987     int		from, to;
1988     int		space_needed;	/* space needed for new line */
1989     int		page_size;
1990     int		page_count;
1991     int		db_idx;		/* index for lnum in data block */
1992     bhdr_T	*hp;
1993     memfile_T	*mfp;
1994     DATA_BL	*dp;
1995     PTR_BL	*pp;
1996     infoptr_T	*ip;
1997 
1998 					/* lnum out of range */
1999     if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
2000 	return FAIL;
2001 
2002     if (lowest_marked && lowest_marked > lnum)
2003 	lowest_marked = lnum + 1;
2004 
2005     if (len == 0)
2006 	len = (colnr_T)STRLEN(line) + 1;	/* space needed for the text */
2007     space_needed = len + INDEX_SIZE;	/* space needed for text + index */
2008 
2009     mfp = buf->b_ml.ml_mfp;
2010     page_size = mfp->mf_page_size;
2011 
2012 /*
2013  * find the data block containing the previous line
2014  * This also fills the stack with the blocks from the root to the data block
2015  * This also releases any locked block.
2016  */
2017     if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum,
2018 							  ML_INSERT)) == NULL)
2019 	return FAIL;
2020 
2021     buf->b_ml.ml_flags &= ~ML_EMPTY;
2022 
2023     if (lnum == 0)		/* got line one instead, correct db_idx */
2024 	db_idx = -1;		/* careful, it is negative! */
2025     else
2026 	db_idx = lnum - buf->b_ml.ml_locked_low;
2027 		/* get line count before the insertion */
2028     line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
2029 
2030     dp = (DATA_BL *)(hp->bh_data);
2031 
2032 /*
2033  * If
2034  * - there is not enough room in the current block
2035  * - appending to the last line in the block
2036  * - not appending to the last line in the file
2037  * insert in front of the next block.
2038  */
2039     if ((int)dp->db_free < space_needed && db_idx == line_count - 1
2040 					    && lnum < buf->b_ml.ml_line_count)
2041     {
2042 	/*
2043 	 * Now that the line is not going to be inserted in the block that we
2044 	 * expected, the line count has to be adjusted in the pointer blocks
2045 	 * by using ml_locked_lineadd.
2046 	 */
2047 	--(buf->b_ml.ml_locked_lineadd);
2048 	--(buf->b_ml.ml_locked_high);
2049 	if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
2050 	    return FAIL;
2051 
2052 	db_idx = -1;		    /* careful, it is negative! */
2053 		    /* get line count before the insertion */
2054 	line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
2055 	CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1");
2056 
2057 	dp = (DATA_BL *)(hp->bh_data);
2058     }
2059 
2060     ++buf->b_ml.ml_line_count;
2061 
2062     if ((int)dp->db_free >= space_needed)	/* enough room in data block */
2063     {
2064 /*
2065  * Insert new line in existing data block, or in data block allocated above.
2066  */
2067 	dp->db_txt_start -= len;
2068 	dp->db_free -= space_needed;
2069 	++(dp->db_line_count);
2070 
2071 	/*
2072 	 * move the text of the lines that follow to the front
2073 	 * adjust the indexes of the lines that follow
2074 	 */
2075 	if (line_count > db_idx + 1)	    /* if there are following lines */
2076 	{
2077 	    /*
2078 	     * Offset is the start of the previous line.
2079 	     * This will become the character just after the new line.
2080 	     */
2081 	    if (db_idx < 0)
2082 		offset = dp->db_txt_end;
2083 	    else
2084 		offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK);
2085 	    mch_memmove((char *)dp + dp->db_txt_start,
2086 					  (char *)dp + dp->db_txt_start + len,
2087 				 (size_t)(offset - (dp->db_txt_start + len)));
2088 	    for (i = line_count - 1; i > db_idx; --i)
2089 		dp->db_index[i + 1] = dp->db_index[i] - len;
2090 	    dp->db_index[db_idx + 1] = offset - len;
2091 	}
2092 	else				    /* add line at the end */
2093 	    dp->db_index[db_idx + 1] = dp->db_txt_start;
2094 
2095 	/*
2096 	 * copy the text into the block
2097 	 */
2098 	mch_memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len);
2099 	if (mark)
2100 	    dp->db_index[db_idx + 1] |= DB_MARKED;
2101 
2102 	/*
2103 	 * Mark the block dirty.
2104 	 */
2105 	buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2106 	if (!newfile)
2107 	    buf->b_ml.ml_flags |= ML_LOCKED_POS;
2108     }
2109     else	    /* not enough space in data block */
2110     {
2111 /*
2112  * If there is not enough room we have to create a new data block and copy some
2113  * lines into it.
2114  * Then we have to insert an entry in the pointer block.
2115  * If this pointer block also is full, we go up another block, and so on, up
2116  * to the root if necessary.
2117  * The line counts in the pointer blocks have already been adjusted by
2118  * ml_find_line().
2119  */
2120 	long	    line_count_left, line_count_right;
2121 	int	    page_count_left, page_count_right;
2122 	bhdr_T	    *hp_left;
2123 	bhdr_T	    *hp_right;
2124 	bhdr_T	    *hp_new;
2125 	int	    lines_moved;
2126 	int	    data_moved = 0;	    /* init to shut up gcc */
2127 	int	    total_moved = 0;	    /* init to shut up gcc */
2128 	DATA_BL	    *dp_right, *dp_left;
2129 	int	    stack_idx;
2130 	int	    in_left;
2131 	int	    lineadd;
2132 	blocknr_T   bnum_left, bnum_right;
2133 	linenr_T    lnum_left, lnum_right;
2134 	int	    pb_idx;
2135 	PTR_BL	    *pp_new;
2136 
2137 	/*
2138 	 * We are going to allocate a new data block. Depending on the
2139 	 * situation it will be put to the left or right of the existing
2140 	 * block.  If possible we put the new line in the left block and move
2141 	 * the lines after it to the right block. Otherwise the new line is
2142 	 * also put in the right block. This method is more efficient when
2143 	 * inserting a lot of lines at one place.
2144 	 */
2145 	if (db_idx < 0)		/* left block is new, right block is existing */
2146 	{
2147 	    lines_moved = 0;
2148 	    in_left = TRUE;
2149 	    /* space_needed does not change */
2150 	}
2151 	else			/* left block is existing, right block is new */
2152 	{
2153 	    lines_moved = line_count - db_idx - 1;
2154 	    if (lines_moved == 0)
2155 		in_left = FALSE;	/* put new line in right block */
2156 					/* space_needed does not change */
2157 	    else
2158 	    {
2159 		data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) -
2160 							    dp->db_txt_start;
2161 		total_moved = data_moved + lines_moved * INDEX_SIZE;
2162 		if ((int)dp->db_free + total_moved >= space_needed)
2163 		{
2164 		    in_left = TRUE;	/* put new line in left block */
2165 		    space_needed = total_moved;
2166 		}
2167 		else
2168 		{
2169 		    in_left = FALSE;	    /* put new line in right block */
2170 		    space_needed += total_moved;
2171 		}
2172 	    }
2173 	}
2174 
2175 	page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
2176 	if ((hp_new = ml_new_data(mfp, newfile, page_count)) == NULL)
2177 	{
2178 			/* correct line counts in pointer blocks */
2179 	    --(buf->b_ml.ml_locked_lineadd);
2180 	    --(buf->b_ml.ml_locked_high);
2181 	    return FAIL;
2182 	}
2183 	if (db_idx < 0)		/* left block is new */
2184 	{
2185 	    hp_left = hp_new;
2186 	    hp_right = hp;
2187 	    line_count_left = 0;
2188 	    line_count_right = line_count;
2189 	}
2190 	else			/* right block is new */
2191 	{
2192 	    hp_left = hp;
2193 	    hp_right = hp_new;
2194 	    line_count_left = line_count;
2195 	    line_count_right = 0;
2196 	}
2197 	dp_right = (DATA_BL *)(hp_right->bh_data);
2198 	dp_left = (DATA_BL *)(hp_left->bh_data);
2199 	bnum_left = hp_left->bh_bnum;
2200 	bnum_right = hp_right->bh_bnum;
2201 	page_count_left = hp_left->bh_page_count;
2202 	page_count_right = hp_right->bh_page_count;
2203 
2204 	/*
2205 	 * May move the new line into the right/new block.
2206 	 */
2207 	if (!in_left)
2208 	{
2209 	    dp_right->db_txt_start -= len;
2210 	    dp_right->db_free -= len + INDEX_SIZE;
2211 	    dp_right->db_index[0] = dp_right->db_txt_start;
2212 	    if (mark)
2213 		dp_right->db_index[0] |= DB_MARKED;
2214 
2215 	    mch_memmove((char *)dp_right + dp_right->db_txt_start,
2216 							   line, (size_t)len);
2217 	    ++line_count_right;
2218 	}
2219 	/*
2220 	 * may move lines from the left/old block to the right/new one.
2221 	 */
2222 	if (lines_moved)
2223 	{
2224 	    /*
2225 	     */
2226 	    dp_right->db_txt_start -= data_moved;
2227 	    dp_right->db_free -= total_moved;
2228 	    mch_memmove((char *)dp_right + dp_right->db_txt_start,
2229 			(char *)dp_left + dp_left->db_txt_start,
2230 			(size_t)data_moved);
2231 	    offset = dp_right->db_txt_start - dp_left->db_txt_start;
2232 	    dp_left->db_txt_start += data_moved;
2233 	    dp_left->db_free += total_moved;
2234 
2235 	    /*
2236 	     * update indexes in the new block
2237 	     */
2238 	    for (to = line_count_right, from = db_idx + 1;
2239 					 from < line_count_left; ++from, ++to)
2240 		dp_right->db_index[to] = dp->db_index[from] + offset;
2241 	    line_count_right += lines_moved;
2242 	    line_count_left -= lines_moved;
2243 	}
2244 
2245 	/*
2246 	 * May move the new line into the left (old or new) block.
2247 	 */
2248 	if (in_left)
2249 	{
2250 	    dp_left->db_txt_start -= len;
2251 	    dp_left->db_free -= len + INDEX_SIZE;
2252 	    dp_left->db_index[line_count_left] = dp_left->db_txt_start;
2253 	    if (mark)
2254 		dp_left->db_index[line_count_left] |= DB_MARKED;
2255 	    mch_memmove((char *)dp_left + dp_left->db_txt_start,
2256 							   line, (size_t)len);
2257 	    ++line_count_left;
2258 	}
2259 
2260 	if (db_idx < 0)		/* left block is new */
2261 	{
2262 	    lnum_left = lnum + 1;
2263 	    lnum_right = 0;
2264 	}
2265 	else			/* right block is new */
2266 	{
2267 	    lnum_left = 0;
2268 	    if (in_left)
2269 		lnum_right = lnum + 2;
2270 	    else
2271 		lnum_right = lnum + 1;
2272 	}
2273 	dp_left->db_line_count = line_count_left;
2274 	dp_right->db_line_count = line_count_right;
2275 
2276 	/*
2277 	 * release the two data blocks
2278 	 * The new one (hp_new) already has a correct blocknumber.
2279 	 * The old one (hp, in ml_locked) gets a positive blocknumber if
2280 	 * we changed it and we are not editing a new file.
2281 	 */
2282 	if (lines_moved || in_left)
2283 	    buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2284 	if (!newfile && db_idx >= 0 && in_left)
2285 	    buf->b_ml.ml_flags |= ML_LOCKED_POS;
2286 	mf_put(mfp, hp_new, TRUE, FALSE);
2287 
2288 	/*
2289 	 * flush the old data block
2290 	 * set ml_locked_lineadd to 0, because the updating of the
2291 	 * pointer blocks is done below
2292 	 */
2293 	lineadd = buf->b_ml.ml_locked_lineadd;
2294 	buf->b_ml.ml_locked_lineadd = 0;
2295 	ml_find_line(buf, (linenr_T)0, ML_FLUSH);   /* flush data block */
2296 
2297 	/*
2298 	 * update pointer blocks for the new data block
2299 	 */
2300 	for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0;
2301 								  --stack_idx)
2302 	{
2303 	    ip = &(buf->b_ml.ml_stack[stack_idx]);
2304 	    pb_idx = ip->ip_index;
2305 	    if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
2306 		return FAIL;
2307 	    pp = (PTR_BL *)(hp->bh_data);   /* must be pointer block */
2308 	    if (pp->pb_id != PTR_ID)
2309 	    {
2310 		EMSG(_("E317: pointer block id wrong 3"));
2311 		mf_put(mfp, hp, FALSE, FALSE);
2312 		return FAIL;
2313 	    }
2314 	    /*
2315 	     * TODO: If the pointer block is full and we are adding at the end
2316 	     * try to insert in front of the next block
2317 	     */
2318 	    /* block not full, add one entry */
2319 	    if (pp->pb_count < pp->pb_count_max)
2320 	    {
2321 		if (pb_idx + 1 < (int)pp->pb_count)
2322 		    mch_memmove(&pp->pb_pointer[pb_idx + 2],
2323 				&pp->pb_pointer[pb_idx + 1],
2324 			(size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
2325 		++pp->pb_count;
2326 		pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
2327 		pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
2328 		pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
2329 		pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
2330 		pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
2331 		pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
2332 
2333 		if (lnum_left != 0)
2334 		    pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
2335 		if (lnum_right != 0)
2336 		    pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
2337 
2338 		mf_put(mfp, hp, TRUE, FALSE);
2339 		buf->b_ml.ml_stack_top = stack_idx + 1;	    /* truncate stack */
2340 
2341 		if (lineadd)
2342 		{
2343 		    --(buf->b_ml.ml_stack_top);
2344 			/* fix line count for rest of blocks in the stack */
2345 		    ml_lineadd(buf, lineadd);
2346 							/* fix stack itself */
2347 		    buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
2348 								      lineadd;
2349 		    ++(buf->b_ml.ml_stack_top);
2350 		}
2351 
2352 		/*
2353 		 * We are finished, break the loop here.
2354 		 */
2355 		break;
2356 	    }
2357 	    else			/* pointer block full */
2358 	    {
2359 		/*
2360 		 * split the pointer block
2361 		 * allocate a new pointer block
2362 		 * move some of the pointer into the new block
2363 		 * prepare for updating the parent block
2364 		 */
2365 		for (;;)	/* do this twice when splitting block 1 */
2366 		{
2367 		    hp_new = ml_new_ptr(mfp);
2368 		    if (hp_new == NULL)	    /* TODO: try to fix tree */
2369 			return FAIL;
2370 		    pp_new = (PTR_BL *)(hp_new->bh_data);
2371 
2372 		    if (hp->bh_bnum != 1)
2373 			break;
2374 
2375 		    /*
2376 		     * if block 1 becomes full the tree is given an extra level
2377 		     * The pointers from block 1 are moved into the new block.
2378 		     * block 1 is updated to point to the new block
2379 		     * then continue to split the new block
2380 		     */
2381 		    mch_memmove(pp_new, pp, (size_t)page_size);
2382 		    pp->pb_count = 1;
2383 		    pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
2384 		    pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
2385 		    pp->pb_pointer[0].pe_old_lnum = 1;
2386 		    pp->pb_pointer[0].pe_page_count = 1;
2387 		    mf_put(mfp, hp, TRUE, FALSE);   /* release block 1 */
2388 		    hp = hp_new;		/* new block is to be split */
2389 		    pp = pp_new;
2390 		    CHECK(stack_idx != 0, _("stack_idx should be 0"));
2391 		    ip->ip_index = 0;
2392 		    ++stack_idx;	/* do block 1 again later */
2393 		}
2394 		/*
2395 		 * move the pointers after the current one to the new block
2396 		 * If there are none, the new entry will be in the new block.
2397 		 */
2398 		total_moved = pp->pb_count - pb_idx - 1;
2399 		if (total_moved)
2400 		{
2401 		    mch_memmove(&pp_new->pb_pointer[0],
2402 				&pp->pb_pointer[pb_idx + 1],
2403 				(size_t)(total_moved) * sizeof(PTR_EN));
2404 		    pp_new->pb_count = total_moved;
2405 		    pp->pb_count -= total_moved - 1;
2406 		    pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
2407 		    pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
2408 		    pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
2409 		    if (lnum_right)
2410 			pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
2411 		}
2412 		else
2413 		{
2414 		    pp_new->pb_count = 1;
2415 		    pp_new->pb_pointer[0].pe_bnum = bnum_right;
2416 		    pp_new->pb_pointer[0].pe_line_count = line_count_right;
2417 		    pp_new->pb_pointer[0].pe_page_count = page_count_right;
2418 		    pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
2419 		}
2420 		pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
2421 		pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
2422 		pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
2423 		if (lnum_left)
2424 		    pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
2425 		lnum_left = 0;
2426 		lnum_right = 0;
2427 
2428 		/*
2429 		 * recompute line counts
2430 		 */
2431 		line_count_right = 0;
2432 		for (i = 0; i < (int)pp_new->pb_count; ++i)
2433 		    line_count_right += pp_new->pb_pointer[i].pe_line_count;
2434 		line_count_left = 0;
2435 		for (i = 0; i < (int)pp->pb_count; ++i)
2436 		    line_count_left += pp->pb_pointer[i].pe_line_count;
2437 
2438 		bnum_left = hp->bh_bnum;
2439 		bnum_right = hp_new->bh_bnum;
2440 		page_count_left = 1;
2441 		page_count_right = 1;
2442 		mf_put(mfp, hp, TRUE, FALSE);
2443 		mf_put(mfp, hp_new, TRUE, FALSE);
2444 	    }
2445 	}
2446 
2447 	/*
2448 	 * Safety check: fallen out of for loop?
2449 	 */
2450 	if (stack_idx < 0)
2451 	{
2452 	    EMSG(_("E318: Updated too many blocks?"));
2453 	    buf->b_ml.ml_stack_top = 0;	/* invalidate stack */
2454 	}
2455     }
2456 
2457 #ifdef FEAT_BYTEOFF
2458     /* The line was inserted below 'lnum' */
2459     ml_updatechunk(buf, lnum + 1, (long)len, ML_CHNK_ADDLINE);
2460 #endif
2461 #ifdef FEAT_NETBEANS_INTG
2462     if (usingNetbeans)
2463     {
2464 	if (STRLEN(line) > 0)
2465 	    netbeans_inserted(buf, lnum+1, (colnr_T)0, 0, line, STRLEN(line));
2466 	netbeans_inserted(buf, lnum+1, (colnr_T)STRLEN(line), 0,
2467 							   (char_u *)"\n", 1);
2468     }
2469 #endif
2470     return OK;
2471 }
2472 
2473 /*
2474  * replace line lnum, with buffering, in current buffer
2475  *
2476  * If copy is TRUE, make a copy of the line, otherwise the line has been
2477  * copied to allocated memory already.
2478  *
2479  * Check: The caller of this function should probably also call
2480  * changed_lines(), unless update_screen(NOT_VALID) is used.
2481  *
2482  * return FAIL for failure, OK otherwise
2483  */
2484     int
2485 ml_replace(lnum, line, copy)
2486     linenr_T	lnum;
2487     char_u	*line;
2488     int		copy;
2489 {
2490     if (line == NULL)		/* just checking... */
2491 	return FAIL;
2492 
2493     /* When starting up, we might still need to create the memfile */
2494     if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
2495 	return FAIL;
2496 
2497     if (copy && (line = vim_strsave(line)) == NULL) /* allocate memory */
2498 	return FAIL;
2499 #ifdef FEAT_NETBEANS_INTG
2500     if (usingNetbeans)
2501     {
2502 	netbeans_removed(curbuf, lnum, 0, (long)STRLEN(ml_get(lnum)));
2503 	netbeans_inserted(curbuf, lnum, 0, 0, line, STRLEN(line));
2504     }
2505 #endif
2506     if (curbuf->b_ml.ml_line_lnum != lnum)	    /* other line buffered */
2507 	ml_flush_line(curbuf);			    /* flush it */
2508     else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
2509 	vim_free(curbuf->b_ml.ml_line_ptr);	    /* free it */
2510     curbuf->b_ml.ml_line_ptr = line;
2511     curbuf->b_ml.ml_line_lnum = lnum;
2512     curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
2513 
2514     return OK;
2515 }
2516 
2517 /*
2518  * delete line 'lnum'
2519  *
2520  * Check: The caller of this function should probably also call
2521  * deleted_lines() after this.
2522  *
2523  * return FAIL for failure, OK otherwise
2524  */
2525     int
2526 ml_delete(lnum, message)
2527     linenr_T	lnum;
2528     int		message;
2529 {
2530     ml_flush_line(curbuf);
2531     return ml_delete_int(curbuf, lnum, message);
2532 }
2533 
2534     static int
2535 ml_delete_int(buf, lnum, message)
2536     buf_T	*buf;
2537     linenr_T	lnum;
2538     int		message;
2539 {
2540     bhdr_T	*hp;
2541     memfile_T	*mfp;
2542     DATA_BL	*dp;
2543     PTR_BL	*pp;
2544     infoptr_T	*ip;
2545     int		count;	    /* number of entries in block */
2546     int		idx;
2547     int		stack_idx;
2548     int		text_start;
2549     int		line_start;
2550     long	line_size;
2551     int		i;
2552 
2553     if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
2554 	return FAIL;
2555 
2556     if (lowest_marked && lowest_marked > lnum)
2557 	lowest_marked--;
2558 
2559 /*
2560  * If the file becomes empty the last line is replaced by an empty line.
2561  */
2562     if (buf->b_ml.ml_line_count == 1)	    /* file becomes empty */
2563     {
2564 	if (message
2565 #ifdef FEAT_NETBEANS_INTG
2566 		&& !netbeansSuppressNoLines
2567 #endif
2568 	   )
2569 	{
2570 	    set_keep_msg((char_u *)_(no_lines_msg));
2571 	    keep_msg_attr = 0;
2572 	}
2573 	/* FEAT_BYTEOFF already handled in there, dont worry 'bout it below */
2574 	i = ml_replace((linenr_T)1, (char_u *)"", TRUE);
2575 	buf->b_ml.ml_flags |= ML_EMPTY;
2576 
2577 	return i;
2578     }
2579 
2580 /*
2581  * find the data block containing the line
2582  * This also fills the stack with the blocks from the root to the data block
2583  * This also releases any locked block.
2584  */
2585     mfp = buf->b_ml.ml_mfp;
2586     if (mfp == NULL)
2587 	return FAIL;
2588 
2589     if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL)
2590 	return FAIL;
2591 
2592     dp = (DATA_BL *)(hp->bh_data);
2593     /* compute line count before the delete */
2594     count = (long)(buf->b_ml.ml_locked_high)
2595 					- (long)(buf->b_ml.ml_locked_low) + 2;
2596     idx = lnum - buf->b_ml.ml_locked_low;
2597 
2598     --buf->b_ml.ml_line_count;
2599 
2600     line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
2601     if (idx == 0)		/* first line in block, text at the end */
2602 	line_size = dp->db_txt_end - line_start;
2603     else
2604 	line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
2605 
2606 #ifdef FEAT_NETBEANS_INTG
2607     if (usingNetbeans)
2608 	netbeans_removed(buf, lnum, 0, line_size);
2609 #endif
2610 
2611 /*
2612  * special case: If there is only one line in the data block it becomes empty.
2613  * Then we have to remove the entry, pointing to this data block, from the
2614  * pointer block. If this pointer block also becomes empty, we go up another
2615  * block, and so on, up to the root if necessary.
2616  * The line counts in the pointer blocks have already been adjusted by
2617  * ml_find_line().
2618  */
2619     if (count == 1)
2620     {
2621 	mf_free(mfp, hp);	/* free the data block */
2622 	buf->b_ml.ml_locked = NULL;
2623 
2624 	for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
2625 	{
2626 	    buf->b_ml.ml_stack_top = 0;	    /* stack is invalid when failing */
2627 	    ip = &(buf->b_ml.ml_stack[stack_idx]);
2628 	    idx = ip->ip_index;
2629 	    if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
2630 		return FAIL;
2631 	    pp = (PTR_BL *)(hp->bh_data);   /* must be pointer block */
2632 	    if (pp->pb_id != PTR_ID)
2633 	    {
2634 		EMSG(_("E317: pointer block id wrong 4"));
2635 		mf_put(mfp, hp, FALSE, FALSE);
2636 		return FAIL;
2637 	    }
2638 	    count = --(pp->pb_count);
2639 	    if (count == 0)	    /* the pointer block becomes empty! */
2640 		mf_free(mfp, hp);
2641 	    else
2642 	    {
2643 		if (count != idx)	/* move entries after the deleted one */
2644 		    mch_memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1],
2645 				      (size_t)(count - idx) * sizeof(PTR_EN));
2646 		mf_put(mfp, hp, TRUE, FALSE);
2647 
2648 		buf->b_ml.ml_stack_top = stack_idx;	/* truncate stack */
2649 		    /* fix line count for rest of blocks in the stack */
2650 		if (buf->b_ml.ml_locked_lineadd)
2651 		{
2652 		    ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
2653 		    buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
2654 						buf->b_ml.ml_locked_lineadd;
2655 		}
2656 		++(buf->b_ml.ml_stack_top);
2657 
2658 		break;
2659 	    }
2660 	}
2661 	CHECK(stack_idx < 0, _("deleted block 1?"));
2662     }
2663     else
2664     {
2665 	/*
2666 	 * delete the text by moving the next lines forwards
2667 	 */
2668 	text_start = dp->db_txt_start;
2669 	mch_memmove((char *)dp + text_start + line_size,
2670 		  (char *)dp + text_start, (size_t)(line_start - text_start));
2671 
2672 	/*
2673 	 * delete the index by moving the next indexes backwards
2674 	 * Adjust the indexes for the text movement.
2675 	 */
2676 	for (i = idx; i < count - 1; ++i)
2677 	    dp->db_index[i] = dp->db_index[i + 1] + line_size;
2678 
2679 	dp->db_free += line_size + INDEX_SIZE;
2680 	dp->db_txt_start += line_size;
2681 	--(dp->db_line_count);
2682 
2683 	/*
2684 	 * mark the block dirty and make sure it is in the file (for recovery)
2685 	 */
2686 	buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
2687     }
2688 
2689 #ifdef FEAT_BYTEOFF
2690     ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE);
2691 #endif
2692     return OK;
2693 }
2694 
2695 /*
2696  * set the B_MARKED flag for line 'lnum'
2697  */
2698     void
2699 ml_setmarked(lnum)
2700     linenr_T lnum;
2701 {
2702     bhdr_T    *hp;
2703     DATA_BL *dp;
2704 				    /* invalid line number */
2705     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count
2706 					       || curbuf->b_ml.ml_mfp == NULL)
2707 	return;			    /* give error message? */
2708 
2709     if (lowest_marked == 0 || lowest_marked > lnum)
2710 	lowest_marked = lnum;
2711 
2712     /*
2713      * find the data block containing the line
2714      * This also fills the stack with the blocks from the root to the data block
2715      * This also releases any locked block.
2716      */
2717     if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
2718 	return;		    /* give error message? */
2719 
2720     dp = (DATA_BL *)(hp->bh_data);
2721     dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED;
2722     curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2723 }
2724 
2725 /*
2726  * find the first line with its B_MARKED flag set
2727  */
2728     linenr_T
2729 ml_firstmarked()
2730 {
2731     bhdr_T	*hp;
2732     DATA_BL	*dp;
2733     linenr_T	lnum;
2734     int		i;
2735 
2736     if (curbuf->b_ml.ml_mfp == NULL)
2737 	return (linenr_T) 0;
2738 
2739     /*
2740      * The search starts with lowest_marked line. This is the last line where
2741      * a mark was found, adjusted by inserting/deleting lines.
2742      */
2743     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
2744     {
2745 	/*
2746 	 * Find the data block containing the line.
2747 	 * This also fills the stack with the blocks from the root to the data
2748 	 * block This also releases any locked block.
2749 	 */
2750 	if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
2751 	    return (linenr_T)0;		    /* give error message? */
2752 
2753 	dp = (DATA_BL *)(hp->bh_data);
2754 
2755 	for (i = lnum - curbuf->b_ml.ml_locked_low;
2756 			    lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
2757 	    if ((dp->db_index[i]) & DB_MARKED)
2758 	    {
2759 		(dp->db_index[i]) &= DB_INDEX_MASK;
2760 		curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2761 		lowest_marked = lnum + 1;
2762 		return lnum;
2763 	    }
2764     }
2765 
2766     return (linenr_T) 0;
2767 }
2768 
2769 #if 0  /* not used */
2770 /*
2771  * return TRUE if line 'lnum' has a mark
2772  */
2773     int
2774 ml_has_mark(lnum)
2775     linenr_T	lnum;
2776 {
2777     bhdr_T	*hp;
2778     DATA_BL	*dp;
2779 
2780     if (curbuf->b_ml.ml_mfp == NULL
2781 			|| (hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
2782 	return FALSE;
2783 
2784     dp = (DATA_BL *)(hp->bh_data);
2785     return (int)((dp->db_index[lnum - curbuf->b_ml.ml_locked_low]) & DB_MARKED);
2786 }
2787 #endif
2788 
2789 /*
2790  * clear all DB_MARKED flags
2791  */
2792     void
2793 ml_clearmarked()
2794 {
2795     bhdr_T	*hp;
2796     DATA_BL	*dp;
2797     linenr_T	lnum;
2798     int		i;
2799 
2800     if (curbuf->b_ml.ml_mfp == NULL)	    /* nothing to do */
2801 	return;
2802 
2803     /*
2804      * The search starts with line lowest_marked.
2805      */
2806     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
2807     {
2808 	/*
2809 	 * Find the data block containing the line.
2810 	 * This also fills the stack with the blocks from the root to the data
2811 	 * block and releases any locked block.
2812 	 */
2813 	if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
2814 	    return;		/* give error message? */
2815 
2816 	dp = (DATA_BL *)(hp->bh_data);
2817 
2818 	for (i = lnum - curbuf->b_ml.ml_locked_low;
2819 			    lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
2820 	    if ((dp->db_index[i]) & DB_MARKED)
2821 	    {
2822 		(dp->db_index[i]) &= DB_INDEX_MASK;
2823 		curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2824 	    }
2825     }
2826 
2827     lowest_marked = 0;
2828     return;
2829 }
2830 
2831 /*
2832  * flush ml_line if necessary
2833  */
2834     static void
2835 ml_flush_line(buf)
2836     buf_T	*buf;
2837 {
2838     bhdr_T	*hp;
2839     DATA_BL	*dp;
2840     linenr_T	lnum;
2841     char_u	*new_line;
2842     char_u	*old_line;
2843     colnr_T	new_len;
2844     int		old_len;
2845     int		extra;
2846     int		idx;
2847     int		start;
2848     int		count;
2849     int		i;
2850 
2851     if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL)
2852 	return;		/* nothing to do */
2853 
2854     if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
2855     {
2856 	lnum = buf->b_ml.ml_line_lnum;
2857 	new_line = buf->b_ml.ml_line_ptr;
2858 
2859 	hp = ml_find_line(buf, lnum, ML_FIND);
2860 	if (hp == NULL)
2861 	    EMSGN(_("E320: Cannot find line %ld"), lnum);
2862 	else
2863 	{
2864 	    dp = (DATA_BL *)(hp->bh_data);
2865 	    idx = lnum - buf->b_ml.ml_locked_low;
2866 	    start = ((dp->db_index[idx]) & DB_INDEX_MASK);
2867 	    old_line = (char_u *)dp + start;
2868 	    if (idx == 0)	/* line is last in block */
2869 		old_len = dp->db_txt_end - start;
2870 	    else		/* text of previous line follows */
2871 		old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
2872 	    new_len = (colnr_T)STRLEN(new_line) + 1;
2873 	    extra = new_len - old_len;	    /* negative if lines gets smaller */
2874 
2875 	    /*
2876 	     * if new line fits in data block, replace directly
2877 	     */
2878 	    if ((int)dp->db_free >= extra)
2879 	    {
2880 		/* if the length changes and there are following lines */
2881 		count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
2882 		if (extra != 0 && idx < count - 1)
2883 		{
2884 		    /* move text of following lines */
2885 		    mch_memmove((char *)dp + dp->db_txt_start - extra,
2886 				(char *)dp + dp->db_txt_start,
2887 				(size_t)(start - dp->db_txt_start));
2888 
2889 		    /* adjust pointers of this and following lines */
2890 		    for (i = idx + 1; i < count; ++i)
2891 			dp->db_index[i] -= extra;
2892 		}
2893 		dp->db_index[idx] -= extra;
2894 
2895 		/* adjust free space */
2896 		dp->db_free -= extra;
2897 		dp->db_txt_start -= extra;
2898 
2899 		/* copy new line into the data block */
2900 		mch_memmove(old_line - extra, new_line, (size_t)new_len);
2901 		buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
2902 #ifdef FEAT_BYTEOFF
2903 		/* The else case is already covered by the insert and delete */
2904 		ml_updatechunk(buf, lnum, (long)extra, ML_CHNK_UPDLINE);
2905 #endif
2906 	    }
2907 	    else
2908 	    {
2909 		/*
2910 		 * Cannot do it in one data block: Delete and append.
2911 		 * Append first, because ml_delete_int() cannot delete the
2912 		 * last line in a buffer, which causes trouble for a buffer
2913 		 * that has only one line.
2914 		 * Don't forget to copy the mark!
2915 		 */
2916 		/* How about handling errors??? */
2917 		(void)ml_append_int(buf, lnum, new_line, new_len, FALSE,
2918 					     (dp->db_index[idx] & DB_MARKED));
2919 		(void)ml_delete_int(buf, lnum, FALSE);
2920 	    }
2921 	}
2922 	vim_free(new_line);
2923     }
2924 
2925     buf->b_ml.ml_line_lnum = 0;
2926 }
2927 
2928 /*
2929  * create a new, empty, data block
2930  */
2931     static bhdr_T *
2932 ml_new_data(mfp, negative, page_count)
2933     memfile_T	*mfp;
2934     int		negative;
2935     int		page_count;
2936 {
2937     bhdr_T	*hp;
2938     DATA_BL	*dp;
2939 
2940     if ((hp = mf_new(mfp, negative, page_count)) == NULL)
2941 	return NULL;
2942 
2943     dp = (DATA_BL *)(hp->bh_data);
2944     dp->db_id = DATA_ID;
2945     dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size;
2946     dp->db_free = dp->db_txt_start - HEADER_SIZE;
2947     dp->db_line_count = 0;
2948 
2949     return hp;
2950 }
2951 
2952 /*
2953  * create a new, empty, pointer block
2954  */
2955     static bhdr_T *
2956 ml_new_ptr(mfp)
2957     memfile_T	*mfp;
2958 {
2959     bhdr_T	*hp;
2960     PTR_BL	*pp;
2961 
2962     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
2963 	return NULL;
2964 
2965     pp = (PTR_BL *)(hp->bh_data);
2966     pp->pb_id = PTR_ID;
2967     pp->pb_count = 0;
2968     pp->pb_count_max = (short_u)((mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1);
2969 
2970     return hp;
2971 }
2972 
2973 /*
2974  * lookup line 'lnum' in a memline
2975  *
2976  *   action: if ML_DELETE or ML_INSERT the line count is updated while searching
2977  *	     if ML_FLUSH only flush a locked block
2978  *	     if ML_FIND just find the line
2979  *
2980  * If the block was found it is locked and put in ml_locked.
2981  * The stack is updated to lead to the locked block. The ip_high field in
2982  * the stack is updated to reflect the last line in the block AFTER the
2983  * insert or delete, also if the pointer block has not been updated yet. But
2984  * if if ml_locked != NULL ml_locked_lineadd must be added to ip_high.
2985  *
2986  * return: NULL for failure, pointer to block header otherwise
2987  */
2988     static bhdr_T *
2989 ml_find_line(buf, lnum, action)
2990     buf_T	*buf;
2991     linenr_T	lnum;
2992     int		action;
2993 {
2994     DATA_BL	*dp;
2995     PTR_BL	*pp;
2996     infoptr_T	*ip;
2997     bhdr_T	*hp;
2998     memfile_T	*mfp;
2999     linenr_T	t;
3000     blocknr_T	bnum, bnum2;
3001     int		dirty;
3002     linenr_T	low, high;
3003     int		top;
3004     int		page_count;
3005     int		idx;
3006 
3007     mfp = buf->b_ml.ml_mfp;
3008 
3009     /*
3010      * If there is a locked block check if the wanted line is in it.
3011      * If not, flush and release the locked block.
3012      * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
3013      * Don't do this for ML_FLUSH, because we want to flush the locked block.
3014      */
3015     if (buf->b_ml.ml_locked)
3016     {
3017 	if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum
3018 					  && buf->b_ml.ml_locked_high >= lnum)
3019 	{
3020 		/* remember to update pointer blocks and stack later */
3021 	    if (action == ML_INSERT)
3022 	    {
3023 		++(buf->b_ml.ml_locked_lineadd);
3024 		++(buf->b_ml.ml_locked_high);
3025 	    }
3026 	    else if (action == ML_DELETE)
3027 	    {
3028 		--(buf->b_ml.ml_locked_lineadd);
3029 		--(buf->b_ml.ml_locked_high);
3030 	    }
3031 	    return (buf->b_ml.ml_locked);
3032 	}
3033 
3034 	mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY,
3035 					    buf->b_ml.ml_flags & ML_LOCKED_POS);
3036 	buf->b_ml.ml_locked = NULL;
3037 
3038 	    /*
3039 	     * if lines have been added or deleted in the locked block, need to
3040 	     * update the line count in pointer blocks
3041 	     */
3042 	if (buf->b_ml.ml_locked_lineadd)
3043 	    ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
3044     }
3045 
3046     if (action == ML_FLUSH)	    /* nothing else to do */
3047 	return NULL;
3048 
3049     bnum = 1;			    /* start at the root of the tree */
3050     page_count = 1;
3051     low = 1;
3052     high = buf->b_ml.ml_line_count;
3053 
3054     if (action == ML_FIND)	/* first try stack entries */
3055     {
3056 	for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top)
3057 	{
3058 	    ip = &(buf->b_ml.ml_stack[top]);
3059 	    if (ip->ip_low <= lnum && ip->ip_high >= lnum)
3060 	    {
3061 		bnum = ip->ip_bnum;
3062 		low = ip->ip_low;
3063 		high = ip->ip_high;
3064 		buf->b_ml.ml_stack_top = top;	/* truncate stack at prev entry */
3065 		break;
3066 	    }
3067 	}
3068 	if (top < 0)
3069 	    buf->b_ml.ml_stack_top = 0;		/* not found, start at the root */
3070     }
3071     else	/* ML_DELETE or ML_INSERT */
3072 	buf->b_ml.ml_stack_top = 0;	/* start at the root */
3073 
3074 /*
3075  * search downwards in the tree until a data block is found
3076  */
3077     for (;;)
3078     {
3079 	if ((hp = mf_get(mfp, bnum, page_count)) == NULL)
3080 	    goto error_noblock;
3081 
3082 	/*
3083 	 * update high for insert/delete
3084 	 */
3085 	if (action == ML_INSERT)
3086 	    ++high;
3087 	else if (action == ML_DELETE)
3088 	    --high;
3089 
3090 	dp = (DATA_BL *)(hp->bh_data);
3091 	if (dp->db_id == DATA_ID)	/* data block */
3092 	{
3093 	    buf->b_ml.ml_locked = hp;
3094 	    buf->b_ml.ml_locked_low = low;
3095 	    buf->b_ml.ml_locked_high = high;
3096 	    buf->b_ml.ml_locked_lineadd = 0;
3097 	    buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS);
3098 	    return hp;
3099 	}
3100 
3101 	pp = (PTR_BL *)(dp);		/* must be pointer block */
3102 	if (pp->pb_id != PTR_ID)
3103 	{
3104 	    EMSG(_("E317: pointer block id wrong"));
3105 	    goto error_block;
3106 	}
3107 
3108 	if ((top = ml_add_stack(buf)) < 0)	/* add new entry to stack */
3109 	    goto error_block;
3110 	ip = &(buf->b_ml.ml_stack[top]);
3111 	ip->ip_bnum = bnum;
3112 	ip->ip_low = low;
3113 	ip->ip_high = high;
3114 	ip->ip_index = -1;		/* index not known yet */
3115 
3116 	dirty = FALSE;
3117 	for (idx = 0; idx < (int)pp->pb_count; ++idx)
3118 	{
3119 	    t = pp->pb_pointer[idx].pe_line_count;
3120 	    CHECK(t == 0, _("pe_line_count is zero"));
3121 	    if ((low += t) > lnum)
3122 	    {
3123 		ip->ip_index = idx;
3124 		bnum = pp->pb_pointer[idx].pe_bnum;
3125 		page_count = pp->pb_pointer[idx].pe_page_count;
3126 		high = low - 1;
3127 		low -= t;
3128 
3129 		/*
3130 		 * a negative block number may have been changed
3131 		 */
3132 		if (bnum < 0)
3133 		{
3134 		    bnum2 = mf_trans_del(mfp, bnum);
3135 		    if (bnum != bnum2)
3136 		    {
3137 			bnum = bnum2;
3138 			pp->pb_pointer[idx].pe_bnum = bnum;
3139 			dirty = TRUE;
3140 		    }
3141 		}
3142 
3143 		break;
3144 	    }
3145 	}
3146 	if (idx >= (int)pp->pb_count)	    /* past the end: something wrong! */
3147 	{
3148 	    if (lnum > buf->b_ml.ml_line_count)
3149 		EMSGN(_("E322: line number out of range: %ld past the end"),
3150 					      lnum - buf->b_ml.ml_line_count);
3151 
3152 	    else
3153 		EMSGN(_("E323: line count wrong in block %ld"), bnum);
3154 	    goto error_block;
3155 	}
3156 	if (action == ML_DELETE)
3157 	{
3158 	    pp->pb_pointer[idx].pe_line_count--;
3159 	    dirty = TRUE;
3160 	}
3161 	else if (action == ML_INSERT)
3162 	{
3163 	    pp->pb_pointer[idx].pe_line_count++;
3164 	    dirty = TRUE;
3165 	}
3166 	mf_put(mfp, hp, dirty, FALSE);
3167     }
3168 
3169 error_block:
3170     mf_put(mfp, hp, FALSE, FALSE);
3171 error_noblock:
3172 /*
3173  * If action is ML_DELETE or ML_INSERT we have to correct the tree for
3174  * the incremented/decremented line counts, because there won't be a line
3175  * inserted/deleted after all.
3176  */
3177     if (action == ML_DELETE)
3178 	ml_lineadd(buf, 1);
3179     else if (action == ML_INSERT)
3180 	ml_lineadd(buf, -1);
3181     buf->b_ml.ml_stack_top = 0;
3182     return NULL;
3183 }
3184 
3185 /*
3186  * add an entry to the info pointer stack
3187  *
3188  * return -1 for failure, number of the new entry otherwise
3189  */
3190     static int
3191 ml_add_stack(buf)
3192     buf_T	*buf;
3193 {
3194     int		top;
3195     infoptr_T	*newstack;
3196 
3197     top = buf->b_ml.ml_stack_top;
3198 
3199 	/* may have to increase the stack size */
3200     if (top == buf->b_ml.ml_stack_size)
3201     {
3202 	CHECK(top > 0, _("Stack size increases"));	/* more than 5 levels??? */
3203 
3204 	newstack = (infoptr_T *)alloc((unsigned)sizeof(infoptr_T) *
3205 					(buf->b_ml.ml_stack_size + STACK_INCR));
3206 	if (newstack == NULL)
3207 	    return -1;
3208 	mch_memmove(newstack, buf->b_ml.ml_stack, (size_t)top * sizeof(infoptr_T));
3209 	vim_free(buf->b_ml.ml_stack);
3210 	buf->b_ml.ml_stack = newstack;
3211 	buf->b_ml.ml_stack_size += STACK_INCR;
3212     }
3213 
3214     buf->b_ml.ml_stack_top++;
3215     return top;
3216 }
3217 
3218 /*
3219  * Update the pointer blocks on the stack for inserted/deleted lines.
3220  * The stack itself is also updated.
3221  *
3222  * When a insert/delete line action fails, the line is not inserted/deleted,
3223  * but the pointer blocks have already been updated. That is fixed here by
3224  * walking through the stack.
3225  *
3226  * Count is the number of lines added, negative if lines have been deleted.
3227  */
3228     static void
3229 ml_lineadd(buf, count)
3230     buf_T	*buf;
3231     int		count;
3232 {
3233     int		idx;
3234     infoptr_T	*ip;
3235     PTR_BL	*pp;
3236     memfile_T	*mfp = buf->b_ml.ml_mfp;
3237     bhdr_T	*hp;
3238 
3239     for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx)
3240     {
3241 	ip = &(buf->b_ml.ml_stack[idx]);
3242 	if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
3243 	    break;
3244 	pp = (PTR_BL *)(hp->bh_data);	/* must be pointer block */
3245 	if (pp->pb_id != PTR_ID)
3246 	{
3247 	    mf_put(mfp, hp, FALSE, FALSE);
3248 	    EMSG(_("E317: pointer block id wrong 2"));
3249 	    break;
3250 	}
3251 	pp->pb_pointer[ip->ip_index].pe_line_count += count;
3252 	ip->ip_high += count;
3253 	mf_put(mfp, hp, TRUE, FALSE);
3254     }
3255 }
3256 
3257 /*
3258  * make swap file name out of the file name and a directory name
3259  */
3260     static char_u *
3261 makeswapname(buf, dir_name)
3262     buf_T	*buf;
3263     char_u	*dir_name;
3264 {
3265     char_u	*r, *s;
3266 
3267 #if defined(UNIX) || defined(WIN3264)  /* Need _very_ long file names */
3268     s = dir_name + STRLEN(dir_name);
3269     if (vim_ispathsep(s[-1]) && s[-1] == s[-2])
3270     {			       /* Ends with '//', Use Full path */
3271 	r = NULL;
3272 	if ((s = make_percent_swname(dir_name, buf->b_fname)) != NULL)
3273 	{
3274 	    r = modname(s, (char_u *)".swp", FALSE);
3275 	    vim_free(s);
3276 	}
3277 	return r;
3278     }
3279 #endif
3280 
3281     r = buf_modname(
3282 #ifdef SHORT_FNAME
3283 	    TRUE,
3284 #else
3285 	    (buf->b_p_sn || buf->b_shortname),
3286 #endif
3287 #ifdef RISCOS
3288 	    /* Avoid problems if fname has special chars, eg <Wimp$Scrap> */
3289 	    buf->b_ffname,
3290 #else
3291 	    buf->b_fname,
3292 #endif
3293 	    (char_u *)
3294 #if defined(VMS) || defined(RISCOS)
3295 	    "_swp",
3296 #else
3297 	    ".swp",
3298 #endif
3299 #ifdef SHORT_FNAME		/* always 8.3 file name */
3300 	    FALSE
3301 #else
3302 	    /* Prepend a '.' to the swap file name for the current directory. */
3303 	    dir_name[0] == '.' && dir_name[1] == NUL
3304 #endif
3305 	       );
3306     if (r == NULL)	    /* out of memory */
3307 	return NULL;
3308 
3309     s = get_file_in_dir(r, dir_name);
3310     vim_free(r);
3311     return s;
3312 }
3313 
3314 /*
3315  * Get file name to use for swap file or backup file.
3316  * Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir'
3317  * option "dname".
3318  * - If "dname" is ".", return "fname" (swap file in dir of file).
3319  * - If "dname" starts with "./", insert "dname" in "fname" (swap file
3320  *   relative to dir of file).
3321  * - Otherwise, prepend "dname" to the tail of "fname" (swap file in specific
3322  *   dir).
3323  *
3324  * The return value is an allocated string and can be NULL.
3325  */
3326     char_u *
3327 get_file_in_dir(fname, dname)
3328     char_u  *fname;
3329     char_u  *dname;	/* don't use "dirname", it is a global for Alpha */
3330 {
3331     char_u	*t;
3332     char_u	*tail;
3333     char_u	*retval;
3334     int		save_char;
3335 
3336     tail = gettail(fname);
3337 
3338     if (dname[0] == '.' && dname[1] == NUL)
3339 	retval = vim_strsave(fname);
3340     else if (dname[0] == '.' && vim_ispathsep(dname[1]))
3341     {
3342 	if (tail == fname)	    /* no path before file name */
3343 	    retval = concat_fnames(dname + 2, tail, TRUE);
3344 	else
3345 	{
3346 	    save_char = *tail;
3347 	    *tail = NUL;
3348 	    t = concat_fnames(fname, dname + 2, TRUE);
3349 	    *tail = save_char;
3350 	    if (t == NULL)	    /* out of memory */
3351 		retval = NULL;
3352 	    else
3353 	    {
3354 		retval = concat_fnames(t, tail, TRUE);
3355 		vim_free(t);
3356 	    }
3357 	}
3358     }
3359     else
3360 	retval = concat_fnames(dname, tail, TRUE);
3361 
3362     return retval;
3363 }
3364 
3365 /*
3366  * Find out what name to use for the swap file for buffer 'buf'.
3367  *
3368  * Several names are tried to find one that does not exist
3369  *
3370  * Note: If BASENAMELEN is not correct, you will get error messages for
3371  *	 not being able to open the swapfile
3372  */
3373     static char_u *
3374 findswapname(buf, dirp, old_fname)
3375     buf_T	*buf;
3376     char_u	**dirp;		/* pointer to list of directories */
3377     char_u	*old_fname;	/* don't give warning for this file name */
3378 {
3379     char_u	*fname;
3380     int		n;
3381     time_t	x, sx;
3382     char_u	*dir_name;
3383 #ifdef AMIGA
3384     BPTR	fh;
3385 #endif
3386 #ifndef SHORT_FNAME
3387     int		r;
3388 #endif
3389 
3390 #if !defined(SHORT_FNAME) \
3391 		     && ((!defined(UNIX) && !defined(OS2)) || defined(ARCHIE))
3392 # define CREATE_DUMMY_FILE
3393     FILE	*dummyfd = NULL;
3394 
3395 /*
3396  * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
3397  * compatible filesystem, it is possible that the file "test.doc.swp" which we
3398  * create will be exactly the same file. To avoid this problem we temporarily
3399  * create "test.doc".
3400  * Don't do this when the check below for a 8.3 file name is used.
3401  */
3402     if (!(buf->b_p_sn || buf->b_shortname) && buf->b_fname != NULL
3403 					     && mch_getperm(buf->b_fname) < 0)
3404 	dummyfd = mch_fopen((char *)buf->b_fname, "w");
3405 #endif
3406 
3407 /*
3408  * Isolate a directory name from *dirp and put it in dir_name.
3409  * First allocate some memory to put the directory name in.
3410  */
3411     dir_name = alloc((unsigned)STRLEN(*dirp) + 1);
3412     if (dir_name != NULL)
3413 	(void)copy_option_part(dirp, dir_name, 31000, ",");
3414 
3415 /*
3416  * we try different names until we find one that does not exist yet
3417  */
3418     if (dir_name == NULL)	    /* out of memory */
3419 	fname = NULL;
3420     else
3421 	fname = makeswapname(buf, dir_name);
3422 
3423     for (;;)
3424     {
3425 	if (fname == NULL)	/* must be out of memory */
3426 	    break;
3427 	if ((n = (int)STRLEN(fname)) == 0)	/* safety check */
3428 	{
3429 	    vim_free(fname);
3430 	    fname = NULL;
3431 	    break;
3432 	}
3433 #if (defined(UNIX) || defined(OS2)) && !defined(ARCHIE) && !defined(SHORT_FNAME)
3434 /*
3435  * Some systems have a MS-DOS compatible filesystem that use 8.3 character
3436  * file names. If this is the first try and the swap file name does not fit in
3437  * 8.3, detect if this is the case, set shortname and try again.
3438  */
3439 	if (fname[n - 2] == 'w' && fname[n - 1] == 'p'
3440 					&& !(buf->b_p_sn || buf->b_shortname))
3441 	{
3442 	    char_u	    *tail;
3443 	    char_u	    *fname2;
3444 	    struct stat	    s1, s2;
3445 	    int		    f1, f2;
3446 	    int		    created1 = FALSE, created2 = FALSE;
3447 	    int		    same = FALSE;
3448 
3449 	    /*
3450 	     * Check if swapfile name does not fit in 8.3:
3451 	     * It either contains two dots, is longer than 8 chars, or starts
3452 	     * with a dot.
3453 	     */
3454 	    tail = gettail(buf->b_fname);
3455 	    if (       vim_strchr(tail, '.') != NULL
3456 		    || STRLEN(tail) > (size_t)8
3457 		    || *gettail(fname) == '.')
3458 	    {
3459 		fname2 = alloc(n + 2);
3460 		if (fname2 != NULL)
3461 		{
3462 		    STRCPY(fname2, fname);
3463 		    /* if fname == "xx.xx.swp",	    fname2 = "xx.xx.swx"
3464 		     * if fname == ".xx.swp",	    fname2 = ".xx.swpx"
3465 		     * if fname == "123456789.swp", fname2 = "12345678x.swp"
3466 		     */
3467 		    if (vim_strchr(tail, '.') != NULL)
3468 			fname2[n - 1] = 'x';
3469 		    else if (*gettail(fname) == '.')
3470 		    {
3471 			fname2[n] = 'x';
3472 			fname2[n + 1] = NUL;
3473 		    }
3474 		    else
3475 			fname2[n - 5] += 1;
3476 		    /*
3477 		     * may need to create the files to be able to use mch_stat()
3478 		     */
3479 		    f1 = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
3480 		    if (f1 < 0)
3481 		    {
3482 			f1 = mch_open_rw((char *)fname,
3483 					       O_RDWR|O_CREAT|O_EXCL|O_EXTRA);
3484 #if defined(OS2)
3485 			if (f1 < 0 && errno == ENOENT)
3486 			    same = TRUE;
3487 #endif
3488 			created1 = TRUE;
3489 		    }
3490 		    if (f1 >= 0)
3491 		    {
3492 			f2 = mch_open((char *)fname2, O_RDONLY | O_EXTRA, 0);
3493 			if (f2 < 0)
3494 			{
3495 			    f2 = mch_open_rw((char *)fname2,
3496 					       O_RDWR|O_CREAT|O_EXCL|O_EXTRA);
3497 			    created2 = TRUE;
3498 			}
3499 			if (f2 >= 0)
3500 			{
3501 			    /*
3502 			     * Both files exist now. If mch_stat() returns the
3503 			     * same device and inode they are the same file.
3504 			     */
3505 			    if (mch_fstat(f1, &s1) != -1
3506 				    && mch_fstat(f2, &s2) != -1
3507 				    && s1.st_dev == s2.st_dev
3508 				    && s1.st_ino == s2.st_ino)
3509 				same = TRUE;
3510 			    close(f2);
3511 			    if (created2)
3512 				mch_remove(fname2);
3513 			}
3514 			close(f1);
3515 			if (created1)
3516 			    mch_remove(fname);
3517 		    }
3518 		    vim_free(fname2);
3519 		    if (same)
3520 		    {
3521 			buf->b_shortname = TRUE;
3522 			vim_free(fname);
3523 			fname = makeswapname(buf, dir_name);
3524 			continue;	/* try again with b_shortname set */
3525 		    }
3526 		}
3527 	    }
3528 	}
3529 #endif
3530 	/*
3531 	 * check if the swapfile already exists
3532 	 */
3533 	if (mch_getperm(fname) < 0)	/* it does not exist */
3534 	{
3535 #ifdef HAVE_LSTAT
3536 	    struct stat sb;
3537 
3538 	    /*
3539 	     * Extra security check: When a swap file is a symbolic link, this
3540 	     * is most likely a symlink attack.
3541 	     */
3542 	    if (mch_lstat((char *)fname, &sb) < 0)
3543 #else
3544 # ifdef AMIGA
3545 	    fh = Open((UBYTE *)fname, (long)MODE_NEWFILE);
3546 	    /*
3547 	     * on the Amiga mch_getperm() will return -1 when the file exists
3548 	     * but is being used by another program. This happens if you edit
3549 	     * a file twice.
3550 	     */
3551 	    if (fh != (BPTR)NULL)	/* can open file, OK */
3552 	    {
3553 		Close(fh);
3554 		mch_remove(fname);
3555 		break;
3556 	    }
3557 	    if (IoErr() != ERROR_OBJECT_IN_USE
3558 					    && IoErr() != ERROR_OBJECT_EXISTS)
3559 # endif
3560 #endif
3561 		break;
3562 	}
3563 
3564 	/*
3565 	 * A file name equal to old_fname is OK to use.
3566 	 */
3567 	if (old_fname != NULL && fnamecmp(fname, old_fname) == 0)
3568 	    break;
3569 
3570 	/*
3571 	 * get here when file already exists
3572 	 */
3573 	if (fname[n - 2] == 'w' && fname[n - 1] == 'p')	/* first try */
3574 	{
3575 #ifndef SHORT_FNAME
3576 	    /*
3577 	     * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp
3578 	     * and file.doc are the same file. To guess if this problem is
3579 	     * present try if file.doc.swx exists. If it does, we set
3580 	     * buf->b_shortname and try file_doc.swp (dots replaced by
3581 	     * underscores for this file), and try again. If it doesn't we
3582 	     * assume that "file.doc.swp" already exists.
3583 	     */
3584 	    if (!(buf->b_p_sn || buf->b_shortname))	/* not tried yet */
3585 	    {
3586 		fname[n - 1] = 'x';
3587 		r = mch_getperm(fname);		/* try "file.swx" */
3588 		fname[n - 1] = 'p';
3589 		if (r >= 0)		    /* "file.swx" seems to exist */
3590 		{
3591 		    buf->b_shortname = TRUE;
3592 		    vim_free(fname);
3593 		    fname = makeswapname(buf, dir_name);
3594 		    continue;	    /* try again with '.' replaced with '_' */
3595 		}
3596 	    }
3597 #endif
3598 	    /*
3599 	     * If we get here the ".swp" file really exists.
3600 	     * Give an error message, unless recovering, no file name, we are
3601 	     * viewing a help file or when the path of the file is different
3602 	     * (happens when all .swp files are in one directory).
3603 	     */
3604 	    if (!recoverymode && buf->b_fname != NULL && !buf->b_help)
3605 	    {
3606 		int		fd;
3607 		struct block0	b0;
3608 		int		differ = FALSE;
3609 
3610 		/*
3611 		 * Try to read block 0 from the swap file to get the original
3612 		 * file name (and inode number).
3613 		 */
3614 		fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
3615 		if (fd >= 0)
3616 		{
3617 		    if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
3618 		    {
3619 			/*
3620 			 * The name in the swap file may be "~user/path/file".
3621 			 * Expand it first.
3622 			 */
3623 			expand_env(b0.b0_fname, NameBuff, MAXPATHL);
3624 #ifdef CHECK_INODE
3625 			if (fnamecmp_ino(buf->b_ffname, NameBuff,
3626 						     char_to_long(b0.b0_ino)))
3627 			    differ = TRUE;
3628 #else
3629 			if (fnamecmp(NameBuff, buf->b_ffname) != 0)
3630 			    differ = TRUE;
3631 #endif
3632 		    }
3633 		    close(fd);
3634 		}
3635 #ifdef RISCOS
3636 		else
3637 		    /* Can't open swap file, though it does exist.
3638 		     * Assume that the user is editing two files with
3639 		     * the same name in different directories. No error.
3640 		     */
3641 		    differ = TRUE;
3642 #endif
3643 
3644 		/* give the ATTENTION message when there is an old swap file
3645 		 * for the current file, and the buffer was not recovered. */
3646 		if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
3647 			&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
3648 		{
3649 		    struct stat st;
3650 #ifdef CREATE_DUMMY_FILE
3651 		    int		did_use_dummy = FALSE;
3652 
3653 		    /* Avoid getting a warning for the file being created
3654 		     * outside of Vim, it was created at the start of this
3655 		     * function.  Delete the file now, because Vim might exit
3656 		     * here if the window is closed. */
3657 		    if (dummyfd != NULL)
3658 		    {
3659 			fclose(dummyfd);
3660 			dummyfd = NULL;
3661 			mch_remove(buf->b_fname);
3662 			did_use_dummy = TRUE;
3663 		    }
3664 #endif
3665 #ifdef FEAT_GUI
3666 		    /* If we are supposed to start the GUI but it wasn't
3667 		     * completely started yet, start it now.  This makes the
3668 		     * messages displayed in the Vim window when loading a
3669 		     * session from the .gvimrc file. */
3670 		    if (gui.starting && !gui.in_use)
3671 			gui_start();
3672 #endif
3673 
3674 #if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
3675 		    process_still_running = FALSE;
3676 #endif
3677 		    ++no_wait_return;
3678 		    (void)EMSG(_("E325: ATTENTION"));
3679 		    MSG_PUTS(_("\nFound a swap file by the name \""));
3680 		    msg_home_replace(fname);
3681 		    MSG_PUTS("\"\n");
3682 		    sx = swapfile_info(fname);
3683 		    MSG_PUTS(_("While opening file \""));
3684 		    msg_outtrans(buf->b_fname);
3685 		    MSG_PUTS("\"\n");
3686 		    if (mch_stat((char *)buf->b_fname, &st) != -1)
3687 		    {
3688 			MSG_PUTS(_("             dated: "));
3689 			x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
3690 			MSG_PUTS(ctime(&x));
3691 			if (sx != 0 && x > sx)
3692 			    MSG_PUTS(_("      NEWER than swap file!\n"));
3693 		    }
3694 		    /* Some of these messages are long to allow translation to
3695 		     * other languages. */
3696 		    MSG_PUTS(_("\n(1) Another program may be editing the same file.\n    If this is the case, be careful not to end up with two\n    different instances of the same file when making changes.\n"));
3697 		    MSG_PUTS(_("    Quit, or continue with caution.\n"));
3698 		    MSG_PUTS(_("\n(2) An edit session for this file crashed.\n"));
3699 		    MSG_PUTS(_("    If this is the case, use \":recover\" or \"vim -r "));
3700 		    msg_outtrans(buf->b_fname);
3701 		    MSG_PUTS(_("\"\n    to recover the changes (see \":help recovery\").\n"));
3702 		    MSG_PUTS(_("    If you did this already, delete the swap file \""));
3703 		    msg_outtrans(fname);
3704 		    MSG_PUTS(_("\"\n    to avoid this message.\n"));
3705 		    cmdline_row = msg_row;
3706 		    --no_wait_return;
3707 
3708 		    /* We don't want a 'q' typed at the more-prompt interrupt
3709 		     * loading a file. */
3710 		    got_int = FALSE;
3711 
3712 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
3713 		    if (swap_exists_action)
3714 		    {
3715 			char_u	*name;
3716 
3717 			name = alloc((unsigned)(STRLEN(fname)
3718 				+ STRLEN(_("Swap file \""))
3719 				+ STRLEN(_("\" already exists!")) + 5));
3720 			if (name != NULL)
3721 			{
3722 			    STRCPY(name, _("Swap file \""));
3723 			    home_replace(NULL, fname, name + STRLEN(name),
3724 								  1000, TRUE);
3725 			    STRCAT(name, _("\" already exists!"));
3726 			}
3727 			switch (do_dialog(VIM_WARNING,
3728 				    (char_u *)_("VIM - ATTENTION"),
3729 				    name == NULL
3730 					?  (char_u *)_("Swap file already exists!")
3731 					: name,
3732 # if defined(UNIX) || defined(__EMX__) || defined(VMS)
3733 				    process_still_running
3734 					? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") :
3735 # endif
3736 					(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort\n&Delete it"), 1, NULL))
3737 			{
3738 			    case 1:
3739 				buf->b_p_ro = TRUE;
3740 				break;
3741 			    case 2:
3742 				break;
3743 			    case 3:
3744 				swap_exists_action = SEA_RECOVER;
3745 				break;
3746 			    case 4:
3747 				swap_exists_action = SEA_QUIT;
3748 				break;
3749 			    case 5:
3750 				swap_exists_action = SEA_QUIT;
3751 				got_int = TRUE;
3752 				break;
3753 			    case 6:
3754 				mch_remove(fname);
3755 				break;
3756 			}
3757 			vim_free(name);
3758 
3759 			/* pretend screen didn't scroll, need redraw anyway */
3760 			msg_scrolled = 0;
3761 			redraw_all_later(NOT_VALID);
3762 
3763 			/* If the file was deleted this fname can be used. */
3764 			if (mch_getperm(fname) < 0)
3765 			    break;
3766 		    }
3767 		    else
3768 #endif
3769 		    {
3770 			MSG_PUTS("\n");
3771 			need_wait_return = TRUE; /* call wait_return later */
3772 		    }
3773 
3774 #ifdef CREATE_DUMMY_FILE
3775 		    /* Going to try another name, need the dummy file again. */
3776 		    if (did_use_dummy)
3777 			dummyfd = mch_fopen((char *)buf->b_fname, "w");
3778 #endif
3779 		}
3780 	    }
3781 	}
3782 
3783 	/*
3784 	 * Change the ".swp" extension to find another file that can be used.
3785 	 * First decrement the last char: ".swo", ".swn", etc.
3786 	 * If that still isn't enough decrement the last but one char: ".svz"
3787 	 * Can happen when editing many "No Name" buffers.
3788 	 */
3789 	if (fname[n - 1] == 'a')	/* ".s?a" */
3790 	{
3791 	    if (fname[n - 2] == 'a')    /* ".saa": tried enough, give up */
3792 	    {
3793 		EMSG(_("E326: Too many swap files found"));
3794 		vim_free(fname);
3795 		fname = NULL;
3796 		break;
3797 	    }
3798 	    --fname[n - 2];		/* ".svz", ".suz", etc. */
3799 	    fname[n - 1] = 'z' + 1;
3800 	}
3801 	--fname[n - 1];			/* ".swo", ".swn", etc. */
3802     }
3803 
3804     vim_free(dir_name);
3805 #ifdef CREATE_DUMMY_FILE
3806     if (dummyfd != NULL)	/* file has been created temporarily */
3807     {
3808 	fclose(dummyfd);
3809 	mch_remove(buf->b_fname);
3810     }
3811 #endif
3812     return fname;
3813 }
3814 
3815     static int
3816 b0_magic_wrong(b0p)
3817     ZERO_BL *b0p;
3818 {
3819     return (b0p->b0_magic_long != (long)B0_MAGIC_LONG
3820 	    || b0p->b0_magic_int != (int)B0_MAGIC_INT
3821 	    || b0p->b0_magic_short != (short)B0_MAGIC_SHORT
3822 	    || b0p->b0_magic_char != B0_MAGIC_CHAR);
3823 }
3824 
3825 #ifdef CHECK_INODE
3826 /*
3827  * Compare current file name with file name from swap file.
3828  * Try to use inode numbers when possible.
3829  * Return non-zero when files are different.
3830  *
3831  * When comparing file names a few things have to be taken into consideration:
3832  * - When working over a network the full path of a file depends on the host.
3833  *   We check the inode number if possible.  It is not 100% reliable though,
3834  *   because the device number cannot be used over a network.
3835  * - When a file does not exist yet (editing a new file) there is no inode
3836  *   number.
3837  * - The file name in a swap file may not be valid on the current host.  The
3838  *   "~user" form is used whenever possible to avoid this.
3839  *
3840  * This is getting complicated, let's make a table:
3841  *
3842  *		ino_c  ino_s  fname_c  fname_s	differ =
3843  *
3844  * both files exist -> compare inode numbers:
3845  *		!= 0   != 0	X	 X	ino_c != ino_s
3846  *
3847  * inode number(s) unknown, file names available -> compare file names
3848  *		== 0	X	OK	 OK	fname_c != fname_s
3849  *		 X     == 0	OK	 OK	fname_c != fname_s
3850  *
3851  * current file doesn't exist, file for swap file exist, file name(s) not
3852  * available -> probably different
3853  *		== 0   != 0    FAIL	 X	TRUE
3854  *		== 0   != 0	X	FAIL	TRUE
3855  *
3856  * current file exists, inode for swap unknown, file name(s) not
3857  * available -> probably different
3858  *		!= 0   == 0    FAIL	 X	TRUE
3859  *		!= 0   == 0	X	FAIL	TRUE
3860  *
3861  * current file doesn't exist, inode for swap unknown, one file name not
3862  * available -> probably different
3863  *		== 0   == 0    FAIL	 OK	TRUE
3864  *		== 0   == 0	OK	FAIL	TRUE
3865  *
3866  * current file doesn't exist, inode for swap unknown, both file names not
3867  * available -> probably same file
3868  *		== 0   == 0    FAIL	FAIL	FALSE
3869  *
3870  * Note that when the ino_t is 64 bits, only the last 32 will be used.  This
3871  * can't be changed without making the block 0 incompatible with 32 bit
3872  * versions.
3873  */
3874 
3875     static int
3876 fnamecmp_ino(fname_c, fname_s, ino_block0)
3877     char_u	*fname_c;	    /* current file name */
3878     char_u	*fname_s;	    /* file name from swap file */
3879     long	ino_block0;
3880 {
3881     struct stat	st;
3882     ino_t	ino_c = 0;	    /* ino of current file */
3883     ino_t	ino_s;		    /* ino of file from swap file */
3884     char_u	buf_c[MAXPATHL];    /* full path of fname_c */
3885     char_u	buf_s[MAXPATHL];    /* full path of fname_s */
3886     int		retval_c;	    /* flag: buf_c valid */
3887     int		retval_s;	    /* flag: buf_s valid */
3888 
3889     if (mch_stat((char *)fname_c, &st) == 0)
3890 	ino_c = (ino_t)st.st_ino;
3891 
3892     /*
3893      * First we try to get the inode from the file name, because the inode in
3894      * the swap file may be outdated.  If that fails (e.g. this path is not
3895      * valid on this machine), use the inode from block 0.
3896      */
3897     if (mch_stat((char *)fname_s, &st) == 0)
3898 	ino_s = (ino_t)st.st_ino;
3899     else
3900 	ino_s = (ino_t)ino_block0;
3901 
3902     if (ino_c && ino_s)
3903 	return (ino_c != ino_s);
3904 
3905     /*
3906      * One of the inode numbers is unknown, try a forced vim_FullName() and
3907      * compare the file names.
3908      */
3909     retval_c = vim_FullName(fname_c, buf_c, MAXPATHL, TRUE);
3910     retval_s = vim_FullName(fname_s, buf_s, MAXPATHL, TRUE);
3911     if (retval_c == OK && retval_s == OK)
3912 	return (STRCMP(buf_c, buf_s) != 0);
3913 
3914     /*
3915      * Can't compare inodes or file names, guess that the files are different,
3916      * unless both appear not to exist at all.
3917      */
3918     if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL)
3919 	return FALSE;
3920     return TRUE;
3921 }
3922 #endif /* CHECK_INODE */
3923 
3924 /*
3925  * Move a long integer into a four byte character array.
3926  * Used for machine independency in block zero.
3927  */
3928     static void
3929 long_to_char(n, s)
3930     long    n;
3931     char_u  *s;
3932 {
3933     s[0] = (char_u)(n & 0xff);
3934     n = (unsigned)n >> 8;
3935     s[1] = (char_u)(n & 0xff);
3936     n = (unsigned)n >> 8;
3937     s[2] = (char_u)(n & 0xff);
3938     n = (unsigned)n >> 8;
3939     s[3] = (char_u)(n & 0xff);
3940 }
3941 
3942     static long
3943 char_to_long(s)
3944     char_u  *s;
3945 {
3946     long    retval;
3947 
3948     retval = s[3];
3949     retval <<= 8;
3950     retval |= s[2];
3951     retval <<= 8;
3952     retval |= s[1];
3953     retval <<= 8;
3954     retval |= s[0];
3955 
3956     return retval;
3957 }
3958 
3959     void
3960 ml_setdirty(buf, flag)
3961     buf_T	*buf;
3962     int		flag;
3963 {
3964     bhdr_T	*hp;
3965     ZERO_BL	*b0p;
3966 
3967     if (!buf->b_ml.ml_mfp)
3968 	return;
3969     for (hp = buf->b_ml.ml_mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
3970     {
3971 	if (hp->bh_bnum == 0)
3972 	{
3973 	    b0p = (ZERO_BL *)(hp->bh_data);
3974 	    b0p->b0_dirty = flag ? 0x55 : 0;
3975 	    hp->bh_flags |= BH_DIRTY;
3976 	    mf_sync(buf->b_ml.ml_mfp, MFS_ZERO);
3977 	    break;
3978 	}
3979     }
3980 }
3981 
3982 #if defined(FEAT_BYTEOFF) || defined(PROTO)
3983 
3984 #define MLCS_MAXL 800	/* max no of lines in chunk */
3985 #define MLCS_MINL 400   /* should be half of MLCS_MAXL */
3986 
3987 /*
3988  * Keep information for finding byte offset of a line, updtytpe may be one of:
3989  * ML_CHNK_ADDLINE: Add len to parent chunk, possibly splitting it
3990  *	   Careful: ML_CHNK_ADDLINE may cause ml_find_line() to be called.
3991  * ML_CHNK_DELLINE: Subtract len from parent chunk, possibly deleting it
3992  * ML_CHNK_UPDLINE: Add len to parent chunk, as a signed entity.
3993  */
3994     static void
3995 ml_updatechunk(buf, line, len, updtype)
3996     buf_T	*buf;
3997     linenr_T	line;
3998     long	len;
3999     int		updtype;
4000 {
4001     static buf_T	*ml_upd_lastbuf = NULL;
4002     static linenr_T	ml_upd_lastline;
4003     static linenr_T	ml_upd_lastcurline;
4004     static int		ml_upd_lastcurix;
4005 
4006     linenr_T		curline = ml_upd_lastcurline;
4007     int			curix = ml_upd_lastcurix;
4008     long		size;
4009     chunksize_T		*curchnk;
4010     int			rest;
4011     bhdr_T		*hp;
4012     DATA_BL		*dp;
4013 
4014     if (buf->b_ml.ml_usedchunks == -1 || len == 0)
4015 	return;
4016     if (buf->b_ml.ml_chunksize == NULL)
4017     {
4018 	buf->b_ml.ml_chunksize = (chunksize_T *)
4019 				  alloc((unsigned)sizeof(chunksize_T) * 100);
4020 	if (buf->b_ml.ml_chunksize == NULL)
4021 	{
4022 	    buf->b_ml.ml_usedchunks = -1;
4023 	    return;
4024 	}
4025 	buf->b_ml.ml_numchunks = 100;
4026 	buf->b_ml.ml_usedchunks = 1;
4027 	buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
4028 	buf->b_ml.ml_chunksize[0].mlcs_totalsize = 1;
4029     }
4030 
4031     if (updtype == ML_CHNK_UPDLINE && buf->b_ml.ml_line_count == 1)
4032     {
4033 	/*
4034 	 * First line in empty buffer from ml_flush_line() -- reset
4035 	 */
4036 	buf->b_ml.ml_usedchunks = 1;
4037 	buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
4038 	buf->b_ml.ml_chunksize[0].mlcs_totalsize =
4039 				  (long)STRLEN(buf->b_ml.ml_line_ptr) + 1;
4040 	return;
4041     }
4042 
4043     /*
4044      * Find chunk that our line belongs to, curline will be at start of the
4045      * chunk.
4046      */
4047     if (buf != ml_upd_lastbuf || line != ml_upd_lastline + 1
4048 	    || updtype != ML_CHNK_ADDLINE)
4049     {
4050 	for (curline = 1, curix = 0;
4051 	     curix < buf->b_ml.ml_usedchunks - 1
4052 	     && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines;
4053 	     curix++)
4054 	{
4055 	    curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
4056 	}
4057     }
4058     else if (line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines
4059 		 && curix < buf->b_ml.ml_usedchunks - 1)
4060     {
4061 	/* Adjust cached curix & curline */
4062 	curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
4063 	curix++;
4064     }
4065     curchnk = buf->b_ml.ml_chunksize + curix;
4066 
4067     if (updtype == ML_CHNK_DELLINE)
4068 	len *= -1;
4069     curchnk->mlcs_totalsize += len;
4070     if (updtype == ML_CHNK_ADDLINE)
4071     {
4072 	curchnk->mlcs_numlines++;
4073 
4074 	/* May resize here so we don't have to do it in both cases below */
4075 	if (buf->b_ml.ml_usedchunks + 1 >= buf->b_ml.ml_numchunks)
4076 	{
4077 	    buf->b_ml.ml_numchunks = buf->b_ml.ml_numchunks * 3 / 2;
4078 	    buf->b_ml.ml_chunksize = (chunksize_T *)
4079 		vim_realloc(buf->b_ml.ml_chunksize,
4080 			    sizeof(chunksize_T) * buf->b_ml.ml_numchunks);
4081 	    if (buf->b_ml.ml_chunksize == NULL)
4082 	    {
4083 		/* Hmmmm, Give up on offset for this buffer */
4084 		buf->b_ml.ml_usedchunks = -1;
4085 		return;
4086 	    }
4087 	}
4088 
4089 	if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MAXL)
4090 	{
4091 	    int	    count;	    /* number of entries in block */
4092 	    int	    idx;
4093 	    int	    text_end;
4094 	    int	    linecnt;
4095 
4096 	    mch_memmove(buf->b_ml.ml_chunksize + curix + 1,
4097 			buf->b_ml.ml_chunksize + curix,
4098 			(buf->b_ml.ml_usedchunks - curix) *
4099 			sizeof(chunksize_T));
4100 	    /* Compute length of first half of lines in the splitted chunk */
4101 	    size = 0;
4102 	    linecnt = 0;
4103 	    while (curline < buf->b_ml.ml_line_count
4104 			&& linecnt < MLCS_MINL)
4105 	    {
4106 		if ((hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
4107 		{
4108 		    buf->b_ml.ml_usedchunks = -1;
4109 		    return;
4110 		}
4111 		dp = (DATA_BL *)(hp->bh_data);
4112 		count = (long)(buf->b_ml.ml_locked_high) -
4113 			(long)(buf->b_ml.ml_locked_low) + 1;
4114 		idx = curline - buf->b_ml.ml_locked_low;
4115 		curline = buf->b_ml.ml_locked_high + 1;
4116 		if (idx == 0)/* first line in block, text at the end */
4117 		    text_end = dp->db_txt_end;
4118 		else
4119 		    text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
4120 		/* Compute index of last line to use in this MEMLINE */
4121 		rest = count - idx;
4122 		if (linecnt + rest > MLCS_MINL)
4123 		{
4124 		    idx += MLCS_MINL - linecnt - 1;
4125 		    linecnt = MLCS_MINL;
4126 		}
4127 		else
4128 		{
4129 		    idx = count - 1;
4130 		    linecnt += rest;
4131 		}
4132 		size += text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
4133 	    }
4134 	    buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt;
4135 	    buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt;
4136 	    buf->b_ml.ml_chunksize[curix].mlcs_totalsize = size;
4137 	    buf->b_ml.ml_chunksize[curix + 1].mlcs_totalsize -= size;
4138 	    buf->b_ml.ml_usedchunks++;
4139 	    ml_upd_lastbuf = NULL;   /* Force recalc of curix & curline */
4140 	    return;
4141 	}
4142 	else if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MINL
4143 		     && curix == buf->b_ml.ml_usedchunks - 1
4144 		     && buf->b_ml.ml_line_count - line <= 1)
4145 	{
4146 	    /*
4147 	     * We are in the last chunk and it is cheap to crate a new one
4148 	     * after this. Do it now to avoid the loop above later on
4149 	     */
4150 	    curchnk = buf->b_ml.ml_chunksize + curix + 1;
4151 	    buf->b_ml.ml_usedchunks++;
4152 	    if (line == buf->b_ml.ml_line_count)
4153 	    {
4154 		curchnk->mlcs_numlines = 0;
4155 		curchnk->mlcs_totalsize = 0;
4156 	    }
4157 	    else
4158 	    {
4159 		/*
4160 		 * Line is just prior to last, move count for last
4161 		 * This is the common case  when loading a new file
4162 		 */
4163 		hp = ml_find_line(buf, buf->b_ml.ml_line_count, ML_FIND);
4164 		if (hp == NULL)
4165 		{
4166 		    buf->b_ml.ml_usedchunks = -1;
4167 		    return;
4168 		}
4169 		dp = (DATA_BL *)(hp->bh_data);
4170 		if (dp->db_line_count == 1)
4171 		    rest = dp->db_txt_end - dp->db_txt_start;
4172 		else
4173 		    rest =
4174 			((dp->db_index[dp->db_line_count - 2]) & DB_INDEX_MASK)
4175 			- dp->db_txt_start;
4176 		curchnk->mlcs_totalsize = rest;
4177 		curchnk->mlcs_numlines = 1;
4178 		curchnk[-1].mlcs_totalsize -= rest;
4179 		curchnk[-1].mlcs_numlines -= 1;
4180 	    }
4181 	}
4182     }
4183     else if (updtype == ML_CHNK_DELLINE)
4184     {
4185 	curchnk->mlcs_numlines--;
4186 	ml_upd_lastbuf = NULL;   /* Force recalc of curix & curline */
4187 	if (curix < (buf->b_ml.ml_usedchunks - 1)
4188 		&& (curchnk->mlcs_numlines + curchnk[1].mlcs_numlines)
4189 		   <= MLCS_MINL)
4190 	{
4191 	    curix++;
4192 	    curchnk = buf->b_ml.ml_chunksize + curix;
4193 	}
4194 	else if (curix == 0 && curchnk->mlcs_numlines <= 0)
4195 	{
4196 	    buf->b_ml.ml_usedchunks--;
4197 	    mch_memmove(buf->b_ml.ml_chunksize, buf->b_ml.ml_chunksize + 1,
4198 			buf->b_ml.ml_usedchunks * sizeof(chunksize_T));
4199 	    return;
4200 	}
4201 	else if (curix == 0 || (curchnk->mlcs_numlines > 10
4202 		    && (curchnk->mlcs_numlines + curchnk[-1].mlcs_numlines)
4203 		       > MLCS_MINL))
4204 	{
4205 	    return;
4206 	}
4207 
4208 	/* Collapse chunks */
4209 	curchnk[-1].mlcs_numlines += curchnk->mlcs_numlines;
4210 	curchnk[-1].mlcs_totalsize += curchnk->mlcs_totalsize;
4211 	buf->b_ml.ml_usedchunks--;
4212 	if (curix < buf->b_ml.ml_usedchunks)
4213 	{
4214 	    mch_memmove(buf->b_ml.ml_chunksize + curix,
4215 			buf->b_ml.ml_chunksize + curix + 1,
4216 			(buf->b_ml.ml_usedchunks - curix) *
4217 			sizeof(chunksize_T));
4218 	}
4219 	return;
4220     }
4221     ml_upd_lastbuf = buf;
4222     ml_upd_lastline = line;
4223     ml_upd_lastcurline = curline;
4224     ml_upd_lastcurix = curix;
4225 }
4226 
4227 /*
4228  * Find offset for line or line with offset.
4229  * Find line with offset if line is 0; return remaining offset in offp
4230  * Find offset of line if line > 0
4231  * return -1 if information is not available
4232  */
4233     long
4234 ml_find_line_or_offset(buf, line, offp)
4235     buf_T	*buf;
4236     linenr_T	line;
4237     long	*offp;
4238 {
4239     linenr_T	curline;
4240     int		curix;
4241     long	size;
4242     bhdr_T	*hp;
4243     DATA_BL	*dp;
4244     int		count;		/* number of entries in block */
4245     int		idx;
4246     int		start_idx;
4247     int		text_end;
4248     long	offset;
4249     int		len;
4250     int		ffdos = (get_fileformat(buf) == EOL_DOS);
4251     int		extra = 0;
4252 
4253     if (buf->b_ml.ml_usedchunks == -1
4254 	    || buf->b_ml.ml_chunksize == NULL
4255 	    || line < 0)
4256 	return -1;
4257 
4258     if (offp == NULL)
4259 	offset = 0;
4260     else
4261 	offset = *offp;
4262     if (line == 0 && offset <= 0)
4263 	return 1;   /* Not a "find offset" and offset 0 _must_ be in line 1 */
4264     /*
4265      * Find the last chunk before the one containing our line. Last chunk is
4266      * special because it will never qualify
4267      */
4268     curline = 1;
4269     curix = size = 0;
4270     while (curix < buf->b_ml.ml_usedchunks - 1
4271 	    && ((line != 0
4272 	     && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines)
4273 		|| (offset != 0
4274 	       && offset > size + buf->b_ml.ml_chunksize[curix].mlcs_totalsize
4275 		      + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines)))
4276     {
4277 	curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
4278 	size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize;
4279 	if (offset && ffdos)
4280 	    size += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
4281 	curix++;
4282     }
4283 
4284     while ((line != 0 && curline < line) || (offset != 0 && size < offset))
4285     {
4286 	if (curline > buf->b_ml.ml_line_count
4287 		|| (hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
4288 	    return -1;
4289 	dp = (DATA_BL *)(hp->bh_data);
4290 	count = (long)(buf->b_ml.ml_locked_high) -
4291 		(long)(buf->b_ml.ml_locked_low) + 1;
4292 	start_idx = idx = curline - buf->b_ml.ml_locked_low;
4293 	if (idx == 0)/* first line in block, text at the end */
4294 	    text_end = dp->db_txt_end;
4295 	else
4296 	    text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
4297 	/* Compute index of last line to use in this MEMLINE */
4298 	if (line != 0)
4299 	{
4300 	    if (curline + (count - idx) >= line)
4301 		idx += line - curline - 1;
4302 	    else
4303 		idx = count - 1;
4304 	}
4305 	else
4306 	{
4307 	    extra = 0;
4308 	    while (offset >= size
4309 		       + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK)
4310 								      + ffdos)
4311 	    {
4312 		if (ffdos)
4313 		    size++;
4314 		if (idx == count - 1)
4315 		{
4316 		    extra = 1;
4317 		    break;
4318 		}
4319 		idx++;
4320 	    }
4321 	}
4322 	len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
4323 	size += len;
4324 	if (offset != 0 && size >= offset)
4325 	{
4326 	    if (size + ffdos == offset)
4327 		*offp = 0;
4328 	    else if (idx == start_idx)
4329 		*offp = offset - size + len;
4330 	    else
4331 		*offp = offset - size + len
4332 		     - (text_end - ((dp->db_index[idx - 1]) & DB_INDEX_MASK));
4333 	    curline += idx - start_idx + extra;
4334 	    if (curline > buf->b_ml.ml_line_count)
4335 		return -1;	/* exactly one byte beyond the end */
4336 	    return curline;
4337 	}
4338 	curline = buf->b_ml.ml_locked_high + 1;
4339     }
4340 
4341     if (ffdos)
4342 	size += line - 1;
4343     return size;
4344 }
4345 
4346 /*
4347  * Goto byte in buffer with offset 'cnt'.
4348  */
4349     void
4350 goto_byte(cnt)
4351     long	cnt;
4352 {
4353     long	boff = cnt;
4354     linenr_T	lnum;
4355 
4356     ml_flush_line(curbuf);	/* cached line may be dirty */
4357     setpcmark();
4358     if (boff)
4359 	--boff;
4360     lnum = ml_find_line_or_offset(curbuf, (linenr_T)0, &boff);
4361     if (lnum < 1)	/* past the end */
4362     {
4363 	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
4364 	curwin->w_curswant = MAXCOL;
4365 	coladvance((colnr_T)MAXCOL);
4366     }
4367     else
4368     {
4369 	curwin->w_cursor.lnum = lnum;
4370 	curwin->w_cursor.col = (colnr_T)boff;
4371 	curwin->w_set_curswant = TRUE;
4372     }
4373     check_cursor();
4374 
4375 # ifdef FEAT_MBYTE
4376     /* Make sure the cursor is on the first byte of a multi-byte char. */
4377     if (has_mbyte)
4378 	mb_adjust_cursor();
4379 # endif
4380 }
4381 #endif
4382