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 / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-08  |  40.7 KB  |  1,857 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. /*
  10.  * buffer.c: functions for dealing with the buffer structure
  11.  */
  12.  
  13. /*
  14.  * The buffer list is a double linked list of all buffers.
  15.  * Each buffer can be in one of these states:
  16.  * never loaded: b_neverloaded == TRUE, only the file name is valid
  17.  *   not loaded: b_ml.ml_mfp == NULL, no memfile allocated
  18.  *       hidden: b_nwindows == 0, loaded but not displayed in a window
  19.  *       normal: loaded and displayed in a window
  20.  *
  21.  * Instead of storing file names all over the place, each file name is
  22.  * stored in the buffer list. It can be referenced by a number.
  23.  *
  24.  * The current implementation remembers all file names ever used.
  25.  */
  26.  
  27. #include "vim.h"
  28. #include "globals.h"
  29. #include "proto.h"
  30. #include "option.h"
  31.  
  32. static void        enter_buffer __ARGS((BUF *));
  33. static char_u    *buflist_match __ARGS((regexp *prog, BUF *buf));
  34. static void        buflist_setlnum __ARGS((BUF *, linenr_t));
  35. static linenr_t buflist_findlnum __ARGS((BUF *));
  36. static int        append_arg_number __ARGS((char_u *, int, int));
  37.  
  38. /*
  39.  * Open current buffer, that is: open the memfile and read the file into memory
  40.  * return FAIL for failure, OK otherwise
  41.  */
  42.      int
  43. open_buffer()
  44. {
  45.     int        retval = OK;
  46. #ifdef AUTOCMD
  47.     BUF        *old_curbuf;
  48.     BUF        *new_curbuf;
  49. #endif
  50.  
  51.     /*
  52.      * The 'readonly' flag is only set when b_neverloaded is being reset.
  53.      * When re-entering the same buffer, it should not change, because the
  54.      * user may have reset the flag by hand.
  55.      */
  56.     if (readonlymode && curbuf->b_filename != NULL && curbuf->b_neverloaded)
  57.         curbuf->b_p_ro = TRUE;
  58.  
  59.     if (ml_open() == FAIL)
  60.     {
  61.         /*
  62.          * There MUST be a memfile, otherwise we can't do anything
  63.          * If we can't create one for the current buffer, take another buffer
  64.          */
  65.         close_buffer(NULL, curbuf, FALSE, FALSE);
  66.         for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next)
  67.             if (curbuf->b_ml.ml_mfp != NULL)
  68.                 break;
  69.         /*
  70.          * if there is no memfile at all, exit
  71.          * This is OK, since there are no changes to loose.
  72.          */
  73.         if (curbuf == NULL)
  74.         {
  75.             EMSG("Cannot allocate buffer, exiting...");
  76.             getout(2);
  77.         }
  78.         EMSG("Cannot allocate buffer, using other one...");
  79.         enter_buffer(curbuf);
  80.         return FAIL;
  81.     }
  82. #ifdef AUTOCMD
  83.     /* The autocommands in readfile() may change the buffer, but only AFTER
  84.      * reading the file. */
  85.     old_curbuf = curbuf;
  86. #endif
  87.     if (curbuf->b_filename != NULL)
  88.         retval = readfile(curbuf->b_filename, curbuf->b_sfilename,
  89.                               (linenr_t)0, TRUE, (linenr_t)0, MAXLNUM, FALSE);
  90.     else
  91.     {
  92.         MSG("Empty Buffer");
  93.         msg_col = 0;
  94.         msg_didout = FALSE;        /* overwrite this message whenever you like */
  95.     }
  96.  
  97.     /* if first time loading this buffer, init chartab */
  98.     if (curbuf->b_neverloaded)
  99.         init_chartab();
  100.  
  101.     /*
  102.      * Reset the Changed flag first, autocmds may change the buffer.
  103.      * Apply the automatic commands, before processing the modelines.
  104.      * So the modelines have priority over auto commands.
  105.      */
  106.     if (retval != FAIL)
  107.         UNCHANGED(curbuf);
  108.  
  109. #ifdef AUTOCMD
  110.     apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE);
  111. #endif
  112.  
  113.     if (retval != FAIL)
  114.     {
  115. #ifdef AUTOCMD
  116.         /*
  117.          * The autocommands may have changed the current buffer.  Apply the
  118.          * modelines to the correct buffer, if it still exists.
  119.          */
  120.         if (buf_valid(old_curbuf))
  121.         {
  122.             new_curbuf = curbuf;
  123.             curbuf = old_curbuf;
  124.             curwin->w_buffer = old_curbuf;
  125. #endif
  126.             do_modelines();
  127.             curbuf->b_neverloaded = FALSE;
  128. #ifdef AUTOCMD
  129.             curbuf = new_curbuf;
  130.             curwin->w_buffer = new_curbuf;
  131.         }
  132. #endif
  133.     }
  134.  
  135.     return retval;
  136. }
  137.  
  138. /*
  139.  * Return TRUE if "buf" points to a valid buffer (in the buffer list).
  140.  */
  141.     int
  142. buf_valid(buf)
  143.     BUF        *buf;
  144. {
  145.     BUF        *bp;
  146.  
  147.     for (bp = firstbuf; bp != NULL; bp = bp->b_next)
  148.         if (bp == buf)
  149.             return TRUE;
  150.     return FALSE;
  151. }
  152.  
  153. /*
  154.  * Close the link to a buffer. If "free_buf" is TRUE free the buffer if it
  155.  * becomes unreferenced. The caller should get a new buffer very soon!
  156.  * if 'del_buf' is TRUE, remove the buffer from the buffer list.
  157.  */
  158.     void
  159. close_buffer(win, buf, free_buf, del_buf)
  160.     WIN        *win;            /* if not NULL, set b_last_cursor */
  161.     BUF        *buf;
  162.     int        free_buf;
  163.     int        del_buf;
  164. {
  165.     if (buf->b_nwindows > 0)
  166.         --buf->b_nwindows;
  167.     if (buf->b_nwindows == 0 && win != NULL)
  168.         set_last_cursor(win);    /* may set b_last_cursor */
  169.     if (buf->b_nwindows > 0 || !free_buf)
  170.     {
  171.         if (buf == curbuf)
  172.             u_sync();        /* sync undo before going to another buffer */
  173.         return;
  174.     }
  175.  
  176.     buf_freeall(buf);        /* free all things allocated for this buffer */
  177.     /*
  178.      * If there is no file name, remove the buffer from the list
  179.      */
  180.     if (buf->b_filename == NULL || del_buf)
  181.     {
  182.         vim_free(buf->b_filename);
  183.         vim_free(buf->b_sfilename);
  184.         if (buf->b_prev == NULL)
  185.             firstbuf = buf->b_next;
  186.         else
  187.             buf->b_prev->b_next = buf->b_next;
  188.         if (buf->b_next == NULL)
  189.             lastbuf = buf->b_prev;
  190.         else
  191.             buf->b_next->b_prev = buf->b_prev;
  192.         free_buf_options(buf);
  193.         vim_free(buf);
  194.     }
  195.     else
  196.         buf_clear(buf);
  197. }
  198.  
  199. /*
  200.  * buf_clear() - make buffer empty
  201.  */
  202.     void
  203. buf_clear(buf)
  204.     BUF        *buf;
  205. {
  206.     buf->b_ml.ml_line_count = 1;
  207.     buf->b_changed = FALSE;
  208. #ifndef SHORT_FNAME
  209.     buf->b_shortname = FALSE;
  210. #endif
  211.     buf->b_p_eol = TRUE;
  212.     buf->b_ml.ml_mfp = NULL;
  213.     buf->b_ml.ml_flags = ML_EMPTY;                /* empty buffer */
  214. }
  215.  
  216. /*
  217.  * buf_freeall() - free all things allocated for the buffer
  218.  */
  219.     void
  220. buf_freeall(buf)
  221.     BUF        *buf;
  222. {
  223.     u_blockfree(buf);                /* free the memory allocated for undo */
  224.     ml_close(buf, TRUE);            /* close and delete the memline/memfile */
  225.     buf->b_ml.ml_line_count = 0;    /* no lines in buffer */
  226.     u_clearall(buf);                /* reset all undo information */
  227. }
  228.  
  229. /*
  230.  * do_bufdel() - delete or unload buffer(s)
  231.  *
  232.  * addr_count == 0:    ":bdel" - delete current buffer
  233.  * addr_count == 1: ":N bdel" or ":bdel N [N ..] - first delete
  234.  *                    buffer "end_bnr", then any other arguments.
  235.  * addr_count == 2: ":N,N bdel" - delete buffers in range
  236.  *
  237.  * command can be DOBUF_UNLOAD (":bunload") or DOBUF_DEL (":bdel")
  238.  *
  239.  * Returns error message or NULL
  240.  */
  241.     char_u *
  242. do_bufdel(command, arg, addr_count, start_bnr, end_bnr, forceit)
  243.     int        command;
  244.     char_u    *arg;        /* pointer to extra arguments */
  245.     int        addr_count;
  246.     int        start_bnr;    /* first buffer number in a range */
  247.     int        end_bnr;    /* buffer number or last buffer number in a range */
  248.     int        forceit;
  249. {
  250.     int        do_current = 0;        /* delete current buffer? */
  251.     int        deleted = 0;        /* number of buffers deleted */
  252.     char_u    *errormsg = NULL;    /* return value */
  253.     int        bnr;                /* buffer number */
  254.     char_u    *p;
  255.  
  256.     if (addr_count == 0)
  257.         (void)do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
  258.     else
  259.     {
  260.         if (addr_count == 2)
  261.         {
  262.             if (*arg)            /* both range and argument is not allowed */
  263.                 return e_trailing;
  264.             bnr = start_bnr;
  265.         }
  266.         else    /* addr_count == 1 */
  267.             bnr = end_bnr;
  268.  
  269.         for ( ;!got_int; mch_breakcheck())
  270.         {
  271.             /*
  272.              * delete the current buffer last, otherwise when the
  273.              * current buffer is deleted, the next buffer becomes
  274.              * the current one and will be loaded, which may then
  275.              * also be deleted, etc.
  276.              */
  277.             if (bnr == curbuf->b_fnum)
  278.                 do_current = bnr;
  279.             else if (do_buffer(command, DOBUF_FIRST, FORWARD, (int)bnr,
  280.                                                                forceit) == OK)
  281.                 ++deleted;
  282.  
  283.             /*
  284.              * find next buffer number to delete/unload
  285.              */
  286.             if (addr_count == 2)
  287.             {
  288.                 if (++bnr > end_bnr)
  289.                     break;
  290.             }
  291.             else    /* addr_count == 1 */
  292.             {
  293.                 arg = skipwhite(arg);
  294.                 if (*arg == NUL)
  295.                     break;
  296.                 if (!isdigit(*arg))
  297.                 {
  298.                     p = skiptowhite_esc(arg);
  299.                     bnr = buflist_findpat(arg, p);
  300.                     if (bnr < 0)            /* failed */
  301.                         break;
  302.                     arg = p;
  303.                 }
  304.                 else
  305.                     bnr = getdigits(&arg);
  306.             }
  307.         }
  308.         if (!got_int && do_current && do_buffer(command, DOBUF_FIRST,
  309.                                           FORWARD, do_current, forceit) == OK)
  310.             ++deleted;
  311.  
  312.         if (deleted == 0)
  313.         {
  314.             sprintf((char *)IObuff, "No buffers were %s",
  315.                     command == DOBUF_UNLOAD ? "unloaded" : "deleted");
  316.             errormsg = IObuff;
  317.         }
  318.         else
  319.             smsg((char_u *)"%d buffer%s %s", deleted,
  320.                     plural((long)deleted),
  321.                     command == DOBUF_UNLOAD ? "unloaded" : "deleted");
  322.     }
  323.  
  324.     return errormsg;
  325. }
  326.  
  327. /*
  328.  * Implementation of the command for the buffer list
  329.  *
  330.  * action == DOBUF_GOTO        go to specified buffer
  331.  * action == DOBUF_SPLIT    split window and go to specified buffer
  332.  * action == DOBUF_UNLOAD    unload specified buffer(s)
  333.  * action == DOBUF_DEL        delete specified buffer(s)
  334.  *
  335.  * start == DOBUF_CURRENT    go to "count" buffer from current buffer
  336.  * start == DOBUF_FIRST        go to "count" buffer from first buffer
  337.  * start == DOBUF_LAST        go to "count" buffer from last buffer
  338.  * start == DOBUF_MOD        go to "count" modified buffer from current buffer
  339.  *
  340.  * Return FAIL or OK.
  341.  */
  342.     int
  343. do_buffer(action, start, dir, count, forceit)
  344.     int        action;
  345.     int        start;
  346.     int        dir;        /* FORWARD or BACKWARD */
  347.     int        count;        /* buffer number or number of buffers */
  348.     int        forceit;    /* TRUE for :bdelete! */
  349. {
  350.     BUF        *buf;
  351.     BUF        *delbuf;
  352.     int        retval;
  353.  
  354.     switch (start)
  355.     {
  356.         case DOBUF_FIRST:    buf = firstbuf;    break;
  357.         case DOBUF_LAST:    buf = lastbuf;    break;
  358.         default:            buf = curbuf;    break;
  359.     }
  360.     if (start == DOBUF_MOD)            /* find next modified buffer */
  361.     {
  362.         while (count-- > 0)
  363.         {
  364.             do
  365.             {
  366.                 buf = buf->b_next;
  367.                 if (buf == NULL)
  368.                     buf = firstbuf;
  369.             }
  370.             while (buf != curbuf && !buf->b_changed);
  371.         }
  372.         if (!buf->b_changed)
  373.         {
  374.             EMSG("No modified buffer found");
  375.             return FAIL;
  376.         }
  377.     }
  378.     else if (start == DOBUF_FIRST && count)    /* find specified buffer number */
  379.     {
  380.         while (buf != NULL && buf->b_fnum != count)
  381.             buf = buf->b_next;
  382.     }
  383.     else
  384.     {
  385.         while (count-- > 0)
  386.         {
  387.             if (dir == FORWARD)
  388.             {
  389.                 buf = buf->b_next;
  390.                 if (buf == NULL)
  391.                     buf = firstbuf;
  392.             }
  393.             else
  394.             {
  395.                 buf = buf->b_prev;
  396.                 if (buf == NULL)
  397.                     buf = lastbuf;
  398.             }
  399.         }
  400.     }
  401.  
  402.     if (buf == NULL)        /* could not find it */
  403.     {
  404.         if (start == DOBUF_FIRST)
  405.         {
  406.                                             /* don't warn when deleting */
  407.             if (action != DOBUF_UNLOAD && action != DOBUF_DEL)
  408.                 EMSGN("Cannot go to buffer %ld", count);
  409.         }
  410.         else if (dir == FORWARD)
  411.             EMSG("Cannot go beyond last buffer");
  412.         else
  413.             EMSG("Cannot go before first buffer");
  414.         return FAIL;
  415.     }
  416.  
  417.     /*
  418.      * delete buffer buf from memory and/or the list
  419.      */
  420.     if (action == DOBUF_UNLOAD || action == DOBUF_DEL)
  421.     {
  422.         if (!forceit && buf->b_changed)
  423.         {
  424.             EMSGN("No write since last change for buffer %ld (use ! to override)",
  425.                         buf->b_fnum);
  426.             return FAIL;
  427.         }
  428.  
  429.         /*
  430.          * If deleting last buffer, make it empty.
  431.          * The last buffer cannot be unloaded.
  432.          */
  433.         if (firstbuf->b_next == NULL)
  434.         {
  435.             if (action == DOBUF_UNLOAD)
  436.             {
  437.                 EMSG("Cannot unload last buffer");
  438.                 return FAIL;
  439.             }
  440.  
  441.             /* Close any other windows on this buffer, then make it empty. */
  442.             close_others(FALSE);
  443.             buf = curbuf;
  444.             setpcmark();
  445.             retval = do_ecmd(0, NULL, NULL, NULL, (linenr_t)1,
  446.                                                   forceit ? ECMD_FORCEIT : 0);
  447.  
  448.             /*
  449.              * do_ecmd() may create a new buffer, then we have to delete
  450.              * the old one.  But do_ecmd() may have done that already, check
  451.              * if the buffer still exists.
  452.              */
  453.             if (buf != curbuf && buf_valid(buf))
  454.                 close_buffer(NULL, buf, TRUE, TRUE);
  455.             return retval;
  456.         }
  457.  
  458.         /*
  459.          * If the deleted buffer is the current one, close the current window
  460.          * (unless it's the only window).
  461.          */
  462.         while (buf == curbuf && firstwin != lastwin)
  463.             close_window(curwin, FALSE);
  464.  
  465.         /*
  466.          * If the buffer to be deleted is not current one, delete it here.
  467.          */
  468.         if (buf != curbuf)
  469.         {
  470.             close_windows(buf);
  471.             if (buf_valid(buf))
  472.                 close_buffer(NULL, buf, TRUE, action == DOBUF_DEL);
  473.             return OK;
  474.         }
  475.  
  476.         /*
  477.          * Deleting the current buffer: Need to find another buffer to go to.
  478.          * There must be another, otherwise it would have been handled above.
  479.          * First try to find one that is loaded.
  480.          */
  481.         for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  482.             if (buf != curbuf && buf->b_ml.ml_mfp != NULL)
  483.                 break;
  484.         if (buf == NULL)        /* No loaded buffers, just take anyone */
  485.         {
  486.             if (curbuf->b_next != NULL)
  487.                 buf = curbuf->b_next;
  488.             else
  489.                 buf = curbuf->b_prev;
  490.         }
  491.     }
  492.  
  493.     /*
  494.      * make buf current buffer
  495.      */
  496.     if (action == DOBUF_SPLIT)        /* split window first */
  497.     {
  498.         if (win_split(0, FALSE) == FAIL)
  499.             return FAIL;
  500.     }
  501.  
  502.     /* go to current buffer - nothing to do */
  503.     if (buf == curbuf)
  504.         return OK;
  505.  
  506.     setpcmark();
  507.     curwin->w_alt_fnum = curbuf->b_fnum; /* remember alternate file */
  508.     buflist_altlnum();                     /* remember curpos.lnum */
  509.  
  510.     /* close_windows() or apply_autocmds() may change curbuf */
  511.     delbuf = curbuf;
  512.  
  513. #ifdef AUTOCMD
  514.     apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE);
  515.     if (buf_valid(delbuf))
  516. #endif
  517.     {
  518.         if (action == DOBUF_UNLOAD || action == DOBUF_DEL)
  519.             close_windows(delbuf);
  520.         if (buf_valid(delbuf))
  521.             close_buffer(NULL, delbuf, action == DOBUF_UNLOAD ||
  522.                                     action == DOBUF_DEL, action == DOBUF_DEL);
  523.     }
  524. #ifdef AUTOCMD
  525.     if (buf_valid(buf))        /* an autocommand may have deleted buf! */
  526. #endif
  527.         enter_buffer(buf);
  528.     return OK;
  529. }
  530.  
  531. /*
  532.  * enter a new current buffer.
  533.  * (old curbuf must have been freed already)
  534.  */
  535.     static void
  536. enter_buffer(buf)
  537.     BUF        *buf;
  538. {
  539.     buf_copy_options(curbuf, buf, TRUE, FALSE);
  540.     curwin->w_buffer = buf;
  541.     curbuf = buf;
  542.     ++curbuf->b_nwindows;
  543.     if (curbuf->b_ml.ml_mfp == NULL)    /* need to load the file */
  544.         open_buffer();
  545.     else
  546.     {
  547.         need_fileinfo = TRUE;            /* display file info after redraw */
  548.         buf_check_timestamp(curbuf);    /* check if file has changed */
  549. #ifdef AUTOCMD
  550.         apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE);
  551. #endif
  552.     }
  553.     buflist_getlnum();                    /* restore curpos.lnum */
  554.     check_arg_idx();                    /* check for valid arg_idx */
  555.     maketitle();
  556.     scroll_cursor_halfway(FALSE);        /* redisplay at correct position */
  557.     updateScreen(NOT_VALID);
  558. }
  559.  
  560. /*
  561.  * functions for dealing with the buffer list
  562.  */
  563.  
  564. /*
  565.  * Add a file name to the buffer list. Return a pointer to the buffer.
  566.  * If the same file name already exists return a pointer to that buffer.
  567.  * If it does not exist, or if fname == NULL, a new entry is created.
  568.  * If use_curbuf is TRUE, may use current buffer.
  569.  * This is the ONLY way to create a new buffer.
  570.  */
  571.     BUF *
  572. buflist_new(fname, sfname, lnum, use_curbuf)
  573.     char_u        *fname;
  574.     char_u        *sfname;
  575.     linenr_t    lnum;
  576.     int            use_curbuf;
  577. {
  578.     static int    top_file_num = 1;            /* highest file number */
  579.     BUF            *buf;
  580.  
  581.     fname_expand(&fname, &sfname);
  582.  
  583. /*
  584.  * If file name already exists in the list, update the entry
  585.  */
  586.     if (fname != NULL && (buf = buflist_findname(fname)) != NULL)
  587.     {
  588.         if (lnum != 0)
  589.             buflist_setlnum(buf, lnum);
  590.         /* copy the options now, if 'cpo' doesn't have 's' and not done
  591.          * already */
  592.         buf_copy_options(curbuf, buf, FALSE, FALSE);
  593.         return buf;
  594.     }
  595.  
  596. /*
  597.  * If the current buffer has no name and no contents, use the current buffer.
  598.  * Otherwise: Need to allocate a new buffer structure.
  599.  *
  600.  * This is the ONLY place where a new buffer structure is allocated!
  601.  */
  602.     if (use_curbuf && curbuf != NULL && curbuf->b_filename == NULL &&
  603.                 curbuf->b_nwindows <= 1 &&
  604.                 (curbuf->b_ml.ml_mfp == NULL || bufempty()))
  605.         buf = curbuf;
  606.     else
  607.     {
  608.         buf = (BUF *)alloc((unsigned)sizeof(BUF));
  609.         if (buf == NULL)
  610.             return NULL;
  611.         (void)vim_memset(buf, 0, sizeof(BUF));
  612.     }
  613.  
  614.     if (fname != NULL)
  615.     {
  616.         buf->b_filename = strsave(fname);
  617.         buf->b_sfilename = strsave(sfname);
  618.     }
  619.     if (buf->b_winlnum == NULL)
  620.         buf->b_winlnum = (WINLNUM *)alloc((unsigned)sizeof(WINLNUM));
  621.     if ((fname != NULL && (buf->b_filename == NULL ||
  622.                          buf->b_sfilename == NULL)) || buf->b_winlnum == NULL)
  623.     {
  624.         vim_free(buf->b_filename);
  625.         buf->b_filename = NULL;
  626.         vim_free(buf->b_sfilename);
  627.         buf->b_sfilename = NULL;
  628.         if (buf != curbuf)
  629.         {
  630.             vim_free(buf->b_winlnum);
  631.             free_buf_options(buf);
  632.             vim_free(buf);
  633.         }
  634.         return NULL;
  635.     }
  636.  
  637.     if (buf == curbuf)
  638.     {
  639.         buf_freeall(buf);        /* free all things allocated for this buffer */
  640.         buf->b_nwindows = 0;
  641.     }
  642.     else
  643.     {
  644.         /*
  645.          * put new buffer at the end of the buffer list
  646.          */
  647.         buf->b_next = NULL;
  648.         if (firstbuf == NULL)            /* buffer list is empty */
  649.         {
  650.             buf->b_prev = NULL;
  651.             firstbuf = buf;
  652.         }
  653.         else                            /* append new buffer at end of list */
  654.         {
  655.             lastbuf->b_next = buf;
  656.             buf->b_prev = lastbuf;
  657.         }
  658.         lastbuf = buf;
  659.  
  660.         buf->b_fnum = top_file_num++;
  661.         if (top_file_num < 0)            /* wrap around (may cause duplicates) */
  662.         {
  663.             EMSG("Warning: List of file names overflow");
  664.             mch_delay(3000L, TRUE);        /* make sure it is noticed */
  665.             top_file_num = 1;
  666.         }
  667.  
  668.         buf->b_winlnum->wl_lnum = lnum;
  669.         buf->b_winlnum->wl_next = NULL;
  670.         buf->b_winlnum->wl_prev = NULL;
  671.         buf->b_winlnum->wl_win = curwin;
  672.  
  673.         /*
  674.          * Always copy the options from the current buffer.
  675.          */
  676.         buf_copy_options(curbuf, buf, FALSE, TRUE);
  677.     }
  678.  
  679.     if (did_cd)
  680.         buf->b_xfilename = buf->b_filename;
  681.     else
  682.         buf->b_xfilename = buf->b_sfilename;
  683.     buf->b_u_synced = TRUE;
  684.     buf->b_neverloaded = TRUE;
  685.     buf_clear(buf);
  686.     clrallmarks(buf);                /* clear marks */
  687.     fmarks_check_names(buf);        /* check file marks for this file */
  688.  
  689.     return buf;
  690. }
  691.  
  692. /*
  693.  * Free the memory for the options of a buffer.
  694.  */
  695.     void
  696. free_buf_options(buf)
  697.     BUF        *buf;
  698. {
  699.     free_string_option(buf->b_p_fo);
  700.     free_string_option(buf->b_p_isk);
  701.     free_string_option(buf->b_p_com);
  702. #ifdef CINDENT
  703.     free_string_option(buf->b_p_cink);
  704.     free_string_option(buf->b_p_cino);
  705. #endif
  706. #if defined(CINDENT) || defined(SMARTINDENT)
  707.     free_string_option(buf->b_p_cinw);
  708. #endif
  709. }
  710.  
  711. /*
  712.  * get alternate file n
  713.  * set linenr to lnum or altlnum if lnum == 0
  714.  * if (options & GETF_SETMARK) call setpcmark()
  715.  * if (options & GETF_ALT) we are jumping to an alternate file.
  716.  *
  717.  * return FAIL for failure, OK for success
  718.  */
  719.     int
  720. buflist_getfile(n, lnum, options, forceit)
  721.     int            n;
  722.     linenr_t    lnum;
  723.     int            options;
  724.     int            forceit;
  725. {
  726.     BUF        *buf;
  727.  
  728.     buf = buflist_findnr(n);
  729.     if (buf == NULL)
  730.     {
  731.         if ((options & GETF_ALT) && n == 0)
  732.             emsg(e_noalt);
  733.         else
  734.             EMSGN("buffer %ld not found", n);
  735.         return FAIL;
  736.     }
  737.  
  738.     /* if alternate file is the current buffer, nothing to do */
  739.     if (buf == curbuf)
  740.         return OK;
  741.  
  742.     /* altlnum may be changed by getfile(), get it now */
  743.     if (lnum == 0)
  744.         lnum = buflist_findlnum(buf);
  745.     ++RedrawingDisabled;
  746.     if (getfile(buf->b_fnum, NULL, NULL, (options & GETF_SETMARK),
  747.                                                           lnum, forceit) <= 0)
  748.     {
  749.         --RedrawingDisabled;
  750.         return OK;
  751.     }
  752.     --RedrawingDisabled;
  753.     return FAIL;
  754. }
  755.  
  756. /*
  757.  * go to the last know line number for the current buffer
  758.  */
  759.     void
  760. buflist_getlnum()
  761. {
  762.     linenr_t    lnum;
  763.  
  764.     curwin->w_cursor.lnum = 1;
  765.     curwin->w_cursor.col = 0;
  766.     lnum = buflist_findlnum(curbuf);
  767.     if (lnum != 0 && lnum <= curbuf->b_ml.ml_line_count)
  768.         curwin->w_cursor.lnum = lnum;
  769. }
  770.  
  771. /*
  772.  * find file in buffer list by name (it has to be for the current window)
  773.  * 'fname' must have a full path.
  774.  */
  775.     BUF *
  776. buflist_findname(fname)
  777.     char_u        *fname;
  778. {
  779.     BUF            *buf;
  780.  
  781.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  782.         if (buf->b_filename != NULL && fnamecmp(fname, buf->b_filename) == 0)
  783.             return (buf);
  784.     return NULL;
  785. }
  786.  
  787. /*
  788.  * Find file in buffer list by a regexppattern.
  789.  * Return fnum of the found buffer, < 0 for error.
  790.  */
  791.     int
  792. buflist_findpat(pattern, pattern_end)
  793.     char_u        *pattern;
  794.     char_u        *pattern_end;        /* pointer to first char after pattern */
  795. {
  796.     BUF            *buf;
  797.     regexp        *prog;
  798.     int            fnum = -1;
  799.     char_u        *pat;
  800.     char_u        *match;
  801.     int            attempt;
  802.     char_u        *p;
  803.  
  804.     if (pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#'))
  805.     {
  806.         if (*pattern == '%')
  807.             fnum = curbuf->b_fnum;
  808.         else
  809.             fnum = curwin->w_alt_fnum;
  810.     }
  811.  
  812.     /*
  813.      * Try four ways of matching:
  814.      * attempt == 0: without '^' or '$' (at any position)
  815.      * attempt == 1: with '^' at start (only at postion 0)
  816.      * attempt == 2: with '$' at end (only match at end)
  817.      * attempt == 3: with '^' at start and '$' at end (only full match)
  818.      */
  819.     else for (attempt = 0; attempt <= 3; ++attempt)
  820.     {
  821.         /* may add '^' and '$' */
  822.         pat = file_pat_to_reg_pat(pattern, pattern_end, NULL);
  823.         if (pat == NULL)
  824.             return -1;
  825.         if (attempt < 2)
  826.         {
  827.             p = pat + STRLEN(pat) - 1;
  828.             if (p > pat && *p == '$')                /* remove '$' */
  829.                 *p = NUL;
  830.         }
  831.         p = pat;
  832.         if (*p == '^' && !(attempt & 1))            /* remove '^' */
  833.             ++p;
  834.         prog = vim_regcomp(p);
  835.         vim_free(pat);
  836.         if (prog == NULL)
  837.             return -1;
  838.  
  839.         for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  840.         {
  841.             match = buflist_match(prog, buf);
  842.             if (match != NULL)
  843.             {
  844.                 if (fnum >= 0)            /* already found a match */
  845.                 {
  846.                     fnum = -2;
  847.                     break;
  848.                 }
  849.                 fnum = buf->b_fnum;        /* remember first match */
  850.             }
  851.         }
  852.         vim_free(prog);
  853.         if (fnum >= 0)                    /* found one match */
  854.             break;
  855.     }
  856.  
  857.     if (fnum == -2)
  858.         EMSG2("More than one match for %s", pattern);
  859.     else if (fnum < 1)
  860.         EMSG2("No matching buffer for %s", pattern);
  861.     return fnum;
  862. }
  863.  
  864. /*
  865.  * Find all buffer names that match.
  866.  * For command line expansion of ":buf" and ":sbuf".
  867.  * Return OK if matches found, FAIL otherwise.
  868.  */
  869.     int
  870. ExpandBufnames(pat, num_file, file, options)
  871.     char_u        *pat;
  872.     int            *num_file;
  873.     char_u        ***file;
  874.     int            options;
  875. {
  876.     int            count = 0;
  877.     BUF            *buf;
  878.     int            round;
  879.     char_u        *p;
  880.     int            attempt;
  881.     regexp        *prog;
  882.  
  883.     *num_file = 0;                    /* return values in case of FAIL */
  884.     *file = NULL;
  885.  
  886.     /*
  887.      * attempt == 1: try match with    '^', match at start
  888.      * attempt == 2: try match without '^', match anywhere
  889.      */
  890.     for (attempt = 1; attempt <= 2; ++attempt)
  891.     {
  892.         if (attempt == 2)
  893.         {
  894.             if (*pat != '^')        /* there's no '^', no need to try again */
  895.                 break;
  896.             ++pat;                    /* skip the '^' */
  897.         }
  898.         prog = vim_regcomp(pat);
  899.         if (prog == NULL)
  900.             return FAIL;
  901.  
  902.         /*
  903.          * round == 1: Count the matches.
  904.          * round == 2: Build the array to keep the matches.
  905.          */
  906.         for (round = 1; round <= 2; ++round)
  907.         {
  908.             count = 0;
  909.             for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  910.             {
  911.                 p = buflist_match(prog, buf);
  912.                 if (p != NULL)
  913.                 {
  914.                     if (round == 1)
  915.                         ++count;
  916.                     else
  917.                     {
  918.                         if (options & WILD_HOME_REPLACE)
  919.                             p = home_replace_save(buf, p);
  920.                         else
  921.                             p = strsave(p);
  922.                         (*file)[count++] = p;
  923.                     }
  924.                 }
  925.             }
  926.             if (count == 0)        /* no match found, break here */
  927.                 break;
  928.             if (round == 1)
  929.             {
  930.                 *file = (char_u **)alloc((unsigned)(count * sizeof(char_u *)));
  931.                 if (*file == NULL)
  932.                 {
  933.                     vim_free(prog);
  934.                     return FAIL;
  935.                 }
  936.             }
  937.         }
  938.         vim_free(prog);
  939.         if (count)                /* match(es) found, break here */
  940.             break;
  941.     }
  942.  
  943.     *num_file = count;
  944.     return (count == 0 ? FAIL : OK);
  945. }
  946.  
  947. /*
  948.  * Check for a match on the file name for buffer "buf" with regex prog "prog".
  949.  */
  950.     static char_u *
  951. buflist_match(prog, buf)
  952.     regexp        *prog;
  953.     BUF            *buf;
  954. {
  955.     char_u    *match = NULL;
  956.  
  957.     if (buf->b_sfilename != NULL &&
  958.                                vim_regexec(prog, buf->b_sfilename, TRUE) != 0)
  959.         match = buf->b_sfilename;
  960.     else if (buf->b_filename != NULL)
  961.     {
  962.         if (vim_regexec(prog, buf->b_filename, TRUE) != 0)
  963.             match = buf->b_filename;
  964.         else
  965.         {
  966.             home_replace(NULL, buf->b_filename, NameBuff, MAXPATHL);
  967.             if (vim_regexec(prog, NameBuff, TRUE) != 0)
  968.                 match = buf->b_filename;
  969.         }
  970.     }
  971.     return match;
  972. }
  973.  
  974. /*
  975.  * find file in buffer name list by number
  976.  */
  977.     BUF    *
  978. buflist_findnr(nr)
  979.     int            nr;
  980. {
  981.     BUF            *buf;
  982.  
  983.     if (nr == 0)
  984.         nr = curwin->w_alt_fnum;
  985.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  986.         if (buf->b_fnum == nr)
  987.             return (buf);
  988.     return NULL;
  989. }
  990.  
  991. /*
  992.  * get name of file 'n' in the buffer list
  993.  */
  994.      char_u *
  995. buflist_nr2name(n, fullname, helptail)
  996.     int n;
  997.     int fullname;
  998.     int helptail;            /* for help buffers return tail only */
  999. {
  1000.     BUF        *buf;
  1001.     char_u    *fname;
  1002.  
  1003.     buf = buflist_findnr(n);
  1004.     if (buf == NULL)
  1005.         return NULL;
  1006.     if (fullname)
  1007.         fname = buf->b_filename;
  1008.     else
  1009.         fname = buf->b_xfilename;
  1010.     home_replace(helptail ? buf : NULL, fname, NameBuff, MAXPATHL);
  1011.     return NameBuff;
  1012. }
  1013.  
  1014. /*
  1015.  * set the lnum for the buffer 'buf' and the current window
  1016.  */
  1017.     static void
  1018. buflist_setlnum(buf, lnum)
  1019.     BUF            *buf;
  1020.     linenr_t    lnum;
  1021. {
  1022.     WINLNUM        *wlp;
  1023.     
  1024.     for (wlp = buf->b_winlnum; wlp != NULL; wlp = wlp->wl_next)
  1025.         if (wlp->wl_win == curwin)
  1026.             break;
  1027.     if (wlp == NULL)            /* make new entry */
  1028.     {
  1029.         wlp = (WINLNUM *)alloc((unsigned)sizeof(WINLNUM));
  1030.         if (wlp == NULL)
  1031.             return;
  1032.         wlp->wl_win = curwin;
  1033.     }
  1034.     else                        /* remove entry from list */
  1035.     {
  1036.         if (wlp->wl_prev)
  1037.             wlp->wl_prev->wl_next = wlp->wl_next;
  1038.         else
  1039.             buf->b_winlnum = wlp->wl_next;
  1040.         if (wlp->wl_next)
  1041.             wlp->wl_next->wl_prev = wlp->wl_prev;
  1042.     }
  1043.     wlp->wl_lnum = lnum;
  1044. /*
  1045.  * insert entry in front of the list
  1046.  */
  1047.     wlp->wl_next = buf->b_winlnum;
  1048.     buf->b_winlnum = wlp;
  1049.     wlp->wl_prev = NULL;
  1050.     if (wlp->wl_next)
  1051.         wlp->wl_next->wl_prev = wlp;
  1052.  
  1053.     return;
  1054. }
  1055.  
  1056. /*
  1057.  * find the lnum for the buffer 'buf' for the current window
  1058.  */
  1059.     static linenr_t
  1060. buflist_findlnum(buf)
  1061.     BUF        *buf;
  1062. {
  1063.     WINLNUM     *wlp;
  1064.  
  1065.     for (wlp = buf->b_winlnum; wlp != NULL; wlp = wlp->wl_next)
  1066.         if (wlp->wl_win == curwin)
  1067.             break;
  1068.  
  1069.     if (wlp == NULL)        /* if no lnum for curwin, use the first in the list */
  1070.         wlp = buf->b_winlnum;
  1071.  
  1072.     if (wlp)
  1073.         return wlp->wl_lnum;
  1074.     else
  1075.         return (linenr_t)1;
  1076. }
  1077.  
  1078. /*
  1079.  * list all know file names (for :files and :buffers command)
  1080.  */
  1081.     void
  1082. buflist_list()
  1083. {
  1084.     BUF            *buf;
  1085.     int            len;
  1086.  
  1087.     for (buf = firstbuf; buf != NULL && !got_int; buf = buf->b_next)
  1088.     {
  1089.         msg_outchar('\n');
  1090.         if (buf->b_xfilename == NULL)
  1091.             STRCPY(NameBuff, "No File");
  1092.         else
  1093.             /* careful: home_replace calls vim_getenv(), which uses IObuff! */
  1094.             home_replace(buf, buf->b_xfilename, NameBuff, MAXPATHL);
  1095.  
  1096.         sprintf((char *)IObuff, "%3d %c%c%c \"",
  1097.                 buf->b_fnum,
  1098.                 buf == curbuf ? '%' :
  1099.                         (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
  1100.                 buf->b_ml.ml_mfp == NULL ? '-' :
  1101.                         (buf->b_nwindows == 0 ? 'h' : ' '),
  1102.                 buf->b_changed ? '+' : ' ');
  1103.  
  1104.         len = STRLEN(IObuff);
  1105.         STRNCPY(IObuff + len, NameBuff, IOSIZE - 20 - len);
  1106.  
  1107.         len = STRLEN(IObuff);
  1108.         IObuff[len++] = '"';
  1109.         /*
  1110.          * try to put the "line" strings in column 40
  1111.          */
  1112.         do
  1113.         {
  1114.             IObuff[len++] = ' ';
  1115.         } while (len < 40 && len < IOSIZE - 18);
  1116.         sprintf((char *)IObuff + len, "line %ld",
  1117.                 buf == curbuf ? curwin->w_cursor.lnum :
  1118.                                 (long)buflist_findlnum(buf));
  1119.         msg_outtrans(IObuff);
  1120.         flushbuf();            /* output one line at a time */
  1121.         mch_breakcheck();
  1122.     }
  1123. }
  1124.  
  1125. /*
  1126.  * get file name and line number for file 'fnum'
  1127.  * used by DoOneCmd() for translating '%' and '#'
  1128.  * return FAIL if not found, OK for success
  1129.  */
  1130.     int
  1131. buflist_name_nr(fnum, fname, lnum)
  1132.     int            fnum;
  1133.     char_u        **fname;
  1134.     linenr_t    *lnum;
  1135. {
  1136.     BUF            *buf;
  1137.  
  1138.     buf = buflist_findnr(fnum);
  1139.     if (buf == NULL || buf->b_filename == NULL)
  1140.         return FAIL;
  1141.  
  1142.     if (did_cd)
  1143.         *fname = buf->b_filename;
  1144.     else
  1145.         *fname = buf->b_sfilename;
  1146.     *lnum = buflist_findlnum(buf);
  1147.  
  1148.     return OK;
  1149. }
  1150.  
  1151. /*
  1152.  * Set the current file name to 's', short file name to 'ss'.
  1153.  * The file name with the full path is also remembered, for when :cd is used.
  1154.  * Returns FAIL for failure (file name already in use by other buffer)
  1155.  *         OK otherwise.
  1156.  */
  1157.     int
  1158. setfname(fname, sfname, message)
  1159.     char_u *fname, *sfname;
  1160.     int        message;
  1161. {
  1162.     BUF        *buf;
  1163.  
  1164.     if (fname == NULL || *fname == NUL)
  1165.     {
  1166.         vim_free(curbuf->b_filename);
  1167.         vim_free(curbuf->b_sfilename);
  1168.         curbuf->b_filename = NULL;
  1169.         curbuf->b_sfilename = NULL;
  1170.     }
  1171.     else
  1172.     {
  1173.         fname_expand(&fname, &sfname);
  1174. #ifdef USE_FNAME_CASE
  1175. # ifdef USE_LONG_FNAME
  1176.         if (USE_LONG_FNAME)
  1177. # endif
  1178.             fname_case(sfname);        /* set correct case for short filename */
  1179. #endif
  1180.         /*
  1181.          * if the file name is already used in another buffer:
  1182.          * - if the buffer is loaded, fail
  1183.          * - if the buffer is not loaded, delete it from the list
  1184.          */
  1185.         buf = buflist_findname(fname);
  1186.         if (buf != NULL && buf != curbuf)
  1187.         {
  1188.             if (buf->b_ml.ml_mfp != NULL)        /* it's loaded, fail */
  1189.             {
  1190.                 if (message)
  1191.                     EMSG("Buffer with this name already exists");
  1192.                 return FAIL;
  1193.             }
  1194.             close_buffer(NULL, buf, TRUE, TRUE);    /* delete from the list */
  1195.         }
  1196.         fname = strsave(fname);
  1197.         sfname = strsave(sfname);
  1198.         if (fname == NULL || sfname == NULL)
  1199.         {
  1200.             vim_free(sfname);
  1201.             vim_free(fname);
  1202.             return FAIL;
  1203.         }
  1204.         vim_free(curbuf->b_filename);
  1205.         vim_free(curbuf->b_sfilename);
  1206.         curbuf->b_filename = fname;
  1207.         curbuf->b_sfilename = sfname;
  1208.     }
  1209.     if (did_cd)
  1210.         curbuf->b_xfilename = curbuf->b_filename;
  1211.     else
  1212.         curbuf->b_xfilename = curbuf->b_sfilename;
  1213.  
  1214. #ifndef SHORT_FNAME
  1215.     curbuf->b_shortname = FALSE;
  1216. #endif
  1217.     /*
  1218.      * If the file name changed, also change the name of the swapfile
  1219.      */
  1220.     if (curbuf->b_ml.ml_mfp != NULL)
  1221.         ml_setname();
  1222.  
  1223.     check_arg_idx();            /* check file name for arg list */
  1224.     maketitle();                /* set window title */
  1225.     status_redraw_all();        /* status lines need to be redrawn */
  1226.     fmarks_check_names(curbuf);    /* check named file marks */
  1227.     ml_timestamp(curbuf);        /* reset timestamp */
  1228.     return OK;
  1229. }
  1230.  
  1231. /*
  1232.  * set alternate file name for current window
  1233.  *
  1234.  * Used by do_one_cmd(), do_write() and do_ecmd().
  1235.  */
  1236.     void
  1237. setaltfname(fname, sfname, lnum)
  1238.     char_u        *fname;
  1239.     char_u        *sfname;
  1240.     linenr_t    lnum;
  1241. {
  1242.     BUF        *buf;
  1243.  
  1244.     buf = buflist_new(fname, sfname, lnum, FALSE);
  1245.     if (buf != NULL)
  1246.         curwin->w_alt_fnum = buf->b_fnum;
  1247. }
  1248.  
  1249. /*
  1250.  * add a file name to the buflist and return its number
  1251.  *
  1252.  * used by qf_init(), main() and doarglist()
  1253.  */
  1254.     int
  1255. buflist_add(fname)
  1256.     char_u        *fname;
  1257. {
  1258.     BUF        *buf;
  1259.  
  1260.     buf = buflist_new(fname, NULL, (linenr_t)0, FALSE);
  1261.     if (buf != NULL)
  1262.         return buf->b_fnum;
  1263.     return 0;
  1264. }
  1265.  
  1266. /*
  1267.  * set alternate lnum for current window
  1268.  */
  1269.     void
  1270. buflist_altlnum()
  1271. {
  1272.     buflist_setlnum(curbuf, curwin->w_cursor.lnum);
  1273. }
  1274.  
  1275. /*
  1276.  * return nonzero if 'fname' is not the same file as current file
  1277.  * fname must have a full path (expanded by FullName)
  1278.  */
  1279.     int
  1280. otherfile(fname)
  1281.     char_u    *fname;
  1282. {                                    /* no name is different */
  1283.     if (fname == NULL || *fname == NUL || curbuf->b_filename == NULL)
  1284.         return TRUE;
  1285.     return fnamecmp(fname, curbuf->b_filename);
  1286. }
  1287.  
  1288.     void
  1289. fileinfo(fullname, shorthelp, dont_truncate)
  1290.     int fullname;
  1291.     int shorthelp;
  1292.     int    dont_truncate;
  1293. {
  1294.     char_u        *name;
  1295.     int            n;
  1296.     char_u        *p;
  1297.     char_u        *buffer;
  1298.  
  1299.     buffer = alloc(IOSIZE);
  1300.     if (buffer == NULL)
  1301.         return;
  1302.  
  1303.     if (fullname > 1)        /* 2 CTRL-G: include buffer number */
  1304.     {
  1305.         sprintf((char *)buffer, "buf %d: ", curbuf->b_fnum);
  1306.         p = buffer + STRLEN(buffer);
  1307.     }
  1308.     else
  1309.         p = buffer;
  1310.  
  1311.     *p++ = '"';
  1312.     if (curbuf->b_filename == NULL)
  1313.         STRCPY(p, "No File");
  1314.     else
  1315.     {
  1316.         if (!fullname && curbuf->b_sfilename != NULL)
  1317.             name = curbuf->b_sfilename;
  1318.         else
  1319.             name = curbuf->b_filename;
  1320.         home_replace(shorthelp ? curbuf : NULL, name, p,
  1321.                                                 (int)(IOSIZE - (p - buffer)));
  1322.     }
  1323.  
  1324.     sprintf((char *)buffer + STRLEN(buffer),
  1325.             "\"%s%s%s%s",
  1326.             curbuf->b_changed ? (shortmess(SHM_MOD) ?
  1327.                                                 " [+]" : " [Modified]") : " ",
  1328.             curbuf->b_notedited ? "[Not edited]" : "",
  1329.             curbuf->b_p_ro ? (shortmess(SHM_RO) ? "[RO]" : "[readonly]") : "",
  1330.             (curbuf->b_changed || curbuf->b_notedited || curbuf->b_p_ro) ?
  1331.                                                                     " " : "");
  1332.     n = (int)(((long)curwin->w_cursor.lnum * 100L) /
  1333.                                             (long)curbuf->b_ml.ml_line_count);
  1334.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  1335.     {
  1336.         STRCPY(buffer + STRLEN(buffer), no_lines_msg);
  1337.     }
  1338.     else if (p_ru)
  1339.     {
  1340.         /* Current line and column are already on the screen -- webb */
  1341.         sprintf((char *)buffer + STRLEN(buffer),
  1342.             "%ld line%s --%d%%--",
  1343.             (long)curbuf->b_ml.ml_line_count,
  1344.             plural((long)curbuf->b_ml.ml_line_count),
  1345.             n);
  1346.     }
  1347.     else
  1348.     {
  1349.         sprintf((char *)buffer + STRLEN(buffer),
  1350.             "line %ld of %ld --%d%%-- col ",
  1351.             (long)curwin->w_cursor.lnum,
  1352.             (long)curbuf->b_ml.ml_line_count,
  1353.             n);
  1354.         col_print(buffer + STRLEN(buffer),
  1355.                    (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
  1356.     }
  1357.  
  1358.     (void)append_arg_number(buffer, !shortmess(SHM_FILE), IOSIZE);
  1359.  
  1360.     if (dont_truncate)
  1361.         msg(buffer);
  1362.     else
  1363.         msg_trunc(buffer);
  1364.  
  1365.     vim_free(buffer);
  1366. }
  1367.  
  1368. /*
  1369.  * Give some info about the position of the cursor (for "g CTRL-G").
  1370.  */
  1371.     void
  1372. cursor_pos_info()
  1373. {
  1374.     char_u        *p;
  1375.     char_u        buf1[20];
  1376.     char_u        buf2[20];
  1377.     linenr_t    lnum;
  1378.     long        char_count = 0;
  1379.     long        char_count_cursor = 0;
  1380.     int        eol_size;
  1381.  
  1382.     /*
  1383.      * Compute the length of the file in characters.
  1384.      */
  1385.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  1386.     {
  1387.         MSG(no_lines_msg);
  1388.     }
  1389.     else
  1390.     {
  1391.         if (curbuf->b_p_tx)
  1392.             eol_size = 2;
  1393.         else
  1394.             eol_size = 1;
  1395.         for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  1396.         {
  1397.             if (lnum == curwin->w_cursor.lnum)
  1398.                 char_count_cursor = char_count + curwin->w_cursor.col + 1;
  1399.             char_count += STRLEN(ml_get(lnum)) + eol_size;
  1400.         }
  1401.         if (!curbuf->b_p_eol && curbuf->b_p_bin)
  1402.             char_count -= eol_size;
  1403.  
  1404.         p = ml_get_curline();
  1405.         col_print(buf1, (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
  1406.         col_print(buf2, (int)STRLEN(p), linetabsize(p));
  1407.  
  1408.         sprintf((char *)IObuff, "Col %s of %s; Line %ld of %ld; Char %ld of %ld",
  1409.                 (char *)buf1, (char *)buf2,
  1410.                 (long)curwin->w_cursor.lnum, (long)curbuf->b_ml.ml_line_count,
  1411.                 char_count_cursor, char_count);
  1412.         msg(IObuff);
  1413.     }
  1414. }
  1415.  
  1416.     void
  1417. col_print(buf, col, vcol)
  1418.     char_u    *buf;
  1419.     int        col;
  1420.     int        vcol;
  1421. {
  1422.     if (col == vcol)
  1423.         sprintf((char *)buf, "%d", col);
  1424.     else
  1425.         sprintf((char *)buf, "%d-%d", col, vcol);
  1426. }
  1427.  
  1428. /*
  1429.  * put filename in title bar of window and in icon title
  1430.  */
  1431.  
  1432. static char_u *lasttitle = NULL;
  1433. static char_u *lasticon = NULL;
  1434.  
  1435.     void
  1436. maketitle()
  1437. {
  1438.     char_u        *t_name;
  1439.     char_u        *i_name;
  1440.     int            maxlen;
  1441.     int            len;
  1442.  
  1443.     if (curbuf->b_filename == NULL)
  1444.     {
  1445.         t_name = (char_u *)"VIM -";
  1446.         i_name = (char_u *)"No File";
  1447.     }
  1448.     else
  1449.     {
  1450.         STRCPY(IObuff, "VIM - ");
  1451.         home_replace(curbuf, curbuf->b_filename, IObuff + 6, IOSIZE - 6);
  1452.         append_arg_number(IObuff, FALSE, IOSIZE);
  1453.         if (p_titlelen > 0)
  1454.         {
  1455.             maxlen = p_titlelen * Columns / 100;
  1456.             if (maxlen < 10)
  1457.                 maxlen = 10;
  1458.             len = STRLEN(IObuff);
  1459.             if (len > maxlen)
  1460.             {
  1461.                 vim_memmove(IObuff + 6, IObuff + 6 + len - maxlen,
  1462.                                                           (size_t)maxlen - 5);
  1463.                 IObuff[5] = '<';
  1464.             }
  1465.         }
  1466.         t_name = IObuff;
  1467.         i_name = gettail(curbuf->b_filename);    /* use filename only for icon */
  1468.     }
  1469.  
  1470.     vim_free(lasttitle);
  1471.     if (p_title && (lasttitle = alloc((unsigned)(strsize(t_name) + 1))) != NULL)
  1472.     {
  1473.         *lasttitle = NUL;
  1474.         while (*t_name)
  1475.             STRCAT(lasttitle, transchar(*t_name++));
  1476.     }
  1477.     else
  1478.         lasttitle = NULL;
  1479.  
  1480.     vim_free(lasticon);
  1481.     if (p_icon && (lasticon = alloc((unsigned)(strsize(i_name) + 1))) != NULL)
  1482.     {
  1483.         *lasticon = NUL;
  1484.         while (*i_name)
  1485.             STRCAT(lasticon, transchar(*i_name++));
  1486.     }
  1487.     else
  1488.         lasticon = NULL;
  1489.  
  1490.     resettitle();
  1491. }
  1492.  
  1493. /*
  1494.  * Append (file 2 of 8) to 'buf', if editing more than one file.
  1495.  * Return TRUE if it was appended.
  1496.  */
  1497.     static int
  1498. append_arg_number(buf, add_file, maxlen)
  1499.     char_u    *buf;
  1500.     int        add_file;            /* Add "file" before the arg number */
  1501.     int        maxlen;                /* maximum nr of chars in buf */
  1502. {
  1503.     char_u        *p;
  1504.  
  1505.     if (arg_count <= 1)            /* nothing to do */
  1506.         return FALSE;
  1507.  
  1508.     p = buf + STRLEN(buf);        /* go to the end of the buffer */
  1509.     if (p - buf + 35 >= maxlen)    /* getting too long */
  1510.         return FALSE;
  1511.     *p++ = ' ';
  1512.     *p++ = '(';
  1513.     if (add_file)
  1514.     {
  1515.         STRCPY(p, "file ");
  1516.         p += 5;
  1517.     }
  1518.     sprintf((char *)p, curwin->w_arg_idx_invalid ? "(%d) of %d)" :
  1519.                                "%d of %d)", curwin->w_arg_idx + 1, arg_count);
  1520.     return TRUE;
  1521. }
  1522.  
  1523. /*
  1524.  * Put current window title back (used after calling a shell)
  1525.  */
  1526.     void
  1527. resettitle()
  1528. {
  1529.     mch_settitle(lasttitle, lasticon);
  1530. }
  1531.  
  1532. /*
  1533.  * If fname is not a full path, make it a full path
  1534.  */
  1535.     char_u    *
  1536. fix_fname(fname)
  1537.     char_u    *fname;
  1538. {
  1539.     if (fname != NameBuff)            /* if not already expanded */
  1540.     {
  1541.         if (!isFullName(fname))
  1542.         {
  1543.             (void)FullName(fname, NameBuff, MAXPATHL, FALSE);
  1544.             fname = NameBuff;
  1545.         }
  1546. #ifdef USE_FNAME_CASE
  1547.         else
  1548. # ifdef USE_LONG_FNAME
  1549.             if (USE_LONG_FNAME)
  1550. # endif
  1551.         {
  1552.             STRNCPY(NameBuff, fname, MAXPATHL);    /* make copy, it may change */
  1553.             fname = NameBuff;
  1554.             fname_case(fname);            /* set correct case for filename */
  1555.         }
  1556. #endif
  1557.     }
  1558.     return fname;
  1559. }
  1560.  
  1561. /*
  1562.  * make fname a full file name, set sfname to fname if not NULL
  1563.  */
  1564.     void
  1565. fname_expand(fname, sfname)
  1566.     char_u        **fname;
  1567.     char_u        **sfname;
  1568. {
  1569.     if (*fname == NULL)            /* if no file name given, nothing to do */
  1570.         return;
  1571.     if (*sfname == NULL)        /* if no short file name given, use fname */
  1572.         *sfname = *fname;
  1573.     *fname = fix_fname(*fname);    /* expand to full path */
  1574. }
  1575.  
  1576. /*
  1577.  * do_arg_all: open up to 'count' windows, one for each argument
  1578.  */
  1579.     void
  1580. do_arg_all(count)
  1581.     int count;
  1582. {
  1583.     int        i;
  1584.  
  1585.     if (arg_count <= 1)
  1586.     {
  1587.         /* Don't give this obvious error message. We don't want it when the
  1588.          * ":all" command is in the .vimrc. */
  1589.         /* EMSG("Argument list contains less than 2 files"); */
  1590.         return;
  1591.     }
  1592.  
  1593.     /*
  1594.      * 1. close all but first window
  1595.      * 2. make the desired number of windows
  1596.      * 3. start editing one file in each window
  1597.      *    arg_count may change while doing this, because of autocommands.
  1598.      */
  1599.     setpcmark();
  1600.     close_others(FALSE);
  1601.     curwin->w_arg_idx = 0;
  1602.     if (count > arg_count || count <= 0)
  1603.         count = arg_count;
  1604.     count = make_windows(count);
  1605.  
  1606. #ifdef AUTOCMD
  1607.     /*
  1608.      * Don't execute Win/Buf Enter/Leave autocommands here
  1609.      */
  1610.     ++autocmd_no_enter;
  1611.     ++autocmd_no_leave;
  1612. #endif
  1613.     for (i = 0; i < count && i < arg_count && !got_int; ++i)
  1614.     {
  1615.         if (i == arg_count - 1)
  1616.             arg_had_last = TRUE;
  1617.         curwin->w_arg_idx = i;
  1618. #ifdef AUTOCMD
  1619.         if (i == 0)        /* first window: do autocmd for leaving this buffer */
  1620.             --autocmd_no_leave;
  1621. #endif
  1622.                                                 /* edit file i */
  1623.         (void)do_ecmd(0, arg_files[i], NULL, NULL, (linenr_t)1,
  1624.                                                      ECMD_HIDE + ECMD_OLDBUF);
  1625. #ifdef AUTOCMD
  1626.         if (i == 0)
  1627.             ++autocmd_no_leave;
  1628. #endif
  1629.         if (curwin->w_next == NULL)                /* just checking */
  1630.             break;
  1631.         win_enter(curwin->w_next, FALSE);
  1632.         mch_breakcheck();
  1633.     }
  1634. #ifdef AUTOCMD
  1635.     --autocmd_no_enter;
  1636. #endif
  1637.     win_enter(firstwin, FALSE);                    /* back to first window */
  1638. #ifdef AUTOCMD
  1639.     --autocmd_no_leave;
  1640. #endif
  1641. }
  1642.  
  1643. /*
  1644.  * do_buffer_all: open a window for each buffer
  1645.  *
  1646.  * 'count' is the maximum number of windows to open.
  1647.  * when 'all' is TRUE, also load inactive buffers
  1648.  */
  1649.     void
  1650. do_buffer_all(count, all)
  1651.     int        count;
  1652.     int        all;
  1653. {
  1654.     int        buf_count;
  1655.     BUF        *buf;
  1656.     int        i;
  1657.  
  1658. /*
  1659.  * count number of desired windows
  1660.  */
  1661.     buf_count = 0; 
  1662.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  1663.         if (all || buf->b_ml.ml_mfp != NULL)
  1664.             ++buf_count;
  1665.  
  1666.     if (buf_count == 0)                /* Cannot happen? */
  1667.     {
  1668.         EMSG("No relevant entries in buffer list");
  1669.         return;
  1670.     }
  1671.  
  1672.     /*
  1673.      * 1. close all but first window
  1674.      * 2. make the desired number of windows
  1675.      * 3. stuff commands to fill the windows
  1676.      * Watch out for autocommands that delete buffers or windows.
  1677.      */
  1678.     close_others(FALSE);
  1679.     curwin->w_arg_idx = 0;
  1680.     if (buf_count > count)
  1681.         buf_count = count;
  1682.     buf_count = make_windows(buf_count);
  1683.  
  1684. #ifdef AUTOCMD
  1685.     /*
  1686.      * Don't execute Win/Buf Enter/Leave autocommands here
  1687.      */
  1688.     ++autocmd_no_enter;
  1689.     ++autocmd_no_leave;
  1690. #endif
  1691.     buf = firstbuf;
  1692.     for (i = 0; i < buf_count; ++i)
  1693.     {
  1694.         /* find buffer number to put in this window */
  1695.         for ( ; buf != NULL; buf = buf->b_next)
  1696.             if (all || buf->b_ml.ml_mfp != NULL)
  1697.                 break;
  1698.         if (buf == NULL)            /* Cannot happen? */
  1699.             break;
  1700.  
  1701.         /* advance to next window */
  1702.         if (i != 0)
  1703.         {
  1704.             if (curwin->w_next == NULL)            /* just checking */
  1705.                 break;
  1706.             win_enter(curwin->w_next, FALSE);
  1707.         }
  1708.  
  1709. #ifdef AUTOCMD
  1710.         if (i == 0)        /* first window: do autocmd for leaving this buffer */
  1711.             --autocmd_no_leave;
  1712. #endif
  1713.  
  1714.         /* get buffer for this window */
  1715.         (void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, (int)buf->b_fnum, 0);
  1716. #ifdef AUTOCMD
  1717.         if (i == 0)
  1718.             ++autocmd_no_leave;
  1719.         if (!buf_valid(buf))        /* autocommands deleted the buffer!!! */
  1720.             break;
  1721. #endif
  1722.  
  1723.         mch_breakcheck();
  1724.         if (got_int)
  1725.         {
  1726.             (void)vgetc();        /* only break the file loading, not the rest */
  1727.             break;
  1728.         }
  1729.         buf = buf->b_next;
  1730.     }
  1731. #ifdef AUTOCMD
  1732.     --autocmd_no_enter;
  1733. #endif
  1734.     win_enter(firstwin, FALSE);                /* back to first window */
  1735. #ifdef AUTOCMD
  1736.     --autocmd_no_leave;
  1737. #endif
  1738.     if (buf_count > 1)
  1739.         win_equal(curwin, FALSE);            /* adjust heights */
  1740. }
  1741.  
  1742. /*
  1743.  * do_modelines() - process mode lines for the current file
  1744.  *
  1745.  * Returns immediately if the "ml" option isn't set.
  1746.  */
  1747. static int     chk_modeline __ARGS((linenr_t));
  1748.  
  1749.     void
  1750. do_modelines()
  1751. {
  1752.     linenr_t        lnum;
  1753.     int             nmlines;
  1754.  
  1755.     if (!curbuf->b_p_ml || (nmlines = (int)p_mls) == 0)
  1756.         return;
  1757.  
  1758.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count && lnum <= nmlines;
  1759.                                                                        ++lnum)
  1760.         if (chk_modeline(lnum) == FAIL)
  1761.             nmlines = 0;
  1762.  
  1763.     for (lnum = curbuf->b_ml.ml_line_count; lnum > 0 && lnum > nmlines &&
  1764.                           lnum > curbuf->b_ml.ml_line_count - nmlines; --lnum)
  1765.         if (chk_modeline(lnum) == FAIL)
  1766.             nmlines = 0;
  1767. }
  1768.  
  1769. /*
  1770.  * chk_modeline() - check a single line for a mode string
  1771.  * Return FAIL if an error encountered.
  1772.  */
  1773.     static int
  1774. chk_modeline(lnum)
  1775.     linenr_t lnum;
  1776. {
  1777.     register char_u    *s;
  1778.     register char_u    *e;
  1779.     char_u            *linecopy;            /* local copy of any modeline found */
  1780.     int                prev;
  1781.     int                end;
  1782.     int                retval = OK;
  1783.     char_u            *save_sourcing_name;
  1784.  
  1785.     prev = -1;
  1786.     for (s = ml_get(lnum); *s != NUL; ++s)
  1787.     {
  1788.         if (prev == -1 || vim_isspace(prev))
  1789.         {
  1790.             if ((prev != -1 && STRNCMP(s, "ex:", (size_t)3) == 0) ||
  1791.                                 STRNCMP(s, "vi:", (size_t)3) == 0 ||
  1792.                                STRNCMP(s, "vim:", (size_t)4) == 0)
  1793.                 break;
  1794.         }
  1795.         prev = *s;
  1796.     }
  1797.  
  1798.     if (*s)
  1799.     {
  1800.         do                                /* skip over "ex:", "vi:" or "vim:" */
  1801.             ++s;
  1802.         while (s[-1] != ':');
  1803.  
  1804.         s = linecopy = strsave(s);        /* copy the line, it will change */
  1805.         if (linecopy == NULL)
  1806.             return FAIL;
  1807.  
  1808.         sourcing_lnum = lnum;            /* prepare for emsg() */
  1809.         save_sourcing_name = sourcing_name;
  1810.         sourcing_name = (char_u *)"modelines";
  1811.  
  1812.         end = FALSE;
  1813.         while (end == FALSE)
  1814.         {
  1815.             s = skipwhite(s);
  1816.             if (*s == NUL)
  1817.                 break;
  1818.  
  1819.             /*
  1820.              * Find end of set command: ':' or end of line.
  1821.              */
  1822.             for (e = s; (*e != ':' || *(e - 1) == '\\') && *e != NUL; ++e)
  1823.                 ;
  1824.             if (*e == NUL)
  1825.                 end = TRUE;
  1826.  
  1827.             /*
  1828.              * If there is a "set" command, require a terminating ':' and
  1829.              * ignore the stuff after the ':'.
  1830.              * "vi:set opt opt opt: foo" -- foo not interpreted
  1831.              * "vi:opt opt opt: foo" -- foo interpreted
  1832.              */
  1833.             if (STRNCMP(s, "set ", (size_t)4) == 0)
  1834.             {
  1835.                 if (*e != ':')            /* no terminating ':'? */
  1836.                     break;
  1837.                 end = TRUE;
  1838.                 s += 4;
  1839.             }
  1840.  
  1841.             *e = NUL;                    /* truncate the set command */
  1842.             if (do_set(s) == FAIL)        /* stop if error found */
  1843.             {
  1844.                 retval = FAIL;
  1845.                 break;
  1846.             }
  1847.             s = e + 1;                    /* advance to next part */
  1848.         }
  1849.  
  1850.         sourcing_lnum = 0;
  1851.         sourcing_name = save_sourcing_name;
  1852.  
  1853.         vim_free(linecopy);
  1854.     }
  1855.     return retval;
  1856. }
  1857.