xref: /vim-8.2.3635/src/memline.c (revision 94688b8a)
1 /* vi:set ts=8 sts=4 sw=4 noet:
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)	do { if (c) emsg((s)); } while (0) */
12 #define CHECK(c, s)	do { /**/ } while (0)
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
17  * blocks of memory, backed up by a file. The structure of the information is
18  * a tree.  The root of the tree is a pointer block. The leaves of the tree
19  * are data blocks. In between may be several layers of pointer blocks,
20  * forming branches.
21  *
22  * Three types of blocks are used:
23  * - Block nr 0 contains information for recovery
24  * - Pointer blocks contain list of pointers to other blocks.
25  * - Data blocks contain the actual text.
26  *
27  * Block nr 0 contains the block0 structure (see below).
28  *
29  * Block nr 1 is the first pointer block. It is the root of the tree.
30  * Other pointer blocks are branches.
31  *
32  *  If a line is too big to fit in a single page, the block containing that
33  *  line is made big enough to hold the line. It may span several pages.
34  *  Otherwise all blocks are one page.
35  *
36  *  A data block that was filled when starting to edit a file and was not
37  *  changed since then, can have a negative block number. This means that it
38  *  has not yet been assigned a place in the file. When recovering, the lines
39  *  in this data block can be read from the original file. When the block is
40  *  changed (lines appended/deleted/changed) or when it is flushed it gets a
41  *  positive number. Use mf_trans_del() to get the new number, before calling
42  *  mf_get().
43  */
44 
45 #include "vim.h"
46 
47 #ifndef UNIX		/* it's in os_unix.h for Unix */
48 # include <time.h>
49 #endif
50 
51 #if defined(SASC) || defined(__amigaos4__)
52 # include <proto/dos.h>	    /* for Open() and Close() */
53 #endif
54 
55 typedef struct block0		ZERO_BL;    /* contents of the first block */
56 typedef struct pointer_block	PTR_BL;	    /* contents of a pointer block */
57 typedef struct data_block	DATA_BL;    /* contents of a data block */
58 typedef struct pointer_entry	PTR_EN;	    /* block/line-count pair */
59 
60 #define DATA_ID	       (('d' << 8) + 'a')   /* data block id */
61 #define PTR_ID	       (('p' << 8) + 't')   /* pointer block id */
62 #define BLOCK0_ID0     'b'		    /* block 0 id 0 */
63 #define BLOCK0_ID1     '0'		    /* block 0 id 1 */
64 #define BLOCK0_ID1_C0  'c'		    /* block 0 id 1 'cm' 0 */
65 #define BLOCK0_ID1_C1  'C'		    /* block 0 id 1 'cm' 1 */
66 #define BLOCK0_ID1_C2  'd'		    /* block 0 id 1 'cm' 2 */
67 
68 #if defined(FEAT_CRYPT)
69 static int id1_codes[] = {
70     BLOCK0_ID1_C0,  /* CRYPT_M_ZIP */
71     BLOCK0_ID1_C1,  /* CRYPT_M_BF */
72     BLOCK0_ID1_C2,  /* CRYPT_M_BF2 */
73 };
74 #endif
75 
76 /*
77  * pointer to a block, used in a pointer block
78  */
79 struct pointer_entry
80 {
81     blocknr_T	pe_bnum;	/* block number */
82     linenr_T	pe_line_count;	/* number of lines in this branch */
83     linenr_T	pe_old_lnum;	/* lnum for this block (for recovery) */
84     int		pe_page_count;	/* number of pages in block pe_bnum */
85 };
86 
87 /*
88  * A pointer block contains a list of branches in the tree.
89  */
90 struct pointer_block
91 {
92     short_u	pb_id;		/* ID for pointer block: PTR_ID */
93     short_u	pb_count;	/* number of pointers in this block */
94     short_u	pb_count_max;	/* maximum value for pb_count */
95     PTR_EN	pb_pointer[1];	/* list of pointers to blocks (actually longer)
96 				 * followed by empty space until end of page */
97 };
98 
99 /*
100  * A data block is a leaf in the tree.
101  *
102  * The text of the lines is at the end of the block. The text of the first line
103  * in the block is put at the end, the text of the second line in front of it,
104  * etc. Thus the order of the lines is the opposite of the line number.
105  */
106 struct data_block
107 {
108     short_u	db_id;		/* ID for data block: DATA_ID */
109     unsigned	db_free;	/* free space available */
110     unsigned	db_txt_start;	/* byte where text starts */
111     unsigned	db_txt_end;	/* byte just after data block */
112     linenr_T	db_line_count;	/* number of lines in this block */
113     unsigned	db_index[1];	/* index for start of line (actually bigger)
114 				 * followed by empty space upto db_txt_start
115 				 * followed by the text in the lines until
116 				 * end of page */
117 };
118 
119 /*
120  * The low bits of db_index hold the actual index. The topmost bit is
121  * used for the global command to be able to mark a line.
122  * This method is not clean, but otherwise there would be at least one extra
123  * byte used for each line.
124  * The mark has to be in this place to keep it with the correct line when other
125  * lines are inserted or deleted.
126  */
127 #define DB_MARKED	((unsigned)1 << ((sizeof(unsigned) * 8) - 1))
128 #define DB_INDEX_MASK	(~DB_MARKED)
129 
130 #define INDEX_SIZE  (sizeof(unsigned))	    /* size of one db_index entry */
131 #define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE)  /* size of data block header */
132 
133 #define B0_FNAME_SIZE_ORG	900	/* what it was in older versions */
134 #define B0_FNAME_SIZE_NOCRYPT	898	/* 2 bytes used for other things */
135 #define B0_FNAME_SIZE_CRYPT	890	/* 10 bytes used for other things */
136 #define B0_UNAME_SIZE		40
137 #define B0_HNAME_SIZE		40
138 /*
139  * Restrict the numbers to 32 bits, otherwise most compilers will complain.
140  * This won't detect a 64 bit machine that only swaps a byte in the top 32
141  * bits, but that is crazy anyway.
142  */
143 #define B0_MAGIC_LONG	0x30313233L
144 #define B0_MAGIC_INT	0x20212223L
145 #define B0_MAGIC_SHORT	0x10111213L
146 #define B0_MAGIC_CHAR	0x55
147 
148 /*
149  * Block zero holds all info about the swap file.
150  *
151  * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing
152  * swap files unusable!
153  *
154  * If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!!
155  *
156  * This block is built up of single bytes, to make it portable across
157  * different machines. b0_magic_* is used to check the byte order and size of
158  * variables, because the rest of the swap file is not portable.
159  */
160 struct block0
161 {
162     char_u	b0_id[2];	/* id for block 0: BLOCK0_ID0 and BLOCK0_ID1,
163 				 * BLOCK0_ID1_C0, BLOCK0_ID1_C1, etc. */
164     char_u	b0_version[10];	/* Vim version string */
165     char_u	b0_page_size[4];/* number of bytes per page */
166     char_u	b0_mtime[4];	/* last modification time of file */
167     char_u	b0_ino[4];	/* inode of b0_fname */
168     char_u	b0_pid[4];	/* process id of creator (or 0) */
169     char_u	b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
170     char_u	b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
171     char_u	b0_fname[B0_FNAME_SIZE_ORG]; /* name of file being edited */
172     long	b0_magic_long;	/* check for byte order of long */
173     int		b0_magic_int;	/* check for byte order of int */
174     short	b0_magic_short;	/* check for byte order of short */
175     char_u	b0_magic_char;	/* check for last char */
176 };
177 
178 /*
179  * Note: b0_dirty and b0_flags are put at the end of the file name.  For very
180  * long file names in older versions of Vim they are invalid.
181  * The 'fileencoding' comes before b0_flags, with a NUL in front.  But only
182  * when there is room, for very long file names it's omitted.
183  */
184 #define B0_DIRTY	0x55
185 #define b0_dirty	b0_fname[B0_FNAME_SIZE_ORG - 1]
186 
187 /*
188  * The b0_flags field is new in Vim 7.0.
189  */
190 #define b0_flags	b0_fname[B0_FNAME_SIZE_ORG - 2]
191 
192 /*
193  * Crypt seed goes here, 8 bytes.  New in Vim 7.3.
194  * Without encryption these bytes may be used for 'fenc'.
195  */
196 #define b0_seed		b0_fname[B0_FNAME_SIZE_ORG - 2 - MF_SEED_LEN]
197 
198 /* The lowest two bits contain the fileformat.  Zero means it's not set
199  * (compatible with Vim 6.x), otherwise it's EOL_UNIX + 1, EOL_DOS + 1 or
200  * EOL_MAC + 1. */
201 #define B0_FF_MASK	3
202 
203 /* Swap file is in directory of edited file.  Used to find the file from
204  * different mount points. */
205 #define B0_SAME_DIR	4
206 
207 /* The 'fileencoding' is at the end of b0_fname[], with a NUL in front of it.
208  * When empty there is only the NUL. */
209 #define B0_HAS_FENC	8
210 
211 #define STACK_INCR	5	/* nr of entries added to ml_stack at a time */
212 
213 /*
214  * The line number where the first mark may be is remembered.
215  * If it is 0 there are no marks at all.
216  * (always used for the current buffer only, no buffer change possible while
217  * executing a global command).
218  */
219 static linenr_T	lowest_marked = 0;
220 
221 /*
222  * arguments for ml_find_line()
223  */
224 #define ML_DELETE	0x11	    /* delete line */
225 #define ML_INSERT	0x12	    /* insert line */
226 #define ML_FIND		0x13	    /* just find the line */
227 #define ML_FLUSH	0x02	    /* flush locked block */
228 #define ML_SIMPLE(x)	(x & 0x10)  /* DEL, INS or FIND */
229 
230 /* argument for ml_upd_block0() */
231 typedef enum {
232       UB_FNAME = 0	/* update timestamp and filename */
233     , UB_SAME_DIR       /* update the B0_SAME_DIR flag */
234     , UB_CRYPT		/* update crypt key */
235 } upd_block0_T;
236 
237 #ifdef FEAT_CRYPT
238 static void ml_set_b0_crypt(buf_T *buf, ZERO_BL *b0p);
239 #endif
240 static void ml_upd_block0(buf_T *buf, upd_block0_T what);
241 static void set_b0_fname(ZERO_BL *, buf_T *buf);
242 static void set_b0_dir_flag(ZERO_BL *b0p, buf_T *buf);
243 static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf);
244 static time_t swapfile_info(char_u *);
245 static int recov_file_names(char_u **, char_u *, int prepend_dot);
246 static int ml_append_int(buf_T *, linenr_T, char_u *, colnr_T, int, int);
247 static int ml_delete_int(buf_T *, linenr_T, int);
248 static char_u *findswapname(buf_T *, char_u **, char_u *);
249 static void ml_flush_line(buf_T *);
250 static bhdr_T *ml_new_data(memfile_T *, int, int);
251 static bhdr_T *ml_new_ptr(memfile_T *);
252 static bhdr_T *ml_find_line(buf_T *, linenr_T, int);
253 static int ml_add_stack(buf_T *);
254 static void ml_lineadd(buf_T *, int);
255 static int b0_magic_wrong(ZERO_BL *);
256 #ifdef CHECK_INODE
257 static int fnamecmp_ino(char_u *, char_u *, long);
258 #endif
259 static void long_to_char(long, char_u *);
260 static long char_to_long(char_u *);
261 #ifdef FEAT_CRYPT
262 static cryptstate_T *ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading);
263 #endif
264 #ifdef FEAT_BYTEOFF
265 static void ml_updatechunk(buf_T *buf, long line, long len, int updtype);
266 #endif
267 
268 /*
269  * Open a new memline for "buf".
270  *
271  * Return FAIL for failure, OK otherwise.
272  */
273     int
274 ml_open(buf_T *buf)
275 {
276     memfile_T	*mfp;
277     bhdr_T	*hp = NULL;
278     ZERO_BL	*b0p;
279     PTR_BL	*pp;
280     DATA_BL	*dp;
281 
282     /*
283      * init fields in memline struct
284      */
285     buf->b_ml.ml_stack_size = 0; /* no stack yet */
286     buf->b_ml.ml_stack = NULL;	/* no stack yet */
287     buf->b_ml.ml_stack_top = 0;	/* nothing in the stack */
288     buf->b_ml.ml_locked = NULL;	/* no cached block */
289     buf->b_ml.ml_line_lnum = 0;	/* no cached line */
290 #ifdef FEAT_BYTEOFF
291     buf->b_ml.ml_chunksize = NULL;
292 #endif
293 
294     if (cmdmod.noswapfile)
295 	buf->b_p_swf = FALSE;
296 
297     /*
298      * When 'updatecount' is non-zero swap file may be opened later.
299      */
300     if (p_uc && buf->b_p_swf)
301 	buf->b_may_swap = TRUE;
302     else
303 	buf->b_may_swap = FALSE;
304 
305     /*
306      * Open the memfile.  No swap file is created yet.
307      */
308     mfp = mf_open(NULL, 0);
309     if (mfp == NULL)
310 	goto error;
311 
312     buf->b_ml.ml_mfp = mfp;
313 #ifdef FEAT_CRYPT
314     mfp->mf_buffer = buf;
315 #endif
316     buf->b_ml.ml_flags = ML_EMPTY;
317     buf->b_ml.ml_line_count = 1;
318 #ifdef FEAT_LINEBREAK
319     curwin->w_nrwidth_line_count = 0;
320 #endif
321 
322 /*
323  * fill block0 struct and write page 0
324  */
325     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
326 	goto error;
327     if (hp->bh_bnum != 0)
328     {
329 	iemsg(_("E298: Didn't get block nr 0?"));
330 	goto error;
331     }
332     b0p = (ZERO_BL *)(hp->bh_data);
333 
334     b0p->b0_id[0] = BLOCK0_ID0;
335     b0p->b0_id[1] = BLOCK0_ID1;
336     b0p->b0_magic_long = (long)B0_MAGIC_LONG;
337     b0p->b0_magic_int = (int)B0_MAGIC_INT;
338     b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
339     b0p->b0_magic_char = B0_MAGIC_CHAR;
340     mch_memmove(b0p->b0_version, "VIM ", 4);
341     STRNCPY(b0p->b0_version + 4, Version, 6);
342     long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
343 
344 #ifdef FEAT_SPELL
345     if (!buf->b_spell)
346 #endif
347     {
348 	b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0;
349 	b0p->b0_flags = get_fileformat(buf) + 1;
350 	set_b0_fname(b0p, buf);
351 	(void)get_user_name(b0p->b0_uname, B0_UNAME_SIZE);
352 	b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL;
353 	mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
354 	b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
355 	long_to_char(mch_get_pid(), b0p->b0_pid);
356 #ifdef FEAT_CRYPT
357 	ml_set_b0_crypt(buf, b0p);
358 #endif
359     }
360 
361     /*
362      * Always sync block number 0 to disk, so we can check the file name in
363      * the swap file in findswapname(). Don't do this for a help files or
364      * a spell buffer though.
365      * Only works when there's a swapfile, otherwise it's done when the file
366      * is created.
367      */
368     mf_put(mfp, hp, TRUE, FALSE);
369     if (!buf->b_help && !B_SPELL(buf))
370 	(void)mf_sync(mfp, 0);
371 
372     /*
373      * Fill in root pointer block and write page 1.
374      */
375     if ((hp = ml_new_ptr(mfp)) == NULL)
376 	goto error;
377     if (hp->bh_bnum != 1)
378     {
379 	iemsg(_("E298: Didn't get block nr 1?"));
380 	goto error;
381     }
382     pp = (PTR_BL *)(hp->bh_data);
383     pp->pb_count = 1;
384     pp->pb_pointer[0].pe_bnum = 2;
385     pp->pb_pointer[0].pe_page_count = 1;
386     pp->pb_pointer[0].pe_old_lnum = 1;
387     pp->pb_pointer[0].pe_line_count = 1;    /* line count after insertion */
388     mf_put(mfp, hp, TRUE, FALSE);
389 
390     /*
391      * Allocate first data block and create an empty line 1.
392      */
393     if ((hp = ml_new_data(mfp, FALSE, 1)) == NULL)
394 	goto error;
395     if (hp->bh_bnum != 2)
396     {
397 	iemsg(_("E298: Didn't get block nr 2?"));
398 	goto error;
399     }
400 
401     dp = (DATA_BL *)(hp->bh_data);
402     dp->db_index[0] = --dp->db_txt_start;	/* at end of block */
403     dp->db_free -= 1 + INDEX_SIZE;
404     dp->db_line_count = 1;
405     *((char_u *)dp + dp->db_txt_start) = NUL;	/* empty line */
406 
407     return OK;
408 
409 error:
410     if (mfp != NULL)
411     {
412 	if (hp)
413 	    mf_put(mfp, hp, FALSE, FALSE);
414 	mf_close(mfp, TRUE);	    /* will also free(mfp->mf_fname) */
415     }
416     buf->b_ml.ml_mfp = NULL;
417     return FAIL;
418 }
419 
420 #if defined(FEAT_CRYPT) || defined(PROTO)
421 /*
422  * Prepare encryption for "buf" for the current key and method.
423  */
424     static void
425 ml_set_mfp_crypt(buf_T *buf)
426 {
427     if (*buf->b_p_key != NUL)
428     {
429 	int method_nr = crypt_get_method_nr(buf);
430 
431 	if (method_nr > CRYPT_M_ZIP)
432 	{
433 	    /* Generate a seed and store it in the memfile. */
434 	    sha2_seed(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN, NULL, 0);
435 	}
436     }
437 }
438 
439 /*
440  * Prepare encryption for "buf" with block 0 "b0p".
441  */
442     static void
443 ml_set_b0_crypt(buf_T *buf, ZERO_BL *b0p)
444 {
445     if (*buf->b_p_key == NUL)
446 	b0p->b0_id[1] = BLOCK0_ID1;
447     else
448     {
449 	int method_nr = crypt_get_method_nr(buf);
450 
451 	b0p->b0_id[1] = id1_codes[method_nr];
452 	if (method_nr > CRYPT_M_ZIP)
453 	{
454 	    /* Generate a seed and store it in block 0 and in the memfile. */
455 	    sha2_seed(&b0p->b0_seed, MF_SEED_LEN, NULL, 0);
456 	    mch_memmove(buf->b_ml.ml_mfp->mf_seed, &b0p->b0_seed, MF_SEED_LEN);
457 	}
458     }
459 }
460 
461 /*
462  * Called after the crypt key or 'cryptmethod' was changed for "buf".
463  * Will apply this to the swapfile.
464  * "old_key" is the previous key.  It is equal to buf->b_p_key when
465  * 'cryptmethod' is changed.
466  * "old_cm" is the previous 'cryptmethod'.  It is equal to the current
467  * 'cryptmethod' when 'key' is changed.
468  */
469     void
470 ml_set_crypt_key(
471     buf_T	*buf,
472     char_u	*old_key,
473     char_u	*old_cm)
474 {
475     memfile_T	*mfp = buf->b_ml.ml_mfp;
476     bhdr_T	*hp;
477     int		page_count;
478     int		idx;
479     long	error;
480     infoptr_T	*ip;
481     PTR_BL	*pp;
482     DATA_BL	*dp;
483     blocknr_T	bnum;
484     int		top;
485     int		old_method;
486 
487     if (mfp == NULL)
488 	return;  /* no memfile yet, nothing to do */
489     old_method = crypt_method_nr_from_name(old_cm);
490 
491     /* First make sure the swapfile is in a consistent state, using the old
492      * key and method. */
493     {
494 	char_u *new_key = buf->b_p_key;
495 	char_u *new_buf_cm = buf->b_p_cm;
496 
497 	buf->b_p_key = old_key;
498 	buf->b_p_cm = old_cm;
499 	ml_preserve(buf, FALSE);
500 	buf->b_p_key = new_key;
501 	buf->b_p_cm = new_buf_cm;
502     }
503 
504     /* Set the key, method and seed to be used for reading, these must be the
505      * old values. */
506     mfp->mf_old_key = old_key;
507     mfp->mf_old_cm = old_method;
508     if (old_method > 0 && *old_key != NUL)
509 	mch_memmove(mfp->mf_old_seed, mfp->mf_seed, MF_SEED_LEN);
510 
511     /* Update block 0 with the crypt flag and may set a new seed. */
512     ml_upd_block0(buf, UB_CRYPT);
513 
514     if (mfp->mf_infile_count > 2)
515     {
516 	/*
517 	 * Need to read back all data blocks from disk, decrypt them with the
518 	 * old key/method and mark them to be written. The algorithm is
519 	 * similar to what happens in ml_recover(), but we skip negative block
520 	 * numbers.
521 	 */
522 	ml_flush_line(buf);		    /* flush buffered line */
523 	(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */
524 
525 	hp = NULL;
526 	bnum = 1;		/* start with block 1 */
527 	page_count = 1;		/* which is 1 page */
528 	idx = 0;		/* start with first index in block 1 */
529 	error = 0;
530 	buf->b_ml.ml_stack_top = 0;
531 	VIM_CLEAR(buf->b_ml.ml_stack);
532 	buf->b_ml.ml_stack_size = 0;	/* no stack yet */
533 
534 	for ( ; !got_int; line_breakcheck())
535 	{
536 	    if (hp != NULL)
537 		mf_put(mfp, hp, FALSE, FALSE);	/* release previous block */
538 
539 	    /* get the block (pointer or data) */
540 	    if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL)
541 	    {
542 		if (bnum == 1)
543 		    break;
544 		++error;
545 	    }
546 	    else
547 	    {
548 		pp = (PTR_BL *)(hp->bh_data);
549 		if (pp->pb_id == PTR_ID)	/* it is a pointer block */
550 		{
551 		    if (pp->pb_count == 0)
552 		    {
553 			/* empty block? */
554 			++error;
555 		    }
556 		    else if (idx < (int)pp->pb_count)	/* go a block deeper */
557 		    {
558 			if (pp->pb_pointer[idx].pe_bnum < 0)
559 			{
560 			    /* Skip data block with negative block number.
561 			     * Should not happen, because of the ml_preserve()
562 			     * above. Get same block again for next index. */
563 			    ++idx;
564 			    continue;
565 			}
566 
567 			/* going one block deeper in the tree, new entry in
568 			 * stack */
569 			if ((top = ml_add_stack(buf)) < 0)
570 			{
571 			    ++error;
572 			    break;		    /* out of memory */
573 			}
574 			ip = &(buf->b_ml.ml_stack[top]);
575 			ip->ip_bnum = bnum;
576 			ip->ip_index = idx;
577 
578 			bnum = pp->pb_pointer[idx].pe_bnum;
579 			page_count = pp->pb_pointer[idx].pe_page_count;
580 			idx = 0;
581 			continue;
582 		    }
583 		}
584 		else	    /* not a pointer block */
585 		{
586 		    dp = (DATA_BL *)(hp->bh_data);
587 		    if (dp->db_id != DATA_ID)	/* block id wrong */
588 			++error;
589 		    else
590 		    {
591 			/* It is a data block, need to write it back to disk. */
592 			mf_put(mfp, hp, TRUE, FALSE);
593 			hp = NULL;
594 		    }
595 		}
596 	    }
597 
598 	    if (buf->b_ml.ml_stack_top == 0)	/* finished */
599 		break;
600 
601 	    /* go one block up in the tree */
602 	    ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
603 	    bnum = ip->ip_bnum;
604 	    idx = ip->ip_index + 1;	    /* go to next index */
605 	    page_count = 1;
606 	}
607 	if (hp != NULL)
608 	    mf_put(mfp, hp, FALSE, FALSE);  /* release previous block */
609 
610 	if (error > 0)
611 	    emsg(_("E843: Error while updating swap file crypt"));
612     }
613 
614     mfp->mf_old_key = NULL;
615 }
616 #endif
617 
618 /*
619  * ml_setname() is called when the file name of "buf" has been changed.
620  * It may rename the swap file.
621  */
622     void
623 ml_setname(buf_T *buf)
624 {
625     int		success = FALSE;
626     memfile_T	*mfp;
627     char_u	*fname;
628     char_u	*dirp;
629 #if defined(MSWIN)
630     char_u	*p;
631 #endif
632 
633     mfp = buf->b_ml.ml_mfp;
634     if (mfp->mf_fd < 0)		    /* there is no swap file yet */
635     {
636 	/*
637 	 * When 'updatecount' is 0 and 'noswapfile' there is no swap file.
638 	 * For help files we will make a swap file now.
639 	 */
640 	if (p_uc != 0 && !cmdmod.noswapfile)
641 	    ml_open_file(buf);	    /* create a swap file */
642 	return;
643     }
644 
645     /*
646      * Try all directories in the 'directory' option.
647      */
648     dirp = p_dir;
649     for (;;)
650     {
651 	if (*dirp == NUL)	    /* tried all directories, fail */
652 	    break;
653 	fname = findswapname(buf, &dirp, mfp->mf_fname);
654 						    /* alloc's fname */
655 	if (dirp == NULL)	    /* out of memory */
656 	    break;
657 	if (fname == NULL)	    /* no file name found for this dir */
658 	    continue;
659 
660 #if defined(MSWIN)
661 	/*
662 	 * Set full pathname for swap file now, because a ":!cd dir" may
663 	 * change directory without us knowing it.
664 	 */
665 	p = FullName_save(fname, FALSE);
666 	vim_free(fname);
667 	fname = p;
668 	if (fname == NULL)
669 	    continue;
670 #endif
671 	/* if the file name is the same we don't have to do anything */
672 	if (fnamecmp(fname, mfp->mf_fname) == 0)
673 	{
674 	    vim_free(fname);
675 	    success = TRUE;
676 	    break;
677 	}
678 	/* need to close the swap file before renaming */
679 	if (mfp->mf_fd >= 0)
680 	{
681 	    close(mfp->mf_fd);
682 	    mfp->mf_fd = -1;
683 	}
684 
685 	/* try to rename the swap file */
686 	if (vim_rename(mfp->mf_fname, fname) == 0)
687 	{
688 	    success = TRUE;
689 	    vim_free(mfp->mf_fname);
690 	    mfp->mf_fname = fname;
691 	    vim_free(mfp->mf_ffname);
692 #if defined(MSWIN)
693 	    mfp->mf_ffname = NULL;  /* mf_fname is full pathname already */
694 #else
695 	    mf_set_ffname(mfp);
696 #endif
697 	    ml_upd_block0(buf, UB_SAME_DIR);
698 	    break;
699 	}
700 	vim_free(fname);	    /* this fname didn't work, try another */
701     }
702 
703     if (mfp->mf_fd == -1)	    /* need to (re)open the swap file */
704     {
705 	mfp->mf_fd = mch_open((char *)mfp->mf_fname, O_RDWR | O_EXTRA, 0);
706 	if (mfp->mf_fd < 0)
707 	{
708 	    /* could not (re)open the swap file, what can we do???? */
709 	    emsg(_("E301: Oops, lost the swap file!!!"));
710 	    return;
711 	}
712 #ifdef HAVE_FD_CLOEXEC
713 	{
714 	    int fdflags = fcntl(mfp->mf_fd, F_GETFD);
715 	    if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
716 		(void)fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
717 	}
718 #endif
719     }
720     if (!success)
721 	emsg(_("E302: Could not rename swap file"));
722 }
723 
724 /*
725  * Open a file for the memfile for all buffers that are not readonly or have
726  * been modified.
727  * Used when 'updatecount' changes from zero to non-zero.
728  */
729     void
730 ml_open_files(void)
731 {
732     buf_T	*buf;
733 
734     FOR_ALL_BUFFERS(buf)
735 	if (!buf->b_p_ro || buf->b_changed)
736 	    ml_open_file(buf);
737 }
738 
739 /*
740  * Open a swap file for an existing memfile, if there is no swap file yet.
741  * If we are unable to find a file name, mf_fname will be NULL
742  * and the memfile will be in memory only (no recovery possible).
743  */
744     void
745 ml_open_file(buf_T *buf)
746 {
747     memfile_T	*mfp;
748     char_u	*fname;
749     char_u	*dirp;
750 
751     mfp = buf->b_ml.ml_mfp;
752     if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf || cmdmod.noswapfile)
753 	return;		/* nothing to do */
754 
755 #ifdef FEAT_SPELL
756     /* For a spell buffer use a temp file name. */
757     if (buf->b_spell)
758     {
759 	fname = vim_tempname('s', FALSE);
760 	if (fname != NULL)
761 	    (void)mf_open_file(mfp, fname);	/* consumes fname! */
762 	buf->b_may_swap = FALSE;
763 	return;
764     }
765 #endif
766 
767     /*
768      * Try all directories in 'directory' option.
769      */
770     dirp = p_dir;
771     for (;;)
772     {
773 	if (*dirp == NUL)
774 	    break;
775 	/* There is a small chance that between choosing the swap file name
776 	 * and creating it, another Vim creates the file.  In that case the
777 	 * creation will fail and we will use another directory. */
778 	fname = findswapname(buf, &dirp, NULL); /* allocates fname */
779 	if (dirp == NULL)
780 	    break;  /* out of memory */
781 	if (fname == NULL)
782 	    continue;
783 	if (mf_open_file(mfp, fname) == OK)	/* consumes fname! */
784 	{
785 #if defined(MSWIN)
786 	    /*
787 	     * set full pathname for swap file now, because a ":!cd dir" may
788 	     * change directory without us knowing it.
789 	     */
790 	    mf_fullname(mfp);
791 #endif
792 	    ml_upd_block0(buf, UB_SAME_DIR);
793 
794 	    /* Flush block zero, so others can read it */
795 	    if (mf_sync(mfp, MFS_ZERO) == OK)
796 	    {
797 		/* Mark all blocks that should be in the swapfile as dirty.
798 		 * Needed for when the 'swapfile' option was reset, so that
799 		 * the swap file was deleted, and then on again. */
800 		mf_set_dirty(mfp);
801 		break;
802 	    }
803 	    /* Writing block 0 failed: close the file and try another dir */
804 	    mf_close_file(buf, FALSE);
805 	}
806     }
807 
808     if (mfp->mf_fname == NULL)		/* Failed! */
809     {
810 	need_wait_return = TRUE;	/* call wait_return later */
811 	++no_wait_return;
812 	(void)semsg(_("E303: Unable to open swap file for \"%s\", recovery impossible"),
813 		    buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname);
814 	--no_wait_return;
815     }
816 
817     /* don't try to open a swap file again */
818     buf->b_may_swap = FALSE;
819 }
820 
821 /*
822  * If still need to create a swap file, and starting to edit a not-readonly
823  * file, or reading into an existing buffer, create a swap file now.
824  */
825     void
826 check_need_swap(
827     int	    newfile)		// reading file into new buffer
828 {
829     int old_msg_silent = msg_silent; // might be reset by an E325 message
830 
831     if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile))
832 	ml_open_file(curbuf);
833     msg_silent = old_msg_silent;
834 }
835 
836 /*
837  * Close memline for buffer 'buf'.
838  * If 'del_file' is TRUE, delete the swap file
839  */
840     void
841 ml_close(buf_T *buf, int del_file)
842 {
843     if (buf->b_ml.ml_mfp == NULL)		/* not open */
844 	return;
845     mf_close(buf->b_ml.ml_mfp, del_file);	/* close the .swp file */
846     if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
847 	vim_free(buf->b_ml.ml_line_ptr);
848     vim_free(buf->b_ml.ml_stack);
849 #ifdef FEAT_BYTEOFF
850     VIM_CLEAR(buf->b_ml.ml_chunksize);
851 #endif
852     buf->b_ml.ml_mfp = NULL;
853 
854     /* Reset the "recovered" flag, give the ATTENTION prompt the next time
855      * this buffer is loaded. */
856     buf->b_flags &= ~BF_RECOVERED;
857 }
858 
859 /*
860  * Close all existing memlines and memfiles.
861  * Only used when exiting.
862  * When 'del_file' is TRUE, delete the memfiles.
863  * But don't delete files that were ":preserve"d when we are POSIX compatible.
864  */
865     void
866 ml_close_all(int del_file)
867 {
868     buf_T	*buf;
869 
870     FOR_ALL_BUFFERS(buf)
871 	ml_close(buf, del_file && ((buf->b_flags & BF_PRESERVED) == 0
872 				 || vim_strchr(p_cpo, CPO_PRESERVE) == NULL));
873 #ifdef FEAT_SPELL
874     spell_delete_wordlist();	/* delete the internal wordlist */
875 #endif
876 #ifdef TEMPDIRNAMES
877     vim_deltempdir();		/* delete created temp directory */
878 #endif
879 }
880 
881 /*
882  * Close all memfiles for not modified buffers.
883  * Only use just before exiting!
884  */
885     void
886 ml_close_notmod(void)
887 {
888     buf_T	*buf;
889 
890     FOR_ALL_BUFFERS(buf)
891 	if (!bufIsChanged(buf))
892 	    ml_close(buf, TRUE);    /* close all not-modified buffers */
893 }
894 
895 /*
896  * Update the timestamp in the .swp file.
897  * Used when the file has been written.
898  */
899     void
900 ml_timestamp(buf_T *buf)
901 {
902     ml_upd_block0(buf, UB_FNAME);
903 }
904 
905 /*
906  * Return FAIL when the ID of "b0p" is wrong.
907  */
908     static int
909 ml_check_b0_id(ZERO_BL *b0p)
910 {
911     if (b0p->b0_id[0] != BLOCK0_ID0
912 	    || (b0p->b0_id[1] != BLOCK0_ID1
913 		&& b0p->b0_id[1] != BLOCK0_ID1_C0
914 		&& b0p->b0_id[1] != BLOCK0_ID1_C1
915 		&& b0p->b0_id[1] != BLOCK0_ID1_C2)
916 	    )
917 	return FAIL;
918     return OK;
919 }
920 
921 /*
922  * Update the timestamp or the B0_SAME_DIR flag of the .swp file.
923  */
924     static void
925 ml_upd_block0(buf_T *buf, upd_block0_T what)
926 {
927     memfile_T	*mfp;
928     bhdr_T	*hp;
929     ZERO_BL	*b0p;
930 
931     mfp = buf->b_ml.ml_mfp;
932     if (mfp == NULL)
933 	return;
934     hp = mf_get(mfp, (blocknr_T)0, 1);
935     if (hp == NULL)
936     {
937 #ifdef FEAT_CRYPT
938 	/* Possibly update the seed in the memfile before there is a block0. */
939 	if (what == UB_CRYPT)
940 	    ml_set_mfp_crypt(buf);
941 #endif
942 	return;
943     }
944 
945     b0p = (ZERO_BL *)(hp->bh_data);
946     if (ml_check_b0_id(b0p) == FAIL)
947 	iemsg(_("E304: ml_upd_block0(): Didn't get block 0??"));
948     else
949     {
950 	if (what == UB_FNAME)
951 	    set_b0_fname(b0p, buf);
952 #ifdef FEAT_CRYPT
953 	else if (what == UB_CRYPT)
954 	    ml_set_b0_crypt(buf, b0p);
955 #endif
956 	else /* what == UB_SAME_DIR */
957 	    set_b0_dir_flag(b0p, buf);
958     }
959     mf_put(mfp, hp, TRUE, FALSE);
960 }
961 
962 /*
963  * Write file name and timestamp into block 0 of a swap file.
964  * Also set buf->b_mtime.
965  * Don't use NameBuff[]!!!
966  */
967     static void
968 set_b0_fname(ZERO_BL *b0p, buf_T *buf)
969 {
970     stat_T	st;
971 
972     if (buf->b_ffname == NULL)
973 	b0p->b0_fname[0] = NUL;
974     else
975     {
976 #if defined(MSWIN) || defined(AMIGA)
977 	/* Systems that cannot translate "~user" back into a path: copy the
978 	 * file name unmodified.  Do use slashes instead of backslashes for
979 	 * portability. */
980 	vim_strncpy(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE_CRYPT - 1);
981 # ifdef BACKSLASH_IN_FILENAME
982 	forward_slash(b0p->b0_fname);
983 # endif
984 #else
985 	size_t	flen, ulen;
986 	char_u	uname[B0_UNAME_SIZE];
987 
988 	/*
989 	 * For a file under the home directory of the current user, we try to
990 	 * replace the home directory path with "~user". This helps when
991 	 * editing the same file on different machines over a network.
992 	 * First replace home dir path with "~/" with home_replace().
993 	 * Then insert the user name to get "~user/".
994 	 */
995 	home_replace(NULL, buf->b_ffname, b0p->b0_fname,
996 						   B0_FNAME_SIZE_CRYPT, TRUE);
997 	if (b0p->b0_fname[0] == '~')
998 	{
999 	    flen = STRLEN(b0p->b0_fname);
1000 	    /* If there is no user name or it is too long, don't use "~/" */
1001 	    if (get_user_name(uname, B0_UNAME_SIZE) == FAIL
1002 		   || (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE_CRYPT - 1)
1003 		vim_strncpy(b0p->b0_fname, buf->b_ffname,
1004 						     B0_FNAME_SIZE_CRYPT - 1);
1005 	    else
1006 	    {
1007 		mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
1008 		mch_memmove(b0p->b0_fname + 1, uname, ulen);
1009 	    }
1010 	}
1011 #endif
1012 	if (mch_stat((char *)buf->b_ffname, &st) >= 0)
1013 	{
1014 	    long_to_char((long)st.st_mtime, b0p->b0_mtime);
1015 #ifdef CHECK_INODE
1016 	    long_to_char((long)st.st_ino, b0p->b0_ino);
1017 #endif
1018 	    buf_store_time(buf, &st, buf->b_ffname);
1019 	    buf->b_mtime_read = buf->b_mtime;
1020 	}
1021 	else
1022 	{
1023 	    long_to_char(0L, b0p->b0_mtime);
1024 #ifdef CHECK_INODE
1025 	    long_to_char(0L, b0p->b0_ino);
1026 #endif
1027 	    buf->b_mtime = 0;
1028 	    buf->b_mtime_read = 0;
1029 	    buf->b_orig_size = 0;
1030 	    buf->b_orig_mode = 0;
1031 	}
1032     }
1033 
1034     /* Also add the 'fileencoding' if there is room. */
1035     add_b0_fenc(b0p, curbuf);
1036 }
1037 
1038 /*
1039  * Update the B0_SAME_DIR flag of the swap file.  It's set if the file and the
1040  * swapfile for "buf" are in the same directory.
1041  * This is fail safe: if we are not sure the directories are equal the flag is
1042  * not set.
1043  */
1044     static void
1045 set_b0_dir_flag(ZERO_BL *b0p, buf_T *buf)
1046 {
1047     if (same_directory(buf->b_ml.ml_mfp->mf_fname, buf->b_ffname))
1048 	b0p->b0_flags |= B0_SAME_DIR;
1049     else
1050 	b0p->b0_flags &= ~B0_SAME_DIR;
1051 }
1052 
1053 /*
1054  * When there is room, add the 'fileencoding' to block zero.
1055  */
1056     static void
1057 add_b0_fenc(
1058     ZERO_BL	*b0p,
1059     buf_T	*buf)
1060 {
1061     int		n;
1062     int		size = B0_FNAME_SIZE_NOCRYPT;
1063 
1064 #ifdef FEAT_CRYPT
1065     /* Without encryption use the same offset as in Vim 7.2 to be compatible.
1066      * With encryption it's OK to move elsewhere, the swap file is not
1067      * compatible anyway. */
1068     if (*buf->b_p_key != NUL)
1069 	size = B0_FNAME_SIZE_CRYPT;
1070 #endif
1071 
1072     n = (int)STRLEN(buf->b_p_fenc);
1073     if ((int)STRLEN(b0p->b0_fname) + n + 1 > size)
1074 	b0p->b0_flags &= ~B0_HAS_FENC;
1075     else
1076     {
1077 	mch_memmove((char *)b0p->b0_fname + size - n,
1078 					    (char *)buf->b_p_fenc, (size_t)n);
1079 	*(b0p->b0_fname + size - n - 1) = NUL;
1080 	b0p->b0_flags |= B0_HAS_FENC;
1081     }
1082 }
1083 
1084 
1085 /*
1086  * Try to recover curbuf from the .swp file.
1087  */
1088     void
1089 ml_recover(void)
1090 {
1091     buf_T	*buf = NULL;
1092     memfile_T	*mfp = NULL;
1093     char_u	*fname;
1094     char_u	*fname_used = NULL;
1095     bhdr_T	*hp = NULL;
1096     ZERO_BL	*b0p;
1097     int		b0_ff;
1098     char_u	*b0_fenc = NULL;
1099 #ifdef FEAT_CRYPT
1100     int		b0_cm = -1;
1101 #endif
1102     PTR_BL	*pp;
1103     DATA_BL	*dp;
1104     infoptr_T	*ip;
1105     blocknr_T	bnum;
1106     int		page_count;
1107     stat_T	org_stat, swp_stat;
1108     int		len;
1109     int		directly;
1110     linenr_T	lnum;
1111     char_u	*p;
1112     int		i;
1113     long	error;
1114     int		cannot_open;
1115     linenr_T	line_count;
1116     int		has_error;
1117     int		idx;
1118     int		top;
1119     int		txt_start;
1120     off_T	size;
1121     int		called_from_main;
1122     int		serious_error = TRUE;
1123     long	mtime;
1124     int		attr;
1125     int		orig_file_status = NOTDONE;
1126 
1127     recoverymode = TRUE;
1128     called_from_main = (curbuf->b_ml.ml_mfp == NULL);
1129     attr = HL_ATTR(HLF_E);
1130 
1131     /*
1132      * If the file name ends in ".s[a-w][a-z]" we assume this is the swap file.
1133      * Otherwise a search is done to find the swap file(s).
1134      */
1135     fname = curbuf->b_fname;
1136     if (fname == NULL)		    /* When there is no file name */
1137 	fname = (char_u *)"";
1138     len = (int)STRLEN(fname);
1139     if (len >= 4 &&
1140 #if defined(VMS)
1141 	    STRNICMP(fname + len - 4, "_s", 2)
1142 #else
1143 	    STRNICMP(fname + len - 4, ".s", 2)
1144 #endif
1145 						== 0
1146 		&& vim_strchr((char_u *)"abcdefghijklmnopqrstuvw",
1147 					   TOLOWER_ASC(fname[len - 2])) != NULL
1148 		&& ASCII_ISALPHA(fname[len - 1]))
1149     {
1150 	directly = TRUE;
1151 	fname_used = vim_strsave(fname); /* make a copy for mf_open() */
1152     }
1153     else
1154     {
1155 	directly = FALSE;
1156 
1157 	/* count the number of matching swap files */
1158 	len = recover_names(fname, FALSE, 0, NULL);
1159 	if (len == 0)		    /* no swap files found */
1160 	{
1161 	    semsg(_("E305: No swap file found for %s"), fname);
1162 	    goto theend;
1163 	}
1164 	if (len == 1)		    /* one swap file found, use it */
1165 	    i = 1;
1166 	else			    /* several swap files found, choose */
1167 	{
1168 	    /* list the names of the swap files */
1169 	    (void)recover_names(fname, TRUE, 0, NULL);
1170 	    msg_putchar('\n');
1171 	    msg_puts(_("Enter number of swap file to use (0 to quit): "));
1172 	    i = get_number(FALSE, NULL);
1173 	    if (i < 1 || i > len)
1174 		goto theend;
1175 	}
1176 	/* get the swap file name that will be used */
1177 	(void)recover_names(fname, FALSE, i, &fname_used);
1178     }
1179     if (fname_used == NULL)
1180 	goto theend;			/* out of memory */
1181 
1182     /* When called from main() still need to initialize storage structure */
1183     if (called_from_main && ml_open(curbuf) == FAIL)
1184 	getout(1);
1185 
1186     /*
1187      * Allocate a buffer structure for the swap file that is used for recovery.
1188      * Only the memline and crypt information in it are really used.
1189      */
1190     buf = (buf_T *)alloc((unsigned)sizeof(buf_T));
1191     if (buf == NULL)
1192 	goto theend;
1193 
1194     /*
1195      * init fields in memline struct
1196      */
1197     buf->b_ml.ml_stack_size = 0;	/* no stack yet */
1198     buf->b_ml.ml_stack = NULL;		/* no stack yet */
1199     buf->b_ml.ml_stack_top = 0;		/* nothing in the stack */
1200     buf->b_ml.ml_line_lnum = 0;		/* no cached line */
1201     buf->b_ml.ml_locked = NULL;		/* no locked block */
1202     buf->b_ml.ml_flags = 0;
1203 #ifdef FEAT_CRYPT
1204     buf->b_p_key = empty_option;
1205     buf->b_p_cm = empty_option;
1206 #endif
1207 
1208     /*
1209      * open the memfile from the old swap file
1210      */
1211     p = vim_strsave(fname_used); /* save "fname_used" for the message:
1212 				    mf_open() will consume "fname_used"! */
1213     mfp = mf_open(fname_used, O_RDONLY);
1214     fname_used = p;
1215     if (mfp == NULL || mfp->mf_fd < 0)
1216     {
1217 	if (fname_used != NULL)
1218 	    semsg(_("E306: Cannot open %s"), fname_used);
1219 	goto theend;
1220     }
1221     buf->b_ml.ml_mfp = mfp;
1222 #ifdef FEAT_CRYPT
1223     mfp->mf_buffer = buf;
1224 #endif
1225 
1226     /*
1227      * The page size set in mf_open() might be different from the page size
1228      * used in the swap file, we must get it from block 0.  But to read block
1229      * 0 we need a page size.  Use the minimal size for block 0 here, it will
1230      * be set to the real value below.
1231      */
1232     mfp->mf_page_size = MIN_SWAP_PAGE_SIZE;
1233 
1234     /*
1235      * try to read block 0
1236      */
1237     if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL)
1238     {
1239 	msg_start();
1240 	msg_puts_attr(_("Unable to read block 0 from "), attr | MSG_HIST);
1241 	msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
1242 	msg_puts_attr(_("\nMaybe no changes were made or Vim did not update the swap file."),
1243 		attr | MSG_HIST);
1244 	msg_end();
1245 	goto theend;
1246     }
1247     b0p = (ZERO_BL *)(hp->bh_data);
1248     if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0)
1249     {
1250 	msg_start();
1251 	msg_outtrans_attr(mfp->mf_fname, MSG_HIST);
1252 	msg_puts_attr(_(" cannot be used with this version of Vim.\n"),
1253 								    MSG_HIST);
1254 	msg_puts_attr(_("Use Vim version 3.0.\n"), MSG_HIST);
1255 	msg_end();
1256 	goto theend;
1257     }
1258     if (ml_check_b0_id(b0p) == FAIL)
1259     {
1260 	semsg(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname);
1261 	goto theend;
1262     }
1263     if (b0_magic_wrong(b0p))
1264     {
1265 	msg_start();
1266 	msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
1267 #if defined(MSWIN)
1268 	if (STRNCMP(b0p->b0_hname, "PC ", 3) == 0)
1269 	    msg_puts_attr(_(" cannot be used with this version of Vim.\n"),
1270 							     attr | MSG_HIST);
1271 	else
1272 #endif
1273 	    msg_puts_attr(_(" cannot be used on this computer.\n"),
1274 							     attr | MSG_HIST);
1275 	msg_puts_attr(_("The file was created on "), attr | MSG_HIST);
1276 	/* avoid going past the end of a corrupted hostname */
1277 	b0p->b0_fname[0] = NUL;
1278 	msg_puts_attr((char *)b0p->b0_hname, attr | MSG_HIST);
1279 	msg_puts_attr(_(",\nor the file has been damaged."), attr | MSG_HIST);
1280 	msg_end();
1281 	goto theend;
1282     }
1283 
1284 #ifdef FEAT_CRYPT
1285     for (i = 0; i < (int)(sizeof(id1_codes) / sizeof(int)); ++i)
1286 	if (id1_codes[i] == b0p->b0_id[1])
1287 	    b0_cm = i;
1288     if (b0_cm > 0)
1289 	mch_memmove(mfp->mf_seed, &b0p->b0_seed, MF_SEED_LEN);
1290     crypt_set_cm_option(buf, b0_cm < 0 ? 0 : b0_cm);
1291 #else
1292     if (b0p->b0_id[1] != BLOCK0_ID1)
1293     {
1294 	semsg(_("E833: %s is encrypted and this version of Vim does not support encryption"), mfp->mf_fname);
1295 	goto theend;
1296     }
1297 #endif
1298 
1299     /*
1300      * If we guessed the wrong page size, we have to recalculate the
1301      * highest block number in the file.
1302      */
1303     if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size))
1304     {
1305 	unsigned previous_page_size = mfp->mf_page_size;
1306 
1307 	mf_new_page_size(mfp, (unsigned)char_to_long(b0p->b0_page_size));
1308 	if (mfp->mf_page_size < previous_page_size)
1309 	{
1310 	    msg_start();
1311 	    msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST);
1312 	    msg_puts_attr(_(" has been damaged (page size is smaller than minimum value).\n"),
1313 			attr | MSG_HIST);
1314 	    msg_end();
1315 	    goto theend;
1316 	}
1317 	if ((size = vim_lseek(mfp->mf_fd, (off_T)0L, SEEK_END)) <= 0)
1318 	    mfp->mf_blocknr_max = 0;	    /* no file or empty file */
1319 	else
1320 	    mfp->mf_blocknr_max = (blocknr_T)(size / mfp->mf_page_size);
1321 	mfp->mf_infile_count = mfp->mf_blocknr_max;
1322 
1323 	/* need to reallocate the memory used to store the data */
1324 	p = alloc(mfp->mf_page_size);
1325 	if (p == NULL)
1326 	    goto theend;
1327 	mch_memmove(p, hp->bh_data, previous_page_size);
1328 	vim_free(hp->bh_data);
1329 	hp->bh_data = p;
1330 	b0p = (ZERO_BL *)(hp->bh_data);
1331     }
1332 
1333     /*
1334      * If .swp file name given directly, use name from swap file for buffer.
1335      */
1336     if (directly)
1337     {
1338 	expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
1339 	if (setfname(curbuf, NameBuff, NULL, TRUE) == FAIL)
1340 	    goto theend;
1341     }
1342 
1343     home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, TRUE);
1344     smsg(_("Using swap file \"%s\""), NameBuff);
1345 
1346     if (buf_spname(curbuf) != NULL)
1347 	vim_strncpy(NameBuff, buf_spname(curbuf), MAXPATHL - 1);
1348     else
1349 	home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, TRUE);
1350     smsg(_("Original file \"%s\""), NameBuff);
1351     msg_putchar('\n');
1352 
1353     /*
1354      * check date of swap file and original file
1355      */
1356     mtime = char_to_long(b0p->b0_mtime);
1357     if (curbuf->b_ffname != NULL
1358 	    && mch_stat((char *)curbuf->b_ffname, &org_stat) != -1
1359 	    && ((mch_stat((char *)mfp->mf_fname, &swp_stat) != -1
1360 		    && org_stat.st_mtime > swp_stat.st_mtime)
1361 		|| org_stat.st_mtime != mtime))
1362     {
1363 	emsg(_("E308: Warning: Original file may have been changed"));
1364     }
1365     out_flush();
1366 
1367     /* Get the 'fileformat' and 'fileencoding' from block zero. */
1368     b0_ff = (b0p->b0_flags & B0_FF_MASK);
1369     if (b0p->b0_flags & B0_HAS_FENC)
1370     {
1371 	int fnsize = B0_FNAME_SIZE_NOCRYPT;
1372 
1373 #ifdef FEAT_CRYPT
1374 	/* Use the same size as in add_b0_fenc(). */
1375 	if (b0p->b0_id[1] != BLOCK0_ID1)
1376 	    fnsize = B0_FNAME_SIZE_CRYPT;
1377 #endif
1378 	for (p = b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; --p)
1379 	    ;
1380 	b0_fenc = vim_strnsave(p, (int)(b0p->b0_fname + fnsize - p));
1381     }
1382 
1383     mf_put(mfp, hp, FALSE, FALSE);	/* release block 0 */
1384     hp = NULL;
1385 
1386     /*
1387      * Now that we are sure that the file is going to be recovered, clear the
1388      * contents of the current buffer.
1389      */
1390     while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
1391 	ml_delete((linenr_T)1, FALSE);
1392 
1393     /*
1394      * Try reading the original file to obtain the values of 'fileformat',
1395      * 'fileencoding', etc.  Ignore errors.  The text itself is not used.
1396      * When the file is encrypted the user is asked to enter the key.
1397      */
1398     if (curbuf->b_ffname != NULL)
1399 	orig_file_status = readfile(curbuf->b_ffname, NULL, (linenr_T)0,
1400 			      (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW);
1401 
1402 #ifdef FEAT_CRYPT
1403     if (b0_cm >= 0)
1404     {
1405 	/* Need to ask the user for the crypt key.  If this fails we continue
1406 	 * without a key, will probably get garbage text. */
1407 	if (*curbuf->b_p_key != NUL)
1408 	{
1409 	    smsg(_("Swap file is encrypted: \"%s\""), fname_used);
1410 	    msg_puts(_("\nIf you entered a new crypt key but did not write the text file,"));
1411 	    msg_puts(_("\nenter the new crypt key."));
1412 	    msg_puts(_("\nIf you wrote the text file after changing the crypt key press enter"));
1413 	    msg_puts(_("\nto use the same key for text file and swap file"));
1414 	}
1415 	else
1416 	    smsg(_(need_key_msg), fname_used);
1417 	buf->b_p_key = crypt_get_key(FALSE, FALSE);
1418 	if (buf->b_p_key == NULL)
1419 	    buf->b_p_key = curbuf->b_p_key;
1420 	else if (*buf->b_p_key == NUL)
1421 	{
1422 	    vim_free(buf->b_p_key);
1423 	    buf->b_p_key = curbuf->b_p_key;
1424 	}
1425 	if (buf->b_p_key == NULL)
1426 	    buf->b_p_key = empty_option;
1427     }
1428 #endif
1429 
1430     /* Use the 'fileformat' and 'fileencoding' as stored in the swap file. */
1431     if (b0_ff != 0)
1432 	set_fileformat(b0_ff - 1, OPT_LOCAL);
1433     if (b0_fenc != NULL)
1434     {
1435 	set_option_value((char_u *)"fenc", 0L, b0_fenc, OPT_LOCAL);
1436 	vim_free(b0_fenc);
1437     }
1438     unchanged(curbuf, TRUE);
1439 
1440     bnum = 1;		/* start with block 1 */
1441     page_count = 1;	/* which is 1 page */
1442     lnum = 0;		/* append after line 0 in curbuf */
1443     line_count = 0;
1444     idx = 0;		/* start with first index in block 1 */
1445     error = 0;
1446     buf->b_ml.ml_stack_top = 0;
1447     buf->b_ml.ml_stack = NULL;
1448     buf->b_ml.ml_stack_size = 0;	/* no stack yet */
1449 
1450     if (curbuf->b_ffname == NULL)
1451 	cannot_open = TRUE;
1452     else
1453 	cannot_open = FALSE;
1454 
1455     serious_error = FALSE;
1456     for ( ; !got_int; line_breakcheck())
1457     {
1458 	if (hp != NULL)
1459 	    mf_put(mfp, hp, FALSE, FALSE);	/* release previous block */
1460 
1461 	/*
1462 	 * get block
1463 	 */
1464 	if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL)
1465 	{
1466 	    if (bnum == 1)
1467 	    {
1468 		semsg(_("E309: Unable to read block 1 from %s"), mfp->mf_fname);
1469 		goto theend;
1470 	    }
1471 	    ++error;
1472 	    ml_append(lnum++, (char_u *)_("???MANY LINES MISSING"),
1473 							    (colnr_T)0, TRUE);
1474 	}
1475 	else		/* there is a block */
1476 	{
1477 	    pp = (PTR_BL *)(hp->bh_data);
1478 	    if (pp->pb_id == PTR_ID)		/* it is a pointer block */
1479 	    {
1480 		/* check line count when using pointer block first time */
1481 		if (idx == 0 && line_count != 0)
1482 		{
1483 		    for (i = 0; i < (int)pp->pb_count; ++i)
1484 			line_count -= pp->pb_pointer[i].pe_line_count;
1485 		    if (line_count != 0)
1486 		    {
1487 			++error;
1488 			ml_append(lnum++, (char_u *)_("???LINE COUNT WRONG"),
1489 							    (colnr_T)0, TRUE);
1490 		    }
1491 		}
1492 
1493 		if (pp->pb_count == 0)
1494 		{
1495 		    ml_append(lnum++, (char_u *)_("???EMPTY BLOCK"),
1496 							    (colnr_T)0, TRUE);
1497 		    ++error;
1498 		}
1499 		else if (idx < (int)pp->pb_count)	/* go a block deeper */
1500 		{
1501 		    if (pp->pb_pointer[idx].pe_bnum < 0)
1502 		    {
1503 			/*
1504 			 * Data block with negative block number.
1505 			 * Try to read lines from the original file.
1506 			 * This is slow, but it works.
1507 			 */
1508 			if (!cannot_open)
1509 			{
1510 			    line_count = pp->pb_pointer[idx].pe_line_count;
1511 			    if (readfile(curbuf->b_ffname, NULL, lnum,
1512 					pp->pb_pointer[idx].pe_old_lnum - 1,
1513 					line_count, NULL, 0) != OK)
1514 				cannot_open = TRUE;
1515 			    else
1516 				lnum += line_count;
1517 			}
1518 			if (cannot_open)
1519 			{
1520 			    ++error;
1521 			    ml_append(lnum++, (char_u *)_("???LINES MISSING"),
1522 							    (colnr_T)0, TRUE);
1523 			}
1524 			++idx;	    /* get same block again for next index */
1525 			continue;
1526 		    }
1527 
1528 		    /*
1529 		     * going one block deeper in the tree
1530 		     */
1531 		    if ((top = ml_add_stack(buf)) < 0)	/* new entry in stack */
1532 		    {
1533 			++error;
1534 			break;		    /* out of memory */
1535 		    }
1536 		    ip = &(buf->b_ml.ml_stack[top]);
1537 		    ip->ip_bnum = bnum;
1538 		    ip->ip_index = idx;
1539 
1540 		    bnum = pp->pb_pointer[idx].pe_bnum;
1541 		    line_count = pp->pb_pointer[idx].pe_line_count;
1542 		    page_count = pp->pb_pointer[idx].pe_page_count;
1543 		    idx = 0;
1544 		    continue;
1545 		}
1546 	    }
1547 	    else	    /* not a pointer block */
1548 	    {
1549 		dp = (DATA_BL *)(hp->bh_data);
1550 		if (dp->db_id != DATA_ID)	/* block id wrong */
1551 		{
1552 		    if (bnum == 1)
1553 		    {
1554 			semsg(_("E310: Block 1 ID wrong (%s not a .swp file?)"),
1555 							       mfp->mf_fname);
1556 			goto theend;
1557 		    }
1558 		    ++error;
1559 		    ml_append(lnum++, (char_u *)_("???BLOCK MISSING"),
1560 							    (colnr_T)0, TRUE);
1561 		}
1562 		else
1563 		{
1564 		    /*
1565 		     * it is a data block
1566 		     * Append all the lines in this block
1567 		     */
1568 		    has_error = FALSE;
1569 			/*
1570 			 * check length of block
1571 			 * if wrong, use length in pointer block
1572 			 */
1573 		    if (page_count * mfp->mf_page_size != dp->db_txt_end)
1574 		    {
1575 			ml_append(lnum++, (char_u *)_("??? from here until ???END lines may be messed up"),
1576 							    (colnr_T)0, TRUE);
1577 			++error;
1578 			has_error = TRUE;
1579 			dp->db_txt_end = page_count * mfp->mf_page_size;
1580 		    }
1581 
1582 			/* make sure there is a NUL at the end of the block */
1583 		    *((char_u *)dp + dp->db_txt_end - 1) = NUL;
1584 
1585 			/*
1586 			 * check number of lines in block
1587 			 * if wrong, use count in data block
1588 			 */
1589 		    if (line_count != dp->db_line_count)
1590 		    {
1591 			ml_append(lnum++, (char_u *)_("??? from here until ???END lines may have been inserted/deleted"),
1592 							    (colnr_T)0, TRUE);
1593 			++error;
1594 			has_error = TRUE;
1595 		    }
1596 
1597 		    for (i = 0; i < dp->db_line_count; ++i)
1598 		    {
1599 			txt_start = (dp->db_index[i] & DB_INDEX_MASK);
1600 			if (txt_start <= (int)HEADER_SIZE
1601 					  || txt_start >= (int)dp->db_txt_end)
1602 			{
1603 			    p = (char_u *)"???";
1604 			    ++error;
1605 			}
1606 			else
1607 			    p = (char_u *)dp + txt_start;
1608 			ml_append(lnum++, p, (colnr_T)0, TRUE);
1609 		    }
1610 		    if (has_error)
1611 			ml_append(lnum++, (char_u *)_("???END"),
1612 							    (colnr_T)0, TRUE);
1613 		}
1614 	    }
1615 	}
1616 
1617 	if (buf->b_ml.ml_stack_top == 0)	/* finished */
1618 	    break;
1619 
1620 	/*
1621 	 * go one block up in the tree
1622 	 */
1623 	ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
1624 	bnum = ip->ip_bnum;
1625 	idx = ip->ip_index + 1;	    /* go to next index */
1626 	page_count = 1;
1627     }
1628 
1629     /*
1630      * Compare the buffer contents with the original file.  When they differ
1631      * set the 'modified' flag.
1632      * Lines 1 - lnum are the new contents.
1633      * Lines lnum + 1 to ml_line_count are the original contents.
1634      * Line ml_line_count + 1 in the dummy empty line.
1635      */
1636     if (orig_file_status != OK || curbuf->b_ml.ml_line_count != lnum * 2 + 1)
1637     {
1638 	/* Recovering an empty file results in two lines and the first line is
1639 	 * empty.  Don't set the modified flag then. */
1640 	if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL))
1641 	{
1642 	    changed_int();
1643 	    ++CHANGEDTICK(curbuf);
1644 	}
1645     }
1646     else
1647     {
1648 	for (idx = 1; idx <= lnum; ++idx)
1649 	{
1650 	    /* Need to copy one line, fetching the other one may flush it. */
1651 	    p = vim_strsave(ml_get(idx));
1652 	    i = STRCMP(p, ml_get(idx + lnum));
1653 	    vim_free(p);
1654 	    if (i != 0)
1655 	    {
1656 		changed_int();
1657 		++CHANGEDTICK(curbuf);
1658 		break;
1659 	    }
1660 	}
1661     }
1662 
1663     /*
1664      * Delete the lines from the original file and the dummy line from the
1665      * empty buffer.  These will now be after the last line in the buffer.
1666      */
1667     while (curbuf->b_ml.ml_line_count > lnum
1668 				       && !(curbuf->b_ml.ml_flags & ML_EMPTY))
1669 	ml_delete(curbuf->b_ml.ml_line_count, FALSE);
1670     curbuf->b_flags |= BF_RECOVERED;
1671 
1672     recoverymode = FALSE;
1673     if (got_int)
1674 	emsg(_("E311: Recovery Interrupted"));
1675     else if (error)
1676     {
1677 	++no_wait_return;
1678 	msg(">>>>>>>>>>>>>");
1679 	emsg(_("E312: Errors detected while recovering; look for lines starting with ???"));
1680 	--no_wait_return;
1681 	msg(_("See \":help E312\" for more information."));
1682 	msg(">>>>>>>>>>>>>");
1683     }
1684     else
1685     {
1686 	if (curbuf->b_changed)
1687 	{
1688 	    msg(_("Recovery completed. You should check if everything is OK."));
1689 	    msg_puts(_("\n(You might want to write out this file under another name\n"));
1690 	    msg_puts(_("and run diff with the original file to check for changes)"));
1691 	}
1692 	else
1693 	    msg(_("Recovery completed. Buffer contents equals file contents."));
1694 	msg_puts(_("\nYou may want to delete the .swp file now.\n\n"));
1695 	cmdline_row = msg_row;
1696     }
1697 #ifdef FEAT_CRYPT
1698     if (*buf->b_p_key != NUL && STRCMP(curbuf->b_p_key, buf->b_p_key) != 0)
1699     {
1700 	msg_puts(_("Using crypt key from swap file for the text file.\n"));
1701 	set_option_value((char_u *)"key", 0L, buf->b_p_key, OPT_LOCAL);
1702     }
1703 #endif
1704     redraw_curbuf_later(NOT_VALID);
1705 
1706 theend:
1707     vim_free(fname_used);
1708     recoverymode = FALSE;
1709     if (mfp != NULL)
1710     {
1711 	if (hp != NULL)
1712 	    mf_put(mfp, hp, FALSE, FALSE);
1713 	mf_close(mfp, FALSE);	    /* will also vim_free(mfp->mf_fname) */
1714     }
1715     if (buf != NULL)
1716     {
1717 #ifdef FEAT_CRYPT
1718 	if (buf->b_p_key != curbuf->b_p_key)
1719 	    free_string_option(buf->b_p_key);
1720 	free_string_option(buf->b_p_cm);
1721 #endif
1722 	vim_free(buf->b_ml.ml_stack);
1723 	vim_free(buf);
1724     }
1725     if (serious_error && called_from_main)
1726 	ml_close(curbuf, TRUE);
1727     else
1728     {
1729 	apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf);
1730 	apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, FALSE, curbuf);
1731     }
1732     return;
1733 }
1734 
1735 /*
1736  * Find the names of swap files in current directory and the directory given
1737  * with the 'directory' option.
1738  *
1739  * Used to:
1740  * - list the swap files for "vim -r"
1741  * - count the number of swap files when recovering
1742  * - list the swap files when recovering
1743  * - find the name of the n'th swap file when recovering
1744  */
1745     int
1746 recover_names(
1747     char_u	*fname,		/* base for swap file name */
1748     int		list,		/* when TRUE, list the swap file names */
1749     int		nr,		/* when non-zero, return nr'th swap file name */
1750     char_u	**fname_out)	/* result when "nr" > 0 */
1751 {
1752     int		num_names;
1753     char_u	*(names[6]);
1754     char_u	*tail;
1755     char_u	*p;
1756     int		num_files;
1757     int		file_count = 0;
1758     char_u	**files;
1759     int		i;
1760     char_u	*dirp;
1761     char_u	*dir_name;
1762     char_u	*fname_res = NULL;
1763 #ifdef HAVE_READLINK
1764     char_u	fname_buf[MAXPATHL];
1765 #endif
1766 
1767     if (fname != NULL)
1768     {
1769 #ifdef HAVE_READLINK
1770 	/* Expand symlink in the file name, because the swap file is created
1771 	 * with the actual file instead of with the symlink. */
1772 	if (resolve_symlink(fname, fname_buf) == OK)
1773 	    fname_res = fname_buf;
1774 	else
1775 #endif
1776 	    fname_res = fname;
1777     }
1778 
1779     if (list)
1780     {
1781 	/* use msg() to start the scrolling properly */
1782 	msg(_("Swap files found:"));
1783 	msg_putchar('\n');
1784     }
1785 
1786     /*
1787      * Do the loop for every directory in 'directory'.
1788      * First allocate some memory to put the directory name in.
1789      */
1790     dir_name = alloc((unsigned)STRLEN(p_dir) + 1);
1791     dirp = p_dir;
1792     while (dir_name != NULL && *dirp)
1793     {
1794 	/*
1795 	 * Isolate a directory name from *dirp and put it in dir_name (we know
1796 	 * it is large enough, so use 31000 for length).
1797 	 * Advance dirp to next directory name.
1798 	 */
1799 	(void)copy_option_part(&dirp, dir_name, 31000, ",");
1800 
1801 	if (dir_name[0] == '.' && dir_name[1] == NUL)	/* check current dir */
1802 	{
1803 	    if (fname == NULL)
1804 	    {
1805 #ifdef VMS
1806 		names[0] = vim_strsave((char_u *)"*_sw%");
1807 #else
1808 		names[0] = vim_strsave((char_u *)"*.sw?");
1809 #endif
1810 #if defined(UNIX) || defined(WIN3264)
1811 		/* For Unix names starting with a dot are special.  MS-Windows
1812 		 * supports this too, on some file systems. */
1813 		names[1] = vim_strsave((char_u *)".*.sw?");
1814 		names[2] = vim_strsave((char_u *)".sw?");
1815 		num_names = 3;
1816 #else
1817 # ifdef VMS
1818 		names[1] = vim_strsave((char_u *)".*_sw%");
1819 		num_names = 2;
1820 # else
1821 		num_names = 1;
1822 # endif
1823 #endif
1824 	    }
1825 	    else
1826 		num_names = recov_file_names(names, fname_res, TRUE);
1827 	}
1828 	else			    /* check directory dir_name */
1829 	{
1830 	    if (fname == NULL)
1831 	    {
1832 #ifdef VMS
1833 		names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE);
1834 #else
1835 		names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE);
1836 #endif
1837 #if defined(UNIX) || defined(WIN3264)
1838 		/* For Unix names starting with a dot are special.  MS-Windows
1839 		 * supports this too, on some file systems. */
1840 		names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE);
1841 		names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE);
1842 		num_names = 3;
1843 #else
1844 # ifdef VMS
1845 		names[1] = concat_fnames(dir_name, (char_u *)".*_sw%", TRUE);
1846 		num_names = 2;
1847 # else
1848 		num_names = 1;
1849 # endif
1850 #endif
1851 	    }
1852 	    else
1853 	    {
1854 #if defined(UNIX) || defined(WIN3264)
1855 		int	len = (int)STRLEN(dir_name);
1856 
1857 		p = dir_name + len;
1858 		if (after_pathsep(dir_name, p) && len > 1 && p[-1] == p[-2])
1859 		{
1860 		    /* Ends with '//', Use Full path for swap name */
1861 		    tail = make_percent_swname(dir_name, fname_res);
1862 		}
1863 		else
1864 #endif
1865 		{
1866 		    tail = gettail(fname_res);
1867 		    tail = concat_fnames(dir_name, tail, TRUE);
1868 		}
1869 		if (tail == NULL)
1870 		    num_names = 0;
1871 		else
1872 		{
1873 		    num_names = recov_file_names(names, tail, FALSE);
1874 		    vim_free(tail);
1875 		}
1876 	    }
1877 	}
1878 
1879 	    /* check for out-of-memory */
1880 	for (i = 0; i < num_names; ++i)
1881 	{
1882 	    if (names[i] == NULL)
1883 	    {
1884 		for (i = 0; i < num_names; ++i)
1885 		    vim_free(names[i]);
1886 		num_names = 0;
1887 	    }
1888 	}
1889 	if (num_names == 0)
1890 	    num_files = 0;
1891 	else if (expand_wildcards(num_names, names, &num_files, &files,
1892 					EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL)
1893 	    num_files = 0;
1894 
1895 	/*
1896 	 * When no swap file found, wildcard expansion might have failed (e.g.
1897 	 * not able to execute the shell).
1898 	 * Try finding a swap file by simply adding ".swp" to the file name.
1899 	 */
1900 	if (*dirp == NUL && file_count + num_files == 0 && fname != NULL)
1901 	{
1902 	    stat_T	    st;
1903 	    char_u	    *swapname;
1904 
1905 	    swapname = modname(fname_res,
1906 #if defined(VMS)
1907 			       (char_u *)"_swp", FALSE
1908 #else
1909 			       (char_u *)".swp", TRUE
1910 #endif
1911 			      );
1912 	    if (swapname != NULL)
1913 	    {
1914 		if (mch_stat((char *)swapname, &st) != -1)	    /* It exists! */
1915 		{
1916 		    files = (char_u **)alloc((unsigned)sizeof(char_u *));
1917 		    if (files != NULL)
1918 		    {
1919 			files[0] = swapname;
1920 			swapname = NULL;
1921 			num_files = 1;
1922 		    }
1923 		}
1924 		vim_free(swapname);
1925 	    }
1926 	}
1927 
1928 	/*
1929 	 * remove swapfile name of the current buffer, it must be ignored
1930 	 */
1931 	if (curbuf->b_ml.ml_mfp != NULL
1932 			       && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
1933 	{
1934 	    for (i = 0; i < num_files; ++i)
1935 		if (fullpathcmp(p, files[i], TRUE) & FPC_SAME)
1936 		{
1937 		    /* Remove the name from files[i].  Move further entries
1938 		     * down.  When the array becomes empty free it here, since
1939 		     * FreeWild() won't be called below. */
1940 		    vim_free(files[i]);
1941 		    if (--num_files == 0)
1942 			vim_free(files);
1943 		    else
1944 			for ( ; i < num_files; ++i)
1945 			    files[i] = files[i + 1];
1946 		}
1947 	}
1948 	if (nr > 0)
1949 	{
1950 	    file_count += num_files;
1951 	    if (nr <= file_count)
1952 	    {
1953 		*fname_out = vim_strsave(
1954 				      files[nr - 1 + num_files - file_count]);
1955 		dirp = (char_u *)"";		    /* stop searching */
1956 	    }
1957 	}
1958 	else if (list)
1959 	{
1960 	    if (dir_name[0] == '.' && dir_name[1] == NUL)
1961 	    {
1962 		if (fname == NULL)
1963 		    msg_puts(_("   In current directory:\n"));
1964 		else
1965 		    msg_puts(_("   Using specified name:\n"));
1966 	    }
1967 	    else
1968 	    {
1969 		msg_puts(_("   In directory "));
1970 		msg_home_replace(dir_name);
1971 		msg_puts(":\n");
1972 	    }
1973 
1974 	    if (num_files)
1975 	    {
1976 		for (i = 0; i < num_files; ++i)
1977 		{
1978 		    /* print the swap file name */
1979 		    msg_outnum((long)++file_count);
1980 		    msg_puts(".    ");
1981 		    msg_puts((char *)gettail(files[i]));
1982 		    msg_putchar('\n');
1983 		    (void)swapfile_info(files[i]);
1984 		}
1985 	    }
1986 	    else
1987 		msg_puts(_("      -- none --\n"));
1988 	    out_flush();
1989 	}
1990 	else
1991 	    file_count += num_files;
1992 
1993 	for (i = 0; i < num_names; ++i)
1994 	    vim_free(names[i]);
1995 	if (num_files > 0)
1996 	    FreeWild(num_files, files);
1997     }
1998     vim_free(dir_name);
1999     return file_count;
2000 }
2001 
2002 #if defined(UNIX) || defined(WIN3264) || defined(PROTO)
2003 /*
2004  * Need _very_ long file names.
2005  * Append the full path to name with path separators made into percent
2006  * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
2007  */
2008     char_u *
2009 make_percent_swname(char_u *dir, char_u *name)
2010 {
2011     char_u *d = NULL, *s, *f;
2012 
2013     f = fix_fname(name != NULL ? name : (char_u *)"");
2014     if (f != NULL)
2015     {
2016 	s = alloc((unsigned)(STRLEN(f) + 1));
2017 	if (s != NULL)
2018 	{
2019 	    STRCPY(s, f);
2020 	    for (d = s; *d != NUL; MB_PTR_ADV(d))
2021 		if (vim_ispathsep(*d))
2022 		    *d = '%';
2023 	    d = concat_fnames(dir, s, TRUE);
2024 	    vim_free(s);
2025 	}
2026 	vim_free(f);
2027     }
2028     return d;
2029 }
2030 #endif
2031 
2032 #if (defined(UNIX) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
2033 static int process_still_running;
2034 #endif
2035 
2036 #if defined(FEAT_EVAL) || defined(PROTO)
2037 /*
2038  * Return information found in swapfile "fname" in dictionary "d".
2039  * This is used by the swapinfo() function.
2040  */
2041     void
2042 get_b0_dict(char_u *fname, dict_T *d)
2043 {
2044     int fd;
2045     struct block0 b0;
2046 
2047     if ((fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
2048     {
2049 	if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0))
2050 	{
2051 	    if (ml_check_b0_id(&b0) == FAIL)
2052 		dict_add_string(d, "error", (char_u *)"Not a swap file");
2053 	    else if (b0_magic_wrong(&b0))
2054 		dict_add_string(d, "error", (char_u *)"Magic number mismatch");
2055 	    else
2056 	    {
2057 		/* we have swap information */
2058 		dict_add_string_len(d, "version", b0.b0_version, 10);
2059 		dict_add_string_len(d, "user", b0.b0_uname, B0_UNAME_SIZE);
2060 		dict_add_string_len(d, "host", b0.b0_hname, B0_HNAME_SIZE);
2061 		dict_add_string_len(d, "fname", b0.b0_fname, B0_FNAME_SIZE_ORG);
2062 
2063 		dict_add_number(d, "pid", char_to_long(b0.b0_pid));
2064 		dict_add_number(d, "mtime", char_to_long(b0.b0_mtime));
2065 		dict_add_number(d, "dirty", b0.b0_dirty ? 1 : 0);
2066 # ifdef CHECK_INODE
2067 		dict_add_number(d, "inode", char_to_long(b0.b0_ino));
2068 # endif
2069 	    }
2070 	}
2071 	else
2072 	    dict_add_string(d, "error", (char_u *)"Cannot read file");
2073 	close(fd);
2074     }
2075     else
2076 	dict_add_string(d, "error", (char_u *)"Cannot open file");
2077 }
2078 #endif
2079 
2080 /*
2081  * Give information about an existing swap file.
2082  * Returns timestamp (0 when unknown).
2083  */
2084     static time_t
2085 swapfile_info(char_u *fname)
2086 {
2087     stat_T	    st;
2088     int		    fd;
2089     struct block0   b0;
2090     time_t	    x = (time_t)0;
2091     char	    *p;
2092 #ifdef UNIX
2093     char_u	    uname[B0_UNAME_SIZE];
2094 #endif
2095 
2096     /* print the swap file date */
2097     if (mch_stat((char *)fname, &st) != -1)
2098     {
2099 #ifdef UNIX
2100 	/* print name of owner of the file */
2101 	if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK)
2102 	{
2103 	    msg_puts(_("          owned by: "));
2104 	    msg_outtrans(uname);
2105 	    msg_puts(_("   dated: "));
2106 	}
2107 	else
2108 #endif
2109 	    msg_puts(_("             dated: "));
2110 	x = st.st_mtime;		    /* Manx C can't do &st.st_mtime */
2111 	p = ctime(&x);			    /* includes '\n' */
2112 	if (p == NULL)
2113 	    msg_puts("(invalid)\n");
2114 	else
2115 	    msg_puts(p);
2116     }
2117 
2118     /*
2119      * print the original file name
2120      */
2121     fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2122     if (fd >= 0)
2123     {
2124 	if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0))
2125 	{
2126 	    if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0)
2127 	    {
2128 		msg_puts(_("         [from Vim version 3.0]"));
2129 	    }
2130 	    else if (ml_check_b0_id(&b0) == FAIL)
2131 	    {
2132 		msg_puts(_("         [does not look like a Vim swap file]"));
2133 	    }
2134 	    else
2135 	    {
2136 		msg_puts(_("         file name: "));
2137 		if (b0.b0_fname[0] == NUL)
2138 		    msg_puts(_("[No Name]"));
2139 		else
2140 		    msg_outtrans(b0.b0_fname);
2141 
2142 		msg_puts(_("\n          modified: "));
2143 		msg_puts(b0.b0_dirty ? _("YES") : _("no"));
2144 
2145 		if (*(b0.b0_uname) != NUL)
2146 		{
2147 		    msg_puts(_("\n         user name: "));
2148 		    msg_outtrans(b0.b0_uname);
2149 		}
2150 
2151 		if (*(b0.b0_hname) != NUL)
2152 		{
2153 		    if (*(b0.b0_uname) != NUL)
2154 			msg_puts(_("   host name: "));
2155 		    else
2156 			msg_puts(_("\n         host name: "));
2157 		    msg_outtrans(b0.b0_hname);
2158 		}
2159 
2160 		if (char_to_long(b0.b0_pid) != 0L)
2161 		{
2162 		    msg_puts(_("\n        process ID: "));
2163 		    msg_outnum(char_to_long(b0.b0_pid));
2164 #if defined(UNIX)
2165 		    /* EMX kill() not working correctly, it seems */
2166 		    if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
2167 		    {
2168 			msg_puts(_(" (STILL RUNNING)"));
2169 # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
2170 			process_still_running = TRUE;
2171 # endif
2172 		    }
2173 #endif
2174 		}
2175 
2176 		if (b0_magic_wrong(&b0))
2177 		{
2178 #if defined(MSWIN)
2179 		    if (STRNCMP(b0.b0_hname, "PC ", 3) == 0)
2180 			msg_puts(_("\n         [not usable with this version of Vim]"));
2181 		    else
2182 #endif
2183 			msg_puts(_("\n         [not usable on this computer]"));
2184 		}
2185 	    }
2186 	}
2187 	else
2188 	    msg_puts(_("         [cannot be read]"));
2189 	close(fd);
2190     }
2191     else
2192 	msg_puts(_("         [cannot be opened]"));
2193     msg_putchar('\n');
2194 
2195     return x;
2196 }
2197 
2198     static int
2199 recov_file_names(char_u **names, char_u *path, int prepend_dot)
2200 {
2201     int		num_names;
2202 
2203     /*
2204      * (Win32 and Win64) never short names, but do prepend a dot.
2205      * (Not MS-DOS or Win32 or Win64) maybe short name, maybe not: Try both.
2206      * Only use the short name if it is different.
2207      */
2208     char_u	*p;
2209     int		i;
2210 # ifndef WIN3264
2211     int	    shortname = curbuf->b_shortname;
2212 
2213     curbuf->b_shortname = FALSE;
2214 # endif
2215 
2216     num_names = 0;
2217 
2218     /*
2219      * May also add the file name with a dot prepended, for swap file in same
2220      * dir as original file.
2221      */
2222     if (prepend_dot)
2223     {
2224 	names[num_names] = modname(path, (char_u *)".sw?", TRUE);
2225 	if (names[num_names] == NULL)
2226 	    goto end;
2227 	++num_names;
2228     }
2229 
2230     /*
2231      * Form the normal swap file name pattern by appending ".sw?".
2232      */
2233 #ifdef VMS
2234     names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE);
2235 #else
2236     names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE);
2237 #endif
2238     if (names[num_names] == NULL)
2239 	goto end;
2240     if (num_names >= 1)	    /* check if we have the same name twice */
2241     {
2242 	p = names[num_names - 1];
2243 	i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]);
2244 	if (i > 0)
2245 	    p += i;	    /* file name has been expanded to full path */
2246 
2247 	if (STRCMP(p, names[num_names]) != 0)
2248 	    ++num_names;
2249 	else
2250 	    vim_free(names[num_names]);
2251     }
2252     else
2253 	++num_names;
2254 
2255 # ifndef WIN3264
2256     /*
2257      * Also try with 'shortname' set, in case the file is on a DOS filesystem.
2258      */
2259     curbuf->b_shortname = TRUE;
2260 #ifdef VMS
2261     names[num_names] = modname(path, (char_u *)"_sw%", FALSE);
2262 #else
2263     names[num_names] = modname(path, (char_u *)".sw?", FALSE);
2264 #endif
2265     if (names[num_names] == NULL)
2266 	goto end;
2267 
2268     /*
2269      * Remove the one from 'shortname', if it's the same as with 'noshortname'.
2270      */
2271     p = names[num_names];
2272     i = STRLEN(names[num_names]) - STRLEN(names[num_names - 1]);
2273     if (i > 0)
2274 	p += i;		/* file name has been expanded to full path */
2275     if (STRCMP(names[num_names - 1], p) == 0)
2276 	vim_free(names[num_names]);
2277     else
2278 	++num_names;
2279 # endif
2280 
2281 end:
2282 # ifndef WIN3264
2283     curbuf->b_shortname = shortname;
2284 # endif
2285 
2286     return num_names;
2287 }
2288 
2289 /*
2290  * sync all memlines
2291  *
2292  * If 'check_file' is TRUE, check if original file exists and was not changed.
2293  * If 'check_char' is TRUE, stop syncing when character becomes available, but
2294  * always sync at least one block.
2295  */
2296     void
2297 ml_sync_all(int check_file, int check_char)
2298 {
2299     buf_T		*buf;
2300     stat_T		st;
2301 
2302     FOR_ALL_BUFFERS(buf)
2303     {
2304 	if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
2305 	    continue;			    /* no file */
2306 
2307 	ml_flush_line(buf);		    /* flush buffered line */
2308 					    /* flush locked block */
2309 	(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);
2310 	if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
2311 						     && buf->b_ffname != NULL)
2312 	{
2313 	    /*
2314 	     * If the original file does not exist anymore or has been changed
2315 	     * call ml_preserve() to get rid of all negative numbered blocks.
2316 	     */
2317 	    if (mch_stat((char *)buf->b_ffname, &st) == -1
2318 		    || st.st_mtime != buf->b_mtime_read
2319 		    || st.st_size != buf->b_orig_size)
2320 	    {
2321 		ml_preserve(buf, FALSE);
2322 		did_check_timestamps = FALSE;
2323 		need_check_timestamps = TRUE;	/* give message later */
2324 	    }
2325 	}
2326 	if (buf->b_ml.ml_mfp->mf_dirty)
2327 	{
2328 	    (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
2329 					| (bufIsChanged(buf) ? MFS_FLUSH : 0));
2330 	    if (check_char && ui_char_avail())	/* character available now */
2331 		break;
2332 	}
2333     }
2334 }
2335 
2336 /*
2337  * sync one buffer, including negative blocks
2338  *
2339  * after this all the blocks are in the swap file
2340  *
2341  * Used for the :preserve command and when the original file has been
2342  * changed or deleted.
2343  *
2344  * when message is TRUE the success of preserving is reported
2345  */
2346     void
2347 ml_preserve(buf_T *buf, int message)
2348 {
2349     bhdr_T	*hp;
2350     linenr_T	lnum;
2351     memfile_T	*mfp = buf->b_ml.ml_mfp;
2352     int		status;
2353     int		got_int_save = got_int;
2354 
2355     if (mfp == NULL || mfp->mf_fname == NULL)
2356     {
2357 	if (message)
2358 	    emsg(_("E313: Cannot preserve, there is no swap file"));
2359 	return;
2360     }
2361 
2362     /* We only want to stop when interrupted here, not when interrupted
2363      * before. */
2364     got_int = FALSE;
2365 
2366     ml_flush_line(buf);				    /* flush buffered line */
2367     (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */
2368     status = mf_sync(mfp, MFS_ALL | MFS_FLUSH);
2369 
2370     /* stack is invalid after mf_sync(.., MFS_ALL) */
2371     buf->b_ml.ml_stack_top = 0;
2372 
2373     /*
2374      * Some of the data blocks may have been changed from negative to
2375      * positive block number. In that case the pointer blocks need to be
2376      * updated.
2377      *
2378      * We don't know in which pointer block the references are, so we visit
2379      * all data blocks until there are no more translations to be done (or
2380      * we hit the end of the file, which can only happen in case a write fails,
2381      * e.g. when file system if full).
2382      * ml_find_line() does the work by translating the negative block numbers
2383      * when getting the first line of each data block.
2384      */
2385     if (mf_need_trans(mfp) && !got_int)
2386     {
2387 	lnum = 1;
2388 	while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count)
2389 	{
2390 	    hp = ml_find_line(buf, lnum, ML_FIND);
2391 	    if (hp == NULL)
2392 	    {
2393 		status = FAIL;
2394 		goto theend;
2395 	    }
2396 	    CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
2397 	    lnum = buf->b_ml.ml_locked_high + 1;
2398 	}
2399 	(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);	/* flush locked block */
2400 	/* sync the updated pointer blocks */
2401 	if (mf_sync(mfp, MFS_ALL | MFS_FLUSH) == FAIL)
2402 	    status = FAIL;
2403 	buf->b_ml.ml_stack_top = 0;	    /* stack is invalid now */
2404     }
2405 theend:
2406     got_int |= got_int_save;
2407 
2408     if (message)
2409     {
2410 	if (status == OK)
2411 	    msg(_("File preserved"));
2412 	else
2413 	    emsg(_("E314: Preserve failed"));
2414     }
2415 }
2416 
2417 /*
2418  * NOTE: The pointer returned by the ml_get_*() functions only remains valid
2419  * until the next call!
2420  *  line1 = ml_get(1);
2421  *  line2 = ml_get(2);	// line1 is now invalid!
2422  * Make a copy of the line if necessary.
2423  */
2424 /*
2425  * Return a pointer to a (read-only copy of a) line.
2426  *
2427  * On failure an error message is given and IObuff is returned (to avoid
2428  * having to check for error everywhere).
2429  */
2430     char_u  *
2431 ml_get(linenr_T lnum)
2432 {
2433     return ml_get_buf(curbuf, lnum, FALSE);
2434 }
2435 
2436 /*
2437  * Return pointer to position "pos".
2438  */
2439     char_u *
2440 ml_get_pos(pos_T *pos)
2441 {
2442     return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
2443 }
2444 
2445 /*
2446  * Return pointer to cursor line.
2447  */
2448     char_u *
2449 ml_get_curline(void)
2450 {
2451     return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE);
2452 }
2453 
2454 /*
2455  * Return pointer to cursor position.
2456  */
2457     char_u *
2458 ml_get_cursor(void)
2459 {
2460     return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
2461 							curwin->w_cursor.col);
2462 }
2463 
2464 /*
2465  * Return a pointer to a line in a specific buffer
2466  *
2467  * "will_change": if TRUE mark the buffer dirty (chars in the line will be
2468  * changed)
2469  */
2470     char_u  *
2471 ml_get_buf(
2472     buf_T	*buf,
2473     linenr_T	lnum,
2474     int		will_change)		/* line will be changed */
2475 {
2476     bhdr_T	*hp;
2477     DATA_BL	*dp;
2478     static int	recursive = 0;
2479 
2480     if (lnum > buf->b_ml.ml_line_count)	/* invalid line number */
2481     {
2482 	if (recursive == 0)
2483 	{
2484 	    /* Avoid giving this message for a recursive call, may happen when
2485 	     * the GUI redraws part of the text. */
2486 	    ++recursive;
2487 	    siemsg(_("E315: ml_get: invalid lnum: %ld"), lnum);
2488 	    --recursive;
2489 	}
2490 errorret:
2491 	STRCPY(IObuff, "???");
2492 	return IObuff;
2493     }
2494     if (lnum <= 0)			/* pretend line 0 is line 1 */
2495 	lnum = 1;
2496 
2497     if (buf->b_ml.ml_mfp == NULL)	/* there are no lines */
2498 	return (char_u *)"";
2499 
2500     /*
2501      * See if it is the same line as requested last time.
2502      * Otherwise may need to flush last used line.
2503      * Don't use the last used line when 'swapfile' is reset, need to load all
2504      * blocks.
2505      */
2506     if (buf->b_ml.ml_line_lnum != lnum || mf_dont_release)
2507     {
2508 	unsigned    start, end;
2509 	colnr_T	    len;
2510 	int	    idx;
2511 
2512 	ml_flush_line(buf);
2513 
2514 	/*
2515 	 * Find the data block containing the line.
2516 	 * This also fills the stack with the blocks from the root to the data
2517 	 * block and releases any locked block.
2518 	 */
2519 	if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
2520 	{
2521 	    if (recursive == 0)
2522 	    {
2523 		/* Avoid giving this message for a recursive call, may happen
2524 		 * when the GUI redraws part of the text. */
2525 		++recursive;
2526 		siemsg(_("E316: ml_get: cannot find line %ld"), lnum);
2527 		--recursive;
2528 	    }
2529 	    goto errorret;
2530 	}
2531 
2532 	dp = (DATA_BL *)(hp->bh_data);
2533 
2534 	idx = lnum - buf->b_ml.ml_locked_low;
2535 	start = ((dp->db_index[idx]) & DB_INDEX_MASK);
2536 	// The text ends where the previous line starts.  The first line ends
2537 	// at the end of the block.
2538 	if (idx == 0)
2539 	    end = dp->db_txt_end;
2540 	else
2541 	    end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
2542 	len = end - start;
2543 
2544 	buf->b_ml.ml_line_ptr = (char_u *)dp + start;
2545 	buf->b_ml.ml_line_len = len;
2546 	buf->b_ml.ml_line_lnum = lnum;
2547 	buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
2548     }
2549     if (will_change)
2550 	buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
2551 
2552     return buf->b_ml.ml_line_ptr;
2553 }
2554 
2555 /*
2556  * Check if a line that was just obtained by a call to ml_get
2557  * is in allocated memory.
2558  */
2559     int
2560 ml_line_alloced(void)
2561 {
2562     return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
2563 }
2564 
2565 #ifdef FEAT_TEXT_PROP
2566     static void
2567 add_text_props_for_append(
2568 	    buf_T	*buf,
2569 	    linenr_T	lnum,
2570 	    char_u	**line,
2571 	    int		*len,
2572 	    char_u	**tofree)
2573 {
2574     int		round;
2575     int		new_prop_count = 0;
2576     int		count;
2577     int		n;
2578     char_u	*props;
2579     int		new_len;
2580     char_u	*new_line;
2581     textprop_T	prop;
2582 
2583     // Make two rounds:
2584     // 1. calculate the extra space needed
2585     // 2. allocate the space and fill it
2586     for (round = 1; round <= 2; ++round)
2587     {
2588 	if (round == 2)
2589 	{
2590 	    if (new_prop_count == 0)
2591 		return;  // nothing to do
2592 	    new_len = *len + new_prop_count * sizeof(textprop_T);
2593 	    new_line = alloc((unsigned)new_len);
2594 	    if (new_line == NULL)
2595 		return;
2596 	    mch_memmove(new_line, *line, *len);
2597 	    new_prop_count = 0;
2598 	}
2599 
2600 	// Get the line above to find any props that continue in the next
2601 	// line.
2602 	count = get_text_props(buf, lnum, &props, FALSE);
2603 	for (n = 0; n < count; ++n)
2604 	{
2605 	    mch_memmove(&prop, props + n * sizeof(textprop_T), sizeof(textprop_T));
2606 	    if (prop.tp_flags & TP_FLAG_CONT_NEXT)
2607 	    {
2608 		if (round == 2)
2609 		{
2610 		    prop.tp_flags |= TP_FLAG_CONT_PREV;
2611 		    prop.tp_col = 1;
2612 		    prop.tp_len = *len;
2613 		    mch_memmove(new_line + *len + new_prop_count * sizeof(textprop_T), &prop, sizeof(textprop_T));
2614 		}
2615 		++new_prop_count;
2616 	    }
2617 	}
2618     }
2619     *line = new_line;
2620     *tofree = new_line;
2621     *len = new_len;
2622 }
2623 #endif
2624 
2625 /*
2626  * Append a line after lnum (may be 0 to insert a line in front of the file).
2627  * "line" does not need to be allocated, but can't be another line in a
2628  * buffer, unlocking may make it invalid.
2629  *
2630  *   newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
2631  *		will be set for recovery
2632  * Check: The caller of this function should probably also call
2633  * appended_lines().
2634  *
2635  * return FAIL for failure, OK otherwise
2636  */
2637     int
2638 ml_append(
2639     linenr_T	lnum,		/* append after this line (can be 0) */
2640     char_u	*line,		/* text of the new line */
2641     colnr_T	len,		/* length of new line, including NUL, or 0 */
2642     int		newfile)	/* flag, see above */
2643 {
2644     /* When starting up, we might still need to create the memfile */
2645     if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
2646 	return FAIL;
2647 
2648     if (curbuf->b_ml.ml_line_lnum != 0)
2649 	ml_flush_line(curbuf);
2650     return ml_append_int(curbuf, lnum, line, len, newfile, FALSE);
2651 }
2652 
2653 #if defined(FEAT_SPELL) || defined(FEAT_QUICKFIX) || defined(PROTO)
2654 /*
2655  * Like ml_append() but for an arbitrary buffer.  The buffer must already have
2656  * a memline.
2657  */
2658     int
2659 ml_append_buf(
2660     buf_T	*buf,
2661     linenr_T	lnum,		/* append after this line (can be 0) */
2662     char_u	*line,		/* text of the new line */
2663     colnr_T	len,		/* length of new line, including NUL, or 0 */
2664     int		newfile)	/* flag, see above */
2665 {
2666     if (buf->b_ml.ml_mfp == NULL)
2667 	return FAIL;
2668 
2669     if (buf->b_ml.ml_line_lnum != 0)
2670 	ml_flush_line(buf);
2671     return ml_append_int(buf, lnum, line, len, newfile, FALSE);
2672 }
2673 #endif
2674 
2675     static int
2676 ml_append_int(
2677     buf_T	*buf,
2678     linenr_T	lnum,		// append after this line (can be 0)
2679     char_u	*line_arg,	// text of the new line
2680     colnr_T	len_arg,	// length of line, including NUL, or 0
2681     int		newfile,	// flag, see above
2682     int		mark)		// mark the new line
2683 {
2684     char_u	*line = line_arg;
2685     colnr_T	len = len_arg;
2686     int		i;
2687     int		line_count;	// number of indexes in current block
2688     int		offset;
2689     int		from, to;
2690     int		space_needed;	// space needed for new line
2691     int		page_size;
2692     int		page_count;
2693     int		db_idx;		// index for lnum in data block
2694     bhdr_T	*hp;
2695     memfile_T	*mfp;
2696     DATA_BL	*dp;
2697     PTR_BL	*pp;
2698     infoptr_T	*ip;
2699 #ifdef FEAT_TEXT_PROP
2700     char_u	*tofree = NULL;
2701 #endif
2702     int		ret = FAIL;
2703 
2704     if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
2705 	return FAIL;  // lnum out of range
2706 
2707     if (lowest_marked && lowest_marked > lnum)
2708 	lowest_marked = lnum + 1;
2709 
2710     if (len == 0)
2711 	len = (colnr_T)STRLEN(line) + 1;	// space needed for the text
2712 
2713 #ifdef FEAT_TEXT_PROP
2714     if (curbuf->b_has_textprop && lnum > 0)
2715 	// Add text properties that continue from the previous line.
2716 	add_text_props_for_append(buf, lnum, &line, &len, &tofree);
2717 #endif
2718 
2719     space_needed = len + INDEX_SIZE;	// space needed for text + index
2720 
2721     mfp = buf->b_ml.ml_mfp;
2722     page_size = mfp->mf_page_size;
2723 
2724 /*
2725  * find the data block containing the previous line
2726  * This also fills the stack with the blocks from the root to the data block
2727  * This also releases any locked block.
2728  */
2729     if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum,
2730 							  ML_INSERT)) == NULL)
2731 	goto theend;
2732 
2733     buf->b_ml.ml_flags &= ~ML_EMPTY;
2734 
2735     if (lnum == 0)		/* got line one instead, correct db_idx */
2736 	db_idx = -1;		/* careful, it is negative! */
2737     else
2738 	db_idx = lnum - buf->b_ml.ml_locked_low;
2739 		/* get line count before the insertion */
2740     line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
2741 
2742     dp = (DATA_BL *)(hp->bh_data);
2743 
2744 /*
2745  * If
2746  * - there is not enough room in the current block
2747  * - appending to the last line in the block
2748  * - not appending to the last line in the file
2749  * insert in front of the next block.
2750  */
2751     if ((int)dp->db_free < space_needed && db_idx == line_count - 1
2752 					    && lnum < buf->b_ml.ml_line_count)
2753     {
2754 	/*
2755 	 * Now that the line is not going to be inserted in the block that we
2756 	 * expected, the line count has to be adjusted in the pointer blocks
2757 	 * by using ml_locked_lineadd.
2758 	 */
2759 	--(buf->b_ml.ml_locked_lineadd);
2760 	--(buf->b_ml.ml_locked_high);
2761 	if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
2762 	    goto theend;
2763 
2764 	db_idx = -1;		    /* careful, it is negative! */
2765 		    /* get line count before the insertion */
2766 	line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
2767 	CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1");
2768 
2769 	dp = (DATA_BL *)(hp->bh_data);
2770     }
2771 
2772     ++buf->b_ml.ml_line_count;
2773 
2774     if ((int)dp->db_free >= space_needed)	/* enough room in data block */
2775     {
2776 	/*
2777 	 * Insert the new line in an existing data block, or in the data block
2778 	 * allocated above.
2779 	 */
2780 	dp->db_txt_start -= len;
2781 	dp->db_free -= space_needed;
2782 	++(dp->db_line_count);
2783 
2784 	/*
2785 	 * move the text of the lines that follow to the front
2786 	 * adjust the indexes of the lines that follow
2787 	 */
2788 	if (line_count > db_idx + 1)	    /* if there are following lines */
2789 	{
2790 	    /*
2791 	     * Offset is the start of the previous line.
2792 	     * This will become the character just after the new line.
2793 	     */
2794 	    if (db_idx < 0)
2795 		offset = dp->db_txt_end;
2796 	    else
2797 		offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK);
2798 	    mch_memmove((char *)dp + dp->db_txt_start,
2799 					  (char *)dp + dp->db_txt_start + len,
2800 				 (size_t)(offset - (dp->db_txt_start + len)));
2801 	    for (i = line_count - 1; i > db_idx; --i)
2802 		dp->db_index[i + 1] = dp->db_index[i] - len;
2803 	    dp->db_index[db_idx + 1] = offset - len;
2804 	}
2805 	else
2806 	    // add line at the end (which is the start of the text)
2807 	    dp->db_index[db_idx + 1] = dp->db_txt_start;
2808 
2809 	/*
2810 	 * copy the text into the block
2811 	 */
2812 	mch_memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len);
2813 	if (mark)
2814 	    dp->db_index[db_idx + 1] |= DB_MARKED;
2815 
2816 	/*
2817 	 * Mark the block dirty.
2818 	 */
2819 	buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2820 	if (!newfile)
2821 	    buf->b_ml.ml_flags |= ML_LOCKED_POS;
2822     }
2823     else	    /* not enough space in data block */
2824     {
2825 	long	    line_count_left, line_count_right;
2826 	int	    page_count_left, page_count_right;
2827 	bhdr_T	    *hp_left;
2828 	bhdr_T	    *hp_right;
2829 	bhdr_T	    *hp_new;
2830 	int	    lines_moved;
2831 	int	    data_moved = 0;	    /* init to shut up gcc */
2832 	int	    total_moved = 0;	    /* init to shut up gcc */
2833 	DATA_BL	    *dp_right, *dp_left;
2834 	int	    stack_idx;
2835 	int	    in_left;
2836 	int	    lineadd;
2837 	blocknr_T   bnum_left, bnum_right;
2838 	linenr_T    lnum_left, lnum_right;
2839 	int	    pb_idx;
2840 	PTR_BL	    *pp_new;
2841 
2842 	/*
2843 	 * There is not enough room, we have to create a new data block and
2844 	 * copy some lines into it.
2845 	 * Then we have to insert an entry in the pointer block.
2846 	 * If this pointer block also is full, we go up another block, and so
2847 	 * on, up to the root if necessary.
2848 	 * The line counts in the pointer blocks have already been adjusted by
2849 	 * ml_find_line().
2850 	 *
2851 	 * We are going to allocate a new data block. Depending on the
2852 	 * situation it will be put to the left or right of the existing
2853 	 * block.  If possible we put the new line in the left block and move
2854 	 * the lines after it to the right block. Otherwise the new line is
2855 	 * also put in the right block. This method is more efficient when
2856 	 * inserting a lot of lines at one place.
2857 	 */
2858 	if (db_idx < 0)		/* left block is new, right block is existing */
2859 	{
2860 	    lines_moved = 0;
2861 	    in_left = TRUE;
2862 	    /* space_needed does not change */
2863 	}
2864 	else			/* left block is existing, right block is new */
2865 	{
2866 	    lines_moved = line_count - db_idx - 1;
2867 	    if (lines_moved == 0)
2868 		in_left = FALSE;	/* put new line in right block */
2869 					/* space_needed does not change */
2870 	    else
2871 	    {
2872 		data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) -
2873 							    dp->db_txt_start;
2874 		total_moved = data_moved + lines_moved * INDEX_SIZE;
2875 		if ((int)dp->db_free + total_moved >= space_needed)
2876 		{
2877 		    in_left = TRUE;	/* put new line in left block */
2878 		    space_needed = total_moved;
2879 		}
2880 		else
2881 		{
2882 		    in_left = FALSE;	    /* put new line in right block */
2883 		    space_needed += total_moved;
2884 		}
2885 	    }
2886 	}
2887 
2888 	page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
2889 	if ((hp_new = ml_new_data(mfp, newfile, page_count)) == NULL)
2890 	{
2891 			/* correct line counts in pointer blocks */
2892 	    --(buf->b_ml.ml_locked_lineadd);
2893 	    --(buf->b_ml.ml_locked_high);
2894 	    goto theend;
2895 	}
2896 	if (db_idx < 0)		/* left block is new */
2897 	{
2898 	    hp_left = hp_new;
2899 	    hp_right = hp;
2900 	    line_count_left = 0;
2901 	    line_count_right = line_count;
2902 	}
2903 	else			/* right block is new */
2904 	{
2905 	    hp_left = hp;
2906 	    hp_right = hp_new;
2907 	    line_count_left = line_count;
2908 	    line_count_right = 0;
2909 	}
2910 	dp_right = (DATA_BL *)(hp_right->bh_data);
2911 	dp_left = (DATA_BL *)(hp_left->bh_data);
2912 	bnum_left = hp_left->bh_bnum;
2913 	bnum_right = hp_right->bh_bnum;
2914 	page_count_left = hp_left->bh_page_count;
2915 	page_count_right = hp_right->bh_page_count;
2916 
2917 	/*
2918 	 * May move the new line into the right/new block.
2919 	 */
2920 	if (!in_left)
2921 	{
2922 	    dp_right->db_txt_start -= len;
2923 	    dp_right->db_free -= len + INDEX_SIZE;
2924 	    dp_right->db_index[0] = dp_right->db_txt_start;
2925 	    if (mark)
2926 		dp_right->db_index[0] |= DB_MARKED;
2927 
2928 	    mch_memmove((char *)dp_right + dp_right->db_txt_start,
2929 							   line, (size_t)len);
2930 	    ++line_count_right;
2931 	}
2932 	/*
2933 	 * may move lines from the left/old block to the right/new one.
2934 	 */
2935 	if (lines_moved)
2936 	{
2937 	    /*
2938 	     */
2939 	    dp_right->db_txt_start -= data_moved;
2940 	    dp_right->db_free -= total_moved;
2941 	    mch_memmove((char *)dp_right + dp_right->db_txt_start,
2942 			(char *)dp_left + dp_left->db_txt_start,
2943 			(size_t)data_moved);
2944 	    offset = dp_right->db_txt_start - dp_left->db_txt_start;
2945 	    dp_left->db_txt_start += data_moved;
2946 	    dp_left->db_free += total_moved;
2947 
2948 	    /*
2949 	     * update indexes in the new block
2950 	     */
2951 	    for (to = line_count_right, from = db_idx + 1;
2952 					 from < line_count_left; ++from, ++to)
2953 		dp_right->db_index[to] = dp->db_index[from] + offset;
2954 	    line_count_right += lines_moved;
2955 	    line_count_left -= lines_moved;
2956 	}
2957 
2958 	/*
2959 	 * May move the new line into the left (old or new) block.
2960 	 */
2961 	if (in_left)
2962 	{
2963 	    dp_left->db_txt_start -= len;
2964 	    dp_left->db_free -= len + INDEX_SIZE;
2965 	    dp_left->db_index[line_count_left] = dp_left->db_txt_start;
2966 	    if (mark)
2967 		dp_left->db_index[line_count_left] |= DB_MARKED;
2968 	    mch_memmove((char *)dp_left + dp_left->db_txt_start,
2969 							   line, (size_t)len);
2970 	    ++line_count_left;
2971 	}
2972 
2973 	if (db_idx < 0)		/* left block is new */
2974 	{
2975 	    lnum_left = lnum + 1;
2976 	    lnum_right = 0;
2977 	}
2978 	else			/* right block is new */
2979 	{
2980 	    lnum_left = 0;
2981 	    if (in_left)
2982 		lnum_right = lnum + 2;
2983 	    else
2984 		lnum_right = lnum + 1;
2985 	}
2986 	dp_left->db_line_count = line_count_left;
2987 	dp_right->db_line_count = line_count_right;
2988 
2989 	/*
2990 	 * release the two data blocks
2991 	 * The new one (hp_new) already has a correct blocknumber.
2992 	 * The old one (hp, in ml_locked) gets a positive blocknumber if
2993 	 * we changed it and we are not editing a new file.
2994 	 */
2995 	if (lines_moved || in_left)
2996 	    buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
2997 	if (!newfile && db_idx >= 0 && in_left)
2998 	    buf->b_ml.ml_flags |= ML_LOCKED_POS;
2999 	mf_put(mfp, hp_new, TRUE, FALSE);
3000 
3001 	/*
3002 	 * flush the old data block
3003 	 * set ml_locked_lineadd to 0, because the updating of the
3004 	 * pointer blocks is done below
3005 	 */
3006 	lineadd = buf->b_ml.ml_locked_lineadd;
3007 	buf->b_ml.ml_locked_lineadd = 0;
3008 	ml_find_line(buf, (linenr_T)0, ML_FLUSH);   /* flush data block */
3009 
3010 	/*
3011 	 * update pointer blocks for the new data block
3012 	 */
3013 	for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0;
3014 								  --stack_idx)
3015 	{
3016 	    ip = &(buf->b_ml.ml_stack[stack_idx]);
3017 	    pb_idx = ip->ip_index;
3018 	    if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
3019 		goto theend;
3020 	    pp = (PTR_BL *)(hp->bh_data);   /* must be pointer block */
3021 	    if (pp->pb_id != PTR_ID)
3022 	    {
3023 		iemsg(_("E317: pointer block id wrong 3"));
3024 		mf_put(mfp, hp, FALSE, FALSE);
3025 		goto theend;
3026 	    }
3027 	    /*
3028 	     * TODO: If the pointer block is full and we are adding at the end
3029 	     * try to insert in front of the next block
3030 	     */
3031 	    /* block not full, add one entry */
3032 	    if (pp->pb_count < pp->pb_count_max)
3033 	    {
3034 		if (pb_idx + 1 < (int)pp->pb_count)
3035 		    mch_memmove(&pp->pb_pointer[pb_idx + 2],
3036 				&pp->pb_pointer[pb_idx + 1],
3037 			(size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
3038 		++pp->pb_count;
3039 		pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
3040 		pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
3041 		pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
3042 		pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
3043 		pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
3044 		pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
3045 
3046 		if (lnum_left != 0)
3047 		    pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
3048 		if (lnum_right != 0)
3049 		    pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
3050 
3051 		mf_put(mfp, hp, TRUE, FALSE);
3052 		buf->b_ml.ml_stack_top = stack_idx + 1;	    /* truncate stack */
3053 
3054 		if (lineadd)
3055 		{
3056 		    --(buf->b_ml.ml_stack_top);
3057 		    /* fix line count for rest of blocks in the stack */
3058 		    ml_lineadd(buf, lineadd);
3059 							/* fix stack itself */
3060 		    buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
3061 								      lineadd;
3062 		    ++(buf->b_ml.ml_stack_top);
3063 		}
3064 
3065 		/*
3066 		 * We are finished, break the loop here.
3067 		 */
3068 		break;
3069 	    }
3070 	    else			/* pointer block full */
3071 	    {
3072 		/*
3073 		 * split the pointer block
3074 		 * allocate a new pointer block
3075 		 * move some of the pointer into the new block
3076 		 * prepare for updating the parent block
3077 		 */
3078 		for (;;)	/* do this twice when splitting block 1 */
3079 		{
3080 		    hp_new = ml_new_ptr(mfp);
3081 		    if (hp_new == NULL)	    /* TODO: try to fix tree */
3082 			goto theend;
3083 		    pp_new = (PTR_BL *)(hp_new->bh_data);
3084 
3085 		    if (hp->bh_bnum != 1)
3086 			break;
3087 
3088 		    /*
3089 		     * if block 1 becomes full the tree is given an extra level
3090 		     * The pointers from block 1 are moved into the new block.
3091 		     * block 1 is updated to point to the new block
3092 		     * then continue to split the new block
3093 		     */
3094 		    mch_memmove(pp_new, pp, (size_t)page_size);
3095 		    pp->pb_count = 1;
3096 		    pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
3097 		    pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
3098 		    pp->pb_pointer[0].pe_old_lnum = 1;
3099 		    pp->pb_pointer[0].pe_page_count = 1;
3100 		    mf_put(mfp, hp, TRUE, FALSE);   /* release block 1 */
3101 		    hp = hp_new;		/* new block is to be split */
3102 		    pp = pp_new;
3103 		    CHECK(stack_idx != 0, _("stack_idx should be 0"));
3104 		    ip->ip_index = 0;
3105 		    ++stack_idx;	/* do block 1 again later */
3106 		}
3107 		/*
3108 		 * move the pointers after the current one to the new block
3109 		 * If there are none, the new entry will be in the new block.
3110 		 */
3111 		total_moved = pp->pb_count - pb_idx - 1;
3112 		if (total_moved)
3113 		{
3114 		    mch_memmove(&pp_new->pb_pointer[0],
3115 				&pp->pb_pointer[pb_idx + 1],
3116 				(size_t)(total_moved) * sizeof(PTR_EN));
3117 		    pp_new->pb_count = total_moved;
3118 		    pp->pb_count -= total_moved - 1;
3119 		    pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
3120 		    pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
3121 		    pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
3122 		    if (lnum_right)
3123 			pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
3124 		}
3125 		else
3126 		{
3127 		    pp_new->pb_count = 1;
3128 		    pp_new->pb_pointer[0].pe_bnum = bnum_right;
3129 		    pp_new->pb_pointer[0].pe_line_count = line_count_right;
3130 		    pp_new->pb_pointer[0].pe_page_count = page_count_right;
3131 		    pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
3132 		}
3133 		pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
3134 		pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
3135 		pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
3136 		if (lnum_left)
3137 		    pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
3138 		lnum_left = 0;
3139 		lnum_right = 0;
3140 
3141 		/*
3142 		 * recompute line counts
3143 		 */
3144 		line_count_right = 0;
3145 		for (i = 0; i < (int)pp_new->pb_count; ++i)
3146 		    line_count_right += pp_new->pb_pointer[i].pe_line_count;
3147 		line_count_left = 0;
3148 		for (i = 0; i < (int)pp->pb_count; ++i)
3149 		    line_count_left += pp->pb_pointer[i].pe_line_count;
3150 
3151 		bnum_left = hp->bh_bnum;
3152 		bnum_right = hp_new->bh_bnum;
3153 		page_count_left = 1;
3154 		page_count_right = 1;
3155 		mf_put(mfp, hp, TRUE, FALSE);
3156 		mf_put(mfp, hp_new, TRUE, FALSE);
3157 	    }
3158 	}
3159 
3160 	/*
3161 	 * Safety check: fallen out of for loop?
3162 	 */
3163 	if (stack_idx < 0)
3164 	{
3165 	    iemsg(_("E318: Updated too many blocks?"));
3166 	    buf->b_ml.ml_stack_top = 0;	/* invalidate stack */
3167 	}
3168     }
3169 
3170 #ifdef FEAT_BYTEOFF
3171     /* The line was inserted below 'lnum' */
3172     ml_updatechunk(buf, lnum + 1, (long)len, ML_CHNK_ADDLINE);
3173 #endif
3174 #ifdef FEAT_NETBEANS_INTG
3175     if (netbeans_active())
3176     {
3177 	if (STRLEN(line) > 0)
3178 	    netbeans_inserted(buf, lnum+1, (colnr_T)0, line, (int)STRLEN(line));
3179 	netbeans_inserted(buf, lnum+1, (colnr_T)STRLEN(line),
3180 							   (char_u *)"\n", 1);
3181     }
3182 #endif
3183 #ifdef FEAT_JOB_CHANNEL
3184     if (buf->b_write_to_channel)
3185 	channel_write_new_lines(buf);
3186 #endif
3187     ret = OK;
3188 
3189 theend:
3190 #ifdef FEAT_TEXT_PROP
3191     vim_free(tofree);
3192 #endif
3193     return ret;
3194 }
3195 
3196 /*
3197  * Replace line lnum, with buffering, in current buffer.
3198  *
3199  * If "copy" is TRUE, make a copy of the line, otherwise the line has been
3200  * copied to allocated memory already.
3201  *
3202  * Check: The caller of this function should probably also call
3203  * changed_lines(), unless update_screen(NOT_VALID) is used.
3204  *
3205  * return FAIL for failure, OK otherwise
3206  */
3207     int
3208 ml_replace(linenr_T lnum, char_u *line, int copy)
3209 {
3210     colnr_T len = -1;
3211 
3212     if (line != NULL)
3213 	len = (colnr_T)STRLEN(line);
3214     return ml_replace_len(lnum, line, len, FALSE, copy);
3215 }
3216 
3217 /*
3218  * Replace a line for the current buffer.  Like ml_replace() with:
3219  * "len_arg" is the length of the text, excluding NUL.
3220  * If "has_props" is TRUE then "line_arg" includes the text properties and
3221  * "len_arg" includes the NUL of the text.
3222  */
3223     int
3224 ml_replace_len(
3225 	linenr_T    lnum,
3226 	char_u	    *line_arg,
3227 	colnr_T	    len_arg,
3228 	int	    has_props,
3229 	int	    copy)
3230 {
3231     char_u *line = line_arg;
3232     colnr_T len = len_arg;
3233 
3234     if (line == NULL)		/* just checking... */
3235 	return FAIL;
3236 
3237     /* When starting up, we might still need to create the memfile */
3238     if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL, 0) == FAIL)
3239 	return FAIL;
3240 
3241     if (!has_props)
3242 	++len;  // include the NUL after the text
3243     if (copy)
3244     {
3245 	// copy the line to allocated memory
3246 #ifdef FEAT_TEXT_PROP
3247 	if (has_props)
3248 	    line = vim_memsave(line, len);
3249 	else
3250 #endif
3251 	    line = vim_strnsave(line, len - 1);
3252 	if (line == NULL)
3253 	    return FAIL;
3254     }
3255 
3256 #ifdef FEAT_NETBEANS_INTG
3257     if (netbeans_active())
3258     {
3259 	netbeans_removed(curbuf, lnum, 0, (long)STRLEN(ml_get(lnum)));
3260 	netbeans_inserted(curbuf, lnum, 0, line, (int)STRLEN(line));
3261     }
3262 #endif
3263     if (curbuf->b_ml.ml_line_lnum != lnum)
3264     {
3265 	// another line is buffered, flush it
3266 	ml_flush_line(curbuf);
3267 	curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
3268 
3269 #ifdef FEAT_TEXT_PROP
3270 	if (curbuf->b_has_textprop && !has_props)
3271 	    // Need to fetch the old line to copy over any text properties.
3272 	    ml_get_buf(curbuf, lnum, TRUE);
3273 #endif
3274     }
3275 
3276 #ifdef FEAT_TEXT_PROP
3277     if (curbuf->b_has_textprop && !has_props)
3278     {
3279 	size_t	oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
3280 
3281 	if (oldtextlen < (size_t)curbuf->b_ml.ml_line_len)
3282 	{
3283 	    char_u *newline;
3284 	    size_t textproplen = curbuf->b_ml.ml_line_len - oldtextlen;
3285 
3286 	    // Need to copy over text properties, stored after the text.
3287 	    newline = alloc(len + (int)textproplen);
3288 	    if (newline != NULL)
3289 	    {
3290 		mch_memmove(newline, line, len);
3291 		mch_memmove(newline + len, curbuf->b_ml.ml_line_ptr + oldtextlen, textproplen);
3292 		vim_free(line);
3293 		line = newline;
3294 		len += (colnr_T)textproplen;
3295 	    }
3296 	}
3297     }
3298 #endif
3299 
3300     if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY)	// same line allocated
3301 	vim_free(curbuf->b_ml.ml_line_ptr);	// free it
3302 
3303     curbuf->b_ml.ml_line_ptr = line;
3304     curbuf->b_ml.ml_line_len = len;
3305     curbuf->b_ml.ml_line_lnum = lnum;
3306     curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
3307 
3308     return OK;
3309 }
3310 
3311 #ifdef FEAT_TEXT_PROP
3312 /*
3313  * Adjust text properties in line "lnum" for a deleted line.
3314  * When "above" is true this is the line above the deleted line.
3315  * "del_props" are the properties of the deleted line.
3316  */
3317     static void
3318 adjust_text_props_for_delete(
3319 	buf_T	    *buf,
3320 	linenr_T    lnum,
3321 	char_u	    *del_props,
3322 	int	    del_props_len,
3323 	int	    above)
3324 {
3325     int		did_get_line = FALSE;
3326     int		done_del;
3327     int		done_this;
3328     textprop_T	prop_del;
3329     textprop_T	prop_this;
3330     bhdr_T	*hp;
3331     DATA_BL	*dp;
3332     int		idx;
3333     int		line_start;
3334     long	line_size;
3335     int		this_props_len;
3336     char_u	*text;
3337     size_t	textlen;
3338     int		found;
3339 
3340     for (done_del = 0; done_del < del_props_len; done_del += sizeof(textprop_T))
3341     {
3342 	mch_memmove(&prop_del, del_props + done_del, sizeof(textprop_T));
3343 	if ((above && (prop_del.tp_flags & TP_FLAG_CONT_PREV)
3344 		    && !(prop_del.tp_flags & TP_FLAG_CONT_NEXT))
3345 		|| (!above && (prop_del.tp_flags & TP_FLAG_CONT_NEXT)
3346 		    && !(prop_del.tp_flags & TP_FLAG_CONT_PREV)))
3347 	{
3348 	    if (!did_get_line)
3349 	    {
3350 		did_get_line = TRUE;
3351 		if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
3352 		    return;
3353 
3354 		dp = (DATA_BL *)(hp->bh_data);
3355 		idx = lnum - buf->b_ml.ml_locked_low;
3356 		line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
3357 		if (idx == 0)		// first line in block, text at the end
3358 		    line_size = dp->db_txt_end - line_start;
3359 		else
3360 		    line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
3361 		text = (char_u *)dp + line_start;
3362 		textlen = STRLEN(text) + 1;
3363 		if ((long)textlen >= line_size)
3364 		{
3365 		    if (above)
3366 			internal_error("no text property above deleted line");
3367 		    else
3368 			internal_error("no text property below deleted line");
3369 		    return;
3370 		}
3371 		this_props_len = line_size - (int)textlen;
3372 	    }
3373 
3374 	    found = FALSE;
3375 	    for (done_this = 0; done_this < this_props_len; done_this += sizeof(textprop_T))
3376 	    {
3377 		mch_memmove(&prop_this, text + textlen + done_del, sizeof(textprop_T));
3378 		if (prop_del.tp_id == prop_this.tp_id
3379 			&& prop_del.tp_type == prop_this.tp_type)
3380 		{
3381 		    int flag = above ? TP_FLAG_CONT_NEXT : TP_FLAG_CONT_PREV;
3382 
3383 		    found = TRUE;
3384 		    if (prop_this.tp_flags & flag)
3385 		    {
3386 			prop_this.tp_flags &= ~flag;
3387 			mch_memmove(text + textlen + done_del, &prop_this, sizeof(textprop_T));
3388 		    }
3389 		    else if (above)
3390 			internal_error("text property above deleted line does not continue");
3391 		    else
3392 			internal_error("text property below deleted line does not continue");
3393 		}
3394 	    }
3395 	    if (!found)
3396 	    {
3397 		if (above)
3398 		    internal_error("text property above deleted line not found");
3399 		else
3400 		    internal_error("text property below deleted line not found");
3401 	    }
3402 
3403 	    buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
3404 	}
3405     }
3406 }
3407 #endif
3408 
3409 /*
3410  * Delete line "lnum" in the current buffer.
3411  * When "message" is TRUE may give a "No lines in buffer" message.
3412  *
3413  * Check: The caller of this function should probably also call
3414  * deleted_lines() after this.
3415  *
3416  * return FAIL for failure, OK otherwise
3417  */
3418     int
3419 ml_delete(linenr_T lnum, int message)
3420 {
3421     ml_flush_line(curbuf);
3422     return ml_delete_int(curbuf, lnum, message);
3423 }
3424 
3425     static int
3426 ml_delete_int(buf_T *buf, linenr_T lnum, int message)
3427 {
3428     bhdr_T	*hp;
3429     memfile_T	*mfp;
3430     DATA_BL	*dp;
3431     PTR_BL	*pp;
3432     infoptr_T	*ip;
3433     int		count;	    /* number of entries in block */
3434     int		idx;
3435     int		stack_idx;
3436     int		text_start;
3437     int		line_start;
3438     long	line_size;
3439     int		i;
3440     int		ret = FAIL;
3441 #ifdef FEAT_TEXT_PROP
3442     char_u	*textprop_save = NULL;
3443     int		textprop_save_len;
3444 #endif
3445 
3446     if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
3447 	return FAIL;
3448 
3449     if (lowest_marked && lowest_marked > lnum)
3450 	lowest_marked--;
3451 
3452 /*
3453  * If the file becomes empty the last line is replaced by an empty line.
3454  */
3455     if (buf->b_ml.ml_line_count == 1)	    /* file becomes empty */
3456     {
3457 	if (message
3458 #ifdef FEAT_NETBEANS_INTG
3459 		&& !netbeansSuppressNoLines
3460 #endif
3461 	   )
3462 	    set_keep_msg((char_u *)_(no_lines_msg), 0);
3463 
3464 	/* FEAT_BYTEOFF already handled in there, don't worry 'bout it below */
3465 	i = ml_replace((linenr_T)1, (char_u *)"", TRUE);
3466 	buf->b_ml.ml_flags |= ML_EMPTY;
3467 
3468 	return i;
3469     }
3470 
3471 /*
3472  * Find the data block containing the line.
3473  * This also fills the stack with the blocks from the root to the data block.
3474  * This also releases any locked block..
3475  */
3476     mfp = buf->b_ml.ml_mfp;
3477     if (mfp == NULL)
3478 	return FAIL;
3479 
3480     if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL)
3481 	return FAIL;
3482 
3483     dp = (DATA_BL *)(hp->bh_data);
3484     /* compute line count before the delete */
3485     count = (long)(buf->b_ml.ml_locked_high)
3486 					- (long)(buf->b_ml.ml_locked_low) + 2;
3487     idx = lnum - buf->b_ml.ml_locked_low;
3488 
3489     --buf->b_ml.ml_line_count;
3490 
3491     line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
3492     if (idx == 0)		/* first line in block, text at the end */
3493 	line_size = dp->db_txt_end - line_start;
3494     else
3495 	line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
3496 
3497 #ifdef FEAT_NETBEANS_INTG
3498     if (netbeans_active())
3499 	netbeans_removed(buf, lnum, 0, (long)line_size);
3500 #endif
3501 #ifdef FEAT_TEXT_PROP
3502     // If there are text properties, make a copy, so that we can update
3503     // properties in preceding and following lines.
3504     if (buf->b_has_textprop)
3505     {
3506 	size_t	textlen = STRLEN((char_u *)dp + line_start) + 1;
3507 
3508 	if ((long)textlen < line_size)
3509 	{
3510 	    textprop_save_len = line_size - (int)textlen;
3511 	    textprop_save = vim_memsave((char_u *)dp + line_start + textlen,
3512 							  textprop_save_len);
3513 	}
3514     }
3515 #endif
3516 
3517 /*
3518  * special case: If there is only one line in the data block it becomes empty.
3519  * Then we have to remove the entry, pointing to this data block, from the
3520  * pointer block. If this pointer block also becomes empty, we go up another
3521  * block, and so on, up to the root if necessary.
3522  * The line counts in the pointer blocks have already been adjusted by
3523  * ml_find_line().
3524  */
3525     if (count == 1)
3526     {
3527 	mf_free(mfp, hp);	/* free the data block */
3528 	buf->b_ml.ml_locked = NULL;
3529 
3530 	for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0;
3531 								  --stack_idx)
3532 	{
3533 	    buf->b_ml.ml_stack_top = 0;	    /* stack is invalid when failing */
3534 	    ip = &(buf->b_ml.ml_stack[stack_idx]);
3535 	    idx = ip->ip_index;
3536 	    if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
3537 		goto theend;
3538 	    pp = (PTR_BL *)(hp->bh_data);   /* must be pointer block */
3539 	    if (pp->pb_id != PTR_ID)
3540 	    {
3541 		iemsg(_("E317: pointer block id wrong 4"));
3542 		mf_put(mfp, hp, FALSE, FALSE);
3543 		goto theend;
3544 	    }
3545 	    count = --(pp->pb_count);
3546 	    if (count == 0)	    /* the pointer block becomes empty! */
3547 		mf_free(mfp, hp);
3548 	    else
3549 	    {
3550 		if (count != idx)	/* move entries after the deleted one */
3551 		    mch_memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1],
3552 				      (size_t)(count - idx) * sizeof(PTR_EN));
3553 		mf_put(mfp, hp, TRUE, FALSE);
3554 
3555 		buf->b_ml.ml_stack_top = stack_idx;	/* truncate stack */
3556 		/* fix line count for rest of blocks in the stack */
3557 		if (buf->b_ml.ml_locked_lineadd != 0)
3558 		{
3559 		    ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
3560 		    buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
3561 						  buf->b_ml.ml_locked_lineadd;
3562 		}
3563 		++(buf->b_ml.ml_stack_top);
3564 
3565 		break;
3566 	    }
3567 	}
3568 	CHECK(stack_idx < 0, _("deleted block 1?"));
3569     }
3570     else
3571     {
3572 	/*
3573 	 * delete the text by moving the next lines forwards
3574 	 */
3575 	text_start = dp->db_txt_start;
3576 	mch_memmove((char *)dp + text_start + line_size,
3577 		  (char *)dp + text_start, (size_t)(line_start - text_start));
3578 
3579 	/*
3580 	 * delete the index by moving the next indexes backwards
3581 	 * Adjust the indexes for the text movement.
3582 	 */
3583 	for (i = idx; i < count - 1; ++i)
3584 	    dp->db_index[i] = dp->db_index[i + 1] + line_size;
3585 
3586 	dp->db_free += line_size + INDEX_SIZE;
3587 	dp->db_txt_start += line_size;
3588 	--(dp->db_line_count);
3589 
3590 	/*
3591 	 * mark the block dirty and make sure it is in the file (for recovery)
3592 	 */
3593 	buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
3594     }
3595 
3596 #ifdef FEAT_BYTEOFF
3597     ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE);
3598 #endif
3599     ret = OK;
3600 
3601 theend:
3602 #ifdef FEAT_TEXT_PROP
3603     if (textprop_save != NULL)
3604     {
3605 	// Adjust text properties in the line above and below.
3606 	if (lnum > 1)
3607 	    adjust_text_props_for_delete(buf, lnum - 1, textprop_save, textprop_save_len, TRUE);
3608 	if (lnum <= buf->b_ml.ml_line_count)
3609 	    adjust_text_props_for_delete(buf, lnum, textprop_save, textprop_save_len, FALSE);
3610     }
3611     vim_free(textprop_save);
3612 #endif
3613     return ret;
3614 }
3615 
3616 /*
3617  * set the DB_MARKED flag for line 'lnum'
3618  */
3619     void
3620 ml_setmarked(linenr_T lnum)
3621 {
3622     bhdr_T    *hp;
3623     DATA_BL *dp;
3624 				    /* invalid line number */
3625     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count
3626 					       || curbuf->b_ml.ml_mfp == NULL)
3627 	return;			    /* give error message? */
3628 
3629     if (lowest_marked == 0 || lowest_marked > lnum)
3630 	lowest_marked = lnum;
3631 
3632     /*
3633      * find the data block containing the line
3634      * This also fills the stack with the blocks from the root to the data block
3635      * This also releases any locked block.
3636      */
3637     if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
3638 	return;		    /* give error message? */
3639 
3640     dp = (DATA_BL *)(hp->bh_data);
3641     dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED;
3642     curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
3643 }
3644 
3645 /*
3646  * find the first line with its DB_MARKED flag set
3647  */
3648     linenr_T
3649 ml_firstmarked(void)
3650 {
3651     bhdr_T	*hp;
3652     DATA_BL	*dp;
3653     linenr_T	lnum;
3654     int		i;
3655 
3656     if (curbuf->b_ml.ml_mfp == NULL)
3657 	return (linenr_T) 0;
3658 
3659     /*
3660      * The search starts with lowest_marked line. This is the last line where
3661      * a mark was found, adjusted by inserting/deleting lines.
3662      */
3663     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
3664     {
3665 	/*
3666 	 * Find the data block containing the line.
3667 	 * This also fills the stack with the blocks from the root to the data
3668 	 * block This also releases any locked block.
3669 	 */
3670 	if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
3671 	    return (linenr_T)0;		    /* give error message? */
3672 
3673 	dp = (DATA_BL *)(hp->bh_data);
3674 
3675 	for (i = lnum - curbuf->b_ml.ml_locked_low;
3676 			    lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
3677 	    if ((dp->db_index[i]) & DB_MARKED)
3678 	    {
3679 		(dp->db_index[i]) &= DB_INDEX_MASK;
3680 		curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
3681 		lowest_marked = lnum + 1;
3682 		return lnum;
3683 	    }
3684     }
3685 
3686     return (linenr_T) 0;
3687 }
3688 
3689 /*
3690  * clear all DB_MARKED flags
3691  */
3692     void
3693 ml_clearmarked(void)
3694 {
3695     bhdr_T	*hp;
3696     DATA_BL	*dp;
3697     linenr_T	lnum;
3698     int		i;
3699 
3700     if (curbuf->b_ml.ml_mfp == NULL)	    /* nothing to do */
3701 	return;
3702 
3703     /*
3704      * The search starts with line lowest_marked.
3705      */
3706     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
3707     {
3708 	/*
3709 	 * Find the data block containing the line.
3710 	 * This also fills the stack with the blocks from the root to the data
3711 	 * block and releases any locked block.
3712 	 */
3713 	if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
3714 	    return;		/* give error message? */
3715 
3716 	dp = (DATA_BL *)(hp->bh_data);
3717 
3718 	for (i = lnum - curbuf->b_ml.ml_locked_low;
3719 			    lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
3720 	    if ((dp->db_index[i]) & DB_MARKED)
3721 	    {
3722 		(dp->db_index[i]) &= DB_INDEX_MASK;
3723 		curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
3724 	    }
3725     }
3726 
3727     lowest_marked = 0;
3728     return;
3729 }
3730 
3731 /*
3732  * flush ml_line if necessary
3733  */
3734     static void
3735 ml_flush_line(buf_T *buf)
3736 {
3737     bhdr_T	*hp;
3738     DATA_BL	*dp;
3739     linenr_T	lnum;
3740     char_u	*new_line;
3741     char_u	*old_line;
3742     colnr_T	new_len;
3743     int		old_len;
3744     int		extra;
3745     int		idx;
3746     int		start;
3747     int		count;
3748     int		i;
3749     static int  entered = FALSE;
3750 
3751     if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL)
3752 	return;		/* nothing to do */
3753 
3754     if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
3755     {
3756 	/* This code doesn't work recursively, but Netbeans may call back here
3757 	 * when obtaining the cursor position. */
3758 	if (entered)
3759 	    return;
3760 	entered = TRUE;
3761 
3762 	lnum = buf->b_ml.ml_line_lnum;
3763 	new_line = buf->b_ml.ml_line_ptr;
3764 
3765 	hp = ml_find_line(buf, lnum, ML_FIND);
3766 	if (hp == NULL)
3767 	    siemsg(_("E320: Cannot find line %ld"), lnum);
3768 	else
3769 	{
3770 	    dp = (DATA_BL *)(hp->bh_data);
3771 	    idx = lnum - buf->b_ml.ml_locked_low;
3772 	    start = ((dp->db_index[idx]) & DB_INDEX_MASK);
3773 	    old_line = (char_u *)dp + start;
3774 	    if (idx == 0)	/* line is last in block */
3775 		old_len = dp->db_txt_end - start;
3776 	    else		/* text of previous line follows */
3777 		old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
3778 	    new_len = buf->b_ml.ml_line_len;
3779 	    extra = new_len - old_len;	    /* negative if lines gets smaller */
3780 
3781 	    /*
3782 	     * if new line fits in data block, replace directly
3783 	     */
3784 	    if ((int)dp->db_free >= extra)
3785 	    {
3786 		/* if the length changes and there are following lines */
3787 		count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
3788 		if (extra != 0 && idx < count - 1)
3789 		{
3790 		    /* move text of following lines */
3791 		    mch_memmove((char *)dp + dp->db_txt_start - extra,
3792 				(char *)dp + dp->db_txt_start,
3793 				(size_t)(start - dp->db_txt_start));
3794 
3795 		    /* adjust pointers of this and following lines */
3796 		    for (i = idx + 1; i < count; ++i)
3797 			dp->db_index[i] -= extra;
3798 		}
3799 		dp->db_index[idx] -= extra;
3800 
3801 		/* adjust free space */
3802 		dp->db_free -= extra;
3803 		dp->db_txt_start -= extra;
3804 
3805 		/* copy new line into the data block */
3806 		mch_memmove(old_line - extra, new_line, (size_t)new_len);
3807 		buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
3808 #ifdef FEAT_BYTEOFF
3809 		/* The else case is already covered by the insert and delete */
3810 		ml_updatechunk(buf, lnum, (long)extra, ML_CHNK_UPDLINE);
3811 #endif
3812 	    }
3813 	    else
3814 	    {
3815 		/*
3816 		 * Cannot do it in one data block: Delete and append.
3817 		 * Append first, because ml_delete_int() cannot delete the
3818 		 * last line in a buffer, which causes trouble for a buffer
3819 		 * that has only one line.
3820 		 * Don't forget to copy the mark!
3821 		 */
3822 		/* How about handling errors??? */
3823 		(void)ml_append_int(buf, lnum, new_line, new_len, FALSE,
3824 					     (dp->db_index[idx] & DB_MARKED));
3825 		(void)ml_delete_int(buf, lnum, FALSE);
3826 	    }
3827 	}
3828 	vim_free(new_line);
3829 
3830 	entered = FALSE;
3831     }
3832 
3833     buf->b_ml.ml_line_lnum = 0;
3834 }
3835 
3836 /*
3837  * create a new, empty, data block
3838  */
3839     static bhdr_T *
3840 ml_new_data(memfile_T *mfp, int negative, int page_count)
3841 {
3842     bhdr_T	*hp;
3843     DATA_BL	*dp;
3844 
3845     if ((hp = mf_new(mfp, negative, page_count)) == NULL)
3846 	return NULL;
3847 
3848     dp = (DATA_BL *)(hp->bh_data);
3849     dp->db_id = DATA_ID;
3850     dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size;
3851     dp->db_free = dp->db_txt_start - HEADER_SIZE;
3852     dp->db_line_count = 0;
3853 
3854     return hp;
3855 }
3856 
3857 /*
3858  * create a new, empty, pointer block
3859  */
3860     static bhdr_T *
3861 ml_new_ptr(memfile_T *mfp)
3862 {
3863     bhdr_T	*hp;
3864     PTR_BL	*pp;
3865 
3866     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
3867 	return NULL;
3868 
3869     pp = (PTR_BL *)(hp->bh_data);
3870     pp->pb_id = PTR_ID;
3871     pp->pb_count = 0;
3872     pp->pb_count_max = (short_u)((mfp->mf_page_size - sizeof(PTR_BL))
3873 							/ sizeof(PTR_EN) + 1);
3874 
3875     return hp;
3876 }
3877 
3878 /*
3879  * Lookup line 'lnum' in a memline.
3880  *
3881  *   action: if ML_DELETE or ML_INSERT the line count is updated while searching
3882  *	     if ML_FLUSH only flush a locked block
3883  *	     if ML_FIND just find the line
3884  *
3885  * If the block was found it is locked and put in ml_locked.
3886  * The stack is updated to lead to the locked block. The ip_high field in
3887  * the stack is updated to reflect the last line in the block AFTER the
3888  * insert or delete, also if the pointer block has not been updated yet. But
3889  * if ml_locked != NULL ml_locked_lineadd must be added to ip_high.
3890  *
3891  * return: NULL for failure, pointer to block header otherwise
3892  */
3893     static bhdr_T *
3894 ml_find_line(buf_T *buf, linenr_T lnum, int action)
3895 {
3896     DATA_BL	*dp;
3897     PTR_BL	*pp;
3898     infoptr_T	*ip;
3899     bhdr_T	*hp;
3900     memfile_T	*mfp;
3901     linenr_T	t;
3902     blocknr_T	bnum, bnum2;
3903     int		dirty;
3904     linenr_T	low, high;
3905     int		top;
3906     int		page_count;
3907     int		idx;
3908 
3909     mfp = buf->b_ml.ml_mfp;
3910 
3911     /*
3912      * If there is a locked block check if the wanted line is in it.
3913      * If not, flush and release the locked block.
3914      * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
3915      * Don't do this for ML_FLUSH, because we want to flush the locked block.
3916      * Don't do this when 'swapfile' is reset, we want to load all the blocks.
3917      */
3918     if (buf->b_ml.ml_locked)
3919     {
3920 	if (ML_SIMPLE(action)
3921 		&& buf->b_ml.ml_locked_low <= lnum
3922 		&& buf->b_ml.ml_locked_high >= lnum
3923 		&& !mf_dont_release)
3924 	{
3925 	    /* remember to update pointer blocks and stack later */
3926 	    if (action == ML_INSERT)
3927 	    {
3928 		++(buf->b_ml.ml_locked_lineadd);
3929 		++(buf->b_ml.ml_locked_high);
3930 	    }
3931 	    else if (action == ML_DELETE)
3932 	    {
3933 		--(buf->b_ml.ml_locked_lineadd);
3934 		--(buf->b_ml.ml_locked_high);
3935 	    }
3936 	    return (buf->b_ml.ml_locked);
3937 	}
3938 
3939 	mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY,
3940 					    buf->b_ml.ml_flags & ML_LOCKED_POS);
3941 	buf->b_ml.ml_locked = NULL;
3942 
3943 	/*
3944 	 * If lines have been added or deleted in the locked block, need to
3945 	 * update the line count in pointer blocks.
3946 	 */
3947 	if (buf->b_ml.ml_locked_lineadd != 0)
3948 	    ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
3949     }
3950 
3951     if (action == ML_FLUSH)	    /* nothing else to do */
3952 	return NULL;
3953 
3954     bnum = 1;			    /* start at the root of the tree */
3955     page_count = 1;
3956     low = 1;
3957     high = buf->b_ml.ml_line_count;
3958 
3959     if (action == ML_FIND)	/* first try stack entries */
3960     {
3961 	for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top)
3962 	{
3963 	    ip = &(buf->b_ml.ml_stack[top]);
3964 	    if (ip->ip_low <= lnum && ip->ip_high >= lnum)
3965 	    {
3966 		bnum = ip->ip_bnum;
3967 		low = ip->ip_low;
3968 		high = ip->ip_high;
3969 		buf->b_ml.ml_stack_top = top;	/* truncate stack at prev entry */
3970 		break;
3971 	    }
3972 	}
3973 	if (top < 0)
3974 	    buf->b_ml.ml_stack_top = 0;		/* not found, start at the root */
3975     }
3976     else	/* ML_DELETE or ML_INSERT */
3977 	buf->b_ml.ml_stack_top = 0;	/* start at the root */
3978 
3979 /*
3980  * search downwards in the tree until a data block is found
3981  */
3982     for (;;)
3983     {
3984 	if ((hp = mf_get(mfp, bnum, page_count)) == NULL)
3985 	    goto error_noblock;
3986 
3987 	/*
3988 	 * update high for insert/delete
3989 	 */
3990 	if (action == ML_INSERT)
3991 	    ++high;
3992 	else if (action == ML_DELETE)
3993 	    --high;
3994 
3995 	dp = (DATA_BL *)(hp->bh_data);
3996 	if (dp->db_id == DATA_ID)	/* data block */
3997 	{
3998 	    buf->b_ml.ml_locked = hp;
3999 	    buf->b_ml.ml_locked_low = low;
4000 	    buf->b_ml.ml_locked_high = high;
4001 	    buf->b_ml.ml_locked_lineadd = 0;
4002 	    buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS);
4003 	    return hp;
4004 	}
4005 
4006 	pp = (PTR_BL *)(dp);		/* must be pointer block */
4007 	if (pp->pb_id != PTR_ID)
4008 	{
4009 	    iemsg(_("E317: pointer block id wrong"));
4010 	    goto error_block;
4011 	}
4012 
4013 	if ((top = ml_add_stack(buf)) < 0)	/* add new entry to stack */
4014 	    goto error_block;
4015 	ip = &(buf->b_ml.ml_stack[top]);
4016 	ip->ip_bnum = bnum;
4017 	ip->ip_low = low;
4018 	ip->ip_high = high;
4019 	ip->ip_index = -1;		/* index not known yet */
4020 
4021 	dirty = FALSE;
4022 	for (idx = 0; idx < (int)pp->pb_count; ++idx)
4023 	{
4024 	    t = pp->pb_pointer[idx].pe_line_count;
4025 	    CHECK(t == 0, _("pe_line_count is zero"));
4026 	    if ((low += t) > lnum)
4027 	    {
4028 		ip->ip_index = idx;
4029 		bnum = pp->pb_pointer[idx].pe_bnum;
4030 		page_count = pp->pb_pointer[idx].pe_page_count;
4031 		high = low - 1;
4032 		low -= t;
4033 
4034 		/*
4035 		 * a negative block number may have been changed
4036 		 */
4037 		if (bnum < 0)
4038 		{
4039 		    bnum2 = mf_trans_del(mfp, bnum);
4040 		    if (bnum != bnum2)
4041 		    {
4042 			bnum = bnum2;
4043 			pp->pb_pointer[idx].pe_bnum = bnum;
4044 			dirty = TRUE;
4045 		    }
4046 		}
4047 
4048 		break;
4049 	    }
4050 	}
4051 	if (idx >= (int)pp->pb_count)	    /* past the end: something wrong! */
4052 	{
4053 	    if (lnum > buf->b_ml.ml_line_count)
4054 		siemsg(_("E322: line number out of range: %ld past the end"),
4055 					      lnum - buf->b_ml.ml_line_count);
4056 
4057 	    else
4058 		siemsg(_("E323: line count wrong in block %ld"), bnum);
4059 	    goto error_block;
4060 	}
4061 	if (action == ML_DELETE)
4062 	{
4063 	    pp->pb_pointer[idx].pe_line_count--;
4064 	    dirty = TRUE;
4065 	}
4066 	else if (action == ML_INSERT)
4067 	{
4068 	    pp->pb_pointer[idx].pe_line_count++;
4069 	    dirty = TRUE;
4070 	}
4071 	mf_put(mfp, hp, dirty, FALSE);
4072     }
4073 
4074 error_block:
4075     mf_put(mfp, hp, FALSE, FALSE);
4076 error_noblock:
4077     /*
4078      * If action is ML_DELETE or ML_INSERT we have to correct the tree for
4079      * the incremented/decremented line counts, because there won't be a line
4080      * inserted/deleted after all.
4081      */
4082     if (action == ML_DELETE)
4083 	ml_lineadd(buf, 1);
4084     else if (action == ML_INSERT)
4085 	ml_lineadd(buf, -1);
4086     buf->b_ml.ml_stack_top = 0;
4087     return NULL;
4088 }
4089 
4090 /*
4091  * add an entry to the info pointer stack
4092  *
4093  * return -1 for failure, number of the new entry otherwise
4094  */
4095     static int
4096 ml_add_stack(buf_T *buf)
4097 {
4098     int		top;
4099     infoptr_T	*newstack;
4100 
4101     top = buf->b_ml.ml_stack_top;
4102 
4103     /* may have to increase the stack size */
4104     if (top == buf->b_ml.ml_stack_size)
4105     {
4106 	CHECK(top > 0, _("Stack size increases")); /* more than 5 levels??? */
4107 
4108 	newstack = (infoptr_T *)alloc((unsigned)sizeof(infoptr_T) *
4109 					(buf->b_ml.ml_stack_size + STACK_INCR));
4110 	if (newstack == NULL)
4111 	    return -1;
4112 	if (top > 0)
4113 	    mch_memmove(newstack, buf->b_ml.ml_stack,
4114 					     (size_t)top * sizeof(infoptr_T));
4115 	vim_free(buf->b_ml.ml_stack);
4116 	buf->b_ml.ml_stack = newstack;
4117 	buf->b_ml.ml_stack_size += STACK_INCR;
4118     }
4119 
4120     buf->b_ml.ml_stack_top++;
4121     return top;
4122 }
4123 
4124 /*
4125  * Update the pointer blocks on the stack for inserted/deleted lines.
4126  * The stack itself is also updated.
4127  *
4128  * When a insert/delete line action fails, the line is not inserted/deleted,
4129  * but the pointer blocks have already been updated. That is fixed here by
4130  * walking through the stack.
4131  *
4132  * Count is the number of lines added, negative if lines have been deleted.
4133  */
4134     static void
4135 ml_lineadd(buf_T *buf, int count)
4136 {
4137     int		idx;
4138     infoptr_T	*ip;
4139     PTR_BL	*pp;
4140     memfile_T	*mfp = buf->b_ml.ml_mfp;
4141     bhdr_T	*hp;
4142 
4143     for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx)
4144     {
4145 	ip = &(buf->b_ml.ml_stack[idx]);
4146 	if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
4147 	    break;
4148 	pp = (PTR_BL *)(hp->bh_data);	/* must be pointer block */
4149 	if (pp->pb_id != PTR_ID)
4150 	{
4151 	    mf_put(mfp, hp, FALSE, FALSE);
4152 	    iemsg(_("E317: pointer block id wrong 2"));
4153 	    break;
4154 	}
4155 	pp->pb_pointer[ip->ip_index].pe_line_count += count;
4156 	ip->ip_high += count;
4157 	mf_put(mfp, hp, TRUE, FALSE);
4158     }
4159 }
4160 
4161 #if defined(HAVE_READLINK) || defined(PROTO)
4162 /*
4163  * Resolve a symlink in the last component of a file name.
4164  * Note that f_resolve() does it for every part of the path, we don't do that
4165  * here.
4166  * If it worked returns OK and the resolved link in "buf[MAXPATHL]".
4167  * Otherwise returns FAIL.
4168  */
4169     int
4170 resolve_symlink(char_u *fname, char_u *buf)
4171 {
4172     char_u	tmp[MAXPATHL];
4173     int		ret;
4174     int		depth = 0;
4175 
4176     if (fname == NULL)
4177 	return FAIL;
4178 
4179     /* Put the result so far in tmp[], starting with the original name. */
4180     vim_strncpy(tmp, fname, MAXPATHL - 1);
4181 
4182     for (;;)
4183     {
4184 	/* Limit symlink depth to 100, catch recursive loops. */
4185 	if (++depth == 100)
4186 	{
4187 	    semsg(_("E773: Symlink loop for \"%s\""), fname);
4188 	    return FAIL;
4189 	}
4190 
4191 	ret = readlink((char *)tmp, (char *)buf, MAXPATHL - 1);
4192 	if (ret <= 0)
4193 	{
4194 	    if (errno == EINVAL || errno == ENOENT)
4195 	    {
4196 		/* Found non-symlink or not existing file, stop here.
4197 		 * When at the first level use the unmodified name, skip the
4198 		 * call to vim_FullName(). */
4199 		if (depth == 1)
4200 		    return FAIL;
4201 
4202 		/* Use the resolved name in tmp[]. */
4203 		break;
4204 	    }
4205 
4206 	    /* There must be some error reading links, use original name. */
4207 	    return FAIL;
4208 	}
4209 	buf[ret] = NUL;
4210 
4211 	/*
4212 	 * Check whether the symlink is relative or absolute.
4213 	 * If it's relative, build a new path based on the directory
4214 	 * portion of the filename (if any) and the path the symlink
4215 	 * points to.
4216 	 */
4217 	if (mch_isFullName(buf))
4218 	    STRCPY(tmp, buf);
4219 	else
4220 	{
4221 	    char_u *tail;
4222 
4223 	    tail = gettail(tmp);
4224 	    if (STRLEN(tail) + STRLEN(buf) >= MAXPATHL)
4225 		return FAIL;
4226 	    STRCPY(tail, buf);
4227 	}
4228     }
4229 
4230     /*
4231      * Try to resolve the full name of the file so that the swapfile name will
4232      * be consistent even when opening a relative symlink from different
4233      * working directories.
4234      */
4235     return vim_FullName(tmp, buf, MAXPATHL, TRUE);
4236 }
4237 #endif
4238 
4239 /*
4240  * Make swap file name out of the file name and a directory name.
4241  * Returns pointer to allocated memory or NULL.
4242  */
4243     char_u *
4244 makeswapname(
4245     char_u	*fname,
4246     char_u	*ffname UNUSED,
4247     buf_T	*buf,
4248     char_u	*dir_name)
4249 {
4250     char_u	*r, *s;
4251     char_u	*fname_res = fname;
4252 #ifdef HAVE_READLINK
4253     char_u	fname_buf[MAXPATHL];
4254 #endif
4255 
4256 #if defined(UNIX) || defined(WIN3264)  /* Need _very_ long file names */
4257     int		len = (int)STRLEN(dir_name);
4258 
4259     s = dir_name + len;
4260     if (after_pathsep(dir_name, s) && len > 1 && s[-1] == s[-2])
4261     {			       /* Ends with '//', Use Full path */
4262 	r = NULL;
4263 	if ((s = make_percent_swname(dir_name, fname)) != NULL)
4264 	{
4265 	    r = modname(s, (char_u *)".swp", FALSE);
4266 	    vim_free(s);
4267 	}
4268 	return r;
4269     }
4270 #endif
4271 
4272 #ifdef HAVE_READLINK
4273     /* Expand symlink in the file name, so that we put the swap file with the
4274      * actual file instead of with the symlink. */
4275     if (resolve_symlink(fname, fname_buf) == OK)
4276 	fname_res = fname_buf;
4277 #endif
4278 
4279     r = buf_modname(
4280 	    (buf->b_p_sn || buf->b_shortname),
4281 	    fname_res,
4282 	    (char_u *)
4283 #if defined(VMS)
4284 	    "_swp",
4285 #else
4286 	    ".swp",
4287 #endif
4288 	    /* Prepend a '.' to the swap file name for the current directory. */
4289 	    dir_name[0] == '.' && dir_name[1] == NUL);
4290     if (r == NULL)	    /* out of memory */
4291 	return NULL;
4292 
4293     s = get_file_in_dir(r, dir_name);
4294     vim_free(r);
4295     return s;
4296 }
4297 
4298 /*
4299  * Get file name to use for swap file or backup file.
4300  * Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir'
4301  * option "dname".
4302  * - If "dname" is ".", return "fname" (swap file in dir of file).
4303  * - If "dname" starts with "./", insert "dname" in "fname" (swap file
4304  *   relative to dir of file).
4305  * - Otherwise, prepend "dname" to the tail of "fname" (swap file in specific
4306  *   dir).
4307  *
4308  * The return value is an allocated string and can be NULL.
4309  */
4310     char_u *
4311 get_file_in_dir(
4312     char_u  *fname,
4313     char_u  *dname)	/* don't use "dirname", it is a global for Alpha */
4314 {
4315     char_u	*t;
4316     char_u	*tail;
4317     char_u	*retval;
4318     int		save_char;
4319 
4320     tail = gettail(fname);
4321 
4322     if (dname[0] == '.' && dname[1] == NUL)
4323 	retval = vim_strsave(fname);
4324     else if (dname[0] == '.' && vim_ispathsep(dname[1]))
4325     {
4326 	if (tail == fname)	    /* no path before file name */
4327 	    retval = concat_fnames(dname + 2, tail, TRUE);
4328 	else
4329 	{
4330 	    save_char = *tail;
4331 	    *tail = NUL;
4332 	    t = concat_fnames(fname, dname + 2, TRUE);
4333 	    *tail = save_char;
4334 	    if (t == NULL)	    /* out of memory */
4335 		retval = NULL;
4336 	    else
4337 	    {
4338 		retval = concat_fnames(t, tail, TRUE);
4339 		vim_free(t);
4340 	    }
4341 	}
4342     }
4343     else
4344 	retval = concat_fnames(dname, tail, TRUE);
4345 
4346 #ifdef WIN3264
4347     if (retval != NULL)
4348 	for (t = gettail(retval); *t != NUL; MB_PTR_ADV(t))
4349 	    if (*t == ':')
4350 		*t = '%';
4351 #endif
4352 
4353     return retval;
4354 }
4355 
4356 /*
4357  * Print the ATTENTION message: info about an existing swap file.
4358  */
4359     static void
4360 attention_message(
4361     buf_T   *buf,	/* buffer being edited */
4362     char_u  *fname)	/* swap file name */
4363 {
4364     stat_T	st;
4365     time_t	x, sx;
4366     char	*p;
4367 
4368     ++no_wait_return;
4369     (void)emsg(_("E325: ATTENTION"));
4370     msg_puts(_("\nFound a swap file by the name \""));
4371     msg_home_replace(fname);
4372     msg_puts("\"\n");
4373     sx = swapfile_info(fname);
4374     msg_puts(_("While opening file \""));
4375     msg_outtrans(buf->b_fname);
4376     msg_puts("\"\n");
4377     if (mch_stat((char *)buf->b_fname, &st) == -1)
4378     {
4379 	msg_puts(_("      CANNOT BE FOUND"));
4380     }
4381     else
4382     {
4383 	msg_puts(_("             dated: "));
4384 	x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
4385 	p = ctime(&x);			    /* includes '\n' */
4386 	if (p == NULL)
4387 	    msg_puts("(invalid)\n");
4388 	else
4389 	    msg_puts(p);
4390 	if (sx != 0 && x > sx)
4391 	    msg_puts(_("      NEWER than swap file!\n"));
4392     }
4393     /* Some of these messages are long to allow translation to
4394      * other languages. */
4395     msg_puts(_("\n(1) Another program may be editing the same file.  If this is the case,\n    be careful not to end up with two different instances of the same\n    file when making changes.  Quit, or continue with caution.\n"));
4396     msg_puts(_("(2) An edit session for this file crashed.\n"));
4397     msg_puts(_("    If this is the case, use \":recover\" or \"vim -r "));
4398     msg_outtrans(buf->b_fname);
4399     msg_puts(_("\"\n    to recover the changes (see \":help recovery\").\n"));
4400     msg_puts(_("    If you did this already, delete the swap file \""));
4401     msg_outtrans(fname);
4402     msg_puts(_("\"\n    to avoid this message.\n"));
4403     cmdline_row = msg_row;
4404     --no_wait_return;
4405 }
4406 
4407 #if defined(FEAT_EVAL)
4408 /*
4409  * Trigger the SwapExists autocommands.
4410  * Returns a value for equivalent to do_dialog() (see below):
4411  * 0: still need to ask for a choice
4412  * 1: open read-only
4413  * 2: edit anyway
4414  * 3: recover
4415  * 4: delete it
4416  * 5: quit
4417  * 6: abort
4418  */
4419     static int
4420 do_swapexists(buf_T *buf, char_u *fname)
4421 {
4422     set_vim_var_string(VV_SWAPNAME, fname, -1);
4423     set_vim_var_string(VV_SWAPCHOICE, NULL, -1);
4424 
4425     /* Trigger SwapExists autocommands with <afile> set to the file being
4426      * edited.  Disallow changing directory here. */
4427     ++allbuf_lock;
4428     apply_autocmds(EVENT_SWAPEXISTS, buf->b_fname, NULL, FALSE, NULL);
4429     --allbuf_lock;
4430 
4431     set_vim_var_string(VV_SWAPNAME, NULL, -1);
4432 
4433     switch (*get_vim_var_str(VV_SWAPCHOICE))
4434     {
4435 	case 'o': return 1;
4436 	case 'e': return 2;
4437 	case 'r': return 3;
4438 	case 'd': return 4;
4439 	case 'q': return 5;
4440 	case 'a': return 6;
4441     }
4442 
4443     return 0;
4444 }
4445 #endif
4446 
4447 /*
4448  * Find out what name to use for the swap file for buffer 'buf'.
4449  *
4450  * Several names are tried to find one that does not exist
4451  * Returns the name in allocated memory or NULL.
4452  * When out of memory "dirp" is set to NULL.
4453  *
4454  * Note: If BASENAMELEN is not correct, you will get error messages for
4455  *	 not being able to open the swap or undo file
4456  * Note: May trigger SwapExists autocmd, pointers may change!
4457  */
4458     static char_u *
4459 findswapname(
4460     buf_T	*buf,
4461     char_u	**dirp,		/* pointer to list of directories */
4462     char_u	*old_fname)	/* don't give warning for this file name */
4463 {
4464     char_u	*fname;
4465     int		n;
4466     char_u	*dir_name;
4467 #ifdef AMIGA
4468     BPTR	fh;
4469 #endif
4470     int		r;
4471     char_u	*buf_fname = buf->b_fname;
4472 
4473 #if !defined(UNIX)
4474 # define CREATE_DUMMY_FILE
4475     FILE	*dummyfd = NULL;
4476 
4477 # ifdef WIN3264
4478     if (buf_fname != NULL && !mch_isFullName(buf_fname)
4479 				       && vim_strchr(gettail(buf_fname), ':'))
4480     {
4481 	char_u *t;
4482 
4483 	buf_fname = vim_strsave(buf_fname);
4484 	if (buf_fname == NULL)
4485 	    buf_fname = buf->b_fname;
4486 	else
4487 	    for (t = gettail(buf_fname); *t != NUL; MB_PTR_ADV(t))
4488 		if (*t == ':')
4489 		    *t = '%';
4490     }
4491 # endif
4492 
4493     /*
4494      * If we start editing a new file, e.g. "test.doc", which resides on an
4495      * MSDOS compatible filesystem, it is possible that the file
4496      * "test.doc.swp" which we create will be exactly the same file. To avoid
4497      * this problem we temporarily create "test.doc".  Don't do this when the
4498      * check below for a 8.3 file name is used.
4499      */
4500     if (!(buf->b_p_sn || buf->b_shortname) && buf_fname != NULL
4501 					     && mch_getperm(buf_fname) < 0)
4502 	dummyfd = mch_fopen((char *)buf_fname, "w");
4503 #endif
4504 
4505     /*
4506      * Isolate a directory name from *dirp and put it in dir_name.
4507      * First allocate some memory to put the directory name in.
4508      */
4509     dir_name = alloc((unsigned)STRLEN(*dirp) + 1);
4510     if (dir_name == NULL)
4511 	*dirp = NULL;
4512     else
4513 	(void)copy_option_part(dirp, dir_name, 31000, ",");
4514 
4515     /*
4516      * we try different names until we find one that does not exist yet
4517      */
4518     if (dir_name == NULL)	    /* out of memory */
4519 	fname = NULL;
4520     else
4521 	fname = makeswapname(buf_fname, buf->b_ffname, buf, dir_name);
4522 
4523     for (;;)
4524     {
4525 	if (fname == NULL)	/* must be out of memory */
4526 	    break;
4527 	if ((n = (int)STRLEN(fname)) == 0)	/* safety check */
4528 	{
4529 	    VIM_CLEAR(fname);
4530 	    break;
4531 	}
4532 #if defined(UNIX)
4533 /*
4534  * Some systems have a MS-DOS compatible filesystem that use 8.3 character
4535  * file names. If this is the first try and the swap file name does not fit in
4536  * 8.3, detect if this is the case, set shortname and try again.
4537  */
4538 	if (fname[n - 2] == 'w' && fname[n - 1] == 'p'
4539 					&& !(buf->b_p_sn || buf->b_shortname))
4540 	{
4541 	    char_u	    *tail;
4542 	    char_u	    *fname2;
4543 	    stat_T	    s1, s2;
4544 	    int		    f1, f2;
4545 	    int		    created1 = FALSE, created2 = FALSE;
4546 	    int		    same = FALSE;
4547 
4548 	    /*
4549 	     * Check if swapfile name does not fit in 8.3:
4550 	     * It either contains two dots, is longer than 8 chars, or starts
4551 	     * with a dot.
4552 	     */
4553 	    tail = gettail(buf_fname);
4554 	    if (       vim_strchr(tail, '.') != NULL
4555 		    || STRLEN(tail) > (size_t)8
4556 		    || *gettail(fname) == '.')
4557 	    {
4558 		fname2 = alloc(n + 2);
4559 		if (fname2 != NULL)
4560 		{
4561 		    STRCPY(fname2, fname);
4562 		    /* if fname == "xx.xx.swp",	    fname2 = "xx.xx.swx"
4563 		     * if fname == ".xx.swp",	    fname2 = ".xx.swpx"
4564 		     * if fname == "123456789.swp", fname2 = "12345678x.swp"
4565 		     */
4566 		    if (vim_strchr(tail, '.') != NULL)
4567 			fname2[n - 1] = 'x';
4568 		    else if (*gettail(fname) == '.')
4569 		    {
4570 			fname2[n] = 'x';
4571 			fname2[n + 1] = NUL;
4572 		    }
4573 		    else
4574 			fname2[n - 5] += 1;
4575 		    /*
4576 		     * may need to create the files to be able to use mch_stat()
4577 		     */
4578 		    f1 = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
4579 		    if (f1 < 0)
4580 		    {
4581 			f1 = mch_open_rw((char *)fname,
4582 					       O_RDWR|O_CREAT|O_EXCL|O_EXTRA);
4583 			created1 = TRUE;
4584 		    }
4585 		    if (f1 >= 0)
4586 		    {
4587 			f2 = mch_open((char *)fname2, O_RDONLY | O_EXTRA, 0);
4588 			if (f2 < 0)
4589 			{
4590 			    f2 = mch_open_rw((char *)fname2,
4591 					       O_RDWR|O_CREAT|O_EXCL|O_EXTRA);
4592 			    created2 = TRUE;
4593 			}
4594 			if (f2 >= 0)
4595 			{
4596 			    /*
4597 			     * Both files exist now. If mch_stat() returns the
4598 			     * same device and inode they are the same file.
4599 			     */
4600 			    if (mch_fstat(f1, &s1) != -1
4601 				    && mch_fstat(f2, &s2) != -1
4602 				    && s1.st_dev == s2.st_dev
4603 				    && s1.st_ino == s2.st_ino)
4604 				same = TRUE;
4605 			    close(f2);
4606 			    if (created2)
4607 				mch_remove(fname2);
4608 			}
4609 			close(f1);
4610 			if (created1)
4611 			    mch_remove(fname);
4612 		    }
4613 		    vim_free(fname2);
4614 		    if (same)
4615 		    {
4616 			buf->b_shortname = TRUE;
4617 			vim_free(fname);
4618 			fname = makeswapname(buf_fname, buf->b_ffname,
4619 							       buf, dir_name);
4620 			continue;	/* try again with b_shortname set */
4621 		    }
4622 		}
4623 	    }
4624 	}
4625 #endif
4626 	/*
4627 	 * check if the swapfile already exists
4628 	 */
4629 	if (mch_getperm(fname) < 0)	/* it does not exist */
4630 	{
4631 #ifdef HAVE_LSTAT
4632 	    stat_T	sb;
4633 
4634 	    /*
4635 	     * Extra security check: When a swap file is a symbolic link, this
4636 	     * is most likely a symlink attack.
4637 	     */
4638 	    if (mch_lstat((char *)fname, &sb) < 0)
4639 #else
4640 # ifdef AMIGA
4641 	    fh = Open((UBYTE *)fname, (long)MODE_NEWFILE);
4642 	    /*
4643 	     * on the Amiga mch_getperm() will return -1 when the file exists
4644 	     * but is being used by another program. This happens if you edit
4645 	     * a file twice.
4646 	     */
4647 	    if (fh != (BPTR)NULL)	/* can open file, OK */
4648 	    {
4649 		Close(fh);
4650 		mch_remove(fname);
4651 		break;
4652 	    }
4653 	    if (IoErr() != ERROR_OBJECT_IN_USE
4654 					    && IoErr() != ERROR_OBJECT_EXISTS)
4655 # endif
4656 #endif
4657 		break;
4658 	}
4659 
4660 	/*
4661 	 * A file name equal to old_fname is OK to use.
4662 	 */
4663 	if (old_fname != NULL && fnamecmp(fname, old_fname) == 0)
4664 	    break;
4665 
4666 	/*
4667 	 * get here when file already exists
4668 	 */
4669 	if (fname[n - 2] == 'w' && fname[n - 1] == 'p')	/* first try */
4670 	{
4671 	    /*
4672 	     * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp
4673 	     * and file.doc are the same file. To guess if this problem is
4674 	     * present try if file.doc.swx exists. If it does, we set
4675 	     * buf->b_shortname and try file_doc.swp (dots replaced by
4676 	     * underscores for this file), and try again. If it doesn't we
4677 	     * assume that "file.doc.swp" already exists.
4678 	     */
4679 	    if (!(buf->b_p_sn || buf->b_shortname))	/* not tried yet */
4680 	    {
4681 		fname[n - 1] = 'x';
4682 		r = mch_getperm(fname);		/* try "file.swx" */
4683 		fname[n - 1] = 'p';
4684 		if (r >= 0)		    /* "file.swx" seems to exist */
4685 		{
4686 		    buf->b_shortname = TRUE;
4687 		    vim_free(fname);
4688 		    fname = makeswapname(buf_fname, buf->b_ffname,
4689 							       buf, dir_name);
4690 		    continue;	    /* try again with '.' replaced with '_' */
4691 		}
4692 	    }
4693 	    /*
4694 	     * If we get here the ".swp" file really exists.
4695 	     * Give an error message, unless recovering, no file name, we are
4696 	     * viewing a help file or when the path of the file is different
4697 	     * (happens when all .swp files are in one directory).
4698 	     */
4699 	    if (!recoverymode && buf_fname != NULL
4700 				&& !buf->b_help && !(buf->b_flags & BF_DUMMY))
4701 	    {
4702 		int		fd;
4703 		struct block0	b0;
4704 		int		differ = FALSE;
4705 
4706 		/*
4707 		 * Try to read block 0 from the swap file to get the original
4708 		 * file name (and inode number).
4709 		 */
4710 		fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
4711 		if (fd >= 0)
4712 		{
4713 		    if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0))
4714 		    {
4715 			/*
4716 			 * If the swapfile has the same directory as the
4717 			 * buffer don't compare the directory names, they can
4718 			 * have a different mountpoint.
4719 			 */
4720 			if (b0.b0_flags & B0_SAME_DIR)
4721 			{
4722 			    if (fnamecmp(gettail(buf->b_ffname),
4723 						   gettail(b0.b0_fname)) != 0
4724 				    || !same_directory(fname, buf->b_ffname))
4725 			    {
4726 #ifdef CHECK_INODE
4727 				/* Symlinks may point to the same file even
4728 				 * when the name differs, need to check the
4729 				 * inode too. */
4730 				expand_env(b0.b0_fname, NameBuff, MAXPATHL);
4731 				if (fnamecmp_ino(buf->b_ffname, NameBuff,
4732 						     char_to_long(b0.b0_ino)))
4733 #endif
4734 				    differ = TRUE;
4735 			    }
4736 			}
4737 			else
4738 			{
4739 			    /*
4740 			     * The name in the swap file may be
4741 			     * "~user/path/file".  Expand it first.
4742 			     */
4743 			    expand_env(b0.b0_fname, NameBuff, MAXPATHL);
4744 #ifdef CHECK_INODE
4745 			    if (fnamecmp_ino(buf->b_ffname, NameBuff,
4746 						     char_to_long(b0.b0_ino)))
4747 				differ = TRUE;
4748 #else
4749 			    if (fnamecmp(NameBuff, buf->b_ffname) != 0)
4750 				differ = TRUE;
4751 #endif
4752 			}
4753 		    }
4754 		    close(fd);
4755 		}
4756 
4757 		/* give the ATTENTION message when there is an old swap file
4758 		 * for the current file, and the buffer was not recovered. */
4759 		if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
4760 			&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
4761 		{
4762 #if defined(HAS_SWAP_EXISTS_ACTION)
4763 		    int		choice = 0;
4764 #endif
4765 #ifdef CREATE_DUMMY_FILE
4766 		    int		did_use_dummy = FALSE;
4767 
4768 		    /* Avoid getting a warning for the file being created
4769 		     * outside of Vim, it was created at the start of this
4770 		     * function.  Delete the file now, because Vim might exit
4771 		     * here if the window is closed. */
4772 		    if (dummyfd != NULL)
4773 		    {
4774 			fclose(dummyfd);
4775 			dummyfd = NULL;
4776 			mch_remove(buf_fname);
4777 			did_use_dummy = TRUE;
4778 		    }
4779 #endif
4780 
4781 #if (defined(UNIX) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG))
4782 		    process_still_running = FALSE;
4783 #endif
4784 #if defined(FEAT_EVAL)
4785 		    /*
4786 		     * If there is an SwapExists autocommand and we can handle
4787 		     * the response, trigger it.  It may return 0 to ask the
4788 		     * user anyway.
4789 		     */
4790 		    if (swap_exists_action != SEA_NONE
4791 			    && has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
4792 			choice = do_swapexists(buf, fname);
4793 
4794 		    if (choice == 0)
4795 #endif
4796 		    {
4797 #ifdef FEAT_GUI
4798 			// If we are supposed to start the GUI but it wasn't
4799 			// completely started yet, start it now.  This makes
4800 			// the messages displayed in the Vim window when
4801 			// loading a session from the .gvimrc file.
4802 			if (gui.starting && !gui.in_use)
4803 			    gui_start();
4804 #endif
4805 			// Show info about the existing swap file.
4806 			attention_message(buf, fname);
4807 
4808 			// We don't want a 'q' typed at the more-prompt
4809 			// interrupt loading a file.
4810 			got_int = FALSE;
4811 
4812 			// If vimrc has "simalt ~x" we don't want it to
4813 			// interfere with the prompt here.
4814 			flush_buffers(FLUSH_TYPEAHEAD);
4815 		    }
4816 
4817 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
4818 		    if (swap_exists_action != SEA_NONE && choice == 0)
4819 		    {
4820 			char_u	*name;
4821 
4822 			name = alloc((unsigned)(STRLEN(fname)
4823 				+ STRLEN(_("Swap file \""))
4824 				+ STRLEN(_("\" already exists!")) + 5));
4825 			if (name != NULL)
4826 			{
4827 			    STRCPY(name, _("Swap file \""));
4828 			    home_replace(NULL, fname, name + STRLEN(name),
4829 								  1000, TRUE);
4830 			    STRCAT(name, _("\" already exists!"));
4831 			}
4832 			choice = do_dialog(VIM_WARNING,
4833 				    (char_u *)_("VIM - ATTENTION"),
4834 				    name == NULL
4835 					?  (char_u *)_("Swap file already exists!")
4836 					: name,
4837 # if defined(UNIX) || defined(VMS)
4838 				    process_still_running
4839 					? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") :
4840 # endif
4841 					(char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"), 1, NULL, FALSE);
4842 
4843 # if defined(UNIX) || defined(VMS)
4844 			if (process_still_running && choice >= 4)
4845 			    choice++;	/* Skip missing "Delete it" button */
4846 # endif
4847 			vim_free(name);
4848 
4849 			/* pretend screen didn't scroll, need redraw anyway */
4850 			msg_scrolled = 0;
4851 			redraw_all_later(NOT_VALID);
4852 		    }
4853 #endif
4854 
4855 #if defined(HAS_SWAP_EXISTS_ACTION)
4856 		    if (choice > 0)
4857 		    {
4858 			switch (choice)
4859 			{
4860 			    case 1:
4861 				buf->b_p_ro = TRUE;
4862 				break;
4863 			    case 2:
4864 				break;
4865 			    case 3:
4866 				swap_exists_action = SEA_RECOVER;
4867 				break;
4868 			    case 4:
4869 				mch_remove(fname);
4870 				break;
4871 			    case 5:
4872 				swap_exists_action = SEA_QUIT;
4873 				break;
4874 			    case 6:
4875 				swap_exists_action = SEA_QUIT;
4876 				got_int = TRUE;
4877 				break;
4878 			}
4879 
4880 			/* If the file was deleted this fname can be used. */
4881 			if (mch_getperm(fname) < 0)
4882 			    break;
4883 		    }
4884 		    else
4885 #endif
4886 		    {
4887 			msg_puts("\n");
4888 			if (msg_silent == 0)
4889 			    /* call wait_return() later */
4890 			    need_wait_return = TRUE;
4891 		    }
4892 
4893 #ifdef CREATE_DUMMY_FILE
4894 		    /* Going to try another name, need the dummy file again. */
4895 		    if (did_use_dummy)
4896 			dummyfd = mch_fopen((char *)buf_fname, "w");
4897 #endif
4898 		}
4899 	    }
4900 	}
4901 
4902 	/*
4903 	 * Change the ".swp" extension to find another file that can be used.
4904 	 * First decrement the last char: ".swo", ".swn", etc.
4905 	 * If that still isn't enough decrement the last but one char: ".svz"
4906 	 * Can happen when editing many "No Name" buffers.
4907 	 */
4908 	if (fname[n - 1] == 'a')	/* ".s?a" */
4909 	{
4910 	    if (fname[n - 2] == 'a')    /* ".saa": tried enough, give up */
4911 	    {
4912 		emsg(_("E326: Too many swap files found"));
4913 		VIM_CLEAR(fname);
4914 		break;
4915 	    }
4916 	    --fname[n - 2];		/* ".svz", ".suz", etc. */
4917 	    fname[n - 1] = 'z' + 1;
4918 	}
4919 	--fname[n - 1];			/* ".swo", ".swn", etc. */
4920     }
4921 
4922     vim_free(dir_name);
4923 #ifdef CREATE_DUMMY_FILE
4924     if (dummyfd != NULL)	/* file has been created temporarily */
4925     {
4926 	fclose(dummyfd);
4927 	mch_remove(buf_fname);
4928     }
4929 #endif
4930 #ifdef WIN3264
4931     if (buf_fname != buf->b_fname)
4932 	vim_free(buf_fname);
4933 #endif
4934     return fname;
4935 }
4936 
4937     static int
4938 b0_magic_wrong(ZERO_BL *b0p)
4939 {
4940     return (b0p->b0_magic_long != (long)B0_MAGIC_LONG
4941 	    || b0p->b0_magic_int != (int)B0_MAGIC_INT
4942 	    || b0p->b0_magic_short != (short)B0_MAGIC_SHORT
4943 	    || b0p->b0_magic_char != B0_MAGIC_CHAR);
4944 }
4945 
4946 #ifdef CHECK_INODE
4947 /*
4948  * Compare current file name with file name from swap file.
4949  * Try to use inode numbers when possible.
4950  * Return non-zero when files are different.
4951  *
4952  * When comparing file names a few things have to be taken into consideration:
4953  * - When working over a network the full path of a file depends on the host.
4954  *   We check the inode number if possible.  It is not 100% reliable though,
4955  *   because the device number cannot be used over a network.
4956  * - When a file does not exist yet (editing a new file) there is no inode
4957  *   number.
4958  * - The file name in a swap file may not be valid on the current host.  The
4959  *   "~user" form is used whenever possible to avoid this.
4960  *
4961  * This is getting complicated, let's make a table:
4962  *
4963  *		ino_c  ino_s  fname_c  fname_s	differ =
4964  *
4965  * both files exist -> compare inode numbers:
4966  *		!= 0   != 0	X	 X	ino_c != ino_s
4967  *
4968  * inode number(s) unknown, file names available -> compare file names
4969  *		== 0	X	OK	 OK	fname_c != fname_s
4970  *		 X     == 0	OK	 OK	fname_c != fname_s
4971  *
4972  * current file doesn't exist, file for swap file exist, file name(s) not
4973  * available -> probably different
4974  *		== 0   != 0    FAIL	 X	TRUE
4975  *		== 0   != 0	X	FAIL	TRUE
4976  *
4977  * current file exists, inode for swap unknown, file name(s) not
4978  * available -> probably different
4979  *		!= 0   == 0    FAIL	 X	TRUE
4980  *		!= 0   == 0	X	FAIL	TRUE
4981  *
4982  * current file doesn't exist, inode for swap unknown, one file name not
4983  * available -> probably different
4984  *		== 0   == 0    FAIL	 OK	TRUE
4985  *		== 0   == 0	OK	FAIL	TRUE
4986  *
4987  * current file doesn't exist, inode for swap unknown, both file names not
4988  * available -> compare file names
4989  *		== 0   == 0    FAIL	FAIL	fname_c != fname_s
4990  *
4991  * Note that when the ino_t is 64 bits, only the last 32 will be used.  This
4992  * can't be changed without making the block 0 incompatible with 32 bit
4993  * versions.
4994  */
4995 
4996     static int
4997 fnamecmp_ino(
4998     char_u	*fname_c,	    /* current file name */
4999     char_u	*fname_s,	    /* file name from swap file */
5000     long	ino_block0)
5001 {
5002     stat_T	st;
5003     ino_t	ino_c = 0;	    /* ino of current file */
5004     ino_t	ino_s;		    /* ino of file from swap file */
5005     char_u	buf_c[MAXPATHL];    /* full path of fname_c */
5006     char_u	buf_s[MAXPATHL];    /* full path of fname_s */
5007     int		retval_c;	    /* flag: buf_c valid */
5008     int		retval_s;	    /* flag: buf_s valid */
5009 
5010     if (mch_stat((char *)fname_c, &st) == 0)
5011 	ino_c = (ino_t)st.st_ino;
5012 
5013     /*
5014      * First we try to get the inode from the file name, because the inode in
5015      * the swap file may be outdated.  If that fails (e.g. this path is not
5016      * valid on this machine), use the inode from block 0.
5017      */
5018     if (mch_stat((char *)fname_s, &st) == 0)
5019 	ino_s = (ino_t)st.st_ino;
5020     else
5021 	ino_s = (ino_t)ino_block0;
5022 
5023     if (ino_c && ino_s)
5024 	return (ino_c != ino_s);
5025 
5026     /*
5027      * One of the inode numbers is unknown, try a forced vim_FullName() and
5028      * compare the file names.
5029      */
5030     retval_c = vim_FullName(fname_c, buf_c, MAXPATHL, TRUE);
5031     retval_s = vim_FullName(fname_s, buf_s, MAXPATHL, TRUE);
5032     if (retval_c == OK && retval_s == OK)
5033 	return STRCMP(buf_c, buf_s) != 0;
5034 
5035     /*
5036      * Can't compare inodes or file names, guess that the files are different,
5037      * unless both appear not to exist at all, then compare with the file name
5038      * in the swap file.
5039      */
5040     if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL)
5041 	return STRCMP(fname_c, fname_s) != 0;
5042     return TRUE;
5043 }
5044 #endif /* CHECK_INODE */
5045 
5046 /*
5047  * Move a long integer into a four byte character array.
5048  * Used for machine independency in block zero.
5049  */
5050     static void
5051 long_to_char(long n, char_u *s)
5052 {
5053     s[0] = (char_u)(n & 0xff);
5054     n = (unsigned)n >> 8;
5055     s[1] = (char_u)(n & 0xff);
5056     n = (unsigned)n >> 8;
5057     s[2] = (char_u)(n & 0xff);
5058     n = (unsigned)n >> 8;
5059     s[3] = (char_u)(n & 0xff);
5060 }
5061 
5062     static long
5063 char_to_long(char_u *s)
5064 {
5065     long    retval;
5066 
5067     retval = s[3];
5068     retval <<= 8;
5069     retval |= s[2];
5070     retval <<= 8;
5071     retval |= s[1];
5072     retval <<= 8;
5073     retval |= s[0];
5074 
5075     return retval;
5076 }
5077 
5078 /*
5079  * Set the flags in the first block of the swap file:
5080  * - file is modified or not: buf->b_changed
5081  * - 'fileformat'
5082  * - 'fileencoding'
5083  */
5084     void
5085 ml_setflags(buf_T *buf)
5086 {
5087     bhdr_T	*hp;
5088     ZERO_BL	*b0p;
5089 
5090     if (!buf->b_ml.ml_mfp)
5091 	return;
5092     for (hp = buf->b_ml.ml_mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
5093     {
5094 	if (hp->bh_bnum == 0)
5095 	{
5096 	    b0p = (ZERO_BL *)(hp->bh_data);
5097 	    b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0;
5098 	    b0p->b0_flags = (b0p->b0_flags & ~B0_FF_MASK)
5099 						  | (get_fileformat(buf) + 1);
5100 	    add_b0_fenc(b0p, buf);
5101 	    hp->bh_flags |= BH_DIRTY;
5102 	    mf_sync(buf->b_ml.ml_mfp, MFS_ZERO);
5103 	    break;
5104 	}
5105     }
5106 }
5107 
5108 #if defined(FEAT_CRYPT) || defined(PROTO)
5109 /*
5110  * If "data" points to a data block encrypt the text in it and return a copy
5111  * in allocated memory.  Return NULL when out of memory.
5112  * Otherwise return "data".
5113  */
5114     char_u *
5115 ml_encrypt_data(
5116     memfile_T	*mfp,
5117     char_u	*data,
5118     off_T	offset,
5119     unsigned	size)
5120 {
5121     DATA_BL	*dp = (DATA_BL *)data;
5122     char_u	*head_end;
5123     char_u	*text_start;
5124     char_u	*new_data;
5125     int		text_len;
5126     cryptstate_T *state;
5127 
5128     if (dp->db_id != DATA_ID)
5129 	return data;
5130 
5131     state = ml_crypt_prepare(mfp, offset, FALSE);
5132     if (state == NULL)
5133 	return data;
5134 
5135     new_data = (char_u *)alloc(size);
5136     if (new_data == NULL)
5137 	return NULL;
5138     head_end = (char_u *)(&dp->db_index[dp->db_line_count]);
5139     text_start = (char_u *)dp + dp->db_txt_start;
5140     text_len = size - dp->db_txt_start;
5141 
5142     /* Copy the header and the text. */
5143     mch_memmove(new_data, dp, head_end - (char_u *)dp);
5144 
5145     /* Encrypt the text. */
5146     crypt_encode(state, text_start, text_len, new_data + dp->db_txt_start);
5147     crypt_free_state(state);
5148 
5149     /* Clear the gap. */
5150     if (head_end < text_start)
5151 	vim_memset(new_data + (head_end - data), 0, text_start - head_end);
5152 
5153     return new_data;
5154 }
5155 
5156 /*
5157  * Decrypt the text in "data" if it points to an encrypted data block.
5158  */
5159     void
5160 ml_decrypt_data(
5161     memfile_T	*mfp,
5162     char_u	*data,
5163     off_T	offset,
5164     unsigned	size)
5165 {
5166     DATA_BL	*dp = (DATA_BL *)data;
5167     char_u	*head_end;
5168     char_u	*text_start;
5169     int		text_len;
5170     cryptstate_T *state;
5171 
5172     if (dp->db_id == DATA_ID)
5173     {
5174 	head_end = (char_u *)(&dp->db_index[dp->db_line_count]);
5175 	text_start = (char_u *)dp + dp->db_txt_start;
5176 	text_len = dp->db_txt_end - dp->db_txt_start;
5177 
5178 	if (head_end > text_start || dp->db_txt_start > size
5179 						     || dp->db_txt_end > size)
5180 	    return;  /* data was messed up */
5181 
5182 	state = ml_crypt_prepare(mfp, offset, TRUE);
5183 	if (state != NULL)
5184 	{
5185 	    /* Decrypt the text in place. */
5186 	    crypt_decode_inplace(state, text_start, text_len);
5187 	    crypt_free_state(state);
5188 	}
5189     }
5190 }
5191 
5192 /*
5193  * Prepare for encryption/decryption, using the key, seed and offset.
5194  * Return an allocated cryptstate_T *.
5195  */
5196     static cryptstate_T *
5197 ml_crypt_prepare(memfile_T *mfp, off_T offset, int reading)
5198 {
5199     buf_T	*buf = mfp->mf_buffer;
5200     char_u	salt[50];
5201     int		method_nr;
5202     char_u	*key;
5203     char_u	*seed;
5204 
5205     if (reading && mfp->mf_old_key != NULL)
5206     {
5207 	/* Reading back blocks with the previous key/method/seed. */
5208 	method_nr = mfp->mf_old_cm;
5209 	key = mfp->mf_old_key;
5210 	seed = mfp->mf_old_seed;
5211     }
5212     else
5213     {
5214 	method_nr = crypt_get_method_nr(buf);
5215 	key = buf->b_p_key;
5216 	seed = mfp->mf_seed;
5217     }
5218     if (*key == NUL)
5219 	return NULL;
5220 
5221     if (method_nr == CRYPT_M_ZIP)
5222     {
5223 	/* For PKzip: Append the offset to the key, so that we use a different
5224 	 * key for every block. */
5225 	vim_snprintf((char *)salt, sizeof(salt), "%s%ld", key, (long)offset);
5226 	return crypt_create(method_nr, salt, NULL, 0, NULL, 0);
5227     }
5228 
5229     /* Using blowfish or better: add salt and seed. We use the byte offset
5230      * of the block for the salt. */
5231     vim_snprintf((char *)salt, sizeof(salt), "%ld", (long)offset);
5232     return crypt_create(method_nr, key, salt, (int)STRLEN(salt),
5233 							   seed, MF_SEED_LEN);
5234 }
5235 
5236 #endif
5237 
5238 
5239 #if defined(FEAT_BYTEOFF) || defined(PROTO)
5240 
5241 #define MLCS_MAXL 800	/* max no of lines in chunk */
5242 #define MLCS_MINL 400   /* should be half of MLCS_MAXL */
5243 
5244 /*
5245  * Keep information for finding byte offset of a line, updtype may be one of:
5246  * ML_CHNK_ADDLINE: Add len to parent chunk, possibly splitting it
5247  *	   Careful: ML_CHNK_ADDLINE may cause ml_find_line() to be called.
5248  * ML_CHNK_DELLINE: Subtract len from parent chunk, possibly deleting it
5249  * ML_CHNK_UPDLINE: Add len to parent chunk, as a signed entity.
5250  */
5251     static void
5252 ml_updatechunk(
5253     buf_T	*buf,
5254     linenr_T	line,
5255     long	len,
5256     int		updtype)
5257 {
5258     static buf_T	*ml_upd_lastbuf = NULL;
5259     static linenr_T	ml_upd_lastline;
5260     static linenr_T	ml_upd_lastcurline;
5261     static int		ml_upd_lastcurix;
5262 
5263     linenr_T		curline = ml_upd_lastcurline;
5264     int			curix = ml_upd_lastcurix;
5265     long		size;
5266     chunksize_T		*curchnk;
5267     int			rest;
5268     bhdr_T		*hp;
5269     DATA_BL		*dp;
5270 
5271     if (buf->b_ml.ml_usedchunks == -1 || len == 0)
5272 	return;
5273     if (buf->b_ml.ml_chunksize == NULL)
5274     {
5275 	buf->b_ml.ml_chunksize = (chunksize_T *)
5276 				  alloc((unsigned)sizeof(chunksize_T) * 100);
5277 	if (buf->b_ml.ml_chunksize == NULL)
5278 	{
5279 	    buf->b_ml.ml_usedchunks = -1;
5280 	    return;
5281 	}
5282 	buf->b_ml.ml_numchunks = 100;
5283 	buf->b_ml.ml_usedchunks = 1;
5284 	buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
5285 	buf->b_ml.ml_chunksize[0].mlcs_totalsize = 1;
5286     }
5287 
5288     if (updtype == ML_CHNK_UPDLINE && buf->b_ml.ml_line_count == 1)
5289     {
5290 	/*
5291 	 * First line in empty buffer from ml_flush_line() -- reset
5292 	 */
5293 	buf->b_ml.ml_usedchunks = 1;
5294 	buf->b_ml.ml_chunksize[0].mlcs_numlines = 1;
5295 	buf->b_ml.ml_chunksize[0].mlcs_totalsize = (long)buf->b_ml.ml_line_len;
5296 	return;
5297     }
5298 
5299     /*
5300      * Find chunk that our line belongs to, curline will be at start of the
5301      * chunk.
5302      */
5303     if (buf != ml_upd_lastbuf || line != ml_upd_lastline + 1
5304 	    || updtype != ML_CHNK_ADDLINE)
5305     {
5306 	for (curline = 1, curix = 0;
5307 	     curix < buf->b_ml.ml_usedchunks - 1
5308 	     && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines;
5309 	     curix++)
5310 	{
5311 	    curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
5312 	}
5313     }
5314     else if (curix < buf->b_ml.ml_usedchunks - 1
5315 	      && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines)
5316     {
5317 	/* Adjust cached curix & curline */
5318 	curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
5319 	curix++;
5320     }
5321     curchnk = buf->b_ml.ml_chunksize + curix;
5322 
5323     if (updtype == ML_CHNK_DELLINE)
5324 	len = -len;
5325     curchnk->mlcs_totalsize += len;
5326     if (updtype == ML_CHNK_ADDLINE)
5327     {
5328 	curchnk->mlcs_numlines++;
5329 
5330 	/* May resize here so we don't have to do it in both cases below */
5331 	if (buf->b_ml.ml_usedchunks + 1 >= buf->b_ml.ml_numchunks)
5332 	{
5333 	    chunksize_T *t_chunksize = buf->b_ml.ml_chunksize;
5334 
5335 	    buf->b_ml.ml_numchunks = buf->b_ml.ml_numchunks * 3 / 2;
5336 	    buf->b_ml.ml_chunksize = (chunksize_T *)
5337 		vim_realloc(buf->b_ml.ml_chunksize,
5338 			    sizeof(chunksize_T) * buf->b_ml.ml_numchunks);
5339 	    if (buf->b_ml.ml_chunksize == NULL)
5340 	    {
5341 		/* Hmmmm, Give up on offset for this buffer */
5342 		vim_free(t_chunksize);
5343 		buf->b_ml.ml_usedchunks = -1;
5344 		return;
5345 	    }
5346 	}
5347 
5348 	if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MAXL)
5349 	{
5350 	    int	    count;	    /* number of entries in block */
5351 	    int	    idx;
5352 	    int	    end_idx;
5353 	    int	    text_end;
5354 	    int	    linecnt;
5355 
5356 	    mch_memmove(buf->b_ml.ml_chunksize + curix + 1,
5357 			buf->b_ml.ml_chunksize + curix,
5358 			(buf->b_ml.ml_usedchunks - curix) *
5359 			sizeof(chunksize_T));
5360 	    /* Compute length of first half of lines in the split chunk */
5361 	    size = 0;
5362 	    linecnt = 0;
5363 	    while (curline < buf->b_ml.ml_line_count
5364 			&& linecnt < MLCS_MINL)
5365 	    {
5366 		if ((hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
5367 		{
5368 		    buf->b_ml.ml_usedchunks = -1;
5369 		    return;
5370 		}
5371 		dp = (DATA_BL *)(hp->bh_data);
5372 		count = (long)(buf->b_ml.ml_locked_high) -
5373 			(long)(buf->b_ml.ml_locked_low) + 1;
5374 		idx = curline - buf->b_ml.ml_locked_low;
5375 		curline = buf->b_ml.ml_locked_high + 1;
5376 
5377 		// compute index of last line to use in this MEMLINE
5378 		rest = count - idx;
5379 		if (linecnt + rest > MLCS_MINL)
5380 		{
5381 		    end_idx = idx + MLCS_MINL - linecnt - 1;
5382 		    linecnt = MLCS_MINL;
5383 		}
5384 		else
5385 		{
5386 		    end_idx = count - 1;
5387 		    linecnt += rest;
5388 		}
5389 #ifdef FEAT_TEXT_PROP
5390 		if (buf->b_has_textprop)
5391 		{
5392 		    int i;
5393 
5394 		    // We cannot use the text pointers to get the text length,
5395 		    // the text prop info would also be counted.  Go over the
5396 		    // lines.
5397 		    for (i = end_idx; i < idx; ++i)
5398 			size += (int)STRLEN((char_u *)dp + (dp->db_index[i] & DB_INDEX_MASK)) + 1;
5399 		}
5400 		else
5401 #endif
5402 		{
5403 		    if (idx == 0)/* first line in block, text at the end */
5404 			text_end = dp->db_txt_end;
5405 		    else
5406 			text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
5407 		    size += text_end - ((dp->db_index[end_idx]) & DB_INDEX_MASK);
5408 		}
5409 	    }
5410 	    buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt;
5411 	    buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt;
5412 	    buf->b_ml.ml_chunksize[curix].mlcs_totalsize = size;
5413 	    buf->b_ml.ml_chunksize[curix + 1].mlcs_totalsize -= size;
5414 	    buf->b_ml.ml_usedchunks++;
5415 	    ml_upd_lastbuf = NULL;   /* Force recalc of curix & curline */
5416 	    return;
5417 	}
5418 	else if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MINL
5419 		     && curix == buf->b_ml.ml_usedchunks - 1
5420 		     && buf->b_ml.ml_line_count - line <= 1)
5421 	{
5422 	    /*
5423 	     * We are in the last chunk and it is cheap to crate a new one
5424 	     * after this. Do it now to avoid the loop above later on
5425 	     */
5426 	    curchnk = buf->b_ml.ml_chunksize + curix + 1;
5427 	    buf->b_ml.ml_usedchunks++;
5428 	    if (line == buf->b_ml.ml_line_count)
5429 	    {
5430 		curchnk->mlcs_numlines = 0;
5431 		curchnk->mlcs_totalsize = 0;
5432 	    }
5433 	    else
5434 	    {
5435 		/*
5436 		 * Line is just prior to last, move count for last
5437 		 * This is the common case  when loading a new file
5438 		 */
5439 		hp = ml_find_line(buf, buf->b_ml.ml_line_count, ML_FIND);
5440 		if (hp == NULL)
5441 		{
5442 		    buf->b_ml.ml_usedchunks = -1;
5443 		    return;
5444 		}
5445 		dp = (DATA_BL *)(hp->bh_data);
5446 		if (dp->db_line_count == 1)
5447 		    rest = dp->db_txt_end - dp->db_txt_start;
5448 		else
5449 		    rest =
5450 			((dp->db_index[dp->db_line_count - 2]) & DB_INDEX_MASK)
5451 			- dp->db_txt_start;
5452 		curchnk->mlcs_totalsize = rest;
5453 		curchnk->mlcs_numlines = 1;
5454 		curchnk[-1].mlcs_totalsize -= rest;
5455 		curchnk[-1].mlcs_numlines -= 1;
5456 	    }
5457 	}
5458     }
5459     else if (updtype == ML_CHNK_DELLINE)
5460     {
5461 	curchnk->mlcs_numlines--;
5462 	ml_upd_lastbuf = NULL;   /* Force recalc of curix & curline */
5463 	if (curix < (buf->b_ml.ml_usedchunks - 1)
5464 		&& (curchnk->mlcs_numlines + curchnk[1].mlcs_numlines)
5465 		   <= MLCS_MINL)
5466 	{
5467 	    curix++;
5468 	    curchnk = buf->b_ml.ml_chunksize + curix;
5469 	}
5470 	else if (curix == 0 && curchnk->mlcs_numlines <= 0)
5471 	{
5472 	    buf->b_ml.ml_usedchunks--;
5473 	    mch_memmove(buf->b_ml.ml_chunksize, buf->b_ml.ml_chunksize + 1,
5474 			buf->b_ml.ml_usedchunks * sizeof(chunksize_T));
5475 	    return;
5476 	}
5477 	else if (curix == 0 || (curchnk->mlcs_numlines > 10
5478 		    && (curchnk->mlcs_numlines + curchnk[-1].mlcs_numlines)
5479 		       > MLCS_MINL))
5480 	{
5481 	    return;
5482 	}
5483 
5484 	/* Collapse chunks */
5485 	curchnk[-1].mlcs_numlines += curchnk->mlcs_numlines;
5486 	curchnk[-1].mlcs_totalsize += curchnk->mlcs_totalsize;
5487 	buf->b_ml.ml_usedchunks--;
5488 	if (curix < buf->b_ml.ml_usedchunks)
5489 	{
5490 	    mch_memmove(buf->b_ml.ml_chunksize + curix,
5491 			buf->b_ml.ml_chunksize + curix + 1,
5492 			(buf->b_ml.ml_usedchunks - curix) *
5493 			sizeof(chunksize_T));
5494 	}
5495 	return;
5496     }
5497     ml_upd_lastbuf = buf;
5498     ml_upd_lastline = line;
5499     ml_upd_lastcurline = curline;
5500     ml_upd_lastcurix = curix;
5501 }
5502 
5503 /*
5504  * Find offset for line or line with offset.
5505  * Find line with offset if "lnum" is 0; return remaining offset in offp
5506  * Find offset of line if "lnum" > 0
5507  * return -1 if information is not available
5508  */
5509     long
5510 ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp)
5511 {
5512     linenr_T	curline;
5513     int		curix;
5514     long	size;
5515     bhdr_T	*hp;
5516     DATA_BL	*dp;
5517     int		count;		/* number of entries in block */
5518     int		idx;
5519     int		start_idx;
5520     int		text_end;
5521     long	offset;
5522     int		len;
5523     int		ffdos = (get_fileformat(buf) == EOL_DOS);
5524     int		extra = 0;
5525 
5526     /* take care of cached line first */
5527     ml_flush_line(curbuf);
5528 
5529     if (buf->b_ml.ml_usedchunks == -1
5530 	    || buf->b_ml.ml_chunksize == NULL
5531 	    || lnum < 0)
5532 	return -1;
5533 
5534     if (offp == NULL)
5535 	offset = 0;
5536     else
5537 	offset = *offp;
5538     if (lnum == 0 && offset <= 0)
5539 	return 1;   /* Not a "find offset" and offset 0 _must_ be in line 1 */
5540     /*
5541      * Find the last chunk before the one containing our line. Last chunk is
5542      * special because it will never qualify
5543      */
5544     curline = 1;
5545     curix = size = 0;
5546     while (curix < buf->b_ml.ml_usedchunks - 1
5547 	    && ((lnum != 0
5548 	     && lnum >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines)
5549 		|| (offset != 0
5550 	       && offset > size + buf->b_ml.ml_chunksize[curix].mlcs_totalsize
5551 		      + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines)))
5552     {
5553 	curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
5554 	size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize;
5555 	if (offset && ffdos)
5556 	    size += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
5557 	curix++;
5558     }
5559 
5560     while ((lnum != 0 && curline < lnum) || (offset != 0 && size < offset))
5561     {
5562 	if (curline > buf->b_ml.ml_line_count
5563 		|| (hp = ml_find_line(buf, curline, ML_FIND)) == NULL)
5564 	    return -1;
5565 	dp = (DATA_BL *)(hp->bh_data);
5566 	count = (long)(buf->b_ml.ml_locked_high) -
5567 		(long)(buf->b_ml.ml_locked_low) + 1;
5568 	start_idx = idx = curline - buf->b_ml.ml_locked_low;
5569 	if (idx == 0)/* first line in block, text at the end */
5570 	    text_end = dp->db_txt_end;
5571 	else
5572 	    text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
5573 	/* Compute index of last line to use in this MEMLINE */
5574 	if (lnum != 0)
5575 	{
5576 	    if (curline + (count - idx) >= lnum)
5577 		idx += lnum - curline - 1;
5578 	    else
5579 		idx = count - 1;
5580 	}
5581 	else
5582 	{
5583 	    extra = 0;
5584 	    while (offset >= size
5585 		       + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK)
5586 								      + ffdos)
5587 	    {
5588 		if (ffdos)
5589 		    size++;
5590 		if (idx == count - 1)
5591 		{
5592 		    extra = 1;
5593 		    break;
5594 		}
5595 		idx++;
5596 	    }
5597 	}
5598 #ifdef FEAT_TEXT_PROP
5599 	if (buf->b_has_textprop)
5600 	{
5601 	    int i;
5602 
5603 	    // cannot use the db_index pointer, need to get the actual text
5604 	    // lengths.
5605 	    len = 0;
5606 	    for (i = start_idx; i <= idx; ++i)
5607 		len += (int)STRLEN((char_u *)dp + ((dp->db_index[i]) & DB_INDEX_MASK)) + 1;
5608 	}
5609 	else
5610 #endif
5611 	    len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
5612 	size += len;
5613 	if (offset != 0 && size >= offset)
5614 	{
5615 	    if (size + ffdos == offset)
5616 		*offp = 0;
5617 	    else if (idx == start_idx)
5618 		*offp = offset - size + len;
5619 	    else
5620 		*offp = offset - size + len
5621 		     - (text_end - ((dp->db_index[idx - 1]) & DB_INDEX_MASK));
5622 	    curline += idx - start_idx + extra;
5623 	    if (curline > buf->b_ml.ml_line_count)
5624 		return -1;	/* exactly one byte beyond the end */
5625 	    return curline;
5626 	}
5627 	curline = buf->b_ml.ml_locked_high + 1;
5628     }
5629 
5630     if (lnum != 0)
5631     {
5632 	/* Count extra CR characters. */
5633 	if (ffdos)
5634 	    size += lnum - 1;
5635 
5636 	/* Don't count the last line break if 'noeol' and ('bin' or
5637 	 * 'nofixeol'). */
5638 	if ((!buf->b_p_fixeol || buf->b_p_bin) && !buf->b_p_eol
5639 					   && lnum > buf->b_ml.ml_line_count)
5640 	    size -= ffdos + 1;
5641     }
5642 
5643     return size;
5644 }
5645 
5646 /*
5647  * Goto byte in buffer with offset 'cnt'.
5648  */
5649     void
5650 goto_byte(long cnt)
5651 {
5652     long	boff = cnt;
5653     linenr_T	lnum;
5654 
5655     ml_flush_line(curbuf);	/* cached line may be dirty */
5656     setpcmark();
5657     if (boff)
5658 	--boff;
5659     lnum = ml_find_line_or_offset(curbuf, (linenr_T)0, &boff);
5660     if (lnum < 1)	/* past the end */
5661     {
5662 	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
5663 	curwin->w_curswant = MAXCOL;
5664 	coladvance((colnr_T)MAXCOL);
5665     }
5666     else
5667     {
5668 	curwin->w_cursor.lnum = lnum;
5669 	curwin->w_cursor.col = (colnr_T)boff;
5670 	curwin->w_cursor.coladd = 0;
5671 	curwin->w_set_curswant = TRUE;
5672     }
5673     check_cursor();
5674 
5675     /* Make sure the cursor is on the first byte of a multi-byte char. */
5676     if (has_mbyte)
5677 	mb_adjust_cursor();
5678 }
5679 #endif
5680