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

编辑器/阅读器

开发平台:

DOS

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