home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / amiga / vim46src.lha / vim-4.6 / src / memline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-11  |  89.3 KB  |  3,481 lines

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