memline.c
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:98k
源码类别:

编辑器/阅读器

开发平台:

DOS

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8. /* for debugging */
  9. /* #define CHECK(c, s) if (c) EMSG(s) */
  10. #define CHECK(c, s)
  11. /*
  12.  * memline.c: Contains the functions for appending, deleting and changing the
  13.  * text lines. The memfile functions are used to store the information in blocks
  14.  * of memory, backed up by a file. The structure of the information is a tree.
  15.  * The root of the tree is a pointer block. The leaves of the tree are data
  16.  * blocks. In between may be several layers of pointer blocks, forming branches.
  17.  *
  18.  * Three types of blocks are used:
  19.  * - Block nr 0 contains information for recovery
  20.  * - Pointer blocks contain list of pointers to other blocks.
  21.  * - Data blocks contain the actual text.
  22.  *
  23.  * Block nr 0 contains the block0 structure (see below).
  24.  *
  25.  * Block nr 1 is the first pointer block. It is the root of the tree.
  26.  * Other pointer blocks are branches.
  27.  *
  28.  *  If a line is too big to fit in a single page, the block containing that
  29.  *  line is made big enough to hold the line. It may span several pages.
  30.  *  Otherwise all blocks are one page.
  31.  *
  32.  *  A data block that was filled when starting to edit a file and was not
  33.  *  changed since then, can have a negative block number. This means that it
  34.  *  has not yet been assigned a place in the file. When recovering, the lines
  35.  *  in this data block can be read from the original file. When the block is
  36.  *  changed (lines appended/deleted/changed) or when it is flushed it gets a
  37.  *  positive number. Use mf_trans_del() to get the new number, before calling
  38.  *  mf_get().
  39.  */
  40. #if defined MSDOS  ||  defined WIN32
  41. # include <io.h>
  42. #endif
  43. #include "vim.h"
  44. #ifdef HAVE_FCNTL_H
  45. # include <fcntl.h>
  46. #endif
  47. #ifndef UNIX /* it's in os_unix.h for Unix */
  48. # include <time.h>
  49. #endif
  50. #ifdef SASC
  51. # include <proto/dos.h>     /* for Open() and Close() */
  52. #endif
  53. typedef struct block0 ZERO_BL;    /* contents of the first block */
  54. typedef struct pointer_block PTR_BL;     /* contents of a pointer block */
  55. typedef struct data_block DATA_BL;    /* contents of a data block */
  56. typedef struct pointer_entry PTR_EN;     /* block/line-count pair */
  57. #define DATA_ID     (('d' << 8) + 'a')     /* data block id */
  58. #define PTR_ID     (('p' << 8) + 't')     /* pointer block id */
  59. #define BLOCK0_ID0  'b'     /* block 0 id 0 */
  60. #define BLOCK0_ID1  '0'     /* block 0 id 1 */
  61. /*
  62.  * pointer to a block, used in a pointer block
  63.  */
  64. struct pointer_entry
  65. {
  66.     blocknr_t pe_bnum; /* block number */
  67.     linenr_t pe_line_count; /* number of lines in this branch */
  68.     linenr_t pe_old_lnum; /* lnum for this block (for recovery) */
  69.     int pe_page_count; /* number of pages in block pe_bnum */
  70. };
  71. /*
  72.  * A pointer block contains a list of branches in the tree.
  73.  */
  74. struct pointer_block
  75. {
  76.     short_u pb_id; /* ID for pointer block: PTR_ID */
  77.     short_u pb_count; /* number of pointer in this block */
  78.     short_u pb_count_max; /* maximum value for pb_count */
  79.     PTR_EN pb_pointer[1]; /* list of pointers to blocks (actually longer)
  80.  * followed by empty space until end of page */
  81. };
  82. /*
  83.  * A data block is a leaf in the tree.
  84.  *
  85.  * The text of the lines is at the end of the block. The text of the first line
  86.  * in the block is put at the end, the text of the second line in front of it,
  87.  * etc. Thus the order of the lines is the opposite of the line number.
  88.  */
  89. struct data_block
  90. {
  91.     short_u db_id; /* ID for data block: DATA_ID */
  92.     unsigned db_free; /* free space available */
  93.     unsigned db_txt_start; /* byte where text starts */
  94.     unsigned db_txt_end; /* byte just after data block */
  95.     linenr_t db_line_count; /* number of lines in this block */
  96.     unsigned db_index[1]; /* index for start of line (actually bigger)
  97.  * followed by empty space upto db_txt_start
  98.  * followed by the text in the lines until
  99.  * end of page */
  100. };
  101. /*
  102.  * The low bits of db_index hold the actual index. The topmost bit is
  103.  * used for the global command to be able to mark a line.
  104.  * This method is not clean, but otherwise there would be at least one extra
  105.  * byte used for each line.
  106.  * The mark has to be in this place to keep it with the correct line when other
  107.  * lines are inserted or deleted.
  108.  */
  109. #define DB_MARKED ((unsigned)1 << ((sizeof(unsigned) * 8) - 1))
  110. #define DB_INDEX_MASK (~DB_MARKED)
  111. #define INDEX_SIZE  (sizeof(unsigned))     /* size of one db_index entry */
  112. #define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE)  /* size of data block header */
  113. #define B0_FNAME_SIZE 900
  114. #define B0_UNAME_SIZE 40
  115. #define B0_HNAME_SIZE 40
  116. /*
  117.  * Restrict the numbers to 32 bits, otherwise most compilers will complain.
  118.  * This won't detect a 64 bit machine that only swaps a byte in the top 32
  119.  * bits, but that is crazy anyway.
  120.  */
  121. #define B0_MAGIC_LONG 0x30313233
  122. #define B0_MAGIC_INT 0x20212223
  123. #define B0_MAGIC_SHORT 0x10111213
  124. #define B0_MAGIC_CHAR 0x55
  125. /*
  126.  * Block zero holds all info about the swap file.
  127.  *
  128.  * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE, it makes all existing swap
  129.  * files unusable!
  130.  *
  131.  * If size of block0 changes anyway, adjust minimal block size
  132.  * in mf_open()!!
  133.  *
  134.  * This block is built up of single bytes, to make it portable accros
  135.  * different machines. b0_magic_* is used to check the byte order and size of
  136.  * variables, because the rest of the swap is not portable.
  137.  */
  138. struct block0
  139. {
  140.     char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1 */
  141.     char_u b0_version[10]; /* Vim version string */
  142.     char_u b0_page_size[4];/* number of bytes per page */
  143.     char_u b0_mtime[4]; /* last modification time of file */
  144.     char_u b0_ino[4]; /* inode of b0_fname */
  145.     char_u b0_pid[4]; /* process id of creator (or 0) */
  146.     char_u b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */
  147.     char_u b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */
  148.     char_u b0_fname[B0_FNAME_SIZE]; /* name of file being edited */
  149.     long b0_magic_long; /* check for byte order of long */
  150.     int b0_magic_int; /* check for byte order of int */
  151.     short b0_magic_short; /* check for byte order of short */
  152.     char_u b0_magic_char; /* check for last char */
  153. };
  154. #define STACK_INCR 5 /* nr of entries added to ml_stack at a time */
  155. /*
  156.  * The line number where the first mark may be is remembered.
  157.  * If it is 0 there are no marks at all.
  158.  * (always used for the current buffer only, no buffer change possible while
  159.  * executing a global command).
  160.  */
  161. static linenr_t lowest_marked = 0;
  162. /*
  163.  * arguments for ml_find_line()
  164.  */
  165. #define ML_DELETE 0x11     /* delete line */
  166. #define ML_INSERT 0x12     /* insert line */
  167. #define ML_FIND 0x13     /* just find the line */
  168. #define ML_FLUSH 0x02     /* flush locked block */
  169. #define ML_SIMPLE(x) (x & 0x10)  /* DEL, INS or FIND */
  170. static void set_b0_fname __ARGS((ZERO_BL *, BUF *buf));
  171. static void swapfile_info __ARGS((char_u *));
  172. static int recov_file_names __ARGS((char_u **, char_u *, int prepend_dot));
  173. static int ml_append_int __ARGS((BUF *, linenr_t, char_u *, colnr_t, int, int));
  174. static int ml_delete_int __ARGS((BUF *, linenr_t, int));
  175. static char_u *findswapname __ARGS((BUF *, char_u **, char_u *));
  176. static void ml_flush_line __ARGS((BUF *));
  177. static BHDR *ml_new_data __ARGS((MEMFILE *, int, int));
  178. static BHDR *ml_new_ptr __ARGS((MEMFILE *));
  179. static BHDR *ml_find_line __ARGS((BUF *, linenr_t, int));
  180. static int ml_add_stack __ARGS((BUF *));
  181. static char_u *makeswapname __ARGS((BUF *, char_u *));
  182. static void ml_lineadd __ARGS((BUF *, int));
  183. static int b0_magic_wrong __ARGS((ZERO_BL *));
  184. #ifdef CHECK_INODE
  185. static int fnamecmp_ino __ARGS((char_u *, char_u *, long));
  186. #endif
  187. static void long_to_char __ARGS((long, char_u *));
  188. static long char_to_long __ARGS((char_u *));
  189. /*
  190.  * open a new memline for 'curbuf'
  191.  *
  192.  * return FAIL for failure, OK otherwise
  193.  */
  194.     int
  195. ml_open()
  196. {
  197.     MEMFILE *mfp;
  198.     BHDR *hp = NULL;
  199.     ZERO_BL *b0p;
  200.     PTR_BL *pp;
  201.     DATA_BL *dp;
  202. /*
  203.  * init fields in memline struct
  204.  */
  205.     curbuf->b_ml.ml_stack_size = 0; /* no stack yet */
  206.     curbuf->b_ml.ml_stack = NULL; /* no stack yet */
  207.     curbuf->b_ml.ml_stack_top = 0; /* nothing in the stack */
  208.     curbuf->b_ml.ml_locked = NULL; /* no cached block */
  209.     curbuf->b_ml.ml_line_lnum = 0; /* no cached line */
  210. /*
  211.  * When 'updatecount' is non-zero, flag that a swap file may be opened later.
  212.  */
  213.     if (p_uc && curbuf->b_p_swf)
  214. curbuf->b_may_swap = TRUE;
  215.     else
  216. curbuf->b_may_swap = FALSE;
  217. /*
  218.  * Open the memfile.  No swap file is created yet.
  219.  */
  220.     mfp = mf_open(NULL, TRUE);
  221.     if (mfp == NULL)
  222. goto error;
  223. #if defined(MSDOS) && !defined(DJGPP)
  224.     /* for 16 bit MS-DOS create a swapfile now, because we run out of
  225.      * memory very quickly */
  226.     if (p_uc)
  227. ml_open_file(curbuf);
  228. #endif
  229.     curbuf->b_ml.ml_mfp = mfp;
  230.     curbuf->b_ml.ml_flags = ML_EMPTY;
  231.     curbuf->b_ml.ml_line_count = 1;
  232. /*
  233.  * fill block0 struct and write page 0
  234.  */
  235.     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
  236. goto error;
  237.     if (hp->bh_bnum != 0)
  238.     {
  239. EMSG("didn't get block nr 0?");
  240. goto error;
  241.     }
  242.     b0p = (ZERO_BL *)(hp->bh_data);
  243.     b0p->b0_id[0] = BLOCK0_ID0;
  244.     b0p->b0_id[1] = BLOCK0_ID1;
  245.     b0p->b0_magic_long = (long)B0_MAGIC_LONG;
  246.     b0p->b0_magic_int = (int)B0_MAGIC_INT;
  247.     b0p->b0_magic_short = (short)B0_MAGIC_SHORT;
  248.     b0p->b0_magic_char = B0_MAGIC_CHAR;
  249.     STRNCPY(b0p->b0_version, "VIM ", 4);
  250.     STRNCPY(b0p->b0_version + 4, Version, 6);
  251.     set_b0_fname(b0p, curbuf);
  252.     long_to_char((long)mfp->mf_page_size, b0p->b0_page_size);
  253.     (void)mch_get_user_name(b0p->b0_uname, B0_UNAME_SIZE);
  254.     b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL;
  255.     mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE);
  256.     b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
  257.     long_to_char(mch_get_pid(), b0p->b0_pid);
  258.     /*
  259.      * Always sync block number 0 to disk, so we can check the file name in
  260.      * the swap file in findswapname(). Don't do this for help files though.
  261.      * Only works when there's a swapfile, otherwise it's done when the file
  262.      * is created.
  263.      */
  264.     mf_put(mfp, hp, TRUE, FALSE);
  265.     if (!curbuf->b_help)
  266. (void)mf_sync(mfp, 0);
  267. /*
  268.  * fill in root pointer block and write page 1
  269.  */
  270.     if ((hp = ml_new_ptr(mfp)) == NULL)
  271. goto error;
  272.     if (hp->bh_bnum != 1)
  273.     {
  274. EMSG("didn't get block nr 1?");
  275. goto error;
  276.     }
  277.     pp = (PTR_BL *)(hp->bh_data);
  278.     pp->pb_count = 1;
  279.     pp->pb_pointer[0].pe_bnum = 2;
  280.     pp->pb_pointer[0].pe_page_count = 1;
  281.     pp->pb_pointer[0].pe_old_lnum = 1;
  282.     pp->pb_pointer[0].pe_line_count = 1;    /* line count after insertion */
  283.     mf_put(mfp, hp, TRUE, FALSE);
  284. /*
  285.  * allocate first data block and create an empty line 1.
  286.  */
  287.     if ((hp = ml_new_data(mfp, FALSE, 1)) == NULL)
  288. goto error;
  289.     if (hp->bh_bnum != 2)
  290.     {
  291. EMSG("didn't get block nr 2?");
  292. goto error;
  293.     }
  294.     dp = (DATA_BL *)(hp->bh_data);
  295.     dp->db_index[0] = --dp->db_txt_start; /* at end of block */
  296.     dp->db_free -= 1 + INDEX_SIZE;
  297.     dp->db_line_count = 1;
  298.     *((char_u *)dp + dp->db_txt_start) = NUL; /* emtpy line */
  299.     return OK;
  300. error:
  301.     if (mfp != NULL)
  302.     {
  303. if (hp)
  304.     mf_put(mfp, hp, FALSE, FALSE);
  305. mf_close(mfp, TRUE);     /* will also free(mfp->mf_fname) */
  306.     }
  307.     curbuf->b_ml.ml_mfp = NULL;
  308.     return FAIL;
  309. }
  310. /*
  311.  * ml_setname() is called when the file name has been changed.
  312.  * It may rename the swap file.
  313.  */
  314.     void
  315. ml_setname()
  316. {
  317.     int success = FALSE;
  318.     MEMFILE *mfp;
  319.     char_u *fname;
  320.     char_u *dirp;
  321. #if defined(MSDOS) || defined(WIN32)
  322.     char_u *p;
  323. #endif
  324.     mfp = curbuf->b_ml.ml_mfp;
  325.     if (mfp->mf_fd < 0)     /* there is no swap file yet */
  326.     {
  327. /*
  328.  * When 'updatecount' is 0 and 'noswapfile' there is no swap file.
  329.  * For help files we will make a swap file now.
  330.  */
  331. if (p_uc)
  332.     ml_open_file(curbuf); /* create a swap file */
  333. return;
  334.     }
  335. /*
  336.  * Try all directories in the 'directory' option.
  337.  */
  338.     dirp = p_dir;
  339.     for (;;)
  340.     {
  341. if (*dirp == NUL)     /* tried all directories, fail */
  342.     break;
  343. fname = findswapname(curbuf, &dirp, mfp->mf_fname); /* alloc's fname */
  344. if (fname == NULL)     /* no file name found for this dir */
  345.     continue;
  346. #if defined(MSDOS) || defined(WIN32)
  347. /*
  348.  * Set full pathname for swap file now, because a ":!cd dir" may
  349.  * change directory without us knowing it.
  350.  */
  351. p = FullName_save(fname, FALSE);
  352. vim_free(fname);
  353. fname = p;
  354. if (fname == NULL)
  355.     continue;
  356. #endif
  357.     /* if the file name is the same we don't have to do anything */
  358. if (fnamecmp(fname, mfp->mf_fname) == 0)
  359. {
  360.     vim_free(fname);
  361.     success = TRUE;
  362.     break;
  363. }
  364.     /* need to close the swap file before renaming */
  365. if (mfp->mf_fd >= 0)
  366. {
  367.     close(mfp->mf_fd);
  368.     mfp->mf_fd = -1;
  369. }
  370.     /* try to rename the swap file */
  371. if (vim_rename(mfp->mf_fname, fname) == 0)
  372. {
  373.     success = TRUE;
  374.     vim_free(mfp->mf_fname);
  375.     mfp->mf_fname = fname;
  376.     vim_free(mfp->mf_ffname);
  377. #if defined(MSDOS) || defined(WIN32)
  378.     mfp->mf_ffname = NULL;  /* mf_fname is full pathname already */
  379. #else
  380.     mf_set_ffname(mfp);
  381. #endif
  382.     break;
  383. }
  384. vim_free(fname);     /* this fname didn't work, try another */
  385.     }
  386.     if (mfp->mf_fd == -1)     /* need to (re)open the swap file */
  387.     {
  388. mfp->mf_fd = open((char *)mfp->mf_fname, O_RDWR | O_EXTRA
  389. #ifndef macintosh
  390. , 0
  391. #endif
  392. );
  393. if (mfp->mf_fd < 0)
  394. {
  395.     /* could not (re)open the swap file, what can we do???? */
  396.     EMSG("Oops, lost the swap file!!!");
  397.     return;
  398. }
  399.     }
  400.     if (!success)
  401. EMSG("Could not rename swap file");
  402. }
  403. /*
  404.  * Open a file for the memfile for all buffers that are not readonly or have
  405.  * been modified.
  406.  * Used when 'updatecount' changes from zero to non-zero.
  407.  */
  408.     void
  409. ml_open_files()
  410. {
  411.     BUF *buf;
  412.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  413. if (!buf->b_p_ro || buf->b_changed)
  414.     ml_open_file(buf);
  415. }
  416. /*
  417.  * Open a swap file for an existing memfile, if there is no swap file yet.
  418.  * If we are unable to find a file name, mf_fname will be NULL
  419.  * and the memfile will be in memory only (no recovery possible).
  420.  */
  421.     void
  422. ml_open_file(buf)
  423.     BUF *buf;
  424. {
  425.     MEMFILE *mfp;
  426.     char_u *fname;
  427.     char_u *dirp;
  428.     mfp = buf->b_ml.ml_mfp;
  429.     if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf) /* nothing to do */
  430. return;
  431.     /*
  432.      * Try all directories in 'directory' option.
  433.      */
  434.     dirp = p_dir;
  435.     for (;;)
  436.     {
  437. if (*dirp == NUL)
  438.     break;
  439. fname = findswapname(buf, &dirp, NULL); /* allocates fname */
  440. if (fname == NULL)
  441.     continue;
  442. if (mf_open_file(mfp, fname) == OK) /* consumes fname! */
  443.     break;
  444.     }
  445.     if (mfp->mf_fname == NULL) /* Failed! */
  446.     {
  447. need_wait_return = TRUE; /* call wait_return later */
  448. ++no_wait_return;
  449. (void)EMSG2("Unable to open swap file for "%s", recovery impossible",
  450.    buf->b_fname == NULL ? (char_u *)"No File" : buf->b_fname);
  451. --no_wait_return;
  452.     }
  453.     else
  454.     {
  455. #if defined(MSDOS) || defined(WIN32) || defined(RISCOS)
  456.     /*
  457.      * set full pathname for swap file now, because a ":!cd dir" may
  458.      * change directory without us knowing it.
  459.      */
  460. mf_fullname(mfp);
  461. #endif
  462. /* Flush block zero, so others can read it */
  463. (void)mf_sync(mfp, MFS_ZERO);
  464.     }
  465.     /* don't try to open a swap file again */
  466.     buf->b_may_swap = FALSE;
  467. }
  468. /*
  469.  * If still need to create a swap file, and starting to edit a not-readonly
  470.  * file, or reading into an existing buffer, create a swap file now.
  471.  */
  472.     void
  473. check_need_swap(newfile)
  474.     int     newfile; /* reading file into new buffer */
  475. {
  476.     if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile))
  477. ml_open_file(curbuf);
  478. }
  479. /*
  480.  * Close memline for buffer 'buf'.
  481.  * If 'del_file' is TRUE, delete the swap file
  482.  */
  483.     void
  484. ml_close(buf, del_file)
  485.     BUF     *buf;
  486.     int     del_file;
  487. {
  488.     if (buf->b_ml.ml_mfp == NULL) /* not open */
  489. return;
  490.     mf_close(buf->b_ml.ml_mfp, del_file); /* close the .swp file */
  491.     if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
  492. vim_free(buf->b_ml.ml_line_ptr);
  493.     vim_free(buf->b_ml.ml_stack);
  494.     buf->b_ml.ml_mfp = NULL;
  495. }
  496. /*
  497.  * Close all existing memlines and memfiles.
  498.  * Used when exiting.
  499.  * When 'del_file' is TRUE, delete the memfiles.
  500.  */
  501.     void
  502. ml_close_all(del_file)
  503.     int     del_file;
  504. {
  505.     BUF     *buf;
  506.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  507. ml_close(buf, del_file);
  508. }
  509. /*
  510.  * Close all memfiles for not modified buffers.
  511.  * Only use just before exiting!
  512.  */
  513.     void
  514. ml_close_notmod()
  515. {
  516.     BUF     *buf;
  517.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  518. if (!buf_changed(buf))
  519.     ml_close(buf, TRUE);    /* close all not-modified buffers */
  520. }
  521. /*
  522.  * Update the timestamp in the .swp file.
  523.  * Used when the file has been written.
  524.  */
  525.     void
  526. ml_timestamp(buf)
  527.     BUF *buf;
  528. {
  529.     MEMFILE *mfp;
  530.     BHDR *hp;
  531.     ZERO_BL *b0p;
  532.     mfp = buf->b_ml.ml_mfp;
  533.     if (mfp == NULL || (hp = mf_get(mfp, (blocknr_t)0, 1)) == NULL)
  534. return;
  535.     b0p = (ZERO_BL *)(hp->bh_data);
  536.     if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
  537. EMSG("ml_timestamp: Didn't get block 0??");
  538.     else
  539. set_b0_fname(b0p, buf);
  540.     mf_put(mfp, hp, TRUE, FALSE);
  541. }
  542. /*
  543.  * Write file name and timestamp into block 0 of a swap file.
  544.  * Also set buf->b_mtime.
  545.  * Don't use NameBuff[]!!!
  546.  */
  547.     static void
  548. set_b0_fname(b0p, buf)
  549.     ZERO_BL *b0p;
  550.     BUF *buf;
  551. {
  552.     struct stat st;
  553.     size_t flen, ulen;
  554.     char_u uname[B0_UNAME_SIZE];
  555.     if (buf->b_ffname == NULL)
  556. b0p->b0_fname[0] = NUL;
  557.     else
  558.     {
  559. /*
  560.  * For a file under the home directory of the current user, we try to
  561.  * replace the home directory path with "~user". This helps when
  562.  * editing the same file on different machines over a network.
  563.  * First replace home dir path with "~/" with home_replace().
  564.  * Then insert the user name to get "~user/".
  565.  */
  566. home_replace(NULL, buf->b_ffname, b0p->b0_fname, B0_FNAME_SIZE, TRUE);
  567. if (b0p->b0_fname[0] == '~')
  568. {
  569.     flen = STRLEN(b0p->b0_fname);
  570.     /* If there is no user name or it is too long, don't use "~/" */
  571.     if (mch_get_user_name(uname, B0_UNAME_SIZE) == FAIL ||
  572.  (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE - 1)
  573. STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE);
  574.     else
  575.     {
  576. mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen);
  577. mch_memmove(b0p->b0_fname + 1, uname, ulen);
  578.     }
  579. }
  580. if (stat((char *)buf->b_ffname, &st) >= 0)
  581. {
  582.     long_to_char((long)st.st_mtime, b0p->b0_mtime);
  583. #ifdef CHECK_INODE
  584.     long_to_char((long)st.st_ino, b0p->b0_ino);
  585. #endif
  586.     buf->b_mtime = st.st_mtime;
  587.     buf->b_mtime_read = st.st_mtime;
  588. }
  589. else
  590. {
  591.     long_to_char(0L, b0p->b0_mtime);
  592. #ifdef CHECK_INODE
  593.     long_to_char(0L, b0p->b0_ino);
  594. #endif
  595.     buf->b_mtime = 0;
  596.     buf->b_mtime_read = 0;
  597. }
  598.     }
  599. }
  600. /*
  601.  * try to recover curbuf from the .swp file
  602.  */
  603.     void
  604. ml_recover()
  605. {
  606.     BUF *buf = NULL;
  607.     MEMFILE *mfp = NULL;
  608.     char_u *fname;
  609.     BHDR *hp = NULL;
  610.     ZERO_BL *b0p;
  611.     PTR_BL *pp;
  612.     DATA_BL *dp;
  613.     IPTR *ip;
  614.     blocknr_t bnum;
  615.     int page_count;
  616.     struct stat org_stat, swp_stat;
  617.     int len;
  618.     int directly;
  619.     linenr_t lnum;
  620.     char_u *p;
  621.     int i;
  622.     long error;
  623.     int cannot_open;
  624.     linenr_t line_count;
  625.     int has_error;
  626.     int idx;
  627.     int top;
  628.     int txt_start;
  629.     off_t size;
  630.     int called_from_main;
  631.     int serious_error = TRUE;
  632.     long mtime;
  633.     int attr;
  634.     called_from_main = (curbuf->b_ml.ml_mfp == NULL);
  635.     attr = hl_attr(HLF_E);
  636. /*
  637.  * If the file name ends in ".sw?" we use it directly.
  638.  * Otherwise a search is done to find the swap file(s).
  639.  */
  640.     fname = curbuf->b_fname;
  641.     if (fname == NULL)     /* When there is no file name */
  642. fname = (char_u *)"";
  643.     len = STRLEN(fname);
  644.     if (len >= 4 &&
  645. #if defined(VMS) || defined(RISCOS)
  646.     STRNICMP(fname + len - 4, "_sw" , 3)
  647. #else
  648.     STRNICMP(fname + len - 4, ".sw" , 3)
  649. #endif
  650. == 0)
  651.     {
  652. directly = TRUE;
  653. fname = vim_strsave(fname); /* make a copy for mf_open */
  654.     }
  655.     else
  656.     {
  657. directly = FALSE;
  658. /* count the number of matching swap files */
  659. len = recover_names(&fname, FALSE, 0);
  660. if (len == 0)     /* no swap files found */
  661. {
  662.     EMSG2("No swap file found for %s", fname);
  663.     goto theend;
  664. }
  665. if (len == 1)     /* one swap file found, use it */
  666.     i = 1;
  667. else     /* several swap files found, choose */
  668. {
  669.     /* list the names of the swap files */
  670.     (void)recover_names(&fname, TRUE, 0);
  671.     msg_putchar('n');
  672.     MSG_PUTS("Enter number of swap file to use (0 to quit): ");
  673.     i = get_number(FALSE);
  674.     if (i < 1 || i > len)
  675. goto theend;
  676. }
  677. /* get the swap file name that will be used */
  678. (void)recover_names(&fname, FALSE, i);
  679.     }
  680.     if (fname == NULL)
  681. goto theend; /* out of memory */
  682.     /* When called from main() still need to initialize storage structure */
  683.     if (called_from_main && ml_open() == FAIL)
  684. getout(1);
  685. /*
  686.  * allocate a buffer structure (only the memline in it is really used)
  687.  */
  688.     buf = (BUF *)alloc((unsigned)sizeof(BUF));
  689.     if (buf == NULL)
  690.     {
  691. vim_free(fname);
  692. goto theend;
  693.     }
  694. /*
  695.  * init fields in memline struct
  696.  */
  697.     buf->b_ml.ml_stack_size = 0; /* no stack yet */
  698.     buf->b_ml.ml_stack = NULL; /* no stack yet */
  699.     buf->b_ml.ml_stack_top = 0; /* nothing in the stack */
  700.     buf->b_ml.ml_line_lnum = 0; /* no cached line */
  701.     buf->b_ml.ml_locked = NULL; /* no locked block */
  702.     buf->b_ml.ml_flags = 0;
  703. /*
  704.  * open the memfile from the old swap file
  705.  */
  706.     p = vim_strsave(fname); /* save fname for the message */
  707.     mfp = mf_open(fname, FALSE); /* consumes fname! */
  708.     if (mfp == NULL || mfp->mf_fd < 0)
  709.     {
  710. if (p != NULL)
  711. {
  712.     EMSG2("Cannot open %s", p);
  713.     vim_free(p);
  714. }
  715. goto theend;
  716.     }
  717.     vim_free(p);
  718.     buf->b_ml.ml_mfp = mfp;
  719. /*
  720.  * try to read block 0
  721.  */
  722.     if ((hp = mf_get(mfp, (blocknr_t)0, 1)) == NULL)
  723.     {
  724. msg_start();
  725. MSG_PUTS_ATTR("Unable to read block 0 from ", attr);
  726. msg_outtrans_attr(mfp->mf_fname, attr);
  727. MSG_PUTS_ATTR(
  728. "nMaybe no changes were made or Vim did not update the swap file",
  729. attr);
  730. msg_end();
  731. goto theend;
  732.     }
  733.     b0p = (ZERO_BL *)(hp->bh_data);
  734.     if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0)
  735.     {
  736. msg_start();
  737. MSG_PUTS("The file ");
  738. msg_outtrans(mfp->mf_fname);
  739. MSG_PUTS(" cannot be used with this version of Vim.n");
  740. MSG_PUTS("Use Vim version 3.0.n");
  741. msg_end();
  742. goto theend;
  743.     }
  744.     if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1)
  745.     {
  746. EMSG2("%s is not a swap file", mfp->mf_fname);
  747. goto theend;
  748.     }
  749.     if (b0_magic_wrong(b0p))
  750.     {
  751. msg_start();
  752. MSG_PUTS_ATTR("The file ", attr);
  753. msg_outtrans_attr(mfp->mf_fname, attr);
  754. #if defined(MSDOS) || defined(WIN32)
  755. if (STRNCMP(b0p->b0_hname, "PC ", 3) == 0)
  756.     MSG_PUTS_ATTR(" cannot be used with this version of Vim.n", attr);
  757. else
  758. #endif
  759.     MSG_PUTS_ATTR(" cannot be used on this computer.n", attr);
  760. MSG_PUTS_ATTR("The file was created on ", attr);
  761. /* avoid going past the end of currupted hostname */
  762. b0p->b0_fname[0] = NUL;
  763. MSG_PUTS_ATTR(b0p->b0_hname, attr);
  764. MSG_PUTS_ATTR(",nor the file has been damaged.", attr);
  765. msg_end();
  766. goto theend;
  767.     }
  768.     /*
  769.      * If we guessed the wrong page size, we have to recalculate the
  770.      * highest block number in the file.
  771.      */
  772.     if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size))
  773.     {
  774. mfp->mf_page_size = (unsigned)char_to_long(b0p->b0_page_size);
  775. if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0)
  776.     mfp->mf_blocknr_max = 0;     /* no file or empty file */
  777. else
  778.     mfp->mf_blocknr_max = size / mfp->mf_page_size;
  779. mfp->mf_infile_count = mfp->mf_blocknr_max;
  780.     }
  781. /*
  782.  * If .swp file name given directly, use name from swap file for buffer.
  783.  */
  784.     if (directly)
  785.     {
  786. expand_env(b0p->b0_fname, NameBuff, MAXPATHL);
  787. if (setfname(NameBuff, NULL, TRUE) == FAIL)
  788.     goto theend;
  789.     }
  790.     home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, TRUE);
  791.     smsg((char_u *)"Using swap file "%s"", NameBuff);
  792.     if (curbuf->b_ffname == NULL)
  793. STRCPY(NameBuff, "No File");
  794.     else
  795. home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, TRUE);
  796.     smsg((char_u *)"Original file "%s"", NameBuff);
  797.     msg_putchar('n');
  798. /*
  799.  * check date of swap file and original file
  800.  */
  801.     mtime = char_to_long(b0p->b0_mtime);
  802.     if (curbuf->b_ffname != NULL &&
  803.     stat((char *)curbuf->b_ffname, &org_stat) != -1 &&
  804.     ((stat((char *)mfp->mf_fname, &swp_stat) != -1 &&
  805.     org_stat.st_mtime > swp_stat.st_mtime) ||
  806.     org_stat.st_mtime != mtime))
  807.     {
  808. EMSG("Warning: Original file may have been changed");
  809.     }
  810.     out_flush();
  811.     mf_put(mfp, hp, FALSE, FALSE); /* release block 0 */
  812.     hp = NULL;
  813.     /*
  814.      * Now that we are sure that the file is going to be recovered, clear the
  815.      * contents of the current buffer.
  816.      */
  817.     while (!(curbuf->b_ml.ml_flags & ML_EMPTY))
  818. ml_delete((linenr_t)1, FALSE);
  819.     bnum = 1; /* start with block 1 */
  820.     page_count = 1; /* which is 1 page */
  821.     lnum = 0; /* append after line 0 in curbuf */
  822.     line_count = 0;
  823.     idx = 0; /* start with first index in block 1 */
  824.     error = 0;
  825.     buf->b_ml.ml_stack_top = 0;
  826.     buf->b_ml.ml_stack = NULL;
  827.     buf->b_ml.ml_stack_size = 0; /* no stack yet */
  828.     if (curbuf->b_ffname == NULL)
  829. cannot_open = TRUE;
  830.     else
  831. cannot_open = FALSE;
  832.     serious_error = FALSE;
  833.     for ( ; !got_int; line_breakcheck())
  834.     {
  835. if (hp != NULL)
  836.     mf_put(mfp, hp, FALSE, FALSE); /* release previous block */
  837. /*
  838.  * get block
  839.  */
  840. if ((hp = mf_get(mfp, (blocknr_t)bnum, page_count)) == NULL)
  841. {
  842.     if (bnum == 1)
  843.     {
  844. EMSG2("Unable to read block 1 from %s", mfp->mf_fname);
  845. goto theend;
  846.     }
  847.     ++error;
  848.     ml_append(lnum++, (char_u *)"???MANY LINES MISSING",
  849.     (colnr_t)0, TRUE);
  850. }
  851. else /* there is a block */
  852. {
  853.     pp = (PTR_BL *)(hp->bh_data);
  854.     if (pp->pb_id == PTR_ID) /* it is a pointer block */
  855.     {
  856. /* check line count when using pointer block first time */
  857. if (idx == 0 && line_count != 0)
  858. {
  859.     for (i = 0; i < (int)pp->pb_count; ++i)
  860. line_count -= pp->pb_pointer[i].pe_line_count;
  861.     if (line_count != 0)
  862.     {
  863. ++error;
  864. ml_append(lnum++, (char_u *)"???LINE COUNT WRONG",
  865.     (colnr_t)0, TRUE);
  866.     }
  867. }
  868. if (pp->pb_count == 0)
  869. {
  870.     ml_append(lnum++, (char_u *)"???EMPTY BLOCK",
  871.     (colnr_t)0, TRUE);
  872.     ++error;
  873. }
  874. else if (idx < (int)pp->pb_count) /* go a block deeper */
  875. {
  876.     if (pp->pb_pointer[idx].pe_bnum < 0)
  877.     {
  878. /*
  879.  * Data block with negative block number.
  880.  * Try to read lines from the original file.
  881.  * This is slow, but it works.
  882.  */
  883. if (!cannot_open)
  884. {
  885.     line_count = pp->pb_pointer[idx].pe_line_count;
  886.     if (readfile(curbuf->b_ffname, NULL, lnum,
  887. pp->pb_pointer[idx].pe_old_lnum - 1,
  888. line_count, 0) == FAIL)
  889. cannot_open = TRUE;
  890.     else
  891. lnum += line_count;
  892. }
  893. if (cannot_open)
  894. {
  895.     ++error;
  896.     ml_append(lnum++, (char_u *)"???LINES MISSING",
  897.     (colnr_t)0, TRUE);
  898. }
  899. ++idx;     /* get same block again for next index */
  900. continue;
  901.     }
  902.     /*
  903.      * going one block deeper in the tree
  904.      */
  905.     if ((top = ml_add_stack(buf)) < 0) /* new entry in stack */
  906.     {
  907. ++error;
  908. break;     /* out of memory */
  909.     }
  910.     ip = &(buf->b_ml.ml_stack[top]);
  911.     ip->ip_bnum = bnum;
  912.     ip->ip_index = idx;
  913.     bnum = pp->pb_pointer[idx].pe_bnum;
  914.     line_count = pp->pb_pointer[idx].pe_line_count;
  915.     page_count = pp->pb_pointer[idx].pe_page_count;
  916.     continue;
  917. }
  918.     }
  919.     else     /* not a pointer block */
  920.     {
  921. dp = (DATA_BL *)(hp->bh_data);
  922. if (dp->db_id != DATA_ID) /* block id wrong */
  923. {
  924.     if (bnum == 1)
  925.     {
  926. EMSG2("Block 1 ID wrong (%s not a .swp file?)",
  927.        mfp->mf_fname);
  928. goto theend;
  929.     }
  930.     ++error;
  931.     ml_append(lnum++, (char_u *)"???BLOCK MISSING",
  932.     (colnr_t)0, TRUE);
  933. }
  934. else
  935. {
  936.     /*
  937.      * it is a data block
  938.      * Append all the lines in this block
  939.      */
  940.     has_error = FALSE;
  941. /*
  942.  * check length of block
  943.  * if wrong, use length in pointer block
  944.  */
  945.     if (page_count * mfp->mf_page_size != dp->db_txt_end)
  946.     {
  947. ml_append(lnum++, (char_u *)"??? from here until ???END lines may be messed up",
  948.     (colnr_t)0, TRUE);
  949. ++error;
  950. has_error = TRUE;
  951. dp->db_txt_end = page_count * mfp->mf_page_size;
  952.     }
  953. /* make sure there is a NUL at the end of the block */
  954.     *((char_u *)dp + dp->db_txt_end - 1) = NUL;
  955. /*
  956.  * check number of lines in block
  957.  * if wrong, use count in data block
  958.  */
  959.     if (line_count != dp->db_line_count)
  960.     {
  961. ml_append(lnum++, (char_u *)"??? from here until ???END lines may have been inserted/deleted",
  962.     (colnr_t)0, TRUE);
  963. ++error;
  964. has_error = TRUE;
  965.     }
  966.     for (i = 0; i < dp->db_line_count; ++i)
  967.     {
  968. txt_start = (dp->db_index[i] & DB_INDEX_MASK);
  969. if (txt_start <= HEADER_SIZE ||
  970.      txt_start >= (int)dp->db_txt_end)
  971. {
  972.     p = (char_u *)"???";
  973.     ++error;
  974. }
  975. else
  976.     p = (char_u *)dp + txt_start;
  977. ml_append(lnum++, p, (colnr_t)0, TRUE);
  978.     }
  979.     if (has_error)
  980. ml_append(lnum++, (char_u *)"???END", (colnr_t)0, TRUE);
  981. }
  982.     }
  983. }
  984. if (buf->b_ml.ml_stack_top == 0) /* finished */
  985.     break;
  986. /*
  987.  * go one block up in the tree
  988.  */
  989. ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
  990. bnum = ip->ip_bnum;
  991. idx = ip->ip_index + 1;     /* go to next index */
  992. page_count = 1;
  993.     }
  994.     /*
  995.      * The dummy line from the empty buffer will now be after the last line in
  996.      * the buffer. Delete it.
  997.      */
  998.     ml_delete(curbuf->b_ml.ml_line_count, FALSE);
  999.     curbuf->b_flags |= BF_RECOVERED;
  1000.     recoverymode = FALSE;
  1001.     if (got_int)
  1002. EMSG("Recovery Interrupted");
  1003.     else if (error)
  1004. EMSG("Errors detected while recovering; look for lines starting with ???");
  1005.     else
  1006.     {
  1007. MSG("Recovery completed. You should check if everything is OK.");
  1008. MSG_PUTS("n(You might want to write out this file under another namen");
  1009. MSG_PUTS("and run diff with the original file to check for changes)n");
  1010. MSG_PUTS("Delete the .swp file afterwards.nn");
  1011. cmdline_row = msg_row;
  1012.     }
  1013. theend:
  1014.     if (mfp != NULL)
  1015.     {
  1016. if (hp != NULL)
  1017.     mf_put(mfp, hp, FALSE, FALSE);
  1018. mf_close(mfp, FALSE);     /* will also vim_free(mfp->mf_fname) */
  1019.     }
  1020.     vim_free(buf);
  1021.     if (serious_error && called_from_main)
  1022. ml_close(curbuf, TRUE);
  1023. #ifdef AUTOCMD
  1024.     else
  1025. apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf);
  1026. #endif
  1027.     return;
  1028. }
  1029. /*
  1030.  * Find the names of swap files in current directory and the directory given
  1031.  * with the 'directory' option.
  1032.  *
  1033.  * Used to:
  1034.  * - list the swap files for "vim -r"
  1035.  * - count the number of swap files when recovering
  1036.  * - list the swap files when recovering
  1037.  * - find the name of the n'th swap file when recovering
  1038.  */
  1039.     int
  1040. recover_names(fname, list, nr)
  1041.     char_u **fname;    /* base for swap file name */
  1042.     int list;     /* when TRUE, list the swap file names */
  1043.     int nr;     /* when non-zero, return nr'th swap file name */
  1044. {
  1045.     int num_names;
  1046.     char_u *(names[6]);
  1047.     char_u *tail;
  1048.     char_u *p;
  1049.     int num_files;
  1050.     int file_count = 0;
  1051.     char_u **files;
  1052.     int i;
  1053.     char_u *dirp;
  1054.     char_u *dir_name;
  1055.     if (list)
  1056.     {
  1057.     /* use msg() to start the scrolling properly */
  1058. msg((char_u *)"Swap files found:");
  1059. msg_putchar('n');
  1060.     }
  1061.     expand_interactively = TRUE;
  1062.     /*
  1063.      * Do the loop for every directory in 'directory'.
  1064.      * First allocate some memory to put the directory name in.
  1065.      */
  1066.     dir_name = alloc((unsigned)STRLEN(p_dir) + 1);
  1067.     dirp = p_dir;
  1068.     while (dir_name != NULL && *dirp)
  1069.     {
  1070. /*
  1071.  * Isolate a directory name from *dirp and put it in dir_name (we know
  1072.  * it is large enough, so use 31000 for length).
  1073.  * Advance dirp to next directory name.
  1074.  */
  1075. (void)copy_option_part(&dirp, dir_name, 31000, ",");
  1076. if (dir_name[0] == '.' && dir_name[1] == NUL) /* check current dir */
  1077. {
  1078.     if (fname == NULL || *fname == NULL)
  1079.     {
  1080. #ifdef RISCOS
  1081. names[0] = vim_strsave((char_u *)"*_sw#");
  1082. #else
  1083. names[0] = vim_strsave((char_u *)"*.sw?");
  1084. #endif
  1085. #ifdef UNIX
  1086.     /* for Unix names starting with a dot are special */
  1087. names[1] = vim_strsave((char_u *)".*.sw?");
  1088. names[2] = vim_strsave((char_u *)".sw?");
  1089. num_names = 3;
  1090. #else
  1091. # ifdef VMS
  1092. names[1] = vim_strsave((char_u *)".*_sw%");
  1093. num_names = 2;
  1094. # else
  1095. num_names = 1;
  1096. # endif
  1097. #endif
  1098.     }
  1099.     else
  1100. num_names = recov_file_names(names, *fname, TRUE);
  1101. }
  1102. else     /* check directory dir_name */
  1103. {
  1104.     if (fname == NULL || *fname == NULL)
  1105.     {
  1106. #ifdef RISCOS
  1107. names[0] = concat_fnames(dir_name, (char_u *)"*_sw#", TRUE);
  1108. #else
  1109. names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE);
  1110. #endif
  1111. #ifdef UNIX
  1112.     /* for Unix names starting with a dot are special */
  1113. names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE);
  1114. names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE);
  1115. num_names = 3;
  1116. #else
  1117. #ifdef VMS
  1118. names[1] = concat_fnames(dir_name, (char_u *)".*_sw?", TRUE);
  1119. num_names = 2;
  1120. #else
  1121. num_names = 1;
  1122. #endif
  1123. #endif
  1124.     }
  1125.     else
  1126.     {
  1127. tail = gettail(*fname);
  1128. tail = concat_fnames(dir_name, tail, TRUE);
  1129. if (tail == NULL)
  1130.     num_names = 0;
  1131. else
  1132. {
  1133.     num_names = recov_file_names(names, tail, FALSE);
  1134.     vim_free(tail);
  1135. }
  1136.     }
  1137. }
  1138.     /* check for out-of-memory */
  1139. for (i = 0; i < num_names; ++i)
  1140. {
  1141.     if (names[i] == NULL)
  1142.     {
  1143. for (i = 0; i < num_names; ++i)
  1144.     vim_free(names[i]);
  1145. num_names = 0;
  1146.     }
  1147. }
  1148. if (num_names == 0)
  1149.     num_files = 0;
  1150. else if (expand_wildcards(num_names, names, &num_files, &files,
  1151.      EW_FILE) == FAIL)
  1152.     num_files = 0;
  1153. /*
  1154.  * When no swap file found, wildcard expansion might have failed (e.g.
  1155.  * not able to execute the shell).
  1156.  * Try finding a swap file by simply adding ".swp" to the file name.
  1157.  */
  1158. if (*dirp == NUL && file_count + num_files == 0
  1159.    && fname != NULL && *fname != NULL)
  1160. {
  1161.     struct stat     st;
  1162.     char_u     *swapname;
  1163. #if defined(VMS) || defined(RISCOS)
  1164.     swapname = modname(*fname, (char_u *)"_swp", TRUE);
  1165. #else
  1166.     swapname = modname(*fname, (char_u *)".swp", TRUE);
  1167. #endif
  1168.     if (swapname != NULL)
  1169.     {
  1170. if (stat((char *)swapname, &st) != -1)     /* It exists! */
  1171. {
  1172.     files = (char_u **)alloc((unsigned)sizeof(char_u *));
  1173.     if (files != NULL)
  1174.     {
  1175. files[0] = swapname;
  1176. swapname = NULL;
  1177. num_files = 1;
  1178.     }
  1179. }
  1180. vim_free(swapname);
  1181.     }
  1182. }
  1183. /*
  1184.  * remove swapfile name of the current buffer, it must be ignored
  1185.  */
  1186. if (curbuf->b_ml.ml_mfp != NULL &&
  1187. (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
  1188. {
  1189.     for (i = 0; i < num_files; ++i)
  1190. if (fullpathcmp(p, files[i], TRUE) & FPC_SAME)
  1191. {
  1192.     vim_free(files[i]);
  1193.     --num_files;
  1194.     for ( ; i < num_files; ++i)
  1195. files[i] = files[i + 1];
  1196. }
  1197. }
  1198. if (nr)
  1199. {
  1200.     file_count += num_files;
  1201.     if (nr <= file_count)
  1202.     {
  1203. *fname = vim_strsave(files[nr - 1 + num_files - file_count]);
  1204. dirp = (char_u *)"";     /* stop searching */
  1205.     }
  1206. }
  1207. else if (list)
  1208. {
  1209.     if (dir_name[0] == '.' && dir_name[1] == NUL)
  1210.     {
  1211. if (fname == NULL || *fname == NULL)
  1212.     MSG_PUTS("   In current directory:n");
  1213. else
  1214.     MSG_PUTS("   Using specified name:n");
  1215.     }
  1216.     else
  1217.     {
  1218. MSG_PUTS("   In directory ");
  1219. msg_home_replace(dir_name);
  1220. MSG_PUTS(":n");
  1221.     }
  1222.     if (num_files)
  1223.     {
  1224. for (i = 0; i < num_files; ++i)
  1225. {
  1226.     /* print the swap file name */
  1227.     msg_outnum((long)++file_count);
  1228.     MSG_PUTS(".    ");
  1229.     msg_puts(gettail(files[i]));
  1230.     msg_putchar('n');
  1231.     swapfile_info(files[i]);
  1232. }
  1233.     }
  1234.     else
  1235. MSG_PUTS("      -- none --n");
  1236.     out_flush();
  1237. }
  1238. else
  1239.     file_count += num_files;
  1240. for (i = 0; i < num_names; ++i)
  1241.     vim_free(names[i]);
  1242. FreeWild(num_files, files);
  1243.     }
  1244.     vim_free(dir_name);
  1245.     expand_interactively = FALSE;
  1246.     return file_count;
  1247. }
  1248. /*
  1249.  * Give information about an existing swap file
  1250.  */
  1251.     static void
  1252. swapfile_info(fname)
  1253.     char_u *fname;
  1254. {
  1255.     struct stat     st;
  1256.     int     fd;
  1257.     struct block0   b0;
  1258.     time_t     x;
  1259.     /* print the swap file date */
  1260.     if (stat((char *)fname, &st) != -1)
  1261.     {
  1262. MSG_PUTS("             dated: ");
  1263. x = st.st_mtime;     /* Manx C can't do &st.st_mtime */
  1264. MSG_PUTS(ctime(&x));     /* includes 'n' */
  1265. #ifdef UNIX
  1266. /* print name of owner of the file */
  1267. {
  1268.     char_u uname[B0_UNAME_SIZE];
  1269.     if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK)
  1270.     {
  1271. MSG_PUTS("          owned by: ");
  1272. msg_outtrans(uname);
  1273. msg_putchar('n');
  1274.     }
  1275. }
  1276. #endif
  1277.     }
  1278.     /*
  1279.      * print the original file name
  1280.      */
  1281.     fd = open((char *)fname, O_RDONLY | O_EXTRA
  1282. #ifndef macintosh
  1283. , 0
  1284. #endif
  1285.      );
  1286.     if (fd >= 0)
  1287.     {
  1288. if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
  1289. {
  1290.     if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0)
  1291.     {
  1292. MSG_PUTS("         [from Vim version 3.0]");
  1293.     }
  1294.     else if (b0.b0_id[0] != BLOCK0_ID0 ||
  1295. b0.b0_id[1] != BLOCK0_ID1)
  1296.     {
  1297. MSG_PUTS("         [is not a swap file]");
  1298.     }
  1299.     else
  1300.     {
  1301. MSG_PUTS("         file name: ");
  1302. msg_outtrans(b0.b0_fname);
  1303. if (*(b0.b0_hname) != NUL)
  1304. {
  1305.     MSG_PUTS("n         host name: ");
  1306.     msg_outtrans(b0.b0_hname);
  1307. }
  1308. if (*(b0.b0_uname) != NUL)
  1309. {
  1310.     MSG_PUTS("n         user name: ");
  1311.     msg_outtrans(b0.b0_uname);
  1312. }
  1313. if (char_to_long(b0.b0_pid) != 0L)
  1314. {
  1315.     MSG_PUTS("n        process ID: ");
  1316.     msg_outnum(char_to_long(b0.b0_pid));
  1317. #if defined(UNIX) || defined(__EMX__)
  1318.     /* EMX kill() not working correctly, it seems */
  1319.     if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
  1320. MSG_PUTS(" (still running)");
  1321. #endif
  1322. }
  1323. if (b0_magic_wrong(&b0))
  1324. {
  1325. #if defined(MSDOS) || defined(WIN32)
  1326.     if (STRNCMP(b0.b0_hname, "PC ", 3) == 0)
  1327. MSG_PUTS("n         [not usable with this version of Vim]");
  1328.     else
  1329. #endif
  1330. MSG_PUTS("n         [not usable on this computer]");
  1331. }
  1332.     }
  1333. }
  1334. else
  1335.     MSG_PUTS("         [cannot be read]");
  1336. close(fd);
  1337.     }
  1338.     else
  1339. MSG_PUTS("         [cannot be opened]");
  1340.     msg_putchar('n');
  1341. }
  1342.     static int
  1343. recov_file_names(names, path, prepend_dot)
  1344.     char_u **names;
  1345.     char_u *path;
  1346.     int prepend_dot;
  1347. {
  1348.     int num_names;
  1349. #ifdef SHORT_FNAME
  1350.     /*
  1351.      * (MS-DOS) always short names
  1352.      */
  1353.     names[0] = modname(path, (char_u *)".sw?", FALSE);
  1354.     num_names = 1;
  1355. #else /* !SHORT_FNAME */
  1356.     /*
  1357.      * (WIN32) never short names, but do prepend a dot.
  1358.      * (Not MS-DOS or WIN32) maybe short name, maybe not: Try both.
  1359.      * Only use the short name if it is different.
  1360.      */
  1361.     char_u *p;
  1362.     int i;
  1363. # ifndef WIN32
  1364.     int     shortname = curbuf->b_shortname;
  1365.     curbuf->b_shortname = FALSE;
  1366. # endif
  1367.     num_names = 0;
  1368.     /*
  1369.      * May also add the file name with a dot prepended, for swap file in same
  1370.      * dir as original file.
  1371.      */
  1372.     if (prepend_dot)
  1373.     {
  1374. names[num_names] = modname(path, (char_u *)".sw?", TRUE);
  1375. if (names[num_names] == NULL)
  1376.     goto end;
  1377. ++num_names;
  1378.     }
  1379.     /*
  1380.      * Form the normal swap file name pattern by appending ".sw?".
  1381.      */
  1382. #ifdef VMS
  1383.     names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE);
  1384. #else
  1385. # ifdef RISCOS
  1386.     names[num_names] = concat_fnames(path, (char_u *)"_sw#", FALSE);
  1387. # else
  1388.     names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE);
  1389. # endif
  1390. #endif
  1391.     if (names[num_names] == NULL)
  1392. goto end;
  1393.     if (num_names >= 1)     /* check if we have the same name twice */
  1394.     {
  1395. p = names[num_names - 1];
  1396. i = STRLEN(names[num_names - 1]) - STRLEN(names[num_names]);
  1397. if (i > 0)
  1398.     p += i;     /* file name has been expanded to full path */
  1399. if (STRCMP(p, names[num_names]) != 0)
  1400.     ++num_names;
  1401. else
  1402.     vim_free(names[num_names]);
  1403.     }
  1404.     else
  1405. ++num_names;
  1406. # ifndef WIN32
  1407.     /*
  1408.      * Also try with 'shortname' set, in case the file is on a DOS filesystem.
  1409.      */
  1410.     curbuf->b_shortname = TRUE;
  1411. #ifdef RISCOS
  1412.     names[num_names] = modname(path, (char_u *)"_sw#", FALSE);
  1413. #else
  1414.     names[num_names] = modname(path, (char_u *)".sw?", FALSE);
  1415. #endif
  1416.     if (names[num_names] == NULL)
  1417. goto end;
  1418.     /*
  1419.      * Remove the one from 'shortname', if it's the same as with 'noshortname'.
  1420.      */
  1421.     p = names[num_names];
  1422.     i = STRLEN(names[num_names]) - STRLEN(names[num_names - 1]);
  1423.     if (i > 0)
  1424. p += i; /* file name has been expanded to full path */
  1425.     if (STRCMP(names[num_names - 1], p) == 0)
  1426. vim_free(names[num_names]);
  1427.     else
  1428. ++num_names;
  1429. # endif
  1430. end:
  1431. # ifndef WIN32
  1432.     curbuf->b_shortname = shortname;
  1433. # endif
  1434. #endif /* !SHORT_FNAME */
  1435.     return num_names;
  1436. }
  1437. /*
  1438.  * sync all memlines
  1439.  *
  1440.  * If 'check_file' is TRUE, check if original file exists and was not changed.
  1441.  * If 'check_char' is TRUE, stop syncing when character becomes available, but
  1442.  * always sync at least one block.
  1443.  */
  1444.     void
  1445. ml_sync_all(check_file, check_char)
  1446.     int     check_file;
  1447.     int     check_char;
  1448. {
  1449.     BUF     *buf;
  1450.     struct stat     st;
  1451.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  1452.     {
  1453. if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
  1454.     continue;     /* no file */
  1455. ml_flush_line(buf);     /* flush buffered line */
  1456.     /* flush locked block */
  1457. (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);
  1458. if (buf_changed(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
  1459.      && buf->b_ffname != NULL)
  1460. {
  1461.     /*
  1462.      * if original file does not exist anymore or has been changed
  1463.      * call ml_preserve to get rid of all negative numbered blocks
  1464.      */
  1465.     if (stat((char *)buf->b_ffname, &st) == -1 ||
  1466. st.st_mtime != buf->b_mtime_read)
  1467.     {
  1468. ml_preserve(buf, FALSE);
  1469. need_check_timestamps = TRUE; /* give message later */
  1470.     }
  1471. }
  1472. if (buf->b_ml.ml_mfp->mf_dirty)
  1473. {
  1474.     (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
  1475. | (buf_changed(buf) ? MFS_FLUSH : 0));
  1476.     if (check_char && ui_char_avail()) /* character available now */
  1477. break;
  1478. }
  1479.     }
  1480. }
  1481. /*
  1482.  * sync one buffer, including negative blocks
  1483.  *
  1484.  * after this all the blocks are in the swap file
  1485.  *
  1486.  * Used for the :preserve command and when the original file has been
  1487.  * changed or deleted.
  1488.  *
  1489.  * when message is TRUE the success of preserving is reported
  1490.  */
  1491.     void
  1492. ml_preserve(buf, message)
  1493.     BUF     *buf;
  1494.     int     message;
  1495. {
  1496.     BHDR *hp;
  1497.     linenr_t lnum;
  1498.     MEMFILE *mfp = buf->b_ml.ml_mfp;
  1499.     int status;
  1500.     if (mfp == NULL || mfp->mf_fname == NULL)
  1501.     {
  1502. if (message)
  1503.     EMSG("Cannot preserve, there is no swap file");
  1504. return;
  1505.     }
  1506.     ml_flush_line(buf);     /* flush buffered line */
  1507.     (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH); /* flush locked block */
  1508.     status = mf_sync(mfp, MFS_ALL | MFS_FLUSH);
  1509.     /* stack is invalid after mf_sync(.., MFS_ALL) */
  1510.     buf->b_ml.ml_stack_top = 0;
  1511.     /*
  1512.      * Some of the data blocks may have been changed from negative to
  1513.      * positive block number. In that case the pointer blocks need to be
  1514.      * updated.
  1515.      *
  1516.      * We don't know in which pointer block the references are, so we visit
  1517.      * all data blocks until there are no more translations to be done (or
  1518.      * we hit the end of the file, which can only happen in case a write fails,
  1519.      * e.g. when file system if full).
  1520.      * ml_find_line() does the work by translating the negative block numbers
  1521.      * when getting the first line of each data block.
  1522.      */
  1523.     if (mf_need_trans(mfp))
  1524.     {
  1525. lnum = 1;
  1526. while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count)
  1527. {
  1528.     hp = ml_find_line(buf, lnum, ML_FIND);
  1529.     if (hp == NULL)
  1530.     {
  1531. status = FAIL;
  1532. goto theend;
  1533.     }
  1534.     CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
  1535.     lnum = buf->b_ml.ml_locked_high + 1;
  1536. }
  1537. (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH); /* flush locked block */
  1538. /* sync the updated pointer blocks */
  1539. if (mf_sync(mfp, MFS_ALL | MFS_FLUSH) == FAIL)
  1540.     status = FAIL;
  1541. buf->b_ml.ml_stack_top = 0;     /* stack is invalid now */
  1542.     }
  1543. theend:
  1544.     if (message)
  1545.     {
  1546. if (status == OK)
  1547.     MSG("File preserved");
  1548. else
  1549.     EMSG("Preserve failed");
  1550.     }
  1551. }
  1552. /*
  1553.  * get a pointer to a (read-only copy of a) line
  1554.  *
  1555.  * On failure an error message is given and IObuff is returned (to avoid
  1556.  * having to check for error everywhere).
  1557.  */
  1558.     char_u  *
  1559. ml_get(lnum)
  1560.     linenr_t lnum;
  1561. {
  1562.     return ml_get_buf(curbuf, lnum, FALSE);
  1563. }
  1564. /*
  1565.  * ml_get_pos: get pointer to position 'pos'
  1566.  */
  1567.     char_u *
  1568. ml_get_pos(pos)
  1569.     FPOS    *pos;
  1570. {
  1571.     return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
  1572. }
  1573. /*
  1574.  * ml_get_curline: get pointer to cursor line.
  1575.  */
  1576.     char_u *
  1577. ml_get_curline()
  1578. {
  1579.     return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE);
  1580. }
  1581. /*
  1582.  * ml_get_cursor: get pointer to cursor position
  1583.  */
  1584.     char_u *
  1585. ml_get_cursor()
  1586. {
  1587.     return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
  1588. curwin->w_cursor.col);
  1589. }
  1590. /*
  1591.  * get a pointer to a line in a specific buffer
  1592.  *
  1593.  * "will_change": if TRUE mark the buffer dirty (chars in the line will be
  1594.  * changed)
  1595.  * NOTE: For syntax highlighting, need to call syn_changed() when
  1596.  * update_screenline() is not used.
  1597.  */
  1598.     char_u  *
  1599. ml_get_buf(buf, lnum, will_change)
  1600.     BUF *buf;
  1601.     linenr_t lnum;
  1602.     int will_change; /* line will be changed */
  1603. {
  1604.     BHDR    *hp;
  1605.     DATA_BL *dp;
  1606.     char_u  *ptr;
  1607.     if (lnum > buf->b_ml.ml_line_count) /* invalid line number */
  1608.     {
  1609. EMSGN("ml_get: invalid lnum: %ld", lnum);
  1610. errorret:
  1611. STRCPY(IObuff, "???");
  1612. return IObuff;
  1613.     }
  1614.     if (lnum <= 0) /* pretend line 0 is line 1 */
  1615. lnum = 1;
  1616.     if (buf->b_ml.ml_mfp == NULL) /* there are no lines */
  1617. return (char_u *)"";
  1618. /*
  1619.  * See if it is the same line as requested last time.
  1620.  * Otherwise may need to flush last used line.
  1621.  */
  1622.     if (buf->b_ml.ml_line_lnum != lnum)
  1623.     {
  1624. ml_flush_line(buf);
  1625. /*
  1626.  * Find the data block containing the line.
  1627.  * This also fills the stack with the blocks from the root to the data
  1628.  * block and releases any locked block.
  1629.  */
  1630. if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
  1631. {
  1632.     EMSGN("ml_get: cannot find line %ld", lnum);
  1633.     goto errorret;
  1634. }
  1635. dp = (DATA_BL *)(hp->bh_data);
  1636. ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
  1637. buf->b_ml.ml_line_ptr = ptr;
  1638. buf->b_ml.ml_line_lnum = lnum;
  1639. buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
  1640.     }
  1641.     if (will_change)
  1642. buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  1643.     return buf->b_ml.ml_line_ptr;
  1644. }
  1645. /*
  1646.  * Check if a line that was just obtained by a call to ml_get
  1647.  * is in allocated memory.
  1648.  */
  1649.     int
  1650. ml_line_alloced()
  1651. {
  1652.     return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
  1653. }
  1654. /*
  1655.  * append a line after lnum (may be 0 to insert a line in front of the file)
  1656.  *
  1657.  *   newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
  1658.  * will be set for recovery
  1659.  *
  1660.  * return FAIL for failure, OK otherwise
  1661.  */
  1662.     int
  1663. ml_append(lnum, line, len, newfile)
  1664.     linenr_t lnum; /* append after this line (can be 0) */
  1665.     char_u *line; /* text of the new line */
  1666.     colnr_t len; /* length of new line, including NUL, or 0 */
  1667.     int newfile; /* flag, see above */
  1668. {
  1669. #ifdef SYNTAX_HL
  1670.     if (curbuf->b_syn_change_lnum > lnum + 1)
  1671. curbuf->b_syn_change_lnum = lnum + 1;
  1672. #endif
  1673.     if (curbuf->b_ml.ml_line_lnum != 0)
  1674. ml_flush_line(curbuf);
  1675.     return ml_append_int(curbuf, lnum, line, len, newfile, FALSE);
  1676. }
  1677.     static int
  1678. ml_append_int(buf, lnum, line, len, newfile, mark)
  1679.     BUF *buf;
  1680.     linenr_t lnum; /* append after this line (can be 0) */
  1681.     char_u *line; /* text of the new line */
  1682.     colnr_t len; /* length of line, including NUL, or 0 */
  1683.     int newfile; /* flag, see above */
  1684.     int mark; /* mark the new line */
  1685. {
  1686.     int i;
  1687.     int line_count; /* number of indexes in current block */
  1688.     int offset;
  1689.     int from, to;
  1690.     int space_needed; /* space needed for new line */
  1691.     int page_size;
  1692.     int page_count;
  1693.     int db_idx; /* index for lnum in data block */
  1694.     BHDR *hp;
  1695.     MEMFILE *mfp;
  1696.     DATA_BL *dp;
  1697.     PTR_BL *pp;
  1698.     IPTR *ip;
  1699. /* lnum out of range */
  1700.     if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
  1701. return FAIL;
  1702.     if (lowest_marked && lowest_marked > lnum)
  1703. lowest_marked = lnum + 1;
  1704.     if (len == 0)
  1705. len = STRLEN(line) + 1; /* space needed for the text */
  1706.     space_needed = len + INDEX_SIZE; /* space needed for text + index */
  1707.     mfp = buf->b_ml.ml_mfp;
  1708.     page_size = mfp->mf_page_size;
  1709. /*
  1710.  * find the data block containing the previous line
  1711.  * This also fills the stack with the blocks from the root to the data block
  1712.  * This also releases any locked block.
  1713.  */
  1714.     if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_t)1 : lnum,
  1715.   ML_INSERT)) == NULL)
  1716. return FAIL;
  1717.     buf->b_ml.ml_flags &= ~ML_EMPTY;
  1718.     if (lnum == 0) /* got line one instead, correct db_idx */
  1719. db_idx = -1; /* careful, it is negative! */
  1720.     else
  1721. db_idx = lnum - buf->b_ml.ml_locked_low;
  1722. /* get line count before the insertion */
  1723.     line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
  1724.     dp = (DATA_BL *)(hp->bh_data);
  1725. /*
  1726.  * If
  1727.  * - there is not enough room in the current block
  1728.  * - appending to the last line in the block
  1729.  * - not appending to the last line in the file
  1730.  * insert in front of the next block.
  1731.  */
  1732.     if ((int)dp->db_free < space_needed && db_idx == line_count - 1
  1733.     && lnum < buf->b_ml.ml_line_count)
  1734.     {
  1735. /*
  1736.  * Now that the line is not going to be inserted in the block that we
  1737.  * expected, the line count has to be adjusted in the pointer blocks
  1738.  * by using ml_locked_lineadd.
  1739.  */
  1740. --(buf->b_ml.ml_locked_lineadd);
  1741. --(buf->b_ml.ml_locked_high);
  1742. if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
  1743.     return FAIL;
  1744. db_idx = -1;     /* careful, it is negative! */
  1745.     /* get line count before the insertion */
  1746. line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
  1747. CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1");
  1748. dp = (DATA_BL *)(hp->bh_data);
  1749.     }
  1750.     ++buf->b_ml.ml_line_count;
  1751.     if ((int)dp->db_free >= space_needed) /* enough room in data block */
  1752.     {
  1753. /*
  1754.  * Insert new line in existing data block, or in data block allocated above.
  1755.  */
  1756. dp->db_txt_start -= len;
  1757. dp->db_free -= space_needed;
  1758. ++(dp->db_line_count);
  1759. /*
  1760.  * move the text of the lines that follow to the front
  1761.  * adjust the indexes of the lines that follow
  1762.  */
  1763. if (line_count > db_idx + 1)     /* if there are following lines */
  1764. {
  1765.     /*
  1766.      * Offset is the start of the previous line.
  1767.      * This will become the character just after the new line.
  1768.      */
  1769.     if (db_idx < 0)
  1770. offset = dp->db_txt_end;
  1771.     else
  1772. offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK);
  1773.     mch_memmove((char *)dp + dp->db_txt_start,
  1774.   (char *)dp + dp->db_txt_start + len,
  1775.  (size_t)(offset - (dp->db_txt_start + len)));
  1776.     for (i = line_count - 1; i > db_idx; --i)
  1777. dp->db_index[i + 1] = dp->db_index[i] - len;
  1778.     dp->db_index[db_idx + 1] = offset - len;
  1779. }
  1780. else     /* add line at the end */
  1781.     dp->db_index[db_idx + 1] = dp->db_txt_start;
  1782. /*
  1783.  * copy the text into the block
  1784.  */
  1785. mch_memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len);
  1786. if (mark)
  1787.     dp->db_index[db_idx + 1] |= DB_MARKED;
  1788. /*
  1789.  * Mark the block dirty.
  1790.  */
  1791. buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1792. if (!newfile)
  1793.     buf->b_ml.ml_flags |= ML_LOCKED_POS;
  1794.     }
  1795.     else     /* not enough space in data block */
  1796.     {
  1797. /*
  1798.  * If there is not enough room we have to create a new data block and copy some
  1799.  * lines into it.
  1800.  * Then we have to insert an entry in the pointer block.
  1801.  * If this pointer block also is full, we go up another block, and so on, up
  1802.  * to the root if necessary.
  1803.  * The line counts in the pointer blocks have already been adjusted by
  1804.  * ml_find_line().
  1805.  */
  1806. long     line_count_left, line_count_right;
  1807. int     page_count_left, page_count_right;
  1808. BHDR     *hp_left;
  1809. BHDR     *hp_right;
  1810. BHDR     *hp_new;
  1811. int     lines_moved;
  1812. int     data_moved = 0;     /* init to shut up gcc */
  1813. int     total_moved = 0;     /* init to shut up gcc */
  1814. DATA_BL     *dp_right, *dp_left;
  1815. int     stack_idx;
  1816. int     in_left;
  1817. int     lineadd;
  1818. blocknr_t   bnum_left, bnum_right;
  1819. linenr_t    lnum_left, lnum_right;
  1820. int     pb_idx;
  1821. PTR_BL     *pp_new;
  1822. /*
  1823.  * We are going to allocate a new data block. Depending on the
  1824.  * situation it will be put to the left or right of the existing
  1825.  * block.  If possible we put the new line in the left block and move
  1826.  * the lines after it to the right block. Otherwise the new line is
  1827.  * also put in the right block. This method is more efficient when
  1828.  * inserting a lot of lines at one place.
  1829.  */
  1830. if (db_idx < 0) /* left block is new, right block is existing */
  1831. {
  1832.     lines_moved = 0;
  1833.     in_left = TRUE;
  1834.     /* space_needed does not change */
  1835. }
  1836. else /* left block is existing, right block is new */
  1837. {
  1838.     lines_moved = line_count - db_idx - 1;
  1839.     if (lines_moved == 0)
  1840. in_left = FALSE; /* put new line in right block */
  1841. /* space_needed does not change */
  1842.     else
  1843.     {
  1844. data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) -
  1845.     dp->db_txt_start;
  1846. total_moved = data_moved + lines_moved * INDEX_SIZE;
  1847. if ((int)dp->db_free + total_moved >= space_needed)
  1848. {
  1849.     in_left = TRUE; /* put new line in left block */
  1850.     space_needed = total_moved;
  1851. }
  1852. else
  1853. {
  1854.     in_left = FALSE;     /* put new line in right block */
  1855.     space_needed += total_moved;
  1856. }
  1857.     }
  1858. }
  1859. page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
  1860. if ((hp_new = ml_new_data(mfp, newfile, page_count)) == NULL)
  1861. {
  1862. /* correct line counts in pointer blocks */
  1863.     --(buf->b_ml.ml_locked_lineadd);
  1864.     --(buf->b_ml.ml_locked_high);
  1865.     return FAIL;
  1866. }
  1867. if (db_idx < 0) /* left block is new */
  1868. {
  1869.     hp_left = hp_new;
  1870.     hp_right = hp;
  1871.     line_count_left = 0;
  1872.     line_count_right = line_count;
  1873. }
  1874. else /* right block is new */
  1875. {
  1876.     hp_left = hp;
  1877.     hp_right = hp_new;
  1878.     line_count_left = line_count;
  1879.     line_count_right = 0;
  1880. }
  1881. dp_right = (DATA_BL *)(hp_right->bh_data);
  1882. dp_left = (DATA_BL *)(hp_left->bh_data);
  1883. bnum_left = hp_left->bh_bnum;
  1884. bnum_right = hp_right->bh_bnum;
  1885. page_count_left = hp_left->bh_page_count;
  1886. page_count_right = hp_right->bh_page_count;
  1887. /*
  1888.  * May move the new line into the right/new block.
  1889.  */
  1890. if (!in_left)
  1891. {
  1892.     dp_right->db_txt_start -= len;
  1893.     dp_right->db_free -= len + INDEX_SIZE;
  1894.     dp_right->db_index[0] = dp_right->db_txt_start;
  1895.     if (mark)
  1896. dp_right->db_index[0] |= DB_MARKED;
  1897.     mch_memmove((char *)dp_right + dp_right->db_txt_start,
  1898.    line, (size_t)len);
  1899.     ++line_count_right;
  1900. }
  1901. /*
  1902.  * may move lines from the left/old block to the right/new one.
  1903.  */
  1904. if (lines_moved)
  1905. {
  1906.     /*
  1907.      */
  1908.     dp_right->db_txt_start -= data_moved;
  1909.     dp_right->db_free -= total_moved;
  1910.     mch_memmove((char *)dp_right + dp_right->db_txt_start,
  1911. (char *)dp_left + dp_left->db_txt_start,
  1912. (size_t)data_moved);
  1913.     offset = dp_right->db_txt_start - dp_left->db_txt_start;
  1914.     dp_left->db_txt_start += data_moved;
  1915.     dp_left->db_free += total_moved;
  1916.     /*
  1917.      * update indexes in the new block
  1918.      */
  1919.     for (to = line_count_right, from = db_idx + 1;
  1920.  from < line_count_left; ++from, ++to)
  1921. dp_right->db_index[to] = dp->db_index[from] + offset;
  1922.     line_count_right += lines_moved;
  1923.     line_count_left -= lines_moved;
  1924. }
  1925. /*
  1926.  * May move the new line into the left (old or new) block.
  1927.  */
  1928. if (in_left)
  1929. {
  1930.     dp_left->db_txt_start -= len;
  1931.     dp_left->db_free -= len + INDEX_SIZE;
  1932.     dp_left->db_index[line_count_left] = dp_left->db_txt_start;
  1933.     if (mark)
  1934. dp_left->db_index[line_count_left] |= DB_MARKED;
  1935.     mch_memmove((char *)dp_left + dp_left->db_txt_start,
  1936.    line, (size_t)len);
  1937.     ++line_count_left;
  1938. }
  1939. if (db_idx < 0) /* left block is new */
  1940. {
  1941.     lnum_left = lnum + 1;
  1942.     lnum_right = 0;
  1943. }
  1944. else /* right block is new */
  1945. {
  1946.     lnum_left = 0;
  1947.     if (in_left)
  1948. lnum_right = lnum + 2;
  1949.     else
  1950. lnum_right = lnum + 1;
  1951. }
  1952. dp_left->db_line_count = line_count_left;
  1953. dp_right->db_line_count = line_count_right;
  1954. /*
  1955.  * release the two data blocks
  1956.  * The new one (hp_new) already has a correct blocknumber.
  1957.  * The old one (hp, in ml_locked) gets a positive blocknumber if
  1958.  * we changed it and we are not editing a new file.
  1959.  */
  1960. if (lines_moved || in_left)
  1961.     buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1962. if (!newfile && db_idx >= 0 && in_left)
  1963.     buf->b_ml.ml_flags |= ML_LOCKED_POS;
  1964. mf_put(mfp, hp_new, TRUE, FALSE);
  1965. /*
  1966.  * flush the old data block
  1967.  * set ml_locked_lineadd to 0, because the updating of the
  1968.  * pointer blocks is done below
  1969.  */
  1970. lineadd = buf->b_ml.ml_locked_lineadd;
  1971. buf->b_ml.ml_locked_lineadd = 0;
  1972. ml_find_line(buf, (linenr_t)0, ML_FLUSH);   /* flush data block */
  1973. /*
  1974.  * update pointer blocks for the new data block
  1975.  */
  1976. for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0;
  1977.   --stack_idx)
  1978. {
  1979.     ip = &(buf->b_ml.ml_stack[stack_idx]);
  1980.     pb_idx = ip->ip_index;
  1981.     if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  1982. return FAIL;
  1983.     pp = (PTR_BL *)(hp->bh_data);   /* must be pointer block */
  1984.     if (pp->pb_id != PTR_ID)
  1985.     {
  1986. EMSG("pointer block id wrong 3");
  1987. mf_put(mfp, hp, FALSE, FALSE);
  1988. return FAIL;
  1989.     }
  1990.     /*
  1991.      * TODO: If the pointer block is full and we are adding at the end
  1992.      * try to insert in front of the next block
  1993.      */
  1994.     if (pp->pb_count < pp->pb_count_max)    /* block not full, add one entry */
  1995.     {
  1996. if (pb_idx + 1 < (int)pp->pb_count)
  1997.     mch_memmove(&pp->pb_pointer[pb_idx + 2],
  1998. &pp->pb_pointer[pb_idx + 1],
  1999. (size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
  2000. ++pp->pb_count;
  2001. pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
  2002. pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
  2003. pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
  2004. pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
  2005. pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
  2006. pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
  2007. if (lnum_left != 0)
  2008.     pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
  2009. if (lnum_right != 0)
  2010.     pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
  2011. mf_put(mfp, hp, TRUE, FALSE);
  2012. buf->b_ml.ml_stack_top = stack_idx + 1;     /* truncate stack */
  2013. if (lineadd)
  2014. {
  2015.     --(buf->b_ml.ml_stack_top);
  2016. /* fix line count for rest of blocks in the stack */
  2017.     ml_lineadd(buf, lineadd);
  2018. /* fix stack itself */
  2019.     buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
  2020.       lineadd;
  2021.     ++(buf->b_ml.ml_stack_top);
  2022. }
  2023. return OK;
  2024.     }
  2025.     else /* pointer block full */
  2026.     {
  2027. /*
  2028.  * split the pointer block
  2029.  * allocate a new pointer block
  2030.  * move some of the pointer into the new block
  2031.  * prepare for updating the parent block
  2032.  */
  2033. for (;;) /* do this twice when splitting block 1 */
  2034. {
  2035.     hp_new = ml_new_ptr(mfp);
  2036.     if (hp_new == NULL)     /* TODO: try to fix tree */
  2037. return FAIL;
  2038.     pp_new = (PTR_BL *)(hp_new->bh_data);
  2039.     if (hp->bh_bnum != 1)
  2040. break;
  2041.     /*
  2042.      * if block 1 becomes full the tree is given an extra level
  2043.      * The pointers from block 1 are moved into the new block.
  2044.      * block 1 is updated to point to the new block
  2045.      * then continue to split the new block
  2046.      */
  2047.     mch_memmove(pp_new, pp, (size_t)page_size);
  2048.     pp->pb_count = 1;
  2049.     pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
  2050.     pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
  2051.     pp->pb_pointer[0].pe_old_lnum = 1;
  2052.     pp->pb_pointer[0].pe_page_count = 1;
  2053.     mf_put(mfp, hp, TRUE, FALSE);   /* release block 1 */
  2054.     hp = hp_new;     /* new block is to be split */
  2055.     pp = pp_new;
  2056.     CHECK(stack_idx != 0, "stack_idx should be 0");
  2057.     ip->ip_index = 0;
  2058.     ++stack_idx; /* do block 1 again later */
  2059. }
  2060. /*
  2061.  * move the pointers after the current one to the new block
  2062.  * If there are none, the new entry will be in the new block.
  2063.  */
  2064. total_moved = pp->pb_count - pb_idx - 1;
  2065. if (total_moved)
  2066. {
  2067.     mch_memmove(&pp_new->pb_pointer[0],
  2068. &pp->pb_pointer[pb_idx + 1],
  2069. (size_t)(total_moved) * sizeof(PTR_EN));
  2070.     pp_new->pb_count = total_moved;
  2071.     pp->pb_count -= total_moved - 1;
  2072.     pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
  2073.     pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
  2074.     pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
  2075.     if (lnum_right)
  2076. pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
  2077. }
  2078. else
  2079. {
  2080.     pp_new->pb_count = 1;
  2081.     pp_new->pb_pointer[0].pe_bnum = bnum_right;
  2082.     pp_new->pb_pointer[0].pe_line_count = line_count_right;
  2083.     pp_new->pb_pointer[0].pe_page_count = page_count_right;
  2084.     pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
  2085. }
  2086. pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
  2087. pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
  2088. pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
  2089. if (lnum_left)
  2090.     pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
  2091. lnum_left = 0;
  2092. lnum_right = 0;
  2093. /*
  2094.  * recompute line counts
  2095.  */
  2096. line_count_right = 0;
  2097. for (i = 0; i < (int)pp_new->pb_count; ++i)
  2098.     line_count_right += pp_new->pb_pointer[i].pe_line_count;
  2099. line_count_left = 0;
  2100. for (i = 0; i < (int)pp->pb_count; ++i)
  2101.     line_count_left += pp->pb_pointer[i].pe_line_count;
  2102. bnum_left = hp->bh_bnum;
  2103. bnum_right = hp_new->bh_bnum;
  2104. page_count_left = 1;
  2105. page_count_right = 1;
  2106. mf_put(mfp, hp, TRUE, FALSE);
  2107. mf_put(mfp, hp_new, TRUE, FALSE);
  2108.     }
  2109. }
  2110. EMSG("Updated too many blocks?");
  2111. buf->b_ml.ml_stack_top = 0; /* invalidate stack */
  2112.     }
  2113.     return OK;
  2114. }
  2115. /*
  2116.  * replace line lnum, with buffering, in current buffer
  2117.  *
  2118.  * If copy is TRUE, make a copy of the line, otherwise the line has been
  2119.  * copied to allocated memory already.
  2120.  * NOTE: For syntax highlighting, need to call syn_changed() when
  2121.  * update_screenline() is not used.
  2122.  *
  2123.  * return FAIL for failure, OK otherwise
  2124.  */
  2125.     int
  2126. ml_replace(lnum, line, copy)
  2127.     linenr_t lnum;
  2128.     char_u *line;
  2129.     int copy;
  2130. {
  2131.     if (line == NULL) /* just checking... */
  2132. return FAIL;
  2133.     if (curbuf->b_ml.ml_line_lnum != lnum)     /* other line buffered */
  2134. ml_flush_line(curbuf);     /* flush it */
  2135.     else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */
  2136. vim_free(curbuf->b_ml.ml_line_ptr);     /* free it */
  2137.     if (copy && (line = vim_strsave(line)) == NULL) /* allocate memory */
  2138. return FAIL;
  2139.     curbuf->b_ml.ml_line_ptr = line;
  2140.     curbuf->b_ml.ml_line_lnum = lnum;
  2141.     curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
  2142.     return OK;
  2143. }
  2144. /*
  2145.  * delete line 'lnum'
  2146.  *
  2147.  * return FAIL for failure, OK otherwise
  2148.  */
  2149.     int
  2150. ml_delete(lnum, message)
  2151.     linenr_t lnum;
  2152.     int message;
  2153. {
  2154. #ifdef SYNTAX_HL
  2155.     if (curbuf->b_syn_change_lnum > lnum)
  2156. curbuf->b_syn_change_lnum = lnum;
  2157. #endif
  2158.     ml_flush_line(curbuf);
  2159.     return ml_delete_int(curbuf, lnum, message);
  2160. }
  2161.     static int
  2162. ml_delete_int(buf, lnum, message)
  2163.     BUF *buf;
  2164.     linenr_t lnum;
  2165.     int message;
  2166. {
  2167.     BHDR    *hp;
  2168.     MEMFILE *mfp;
  2169.     DATA_BL *dp;
  2170.     PTR_BL  *pp;
  2171.     IPTR    *ip;
  2172.     int     count;     /* number of entries in block */
  2173.     int     idx;
  2174.     int     stack_idx;
  2175.     int     text_start;
  2176.     int     line_start;
  2177.     int     line_size;
  2178.     int     i;
  2179.     if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
  2180. return FAIL;
  2181.     if (lowest_marked && lowest_marked > lnum)
  2182. lowest_marked--;
  2183. /*
  2184.  * If the file becomes empty the last line is replaced by an empty line.
  2185.  */
  2186.     if (buf->b_ml.ml_line_count == 1)     /* file becomes empty */
  2187.     {
  2188. if (message)
  2189. {
  2190.     keep_msg = no_lines_msg;
  2191.     keep_msg_attr = 0;
  2192. }
  2193. i = ml_replace((linenr_t)1, (char_u *)"", TRUE);
  2194. buf->b_ml.ml_flags |= ML_EMPTY;
  2195. return i;
  2196.     }
  2197. /*
  2198.  * find the data block containing the line
  2199.  * This also fills the stack with the blocks from the root to the data block
  2200.  * This also releases any locked block.
  2201.  */
  2202.     mfp = buf->b_ml.ml_mfp;
  2203.     if (mfp == NULL)
  2204. return FAIL;
  2205.     if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL)
  2206. return FAIL;
  2207.     dp = (DATA_BL *)(hp->bh_data);
  2208.     /* compute line count before the delete */
  2209.     count = (long)(buf->b_ml.ml_locked_high) - (long)(buf->b_ml.ml_locked_low) + 2;
  2210.     idx = lnum - buf->b_ml.ml_locked_low;
  2211.     --buf->b_ml.ml_line_count;
  2212. /*
  2213.  * special case: If there is only one line in the data block it becomes empty.
  2214.  * Then we have to remove the entry, pointing to this data block, from the
  2215.  * pointer block. If this pointer block also becomes empty, we go up another
  2216.  * block, and so on, up to the root if necessary.
  2217.  * The line counts in the pointer blocks have already been adjusted by
  2218.  * ml_find_line().
  2219.  */
  2220.     if (count == 1)
  2221.     {
  2222. mf_free(mfp, hp); /* free the data block */
  2223. buf->b_ml.ml_locked = NULL;
  2224. for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
  2225. {
  2226.     buf->b_ml.ml_stack_top = 0;     /* stack is invalid when failing */
  2227.     ip = &(buf->b_ml.ml_stack[stack_idx]);
  2228.     idx = ip->ip_index;
  2229.     if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  2230. return FAIL;
  2231.     pp = (PTR_BL *)(hp->bh_data);   /* must be pointer block */
  2232.     if (pp->pb_id != PTR_ID)
  2233.     {
  2234. EMSG("pointer block id wrong 4");
  2235. mf_put(mfp, hp, FALSE, FALSE);
  2236. return FAIL;
  2237.     }
  2238.     count = --(pp->pb_count);
  2239.     if (count == 0)     /* the pointer block becomes empty! */
  2240. mf_free(mfp, hp);
  2241.     else
  2242.     {
  2243. if (count != idx) /* move entries after the deleted one */
  2244.     mch_memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1],
  2245.       (size_t)(count - idx) * sizeof(PTR_EN));
  2246. mf_put(mfp, hp, TRUE, FALSE);
  2247. buf->b_ml.ml_stack_top = stack_idx; /* truncate stack */
  2248.     /* fix line count for rest of blocks in the stack */
  2249. if (buf->b_ml.ml_locked_lineadd)
  2250. {
  2251.     ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
  2252.     buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
  2253. buf->b_ml.ml_locked_lineadd;
  2254. }
  2255. ++(buf->b_ml.ml_stack_top);
  2256. return OK;
  2257.     }
  2258. }
  2259. CHECK(1, "deleted block 1?");
  2260. return OK;
  2261.     }
  2262.     /*
  2263.      * delete the text by moving the next lines forwards
  2264.      */
  2265.     text_start = dp->db_txt_start;
  2266.     line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
  2267.     if (idx == 0) /* first line in block, text at the end */
  2268. line_size = dp->db_txt_end - line_start;
  2269.     else
  2270. line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
  2271.     mch_memmove((char *)dp + text_start + line_size, (char *)dp + text_start,
  2272.    (size_t)(line_start - text_start));
  2273.     /*
  2274.      * delete the index by moving the next indexes backwards
  2275.      * Adjust the indexes for the text movement.
  2276.      */
  2277.     for (i = idx; i < count - 1; ++i)
  2278. dp->db_index[i] = dp->db_index[i + 1] + line_size;
  2279.     dp->db_free += line_size + INDEX_SIZE;
  2280.     dp->db_txt_start += line_size;
  2281.     --(dp->db_line_count);
  2282.     /*
  2283.      * mark the block dirty and make sure it is in the file (for recovery)
  2284.      */
  2285.     buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2286.     return OK;
  2287. }
  2288. /*
  2289.  * set the B_MARKED flag for line 'lnum'
  2290.  */
  2291.     void
  2292. ml_setmarked(lnum)
  2293.     linenr_t lnum;
  2294. {
  2295.     BHDR    *hp;
  2296.     DATA_BL *dp;
  2297.     /* invalid line number */
  2298.     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count ||
  2299. curbuf->b_ml.ml_mfp == NULL)
  2300. return;     /* give error message? */
  2301.     if (lowest_marked == 0 || lowest_marked > lnum)
  2302. lowest_marked = lnum;
  2303.     /*
  2304.      * find the data block containing the line
  2305.      * This also fills the stack with the blocks from the root to the data block
  2306.      * This also releases any locked block.
  2307.      */
  2308.     if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2309. return;     /* give error message? */
  2310.     dp = (DATA_BL *)(hp->bh_data);
  2311.     dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED;
  2312.     curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  2313. }
  2314. /*
  2315.  * find the first line with its B_MARKED flag set
  2316.  */
  2317.     linenr_t
  2318. ml_firstmarked()
  2319. {
  2320.     BHDR *hp;
  2321.     DATA_BL *dp;
  2322.     linenr_t lnum;
  2323.     int i;
  2324.     if (curbuf->b_ml.ml_mfp == NULL)
  2325. return (linenr_t) 0;
  2326.     /*
  2327.      * The search starts with lowest_marked line. This is the last line where
  2328.      * a mark was found, adjusted by inserting/deleting lines.
  2329.      */
  2330.     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
  2331.     {
  2332. /*
  2333.  * Find the data block containing the line.
  2334.  * This also fills the stack with the blocks from the root to the data
  2335.  * block This also releases any locked block.
  2336.  */
  2337. if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2338.     return (linenr_t)0;     /* give error message? */
  2339. dp = (DATA_BL *)(hp->bh_data);
  2340. for (i = lnum - curbuf->b_ml.ml_locked_low;
  2341.     lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
  2342.     if ((dp->db_index[i]) & DB_MARKED)
  2343.     {
  2344. (dp->db_index[i]) &= DB_INDEX_MASK;
  2345. curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  2346. lowest_marked = lnum + 1;
  2347. return lnum;
  2348.     }
  2349.     }
  2350.     return (linenr_t) 0;
  2351. }
  2352. /*
  2353.  * return TRUE if line 'lnum' has a mark
  2354.  */
  2355.     int
  2356. ml_has_mark(lnum)
  2357.     linenr_t lnum;
  2358. {
  2359.     BHDR *hp;
  2360.     DATA_BL *dp;
  2361.     if (curbuf->b_ml.ml_mfp == NULL ||
  2362. (hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2363. return FALSE;
  2364.     dp = (DATA_BL *)(hp->bh_data);
  2365.     return (int)((dp->db_index[lnum - curbuf->b_ml.ml_locked_low]) & DB_MARKED);
  2366. }
  2367. /*
  2368.  * clear all DB_MARKED flags
  2369.  */
  2370.     void
  2371. ml_clearmarked()
  2372. {
  2373.     BHDR *hp;
  2374.     DATA_BL *dp;
  2375.     linenr_t lnum;
  2376.     int i;
  2377.     if (curbuf->b_ml.ml_mfp == NULL)     /* nothing to do */
  2378. return;
  2379.     /*
  2380.      * The search starts with line lowest_marked.
  2381.      */
  2382.     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
  2383.     {
  2384. /*
  2385.  * Find the data block containing the line.
  2386.  * This also fills the stack with the blocks from the root to the data
  2387.  * block and releases any locked block.
  2388.  */
  2389. if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  2390.     return; /* give error message? */
  2391. dp = (DATA_BL *)(hp->bh_data);
  2392. for (i = lnum - curbuf->b_ml.ml_locked_low;
  2393.     lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
  2394.     if ((dp->db_index[i]) & DB_MARKED)
  2395.     {
  2396. (dp->db_index[i]) &= DB_INDEX_MASK;
  2397. curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  2398.     }
  2399.     }
  2400.     lowest_marked = 0;
  2401.     return;
  2402. }
  2403. /*
  2404.  * flush ml_line if necessary
  2405.  */
  2406.     static void
  2407. ml_flush_line(buf)
  2408.     BUF     *buf;
  2409. {
  2410.     BHDR *hp;
  2411.     DATA_BL *dp;
  2412.     linenr_t lnum;
  2413.     char_u *new_line;
  2414.     char_u *old_line;
  2415.     colnr_t new_len;
  2416.     int old_len;
  2417.     int extra;
  2418.     int idx;
  2419.     int start;
  2420.     int count;
  2421.     int i;
  2422.     if (buf->b_ml.ml_line_lnum == 0 ||
  2423. buf->b_ml.ml_mfp == NULL) /* nothing to do */
  2424. return;
  2425.     if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
  2426.     {
  2427. lnum = buf->b_ml.ml_line_lnum;
  2428. new_line = buf->b_ml.ml_line_ptr;
  2429. hp = ml_find_line(buf, lnum, ML_FIND);
  2430. if (hp == NULL)
  2431.     EMSGN("Cannot find line %ld", lnum);
  2432. else
  2433. {
  2434.     dp = (DATA_BL *)(hp->bh_data);
  2435.     idx = lnum - buf->b_ml.ml_locked_low;
  2436.     start = ((dp->db_index[idx]) & DB_INDEX_MASK);
  2437.     old_line = (char_u *)dp + start;
  2438.     if (idx == 0) /* line is last in block */
  2439. old_len = dp->db_txt_end - start;
  2440.     else /* text of previous line follows */
  2441. old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
  2442.     new_len = STRLEN(new_line) + 1;
  2443.     extra = new_len - old_len;     /* negative if lines gets smaller */
  2444.     /*
  2445.      * if new line fits in data block, replace directly
  2446.      */
  2447.     if ((int)dp->db_free >= extra)
  2448.     {
  2449. /* if the length changes and there are following lines */
  2450. count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
  2451. if (extra != 0 && idx < count - 1)
  2452. {
  2453.     /* move text of following lines */
  2454.     mch_memmove((char *)dp + dp->db_txt_start - extra,
  2455. (char *)dp + dp->db_txt_start,
  2456. (size_t)(start - dp->db_txt_start));
  2457.     /* adjust pointers of this and following lines */
  2458.     for (i = idx + 1; i < count; ++i)
  2459. dp->db_index[i] -= extra;
  2460. }
  2461. dp->db_index[idx] -= extra;
  2462. /* adjust free space */
  2463. dp->db_free -= extra;
  2464. dp->db_txt_start -= extra;
  2465. /* copy new line into the data block */
  2466. mch_memmove(old_line - extra, new_line, (size_t)new_len);
  2467. buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2468.     }
  2469.     else
  2470.     {
  2471. /*
  2472.  * Cannot do it in one data block: Delete and append.
  2473.  * Append first, because ml_delete_int() cannot delete the
  2474.  * last line in a buffer, which causes trouble for a buffer
  2475.  * that has only one line.
  2476.  * Don't forget to copy the mark!
  2477.  */
  2478. /* How about handling errors??? */
  2479. (void)ml_append_int(buf, lnum, new_line, new_len, FALSE,
  2480.      (dp->db_index[idx] & DB_MARKED));
  2481. (void)ml_delete_int(buf, lnum, FALSE);
  2482.     }
  2483. }
  2484. vim_free(new_line);
  2485.     }
  2486.     buf->b_ml.ml_line_lnum = 0;
  2487. }
  2488. /*
  2489.  * create a new, empty, data block
  2490.  */
  2491.     static BHDR *
  2492. ml_new_data(mfp, negative, page_count)
  2493.     MEMFILE *mfp;
  2494.     int negative;
  2495.     int page_count;
  2496. {
  2497.     BHDR *hp;
  2498.     DATA_BL *dp;
  2499.     if ((hp = mf_new(mfp, negative, page_count)) == NULL)
  2500. return NULL;
  2501.     dp = (DATA_BL *)(hp->bh_data);
  2502.     dp->db_id = DATA_ID;
  2503.     dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size;
  2504.     dp->db_free = dp->db_txt_start - HEADER_SIZE;
  2505.     dp->db_line_count = 0;
  2506.     return hp;
  2507. }
  2508. /*
  2509.  * create a new, empty, pointer block
  2510.  */
  2511.     static BHDR *
  2512. ml_new_ptr(mfp)
  2513.     MEMFILE *mfp;
  2514. {
  2515.     BHDR *hp;
  2516.     PTR_BL *pp;
  2517.     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
  2518. return NULL;
  2519.     pp = (PTR_BL *)(hp->bh_data);
  2520.     pp->pb_id = PTR_ID;
  2521.     pp->pb_count = 0;
  2522.     pp->pb_count_max = (mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1;
  2523.     return hp;
  2524. }
  2525. /*
  2526.  * lookup line 'lnum' in a memline
  2527.  *
  2528.  *   action: if ML_DELETE or ML_INSERT the line count is updated while searching
  2529.  *      if ML_FLUSH only flush a locked block
  2530.  *      if ML_FIND just find the line
  2531.  *
  2532.  * If the block was found it is locked and put in ml_locked.
  2533.  * The stack is updated to lead to the locked block. The ip_high field in
  2534.  * the stack is updated to reflect the last line in the block AFTER the
  2535.  * insert or delete, also if the pointer block has not been updated yet. But
  2536.  * if if ml_locked != NULL ml_locked_lineadd must be added to ip_high.
  2537.  *
  2538.  * return: NULL for failure, pointer to block header otherwise
  2539.  */
  2540.     static BHDR *
  2541. ml_find_line(buf, lnum, action)
  2542.     BUF *buf;
  2543.     linenr_t lnum;
  2544.     int action;
  2545. {
  2546.     DATA_BL *dp;
  2547.     PTR_BL *pp;
  2548.     IPTR *ip;
  2549.     BHDR *hp;
  2550.     MEMFILE *mfp;
  2551.     linenr_t t;
  2552.     blocknr_t bnum, bnum2;
  2553.     int dirty;
  2554.     linenr_t low, high;
  2555.     int top;
  2556.     int page_count;
  2557.     int idx;
  2558.     mfp = buf->b_ml.ml_mfp;
  2559.     /*
  2560.      * If there is a locked block check if the wanted line is in it.
  2561.      * If not, flush and release the locked block.
  2562.      * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
  2563.      * Don't do this for ML_FLUSH, because we want to flush the locked block.
  2564.      */
  2565.     if (buf->b_ml.ml_locked)
  2566.     {
  2567. if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum &&
  2568.     buf->b_ml.ml_locked_high >= lnum)
  2569. {
  2570. /* remember to update pointer blocks and stack later */
  2571.     if (action == ML_INSERT)
  2572.     {
  2573. ++(buf->b_ml.ml_locked_lineadd);
  2574. ++(buf->b_ml.ml_locked_high);
  2575.     }
  2576.     else if (action == ML_DELETE)
  2577.     {
  2578. --(buf->b_ml.ml_locked_lineadd);
  2579. --(buf->b_ml.ml_locked_high);
  2580.     }
  2581.     return (buf->b_ml.ml_locked);
  2582. }
  2583. mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY,
  2584.     buf->b_ml.ml_flags & ML_LOCKED_POS);
  2585. buf->b_ml.ml_locked = NULL;
  2586.     /*
  2587.      * if lines have been added or deleted in the locked block, need to
  2588.      * update the line count in pointer blocks
  2589.      */
  2590. if (buf->b_ml.ml_locked_lineadd)
  2591.     ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
  2592.     }
  2593.     if (action == ML_FLUSH)     /* nothing else to do */
  2594. return NULL;
  2595.     bnum = 1;     /* start at the root of the tree */
  2596.     page_count = 1;
  2597.     low = 1;
  2598.     high = buf->b_ml.ml_line_count;
  2599.     if (action == ML_FIND) /* first try stack entries */
  2600.     {
  2601. for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top)
  2602. {
  2603.     ip = &(buf->b_ml.ml_stack[top]);
  2604.     if (ip->ip_low <= lnum && ip->ip_high >= lnum)
  2605.     {
  2606. bnum = ip->ip_bnum;
  2607. low = ip->ip_low;
  2608. high = ip->ip_high;
  2609. buf->b_ml.ml_stack_top = top; /* truncate stack at prev entry */
  2610. break;
  2611.     }
  2612. }
  2613. if (top < 0)
  2614.     buf->b_ml.ml_stack_top = 0; /* not found, start at the root */
  2615.     }
  2616.     else /* ML_DELETE or ML_INSERT */
  2617. buf->b_ml.ml_stack_top = 0; /* start at the root */
  2618. /*
  2619.  * search downwards in the tree until a data block is found
  2620.  */
  2621.     for (;;)
  2622.     {
  2623. if ((hp = mf_get(mfp, bnum, page_count)) == NULL)
  2624.     goto error_noblock;
  2625. /*
  2626.  * update high for insert/delete
  2627.  */
  2628. if (action == ML_INSERT)
  2629.     ++high;
  2630. else if (action == ML_DELETE)
  2631.     --high;
  2632. dp = (DATA_BL *)(hp->bh_data);
  2633. if (dp->db_id == DATA_ID) /* data block */
  2634. {
  2635.     buf->b_ml.ml_locked = hp;
  2636.     buf->b_ml.ml_locked_low = low;
  2637.     buf->b_ml.ml_locked_high = high;
  2638.     buf->b_ml.ml_locked_lineadd = 0;
  2639.     buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2640.     return hp;
  2641. }
  2642. pp = (PTR_BL *)(dp); /* must be pointer block */
  2643. if (pp->pb_id != PTR_ID)
  2644. {
  2645.     EMSG("pointer block id wrong");
  2646.     goto error_block;
  2647. }
  2648. if ((top = ml_add_stack(buf)) < 0) /* add new entry to stack */
  2649.     goto error_block;
  2650. ip = &(buf->b_ml.ml_stack[top]);
  2651. ip->ip_bnum = bnum;
  2652. ip->ip_low = low;
  2653. ip->ip_high = high;
  2654. ip->ip_index = -1; /* index not known yet */
  2655. dirty = FALSE;
  2656. for (idx = 0; idx < (int)pp->pb_count; ++idx)
  2657. {
  2658.     t = pp->pb_pointer[idx].pe_line_count;
  2659.     CHECK(t == 0, "pe_line_count is zero");
  2660.     if ((low += t) > lnum)
  2661.     {
  2662. ip->ip_index = idx;
  2663. bnum = pp->pb_pointer[idx].pe_bnum;
  2664. page_count = pp->pb_pointer[idx].pe_page_count;
  2665. high = low - 1;
  2666. low -= t;
  2667. /*
  2668.  * a negative block number may have been changed
  2669.  */
  2670. if (bnum < 0)
  2671. {
  2672.     bnum2 = mf_trans_del(mfp, bnum);
  2673.     if (bnum != bnum2)
  2674.     {
  2675. bnum = bnum2;
  2676. pp->pb_pointer[idx].pe_bnum = bnum;
  2677. dirty = TRUE;
  2678.     }
  2679. }
  2680. break;
  2681.     }
  2682. }
  2683. if (idx >= (int)pp->pb_count)     /* past the end: something wrong! */
  2684. {
  2685.     if (lnum > buf->b_ml.ml_line_count)
  2686. EMSGN("line number out of range: %ld past the end",
  2687.       lnum - buf->b_ml.ml_line_count);
  2688.     else
  2689. EMSGN("line count wrong in block %ld", bnum);
  2690.     goto error_block;
  2691. }
  2692. if (action == ML_DELETE)
  2693. {
  2694.     pp->pb_pointer[idx].pe_line_count--;
  2695.     dirty = TRUE;
  2696. }
  2697. else if (action == ML_INSERT)
  2698. {
  2699.     pp->pb_pointer[idx].pe_line_count++;
  2700.     dirty = TRUE;
  2701. }
  2702. mf_put(mfp, hp, dirty, FALSE);
  2703.     }
  2704. error_block:
  2705.     mf_put(mfp, hp, FALSE, FALSE);
  2706. error_noblock:
  2707. /*
  2708.  * If action is ML_DELETE or ML_INSERT we have to correct the tree for
  2709.  * the incremented/decremented line counts, because there won't be a line
  2710.  * inserted/deleted after all.
  2711.  */
  2712.     if (action == ML_DELETE)
  2713. ml_lineadd(buf, 1);
  2714.     else if (action == ML_INSERT)
  2715. ml_lineadd(buf, -1);
  2716.     buf->b_ml.ml_stack_top = 0;
  2717.     return NULL;
  2718. }
  2719. /*
  2720.  * add an entry to the info pointer stack
  2721.  *
  2722.  * return -1 for failure, number of the new entry otherwise
  2723.  */
  2724.     static int
  2725. ml_add_stack(buf)
  2726.     BUF     *buf;
  2727. {
  2728.     int     top;
  2729.     IPTR    *newstack;
  2730.     top = buf->b_ml.ml_stack_top;
  2731. /* may have to increase the stack size */
  2732.     if (top == buf->b_ml.ml_stack_size)
  2733.     {
  2734. CHECK(top > 0, "Stack size increases"); /* more than 5 levels??? */
  2735. newstack = (IPTR *)alloc((unsigned)sizeof(IPTR) *
  2736. (buf->b_ml.ml_stack_size + STACK_INCR));
  2737. if (newstack == NULL)
  2738.     return -1;
  2739. mch_memmove(newstack, buf->b_ml.ml_stack, (size_t)top * sizeof(IPTR));
  2740. vim_free(buf->b_ml.ml_stack);
  2741. buf->b_ml.ml_stack = newstack;
  2742. buf->b_ml.ml_stack_size += STACK_INCR;
  2743.     }
  2744.     buf->b_ml.ml_stack_top++;
  2745.     return top;
  2746. }
  2747. /*
  2748.  * Update the pointer blocks on the stack for inserted/deleted lines.
  2749.  * The stack itself is also updated.
  2750.  *
  2751.  * When a insert/delete line action fails, the line is not inserted/deleted,
  2752.  * but the pointer blocks have already been updated. That is fixed here by
  2753.  * walking through the stack.
  2754.  *
  2755.  * Count is the number of lines added, negative if lines have been deleted.
  2756.  */
  2757.     static void
  2758. ml_lineadd(buf, count)
  2759.     BUF *buf;
  2760.     int count;
  2761. {
  2762.     int idx;
  2763.     IPTR *ip;
  2764.     PTR_BL *pp;
  2765.     MEMFILE *mfp = buf->b_ml.ml_mfp;
  2766.     BHDR *hp;
  2767.     for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx)
  2768.     {
  2769. ip = &(buf->b_ml.ml_stack[idx]);
  2770. if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  2771.     break;
  2772. pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
  2773. if (pp->pb_id != PTR_ID)
  2774. {
  2775.     mf_put(mfp, hp, FALSE, FALSE);
  2776.     EMSG("pointer block id wrong 2");
  2777.     break;
  2778. }
  2779. pp->pb_pointer[ip->ip_index].pe_line_count += count;
  2780. ip->ip_high += count;
  2781. mf_put(mfp, hp, TRUE, FALSE);
  2782.     }
  2783. }
  2784. /*
  2785.  * make swap file name out of the file name and a directory name
  2786.  */
  2787.     static char_u *
  2788. makeswapname(buf, dir_name)
  2789.     BUF     *buf;
  2790.     char_u  *dir_name;
  2791. {
  2792.     char_u *r, *s;
  2793.     r = modname(
  2794. #ifdef RISCOS
  2795.     /* Avoids problems if fname contains special chars, eg <Wimp$Scrap> */
  2796.     buf->b_ffname,
  2797. #else
  2798.     buf->b_fname,
  2799. #endif
  2800.     (char_u *)
  2801. #if defined(VMS) || defined(RISCOS)
  2802.     "_swp",
  2803. #else
  2804.     ".swp",
  2805. #endif
  2806. #ifdef SHORT_FNAME /* always 8.3 file name */
  2807.     FALSE
  2808. #else
  2809.     /* Prepend a '.' to the swap file name for the current directory. */
  2810.     dir_name[0] == '.' && dir_name[1] == NUL
  2811. #endif
  2812.        );
  2813.     if (r == NULL)     /* out of memory */
  2814. return NULL;
  2815.     s = get_file_in_dir(r, dir_name);
  2816.     vim_free(r);
  2817.     return s;
  2818. }
  2819. /*
  2820.  * Get file name to use for swap file or backup file.
  2821.  * Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir'
  2822.  * option "dname".
  2823.  * - If "dname" is ".", return "fname".
  2824.  * - If "dname" starts with "./", insert "dname" in "fname".
  2825.  * - Otherwise, prepend "dname" to the tail of "fname".
  2826.  *
  2827.  * The return value is an allocated string and can be NULL.
  2828.  */
  2829.     char_u *
  2830. get_file_in_dir(fname, dname)
  2831.     char_u  *fname;
  2832.     char_u  *dname; /* don't use "dirname", it is a global for Alpha */
  2833. {
  2834.     char_u *t;
  2835.     char_u *tail;
  2836.     char_u *retval;
  2837.     int save_char;
  2838.     tail = gettail(fname);
  2839.     if (dname[0] == '.' && dname[1] == NUL)
  2840. retval = vim_strsave(fname);
  2841.     else if (dname[0] == '.' && vim_ispathsep(dname[1]))
  2842.     {
  2843. if (tail == fname)     /* no path before file name */
  2844.     retval = concat_fnames(dname + 2, tail, TRUE);
  2845. else
  2846. {
  2847.     save_char = *tail;
  2848.     *tail = NUL;
  2849.     t = concat_fnames(fname, dname + 2, TRUE);
  2850.     *tail = save_char;
  2851.     if (t == NULL)     /* out of memory */
  2852. retval = NULL;
  2853.     else
  2854.     {
  2855. retval = concat_fnames(t, tail, TRUE);
  2856. vim_free(t);
  2857.     }
  2858. }
  2859.     }
  2860.     else
  2861. retval = concat_fnames(dname, tail, TRUE);
  2862.     return retval;
  2863. }
  2864. /*
  2865.  * Find out what name to use for the swap file for buffer 'buf'.
  2866.  *
  2867.  * Several names are tried to find one that does not exist
  2868.  *
  2869.  * Note: if BASENAMELEN is not correct, you will get error messages for
  2870.  *  not being able to open the swapfile
  2871.  */
  2872.     static char_u *
  2873. findswapname(buf, dirp, old_fname)
  2874.     BUF     *buf;
  2875.     char_u  **dirp;     /* pointer to list of directories */
  2876.     char_u  *old_fname;     /* don't give warning for this file name */
  2877. {
  2878.     char_u *fname;
  2879.     int n;
  2880.     time_t x;
  2881.     char_u *dir_name;
  2882. #ifdef AMIGA
  2883.     BPTR fh;
  2884. #endif
  2885. #ifndef SHORT_FNAME
  2886.     int r;
  2887.     FILE *dummyfd = NULL;
  2888. /*
  2889.  * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
  2890.  * compatible filesystem, it is possible that the file "test.doc.swp" which we
  2891.  * create will be exactly the same file. To avoid this problem we temporarily
  2892.  * create "test.doc".
  2893.  * Don't do this for a symbolic link to a file that doesn't exist yet,
  2894.  * because the link would be deleted further on!
  2895.  */
  2896.     if (!(buf->b_p_sn || buf->b_shortname) && buf->b_fname &&
  2897. mch_getperm(buf->b_fname) < 0)
  2898.     {
  2899. # if defined(HAVE_LSTAT) && ((defined(S_IFMT) && defined(S_IFLNK)) || defined(S_ISLNK))
  2900. struct stat st;
  2901. if (lstat((char *)buf->b_fname, &st) == -1 ||
  2902. #  if defined(S_IFMT) && defined(S_IFLNK)
  2903. (st.st_mode & S_IFMT) != S_IFLNK
  2904. #  else
  2905. !S_ISLNK(st.st_mode)
  2906. #  endif
  2907.     )
  2908. # endif
  2909.     dummyfd = fopen((char *)buf->b_fname, "w");
  2910.     }
  2911. #endif
  2912. /*
  2913.  * Isolate a directory name from *dirp and put it in dir_name.
  2914.  * First allocate some memory to put the directory name in.
  2915.  */
  2916.     dir_name = alloc((unsigned)STRLEN(*dirp) + 1);
  2917.     if (dir_name != NULL)
  2918. (void)copy_option_part(dirp, dir_name, 31000, ",");
  2919. /*
  2920.  * we try different names until we find one that does not exist yet
  2921.  */
  2922.     if (dir_name == NULL)     /* out of memory */
  2923. fname = NULL;
  2924.     else
  2925. fname = makeswapname(buf, dir_name);
  2926.     for (;;)
  2927.     {
  2928. if (fname == NULL) /* must be out of memory */
  2929.     break;
  2930. if ((n = STRLEN(fname)) == 0) /* safety check */
  2931. {
  2932.     vim_free(fname);
  2933.     fname = NULL;
  2934.     break;
  2935. }
  2936. #if (defined(UNIX) || defined(OS2)) && !defined(ARCHIE) && !defined(SHORT_FNAME)
  2937. /*
  2938.  * Some systems have a MS-DOS compatible filesystem that use 8.3 character
  2939.  * file names. If this is the first try and the swap file name does not fit in
  2940.  * 8.3, detect if this is the case, set shortname and try again.
  2941.  */
  2942. if (fname[n - 1] == 'p' && !(buf->b_p_sn || buf->b_shortname))
  2943. {
  2944.     char_u     *tail;
  2945.     char_u     *fname2;
  2946.     struct stat     s1, s2;
  2947.     int     f1, f2;
  2948.     int     created1 = FALSE, created2 = FALSE;
  2949.     int     same = FALSE;
  2950.     /*
  2951.      * Check if swapfile name does not fit in 8.3:
  2952.      * It either contains two dots, is longer than 8 chars, or starts
  2953.      * with a dot.
  2954.      */
  2955.     tail = gettail(buf->b_fname);
  2956.     if (       vim_strchr(tail, '.') != NULL
  2957.     || STRLEN(tail) > (size_t)8
  2958.     || *gettail(fname) == '.')
  2959.     {
  2960. fname2 = alloc(n + 2);
  2961. if (fname2 != NULL)
  2962. {
  2963.     STRCPY(fname2, fname);
  2964.     /* if fname == "xx.xx.swp",     fname2 = "xx.xx.swx"
  2965.      * if fname == ".xx.swp",     fname2 = ".xx.swpx"
  2966.      * if fname == "123456789.swp", fname2 = "12345678x.swp"
  2967.      */
  2968.     if (vim_strchr(tail, '.') != NULL)
  2969. fname2[n - 1] = 'x';
  2970.     else if (*gettail(fname) == '.')
  2971.     {
  2972. fname2[n] = 'x';
  2973. fname2[n + 1] = NUL;
  2974.     }
  2975.     else
  2976. fname2[n - 5] += 1;
  2977.     /*
  2978.      * may need to create the files to be able to use stat()
  2979.      */
  2980.     f1 = open((char *)fname, O_RDONLY | O_EXTRA
  2981. #ifndef macintosh
  2982.     , 0
  2983. #endif
  2984.     );
  2985.     if (f1 < 0)
  2986.     {
  2987. f1 = open((char *)fname, O_RDWR|O_CREAT|O_EXCL|O_EXTRA
  2988. #ifdef UNIX     /* open in rw------- mode */
  2989.       , (mode_t)0600
  2990. #endif
  2991. #if defined(MSDOS) || defined(WIN32) || defined(OS2)  /* open read/write */
  2992. , S_IREAD | S_IWRITE
  2993. #endif
  2994.     );
  2995. #if defined(OS2)
  2996. if (f1 < 0 && errno == ENOENT)
  2997.     same = TRUE;
  2998. #endif
  2999. created1 = TRUE;
  3000.     }
  3001.     if (f1 >= 0)
  3002.     {
  3003. f2 = open((char *)fname2, O_RDONLY | O_EXTRA
  3004. #ifndef macintosh
  3005. , 0
  3006. #endif
  3007. );
  3008. if (f2 < 0)
  3009. {
  3010.     f2 = open((char *)fname2,
  3011.  O_RDWR|O_CREAT|O_EXCL|O_EXTRA
  3012. #ifdef UNIX     /* open in rw------- mode */
  3013.       , (mode_t)0600
  3014. #endif
  3015. #if defined(MSDOS) || defined(WIN32) || defined(OS2)  /* open read/write */
  3016. , S_IREAD | S_IWRITE
  3017. #endif
  3018.     );
  3019.     created2 = TRUE;
  3020. }
  3021. if (f2 >= 0)
  3022. {
  3023.     /*
  3024.      * Both files exist now. If stat() returns the
  3025.      * same device and inode they are the same file.
  3026.      */
  3027.     if (fstat(f1, &s1) != -1 &&
  3028. fstat(f2, &s2) != -1 &&
  3029. s1.st_dev == s2.st_dev &&
  3030. s1.st_ino == s2.st_ino)
  3031. same = TRUE;
  3032.     close(f2);
  3033.     if (created2)
  3034. mch_remove(fname2);
  3035. }
  3036. close(f1);
  3037. if (created1)
  3038.     mch_remove(fname);
  3039.     }
  3040.     vim_free(fname2);
  3041.     if (same)
  3042.     {
  3043. buf->b_shortname = TRUE;
  3044. vim_free(fname);
  3045. fname = makeswapname(buf, dir_name);
  3046. continue; /* try again with b_shortname set */
  3047.     }
  3048. }
  3049.     }
  3050. }
  3051. #endif
  3052. /*
  3053.  * check if the swapfile already exists
  3054.  */
  3055. if (mch_getperm(fname) < 0) /* it does not exist */
  3056. {
  3057. #ifdef AMIGA
  3058.     fh = Open((UBYTE *)fname, (long)MODE_NEWFILE);
  3059.     /*
  3060.      * on the Amiga mch_getperm() will return -1 when the file exists
  3061.      * but is being used by another program. This happens if you edit
  3062.      * a file twice.
  3063.      */
  3064.     if (fh != (BPTR)NULL) /* can open file, OK */
  3065.     {
  3066. Close(fh);
  3067. break;
  3068.     }
  3069.     if (IoErr() != ERROR_OBJECT_IN_USE &&
  3070.        IoErr() != ERROR_OBJECT_EXISTS)
  3071. #endif
  3072. break;
  3073. }
  3074. /*
  3075.  * A file name equal to old_fname is OK to use.
  3076.  */
  3077. if (old_fname != NULL && fnamecmp(fname, old_fname) == 0)
  3078.     break;
  3079. /*
  3080.  * get here when file already exists
  3081.  */
  3082. if (fname[n - 1] == 'p') /* first try */
  3083. {
  3084. #ifndef SHORT_FNAME
  3085.     /*
  3086.      * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp
  3087.      * and file.doc are the same file. To guess if this problem is
  3088.      * present try if file.doc.swx exists. If it does, we set
  3089.      * buf->b_shortname and try file_doc.swp (dots replaced by
  3090.      * underscores for this file), and try again. If it doesn't we
  3091.      * assume that "file.doc.swp" already exists.
  3092.      */
  3093.     if (!(buf->b_p_sn || buf->b_shortname)) /* not tried yet */
  3094.     {
  3095. fname[n - 1] = 'x';
  3096. r = mch_getperm(fname); /* try "file.swx" */
  3097. fname[n - 1] = 'p';
  3098. if (r >= 0)     /* "file.swx" seems to exist */
  3099. {
  3100.     buf->b_shortname = TRUE;
  3101.     vim_free(fname);
  3102.     fname = makeswapname(buf, dir_name);
  3103.     continue;     /* try again with '.' replaced by '_' */
  3104. }
  3105.     }
  3106. #endif
  3107.     /*
  3108.      * If we get here the ".swp" file really exists.
  3109.      * Give an error message, unless recovering, no file name, we are
  3110.      * viewing a help file or when the path of the file is different
  3111.      * (happens when all .swp files are in one directory).
  3112.      */
  3113.     if (!recoverymode && buf->b_fname != NULL && !buf->b_help)
  3114.     {
  3115. int fd;
  3116. struct block0 b0;
  3117. int differ = FALSE;
  3118. /*
  3119.  * Try to read block 0 from the swap file to get the original
  3120.  * file name (and inode number).
  3121.  */
  3122. fd = open((char *)fname, O_RDONLY | O_EXTRA
  3123. #ifndef macintosh
  3124. , 0
  3125. #endif
  3126. );
  3127. if (fd >= 0)
  3128. {
  3129.     if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0))
  3130.     {
  3131. /*
  3132.  * The name in the swap file may be "~user/path/file".
  3133.  * Expand it first.
  3134.  */
  3135. expand_env(b0.b0_fname, NameBuff, MAXPATHL);
  3136. #ifdef CHECK_INODE
  3137. if (fnamecmp_ino(buf->b_ffname, NameBuff,
  3138.      char_to_long(b0.b0_ino)))
  3139.     differ = TRUE;
  3140. #else
  3141. if (fnamecmp(NameBuff, buf->b_ffname) != 0)
  3142.     differ = TRUE;
  3143. #endif
  3144.     }
  3145.     close(fd);
  3146. }
  3147. #ifdef RISCOS
  3148. else
  3149.     /* Can't open swap file, though it does exist.
  3150.      * Assume that the user is editing two files with
  3151.      * the same name in different directories. No error.
  3152.      */
  3153.     differ = TRUE;
  3154. #endif
  3155. /* give the ATTENTION message when there is an old swap file
  3156.  * for the current file, and the buffer was not recovered. */
  3157. if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
  3158. && vim_strchr(p_shm, SHM_ATTENTION) == NULL)
  3159. {
  3160.     struct stat st;
  3161.     ++no_wait_return;
  3162.     (void)EMSG("ATTENTION");
  3163.     MSG_PUTS("nFound a swap file by the name "");
  3164.     msg_home_replace(fname);
  3165.     MSG_PUTS(""n");
  3166.     swapfile_info(fname);
  3167.     MSG_PUTS("While opening file "");
  3168.     msg_outtrans(buf->b_fname);
  3169.     MSG_PUTS(""n");
  3170.     if (stat((char *)buf->b_fname, &st) != -1)
  3171.     {
  3172. MSG_PUTS("             dated: ");
  3173. x = st.st_mtime;    /* Manx C can't do &st.st_mtime */
  3174. MSG_PUTS(ctime(&x));
  3175.     }
  3176.     MSG_PUTS("n(1) Another program may be editing the same file.n");
  3177.     MSG_PUTS("    If this is the case, quit this edit session to avoid havingn");
  3178.     MSG_PUTS("    two different instances of the same file when making changes.n");
  3179.     MSG_PUTS("n(2) An edit session for this file crashed.n");
  3180.     MSG_PUTS("    If this is the case, use ":recover" or "vim -r ");
  3181.     msg_outtrans(buf->b_fname);
  3182.     MSG_PUTS(""n    to recover the changes (see ":help recovery)".n");
  3183.     MSG_PUTS("    If you did this already, delete the swap file "");
  3184.     msg_outtrans(fname);
  3185.     MSG_PUTS(""n    to avoid this message.nn");
  3186.     cmdline_row = msg_row;
  3187.     --no_wait_return;
  3188.     need_wait_return = TRUE; /* call wait_return later */
  3189. }
  3190.     }
  3191. }
  3192. if (fname[n - 1] == 'a')    /* tried enough names, give up */
  3193. {
  3194.     vim_free(fname);
  3195.     fname = NULL;
  3196.     break;
  3197. }
  3198. --fname[n - 1];     /* change last char of the name */
  3199.     }
  3200.     vim_free(dir_name);
  3201. #ifndef SHORT_FNAME
  3202.     if (dummyfd) /* file has been created temporarily */
  3203.     {
  3204. fclose(dummyfd);
  3205. mch_remove(buf->b_fname);
  3206.     }
  3207. #endif
  3208.     return fname;
  3209. }
  3210.     static int
  3211. b0_magic_wrong(b0p)
  3212.     ZERO_BL *b0p;
  3213. {
  3214.     return (b0p->b0_magic_long != (long)B0_MAGIC_LONG ||
  3215.     b0p->b0_magic_int != (int)B0_MAGIC_INT ||
  3216.     b0p->b0_magic_short != (short)B0_MAGIC_SHORT ||
  3217.     b0p->b0_magic_char != B0_MAGIC_CHAR);
  3218. }
  3219. #ifdef CHECK_INODE
  3220. /*
  3221.  * Compare current file name with file name from swap file.
  3222.  * Try to use inode numbers when possible.
  3223.  * Return non-zero when files are different.
  3224.  *
  3225.  * When comparing file names a few things have to be taken into consideration:
  3226.  * - When working over a network the full path of a file depends on the host.
  3227.  *   We check the inode number if possible.  It is not 100% reliable though,
  3228.  *   because the device number cannot be used over a network.
  3229.  * - When a file does not exist yet (editing a new file) there is no inode
  3230.  *   number.
  3231.  * - The file name in a swap file may not be valid on the current host.  The
  3232.  *   "~user" form is used whenever possible to avoid this.
  3233.  *
  3234.  * This is getting complicated, let's make a table:
  3235.  *
  3236.  * ino_c  ino_s  fname_c  fname_s differ =
  3237.  *
  3238.  * both files exist -> compare inode numbers:
  3239.  * != 0   != 0 X  X ino_c != ino_s
  3240.  *
  3241.  * inode number(s) unknown, file names available -> compare file names
  3242.  * == 0 X OK  OK fname_c != fname_s
  3243.  *  X     == 0 OK  OK fname_c != fname_s
  3244.  *
  3245.  * current file doesn't exist, file for swap file exist, file name(s) not
  3246.  * available -> probably different
  3247.  * == 0   != 0    FAIL  X TRUE
  3248.  * == 0   != 0 X FAIL TRUE
  3249.  *
  3250.  * current file exists, inode for swap unknown, file name(s) not
  3251.  * available -> probably different
  3252.  * != 0   == 0    FAIL  X TRUE
  3253.  * != 0   == 0 X FAIL TRUE
  3254.  *
  3255.  * current file doesn't exist, inode for swap unknown, one file name not
  3256.  * available -> probably different
  3257.  * == 0   == 0    FAIL  OK TRUE
  3258.  * == 0   == 0 OK FAIL TRUE
  3259.  *
  3260.  * current file doesn't exist, inode for swap unknown, both file names not
  3261.  * available -> probably same file
  3262.  * == 0   == 0    FAIL FAIL FALSE
  3263.  */
  3264.     static int
  3265. fnamecmp_ino(fname_c, fname_s, ino_block0)
  3266.     char_u *fname_c;     /* current file name */
  3267.     char_u *fname_s;     /* file name from swap file */
  3268.     long ino_block0;
  3269. {
  3270.     struct stat st;
  3271.     long ino_c = 0;     /* ino of current file */
  3272.     long ino_s;     /* ino of file from swap file */
  3273.     char_u buf_c[MAXPATHL];    /* full path of fname_c */
  3274.     char_u buf_s[MAXPATHL];    /* full path of fname_s */
  3275.     int retval_c;     /* flag: buf_c valid */
  3276.     int retval_s;     /* flag: buf_s valid */
  3277.     if (stat((char *)fname_c, &st) == 0)
  3278. ino_c = st.st_ino;
  3279.     /*
  3280.      * First we try to get the inode from the file name, because the inode in
  3281.      * the swap file may be outdated.  If that fails (e.g. this path is not
  3282.      * valid on this machine), use the inode from block 0.
  3283.      */
  3284.     if (stat((char *)fname_s, &st) == 0)
  3285. ino_s = st.st_ino;
  3286.     else
  3287. ino_s = ino_block0;
  3288.     if (ino_c && ino_s)
  3289. return (ino_c != ino_s);
  3290.     /*
  3291.      * One of the inode numbers is unknown, try a forced mch_FullName() and
  3292.      * compare the file names.
  3293.      */
  3294.     retval_c = mch_FullName(fname_c, buf_c, MAXPATHL, TRUE);
  3295.     retval_s = mch_FullName(fname_s, buf_s, MAXPATHL, TRUE);
  3296.     if (retval_c == OK && retval_s == OK)
  3297. return (STRCMP(buf_c, buf_s) != 0);
  3298.     /*
  3299.      * Can't compare inodes or file names, guess that the files are different,
  3300.      * unless both appear not to exist at all.
  3301.      */
  3302.     if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL)
  3303. return FALSE;
  3304.     return TRUE;
  3305. }
  3306. #endif /* CHECK_INODE */
  3307. /*
  3308.  * Move a long integer into a four byte character array.
  3309.  * Used for machine independency in block zero.
  3310.  */
  3311.     static void
  3312. long_to_char(n, s)
  3313.     long    n;
  3314.     char_u  *s;
  3315. {
  3316.     s[0] = (n & 0xff);
  3317.     n = (unsigned)n >> 8;
  3318.     s[1] = (n & 0xff);
  3319.     n = (unsigned)n >> 8;
  3320.     s[2] = (n & 0xff);
  3321.     n = (unsigned)n >> 8;
  3322.     s[3] = (n & 0xff);
  3323. }
  3324.     static long
  3325. char_to_long(s)
  3326.     char_u  *s;
  3327. {
  3328.     long    retval;
  3329.     retval = s[3];
  3330.     retval <<= 8;
  3331.     retval += s[2];
  3332.     retval <<= 8;
  3333.     retval += s[1];
  3334.     retval <<= 8;
  3335.     retval += s[0];
  3336.     return retval;
  3337. }