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