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 / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / ex_cmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-25  |  138.3 KB  |  5,882 lines

  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.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * ex_cmds.c: some functions for command line commands
  12.  */
  13.  
  14. #include "vim.h"
  15. #include "version.h"
  16.  
  17. #ifdef FEAT_EX_EXTRA
  18. static int linelen __ARGS((int *has_tab));
  19. #endif
  20. static void do_filter __ARGS((linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, int do_in, int do_out));
  21. #ifdef FEAT_VIMINFO
  22. static char_u *viminfo_filename __ARGS((char_u    *));
  23. static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info, int want_marks, int force_read));
  24. static int viminfo_encoding __ARGS((vir_T *virp));
  25. static int read_viminfo_up_to_marks __ARGS((vir_T *virp, int forceit, int writing));
  26. #endif
  27.  
  28. static int check_overwrite __ARGS((exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int other));
  29. static int check_readonly __ARGS((int *forceit, buf_T *buf));
  30. #ifdef FEAT_AUTOCMD
  31. static void delbuf_msg __ARGS((char_u *name));
  32. #endif
  33. static int do_sub_msg __ARGS((void));
  34. static int
  35. #ifdef __BORLANDC__
  36.     _RTLENTRYF
  37. #endif
  38.     help_compare __ARGS((const void *s1, const void *s2));
  39.  
  40. /*
  41.  * ":ascii" and "ga".
  42.  */
  43. /*ARGSUSED*/
  44.     void
  45. do_ascii(eap)
  46.     exarg_T    *eap;
  47. {
  48.     int        c;
  49.     char    buf1[20];
  50.     char    buf2[20];
  51.     char_u    buf3[7];
  52. #ifdef FEAT_MBYTE
  53.     int        c1 = 0;
  54.     int        c2 = 0;
  55.     int        len;
  56.  
  57.     if (enc_utf8)
  58.     c = utfc_ptr2char(ml_get_cursor(), &c1, &c2);
  59.     else
  60. #endif
  61.     c = gchar_cursor();
  62.     if (c == NUL)
  63.     {
  64.     MSG("NUL");
  65.     return;
  66.     }
  67.  
  68. #ifdef FEAT_MBYTE
  69.     IObuff[0] = NUL;
  70.     if (!has_mbyte || (enc_dbcs != 0 && c < 0x100) || c < 0x80)
  71. #endif
  72.     {
  73.     if (c == NL)        /* NUL is stored as NL */
  74.         c = NUL;
  75.     if (vim_isprintc_strict(c) && (c < ' '
  76. #ifndef EBCDIC
  77.             || c > '~'
  78. #endif
  79.                    ))
  80.     {
  81.         transchar_nonprint(buf3, c);
  82.         sprintf(buf1, "  <%s>", (char *)buf3);
  83.     }
  84.     else
  85.         buf1[0] = NUL;
  86. #ifndef EBCDIC
  87.     if (c >= 0x80)
  88.         sprintf(buf2, "  <M-%s>", transchar(c & 0x7f));
  89.     else
  90. #endif
  91.         buf2[0] = NUL;
  92.     sprintf((char *)IObuff, _("<%s>%s%s  %d,  Hex %02x,  Octal %03o"),
  93.         transchar(c), buf1, buf2, c, c, c);
  94. #ifdef FEAT_MBYTE
  95.     c = c1;
  96.     c1 = c2;
  97.     c2 = 0;
  98. #endif
  99.     }
  100.  
  101. #ifdef FEAT_MBYTE
  102.     /* Repeat for combining characters. */
  103.     while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80)))
  104.     {
  105.     len = (int)STRLEN(IObuff);
  106.     /* This assumes every multi-byte char is printable... */
  107.     if (len > 0)
  108.         IObuff[len++] = ' ';
  109.     IObuff[len++] = '<';
  110.     if (utf_iscomposing(c)
  111. #ifdef USE_GUI
  112.         && !gui.in_use
  113. #endif
  114.         )
  115.         IObuff[len++] = ' '; /* draw composing char on top of a space */
  116.     IObuff[len + (*mb_char2bytes)(c, IObuff + len)] = NUL;
  117.     if (c < 0x10000)
  118.         sprintf((char *)IObuff + STRLEN(IObuff),
  119.                      "> %d, Hex %04x, Octal %o", c, c, c);
  120.     else
  121.         sprintf((char *)IObuff + STRLEN(IObuff),
  122.                      "> %d, Hex %08x, Octal %o", c, c, c);
  123.     c = c1;
  124.     c1 = c2;
  125.     c2 = 0;
  126.     }
  127. #endif
  128.  
  129.     msg(IObuff);
  130. }
  131.  
  132. #if defined(FEAT_EX_EXTRA) || defined(PROTO)
  133. /*
  134.  * ":left", ":center" and ":right": align text.
  135.  */
  136.     void
  137. ex_align(eap)
  138.     exarg_T    *eap;
  139. {
  140.     pos_T    save_curpos;
  141.     int        len;
  142.     int        indent = 0;
  143.     int        new_indent;
  144.     int        has_tab;
  145.     int        width;
  146.  
  147. #ifdef FEAT_RIGHTLEFT
  148.     if (curwin->w_p_rl)
  149.     {
  150.     /* switch left and right aligning */
  151.     if (eap->cmdidx == CMD_right)
  152.         eap->cmdidx = CMD_left;
  153.     else if (eap->cmdidx == CMD_left)
  154.         eap->cmdidx = CMD_right;
  155.     }
  156. #endif
  157.  
  158.     width = atoi((char *)eap->arg);
  159.     save_curpos = curwin->w_cursor;
  160.     if (eap->cmdidx == CMD_left)    /* width is used for new indent */
  161.     {
  162.     if (width >= 0)
  163.         indent = width;
  164.     }
  165.     else
  166.     {
  167.     /*
  168.      * if 'textwidth' set, use it
  169.      * else if 'wrapmargin' set, use it
  170.      * if invalid value, use 80
  171.      */
  172.     if (width <= 0)
  173.         width = curbuf->b_p_tw;
  174.     if (width == 0 && curbuf->b_p_wm > 0)
  175.         width = W_WIDTH(curwin) - curbuf->b_p_wm;
  176.     if (width <= 0)
  177.         width = 80;
  178.     }
  179.  
  180.     if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
  181.     return;
  182.  
  183.     for (curwin->w_cursor.lnum = eap->line1;
  184.          curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum)
  185.     {
  186.     if (eap->cmdidx == CMD_left)        /* left align */
  187.         new_indent = indent;
  188.     else
  189.     {
  190.         len = linelen(eap->cmdidx == CMD_right ? &has_tab
  191.                            : NULL) - get_indent();
  192.  
  193.         if (len <= 0)            /* skip blank lines */
  194.         continue;
  195.  
  196.         if (eap->cmdidx == CMD_center)
  197.         new_indent = (width - len) / 2;
  198.         else
  199.         {
  200.         new_indent = width - len;    /* right align */
  201.  
  202.         /*
  203.          * Make sure that embedded TABs don't make the text go too far
  204.          * to the right.
  205.          */
  206.         if (has_tab)
  207.             while (new_indent > 0)
  208.             {
  209.             (void)set_indent(new_indent, 0);
  210.             if (linelen(NULL) <= width)
  211.             {
  212.                 /*
  213.                  * Now try to move the line as much as possible to
  214.                  * the right.  Stop when it moves too far.
  215.                  */
  216.                 do
  217.                 (void)set_indent(++new_indent, 0);
  218.                 while (linelen(NULL) <= width);
  219.                 --new_indent;
  220.                 break;
  221.             }
  222.             --new_indent;
  223.             }
  224.         }
  225.     }
  226.     if (new_indent < 0)
  227.         new_indent = 0;
  228.     (void)set_indent(new_indent, 0);        /* set indent */
  229.     }
  230.     changed_lines(eap->line1, 0, eap->line2 + 1, 0L);
  231.     curwin->w_cursor = save_curpos;
  232.     beginline(BL_WHITE | BL_FIX);
  233. }
  234.  
  235. /*
  236.  * Get the length of the current line, excluding trailing white space.
  237.  */
  238.     static int
  239. linelen(has_tab)
  240.     int        *has_tab;
  241. {
  242.     char_u  *line;
  243.     char_u  *first;
  244.     char_u  *last;
  245.     int        save;
  246.     int        len;
  247.  
  248.     /* find the first non-blank character */
  249.     line = ml_get_curline();
  250.     first = skipwhite(line);
  251.  
  252.     /* find the character after the last non-blank character */
  253.     for (last = first + STRLEN(first);
  254.                 last > first && vim_iswhite(last[-1]); --last)
  255.     ;
  256.     save = *last;
  257.     *last = NUL;
  258.     len = linetabsize(line);        /* get line length */
  259.     if (has_tab != NULL)        /* check for embedded TAB */
  260.     *has_tab = (vim_strrchr(first, TAB) != NULL);
  261.     *last = save;
  262.  
  263.     return len;
  264. }
  265.  
  266. /*
  267.  * ":retab".
  268.  */
  269.     void
  270. ex_retab(eap)
  271.     exarg_T    *eap;
  272. {
  273.     linenr_T    lnum;
  274.     int        got_tab = FALSE;
  275.     long    num_spaces = 0;
  276.     long    num_tabs;
  277.     long    len;
  278.     long    col;
  279.     long    vcol;
  280.     long    start_col = 0;        /* For start of white-space string */
  281.     long    start_vcol = 0;        /* For start of white-space string */
  282.     int        temp;
  283.     long    old_len;
  284.     char_u    *ptr;
  285.     char_u    *new_line = (char_u *)1;    /* init to non-NULL */
  286.     int        did_undo;        /* called u_save for current line */
  287.     int        new_ts;
  288.     int        save_list;
  289.     linenr_T    first_line = 0;        /* first changed line */
  290.     linenr_T    last_line = 0;        /* last changed line */
  291.  
  292.     save_list = curwin->w_p_list;
  293.     curwin->w_p_list = 0;        /* don't want list mode here */
  294.  
  295.     new_ts = getdigits(&(eap->arg));
  296.     if (new_ts < 0)
  297.     {
  298.     EMSG(_(e_positive));
  299.     return;
  300.     }
  301.     if (new_ts == 0)
  302.     new_ts = curbuf->b_p_ts;
  303.     for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
  304.     {
  305.     ptr = ml_get(lnum);
  306.     col = 0;
  307.     vcol = 0;
  308.     did_undo = FALSE;
  309.     for (;;)
  310.     {
  311.         if (vim_iswhite(ptr[col]))
  312.         {
  313.         if (!got_tab && num_spaces == 0)
  314.         {
  315.             /* First consecutive white-space */
  316.             start_vcol = vcol;
  317.             start_col = col;
  318.         }
  319.         if (ptr[col] == ' ')
  320.             num_spaces++;
  321.         else
  322.             got_tab = TRUE;
  323.         }
  324.         else
  325.         {
  326.         if (got_tab || (eap->forceit && num_spaces > 1))
  327.         {
  328.             /* Retabulate this string of white-space */
  329.  
  330.             /* len is virtual length of white string */
  331.             len = num_spaces = vcol - start_vcol;
  332.             num_tabs = 0;
  333.             if (!curbuf->b_p_et)
  334.             {
  335.             temp = new_ts - (start_vcol % new_ts);
  336.             if (num_spaces >= temp)
  337.             {
  338.                 num_spaces -= temp;
  339.                 num_tabs++;
  340.             }
  341.             num_tabs += num_spaces / new_ts;
  342.             num_spaces -= (num_spaces / new_ts) * new_ts;
  343.             }
  344.             if (curbuf->b_p_et || got_tab ||
  345.                     (num_spaces + num_tabs < len))
  346.             {
  347.             if (did_undo == FALSE)
  348.             {
  349.                 did_undo = TRUE;
  350.                 if (u_save((linenr_T)(lnum - 1),
  351.                         (linenr_T)(lnum + 1)) == FAIL)
  352.                 {
  353.                 new_line = NULL;    /* flag out-of-memory */
  354.                 break;
  355.                 }
  356.             }
  357.  
  358.             /* len is actual number of white characters used */
  359.             len = num_spaces + num_tabs;
  360.             old_len = (long)STRLEN(ptr);
  361.             new_line = lalloc(old_len - col + start_col + len + 1,
  362.                                     TRUE);
  363.             if (new_line == NULL)
  364.                 break;
  365.             if (start_col > 0)
  366.                 mch_memmove(new_line, ptr, (size_t)start_col);
  367.             mch_memmove(new_line + start_col + len,
  368.                       ptr + col, (size_t)(old_len - col + 1));
  369.             ptr = new_line + start_col;
  370.             for (col = 0; col < len; col++)
  371.                 ptr[col] = (col < num_tabs) ? '\t' : ' ';
  372.             ml_replace(lnum, new_line, FALSE);
  373.             if (first_line == 0)
  374.                 first_line = lnum;
  375.             last_line = lnum;
  376.             ptr = new_line;
  377.             col = start_col + len;
  378.             }
  379.         }
  380.         got_tab = FALSE;
  381.         num_spaces = 0;
  382.         }
  383.         if (ptr[col] == NUL)
  384.         break;
  385.         vcol += chartabsize(ptr + col, (colnr_T)vcol);
  386. #ifdef FEAT_MBYTE
  387.         if (has_mbyte)
  388.         col += (*mb_ptr2len_check)(ptr + col);
  389.         else
  390. #endif
  391.         ++col;
  392.     }
  393.     if (new_line == NULL)            /* out of memory */
  394.         break;
  395.     line_breakcheck();
  396.     }
  397.     if (got_int)
  398.     EMSG(_(e_interr));
  399.  
  400.     if (curbuf->b_p_ts != new_ts)
  401.     redraw_curbuf_later(NOT_VALID);
  402.     if (first_line != 0)
  403.     changed_lines(first_line, 0, last_line + 1, 0L);
  404.  
  405.     curwin->w_p_list = save_list;    /* restore 'list' */
  406.  
  407.     curbuf->b_p_ts = new_ts;
  408.     coladvance(curwin->w_curswant);
  409.  
  410.     u_clearline();
  411. }
  412. #endif
  413.  
  414. /*
  415.  * :move command - move lines line1-line2 to line dest
  416.  *
  417.  * return FAIL for failure, OK otherwise
  418.  */
  419.     int
  420. do_move(line1, line2, dest)
  421.     linenr_T    line1;
  422.     linenr_T    line2;
  423.     linenr_T    dest;
  424. {
  425.     char_u    *str;
  426.     linenr_T    l;
  427.     linenr_T    extra;        /* Num lines added before line1 */
  428.     linenr_T    num_lines;  /* Num lines moved */
  429.     linenr_T    last_line;  /* Last line in file after adding new text */
  430.  
  431.     if (dest >= line1 && dest < line2)
  432.     {
  433.     EMSG(_("E134: Move lines into themselves"));
  434.     return FAIL;
  435.     }
  436.  
  437.     num_lines = line2 - line1 + 1;
  438.  
  439.     /*
  440.      * First we copy the old text to its new location -- webb
  441.      * Also copy the flag that ":global" command uses.
  442.      */
  443.     if (u_save(dest, dest + 1) == FAIL)
  444.     return FAIL;
  445.     for (extra = 0, l = line1; l <= line2; l++)
  446.     {
  447.     str = vim_strsave(ml_get(l + extra));
  448.     if (str != NULL)
  449.     {
  450.         ml_append(dest + l - line1, str, (colnr_T)0, FALSE);
  451.         vim_free(str);
  452.         if (dest < line1)
  453.         extra++;
  454.     }
  455.     }
  456.  
  457.     /*
  458.      * Now we must be careful adjusting our marks so that we don't overlap our
  459.      * mark_adjust() calls.
  460.      *
  461.      * We adjust the marks within the old text so that they refer to the
  462.      * last lines of the file (temporarily), because we know no other marks
  463.      * will be set there since these line numbers did not exist until we added
  464.      * our new lines.
  465.      *
  466.      * Then we adjust the marks on lines between the old and new text positions
  467.      * (either forwards or backwards).
  468.      *
  469.      * And Finally we adjust the marks we put at the end of the file back to
  470.      * their final destination at the new text position -- webb
  471.      */
  472.     last_line = curbuf->b_ml.ml_line_count;
  473.     mark_adjust(line1, line2, last_line - line2, 0L);
  474.     if (dest >= line2)
  475.     {
  476.     mark_adjust(line2 + 1, dest, -num_lines, 0L);
  477.     curbuf->b_op_start.lnum = dest - num_lines + 1;
  478.     curbuf->b_op_end.lnum = dest;
  479.     }
  480.     else
  481.     {
  482.     mark_adjust(dest + 1, line1 - 1, num_lines, 0L);
  483.     curbuf->b_op_start.lnum = dest + 1;
  484.     curbuf->b_op_end.lnum = dest + num_lines;
  485.     }
  486.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  487.     mark_adjust(last_line - num_lines + 1, last_line,
  488.                          -(last_line - dest - extra), 0L);
  489.  
  490.     /*
  491.      * Now we delete the original text -- webb
  492.      */
  493.     if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
  494.     return FAIL;
  495.  
  496.     for (l = line1; l <= line2; l++)
  497.     ml_delete(line1 + extra, TRUE);
  498.  
  499.     if (!global_busy && num_lines > p_report)
  500.     {
  501.     if (num_lines == 1)
  502.         MSG(_("1 line moved"));
  503.     else
  504.         smsg((char_u *)_("%ld lines moved"), num_lines);
  505.     }
  506.  
  507.     /*
  508.      * Leave the cursor on the last of the moved lines.
  509.      */
  510.     if (dest >= line1)
  511.     curwin->w_cursor.lnum = dest;
  512.     else
  513.     curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
  514.  
  515.     if (line1 < dest)
  516.     changed_lines(line1, 0, dest + num_lines + 1, 0L);
  517.     else
  518.     changed_lines(dest + 1, 0, line1 + num_lines, 0L);
  519.  
  520.     return OK;
  521. }
  522.  
  523. /*
  524.  * ":copy"
  525.  */
  526.     void
  527. ex_copy(line1, line2, n)
  528.     linenr_T    line1;
  529.     linenr_T    line2;
  530.     linenr_T    n;
  531. {
  532.     linenr_T    count;
  533.     char_u    *p;
  534.  
  535.     count = line2 - line1 + 1;
  536.     curbuf->b_op_start.lnum = n + 1;
  537.     curbuf->b_op_end.lnum = n + count;
  538.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  539.  
  540.     /*
  541.      * there are three situations:
  542.      * 1. destination is above line1
  543.      * 2. destination is between line1 and line2
  544.      * 3. destination is below line2
  545.      *
  546.      * n = destination (when starting)
  547.      * curwin->w_cursor.lnum = destination (while copying)
  548.      * line1 = start of source (while copying)
  549.      * line2 = end of source (while copying)
  550.      */
  551.     if (u_save(n, n + 1) == FAIL)
  552.     return;
  553.  
  554.     curwin->w_cursor.lnum = n;
  555.     while (line1 <= line2)
  556.     {
  557.     /* need to use vim_strsave() because the line will be unlocked within
  558.      * ml_append() */
  559.     p = vim_strsave(ml_get(line1));
  560.     if (p != NULL)
  561.     {
  562.         ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
  563.         vim_free(p);
  564.     }
  565.     /* situation 2: skip already copied lines */
  566.     if (line1 == n)
  567.         line1 = curwin->w_cursor.lnum;
  568.     ++line1;
  569.     if (curwin->w_cursor.lnum < line1)
  570.         ++line1;
  571.     if (curwin->w_cursor.lnum < line2)
  572.         ++line2;
  573.     ++curwin->w_cursor.lnum;
  574.     }
  575.  
  576.     appended_lines_mark(n, count);
  577.  
  578.     msgmore((long)count);
  579. }
  580.  
  581. /*
  582.  * Handle the ":!cmd" command.    Also for ":r !cmd" and ":w !cmd"
  583.  * Bangs in the argument are replaced with the previously entered command.
  584.  * Remember the argument.
  585.  *
  586.  * RISCOS: Bangs only replaced when followed by a space, since many
  587.  * pathnames contain one.
  588.  */
  589.     void
  590. do_bang(addr_count, eap, forceit, do_in, do_out)
  591.     int        addr_count;
  592.     exarg_T    *eap;
  593.     int        forceit;
  594.     int        do_in, do_out;
  595. {
  596.     char_u        *arg = eap->arg;    /* command */
  597.     linenr_T        line1 = eap->line1;    /* start of range */
  598.     linenr_T        line2 = eap->line2;    /* end of range */
  599.     static char_u    *prevcmd = NULL;    /* the previous command */
  600.     char_u        *newcmd = NULL;        /* the new command */
  601.     int            free_newcmd = FALSE;    /* need to free() newcmd */
  602.     int            ins_prevcmd;
  603.     char_u        *t;
  604.     char_u        *p;
  605.     char_u        *trailarg;
  606.     int            len;
  607.     int            scroll_save = msg_scroll;
  608.  
  609.     /*
  610.      * Disallow shell commands for "rvim".
  611.      * Disallow shell commands from .exrc and .vimrc in current directory for
  612.      * security reasons.
  613.      */
  614.     if (check_restricted() || check_secure())
  615.     return;
  616.  
  617.     if (addr_count == 0)        /* :! */
  618.     {
  619.     msg_scroll = FALSE;        /* don't scroll here */
  620.     autowrite_all();
  621.     msg_scroll = scroll_save;
  622.     }
  623.  
  624.     /*
  625.      * Try to find an embedded bang, like in :!<cmd> ! [args]
  626.      * (:!! is indicated by the 'forceit' variable)
  627.      */
  628.     ins_prevcmd = forceit;
  629.     trailarg = arg;
  630.     do
  631.     {
  632.     len = (int)STRLEN(trailarg) + 1;
  633.     if (newcmd != NULL)
  634.         len += (int)STRLEN(newcmd);
  635.     if (ins_prevcmd)
  636.     {
  637.         if (prevcmd == NULL)
  638.         {
  639.         EMSG(_(e_noprev));
  640.         vim_free(newcmd);
  641.         return;
  642.         }
  643.         len += (int)STRLEN(prevcmd);
  644.     }
  645.     if ((t = alloc(len)) == NULL)
  646.     {
  647.         vim_free(newcmd);
  648.         return;
  649.     }
  650.     *t = NUL;
  651.     if (newcmd != NULL)
  652.         STRCAT(t, newcmd);
  653.     if (ins_prevcmd)
  654.         STRCAT(t, prevcmd);
  655.     p = t + STRLEN(t);
  656.     STRCAT(t, trailarg);
  657.     vim_free(newcmd);
  658.     newcmd = t;
  659.  
  660.     /*
  661.      * Scan the rest of the argument for '!', which is replaced by the
  662.      * previous command.  "\!" is replaced by "!" (this is vi compatible).
  663.      */
  664.     trailarg = NULL;
  665.     while (*p)
  666.     {
  667.         if (*p == '!'
  668. #ifdef RISCOS
  669.             && (p[1] == ' ' || p[1] == NUL)
  670. #endif
  671.                     )
  672.         {
  673.         if (p > newcmd && p[-1] == '\\')
  674.             mch_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
  675.         else
  676.         {
  677.             trailarg = p;
  678.             *trailarg++ = NUL;
  679.             ins_prevcmd = TRUE;
  680.             break;
  681.         }
  682.         }
  683.         ++p;
  684.     }
  685.     } while (trailarg != NULL);
  686.  
  687.     vim_free(prevcmd);
  688.     prevcmd = newcmd;
  689.  
  690.     if (bangredo)        /* put cmd in redo buffer for ! command */
  691.     {
  692.     AppendToRedobuffLit(prevcmd);
  693.     AppendToRedobuff((char_u *)"\n");
  694.     bangredo = FALSE;
  695.     }
  696.     /*
  697.      * Add quotes around the command, for shells that need them.
  698.      */
  699.     if (*p_shq != NUL)
  700.     {
  701.     newcmd = alloc((unsigned)(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1));
  702.     if (newcmd == NULL)
  703.         return;
  704.     STRCPY(newcmd, p_shq);
  705.     STRCAT(newcmd, prevcmd);
  706.     STRCAT(newcmd, p_shq);
  707.     free_newcmd = TRUE;
  708.     }
  709.     if (addr_count == 0)        /* :! */
  710.     {
  711.     /* echo the command */
  712.     msg_start();
  713.     msg_putchar(':');
  714.     msg_putchar('!');
  715.     msg_outtrans(newcmd);
  716.     msg_clr_eos();
  717.     windgoto(msg_row, msg_col);
  718.  
  719.     do_shell(newcmd, 0);
  720.     }
  721.     else                /* :range! */
  722.     /* Careful: This may recursively call do_bang() again! (because of
  723.      * autocommands) */
  724.     do_filter(line1, line2, eap, newcmd, do_in, do_out);
  725.     if (free_newcmd)
  726.     vim_free(newcmd);
  727. }
  728.  
  729. /*
  730.  * do_filter: filter lines through a command given by the user
  731.  *
  732.  * We use temp files and the call_shell() routine here. This would normally
  733.  * be done using pipes on a UNIX machine, but this is more portable to
  734.  * non-unix machines. The call_shell() routine needs to be able
  735.  * to deal with redirection somehow, and should handle things like looking
  736.  * at the PATH env. variable, and adding reasonable extensions to the
  737.  * command name given by the user. All reasonable versions of call_shell()
  738.  * do this.
  739.  * We use input redirection if do_in is TRUE.
  740.  * We use output redirection if do_out is TRUE.
  741.  */
  742.     static void
  743. do_filter(line1, line2, eap, cmd, do_in, do_out)
  744.     linenr_T    line1, line2;
  745.     exarg_T    *eap;        /* for forced 'ff' and 'fenc' */
  746.     char_u    *cmd;
  747.     int        do_in, do_out;
  748. {
  749.     char_u    *itmp = NULL;
  750.     char_u    *otmp = NULL;
  751.     linenr_T    linecount;
  752.     pos_T    cursor_save;
  753.     char_u    *cmd_buf;
  754. #ifdef FEAT_AUTOCMD
  755.     buf_T    *old_curbuf = curbuf;
  756. #endif
  757.  
  758.     if (*cmd == NUL)        /* no filter command */
  759.     return;
  760.  
  761. #ifdef WIN3264
  762.     /*
  763.      * Check if external commands are allowed now.
  764.      */
  765.     if (can_end_termcap_mode(TRUE) == FALSE)
  766.     return;
  767. #endif
  768.  
  769.     cursor_save = curwin->w_cursor;
  770.     linecount = line2 - line1 + 1;
  771.     curwin->w_cursor.lnum = line1;
  772.     curwin->w_cursor.col = 0;
  773.     changed_line_abv_curs();
  774.     invalidate_botline();
  775.  
  776.     /*
  777.      * 1. Form temp file names
  778.      * 2. Write the lines to a temp file
  779.      * 3. Run the filter command on the temp file
  780.      * 4. Read the output of the command into the buffer
  781.      * 5. Delete the original lines to be filtered
  782.      * 6. Remove the temp files
  783.      */
  784.  
  785.     if ((do_in && (itmp = vim_tempname('i')) == NULL)
  786.         || (do_out && (otmp = vim_tempname('o')) == NULL))
  787.     {
  788.     EMSG(_(e_notmp));
  789.     goto filterend;
  790.     }
  791.  
  792. /*
  793.  * The writing and reading of temp files will not be shown.
  794.  * Vi also doesn't do this and the messages are not very informative.
  795.  */
  796.     ++no_wait_return;        /* don't call wait_return() while busy */
  797.     if (do_in && buf_write(curbuf, itmp, NULL, line1, line2, eap,
  798.                        FALSE, FALSE, FALSE, TRUE) == FAIL)
  799.     {
  800.     msg_putchar('\n');        /* keep message from buf_write() */
  801.     --no_wait_return;
  802. #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
  803.     if (!aborting())
  804. #endif
  805.         (void)EMSG2(_(e_notcreate), itmp);    /* will call wait_return */
  806.     goto filterend;
  807.     }
  808. #ifdef FEAT_AUTOCMD
  809.     if (curbuf != old_curbuf)
  810.     goto filterend;
  811. #endif
  812.  
  813.     if (!do_out)
  814.     msg_putchar('\n');
  815.  
  816.     cmd_buf = make_filter_cmd(cmd, itmp, otmp);
  817.     if (cmd_buf == NULL)
  818.     goto filterend;
  819.  
  820.     windgoto((int)Rows - 1, 0);
  821.     cursor_on();
  822.  
  823.     /*
  824.      * When not redirecting the output the command can write anything to the
  825.      * screen. If 'shellredir' is equal to ">", screen may be messed up by
  826.      * stderr output of external command. Clear the screen later.
  827.      * If do_in is FALSE, this could be something like ":r !cat", which may
  828.      * also mess up the screen, clear it later.
  829.      */
  830.     if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
  831.     redraw_later_clear();
  832.  
  833.     /*
  834.      * When call_shell() fails wait_return() is called to give the user a
  835.      * chance to read the error messages. Otherwise errors are ignored, so you
  836.      * can see the error messages from the command that appear on stdout; use
  837.      * 'u' to fix the text
  838.      * Switch to cooked mode when not redirecting stdin, avoids that something
  839.      * like ":r !cat" hangs.
  840.      * Pass on the SHELL_DOOUT flag when the output is being redirected.
  841.      */
  842.     if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED
  843.                         | (do_out ? SHELL_DOOUT : 0)))
  844.     {
  845.     redraw_later_clear();
  846.     wait_return(FALSE);
  847.     }
  848.     vim_free(cmd_buf);
  849.  
  850.     did_check_timestamps = FALSE;
  851.     need_check_timestamps = TRUE;
  852.  
  853.     /* When interrupting the shell command, it may still have produced some
  854.      * useful output.  Reset got_int here, so that readfile() won't cancel
  855.      * reading. */
  856.     ui_breakcheck();
  857.     got_int = FALSE;
  858.  
  859.     if (do_out)
  860.     {
  861.     if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
  862.         goto error;
  863.     redraw_curbuf_later(VALID);
  864.     if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap,
  865.                              READ_FILTER) == FAIL)
  866.     {
  867. #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
  868.         if (!aborting())
  869. #endif
  870.         {
  871.         msg_putchar('\n');
  872.         EMSG2(_(e_notread), otmp);
  873.         }
  874.         goto error;
  875.     }
  876. #ifdef FEAT_AUTOCMD
  877.     if (curbuf != old_curbuf)
  878.         goto filterend;
  879. #endif
  880.  
  881.     if (do_in)
  882.     {
  883.         /*
  884.          * Put cursor on first filtered line for ":range!cmd".
  885.          * Adjust '[ and '] (set by buf_write()).
  886.          */
  887.         curwin->w_cursor.lnum = line1;
  888.         del_lines(linecount, TRUE);
  889.         curbuf->b_op_start.lnum -= linecount;    /* adjust '[ */
  890.         curbuf->b_op_end.lnum -= linecount;        /* adjust '] */
  891.         write_lnum_adjust(-linecount);        /* adjust last line
  892.                                for next write */
  893.     }
  894.     else
  895.     {
  896.         /*
  897.          * Put cursor on last new line for ":r !cmd".
  898.          */
  899.         curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
  900.         linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
  901.     }
  902.     beginline(BL_WHITE | BL_FIX);        /* cursor on first non-blank */
  903.     --no_wait_return;
  904.  
  905.     if (linecount > p_report)
  906.     {
  907.         if (do_in)
  908.         {
  909.         sprintf((char *)msg_buf, _("%ld lines filtered"),
  910.                                  (long)linecount);
  911.         if (msg(msg_buf) && !msg_scroll)
  912.         {
  913.             /* save message to display it after redraw */
  914.             set_keep_msg(msg_buf);
  915.             keep_msg_attr = 0;
  916.         }
  917.         }
  918.         else
  919.         msgmore((long)linecount);
  920.     }
  921.     }
  922.     else
  923.     {
  924. error:
  925.     /* put cursor back in same position for ":w !cmd" */
  926.     curwin->w_cursor = cursor_save;
  927.     --no_wait_return;
  928.     wait_return(FALSE);
  929.     }
  930.  
  931. filterend:
  932.  
  933. #ifdef FEAT_AUTOCMD
  934.     if (curbuf != old_curbuf)
  935.     {
  936.     --no_wait_return;
  937.     EMSG(_("E135: *Filter* Autocommands must not change current buffer"));
  938.     }
  939. #endif
  940.     if (itmp != NULL)
  941.     mch_remove(itmp);
  942.     if (otmp != NULL)
  943.     mch_remove(otmp);
  944.     vim_free(itmp);
  945.     vim_free(otmp);
  946. }
  947.  
  948. /*
  949.  * Call a shell to execute a command.
  950.  * When "cmd" is NULL start an interactive shell.
  951.  */
  952.     void
  953. do_shell(cmd, flags)
  954.     char_u    *cmd;
  955.     int        flags;    /* may be SHELL_DOOUT when output is redirected */
  956. {
  957.     buf_T    *buf;
  958. #ifndef FEAT_GUI_MSWIN
  959.     int        save_nwr;
  960. #endif
  961. #ifdef MSWIN
  962.     int        winstart = FALSE;
  963. #endif
  964.  
  965.     /*
  966.      * Disallow shell commands for "rvim".
  967.      * Disallow shell commands from .exrc and .vimrc in current directory for
  968.      * security reasons.
  969.      */
  970.     if (check_restricted() || check_secure())
  971.     {
  972.     msg_end();
  973.     return;
  974.     }
  975.  
  976. #ifdef MSWIN
  977.     /*
  978.      * Check if external commands are allowed now.
  979.      */
  980.     if (can_end_termcap_mode(TRUE) == FALSE)
  981.     return;
  982.  
  983.     /*
  984.      * Check if ":!start" is used.
  985.      */
  986.     if (cmd != NULL)
  987.     winstart = (STRNICMP(cmd, "start ", 6) == 0);
  988. #endif
  989.  
  990.     /*
  991.      * For autocommands we want to get the output on the current screen, to
  992.      * avoid having to type return below.
  993.      */
  994.     msg_putchar('\r');            /* put cursor at start of line */
  995. #ifdef FEAT_AUTOCMD
  996.     if (!autocmd_busy)
  997. #endif
  998.     {
  999. #ifdef MSWIN
  1000.     if (!winstart)
  1001. #endif
  1002.         stoptermcap();
  1003.     }
  1004. #ifdef MSWIN
  1005.     if (!winstart)
  1006. #endif
  1007.     msg_putchar('\n');        /* may shift screen one line up */
  1008.  
  1009.     /* warning message before calling the shell */
  1010.     if (p_warn
  1011. #ifdef FEAT_AUTOCMD
  1012.         && !autocmd_busy
  1013. #endif
  1014.         && msg_silent == 0)
  1015.     for (buf = firstbuf; buf; buf = buf->b_next)
  1016.         if (bufIsChanged(buf))
  1017.         {
  1018. #ifdef FEAT_GUI_MSWIN
  1019.         if (!winstart)
  1020.             starttermcap();    /* don't want a message box here */
  1021. #endif
  1022.         MSG_PUTS(_("[No write since last change]\n"));
  1023. #ifdef FEAT_GUI_MSWIN
  1024.         if (!winstart)
  1025.             stoptermcap();
  1026. #endif
  1027.         break;
  1028.         }
  1029.  
  1030.     /* This windgoto is required for when the '\n' resulted in a "delete line
  1031.      * 1" command to the terminal. */
  1032.     if (!swapping_screen())
  1033.     windgoto(msg_row, msg_col);
  1034.     cursor_on();
  1035.     (void)call_shell(cmd, SHELL_COOKED | flags);
  1036.     did_check_timestamps = FALSE;
  1037.     need_check_timestamps = TRUE;
  1038.  
  1039.     /*
  1040.      * put the message cursor at the end of the screen, avoids wait_return()
  1041.      * to overwrite the text that the external command showed
  1042.      */
  1043.     if (!swapping_screen())
  1044.     {
  1045.     msg_row = Rows - 1;
  1046.     msg_col = 0;
  1047.     }
  1048.  
  1049. #ifdef FEAT_AUTOCMD
  1050.     if (autocmd_busy)
  1051.     {
  1052.     if (msg_silent == 0)
  1053.         redraw_later_clear();
  1054.     }
  1055.     else
  1056. #endif
  1057.     {
  1058.     /*
  1059.      * For ":sh" there is no need to call wait_return(), just redraw.
  1060.      * Also for the Win32 GUI (the output is in a console window).
  1061.      * Otherwise there is probably text on the screen that the user wants
  1062.      * to read before redrawing, so call wait_return().
  1063.      */
  1064. #ifndef FEAT_GUI_MSWIN
  1065.     if (cmd == NULL
  1066. # ifdef WIN3264
  1067.         || (winstart && !need_wait_return)
  1068. # endif
  1069.        )
  1070.     {
  1071.         if (msg_silent == 0)
  1072.         redraw_later_clear();
  1073.         need_wait_return = FALSE;
  1074.     }
  1075.     else
  1076.     {
  1077.         /*
  1078.          * If we switch screens when starttermcap() is called, we really
  1079.          * want to wait for "hit return to continue".
  1080.          */
  1081.         save_nwr = no_wait_return;
  1082.         if (swapping_screen())
  1083.         no_wait_return = FALSE;
  1084. # ifdef AMIGA
  1085.         wait_return(term_console ? -1 : msg_silent == 0);    /* see below */
  1086. # else
  1087.         wait_return(msg_silent == 0);
  1088. # endif
  1089.         no_wait_return = save_nwr;
  1090.     }
  1091. #endif /* FEAT_GUI_W32 */
  1092.  
  1093. #ifdef MSWIN
  1094.     if (!winstart) /* if winstart==TRUE, never stopped termcap! */
  1095. #endif
  1096.         starttermcap();    /* start termcap if not done by wait_return() */
  1097.  
  1098.     /*
  1099.      * In an Amiga window redrawing is caused by asking the window size.
  1100.      * If we got an interrupt this will not work. The chance that the
  1101.      * window size is wrong is very small, but we need to redraw the
  1102.      * screen.  Don't do this if ':' hit in wait_return().    THIS IS UGLY
  1103.      * but it saves an extra redraw.
  1104.      */
  1105. #ifdef AMIGA
  1106.     if (skip_redraw)        /* ':' hit in wait_return() */
  1107.     {
  1108.         if (msg_silent == 0)
  1109.         redraw_later_clear();
  1110.     }
  1111.     else if (term_console)
  1112.     {
  1113.         OUT_STR(IF_EB("\033[0 q", ESC_STR "[0 q"));    /* get window size */
  1114.         if (got_int && msg_silent == 0)
  1115.         redraw_later_clear();    /* if got_int is TRUE, redraw needed */
  1116.         else
  1117.         must_redraw = 0;    /* no extra redraw needed */
  1118.     }
  1119. #endif
  1120.     }
  1121.  
  1122.     /* display any error messages now */
  1123.     display_errors();
  1124. }
  1125.  
  1126. /*
  1127.  * Create a shell command from a command string, input redirection file and
  1128.  * output redirection file.
  1129.  * Returns an allocated string with the shell command, or NULL for failure.
  1130.  */
  1131.     char_u *
  1132. make_filter_cmd(cmd, itmp, otmp)
  1133.     char_u    *cmd;        /* command */
  1134.     char_u    *itmp;        /* NULL or name of input file */
  1135.     char_u    *otmp;        /* NULL or name of output file */
  1136. {
  1137.     char_u    *buf;
  1138.     long_u    len;
  1139.  
  1140.     len = (long_u)STRLEN(cmd) + 3;            /* "()" + NUL */
  1141.     if (itmp != NULL)
  1142.     len += (long_u)STRLEN(itmp) + 9;        /* " { < " + " } " */
  1143.     if (otmp != NULL)
  1144.     len += (long_u)STRLEN(otmp) + (long_u)STRLEN(p_srr) + 2; /* "  " */
  1145.     buf = lalloc(len, TRUE);
  1146.     if (buf == NULL)
  1147.     return NULL;
  1148.  
  1149. #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
  1150.     /*
  1151.      * put braces around the command (for concatenated commands)
  1152.      */
  1153.     sprintf((char *)buf, "(%s)", (char *)cmd);
  1154.     if (itmp != NULL)
  1155.     {
  1156.     STRCAT(buf, " < ");
  1157.     STRCAT(buf, itmp);
  1158.     }
  1159. #else
  1160.     /*
  1161.      * for shells that don't understand braces around commands, at least allow
  1162.      * the use of commands in a pipe.
  1163.      */
  1164.     STRCPY(buf, cmd);
  1165.     if (itmp != NULL)
  1166.     {
  1167.     char_u    *p;
  1168.  
  1169.     /*
  1170.      * If there is a pipe, we have to put the '<' in front of it.
  1171.      * Don't do this when 'shellquote' is not empty, otherwise the
  1172.      * redirection would be inside the quotes.
  1173.      */
  1174.     if (*p_shq == NUL)
  1175.     {
  1176.         p = vim_strchr(buf, '|');
  1177.         if (p != NULL)
  1178.         *p = NUL;
  1179.     }
  1180. # ifdef RISCOS
  1181.     STRCAT(buf, " { < ");    /* Use RISC OS notation for input. */
  1182.     STRCAT(buf, itmp);
  1183.     STRCAT(buf, " } ");
  1184. # else
  1185.     STRCAT(buf, " <");    /* " < " causes problems on Amiga */
  1186.     STRCAT(buf, itmp);
  1187. # endif
  1188.     if (*p_shq == NUL)
  1189.     {
  1190.         p = vim_strchr(cmd, '|');
  1191.         if (p != NULL)
  1192.         {
  1193.         STRCAT(buf, " ");   /* insert a space before the '|' for DOS */
  1194.         STRCAT(buf, p);
  1195.         }
  1196.     }
  1197.     }
  1198. #endif
  1199.     if (otmp != NULL)
  1200.     append_redir(buf, p_srr, otmp);
  1201.  
  1202.     return buf;
  1203. }
  1204.  
  1205. /*
  1206.  * Append output redirection for file "fname" to the end of string buffer "buf"
  1207.  * Works with the 'shellredir' and 'shellpipe' options.
  1208.  * The caller should make sure that there is enough room:
  1209.  *    STRLEN(opt) + STRLEN(fname) + 3
  1210.  */
  1211.     void
  1212. append_redir(buf, opt, fname)
  1213.     char_u    *buf;
  1214.     char_u    *opt;
  1215.     char_u    *fname;
  1216. {
  1217.     char_u    *p;
  1218.  
  1219.     buf += STRLEN(buf);
  1220.     /* find "%s", skipping "%%" */
  1221.     for (p = opt; (p = vim_strchr(p, '%')) != NULL; ++p)
  1222.     if (p[1] == 's')
  1223.         break;
  1224.     if (p != NULL)
  1225.     {
  1226.     *buf = ' '; /* not really needed? Not with sh, ksh or bash */
  1227.     sprintf((char *)buf + 1, (char *)opt, (char *)fname);
  1228.     }
  1229.     else
  1230.     sprintf((char *)buf,
  1231. #ifdef FEAT_QUICKFIX
  1232. # ifndef RISCOS
  1233.         opt != p_sp ? " %s%s" :
  1234. # endif
  1235.         " %s %s",
  1236. #else
  1237. # ifndef RISCOS
  1238.         " %s%s",    /* " > %s" causes problems on Amiga */
  1239. # else
  1240.         " %s %s",    /* But is needed for 'shellpipe' and RISC OS */
  1241. # endif
  1242. #endif
  1243.         (char *)opt, (char *)fname);
  1244. }
  1245.  
  1246. #ifdef FEAT_VIMINFO
  1247.  
  1248. static int no_viminfo __ARGS((void));
  1249. static int  viminfo_errcnt;
  1250.  
  1251.     static int
  1252. no_viminfo()
  1253. {
  1254.     /* "vim -i NONE" does not read or write a viminfo file */
  1255.     return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
  1256. }
  1257.  
  1258. /*
  1259.  * Report an error for reading a viminfo file.
  1260.  * Count the number of errors.    When there are more than 10, return TRUE.
  1261.  */
  1262.     int
  1263. viminfo_error(errnum, message, line)
  1264.     char    *errnum;
  1265.     char    *message;
  1266.     char_u  *line;
  1267. {
  1268.     sprintf((char *)IObuff, _("%sviminfo: %s in line: "), errnum, message);
  1269.     STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
  1270.     emsg(IObuff);
  1271.     if (++viminfo_errcnt >= 10)
  1272.     {
  1273.     EMSG(_("E136: viminfo: Too many errors, skipping rest of file"));
  1274.     return TRUE;
  1275.     }
  1276.     return FALSE;
  1277. }
  1278.  
  1279. /*
  1280.  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
  1281.  * set are not over-written unless force is TRUE. -- webb
  1282.  */
  1283.     int
  1284. read_viminfo(file, want_info, want_marks, forceit)
  1285.     char_u    *file;
  1286.     int        want_info;
  1287.     int        want_marks;
  1288.     int        forceit;
  1289. {
  1290.     FILE    *fp;
  1291.     char_u    *fname;
  1292.  
  1293.     if (no_viminfo())
  1294.     return FAIL;
  1295.  
  1296.     fname = viminfo_filename(file);        /* may set to default if NULL */
  1297.     if (fname == NULL)
  1298.     return FAIL;
  1299.     fp = mch_fopen((char *)fname, READBIN);
  1300.  
  1301.     if (p_verbose > 0)
  1302.     {
  1303.     char_u    *s;
  1304.  
  1305.     s = fname;
  1306.     if (STRLEN(fname) > IOSIZE - 100)
  1307.         s = fname + STRLEN(fname) - (IOSIZE - 100);
  1308.     smsg((char_u *)_("Reading viminfo file \"%s\"%s%s%s"), s,
  1309.             want_info ? _(" info") : "",
  1310.             want_marks ? _(" marks") : "",
  1311.             fp == NULL ? _(" FAILED") : "");
  1312.     }
  1313.  
  1314.     vim_free(fname);
  1315.     if (fp == NULL)
  1316.     return FAIL;
  1317.  
  1318.     viminfo_errcnt = 0;
  1319.     do_viminfo(fp, NULL, want_info, want_marks, forceit);
  1320.  
  1321.     fclose(fp);
  1322.  
  1323.     return OK;
  1324. }
  1325.  
  1326. /*
  1327.  * write_viminfo() -- Write the viminfo file.  The old one is read in first so
  1328.  * that effectively a merge of current info and old info is done.  This allows
  1329.  * multiple vims to run simultaneously, without losing any marks etc.  If
  1330.  * forceit is TRUE, then the old file is not read in, and only internal info is
  1331.  * written to the file. -- webb
  1332.  */
  1333.     void
  1334. write_viminfo(file, forceit)
  1335.     char_u    *file;
  1336.     int        forceit;
  1337. {
  1338.     char_u    *fname;
  1339.     FILE    *fp_in = NULL;    /* input viminfo file, if any */
  1340.     FILE    *fp_out = NULL;    /* output viminfo file */
  1341.     char_u    *tempname = NULL;    /* name of temp viminfo file */
  1342.     struct stat    st_new;        /* mch_stat() of potential new file */
  1343.     char_u    *wp;
  1344. #if defined(UNIX) || defined(VMS)
  1345.     mode_t    umask_save;
  1346. #endif
  1347. #ifdef UNIX
  1348.     int        shortname = FALSE;    /* use 8.3 file name */
  1349.     struct stat    st_old;        /* mch_stat() of existing viminfo file */
  1350. #endif
  1351.  
  1352.     if (no_viminfo())
  1353.     return;
  1354.  
  1355.     fname = viminfo_filename(file);    /* may set to default if NULL */
  1356.     if (fname == NULL)
  1357.     return;
  1358.  
  1359.     fp_in = mch_fopen((char *)fname, READBIN);
  1360.     if (fp_in == NULL)
  1361.     {
  1362.     /* if it does exist, but we can't read it, don't try writing */
  1363.     if (mch_stat((char *)fname, &st_new) == 0)
  1364.         goto end;
  1365. #if defined(UNIX) || defined(VMS)
  1366.     /*
  1367.      * For Unix we create the .viminfo non-accessible for others,
  1368.      * because it may contain text from non-accessible documents.
  1369.      */
  1370.     umask_save = umask(077);
  1371. #endif
  1372.     fp_out = mch_fopen((char *)fname, WRITEBIN);
  1373. #if defined(UNIX) || defined(VMS)
  1374.     (void)umask(umask_save);
  1375. #endif
  1376.     }
  1377.     else
  1378.     {
  1379.     /*
  1380.      * There is an existing viminfo file.  Create a temporary file to
  1381.      * write the new viminfo into, in the same directory as the
  1382.      * existing viminfo file, which will be renamed later.
  1383.      */
  1384. #ifdef UNIX
  1385.     /*
  1386.      * For Unix we check the owner of the file.  It's not very nice to
  1387.      * overwrite a user's viminfo file after a "su root", with a
  1388.      * viminfo file that the user can't read.
  1389.      */
  1390.     st_old.st_dev = st_old.st_ino = 0;
  1391.     st_old.st_mode = 0600;
  1392.     if (mch_stat((char *)fname, &st_old) == 0 && getuid() &&
  1393.         !(st_old.st_uid == getuid()
  1394.             ? (st_old.st_mode & 0200)
  1395.             : (st_old.st_gid == getgid()
  1396.                 ? (st_old.st_mode & 0020)
  1397.                 : (st_old.st_mode & 0002))))
  1398.     {
  1399.         int    tt;
  1400.  
  1401.         /* avoid a wait_return for this message, it's annoying */
  1402.         tt = msg_didany;
  1403.         EMSG2(_("E137: Viminfo file is not writable: %s"), fname);
  1404.         msg_didany = tt;
  1405.         goto end;
  1406.     }
  1407. #endif
  1408.  
  1409.     /*
  1410.      * Make tempname.
  1411.      * May try twice: Once normal and once with shortname set, just in
  1412.      * case somebody puts his viminfo file in an 8.3 filesystem.
  1413.      */
  1414.     for (;;)
  1415.     {
  1416.         tempname = buf_modname(
  1417. #ifdef UNIX
  1418.                     shortname,
  1419. #else
  1420. # ifdef SHORT_FNAME
  1421.                     TRUE,
  1422. # else
  1423. #  ifdef FEAT_GUI_W32
  1424.                     gui_is_win32s(),
  1425. #  else
  1426.                     FALSE,
  1427. #  endif
  1428. # endif
  1429. #endif
  1430.                     fname,
  1431. #ifdef VMS
  1432.                     (char_u *)"-tmp",
  1433. #else
  1434. # ifdef RISCOS
  1435.                     (char_u *)"/tmp",
  1436. # else
  1437.                     (char_u *)".tmp",
  1438. # endif
  1439. #endif
  1440.                     FALSE);
  1441.         if (tempname == NULL)        /* out of memory */
  1442.         break;
  1443.  
  1444.         /*
  1445.          * Check if tempfile already exists.  Never overwrite an
  1446.          * existing file!
  1447.          */
  1448.         if (mch_stat((char *)tempname, &st_new) == 0)
  1449.         {
  1450. #ifdef UNIX
  1451.         /*
  1452.          * Check if tempfile is same as original file.  May happen
  1453.          * when modname() gave the same file back.  E.g.  silly
  1454.          * link, or file name-length reached.  Try again with
  1455.          * shortname set.
  1456.          */
  1457.         if (!shortname && st_new.st_dev == st_old.st_dev &&
  1458.             st_new.st_ino == st_old.st_ino)
  1459.         {
  1460.             vim_free(tempname);
  1461.             tempname = NULL;
  1462.             shortname = TRUE;
  1463.             continue;
  1464.         }
  1465. #endif
  1466.         /*
  1467.          * Try another name.  Change one character, just before
  1468.          * the extension.  This should also work for an 8.3
  1469.          * file name, when after adding the extension it still is
  1470.          * the same file as the original.
  1471.          */
  1472.         wp = tempname + STRLEN(tempname) - 5;
  1473.         if (wp < gettail(tempname))        /* empty file name? */
  1474.             wp = gettail(tempname);
  1475.         for (*wp = 'z'; mch_stat((char *)tempname, &st_new) == 0;
  1476.                                     --*wp)
  1477.         {
  1478.             /*
  1479.              * They all exist?  Must be something wrong! Don't
  1480.              * write the viminfo file then.
  1481.              */
  1482.             if (*wp == 'a')
  1483.             {
  1484.             vim_free(tempname);
  1485.             tempname = NULL;
  1486.             break;
  1487.             }
  1488.         }
  1489.         }
  1490.         break;
  1491.     }
  1492.  
  1493.     if (tempname != NULL)
  1494.     {
  1495.         fp_out = mch_fopen((char *)tempname, WRITEBIN);
  1496.  
  1497.         /*
  1498.          * If we can't create in the same directory, try creating a
  1499.          * "normal" temp file.
  1500.          */
  1501.         if (fp_out == NULL)
  1502.         {
  1503.         vim_free(tempname);
  1504.         if ((tempname = vim_tempname('o')) != NULL)
  1505.             fp_out = mch_fopen((char *)tempname, WRITEBIN);
  1506.         }
  1507. #ifdef UNIX
  1508.         /*
  1509.          * Set file protection same as original file, but strip s-bit
  1510.          * and make sure the owner can read/write it.
  1511.          */
  1512.         if (fp_out != NULL)
  1513.         {
  1514.         (void)mch_setperm(tempname,
  1515.                   (long)((st_old.st_mode & 0777) | 0600));
  1516.         /* this only works for root: */
  1517.         (void)chown((char *)tempname, st_old.st_uid, st_old.st_gid);
  1518.         }
  1519. #endif
  1520.     }
  1521.     }
  1522.  
  1523.     /*
  1524.      * Check if the new viminfo file can be written to.
  1525.      */
  1526.     if (fp_out == NULL)
  1527.     {
  1528.     EMSG2(_("E138: Can't write viminfo file %s!"),
  1529.                         fp_in == NULL ? fname : tempname);
  1530.     if (fp_in != NULL)
  1531.         fclose(fp_in);
  1532.     goto end;
  1533.     }
  1534.  
  1535.     if (p_verbose > 0)
  1536.     msg_str((char_u *)_("Writing viminfo file \"%s\""), fname);
  1537.  
  1538.     viminfo_errcnt = 0;
  1539.     do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
  1540.  
  1541.     fclose(fp_out);        /* errors are ignored !? */
  1542.     if (fp_in != NULL)
  1543.     {
  1544.     fclose(fp_in);
  1545.     /*
  1546.      * In case of an error, don't overwrite the original viminfo file.
  1547.      */
  1548.     if (viminfo_errcnt || vim_rename(tempname, fname) == -1)
  1549.         mch_remove(tempname);
  1550.     }
  1551. end:
  1552.     vim_free(fname);
  1553.     vim_free(tempname);
  1554. }
  1555.  
  1556. /*
  1557.  * Get the viminfo file name to use.
  1558.  * If "file" is given and not empty, use it (has already been expanded by
  1559.  * cmdline functions).
  1560.  * Otherwise use "-i file_name", value from 'viminfo' or the default, and
  1561.  * expand environment variables.
  1562.  * Returns an allocated string.  NULL when out of memory.
  1563.  */
  1564.     static char_u *
  1565. viminfo_filename(file)
  1566.     char_u    *file;
  1567. {
  1568.     if (file == NULL || *file == NUL)
  1569.     {
  1570.     if (use_viminfo != NULL)
  1571.         file = use_viminfo;
  1572.     else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
  1573.     {
  1574. #ifdef VIMINFO_FILE2
  1575.         /* don't use $HOME when not defined (turned into "c:/"!). */
  1576. # ifdef VMS
  1577.         if (mch_getenv((char_u *)"SYS$LOGIN") == NULL)
  1578. # else
  1579.         if (mch_getenv((char_u *)"HOME") == NULL)
  1580. # endif
  1581.         {
  1582.         /* don't use $VIM when not available. */
  1583.         expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
  1584.         if (STRCMP("$VIM", NameBuff) != 0)  /* $VIM was expanded */
  1585.             file = (char_u *)VIMINFO_FILE2;
  1586.         else
  1587.             file = (char_u *)VIMINFO_FILE;
  1588.         }
  1589.         else
  1590. #endif
  1591.         file = (char_u *)VIMINFO_FILE;
  1592.     }
  1593.     expand_env(file, NameBuff, MAXPATHL);
  1594.     file = NameBuff;
  1595.     }
  1596.     return vim_strsave(file);
  1597. }
  1598.  
  1599. /*
  1600.  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
  1601.  */
  1602.     static void
  1603. do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
  1604.     FILE    *fp_in;
  1605.     FILE    *fp_out;
  1606.     int        want_info;
  1607.     int        want_marks;
  1608.     int        force_read;
  1609. {
  1610.     int        count = 0;
  1611.     int        eof = FALSE;
  1612.     vir_T    vir;
  1613.  
  1614.     if ((vir.vir_line = alloc(LSIZE)) == NULL)
  1615.     return;
  1616.     vir.vir_fd = fp_in;
  1617. #ifdef FEAT_MBYTE
  1618.     vir.vir_conv.vc_type = CONV_NONE;
  1619. #endif
  1620.  
  1621.     if (fp_in != NULL)
  1622.     {
  1623.     if (want_info)
  1624.         eof = read_viminfo_up_to_marks(&vir, force_read, fp_out != NULL);
  1625.     else
  1626.         /* Skip info, find start of marks */
  1627.         while (!(eof = viminfo_readline(&vir))
  1628.             && vir.vir_line[0] != '>')
  1629.         ;
  1630.     }
  1631.     if (fp_out != NULL)
  1632.     {
  1633.     /* Write the info: */
  1634.     fprintf(fp_out, _("# This viminfo file was generated by Vim %s.\n"),
  1635.                               VIM_VERSION_MEDIUM);
  1636.     fprintf(fp_out, _("# You may edit it if you're careful!\n\n"));
  1637. #ifdef FEAT_MBYTE
  1638.     fprintf(fp_out, _("# Value of 'encoding' when this file was written\n"));
  1639.     fprintf(fp_out, "*encoding=%s\n\n", p_enc);
  1640. #endif
  1641.     write_viminfo_search_pattern(fp_out);
  1642.     write_viminfo_sub_string(fp_out);
  1643. #ifdef FEAT_CMDHIST
  1644.     write_viminfo_history(fp_out);
  1645. #endif
  1646.     write_viminfo_registers(fp_out);
  1647. #ifdef FEAT_EVAL
  1648.     write_viminfo_varlist(fp_out);
  1649. #endif
  1650.     write_viminfo_filemarks(fp_out);
  1651.     write_viminfo_bufferlist(fp_out);
  1652.     count = write_viminfo_marks(fp_out);
  1653.     }
  1654.     if (fp_in != NULL && want_marks)
  1655.     copy_viminfo_marks(&vir, fp_out, count, eof);
  1656.  
  1657.     vim_free(vir.vir_line);
  1658. #ifdef FEAT_MBYTE
  1659.     if (vir.vir_conv.vc_type != CONV_NONE)
  1660.     convert_setup(&vir.vir_conv, NULL, NULL);
  1661. #endif
  1662. }
  1663.  
  1664. /*
  1665.  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
  1666.  * first part of the viminfo file which contains everything but the marks that
  1667.  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
  1668.  */
  1669.     static int
  1670. read_viminfo_up_to_marks(virp, forceit, writing)
  1671.     vir_T    *virp;
  1672.     int        forceit;
  1673.     int        writing;
  1674. {
  1675.     int        eof;
  1676.     buf_T    *buf;
  1677.  
  1678. #ifdef FEAT_CMDHIST
  1679.     prepare_viminfo_history(forceit ? 9999 : 0);
  1680. #endif
  1681.     eof = viminfo_readline(virp);
  1682.     while (!eof && virp->vir_line[0] != '>')
  1683.     {
  1684.     switch (virp->vir_line[0])
  1685.     {
  1686.         /* Characters reserved for future expansion, ignored now */
  1687.         case '+': /* "+40 /path/dir file", for running vim without args */
  1688.         case '|': /* to be defined */
  1689.         case '^': /* to be defined */
  1690.         case '<': /* long line - ignored */
  1691.         /* A comment or empty line. */
  1692.         case NUL:
  1693.         case '\r':
  1694.         case '\n':
  1695.         case '#':
  1696.         eof = viminfo_readline(virp);
  1697.         break;
  1698.         case '*': /* "*encoding=value" */
  1699.         eof = viminfo_encoding(virp);
  1700.         break;
  1701.         case '!': /* global variable */
  1702. #ifdef FEAT_EVAL
  1703.         eof = read_viminfo_varlist(virp, writing);
  1704. #else
  1705.         eof = viminfo_readline(virp);
  1706. #endif
  1707.         break;
  1708.         case '%': /* entry for buffer list */
  1709.         eof = read_viminfo_bufferlist(virp, writing);
  1710.         break;
  1711.         case '"':
  1712.         eof = read_viminfo_register(virp, forceit);
  1713.         break;
  1714.         case '/':        /* Search string */
  1715.         case '&':        /* Substitute search string */
  1716.         case '~':        /* Last search string, followed by '/' or '&' */
  1717.         eof = read_viminfo_search_pattern(virp, forceit);
  1718.         break;
  1719.         case '$':
  1720.         eof = read_viminfo_sub_string(virp, forceit);
  1721.         break;
  1722.         case ':':
  1723.         case '?':
  1724.         case '=':
  1725.         case '@':
  1726. #ifdef FEAT_CMDHIST
  1727.         eof = read_viminfo_history(virp);
  1728. #else
  1729.         eof = viminfo_readline(virp);
  1730. #endif
  1731.         break;
  1732.         case '-':
  1733.         case '\'':
  1734.         eof = read_viminfo_filemark(virp, forceit);
  1735.         break;
  1736.         default:
  1737.         if (viminfo_error("E575: ", _("Illegal starting char"),
  1738.                 virp->vir_line))
  1739.             eof = TRUE;
  1740.         else
  1741.             eof = viminfo_readline(virp);
  1742.         break;
  1743.     }
  1744.     }
  1745.  
  1746. #ifdef FEAT_CMDHIST
  1747.     /* Finish reading history items. */
  1748.     finish_viminfo_history();
  1749. #endif
  1750.  
  1751.     /* Change file names to buffer numbers for fmarks. */
  1752.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  1753.     fmarks_check_names(buf);
  1754.  
  1755.     return eof;
  1756. }
  1757.  
  1758. /*
  1759.  * Compare the 'encoding' value in the viminfo file with the current value of
  1760.  * 'encoding'.  If different and the 'c' flag is in 'viminfo', setup for
  1761.  * conversion of text with iconv() in viminfo_readstring().
  1762.  */
  1763.     static int
  1764. viminfo_encoding(virp)
  1765.     vir_T    *virp;
  1766. {
  1767. #ifdef FEAT_MBYTE
  1768.     char_u    *p;
  1769.     int        i;
  1770.  
  1771.     if (get_viminfo_parameter('c') != 0)
  1772.     {
  1773.     p = vim_strchr(virp->vir_line, '=');
  1774.     if (p != NULL)
  1775.     {
  1776.         /* remove trailing newline */
  1777.         ++p;
  1778.         for (i = 0; vim_isprintc(p[i]); ++i)
  1779.         ;
  1780.         p[i] = NUL;
  1781.  
  1782.         convert_setup(&virp->vir_conv, p, p_enc);
  1783.     }
  1784.     }
  1785. #endif
  1786.     return viminfo_readline(virp);
  1787. }
  1788.  
  1789. /*
  1790.  * Read a line from the viminfo file.
  1791.  * Returns TRUE for end-of-file;
  1792.  */
  1793.     int
  1794. viminfo_readline(virp)
  1795.     vir_T    *virp;
  1796. {
  1797.     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
  1798. }
  1799.  
  1800. /*
  1801.  * check string read from viminfo file
  1802.  * remove '\n' at the end of the line
  1803.  * - replace CTRL-V CTRL-V with CTRL-V
  1804.  * - replace CTRL-V 'n'    with '\n'
  1805.  *
  1806.  * Check for a long line as written by viminfo_writestring().
  1807.  *
  1808.  * Return the string in allocated memory (NULL when out of memory).
  1809.  */
  1810. /*ARGSUSED*/
  1811.     char_u *
  1812. viminfo_readstring(virp, off, convert)
  1813.     vir_T    *virp;
  1814.     int        off;            /* offset for virp->vir_line */
  1815.     int        convert;        /* convert the string */
  1816. {
  1817.     char_u    *retval;
  1818.     char_u    *s, *d;
  1819.     long    len;
  1820.  
  1821.     if (virp->vir_line[off] == Ctrl_V && isdigit(virp->vir_line[off + 1]))
  1822.     {
  1823.     len = atol((char *)virp->vir_line + off + 1);
  1824.     retval = lalloc(len, TRUE);
  1825.     if (retval == NULL)
  1826.     {
  1827.         /* Line too long?  File messed up?  Skip next line. */
  1828.         (void)vim_fgets(virp->vir_line, 10, virp->vir_fd);
  1829.         return NULL;
  1830.     }
  1831.     (void)vim_fgets(retval, (int)len, virp->vir_fd);
  1832.     s = retval + 1;        /* Skip the leading '<' */
  1833.     }
  1834.     else
  1835.     {
  1836.     retval = vim_strsave(virp->vir_line + off);
  1837.     if (retval == NULL)
  1838.         return NULL;
  1839.     s = retval;
  1840.     }
  1841.  
  1842.     /* Change CTRL-V CTRL-V to CTRL-V and CTRL-V n to \n in-place. */
  1843.     d = retval;
  1844.     while (*s != NUL && *s != '\n')
  1845.     {
  1846.     if (s[0] == Ctrl_V && s[1] != NUL)
  1847.     {
  1848.         if (s[1] == 'n')
  1849.         *d++ = '\n';
  1850.         else
  1851.         *d++ = Ctrl_V;
  1852.         s += 2;
  1853.     }
  1854.     else
  1855.         *d++ = *s++;
  1856.     }
  1857.     *d = NUL;
  1858.  
  1859. #ifdef FEAT_MBYTE
  1860.     if (convert && virp->vir_conv.vc_type != CONV_NONE && *retval != NUL)
  1861.     {
  1862.     d = string_convert(&virp->vir_conv, retval, NULL);
  1863.     if (d != NULL)
  1864.     {
  1865.         vim_free(retval);
  1866.         retval = d;
  1867.     }
  1868.     }
  1869. #endif
  1870.  
  1871.     return retval;
  1872. }
  1873.  
  1874. /*
  1875.  * write string to viminfo file
  1876.  * - replace CTRL-V with CTRL-V CTRL-V
  1877.  * - replace '\n'   with CTRL-V 'n'
  1878.  * - add a '\n' at the end
  1879.  *
  1880.  * For a long line:
  1881.  * - write " CTRL-V <length> \n " in first line
  1882.  * - write " < <string> \n "      in second line
  1883.  */
  1884.     void
  1885. viminfo_writestring(fd, p)
  1886.     FILE    *fd;
  1887.     char_u    *p;
  1888. {
  1889.     int        c;
  1890.     char_u    *s;
  1891.     int        len = 0;
  1892.  
  1893.     for (s = p; *s != NUL; ++s)
  1894.     {
  1895.     if (*s == Ctrl_V || *s == '\n')
  1896.         ++len;
  1897.     ++len;
  1898.     }
  1899.  
  1900.     /* If the string will be too long, write its length and put it in the next
  1901.      * line.  Take into account that some room is needed for what comes before
  1902.      * the string (e.g., variable name).  Add something to the length for the
  1903.      * '<', NL and trailing NUL. */
  1904.     if (len > LSIZE / 2)
  1905.     fprintf(fd, IF_EB("\026%d\n<", CTRL_V_STR "%d\n<"), len + 3);
  1906.  
  1907.     while ((c = *p++) != NUL)
  1908.     {
  1909.     if (c == Ctrl_V || c == '\n')
  1910.     {
  1911.         putc(Ctrl_V, fd);
  1912.         if (c == '\n')
  1913.         c = 'n';
  1914.     }
  1915.     putc(c, fd);
  1916.     }
  1917.     putc('\n', fd);
  1918. }
  1919. #endif /* FEAT_VIMINFO */
  1920.  
  1921. /*
  1922.  * Implementation of ":fixdel", also used by get_stty().
  1923.  *  <BS>    resulting <Del>
  1924.  *   ^?        ^H
  1925.  * not ^?    ^?
  1926.  */
  1927. /*ARGSUSED*/
  1928.     void
  1929. do_fixdel(eap)
  1930.     exarg_T    *eap;
  1931. {
  1932.     char_u  *p;
  1933.  
  1934.     p = find_termcode((char_u *)"kb");
  1935.     add_termcode((char_u *)"kD", p != NULL
  1936.         && *p == DEL ? (char_u *)CTRL_H_STR : DEL_STR, FALSE);
  1937. }
  1938.  
  1939.     void
  1940. print_line_no_prefix(lnum, use_number)
  1941.     linenr_T    lnum;
  1942.     int        use_number;
  1943. {
  1944.     char_u    numbuf[20];
  1945.  
  1946.     if (curwin->w_p_nu || use_number)
  1947.     {
  1948.     sprintf((char *)numbuf, "%7ld ", (long)lnum);
  1949.     msg_puts_attr(numbuf, hl_attr(HLF_N));    /* Highlight line nrs */
  1950.     }
  1951.     msg_prt_line(ml_get(lnum));
  1952. }
  1953.  
  1954. /*
  1955.  * Print a text line.  Also in silent mode ("ex -s").
  1956.  */
  1957.     void
  1958. print_line(lnum, use_number)
  1959.     linenr_T    lnum;
  1960.     int        use_number;
  1961. {
  1962.     int        save_silent = silent_mode;
  1963.  
  1964.     silent_mode = FALSE;
  1965.     msg_start();
  1966.     print_line_no_prefix(lnum, use_number);
  1967.     if (save_silent)
  1968.     {
  1969.     msg_putchar('\n');
  1970.     cursor_on();        /* msg_start() switches it off */
  1971.     out_flush();
  1972.     silent_mode = save_silent;
  1973.     }
  1974. }
  1975.  
  1976. /*
  1977.  * ":file[!] [fname]".
  1978.  */
  1979.     void
  1980. ex_file(eap)
  1981.     exarg_T    *eap;
  1982. {
  1983.     char_u    *fname, *sfname, *xfname;
  1984.     buf_T    *buf;
  1985.  
  1986.     if (*eap->arg != NUL)
  1987.     {
  1988. #ifdef FEAT_AUTOCMD
  1989.     buf = curbuf;
  1990.     apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
  1991.     /* buffer changed, don't change name now */
  1992.     if (buf != curbuf)
  1993.         return;
  1994. # ifdef FEAT_EVAL
  1995.     if (aborting())        /* autocmds may abort script processing */
  1996.         return;
  1997. # endif
  1998. #endif
  1999.     /*
  2000.      * The name of the current buffer will be changed.
  2001.      * A new (unlisted) buffer entry needs to be made to hold the old file
  2002.      * name, which will become the alternate file name.
  2003.      */
  2004.     fname = curbuf->b_ffname;
  2005.     sfname = curbuf->b_sfname;
  2006.     xfname = curbuf->b_fname;
  2007.     curbuf->b_ffname = NULL;
  2008.     curbuf->b_sfname = NULL;
  2009.     if (setfname(eap->arg, NULL, TRUE) == FAIL)
  2010.     {
  2011.         curbuf->b_ffname = fname;
  2012.         curbuf->b_sfname = sfname;
  2013.         return;
  2014.     }
  2015.     curbuf->b_flags |= BF_NOTEDITED;
  2016.     buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0);
  2017.     if (buf != NULL)
  2018.         curwin->w_alt_fnum = buf->b_fnum;
  2019.     vim_free(fname);
  2020.     vim_free(sfname);
  2021. #ifdef FEAT_AUTOCMD
  2022.     apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
  2023. #endif
  2024.     }
  2025.     /* print full file name if :cd used */
  2026.     fileinfo(FALSE, FALSE, eap->forceit);
  2027. }
  2028.  
  2029. /*
  2030.  * ":update".
  2031.  */
  2032.     void
  2033. ex_update(eap)
  2034.     exarg_T    *eap;
  2035. {
  2036.     if (curbufIsChanged())
  2037.     (void)do_write(eap);
  2038. }
  2039.  
  2040. /*
  2041.  * ":write" and ":saveas".
  2042.  */
  2043.     void
  2044. ex_write(eap)
  2045.     exarg_T    *eap;
  2046. {
  2047.     if (eap->usefilter)        /* input lines to shell command */
  2048.     do_bang(1, eap, FALSE, TRUE, FALSE);
  2049.     else
  2050.     (void)do_write(eap);
  2051. }
  2052.  
  2053. /*
  2054.  * write current buffer to file 'eap->arg'
  2055.  * if 'eap->append' is TRUE, append to the file
  2056.  *
  2057.  * if *eap->arg == NUL write to current file
  2058.  *
  2059.  * return FAIL for failure, OK otherwise
  2060.  */
  2061.     int
  2062. do_write(eap)
  2063.     exarg_T    *eap;
  2064. {
  2065.     int        other;
  2066.     char_u    *fname = NULL;        /* init to shut up gcc */
  2067.     char_u    *ffname;
  2068.     int        retval = FAIL;
  2069.     char_u    *free_fname = NULL;
  2070. #ifdef FEAT_BROWSE
  2071.     char_u    *browse_file = NULL;
  2072. #endif
  2073.     buf_T    *alt_buf = NULL;
  2074.  
  2075.     if (not_writing())        /* check 'write' option */
  2076.     return FAIL;
  2077.  
  2078.     ffname = eap->arg;
  2079. #ifdef FEAT_BROWSE
  2080.     if (cmdmod.browse)
  2081.     {
  2082.     browse_file = do_browse(TRUE, (char_u *)_("Save As"), ffname,
  2083.                             NULL, NULL, NULL, curbuf);
  2084.     if (browse_file == NULL)
  2085.         goto theend;
  2086.     ffname = browse_file;
  2087.     }
  2088. #endif
  2089.     if (*ffname == NUL)
  2090.     {
  2091.     if (eap->cmdidx == CMD_saveas)
  2092.     {
  2093.         EMSG(_(e_argreq));
  2094.         goto theend;
  2095.     }
  2096.     other = FALSE;
  2097.     }
  2098.     else
  2099.     {
  2100.     fname = ffname;
  2101.     free_fname = fix_fname(ffname);
  2102.     /*
  2103.      * When out-of-memory, keep unexpanded file name, because we MUST be
  2104.      * able to write the file in this situation.
  2105.      */
  2106.     if (free_fname != NULL)
  2107.         ffname = free_fname;
  2108.     other = otherfile(ffname);
  2109.     }
  2110.  
  2111.     /*
  2112.      * If we have a new file, put its name in the list of alternate file names.
  2113.      */
  2114.     if (other)
  2115.     {
  2116.     if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
  2117.                          || eap->cmdidx == CMD_saveas)
  2118.         alt_buf = setaltfname(ffname, fname, (linenr_T)1);
  2119.     else
  2120.         alt_buf = buflist_findname(ffname);
  2121.     if (alt_buf != NULL && alt_buf->b_ml.ml_mfp != NULL)
  2122.     {
  2123.         /* Overwriting a file that is loaded in another buffer is not a
  2124.          * good idea. */
  2125.         EMSG(_("E139: File is loaded in another buffer"));
  2126.         goto theend;
  2127.     }
  2128.     }
  2129.  
  2130.     /*
  2131.      * Writing to the current file is not allowed in readonly mode
  2132.      * and a file name is required.
  2133.      * "nofile" and "nowrite" buffers cannot be written implicitly either.
  2134.      */
  2135.     if (!other && (
  2136. #ifdef FEAT_QUICKFIX
  2137.         bt_dontwrite_msg(curbuf) ||
  2138. #endif
  2139.         check_fname() == FAIL || check_readonly(&eap->forceit, curbuf)))
  2140.     goto theend;
  2141.  
  2142.     if (!other)
  2143.     {
  2144.     ffname = curbuf->b_ffname;
  2145.     fname = curbuf->b_fname;
  2146.     /*
  2147.      * Not writing the whole file is only allowed with '!'.
  2148.      */
  2149.     if (       (eap->line1 != 1
  2150.             || eap->line2 != curbuf->b_ml.ml_line_count)
  2151.         && !eap->forceit
  2152.         && !eap->append
  2153.         && !p_wa)
  2154.     {
  2155. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2156.         if (p_confirm || cmdmod.confirm)
  2157.         {
  2158.         if (vim_dialog_yesno(VIM_QUESTION, NULL,
  2159.                    (char_u *)_("Write partial file?"), 2) != VIM_YES)
  2160.             goto theend;
  2161.         eap->forceit = TRUE;
  2162.         }
  2163.         else
  2164. #endif
  2165.         {
  2166.         EMSG(_("E140: Use ! to write partial buffer"));
  2167.         goto theend;
  2168.         }
  2169.     }
  2170.     }
  2171.  
  2172.     if (check_overwrite(eap, curbuf, fname, ffname, other) == OK)
  2173.     {
  2174.     if (eap->cmdidx == CMD_saveas && alt_buf != NULL)
  2175.     {
  2176. #ifdef FEAT_AUTOCMD
  2177.         buf_T    *was_curbuf = curbuf;
  2178.  
  2179.         apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
  2180. # ifdef FEAT_EVAL
  2181.         if (curbuf != was_curbuf || aborting())
  2182. # else
  2183.         if (curbuf != was_curbuf)
  2184. # endif
  2185.         {
  2186.         /* buffer changed, don't change name now */
  2187.         retval = FAIL;
  2188.         goto theend;
  2189.         }
  2190. #endif
  2191.         /* Exchange the file names for the current and the alternate
  2192.          * buffer.  This makes it look like we are now editing the buffer
  2193.          * under the new name.  Must be done before buf_write(), because
  2194.          * if there is no file name and 'cpo' contains 'F', it will set
  2195.          * the file name. */
  2196.         fname = alt_buf->b_fname;
  2197.         alt_buf->b_fname = curbuf->b_fname;
  2198.         curbuf->b_fname = fname;
  2199.         fname = alt_buf->b_ffname;
  2200.         alt_buf->b_ffname = curbuf->b_ffname;
  2201.         curbuf->b_ffname = fname;
  2202.         fname = alt_buf->b_sfname;
  2203.         alt_buf->b_sfname = curbuf->b_sfname;
  2204.         curbuf->b_sfname = fname;
  2205.         buf_name_changed();
  2206. #ifdef FEAT_AUTOCMD
  2207.         apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
  2208.         if (!alt_buf->b_p_bl)
  2209.         {
  2210.         alt_buf->b_p_bl = TRUE;
  2211.         apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, alt_buf);
  2212.         }
  2213. # ifdef FEAT_EVAL
  2214.         if (curbuf != was_curbuf || aborting())
  2215. # else
  2216.         if (curbuf != was_curbuf)
  2217. # endif
  2218.         {
  2219.         /* buffer changed, don't write the file */
  2220.         retval = FAIL;
  2221.         goto theend;
  2222.         }
  2223. #endif
  2224.     }
  2225.  
  2226.     retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
  2227.                  eap, eap->append, eap->forceit, TRUE, FALSE);
  2228.     }
  2229.  
  2230. theend:
  2231. #ifdef FEAT_BROWSE
  2232.     vim_free(browse_file);
  2233. #endif
  2234.     vim_free(free_fname);
  2235.     return retval;
  2236. }
  2237.  
  2238. /*
  2239.  * Check if it is allowed to overwrite a file.  If b_flags has BF_NOTEDITED,
  2240.  * BF_NEW or BF_READERR, check for overwriting current file.
  2241.  * May set eap->forceit if a dialog says it's OK to overwrite.
  2242.  * Return OK if it's OK, FAIL if it is not.
  2243.  */
  2244. /*ARGSUSED*/
  2245.     static int
  2246. check_overwrite(eap, buf, fname, ffname, other)
  2247.     exarg_T    *eap;
  2248.     buf_T    *buf;
  2249.     char_u    *fname;        /* file name to be used (can differ from
  2250.                    buf->ffname) */
  2251.     char_u    *ffname;    /* full path version of fname */
  2252.     int        other;        /* writing under other name */
  2253. {
  2254.     /*
  2255.      * write to other file or b_flags set or not writing the whole file:
  2256.      * overwriting only allowed with '!'
  2257.      */
  2258.     if (       (other
  2259.         || (buf->b_flags & BF_NOTEDITED)
  2260.         || ((buf->b_flags & BF_NEW)
  2261.             && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
  2262.         || (buf->b_flags & BF_READERR))
  2263.         && !eap->forceit
  2264.         && !eap->append
  2265.         && !p_wa
  2266.         && vim_fexists(ffname))
  2267.     {
  2268. #ifdef UNIX
  2269.         /* with UNIX it is possible to open a directory */
  2270.     if (mch_isdir(ffname))
  2271.     {
  2272.         EMSG2(_(e_isadir2), ffname);
  2273.         return FAIL;
  2274.     }
  2275. #endif
  2276. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2277.     if (p_confirm || cmdmod.confirm)
  2278.     {
  2279.         char_u    buff[IOSIZE];
  2280.  
  2281.         dialog_msg(buff, _("Overwrite existing file \"%.*s\"?"), fname);
  2282.         if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES)
  2283.         return FAIL;
  2284.         eap->forceit = TRUE;
  2285.     }
  2286.     else
  2287. #endif
  2288.     {
  2289.         EMSG(_(e_exists));
  2290.         return FAIL;
  2291.     }
  2292.     }
  2293.     return OK;
  2294. }
  2295.  
  2296. /*
  2297.  * Handle ":wnext", ":wNext" and ":wprevious" commands.
  2298.  */
  2299.     void
  2300. ex_wnext(eap)
  2301.     exarg_T    *eap;
  2302. {
  2303.     int        i;
  2304.  
  2305.     if (eap->cmd[1] == 'n')
  2306.     i = curwin->w_arg_idx + (int)eap->line2;
  2307.     else
  2308.     i = curwin->w_arg_idx - (int)eap->line2;
  2309.     eap->line1 = 1;
  2310.     eap->line2 = curbuf->b_ml.ml_line_count;
  2311.     if (do_write(eap) != FAIL)
  2312.     do_argfile(eap, i);
  2313. }
  2314.  
  2315. /*
  2316.  * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
  2317.  */
  2318.     void
  2319. do_wqall(eap)
  2320.     exarg_T    *eap;
  2321. {
  2322.     buf_T    *buf;
  2323.     int        error = 0;
  2324.  
  2325.     if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall)
  2326.     exiting = TRUE;
  2327.  
  2328.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  2329.     {
  2330.     if (bufIsChanged(buf))
  2331.     {
  2332.         /*
  2333.          * Check if there is a reason the buffer cannot be written:
  2334.          * 1. if the 'write' option is set
  2335.          * 2. if there is no file name (even after browsing)
  2336.          * 3. if the 'readonly' is set (even after a dialog)
  2337.          * 4. if overwriting is allowed (even after a dialog)
  2338.          */
  2339.         if (not_writing())
  2340.         {
  2341.         ++error;
  2342.         break;
  2343.         }
  2344. #ifdef FEAT_BROWSE
  2345.         /* ":browse wall": ask for file name if there isn't one */
  2346.         if (buf->b_ffname == NULL && cmdmod.browse)
  2347.         buf->b_ffname = do_browse(TRUE, (char_u *)_("Save As"), NULL,
  2348.                                NULL, NULL, NULL, buf);
  2349. #endif
  2350.         if (buf->b_ffname == NULL)
  2351.         {
  2352.         EMSGN(_("E141: No file name for buffer %ld"), (long)buf->b_fnum);
  2353.         ++error;
  2354.         }
  2355.         else if (check_readonly(&eap->forceit, buf)
  2356.             || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname,
  2357.                                    FALSE) == FAIL)
  2358.         {
  2359.         ++error;
  2360.         }
  2361.         else
  2362.         {
  2363.         if (buf_write_all(buf, eap->forceit) == FAIL)
  2364.             ++error;
  2365. #ifdef FEAT_AUTOCMD
  2366.         /* an autocommand may have deleted the buffer */
  2367.         if (!buf_valid(buf))
  2368.             buf = firstbuf;
  2369. #endif
  2370.         }
  2371.     }
  2372.     }
  2373.     if (exiting)
  2374.     {
  2375.     if (!error)
  2376.         getout(0);        /* exit Vim */
  2377.     not_exiting();
  2378.     }
  2379. }
  2380.  
  2381. /*
  2382.  * Check the 'write' option.
  2383.  * Return TRUE and give a message when it's not st.
  2384.  */
  2385.     int
  2386. not_writing()
  2387. {
  2388.     if (p_write)
  2389.     return FALSE;
  2390.     EMSG(_("E142: File not written: Writing is disabled by 'write' option"));
  2391.     return TRUE;
  2392. }
  2393.  
  2394. /*
  2395.  * Check if a buffer is read-only.  Ask for overruling in a dialog.
  2396.  * Return TRUE and give an error message when the buffer is readonly.
  2397.  */
  2398.     static int
  2399. check_readonly(forceit, buf)
  2400.     int        *forceit;
  2401.     buf_T    *buf;
  2402. {
  2403.     if (!*forceit && buf->b_p_ro)
  2404.     {
  2405. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2406.     if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL)
  2407.     {
  2408.         char_u    buff[IOSIZE];
  2409.  
  2410.         dialog_msg(buff, _("'readonly' option is set for \"%.*s\".\nDo you wish to write anyway?"),
  2411.             buf->b_fname);
  2412.  
  2413.         if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES)
  2414.         {
  2415.         /* Set forceit, to force the writing of a readonly file */
  2416.         *forceit = TRUE;
  2417.         return FALSE;
  2418.         }
  2419.         else
  2420.         return TRUE;
  2421.     }
  2422.     else
  2423. #endif
  2424.         EMSG(_(e_readonly));
  2425.     return TRUE;
  2426.     }
  2427.     return FALSE;
  2428. }
  2429.  
  2430. /*
  2431.  * try to abandon current file and edit a new or existing file
  2432.  * 'fnum' is the number of the file, if zero use ffname/sfname
  2433.  *
  2434.  * return 1 for "normal" error, 2 for "not written" error, 0 for success
  2435.  * -1 for succesfully opening another file
  2436.  * 'lnum' is the line number for the cursor in the new file (if non-zero).
  2437.  */
  2438.     int
  2439. getfile(fnum, ffname, sfname, setpm, lnum, forceit)
  2440.     int        fnum;
  2441.     char_u    *ffname;
  2442.     char_u    *sfname;
  2443.     int        setpm;
  2444.     linenr_T    lnum;
  2445.     int        forceit;
  2446. {
  2447.     int        other;
  2448.     int        retval;
  2449.     char_u    *free_me = NULL;
  2450.  
  2451. #ifdef FEAT_CMDWIN
  2452.     if (cmdwin_type != 0)
  2453.     return 1;
  2454. #endif
  2455.  
  2456.     if (fnum == 0)
  2457.     {
  2458.     fname_expand(&ffname, &sfname);    /* make ffname full path, set sfname */
  2459.     other = otherfile(ffname);
  2460.     free_me = ffname;        /* has been allocated, free() later */
  2461.     }
  2462.     else
  2463.     other = (fnum != curbuf->b_fnum);
  2464.  
  2465.     if (other)
  2466.     ++no_wait_return;        /* don't wait for autowrite message */
  2467.     if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf)
  2468.            && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
  2469.     {
  2470.     if (other)
  2471.         --no_wait_return;
  2472.     EMSG(_(e_nowrtmsg));
  2473.     retval = 2;    /* file has been changed */
  2474.     goto theend;
  2475.     }
  2476.     if (other)
  2477.     --no_wait_return;
  2478.     if (setpm)
  2479.     setpcmark();
  2480.     if (!other)
  2481.     {
  2482.     if (lnum != 0)
  2483.         curwin->w_cursor.lnum = lnum;
  2484.     check_cursor_lnum();
  2485.     beginline(BL_SOL | BL_FIX);
  2486.     retval = 0;    /* it's in the same file */
  2487.     }
  2488.     else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
  2489.         (P_HID(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0)) == OK)
  2490.     retval = -1;    /* opened another file */
  2491.     else
  2492.     retval = 1;    /* error encountered */
  2493.  
  2494. theend:
  2495.     vim_free(free_me);
  2496.     return retval;
  2497. }
  2498.  
  2499. /*
  2500.  * start editing a new file
  2501.  *
  2502.  *     fnum: file number; if zero use ffname/sfname
  2503.  *   ffname: the file name
  2504.  *        - full path if sfname used,
  2505.  *        - any file name if sfname is NULL
  2506.  *        - empty string to re-edit with the same file name (but may be
  2507.  *            in a different directory)
  2508.  *        - NULL to start an empty buffer
  2509.  *   sfname: the short file name (or NULL)
  2510.  *    eap: contains the command to be executed after loading the file and
  2511.  *         forced 'ff' and 'fenc'
  2512.  *  newlnum: if > 0: put cursor on this line number (if possible)
  2513.  *         if ECMD_LASTL: use last position in loaded file
  2514.  *         if ECMD_LAST: use last position in all files
  2515.  *         if ECMD_ONE: use first line
  2516.  *    flags:
  2517.  *       ECMD_HIDE: if TRUE don't free the current buffer
  2518.  *     ECMD_SET_HELP: set b_help flag of (new) buffer before opening file
  2519.  *     ECMD_OLDBUF: use existing buffer if it exists
  2520.  *    ECMD_FORCEIT: ! used for Ex command
  2521.  *     ECMD_ADDBUF: don't edit, just add to buffer list
  2522.  *
  2523.  * return FAIL for failure, OK otherwise
  2524.  */
  2525.     int
  2526. do_ecmd(fnum, ffname, sfname, eap, newlnum, flags)
  2527.     int        fnum;
  2528.     char_u    *ffname;
  2529.     char_u    *sfname;
  2530.     exarg_T    *eap;            /* can be NULL! */
  2531.     linenr_T    newlnum;
  2532.     int        flags;
  2533. {
  2534.     int        other_file;        /* TRUE if editing another file */
  2535.     int        oldbuf;            /* TRUE if using existing buffer */
  2536. #ifdef FEAT_AUTOCMD
  2537.     int        auto_buf = FALSE;    /* TRUE if autocommands brought us
  2538.                        into the buffer unexpectedly */
  2539.     char_u    *new_name = NULL;
  2540. #endif
  2541.     buf_T    *buf;
  2542. #if defined(FEAT_AUTOCMD) || defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2543.     buf_T    *old_curbuf = curbuf;
  2544. #endif
  2545.     char_u    *free_fname = NULL;
  2546. #ifdef FEAT_BROWSE
  2547.     char_u    *browse_file = NULL;
  2548. #endif
  2549.     int        retval = FAIL;
  2550.     long    n;
  2551.     linenr_T    lnum;
  2552.     linenr_T    topline = 0;
  2553.     int        newcol = -1;
  2554.     int        solcol = -1;
  2555.     pos_T    *pos;
  2556. #ifdef FEAT_SUN_WORKSHOP
  2557.     char_u    *cp;
  2558. #endif
  2559.     char_u    *command = NULL;
  2560.  
  2561.     if (eap != NULL)
  2562.     command = eap->do_ecmd_cmd;
  2563.  
  2564.     if (fnum != 0)
  2565.     {
  2566.     if (fnum == curbuf->b_fnum)    /* file is already being edited */
  2567.         return OK;            /* nothing to do */
  2568.     other_file = TRUE;
  2569.     }
  2570.     else
  2571.     {
  2572. #ifdef FEAT_BROWSE
  2573.     if (cmdmod.browse)
  2574.     {
  2575.         browse_file = do_browse(FALSE, (char_u *)_("Edit File"), ffname,
  2576.                             NULL, NULL, NULL, curbuf);
  2577.         if (browse_file == NULL)
  2578.         goto theend;
  2579.         ffname = browse_file;
  2580.     }
  2581. #endif
  2582.     /* if no short name given, use ffname for short name */
  2583.     if (sfname == NULL)
  2584.         sfname = ffname;
  2585. #ifdef USE_FNAME_CASE
  2586. # ifdef USE_LONG_FNAME
  2587.     if (USE_LONG_FNAME)
  2588. # endif
  2589.         fname_case(sfname, 0);   /* set correct case for short file name */
  2590. #endif
  2591.  
  2592. #ifdef FEAT_LISTCMDS
  2593.     if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
  2594.         goto theend;
  2595. #endif
  2596.  
  2597.     if (ffname == NULL)
  2598.         other_file = TRUE;
  2599.                         /* there is no file name */
  2600.     else if (*ffname == NUL && curbuf->b_ffname == NULL)
  2601.         other_file = FALSE;
  2602.     else
  2603.     {
  2604.         if (*ffname == NUL)            /* re-edit with same file name */
  2605.         {
  2606.         ffname = curbuf->b_ffname;
  2607.         sfname = curbuf->b_fname;
  2608.         }
  2609.         free_fname = fix_fname(ffname); /* may expand to full path name */
  2610.         if (free_fname != NULL)
  2611.         ffname = free_fname;
  2612.         other_file = otherfile(ffname);
  2613. #ifdef FEAT_SUN_WORKSHOP
  2614.         if (usingSunWorkShop && (cp = vim_strrchr(sfname, '/')) != NULL)
  2615.         sfname = ++cp;
  2616. #endif
  2617.     }
  2618.     }
  2619.  
  2620.     /*
  2621.      * if the file was changed we may not be allowed to abandon it
  2622.      * - if we are going to re-edit the same file
  2623.      * - or if we are the only window on this file and if ECMD_HIDE is FALSE
  2624.      */
  2625.     if (  ((!other_file && !(flags & ECMD_OLDBUF))
  2626.         || (curbuf->b_nwindows == 1
  2627.         && !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
  2628.     && check_changed(curbuf, p_awa, !other_file,
  2629.                     (flags & ECMD_FORCEIT), FALSE))
  2630.     {
  2631.     if (fnum == 0 && other_file && ffname != NULL)
  2632.         (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
  2633.     goto theend;
  2634.     }
  2635.  
  2636. #ifdef FEAT_VISUAL
  2637.     /*
  2638.      * End Visual mode before switching to another buffer, so the text can be
  2639.      * copied into the GUI selection buffer.
  2640.      */
  2641.     reset_VIsual();
  2642. #endif
  2643.  
  2644.     /*
  2645.      * If we are starting to edit another file, open a (new) buffer.
  2646.      * Otherwise we re-use the current buffer.
  2647.      */
  2648.     if (other_file)
  2649.     {
  2650. #ifdef FEAT_LISTCMDS
  2651.     if (!(flags & ECMD_ADDBUF))
  2652. #endif
  2653.     {
  2654.         curwin->w_alt_fnum = curbuf->b_fnum;
  2655.         buflist_altfpos();
  2656.     }
  2657.  
  2658.     if (fnum)
  2659.         buf = buflist_findnr(fnum);
  2660.     else
  2661.     {
  2662. #ifdef FEAT_LISTCMDS
  2663.         if (flags & ECMD_ADDBUF)
  2664.         {
  2665.         linenr_T    tlnum = 1L;
  2666.  
  2667.         if (command != NULL)
  2668.         {
  2669.             tlnum = atol((char *)command);
  2670.             if (tlnum <= 0)
  2671.             tlnum = 1L;
  2672.         }
  2673.         (void)buflist_new(ffname, sfname, tlnum, BLN_LISTED);
  2674.         goto theend;
  2675.         }
  2676. #endif
  2677.         buf = buflist_new(ffname, sfname, 0L,
  2678.             BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
  2679.     }
  2680.     if (buf == NULL)
  2681.         goto theend;
  2682.     if (buf->b_ml.ml_mfp == NULL)        /* no memfile yet */
  2683.     {
  2684.         oldbuf = FALSE;
  2685.         buf->b_nwindows = 0;
  2686.     }
  2687.     else                    /* existing memfile */
  2688.     {
  2689.         oldbuf = TRUE;
  2690.         (void)buf_check_timestamp(buf, FALSE);
  2691.         /* Check if autocommands made buffer invalid. */
  2692.         if (!buf_valid(buf))
  2693.         goto theend;
  2694. #ifdef FEAT_EVAL
  2695.         if (aborting())        /* autocmds may abort script processing */
  2696.         goto theend;
  2697. #endif
  2698.     }
  2699.  
  2700.     /* May jump to last used line number for a loaded buffer or when asked
  2701.      * for explicitly */
  2702.     if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST)
  2703.     {
  2704.         pos = buflist_findfpos(buf);
  2705.         newlnum = pos->lnum;
  2706.         solcol = pos->col;
  2707.     }
  2708.  
  2709.     /*
  2710.      * Make the (new) buffer the one used by the current window.
  2711.      * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
  2712.      * If the current buffer was empty and has no file name, curbuf
  2713.      * is returned by buflist_new().
  2714.      */
  2715.     if (buf != curbuf)
  2716.     {
  2717. #ifdef FEAT_AUTOCMD
  2718.         /*
  2719.          * Be careful: The autocommands may delete any buffer and change
  2720.          * the current buffer.
  2721.          * - If the buffer we are going to edit is deleted, give up.
  2722.          * - If the current buffer is deleted, prefer to load the new
  2723.          *   buffer when loading a buffer is required.  This avoids
  2724.          *   loading another buffer which then must be closed again.
  2725.          * - If we ended up in the new buffer already, need to skip a few
  2726.          *     things, set auto_buf.
  2727.          */
  2728.         if (buf->b_fname != NULL)
  2729.         new_name = vim_strsave(buf->b_fname);
  2730.         au_new_curbuf = buf;
  2731.         apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
  2732.         if (!buf_valid(buf))    /* new buffer has been deleted */
  2733.         {
  2734.         delbuf_msg(new_name);    /* frees new_name */
  2735.         goto theend;
  2736.         }
  2737. # ifdef FEAT_EVAL
  2738.         if (aborting())        /* autocmds may abort script processing */
  2739.         {
  2740.         vim_free(new_name);
  2741.         goto theend;
  2742.         }
  2743. # endif
  2744.         if (buf == curbuf)        /* already in new buffer */
  2745.         auto_buf = TRUE;
  2746.         else
  2747.         {
  2748.         if (curbuf == old_curbuf)
  2749. #endif
  2750.             buf_copy_options(buf, BCO_ENTER);
  2751.  
  2752.         /* close the link to the current buffer */
  2753.         close_buffer(curwin, curbuf,
  2754.                       (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD);
  2755.  
  2756. #ifdef FEAT_AUTOCMD
  2757. # ifdef FEAT_EVAL
  2758.         if (aborting())        /* autocmds may abort script processing */
  2759.         {
  2760.         vim_free(new_name);
  2761.         goto theend;
  2762.         }
  2763. # endif
  2764.         /* Be careful again, like above. */
  2765.         if (!buf_valid(buf))    /* new buffer has been deleted */
  2766.         {
  2767.             delbuf_msg(new_name);    /* frees new_name */
  2768.             goto theend;
  2769.         }
  2770.         if (buf == curbuf)        /* already in new buffer */
  2771.             auto_buf = TRUE;
  2772.         else
  2773. #endif
  2774.  
  2775.         {
  2776.             curwin->w_buffer = buf;
  2777.             curbuf = buf;
  2778.             ++curbuf->b_nwindows;
  2779.             /* set 'fileformat' */
  2780.             if (*p_ffs && !oldbuf)
  2781.             set_fileformat(default_fileformat(), OPT_LOCAL);
  2782.         }
  2783.  
  2784.         /* May get the window options from the last time this buffer
  2785.          * was in this window (or another window).  If not used
  2786.          * before, reset the local window options to the global
  2787.          * values.  Also restores old folding stuff. */
  2788.         get_winopts(buf);
  2789.  
  2790. #ifdef FEAT_AUTOCMD
  2791.         }
  2792.         vim_free(new_name);
  2793.         au_new_curbuf = NULL;
  2794. #endif
  2795.     }
  2796.     else
  2797.         ++curbuf->b_nwindows;
  2798.  
  2799.     curwin->w_pcmark.lnum = 1;
  2800.     curwin->w_pcmark.col = 0;
  2801.     }
  2802.     else /* !other_file */
  2803.     {
  2804.     if (
  2805. #ifdef FEAT_LISTCMDS
  2806.         (flags & ECMD_ADDBUF) ||
  2807. #endif
  2808.         check_fname() == FAIL)
  2809.         goto theend;
  2810.     oldbuf = (flags & ECMD_OLDBUF);
  2811.     }
  2812.  
  2813.     if ((flags & ECMD_SET_HELP) || keep_help_flag)
  2814.     {
  2815.     curbuf->b_help = TRUE;
  2816. #ifdef FEAT_QUICKFIX
  2817.     set_string_option_direct((char_u *)"buftype", -1,
  2818.                        (char_u *)"help", OPT_FREE |OPT_LOCAL);
  2819. #endif
  2820.     curbuf->b_p_ma = FALSE;
  2821.     curbuf->b_p_bin = FALSE;    /* reset 'bin' before reading file */
  2822.     curwin->w_p_nu = 0;        /* no line numbers */
  2823. #ifdef FEAT_SCROLLBIND
  2824.     curwin->w_p_scb = FALSE;    /* no scroll binding */
  2825. #endif
  2826. #ifdef FEAT_ARABIC
  2827.     curwin->w_p_arab = FALSE;    /* no arabic mode */
  2828. #endif
  2829. #ifdef FEAT_RIGHTLEFT
  2830.     curwin->w_p_rl  = FALSE;    /* help window is left-to-right */
  2831. #endif
  2832. #ifdef FEAT_FOLDING
  2833.     curwin->w_p_fen = FALSE;    /* No folding in the help window */
  2834. #endif
  2835. #ifdef FEAT_DIFF
  2836.     curwin->w_p_diff = FALSE;    /* No 'diff' */
  2837. #endif
  2838.  
  2839. #ifdef FEAT_AUTOCMD
  2840.     buf = curbuf;
  2841. #endif
  2842.     set_buflisted(FALSE);
  2843.     }
  2844.     else
  2845.     {
  2846. #ifdef FEAT_AUTOCMD
  2847.     buf = curbuf;
  2848. #endif
  2849.     set_buflisted(TRUE);
  2850.     }
  2851.  
  2852. #ifdef FEAT_AUTOCMD
  2853.     /* If autocommands change buffers under our fingers, forget about
  2854.      * editing the file. */
  2855.     if (buf != curbuf)
  2856.     goto theend;
  2857. # ifdef FEAT_EVAL
  2858.     if (aborting())        /* autocmds may abort script processing */
  2859.     goto theend;
  2860. # endif
  2861.  
  2862.     /* Since we are starting to edit a file, consider the filetype to be
  2863.      * unset.  Helps for when an autocommand changes files and expects syntax
  2864.      * highlighting to work in the other file. */
  2865.     did_filetype = FALSE;
  2866. #endif
  2867.  
  2868. /*
  2869.  * other_file    oldbuf
  2870.  *  FALSE    FALSE        re-edit same file, buffer is re-used
  2871.  *  FALSE    TRUE        re-edit same file, nothing changes
  2872.  *  TRUE    FALSE        start editing new file, new buffer
  2873.  *  TRUE    TRUE        start editing in existing buffer (nothing to do)
  2874.  */
  2875.     if (!other_file && !oldbuf)        /* re-use the buffer */
  2876.     {
  2877.     set_last_cursor(curwin);    /* may set b_last_cursor */
  2878.     if (newlnum == ECMD_LAST || newlnum == ECMD_LASTL)
  2879.     {
  2880.         newlnum = curwin->w_cursor.lnum;
  2881.         solcol = curwin->w_cursor.col;
  2882.     }
  2883. #ifdef FEAT_AUTOCMD
  2884.     buf = curbuf;
  2885.     if (buf->b_fname != NULL)
  2886.         new_name = vim_strsave(buf->b_fname);
  2887.     else
  2888.         new_name = NULL;
  2889. #endif
  2890.     buf_freeall(curbuf, FALSE, FALSE);   /* free all things for buffer */
  2891. #ifdef FEAT_AUTOCMD
  2892.     /* If autocommands deleted the buffer we were going to re-edit, give
  2893.      * up and jump to the end. */
  2894.     if (!buf_valid(buf))
  2895.     {
  2896.         delbuf_msg(new_name);    /* frees new_name */
  2897.         goto theend;
  2898.     }
  2899.     vim_free(new_name);
  2900.  
  2901.     /* If autocommands change buffers under our fingers, forget about
  2902.      * re-editing the file.  Should do the buf_clear_file(), but perhaps
  2903.      * the autocommands changed the buffer... */
  2904.     if (buf != curbuf)
  2905.         goto theend;
  2906. # ifdef FEAT_EVAL
  2907.     if (aborting())        /* autocmds may abort script processing */
  2908.         goto theend;
  2909. # endif
  2910. #endif
  2911.     buf_clear_file(curbuf);
  2912.     curbuf->b_op_start.lnum = 0;    /* clear '[ and '] marks */
  2913.     curbuf->b_op_end.lnum = 0;
  2914.     }
  2915.  
  2916. /*
  2917.  * If we get here we are sure to start editing
  2918.  */
  2919.     /* don't redraw until the cursor is in the right line */
  2920.     ++RedrawingDisabled;
  2921.  
  2922.     /* Assume success now */
  2923.     retval = OK;
  2924.  
  2925.     /*
  2926.      * Reset cursor position, could be used by autocommands.
  2927.      */
  2928.     check_cursor();
  2929.  
  2930.     /*
  2931.      * Check if we are editing the w_arg_idx file in the argument list.
  2932.      */
  2933.     check_arg_idx(curwin);
  2934.  
  2935. #ifdef FEAT_AUTOCMD
  2936.     if (!auto_buf)
  2937. #endif
  2938.     {
  2939.     /*
  2940.      * Set cursor and init window before reading the file and executing
  2941.      * autocommands.  This allows for the autocommands to position the
  2942.      * cursor.
  2943.      */
  2944.     win_init(curwin);
  2945.  
  2946. #ifdef FEAT_FOLDING
  2947.     /* It's like all lines in the buffer changed.  Need to update
  2948.      * automatic folding. */
  2949.     foldUpdateAll(curwin);
  2950. #endif
  2951.  
  2952. #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
  2953.     if (p_acd && curbuf->b_ffname != NULL
  2954.                      && vim_chdirfile(curbuf->b_ffname) == OK)
  2955.         shorten_fnames(TRUE);
  2956. #endif
  2957.     /*
  2958.      * Careful: open_buffer() and apply_autocmds() may change the current
  2959.      * buffer and window.
  2960.      */
  2961.     lnum = curwin->w_cursor.lnum;
  2962.     topline = curwin->w_topline;
  2963.     if (!oldbuf)                /* need to read the file */
  2964.     {
  2965. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2966.         swap_exists_action = SEA_DIALOG;
  2967. #endif
  2968.         curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
  2969.  
  2970.         /*
  2971.          * Open the buffer and read the file.
  2972.          */
  2973. #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
  2974.         if (should_abort(open_buffer(FALSE, eap)))
  2975.         retval = FAIL;
  2976. #else
  2977.         (void)open_buffer(FALSE, eap);
  2978. #endif
  2979.  
  2980. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2981.         if (swap_exists_action == SEA_QUIT)
  2982.         retval = FAIL;
  2983.         handle_swap_exists(old_curbuf);
  2984. #endif
  2985.     }
  2986. #ifdef FEAT_AUTOCMD
  2987.     else
  2988.     {
  2989.         apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf,
  2990.                                     &retval);
  2991.         apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf,
  2992.                                     &retval);
  2993.     }
  2994.     check_arg_idx(curwin);
  2995. #endif
  2996.  
  2997.     /*
  2998.      * If autocommands change the cursor position or topline, we should
  2999.      * keep it.
  3000.      */
  3001.     if (curwin->w_cursor.lnum != lnum)
  3002.     {
  3003.         newlnum = curwin->w_cursor.lnum;
  3004.         newcol = curwin->w_cursor.col;
  3005.     }
  3006.     if (curwin->w_topline == topline)
  3007.         topline = 0;
  3008.  
  3009.     /* Even when cursor didn't move we need to recompute topline. */
  3010.     changed_line_abv_curs();
  3011.  
  3012. #ifdef FEAT_TITLE
  3013.     maketitle();
  3014. #endif
  3015.     }
  3016.  
  3017. #ifdef FEAT_DIFF
  3018.     /* Tell the diff stuff that this buffer is new and/or needs updating.
  3019.      * Also needed when re-editing the same buffer, because unloading will
  3020.      * have removed it as a diff buffer. */
  3021.     diff_new_buffer();
  3022.     diff_invalidate();
  3023. #endif
  3024.  
  3025.     if (command == NULL)
  3026.     {
  3027.     if (newcol >= 0)    /* position set by autocommands */
  3028.     {
  3029.         curwin->w_cursor.lnum = newlnum;
  3030.         curwin->w_cursor.col = newcol;
  3031.         check_cursor();
  3032.     }
  3033.     else if (newlnum > 0)    /* line number from caller or old position */
  3034.     {
  3035.         curwin->w_cursor.lnum = newlnum;
  3036.         check_cursor_lnum();
  3037.         if (solcol >= 0 && !p_sol)
  3038.         {
  3039.         /* 'sol' is off: Use last known column. */
  3040.         curwin->w_cursor.col = solcol;
  3041.         check_cursor_col();
  3042. #ifdef FEAT_VIRTUALEDIT
  3043.         curwin->w_cursor.coladd = 0;
  3044. #endif
  3045.         curwin->w_set_curswant = TRUE;
  3046.         }
  3047.         else
  3048.         beginline(BL_SOL | BL_FIX);
  3049.     }
  3050.     else            /* no line number, go to last line in Ex mode */
  3051.     {
  3052.         if (exmode_active)
  3053.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  3054.         beginline(BL_WHITE | BL_FIX);
  3055.     }
  3056.     }
  3057.  
  3058. #ifdef FEAT_WINDOWS
  3059.     /* Check if cursors in other windows on the same buffer are still valid */
  3060.     check_lnums(FALSE);
  3061. #endif
  3062.  
  3063.     /*
  3064.      * Did not read the file, need to show some info about the file.
  3065.      * Do this after setting the cursor.
  3066.      */
  3067.     if (oldbuf
  3068. #ifdef FEAT_AUTOCMD
  3069.         && !auto_buf
  3070. #endif
  3071.                 )
  3072.     {
  3073.     int    msg_scroll_save = msg_scroll;
  3074.  
  3075.     /* Obey the 'O' flag in 'cpoptions': overwrite any previous file
  3076.      * message. */
  3077.     if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
  3078.         msg_scroll = FALSE;
  3079.     if (!msg_scroll)    /* wait a bit when overwriting an error msg */
  3080.         check_for_delay(FALSE);
  3081.     msg_start();
  3082.     msg_scroll = msg_scroll_save;
  3083.     msg_scrolled_ign = TRUE;
  3084.  
  3085.     fileinfo(FALSE, TRUE, FALSE);
  3086.  
  3087.     msg_scrolled_ign = FALSE;
  3088.     }
  3089.  
  3090.     if (command != NULL)
  3091.     do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
  3092.  
  3093. #ifdef FEAT_KEYMAP
  3094.     if (curbuf->b_kmap_state & KEYMAP_INIT)
  3095.     keymap_init();
  3096. #endif
  3097.  
  3098.     --RedrawingDisabled;
  3099.     if (!skip_redraw)
  3100.     {
  3101.     n = p_so;
  3102.     if (topline == 0 && command == NULL)
  3103.         p_so = 999;            /* force cursor halfway the window */
  3104.     update_topline();
  3105. #ifdef FEAT_SCROLLBIND
  3106.     curwin->w_scbind_pos = curwin->w_topline;
  3107. #endif
  3108.     p_so = n;
  3109.     redraw_curbuf_later(NOT_VALID);    /* redraw this buffer later */
  3110.     }
  3111.  
  3112.     if (p_im)
  3113.     need_start_insertmode = TRUE;
  3114.  
  3115. #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
  3116.     /* Change directories when the acd option is set on. */
  3117.     if (p_acd && curbuf->b_ffname != NULL
  3118.                      && vim_chdirfile(curbuf->b_ffname) == OK)
  3119.     shorten_fnames(TRUE);
  3120.  
  3121.     if (gui.in_use && curbuf->b_fname != NULL)
  3122.     {
  3123. # ifdef FEAT_SUN_WORKSHOP
  3124.     if (usingSunWorkShop)
  3125.         workshop_file_opened((char *)curbuf->b_ffname, curbuf->b_p_ro);
  3126. # endif
  3127. # ifdef FEAT_NETBEANS_INTG
  3128.     if (usingNetbeans)
  3129.         netbeans_file_opened((char *)curbuf->b_ffname);
  3130. # endif
  3131.     }
  3132. #endif
  3133.  
  3134. theend:
  3135. #ifdef FEAT_BROWSE
  3136.     vim_free(browse_file);
  3137. #endif
  3138.     vim_free(free_fname);
  3139.     return retval;
  3140. }
  3141.  
  3142. #ifdef FEAT_AUTOCMD
  3143.     static void
  3144. delbuf_msg(name)
  3145.     char_u    *name;
  3146. {
  3147.     EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"),
  3148.         name == NULL ? (char_u *)"" : name);
  3149.     vim_free(name);
  3150.     au_new_curbuf = NULL;
  3151. }
  3152. #endif
  3153.  
  3154. /*
  3155.  * ":insert" and ":append", also used by ":change"
  3156.  */
  3157.     void
  3158. ex_append(eap)
  3159.     exarg_T    *eap;
  3160. {
  3161.     char_u    *theline;
  3162.     int        did_undo = FALSE;
  3163.     linenr_T    lnum = eap->line2;
  3164.  
  3165.     if (eap->cmdidx != CMD_append)
  3166.     --lnum;
  3167.  
  3168.     State = INSERT;            /* behave like in Insert mode */
  3169.     if (curbuf->b_p_iminsert == B_IMODE_LMAP)
  3170.     State |= LANGMAP;
  3171.     while (1)
  3172.     {
  3173.     msg_scroll = TRUE;
  3174.     need_wait_return = FALSE;
  3175.     if (eap->getline == NULL)
  3176.         theline = getcmdline(
  3177. #ifdef FEAT_EVAL
  3178.             eap->cstack->cs_whilelevel > 0 ? -1 :
  3179. #endif
  3180.             NUL, 0L, 0);
  3181.     else
  3182.         theline = eap->getline(
  3183. #ifdef FEAT_EVAL
  3184.             eap->cstack->cs_whilelevel > 0 ? -1 :
  3185. #endif
  3186.             NUL, eap->cookie, 0);
  3187.     lines_left = Rows - 1;
  3188.     if (theline == NULL || (theline[0] == '.' && theline[1] == NUL))
  3189.         break;
  3190.  
  3191.     if (!did_undo && u_save(lnum, lnum + 1) == FAIL)
  3192.         break;
  3193.     did_undo = TRUE;
  3194.     ml_append(lnum, theline, (colnr_T)0, FALSE);
  3195.     appended_lines_mark(lnum, 1L);
  3196.  
  3197.     vim_free(theline);
  3198.     ++lnum;
  3199.     msg_didout = TRUE;    /* also scroll for empty line */
  3200.     }
  3201.     State = NORMAL;
  3202.  
  3203.     /* "start" is set to eap->line2+1 unless that position is invalid (when
  3204.      * eap->line2 pointed to the end of the buffer and nothig was appended)
  3205.      * "end" is set to lnum when something has been appended, otherwise
  3206.      * it is the same than "start"  -- Acevedo */
  3207.     curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
  3208.     eap->line2 + 1 : curbuf->b_ml.ml_line_count;
  3209.     if (eap->cmdidx != CMD_append)
  3210.     --curbuf->b_op_start.lnum;
  3211.     curbuf->b_op_end.lnum = (eap->line2 < lnum)
  3212.                          ? lnum : curbuf->b_op_start.lnum;
  3213.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  3214.     curwin->w_cursor.lnum = lnum;
  3215.     check_cursor_lnum();
  3216.     beginline(BL_SOL | BL_FIX);
  3217.  
  3218.     need_wait_return = FALSE;    /* don't use wait_return() now */
  3219.     ex_no_reprint = TRUE;
  3220. }
  3221.  
  3222. /*
  3223.  * ":change"
  3224.  */
  3225.     void
  3226. ex_change(eap)
  3227.     exarg_T    *eap;
  3228. {
  3229.     linenr_T    lnum;
  3230.  
  3231.     if (eap->line2 >= eap->line1
  3232.         && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
  3233.     return;
  3234.  
  3235.     for (lnum = eap->line2; lnum >= eap->line1; --lnum)
  3236.     {
  3237.     if (curbuf->b_ml.ml_flags & ML_EMPTY)        /* nothing to delete */
  3238.         break;
  3239.     ml_delete(eap->line1, FALSE);
  3240.     }
  3241.     deleted_lines_mark(eap->line1, (long)(eap->line2 - lnum));
  3242.  
  3243.     /* ":append" on the line above the deleted lines. */
  3244.     eap->line2 = eap->line1;
  3245.     ex_append(eap);
  3246. }
  3247.  
  3248.     void
  3249. ex_z(eap)
  3250.     exarg_T    *eap;
  3251. {
  3252.     char_u    *x;
  3253.     int        bigness = curwin->w_height - 3;
  3254.     char_u    kind;
  3255.     int        numbered = FALSE;
  3256.     int        minus = 0;
  3257.     linenr_T    start, end, curs, i;
  3258.     int        j;
  3259.     linenr_T    lnum = eap->line2;
  3260.  
  3261.     if (bigness < 1)
  3262.     bigness = 1;
  3263.  
  3264.     x = eap->arg;
  3265.     if (*x == '#')
  3266.     {
  3267.     numbered = TRUE;
  3268.     ++x;
  3269.     }
  3270.  
  3271.     kind = *x;
  3272.     if (kind == '-' || kind == '+' || kind == '=' || kind == '^' || kind == '.')
  3273.     ++x;
  3274.  
  3275.     if (*x != 0)
  3276.     {
  3277.     if (!isdigit(*x))
  3278.     {
  3279.         EMSG(_("E144: non-numeric argument to :z"));
  3280.         return;
  3281.     }
  3282.     else
  3283.         bigness = atoi((char *)x);
  3284.     }
  3285.  
  3286.     switch (kind)
  3287.     {
  3288.     case '-':
  3289.         start = lnum - bigness;
  3290.         end = lnum;
  3291.         curs = lnum;
  3292.         break;
  3293.  
  3294.     case '=':
  3295.         start = lnum - bigness / 2 + 1;
  3296.         end = lnum + bigness / 2 - 1;
  3297.         curs = lnum;
  3298.         minus = 1;
  3299.         break;
  3300.  
  3301.     case '^':
  3302.         start = lnum - bigness * 2;
  3303.         end = lnum - bigness;
  3304.         curs = lnum - bigness;
  3305.         break;
  3306.  
  3307.     case '.':
  3308.         start = lnum - bigness / 2;
  3309.         end = lnum + bigness / 2;
  3310.         curs = end;
  3311.         break;
  3312.  
  3313.     default:  /* '+' */
  3314.         start = lnum;
  3315.         end = lnum + bigness;
  3316.         curs = end;
  3317.         break;
  3318.     }
  3319.  
  3320.     if (start < 1)
  3321.     start = 1;
  3322.  
  3323.     if (end > curbuf->b_ml.ml_line_count)
  3324.     end = curbuf->b_ml.ml_line_count;
  3325.  
  3326.     if (curs > curbuf->b_ml.ml_line_count)
  3327.     curs = curbuf->b_ml.ml_line_count;
  3328.  
  3329.     for (i = start; i <= end; i++)
  3330.     {
  3331.     if (minus && i == lnum)
  3332.     {
  3333.         msg_putchar('\n');
  3334.  
  3335.         for (j = 1; j < Columns; j++)
  3336.         msg_putchar('-');
  3337.     }
  3338.  
  3339.     print_line(i, numbered);
  3340.  
  3341.     if (minus && i == lnum)
  3342.     {
  3343.         msg_putchar('\n');
  3344.  
  3345.         for (j = 1; j < Columns; j++)
  3346.         msg_putchar('-');
  3347.     }
  3348.     }
  3349.  
  3350.     curwin->w_cursor.lnum = curs;
  3351.     ex_no_reprint = TRUE;
  3352. }
  3353.  
  3354. /*
  3355.  * Check if the restricted flag is set.
  3356.  * If so, give an error message and return TRUE.
  3357.  * Otherwise, return FALSE.
  3358.  */
  3359.     int
  3360. check_restricted()
  3361. {
  3362.     if (restricted)
  3363.     {
  3364.     EMSG(_("E145: Shell commands not allowed in rvim"));
  3365.     return TRUE;
  3366.     }
  3367.     return FALSE;
  3368. }
  3369.  
  3370. /*
  3371.  * Check if the secure flag is set (.exrc or .vimrc in current directory).
  3372.  * If so, give an error message and return TRUE.
  3373.  * Otherwise, return FALSE.
  3374.  */
  3375.     int
  3376. check_secure()
  3377. {
  3378.     if (secure)
  3379.     {
  3380.     secure = 2;
  3381.     EMSG(_(e_curdir));
  3382.     return TRUE;
  3383.     }
  3384. #ifdef HAVE_SANDBOX
  3385.     /*
  3386.      * In the sandbox more things are not allowed, including the things
  3387.      * disallowed in secure mode.
  3388.      */
  3389.     if (sandbox != 0)
  3390.     {
  3391.     EMSG(_(e_sandbox));
  3392.     return TRUE;
  3393.     }
  3394. #endif
  3395.     return FALSE;
  3396. }
  3397.  
  3398. static char_u    *old_sub = NULL;    /* previous substitute pattern */
  3399. static int    global_need_beginline;    /* call beginline() after ":g" */
  3400.  
  3401. /*
  3402.  * When ":global" is used to number of substitutions and changed lines is
  3403.  * accumulated until it's finished.
  3404.  */
  3405. static long    sub_nsubs;    /* total number of substitutions */
  3406. static linenr_T    sub_nlines;    /* total number of lines changed */
  3407.  
  3408. /* do_sub()
  3409.  *
  3410.  * Perform a substitution from line eap->line1 to line eap->line2 using the
  3411.  * command pointed to by eap->arg which should be of the form:
  3412.  *
  3413.  * /pattern/substitution/{flags}
  3414.  *
  3415.  * The usual escapes are supported as described in the regexp docs.
  3416.  */
  3417.     void
  3418. do_sub(eap)
  3419.     exarg_T    *eap;
  3420. {
  3421.     linenr_T    lnum;
  3422.     long    i = 0;
  3423.     regmmatch_T regmatch;
  3424.     static int    do_all = FALSE;        /* do multiple substitutions per line */
  3425.     static int    do_ask = FALSE;        /* ask for confirmation */
  3426.     static int    do_error = TRUE;    /* if false, ignore errors */
  3427.     static int    do_print = FALSE;    /* print last line with subs. */
  3428.     static int    do_ic = 0;        /* ignore case flag */
  3429.     char_u    *pat = NULL, *sub = NULL;    /* init for GCC */
  3430.     int        delimiter;
  3431.     int        sublen;
  3432.     int        got_quit = FALSE;
  3433.     int        got_match = FALSE;
  3434.     int        temp;
  3435.     int        which_pat;
  3436.     char_u    *cmd;
  3437.     int        save_State;
  3438.     linenr_T    first_line = 0;    /* first changed line */
  3439.     linenr_T    last_line= 0;    /* below last changed line AFTER the
  3440.                      * change */
  3441.     linenr_T    old_line_count = curbuf->b_ml.ml_line_count;
  3442.     linenr_T    line2;
  3443.     long    nmatch;        /* number of lines in match */
  3444.     linenr_T    sub_firstlnum;    /* nr of first sub line */
  3445.     char_u    *sub_firstline;    /* allocated copy of first sub line */
  3446.  
  3447.     cmd = eap->arg;
  3448.     if (!global_busy)
  3449.     {
  3450.     sub_nsubs = 0;
  3451.     sub_nlines = 0;
  3452.     }
  3453.  
  3454. #ifdef FEAT_FKMAP    /* reverse the flow of the Farsi characters */
  3455.     if (p_altkeymap && curwin->w_p_rl)
  3456.     lrF_sub(cmd);
  3457. #endif
  3458.  
  3459.     if (eap->cmdidx == CMD_tilde)
  3460.     which_pat = RE_LAST;    /* use last used regexp */
  3461.     else
  3462.     which_pat = RE_SUBST;    /* use last substitute regexp */
  3463.  
  3464.                 /* new pattern and substitution */
  3465.     if (eap->cmd[0] == 's' && *cmd != NUL && !vim_iswhite(*cmd)
  3466.         && vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL)
  3467.     {
  3468.                 /* don't accept alphanumeric for separator */
  3469.     if (isalpha(*cmd))
  3470.     {
  3471.         EMSG(_("E146: Regular expressions can't be delimited by letters"));
  3472.         return;
  3473.     }
  3474.     /*
  3475.      * undocumented vi feature:
  3476.      *  "\/sub/" and "\?sub?" use last used search pattern (almost like
  3477.      *  //sub/r).  "\&sub&" use last substitute pattern (like //sub/).
  3478.      */
  3479.     if (*cmd == '\\')
  3480.     {
  3481.         ++cmd;
  3482.         if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
  3483.         {
  3484.         EMSG(_(e_backslash));
  3485.         return;
  3486.         }
  3487.         if (*cmd != '&')
  3488.         which_pat = RE_SEARCH;        /* use last '/' pattern */
  3489.         pat = (char_u *)"";            /* empty search pattern */
  3490.         delimiter = *cmd++;            /* remember delimiter character */
  3491.     }
  3492.     else        /* find the end of the regexp */
  3493.     {
  3494.         which_pat = RE_LAST;        /* use last used regexp */
  3495.         delimiter = *cmd++;            /* remember delimiter character */
  3496.         pat = cmd;                /* remember start of search pat */
  3497.         cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg);
  3498.         if (cmd[0] == delimiter)        /* end delimiter found */
  3499.         *cmd++ = NUL;            /* replace it with a NUL */
  3500.     }
  3501.  
  3502.     /*
  3503.      * Small incompatibility: vi sees '\n' as end of the command, but in
  3504.      * Vim we want to use '\n' to find/substitute a NUL.
  3505.      */
  3506.     sub = cmd;        /* remember the start of the substitution */
  3507.  
  3508.     while (cmd[0])
  3509.     {
  3510.         if (cmd[0] == delimiter)        /* end delimiter found */
  3511.         {
  3512.         *cmd++ = NUL;            /* replace it with a NUL */
  3513.         break;
  3514.         }
  3515.         if (cmd[0] == '\\' && cmd[1] != 0)    /* skip escaped characters */
  3516.         ++cmd;
  3517. #ifdef FEAT_MBYTE
  3518.         if (has_mbyte)
  3519.         cmd += (*mb_ptr2len_check)(cmd);
  3520.         else
  3521. #endif
  3522.         ++cmd;
  3523.     }
  3524.  
  3525.     if (!eap->skip)
  3526.     {
  3527.         vim_free(old_sub);
  3528.         old_sub = vim_strsave(sub);
  3529.     }
  3530.     }
  3531.     else if (!eap->skip)    /* use previous pattern and substitution */
  3532.     {
  3533.     if (old_sub == NULL)    /* there is no previous command */
  3534.     {
  3535.         EMSG(_(e_nopresub));
  3536.         return;
  3537.     }
  3538.     pat = NULL;        /* search_regcomp() will use previous pattern */
  3539.     sub = old_sub;
  3540.     }
  3541.  
  3542.     /*
  3543.      * Find trailing options.  When '&' is used, keep old options.
  3544.      */
  3545.     if (*cmd == '&')
  3546.     ++cmd;
  3547.     else
  3548.     {
  3549.     if (!p_ed)
  3550.     {
  3551.         if (p_gd)        /* default is global on */
  3552.         do_all = TRUE;
  3553.         else
  3554.         do_all = FALSE;
  3555.         do_ask = FALSE;
  3556.     }
  3557.     do_error = TRUE;
  3558.     do_print = FALSE;
  3559.     do_ic = 0;
  3560.     }
  3561.     while (*cmd)
  3562.     {
  3563.     /*
  3564.      * Note that 'g' and 'c' are always inverted, also when p_ed is off.
  3565.      * 'r' is never inverted.
  3566.      */
  3567.     if (*cmd == 'g')
  3568.         do_all = !do_all;
  3569.     else if (*cmd == 'c')
  3570.         do_ask = !do_ask;
  3571.     else if (*cmd == 'e')
  3572.         do_error = !do_error;
  3573.     else if (*cmd == 'r')        /* use last used regexp */
  3574.         which_pat = RE_LAST;
  3575.     else if (*cmd == 'p')
  3576.         do_print = TRUE;
  3577.     else if (*cmd == 'i')        /* ignore case */
  3578.         do_ic = 'i';
  3579.     else if (*cmd == 'I')        /* don't ignore case */
  3580.         do_ic = 'I';
  3581.     else
  3582.         break;
  3583.     ++cmd;
  3584.     }
  3585.  
  3586.     /*
  3587.      * check for a trailing count
  3588.      */
  3589.     cmd = skipwhite(cmd);
  3590.     if (isdigit(*cmd))
  3591.     {
  3592.     i = getdigits(&cmd);
  3593.     if (i <= 0 && !eap->skip && do_error)
  3594.     {
  3595.         EMSG(_(e_zerocount));
  3596.         return;
  3597.     }
  3598.     eap->line1 = eap->line2;
  3599.     eap->line2 += i - 1;
  3600.     if (eap->line2 > curbuf->b_ml.ml_line_count)
  3601.         eap->line2 = curbuf->b_ml.ml_line_count;
  3602.     }
  3603.  
  3604.     /*
  3605.      * check for trailing command or garbage
  3606.      */
  3607.     cmd = skipwhite(cmd);
  3608.     if (*cmd && *cmd != '"')        /* if not end-of-line or comment */
  3609.     {
  3610.     eap->nextcmd = check_nextcmd(cmd);
  3611.     if (eap->nextcmd == NULL)
  3612.     {
  3613.         EMSG(_(e_trailing));
  3614.         return;
  3615.     }
  3616.     }
  3617.  
  3618.     if (eap->skip)        /* not executing commands, only parsing */
  3619.     return;
  3620.  
  3621.     if (search_regcomp(pat, RE_SUBST, which_pat, SEARCH_HIS, ®match) == FAIL)
  3622.     {
  3623.     if (do_error)
  3624.         EMSG(_(e_invcmd));
  3625.     return;
  3626.     }
  3627.  
  3628.     /* the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' */
  3629.     if (do_ic == 'i')
  3630.     regmatch.rmm_ic = TRUE;
  3631.     else if (do_ic == 'I')
  3632.     regmatch.rmm_ic = FALSE;
  3633.  
  3634.     sub_firstline = NULL;
  3635.  
  3636.     /*
  3637.      * ~ in the substitute pattern is replaced with the old pattern.
  3638.      * We do it here once to avoid it to be replaced over and over again.
  3639.      * But don't do it when it starts with "\=", then it's an expression.
  3640.      */
  3641.     if (!(sub[0] == '\\' && sub[1] == '='))
  3642.     sub = regtilde(sub, p_magic);
  3643.  
  3644.     /*
  3645.      * Check for a match on each line.
  3646.      */
  3647.     line2 = eap->line2;
  3648.     for (lnum = eap->line1; lnum <= line2 && !(got_quit
  3649. #if defined(FEAT_EVAL) && defined(FEAT_AUTOCMD)
  3650.         || aborting()
  3651. #endif
  3652.         ); ++lnum)
  3653.     {
  3654.     sub_firstlnum = lnum;
  3655.     nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0);
  3656.     if (nmatch)
  3657.     {
  3658.         colnr_T    copycol;
  3659.         colnr_T    matchcol;
  3660.         colnr_T    prev_matchcol = MAXCOL;
  3661.         char_u    *new_end, *new_start = NULL;
  3662.         unsigned    new_start_len = 0;
  3663.         char_u    *p1;
  3664.         int        did_sub = FALSE;
  3665.         int        lastone;
  3666.         unsigned    len, needed_len;
  3667.         long    nmatch_tl = 0;    /* nr of lines matched below lnum */
  3668.         int        do_again;    /* do it again after joining lines */
  3669.  
  3670.         /*
  3671.          * The new text is build up step by step, to avoid too much
  3672.          * copying.  There are these pieces:
  3673.          * sub_firstline    The old text, unmodifed.
  3674.          * copycol        Column in the old text where we started
  3675.          *            looking for a match; from here old text still
  3676.          *            needs to be copied to the new text.
  3677.          * matchcol        Column number of the old text where to look
  3678.          *            for the next match.  It's just after the
  3679.          *            previous match or one further.
  3680.          * prev_matchcol    Column just after the previous match (if any).
  3681.          *            Mostly equal to matchcol, except for the first
  3682.          *            match and after skipping an empty match.
  3683.          * regmatch.*pos    Where the pattern matched in the old text.
  3684.          * new_start    The new text, all that has been produced so
  3685.          *            far.
  3686.          * new_end        The new text, where to append new text.
  3687.          *
  3688.          * lnum        The line number where we were looking for the
  3689.          *            first match in the old line.
  3690.          * sub_firstlnum    The line number in the buffer where to look
  3691.          *            for a match.  Can be different from "lnum"
  3692.          *            when the pattern or substitute string contains
  3693.          *            line breaks.
  3694.          *
  3695.          * Special situations:
  3696.          * - When the substitute string contains a line break, the part up
  3697.          *   to the line break is inserted in the text, but the copy of
  3698.          *   the original line is kept.  "sub_firstlnum" is adjusted for
  3699.          *   the inserted lines.
  3700.          * - When the matched pattern contains a line break, the old line
  3701.          *   is taken from the line at the end of the pattern.  The lines
  3702.          *   in the match are deleted later, "sub_firstlnum" is adjusted
  3703.          *   accordingly.
  3704.          *
  3705.          * The new text is built up in new_start[].  It has some extra
  3706.          * room to avoid using alloc()/free() too often.  new_start_len is
  3707.          * the lenght of the allocated memory at new_start.
  3708.          *
  3709.          * Make a copy of the old line, so it won't be taken away when
  3710.          * updating the screen or handling a multi-line match.  The "old_"
  3711.          * pointers point into this copy.
  3712.          */
  3713.         sub_firstline = vim_strsave(ml_get(sub_firstlnum));
  3714.         if (sub_firstline == NULL)
  3715.         {
  3716.         vim_free(new_start);
  3717.         goto outofmem;
  3718.         }
  3719.         copycol = 0;
  3720.         matchcol = 0;
  3721.  
  3722.         /* At first match, remember current cursor position. */
  3723.         if (!got_match)
  3724.         {
  3725.         setpcmark();
  3726.         got_match = TRUE;
  3727.         }
  3728.  
  3729.         /*
  3730.          * Loop until nothing more to replace in this line.
  3731.          * 1. Handle match with empty string.
  3732.          * 2. If do_ask is set, ask for confirmation.
  3733.          * 3. substitute the string.
  3734.          * 4. if do_all is set, find next match
  3735.          * 5. break if there isn't another match in this line
  3736.          */
  3737.         for (;;)
  3738.         {
  3739.         /* Save the line number of the last change for the final
  3740.          * cursor position (just like Vi). */
  3741.         curwin->w_cursor.lnum = lnum;
  3742.         do_again = FALSE;
  3743.  
  3744.         /*
  3745.          * 1. Match empty string does not count, except for first
  3746.          * match.  This reproduces the strange vi behaviour.
  3747.          * This also catches endless loops.
  3748.          */
  3749.         if (matchcol == prev_matchcol
  3750.             && regmatch.endpos[0].lnum == 0
  3751.             && matchcol == regmatch.endpos[0].col)
  3752.         {
  3753.             ++matchcol; /* search for a match at next column */
  3754.             goto skip;
  3755.         }
  3756.  
  3757.         /* Normally we continue searching for a match just after the
  3758.          * previous match. */
  3759.         matchcol = regmatch.endpos[0].col;
  3760.         prev_matchcol = matchcol;
  3761.  
  3762.         /*
  3763.          * 2. If do_ask is set, ask for confirmation.
  3764.          */
  3765.         if (do_ask)
  3766.         {
  3767.             /* change State to CONFIRM, so that the mouse works
  3768.              * properly */
  3769.             save_State = State;
  3770.             State = CONFIRM;
  3771. #ifdef FEAT_MOUSE
  3772.             setmouse();        /* disable mouse in xterm */
  3773. #endif
  3774.             curwin->w_cursor.col = regmatch.startpos[0].col;
  3775.  
  3776.             /* When 'cpoptions' contains "u" don't sync undo when
  3777.              * asking for confirmation. */
  3778.             if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
  3779.             ++no_u_sync;
  3780.  
  3781.             /*
  3782.              * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
  3783.              */
  3784.             while (do_ask)
  3785.             {
  3786. #ifdef FEAT_FOLDING
  3787.             int save_p_fen = curwin->w_p_fen;
  3788.  
  3789.             curwin->w_p_fen = FALSE;
  3790. #endif
  3791.             /* Invert the matched string.
  3792.              * Remove the inversion afterwards. */
  3793.             temp = RedrawingDisabled;
  3794.             RedrawingDisabled = 0;
  3795.  
  3796.             search_match_lines = regmatch.endpos[0].lnum;
  3797.             search_match_endcol = regmatch.endpos[0].col;
  3798.             highlight_match = TRUE;
  3799.  
  3800.             update_topline();
  3801.             validate_cursor();
  3802.             update_screen(NOT_VALID);
  3803.             highlight_match = FALSE;
  3804.             redraw_later(NOT_VALID);
  3805.  
  3806. #ifdef FEAT_FOLDING
  3807.             curwin->w_p_fen = save_p_fen;
  3808. #endif
  3809.             if (msg_row == Rows - 1)
  3810.                 msg_didout = FALSE;        /* avoid a scroll-up */
  3811.             msg_starthere();
  3812.             i = msg_scroll;
  3813.             msg_scroll = 0;        /* truncate msg when needed */
  3814.             msg_no_more = TRUE;
  3815.             /* write message same highlighting as for wait_return */
  3816.             smsg_attr(hl_attr(HLF_R),
  3817.                 (char_u *)_("replace with %s (y/n/a/q/l/^E/^Y)?"),
  3818.                 sub);
  3819.             msg_no_more = FALSE;
  3820.             msg_scroll = i;
  3821.             showruler(TRUE);
  3822.             windgoto(msg_row, msg_col);
  3823.             RedrawingDisabled = temp;
  3824.  
  3825. #ifdef USE_ON_FLY_SCROLL
  3826.             dont_scroll = FALSE;    /* allow scrolling here */
  3827. #endif
  3828.             ++no_mapping;        /* don't map this key */
  3829.             ++allow_keys;        /* allow special keys */
  3830.             i = safe_vgetc();
  3831.             --allow_keys;
  3832.             --no_mapping;
  3833.  
  3834.             /* clear the question */
  3835.             msg_didout = FALSE;    /* don't scroll up */
  3836.             msg_col = 0;
  3837.             gotocmdline(TRUE);
  3838.             need_wait_return = FALSE; /* no hit-return prompt */
  3839.             if (i == 'q' || i == ESC || i == Ctrl_C
  3840. #ifdef UNIX
  3841.                 || i == intr_char
  3842. #endif
  3843.                 )
  3844.             {
  3845.                 got_quit = TRUE;
  3846.                 break;
  3847.             }
  3848.             if (i == 'n')
  3849.                 break;
  3850.             if (i == 'y')
  3851.                 break;
  3852.             if (i == 'l')
  3853.             {
  3854.                 /* last: replace and then stop */
  3855.                 do_all = FALSE;
  3856.                 line2 = lnum;
  3857.                 break;
  3858.             }
  3859.             if (i == 'a')
  3860.             {
  3861.                 do_ask = FALSE;
  3862.                 break;
  3863.             }
  3864. #ifdef FEAT_INS_EXPAND
  3865.             if (i == Ctrl_E)
  3866.                 scrollup_clamp();
  3867.             else if (i == Ctrl_Y)
  3868.                 scrolldown_clamp();
  3869. #endif
  3870.             }
  3871.             State = save_State;
  3872. #ifdef FEAT_MOUSE
  3873.             setmouse();
  3874. #endif
  3875.             if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
  3876.             --no_u_sync;
  3877.  
  3878.             if (i == 'n')
  3879.             {
  3880.             /* For a multi-line match, put matchcol at the NUL at
  3881.              * the end of the line and set nmatch to one, so that
  3882.              * we continue looking for a match on the next line.
  3883.              * Avoids that ":s/\nB\@=//gc" get stuck. */
  3884.             if (nmatch > 1)
  3885.             {
  3886.                 matchcol = STRLEN(sub_firstline);
  3887.                 nmatch = 1;
  3888.             }
  3889.             goto skip;
  3890.             }
  3891.             if (got_quit)
  3892.             break;
  3893.         }
  3894.  
  3895.         /* Move the cursor to the start of the line, to avoid that it
  3896.          * is beyond the end of the line after the substitution. */
  3897.         curwin->w_cursor.col = 0;
  3898.  
  3899.         /*
  3900.          * 3. substitute the string.
  3901.          */
  3902.         /* get length of substitution part */
  3903.         sublen = vim_regsub_multi(®match, sub_firstlnum,
  3904.                     sub, sub_firstline, FALSE, p_magic, TRUE);
  3905.  
  3906.         /* Need room for:
  3907.          * - result so far in new_start (not for first sub in line)
  3908.          * - original text up to match
  3909.          * - length of substituted part
  3910.          * - original text after match
  3911.          */
  3912.         if (nmatch == 1)
  3913.             p1 = sub_firstline;
  3914.         else
  3915.         {
  3916.             p1 = ml_get(sub_firstlnum + nmatch - 1);
  3917.             nmatch_tl += nmatch - 1;
  3918.         }
  3919.         i = regmatch.startpos[0].col - copycol;
  3920.         needed_len = i + ((unsigned)STRLEN(p1) - regmatch.endpos[0].col)
  3921.                                  + sublen + 1;
  3922.         if (new_start == NULL)
  3923.         {
  3924.             /*
  3925.              * Get some space for a temporary buffer to do the
  3926.              * substitution into (and some extra space to avoid
  3927.              * too many calls to alloc()/free()).
  3928.              */
  3929.             new_start_len = needed_len + 50;
  3930.             if ((new_start = alloc_check(new_start_len)) == NULL)
  3931.             goto outofmem;
  3932.             *new_start = NUL;
  3933.             new_end = new_start;
  3934.         }
  3935.         else
  3936.         {
  3937.             /*
  3938.              * Check if the temporary buffer is long enough to do the
  3939.              * substitution into.  If not, make it larger (with a bit
  3940.              * extra to avoid too many calls to alloc()/free()).
  3941.              */
  3942.             len = (unsigned)STRLEN(new_start);
  3943.             needed_len += len;
  3944.             if (needed_len > new_start_len)
  3945.             {
  3946.             new_start_len = needed_len + 50;
  3947.             if ((p1 = alloc_check(new_start_len)) == NULL)
  3948.             {
  3949.                 vim_free(new_start);
  3950.                 goto outofmem;
  3951.             }
  3952.             mch_memmove(p1, new_start, (size_t)(len + 1));
  3953.             vim_free(new_start);
  3954.             new_start = p1;
  3955.             }
  3956.             new_end = new_start + len;
  3957.         }
  3958.  
  3959.         /*
  3960.          * copy the text up to the part that matched
  3961.          */
  3962.         mch_memmove(new_end, sub_firstline + copycol, (size_t)i);
  3963.         new_end += i;
  3964.  
  3965.         (void)vim_regsub_multi(®match, sub_firstlnum,
  3966.                        sub, new_end, TRUE, p_magic, TRUE);
  3967.         sub_nsubs++;
  3968.         did_sub = TRUE;
  3969.  
  3970.         /* For a multi-line match, make a copy of the last matched
  3971.          * line and continue in that one. */
  3972.         if (nmatch > 1)
  3973.         {
  3974.             sub_firstlnum += nmatch - 1;
  3975.             vim_free(sub_firstline);
  3976.             sub_firstline = vim_strsave(ml_get(sub_firstlnum));
  3977.             /* When going beyond the last line, stop substituting. */
  3978.             if (sub_firstlnum <= line2)
  3979.             do_again = TRUE;
  3980.             else
  3981.             do_all = FALSE;
  3982.         }
  3983.  
  3984.         /* Remember next character to be copied. */
  3985.         copycol = regmatch.endpos[0].col;
  3986.  
  3987.         /*
  3988.          * Now the trick is to replace CTRL-M chars with a real line
  3989.          * break.  This would make it impossible to insert a CTRL-M in
  3990.          * the text.  The line break can be avoided by preceding the
  3991.          * CTRL-M with a backslash.  To be able to insert a backslash,
  3992.          * they must be doubled in the string and are halved here.
  3993.          * That is Vi compatible.
  3994.          */
  3995.         for (p1 = new_end; *p1; ++p1)
  3996.         {
  3997.             if (p1[0] == '\\' && p1[1] != NUL)  /* remove backslash */
  3998.             mch_memmove(p1, p1 + 1, STRLEN(p1));
  3999.             else if (*p1 == CR)
  4000.             {
  4001.             if (u_inssub(lnum) == OK)   /* prepare for undo */
  4002.             {
  4003.                 *p1 = NUL;            /* truncate up to the CR */
  4004.                 ml_append(lnum - 1, new_start,
  4005.                     (colnr_T)(p1 - new_start + 1), FALSE);
  4006.                 mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
  4007.                 if (do_ask)
  4008.                 appended_lines(lnum - 1, 1L);
  4009.                 else
  4010.                 {
  4011.                 if (first_line == 0)
  4012.                     first_line = lnum;
  4013.                 last_line = lnum + 1;
  4014.                 }
  4015.                 /* All line numbers increase. */
  4016.                 ++sub_firstlnum;
  4017.                 ++lnum;
  4018.                 ++line2;
  4019.                 /* move the cursor to the new line, like Vi */
  4020.                 ++curwin->w_cursor.lnum;
  4021.                 STRCPY(new_start, p1 + 1);    /* copy the rest */
  4022.                 p1 = new_start - 1;
  4023.             }
  4024.             }
  4025. #ifdef FEAT_MBYTE
  4026.             else if (has_mbyte)
  4027.             p1 += (*mb_ptr2len_check)(p1) - 1;
  4028. #endif
  4029.         }
  4030.  
  4031.         /*
  4032.          * 4. If do_all is set, find next match.
  4033.          * Prevent endless loop with patterns that match empty
  4034.          * strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g.
  4035.          * But ":s/\n/#/" is OK.
  4036.          */
  4037. skip:
  4038.         lastone = ((sub_firstline[matchcol] == NUL && nmatch <= 1)
  4039.                  || got_int || got_quit || !(do_all || do_again));
  4040.         nmatch = -1;
  4041.         /* The check for nmatch_tl is needed for when multi-line
  4042.          * matching must replace the lines before trying to do another
  4043.          * match, otherwise "\@<=" won't work. */
  4044.         if (lastone
  4045.             || do_ask
  4046.             || nmatch_tl > 0
  4047.             || (nmatch = vim_regexec_multi(®match, curwin,
  4048.                        curbuf, sub_firstlnum, matchcol)) == 0)
  4049.         {
  4050.             if (new_start != NULL)
  4051.             {
  4052.             /*
  4053.              * Copy the rest of the line, that didn't match.
  4054.              * matchcol has to be adjusted, we use the end of the
  4055.              * line as reference, because the substitute may have
  4056.              * changed the number of characters.
  4057.              */
  4058.             STRCAT(new_start, sub_firstline + copycol);
  4059.             matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
  4060.  
  4061.             if (u_savesub(lnum) != OK)
  4062.                 break;
  4063.             ml_replace(lnum, new_start, TRUE);
  4064.  
  4065.             if (nmatch_tl > 0)
  4066.             {
  4067.                 /*
  4068.                  * Matched lines have now been substituted and are
  4069.                  * useless, delete them.  The part after the match
  4070.                  * has been appended to new_start, we don't need
  4071.                  * it in the buffer.
  4072.                  */
  4073.                 ++lnum;
  4074.                 if (u_savedel(lnum, nmatch_tl) != OK)
  4075.                 break;
  4076.                 for (i = 0; i < nmatch_tl; ++i)
  4077.                 ml_delete(lnum, (int)FALSE);
  4078.                 mark_adjust(lnum, lnum + nmatch_tl - 1,
  4079.                            (long)MAXLNUM, -nmatch_tl);
  4080.                 if (do_ask)
  4081.                 deleted_lines(lnum, nmatch_tl);
  4082.                 --lnum;
  4083.                 line2 -= nmatch_tl; /* nr of lines decreases */
  4084.                 nmatch_tl = 0;
  4085.             }
  4086.  
  4087.             /* When asking, undo is saved each time, must also set
  4088.              * changed flag each time. */
  4089.             if (do_ask)
  4090.                 changed_bytes(lnum, 0);
  4091.             else
  4092.             {
  4093.                 if (first_line == 0)
  4094.                 first_line = lnum;
  4095.                 last_line = lnum + 1;
  4096.             }
  4097.  
  4098.             sub_firstlnum = lnum;
  4099.             vim_free(sub_firstline);    /* free the temp buffer */
  4100.             sub_firstline = new_start;
  4101.             new_start = NULL;
  4102.             matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
  4103.             copycol = 0;
  4104.             }
  4105.             if (nmatch == -1 && !lastone)
  4106.             nmatch = vim_regexec_multi(®match, curwin, curbuf,
  4107.                              sub_firstlnum, matchcol);
  4108.  
  4109.             /*
  4110.              * 5. break if there isn't another match in this line
  4111.              */
  4112.             if (nmatch <= 0)
  4113.             break;
  4114.         }
  4115.  
  4116.         line_breakcheck();
  4117.         }
  4118.  
  4119.         if (did_sub)
  4120.         ++sub_nlines;
  4121.         vim_free(sub_firstline);    /* free the copy of the original line */
  4122.         sub_firstline = NULL;
  4123.     }
  4124.  
  4125.     line_breakcheck();
  4126.     }
  4127.  
  4128.     if (first_line != 0)
  4129.     {
  4130.     /* Need to subtract the number of added lines from "last_line" to get
  4131.      * the line number before the change (same as adding the number of
  4132.      * deleted lines). */
  4133.     i = curbuf->b_ml.ml_line_count - old_line_count;
  4134.     changed_lines(first_line, 0, last_line - i, i);
  4135.     }
  4136.  
  4137. outofmem:
  4138.     vim_free(sub_firstline); /* may have to free allocated copy of the line */
  4139.     if (sub_nsubs)
  4140.     {
  4141.     /* Set the '[ and '] marks. */
  4142.     curbuf->b_op_start.lnum = eap->line1;
  4143.     curbuf->b_op_end.lnum = line2;
  4144.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  4145.  
  4146.     if (!global_busy)
  4147.     {
  4148.         beginline(BL_WHITE | BL_FIX);
  4149.         if (!do_sub_msg() && do_ask)
  4150.         MSG("");
  4151.     }
  4152.     else
  4153.         global_need_beginline = TRUE;
  4154.     if (do_print)
  4155.         print_line(curwin->w_cursor.lnum, FALSE);
  4156.     }
  4157.     else if (!global_busy)
  4158.     {
  4159.     if (got_int)        /* interrupted */
  4160.         EMSG(_(e_interr));
  4161.     else if (got_match)    /* did find something but nothing substituted */
  4162.         MSG("");
  4163.     else if (do_error)    /* nothing found */
  4164.         EMSG2(_(e_patnotf2), get_search_pat());
  4165.     }
  4166.  
  4167.     vim_free(regmatch.regprog);
  4168. }
  4169.  
  4170. /*
  4171.  * Give message for number of substitutions.
  4172.  * Can also be used after a ":global" command.
  4173.  * Return TRUE if a message was given.
  4174.  */
  4175.     static int
  4176. do_sub_msg()
  4177. {
  4178.     /*
  4179.      * Only report substitutions when:
  4180.      * - more than 'report' substitutions
  4181.      * - command was typed by user, or number of changed lines > 'report'
  4182.      * - giving messages is not disabled by 'lazyredraw'
  4183.      */
  4184.     if (sub_nsubs > p_report
  4185.         && (KeyTyped || sub_nlines > 1 || p_report < 1)
  4186.         && messaging())
  4187.     {
  4188.     if (got_int)
  4189.         STRCPY(msg_buf, _("(Interrupted) "));
  4190.     else
  4191.         msg_buf[0] = NUL;
  4192.     if (sub_nsubs == 1)
  4193.         STRCAT(msg_buf, _("1 substitution"));
  4194.     else
  4195.         sprintf((char *)msg_buf + STRLEN(msg_buf), _("%ld substitutions"),
  4196.                                    sub_nsubs);
  4197.     if (sub_nlines == 1)
  4198.         STRCAT(msg_buf, _(" on 1 line"));
  4199.     else
  4200.         sprintf((char *)msg_buf + STRLEN(msg_buf), _(" on %ld lines"),
  4201.                                 (long)sub_nlines);
  4202.     if (msg(msg_buf))
  4203.     {
  4204.         /* save message to display it after redraw */
  4205.         set_keep_msg(msg_buf);
  4206.         keep_msg_attr = 0;
  4207.     }
  4208.     return TRUE;
  4209.     }
  4210.     if (got_int)
  4211.     {
  4212.     EMSG(_(e_interr));
  4213.     return TRUE;
  4214.     }
  4215.     return FALSE;
  4216. }
  4217.  
  4218. /*
  4219.  * Execute a global command of the form:
  4220.  *
  4221.  * g/pattern/X : execute X on all lines where pattern matches
  4222.  * v/pattern/X : execute X on all lines where pattern does not match
  4223.  *
  4224.  * where 'X' is an EX command
  4225.  *
  4226.  * The command character (as well as the trailing slash) is optional, and
  4227.  * is assumed to be 'p' if missing.
  4228.  *
  4229.  * This is implemented in two passes: first we scan the file for the pattern and
  4230.  * set a mark for each line that (not) matches. secondly we execute the command
  4231.  * for each line that has a mark. This is required because after deleting
  4232.  * lines we do not know where to search for the next match.
  4233.  */
  4234.     void
  4235. ex_global(eap)
  4236.     exarg_T    *eap;
  4237. {
  4238.     linenr_T    lnum;        /* line number according to old situation */
  4239.     int        ndone;
  4240.     int        type;        /* first char of cmd: 'v' or 'g' */
  4241.     char_u    *cmd;        /* command argument */
  4242.  
  4243.     char_u    delim;        /* delimiter, normally '/' */
  4244.     char_u    *pat;
  4245.     regmmatch_T    regmatch;
  4246.     int        match;
  4247.     int        which_pat;
  4248.  
  4249.     if (global_busy)
  4250.     {
  4251.     EMSG(_("E147: Cannot do :global recursive"));    /* will increment global_busy */
  4252.     return;
  4253.     }
  4254.  
  4255.     if (eap->forceit)            /* ":global!" is like ":vglobal" */
  4256.     type = 'v';
  4257.     else
  4258.     type = *eap->cmd;
  4259.     cmd = eap->arg;
  4260.     which_pat = RE_LAST;        /* default: use last used regexp */
  4261.     sub_nsubs = 0;
  4262.     sub_nlines = 0;
  4263.  
  4264.     /*
  4265.      * undocumented vi feature:
  4266.      *    "\/" and "\?": use previous search pattern.
  4267.      *         "\&": use previous substitute pattern.
  4268.      */
  4269.     if (*cmd == '\\')
  4270.     {
  4271.     ++cmd;
  4272.     if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
  4273.     {
  4274.         EMSG(_(e_backslash));
  4275.         return;
  4276.     }
  4277.     if (*cmd == '&')
  4278.         which_pat = RE_SUBST;    /* use previous substitute pattern */
  4279.     else
  4280.         which_pat = RE_SEARCH;    /* use previous search pattern */
  4281.     ++cmd;
  4282.     pat = (char_u *)"";
  4283.     }
  4284.     else if (*cmd == NUL)
  4285.     {
  4286.     EMSG(_("E148: Regular expression missing from global"));
  4287.     return;
  4288.     }
  4289.     else
  4290.     {
  4291.     delim = *cmd;        /* get the delimiter */
  4292.     if (delim)
  4293.         ++cmd;        /* skip delimiter if there is one */
  4294.     pat = cmd;        /* remember start of pattern */
  4295.     cmd = skip_regexp(cmd, delim, p_magic, &eap->arg);
  4296.     if (cmd[0] == delim)            /* end delimiter found */
  4297.         *cmd++ = NUL;            /* replace it with a NUL */
  4298.     }
  4299.  
  4300. #ifdef FEAT_FKMAP    /* when in Farsi mode, reverse the character flow */
  4301.     if (p_altkeymap && curwin->w_p_rl)
  4302.     lrFswap(pat,0);
  4303. #endif
  4304.  
  4305.     if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, ®match) == FAIL)
  4306.     {
  4307.     EMSG(_(e_invcmd));
  4308.     return;
  4309.     }
  4310.  
  4311.     /*
  4312.      * pass 1: set marks for each (not) matching line
  4313.      */
  4314.     ndone = 0;
  4315.     for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
  4316.     {
  4317.     /* a match on this line? */
  4318.     match = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0);
  4319.     if ((type == 'g' && match) || (type == 'v' && !match))
  4320.     {
  4321.         ml_setmarked(lnum);
  4322.         ndone++;
  4323.     }
  4324.     line_breakcheck();
  4325.     }
  4326.  
  4327.     /*
  4328.      * pass 2: execute the command for each line that has been marked
  4329.      */
  4330.     if (got_int)
  4331.     MSG(_(e_interr));
  4332.     else if (ndone == 0)
  4333.     {
  4334.     if (type == 'v')
  4335.         msg_str((char_u *)_("Pattern found in every line: %s"), pat);
  4336.     else
  4337.         msg_str((char_u *)_(e_patnotf2), pat);
  4338.     }
  4339.     else
  4340.     global_exe(cmd);
  4341.  
  4342.     ml_clearmarked();       /* clear rest of the marks */
  4343.     vim_free(regmatch.regprog);
  4344. }
  4345.  
  4346. /*
  4347.  * Execute "cmd" on lines marked with ml_setmarked().
  4348.  */
  4349.     void
  4350. global_exe(cmd)
  4351.     char_u    *cmd;
  4352. {
  4353.     linenr_T    old_lcount;    /* b_ml.ml_line_count before the command */
  4354.     linenr_T    lnum;        /* line number according to old situation */
  4355.  
  4356.     /*
  4357.      * Set current position only once for a global command.
  4358.      * If global_busy is set, setpcmark() will not do anything.
  4359.      * If there is an error, global_busy will be incremented.
  4360.      */
  4361.     setpcmark();
  4362.  
  4363.     /* When the command writes a message, don't overwrite the command. */
  4364.     msg_didout = TRUE;
  4365.  
  4366.     global_need_beginline = FALSE;
  4367.     global_busy = 1;
  4368.     old_lcount = curbuf->b_ml.ml_line_count;
  4369.     while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1)
  4370.     {
  4371.     curwin->w_cursor.lnum = lnum;
  4372.     curwin->w_cursor.col = 0;
  4373.     if (*cmd == NUL || *cmd == '\n')
  4374.         do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
  4375.     else
  4376.         do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
  4377.     ui_breakcheck();
  4378.     }
  4379.  
  4380.     global_busy = 0;
  4381.     if (global_need_beginline)
  4382.     beginline(BL_WHITE | BL_FIX);
  4383.     else
  4384.     check_cursor();    /* cursor may be beyond the end of the line */
  4385.  
  4386.     /* If it looks like no message was written, allow overwriting the
  4387.      * command with the report for number of changes. */
  4388.     if (msg_col == 0 && msg_scrolled == 0)
  4389.     msg_didout = FALSE;
  4390.  
  4391.     /* If subsitutes done, report number of substitues, otherwise report
  4392.      * number of extra or deleted lines. */
  4393.     if (!do_sub_msg())
  4394.     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  4395. }
  4396.  
  4397. #ifdef FEAT_VIMINFO
  4398.     int
  4399. read_viminfo_sub_string(virp, force)
  4400.     vir_T    *virp;
  4401.     int        force;
  4402. {
  4403.     if (old_sub != NULL && force)
  4404.     vim_free(old_sub);
  4405.     if (force || old_sub == NULL)
  4406.     old_sub = viminfo_readstring(virp, 1, TRUE);
  4407.     return viminfo_readline(virp);
  4408. }
  4409.  
  4410.     void
  4411. write_viminfo_sub_string(fp)
  4412.     FILE    *fp;
  4413. {
  4414.     if (get_viminfo_parameter('/') != 0 && old_sub != NULL)
  4415.     {
  4416.     fprintf(fp, _("\n# Last Substitute String:\n$"));
  4417.     viminfo_writestring(fp, old_sub);
  4418.     }
  4419. }
  4420. #endif /* FEAT_VIMINFO */
  4421.  
  4422. #if (defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)) || defined(PROTO)
  4423. /*
  4424.  * Set up for a tagpreview.
  4425.  */
  4426.     void
  4427. prepare_tagpreview()
  4428. {
  4429.     win_T    *wp;
  4430.  
  4431. # ifdef FEAT_GUI
  4432.     need_mouse_correct = TRUE;
  4433. # endif
  4434.  
  4435.     /*
  4436.      * If there is already a preview window open, use that one.
  4437.      */
  4438.     if (!curwin->w_p_pvw)
  4439.     {
  4440.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  4441.         if (wp->w_p_pvw)
  4442.         break;
  4443.     if (wp != NULL)
  4444.         win_enter(wp, TRUE);
  4445.     else
  4446.     {
  4447.         /*
  4448.          * There is no preview window open yet.  Create one.
  4449.          */
  4450.         if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
  4451.                                       == FAIL)
  4452.         return;
  4453.         curwin->w_p_pvw = TRUE;
  4454.         curwin->w_p_wfh = TRUE;
  4455. # ifdef FEAT_SCROLLBIND
  4456.         curwin->w_p_scb = FALSE;        /* don't take over 'scrollbind' */
  4457. # endif
  4458. # ifdef FEAT_DIFF
  4459.         curwin->w_p_diff = FALSE;        /* no 'diff' */
  4460. # endif
  4461. # ifdef FEAT_FOLDING
  4462.         curwin->w_p_fdc = 0;        /* no 'foldcolumn' */
  4463. # endif
  4464.     }
  4465.     }
  4466. }
  4467.  
  4468. #endif
  4469.  
  4470.  
  4471. /*
  4472.  * ":help": open a read-only window on a help file
  4473.  */
  4474.     void
  4475. ex_help(eap)
  4476.     exarg_T    *eap;
  4477. {
  4478.     char_u    *arg;
  4479.     FILE    *helpfd;    /* file descriptor of help file */
  4480.     int        n;
  4481. #ifdef FEAT_WINDOWS
  4482.     win_T    *wp;
  4483. #endif
  4484.     int        num_matches;
  4485.     char_u    **matches;
  4486.     int        need_free = FALSE;
  4487.     char_u    *p;
  4488.     int        empty_fnum = 0;
  4489.     int        alt_fnum = 0;
  4490.     buf_T    *buf;
  4491.  
  4492.     if (eap != NULL)
  4493.     {
  4494.     /*
  4495.      * A ":help" command ends at the first LF, or at a '|' that is
  4496.      * followed by some text.  Set nextcmd to the following command.
  4497.      */
  4498.     for (arg = eap->arg; *arg; ++arg)
  4499.     {
  4500.         if (*arg == '\n' || *arg == '\r'
  4501.             || (*arg == '|' && arg[1] != NUL && arg[1] != '|'))
  4502.         {
  4503.         *arg++ = NUL;
  4504.         eap->nextcmd = arg;
  4505.         break;
  4506.         }
  4507.     }
  4508.     arg = eap->arg;
  4509.  
  4510.     if (eap->skip)        /* not executing commands */
  4511.         return;
  4512.     }
  4513.     else
  4514.     arg = (char_u *)"";
  4515.  
  4516.     /*
  4517.      * If an argument is given, check if there is a match for it.
  4518.      */
  4519.     if (*arg != NUL)
  4520.     {
  4521.     /* remove trailing blanks */
  4522.     p = arg + STRLEN(arg) - 1;
  4523.     while (p > arg && vim_iswhite(*p) && p[-1] != '\\')
  4524.         *p-- = NUL;
  4525.  
  4526.     n = find_help_tags(arg, &num_matches, &matches);
  4527.     if (num_matches == 0 || n == FAIL)
  4528.     {
  4529.         EMSG2(_("E149: Sorry, no help for %s"), arg);
  4530.         return;
  4531.     }
  4532.  
  4533.     /* The first match is the best match. */
  4534.     arg = vim_strsave(matches[0]);
  4535.     need_free = TRUE;
  4536.     FreeWild(num_matches, matches);
  4537.     }
  4538.  
  4539. #ifdef FEAT_GUI
  4540.     need_mouse_correct = TRUE;
  4541. #endif
  4542.  
  4543.     /*
  4544.      * Re-use an existing help window or open a new one.
  4545.      */
  4546.     if (!curwin->w_buffer->b_help)
  4547.     {
  4548. #ifdef FEAT_WINDOWS
  4549.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  4550.         if (wp->w_buffer != NULL && wp->w_buffer->b_help)
  4551.         break;
  4552.     if (wp != NULL && wp->w_buffer->b_nwindows > 0)
  4553.         win_enter(wp, TRUE);
  4554.     else
  4555. #endif
  4556.     {
  4557.         /*
  4558.          * There is no help window yet.
  4559.          * Try to open the file specified by the "helpfile" option.
  4560.          */
  4561.         if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL)
  4562.         {
  4563.         msg_str((char_u *)_("Sorry, help file \"%s\" not found"),
  4564.                                     p_hf);
  4565.         goto erret;
  4566.         }
  4567.         fclose(helpfd);
  4568.  
  4569. #ifdef FEAT_WINDOWS
  4570.         /* Split off help window; put it at far top if no position
  4571.          * specified, the current window is vertically split and narrow. */
  4572.         n = WSP_HELP;
  4573. # ifdef FEAT_VERTSPLIT
  4574.         if (cmdmod.split == 0 && curwin->w_width != Columns
  4575.                               && curwin->w_width < 80)
  4576.         n |= WSP_TOP;
  4577. # endif
  4578.         if (win_split(0, n) == FAIL)
  4579. #else
  4580.         /* use current window */
  4581.         if (!can_abandon(curbuf, FALSE))
  4582. #endif
  4583.         goto erret;
  4584.  
  4585. #ifdef FEAT_WINDOWS
  4586.         if (curwin->w_height < p_hh)
  4587.         win_setheight((int)p_hh);
  4588. #endif
  4589.  
  4590.         /*
  4591.          * Open help file (do_ecmd() will set b_help flag, readfile() will
  4592.          * set b_p_ro flag).
  4593.          * Set the alternate file to the previously edited file.
  4594.          */
  4595.         alt_fnum = curbuf->b_fnum;
  4596.         (void)do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
  4597.                            ECMD_HIDE + ECMD_SET_HELP);
  4598.         curwin->w_alt_fnum = alt_fnum;
  4599.         empty_fnum = curbuf->b_fnum;
  4600.     }
  4601.     }
  4602.  
  4603.     if (!p_im)
  4604.     restart_edit = 0;        /* don't want insert mode in help file */
  4605.  
  4606.     if (arg == NULL || *arg == NUL)
  4607.     {
  4608.     arg = (char_u *)"help.txt";        /* go to the index */
  4609.     need_free = FALSE;
  4610.     }
  4611.     do_tag(arg, DT_HELP, 1, FALSE, TRUE);
  4612.  
  4613.     /* Delete the empty buffer if we're not using it. */
  4614.     if (empty_fnum != 0 && curbuf->b_fnum != empty_fnum)
  4615.     {
  4616.     buf = buflist_findnr(empty_fnum);
  4617.     if (buf != NULL)
  4618.         wipe_buffer(buf, TRUE);
  4619.     }
  4620.  
  4621.     /* keep the previous alternate file */
  4622.     if (alt_fnum != 0 && curwin->w_alt_fnum == empty_fnum)
  4623.     curwin->w_alt_fnum = alt_fnum;
  4624.  
  4625.     /*
  4626.      * Always set these options after jumping to a help tag, because the user
  4627.      * may have an autocommand that gets in the way.
  4628.      * accept all chars for keywords, except ' ', '*', '"', '|'.
  4629.      * Only set it when needed, buf_init_chartab() is some work.
  4630.      */
  4631.     p =
  4632. #ifdef EBCDIC
  4633.         (char_u *)"65-255,^*,^|,^\"";
  4634. #else
  4635.         (char_u *)"!-~,^*,^|,^\"";
  4636. #endif
  4637.     if (STRCMP(curbuf->b_p_isk, p) != 0)
  4638.     {
  4639.     set_string_option_direct((char_u *)"isk", -1, p, OPT_FREE|OPT_LOCAL);
  4640.     check_buf_options(curbuf);
  4641.     (void)buf_init_chartab(curbuf, FALSE);
  4642.     }
  4643.  
  4644.     curbuf->b_p_ts = 8;
  4645.     curwin->w_p_list = FALSE;
  4646.  
  4647. erret:
  4648.     if (need_free)
  4649.     vim_free(arg);
  4650. }
  4651.  
  4652.  
  4653. /*
  4654.  * Return a heuristic indicating how well the given string matches.  The
  4655.  * smaller the number, the better the match.  This is the order of priorities,
  4656.  * from best match to worst match:
  4657.  *    - Match with least alpha-numeric characters is better.
  4658.  *    - Match with least total characters is better.
  4659.  *    - Match towards the start is better.
  4660.  *    - Match starting with "+" is worse (feature instead of command)
  4661.  * Assumption is made that the matched_string passed has already been found to
  4662.  * match some string for which help is requested.  webb.
  4663.  */
  4664.     int
  4665. help_heuristic(matched_string, offset, wrong_case)
  4666.     char_u    *matched_string;
  4667.     int        offset;            /* offset for match */
  4668.     int        wrong_case;        /* no matching case */
  4669. {
  4670.     int        num_letters;
  4671.     char_u    *p;
  4672.  
  4673.     num_letters = 0;
  4674.     for (p = matched_string; *p; p++)
  4675.     if (ASCII_ISALNUM(*p))
  4676.         num_letters++;
  4677.  
  4678.     /*
  4679.      * Multiply the number of letters by 100 to give it a much bigger
  4680.      * weighting than the number of characters.
  4681.      * If there only is a match while ignoring case, add 5000.
  4682.      * If the match starts in the middle of a word, add 10000 to put it
  4683.      * somewhere in the last half.
  4684.      * If the match is more than 2 chars from the start, multiply by 200 to
  4685.      * put it after matches at the start.
  4686.      */
  4687.     if (ASCII_ISALNUM(matched_string[offset]) && offset > 0
  4688.                  && ASCII_ISALNUM(matched_string[offset - 1]))
  4689.     offset += 10000;
  4690.     else if (offset > 2)
  4691.     offset *= 200;
  4692.     if (wrong_case)
  4693.     offset += 5000;
  4694.     /* Features are less interesting than the subjects themselves, but "+"
  4695.      * alone is not a feature. */
  4696.     if (matched_string[0] == '+' && matched_string[1] != NUL)
  4697.     offset += 100;
  4698.     return (int)(100 * num_letters + STRLEN(matched_string) + offset);
  4699. }
  4700.  
  4701. /*
  4702.  * Compare functions for qsort() below, that checks the help heuristics number
  4703.  * that has been put after the tagname by find_tags().
  4704.  */
  4705.     static int
  4706. #ifdef __BORLANDC__
  4707. _RTLENTRYF
  4708. #endif
  4709. help_compare(s1, s2)
  4710.     const void    *s1;
  4711.     const void    *s2;
  4712. {
  4713.     char    *p1;
  4714.     char    *p2;
  4715.  
  4716.     p1 = *(char **)s1 + strlen(*(char **)s1) + 1;
  4717.     p2 = *(char **)s2 + strlen(*(char **)s2) + 1;
  4718.     return strcmp(p1, p2);
  4719. }
  4720.  
  4721. /*
  4722.  * Find all help tags matching "arg", sort them and return in matches[], with
  4723.  * the number of matches in num_matches.
  4724.  * The matches will be sorted with a "best" match algorithm.
  4725.  */
  4726.     int
  4727. find_help_tags(arg, num_matches, matches)
  4728.     char_u    *arg;
  4729.     int        *num_matches;
  4730.     char_u    ***matches;
  4731. {
  4732.     char_u    *s, *d;
  4733.     int        i;
  4734.     static char *(mtable[]) = {"*", "g*", "[*", "]*", ":*",
  4735.                    "/*", "/\\*", "\"*", "/\\(\\)",
  4736.                    "?", ":?", "?<CR>", "g?", "g?g?", "g??",
  4737.                    "/\\?", "/\\z(\\)",
  4738.                    "[count]", "[quotex]", "[range]",
  4739.                    "[pattern]", "\\|", "\\%$"};
  4740.     static char *(rtable[]) = {"star", "gstar", "[star", "]star", ":star",
  4741.                    "/star", "/\\\\star", "quotestar", "/\\\\(\\\\)",
  4742.                    "?", ":?", "?<CR>", "g?", "g?g?", "g??",
  4743.                    "/\\\\?", "/\\\\z(\\\\)",
  4744.                    "\\[count]", "\\[quotex]", "\\[range]",
  4745.                    "\\[pattern]", "\\\\bar", "/\\\\%\\$"};
  4746.  
  4747.     d = IObuff;            /* assume IObuff is long enough! */
  4748.  
  4749.     /*
  4750.      * Recognize a few exceptions to the rule.    Some strings that contain '*'
  4751.      * with "star".  Otherwise '*' is recognized as a wildcard.
  4752.      */
  4753.     for (i = sizeof(mtable) / sizeof(char *); --i >= 0; )
  4754.     if (STRCMP(arg, mtable[i]) == 0)
  4755.     {
  4756.         STRCPY(d, rtable[i]);
  4757.         break;
  4758.     }
  4759.  
  4760.     if (i < 0)    /* no match in table */
  4761.     {
  4762.     /* Replace "\S" with "/\\S", etc.  Otherwise every tag is matched.
  4763.      * Also replace "\%^" and "\%(", they match every tag too.
  4764.      * And also "\_$" and "\_^". */
  4765.  
  4766.     if (arg[0] == '\\'
  4767.         && ((arg[1] != NUL && arg[2] == NUL)
  4768.             || ((arg[1] == '%' || arg[1] == '_')
  4769.                       && arg[2] != NUL && arg[3] == NUL)))
  4770.     {
  4771.         STRCPY(d, "/\\\\");
  4772.         STRCPY(d + 3, arg + 1);
  4773.         /* Check for "/\\_$", should be "/\\_\$" */
  4774.         if (d[3] == '_' && d[4] == '$')
  4775.         STRCPY(d + 4, "\\$");
  4776.     }
  4777.     else
  4778.     {
  4779.       /* replace "[:...:]" with "\[:...:]"; "[+...]" with "\[++...]" */
  4780.         if (arg[0] == '[' && (arg[1] == ':'
  4781.                      || (arg[1] == '+' && arg[2] == '+')))
  4782.           *d++ = '\\';
  4783.  
  4784.       for (s = arg; *s; ++s)
  4785.       {
  4786.         /*
  4787.          * Replace "|" with "bar" and '"' with "quote" to match the name of
  4788.          * the tags for these commands.
  4789.          * Replace "*" with ".*" and "?" with "." to match command line
  4790.          * completion.
  4791.          * Insert a backslash before '~', '$' and '.' to avoid their
  4792.          * special meaning.
  4793.          */
  4794.         if (d - IObuff > IOSIZE - 10)    /* getting too long!? */
  4795.         break;
  4796.         switch (*s)
  4797.         {
  4798.         case '|':   STRCPY(d, "bar");
  4799.                 d += 3;
  4800.                 continue;
  4801.         case '"':   STRCPY(d, "quote");
  4802.                 d += 5;
  4803.                 continue;
  4804.         case '*':   *d++ = '.';
  4805.                 break;
  4806.         case '?':   *d++ = '.';
  4807.                 continue;
  4808.         case '$':
  4809.         case '.':
  4810.         case '~':   *d++ = '\\';
  4811.                 break;
  4812.         }
  4813.  
  4814.         /*
  4815.          * Replace "^x" by "CTRL-X". Don't do this for "^_" to make
  4816.          * ":help i_^_CTRL-D" work.
  4817.          * Insert '-' before and after "CTRL-X" when applicable.
  4818.          */
  4819.         if (*s < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1])
  4820.                || vim_strchr((char_u *)"?@[\\]^", s[1]) != NULL)))
  4821.         {
  4822.         if (d > IObuff && d[-1] != '_')
  4823.             *d++ = '_';        /* prepend a '_' */
  4824.         STRCPY(d, "CTRL-");
  4825.         d += 5;
  4826.         if (*s < ' ')
  4827.         {
  4828. #ifdef EBCDIC
  4829.             *d++ = CtrlChar(*s);
  4830. #else
  4831.             *d++ = *s + '@';
  4832. #endif
  4833.             if (d[-1] == '\\')
  4834.             *d++ = '\\';    /* double a backslash */
  4835.         }
  4836.         else
  4837.             *d++ = *++s;
  4838.         if (s[1] != NUL && s[1] != '_')
  4839.             *d++ = '_';        /* append a '_' */
  4840.         continue;
  4841.         }
  4842.         else if (*s == '^')        /* "^" or "CTRL-^" or "^_" */
  4843.         *d++ = '\\';
  4844.  
  4845.         /*
  4846.          * Insert a backslash before a backslash after a slash, for search
  4847.          * pattern tags: "/\|" --> "/\\|".
  4848.          */
  4849.         else if (s[0] == '\\' && s[1] != '\\'
  4850.                            && *arg == '/' && s == arg + 1)
  4851.         *d++ = '\\';
  4852.  
  4853.         /* "CTRL-\_" -> "CTRL-\\_" to avoid the special meaning of "\_" in
  4854.          * "CTRL-\_CTRL-N" */
  4855.         if (STRNICMP(s, "CTRL-\\_", 7) == 0)
  4856.         {
  4857.         STRCPY(d, "CTRL-\\\\");
  4858.         d += 7;
  4859.         s += 6;
  4860.         }
  4861.  
  4862.         *d++ = *s;
  4863.  
  4864.         /*
  4865.          * If tag starts with ', toss everything after a second '. Fixes
  4866.          * CTRL-] on 'option'. (would include the trailing '.').
  4867.          */
  4868.         if (*s == '\'' && s > arg && *arg == '\'')
  4869.         break;
  4870.       }
  4871.       *d = NUL;
  4872.     }
  4873.     }
  4874.  
  4875.     *matches = (char_u **)"";
  4876.     *num_matches = 0;
  4877.     if (find_tags(IObuff, num_matches, matches,
  4878.     TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE, (int)MAXCOL) == OK)
  4879.     /*
  4880.      * Sort the matches found on the heuristic number that is after the
  4881.      * tag name.
  4882.      */
  4883.     qsort((void *)*matches, (size_t)*num_matches,
  4884.                           sizeof(char_u *), help_compare)
  4885.     ;
  4886.     return OK;
  4887. }
  4888.  
  4889. /*
  4890.  * After reading a help file: May cleanup a help buffer when syntax
  4891.  * highlighting is not used.
  4892.  */
  4893.     void
  4894. fix_help_buffer()
  4895. {
  4896.     linenr_T    lnum;
  4897.     char_u    *line;
  4898.     int        in_example = FALSE;
  4899.     int        len;
  4900.     char_u    *p;
  4901.     char_u    *rt;
  4902.     int        mustfree;
  4903.  
  4904.     /* set filetype to "help". */
  4905.     set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
  4906.  
  4907. #ifdef FEAT_SYN_HL
  4908.     if (!syntax_present(curbuf))
  4909. #endif
  4910.     {
  4911.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  4912.     {
  4913.         line = ml_get_buf(curbuf, lnum, FALSE);
  4914.         len = (int)STRLEN(line);
  4915.         if (in_example && len > 0 && !vim_iswhite(line[0]))
  4916.         {
  4917.         /* End of example: non-white or '<' in first column. */
  4918.         if (line[0] == '<')
  4919.         {
  4920.             /* blank-out a '<' in the first column */
  4921.             line = ml_get_buf(curbuf, lnum, TRUE);
  4922.             line[0] = ' ';
  4923.         }
  4924.         in_example = FALSE;
  4925.         }
  4926.         if (!in_example && len > 0)
  4927.         {
  4928.         if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' '))
  4929.         {
  4930.             /* blank-out a '>' in the last column (start of example) */
  4931.             line = ml_get_buf(curbuf, lnum, TRUE);
  4932.             line[len - 1] = ' ';
  4933.             in_example = TRUE;
  4934.         }
  4935.         else if (line[len - 1] == '~')
  4936.         {
  4937.             /* blank-out a '~' at the end of line (header marker) */
  4938.             line = ml_get_buf(curbuf, lnum, TRUE);
  4939.             line[len - 1] = ' ';
  4940.         }
  4941.         }
  4942.     }
  4943.     }
  4944.  
  4945.     /*
  4946.      * In the "help.txt" file, add the locally added help files.
  4947.      * This uses the very first line in the help file.
  4948.      */
  4949.     if (fnamecmp(gettail(curbuf->b_fname), "help.txt") == 0)
  4950.     {
  4951.     for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum)
  4952.     {
  4953.         line = ml_get_buf(curbuf, lnum, FALSE);
  4954.         if (strstr((char *)line, "*local-additions*") != NULL)
  4955.         {
  4956.         /* Go through all directories in 'runtimepath', skipping
  4957.          * $VIMRUNTIME. */
  4958.         p = p_rtp;
  4959.         while (*p != NUL)
  4960.         {
  4961.             copy_option_part(&p, NameBuff, MAXPATHL, ",");
  4962.             mustfree = FALSE;
  4963.             rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
  4964.             if (fnamecmp(NameBuff, rt) != 0)
  4965.             {
  4966.             int    fcount;
  4967.             char_u    **fnames;
  4968.             FILE    *fd;
  4969.             char_u    *s;
  4970.             int    fi;
  4971.  
  4972.             /* Find all "doc/ *.txt" files in this directory. */
  4973.             add_pathsep(NameBuff);
  4974.             STRCAT(NameBuff, "doc/*.txt");
  4975.             if (gen_expand_wildcards(1, &NameBuff, &fcount,
  4976.                          &fnames, EW_FILE|EW_SILENT) == OK
  4977.                 && fcount > 0)
  4978.             {
  4979.                 for (fi = 0; fi < fcount; ++fi)
  4980.                 {
  4981.                 fd = fopen((char *)fnames[fi], "r");
  4982.                 if (fd != NULL)
  4983.                 {
  4984.                     vim_fgets(IObuff, IOSIZE, fd);
  4985.                     if (IObuff[0] == '*'
  4986.                         && (s = vim_strchr(IObuff + 1, '*'))
  4987.                                       != NULL)
  4988.                     {
  4989.                     /* Change tag definition to a
  4990.                      * reference and remove <CR>/<NL>. */
  4991.                     IObuff[0] = '|';
  4992.                     *s = '|';
  4993.                     while (*s != NUL)
  4994.                     {
  4995.                         if (*s == '\r' || *s == '\n')
  4996.                         *s = NUL;
  4997.                         ++s;
  4998.                     }
  4999.                     ml_append(lnum, IObuff, (colnr_T)0,
  5000.                                        FALSE);
  5001.                     ++lnum;
  5002.                     }
  5003.                     fclose(fd);
  5004.                 }
  5005.                 }
  5006.                 FreeWild(fcount, fnames);
  5007.             }
  5008.             }
  5009.             if (mustfree)
  5010.             vim_free(rt);
  5011.         }
  5012.         break;
  5013.         }
  5014.     }
  5015.     }
  5016. }
  5017.  
  5018. #if defined(FEAT_EX_EXTRA) || defined(PROTO)
  5019. /*
  5020.  * ":helptags"
  5021.  */
  5022.     void
  5023. ex_helptags(eap)
  5024.     exarg_T    *eap;
  5025. {
  5026.     FILE    *fd_tags;
  5027.     FILE    *fd;
  5028.     garray_T    ga;
  5029.     int        filecount;
  5030.     char_u    **files;
  5031.     char_u    *p1, *p2;
  5032.     int        fi;
  5033.     char_u    *s;
  5034.     int        i;
  5035.     char_u    *fname;
  5036.  
  5037.     if (!mch_isdir(eap->arg))
  5038.     {
  5039.     EMSG2(_("E150: Not a directory: %s"), eap->arg);
  5040.     return;
  5041.     }
  5042.  
  5043.     /*
  5044.      * Find all *.txt files.
  5045.      */
  5046.     STRCPY(NameBuff, eap->arg);
  5047.     add_pathsep(NameBuff);
  5048.     STRCAT(NameBuff, "*.txt");
  5049.     if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
  5050.                             EW_FILE|EW_SILENT) == FAIL
  5051.         || filecount == 0)
  5052.     {
  5053.     EMSG2("E151: No match: %s", NameBuff);
  5054.     return;
  5055.     }
  5056.  
  5057.     /*
  5058.      * Open the tags file for writing.
  5059.      * Do this before scanning through all the files.
  5060.      */
  5061.     STRCPY(NameBuff, eap->arg);
  5062.     add_pathsep(NameBuff);
  5063.     STRCAT(NameBuff, "tags");
  5064.     fd_tags = fopen((char *)NameBuff, "w");
  5065.     if (fd_tags == NULL)
  5066.     {
  5067.     EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
  5068.     FreeWild(filecount, files);
  5069.     return;
  5070.     }
  5071.  
  5072.     /*
  5073.      * If generating tags for "$VIMRUNTIME/doc" add the "help-tags" tag.
  5074.      */
  5075.     ga_init2(&ga, (int)sizeof(char_u *), 100);
  5076.     if (fullpathcmp((char_u *)"$VIMRUNTIME/doc", eap->arg, FALSE) == FPC_SAME)
  5077.     {
  5078.     if (ga_grow(&ga, 1) == FAIL)
  5079.         got_int = TRUE;
  5080.     else
  5081.     {
  5082.         s = vim_strsave((char_u *)"help-tags\ttags\t1\n");
  5083.         if (s == NULL)
  5084.         got_int = TRUE;
  5085.         else
  5086.         {
  5087.         ((char_u **)ga.ga_data)[ga.ga_len] = s;
  5088.         ++ga.ga_len;
  5089.         --ga.ga_room;
  5090.         }
  5091.     }
  5092.     }
  5093.  
  5094.     /*
  5095.      * Go over all the files and extract the tags.
  5096.      */
  5097.     for (fi = 0; fi < filecount && !got_int; ++fi)
  5098.     {
  5099.     fd = fopen((char *)files[fi], "r");
  5100.     if (fd == NULL)
  5101.     {
  5102.         EMSG2(_("E153: Unable to open %s for reading"), files[fi]);
  5103.         continue;
  5104.     }
  5105.     fname = gettail(files[fi]);
  5106.  
  5107.     while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
  5108.     {
  5109.         p1 = vim_strchr(IObuff, '*');    /* find first '*' */
  5110.         while (p1 != NULL)
  5111.         {
  5112.         p2 = vim_strchr(p1 + 1, '*');    /* find second '*' */
  5113.         if (p2 != NULL && p2 > p1 + 1)    /* skip "*" and "**" */
  5114.         {
  5115.             for (s = p1 + 1; s < p2; ++s)
  5116.             if (*s == ' ' || *s == '\t' || *s == '|')
  5117.                 break;
  5118.  
  5119.             /*
  5120.              * Only accept a *tag* when it consists of valid
  5121.              * characters, there is no '-' before it and is followed
  5122.              * by a white character or end-of-line.
  5123.              */
  5124.             if (s == p2
  5125.                 && (p1 == IObuff || p1[-1] != '-')
  5126.                 && (vim_strchr((char_u *)" \t\n\r", s[1]) != NULL
  5127.                 || s[1] == '\0'))
  5128.             {
  5129.             *p2 = '\0';
  5130.             ++p1;
  5131.             if (ga_grow(&ga, 1) == FAIL)
  5132.             {
  5133.                 got_int = TRUE;
  5134.                 break;
  5135.             }
  5136.             s = alloc((unsigned)(p2 - p1 + STRLEN(fname) + 2));
  5137.             if (s == NULL)
  5138.             {
  5139.                 got_int = TRUE;
  5140.                 break;
  5141.             }
  5142.             ((char_u **)ga.ga_data)[ga.ga_len] = s;
  5143.             ++ga.ga_len;
  5144.             --ga.ga_room;
  5145.             sprintf((char *)s, "%s\t%s", p1, fname);
  5146.  
  5147.             /* find next '*' */
  5148.             p2 = vim_strchr(p2 + 1, '*');
  5149.             }
  5150.         }
  5151.         p1 = p2;
  5152.         }
  5153.         line_breakcheck();
  5154.     }
  5155.  
  5156.     fclose(fd);
  5157.     }
  5158.  
  5159.     FreeWild(filecount, files);
  5160.  
  5161.     if (!got_int)
  5162.     {
  5163.     /*
  5164.      * Sort the tags.
  5165.      */
  5166.     sort_strings((char_u **)ga.ga_data, ga.ga_len);
  5167.  
  5168.     /*
  5169.      * Check for duplicates.
  5170.      */
  5171.     for (i = 1; i < ga.ga_len; ++i)
  5172.     {
  5173.         p1 = ((char_u **)ga.ga_data)[i - 1];
  5174.         p2 = ((char_u **)ga.ga_data)[i];
  5175.         while (*p1 == *p2)
  5176.         {
  5177.         if (*p2 == '\t')
  5178.         {
  5179.             *p2 = NUL;
  5180.             sprintf((char *)NameBuff,
  5181.                 _("E154: Duplicate tag \"%s\" in file %s"),
  5182.                 ((char_u **)ga.ga_data)[i], p2 + 1);
  5183.             EMSG(NameBuff);
  5184.             *p2 = '\t';
  5185.             break;
  5186.         }
  5187.         ++p1;
  5188.         ++p2;
  5189.         }
  5190.     }
  5191.  
  5192.     /*
  5193.      * Write the tags into the file.
  5194.      */
  5195.     for (i = 0; i < ga.ga_len; ++i)
  5196.     {
  5197.         s = ((char_u **)ga.ga_data)[i];
  5198.         if (STRNCMP(s, "help-tags\t", 10) == 0)
  5199.         /* help-tags entry was added in formatted form */
  5200.         fprintf(fd_tags, (char *)s);
  5201.         else
  5202.         {
  5203.         fprintf(fd_tags, "%s\t/*", s);
  5204.         for (p1 = s; *p1 != '\t'; ++p1)
  5205.         {
  5206.             /* insert backslash before '\\' and '/' */
  5207.             if (*p1 == '\\' || *p1 == '/')
  5208.             putc('\\', fd_tags);
  5209.             putc(*p1, fd_tags);
  5210.         }
  5211.         fprintf(fd_tags, "*\n");
  5212.         }
  5213.     }
  5214.     }
  5215.  
  5216.     for (i = 0; i < ga.ga_len; ++i)
  5217.     vim_free(((char_u **)ga.ga_data)[i]);
  5218.     ga_clear(&ga);
  5219.     fclose(fd_tags);        /* there is no check for an error... */
  5220. }
  5221. #endif
  5222.  
  5223. #if defined(FEAT_SIGNS) || defined(PROTO)
  5224.  
  5225. /*
  5226.  * Struct to hold the sign properties.
  5227.  */
  5228. typedef struct sign sign_T;
  5229.  
  5230. struct sign
  5231. {
  5232.     sign_T    *sn_next;    /* next sign in list */
  5233.     int        sn_typenr;    /* type number of sign (negative if not equal
  5234.                    to name) */
  5235.     char_u    *sn_name;    /* name of sign */
  5236.     char_u    *sn_icon;    /* name of pixmap */
  5237. #ifdef FEAT_SIGN_ICONS
  5238.     void    *sn_image;    /* icon image */
  5239. #endif
  5240.     char_u    *sn_text;    /* text used instead of pixmap */
  5241.     int        sn_line_hl;    /* highlight ID for line */
  5242.     int        sn_text_hl;    /* highlight ID for text */
  5243. };
  5244.  
  5245. #define MAX_TYPENR 255        /* depends on sattr_T */
  5246. static sign_T    *first_sign = NULL;
  5247. static int    last_sign_typenr = MAX_TYPENR;    /* is decremented */
  5248.  
  5249. static void sign_list_defined __ARGS((sign_T *sp));
  5250.  
  5251. /*
  5252.  * ":sign" command
  5253.  */
  5254.     void
  5255. ex_sign(eap)
  5256.     exarg_T    *eap;
  5257. {
  5258.     char_u    *arg = eap->arg;
  5259.     char_u    *p;
  5260.     int        idx;
  5261.     sign_T    *sp;
  5262.     sign_T    *sp_prev;
  5263.     buf_T    *buf;
  5264.     static char    *cmds[] = {
  5265.             "define",
  5266. #define SIGNCMD_DEFINE    0
  5267.             "undefine",
  5268. #define SIGNCMD_UNDEFINE 1
  5269.             "list",
  5270. #define SIGNCMD_LIST    2
  5271.             "place",
  5272. #define SIGNCMD_PLACE    3
  5273.             "unplace",
  5274. #define SIGNCMD_UNPLACE    4
  5275.             "jump",
  5276. #define SIGNCMD_JUMP    5
  5277. #define SIGNCMD_LAST    6
  5278.     };
  5279.  
  5280.     /* Parse the subcommand. */
  5281.     p = skiptowhite(arg);
  5282.     if (*p != NUL)
  5283.     *p++ = NUL;
  5284.     for (idx = 0; ; ++idx)
  5285.     {
  5286.     if (idx == SIGNCMD_LAST)
  5287.     {
  5288.         EMSG2(_("E160: Unknown sign command: %s"), arg);
  5289.         return;
  5290.     }
  5291.     if (STRCMP(arg, cmds[idx]) == 0)
  5292.         break;
  5293.     }
  5294.     arg = skipwhite(p);
  5295.  
  5296.     if (idx <= SIGNCMD_LIST)
  5297.     {
  5298.     /*
  5299.      * Define, undefine or list signs.
  5300.      */
  5301.     if (idx == SIGNCMD_LIST && *arg == NUL)
  5302.     {
  5303.         /* ":sign list": list all defined signs */
  5304.         for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5305.         sign_list_defined(sp);
  5306.     }
  5307.     else if (*arg == NUL)
  5308.         EMSG(_("E156: Missing sign name"));
  5309.     else
  5310.     {
  5311.         p = skiptowhite(arg);
  5312.         if (*p != NUL)
  5313.         *p++ = NUL;
  5314.         sp_prev = NULL;
  5315.         for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5316.         {
  5317.         if (STRCMP(sp->sn_name, arg) == 0)
  5318.             break;
  5319.         sp_prev = sp;
  5320.         }
  5321.         if (idx == SIGNCMD_DEFINE)
  5322.         {
  5323.         /* ":sign define {name} ...": define a sign */
  5324.         if (sp == NULL)
  5325.         {
  5326.             /* Allocate a new sign. */
  5327.             sp = (sign_T *)alloc_clear((unsigned)sizeof(sign_T));
  5328.             if (sp == NULL)
  5329.             return;
  5330.             if (sp_prev == NULL)
  5331.             first_sign = sp;
  5332.             else
  5333.             sp_prev->sn_next = sp;
  5334.             sp->sn_name = vim_strnsave(arg, (int)(p - arg));
  5335.  
  5336.             /* If the name is a number use that for the typenr,
  5337.              * otherwise use a negative number. */
  5338.             if (isdigit(*arg))
  5339.             sp->sn_typenr = atoi((char *)arg);
  5340.             else
  5341.             {
  5342.             sign_T    *lp;
  5343.             int    start = last_sign_typenr;
  5344.  
  5345.             for (lp = first_sign; lp != NULL; lp = lp->sn_next)
  5346.             {
  5347.                 if (lp->sn_typenr == last_sign_typenr)
  5348.                 {
  5349.                 --last_sign_typenr;
  5350.                 if (last_sign_typenr == 0)
  5351.                     last_sign_typenr = MAX_TYPENR;
  5352.                 if (last_sign_typenr == start)
  5353.                 {
  5354.                     EMSG(_("E612: Too many signs defined"));
  5355.                     return;
  5356.                 }
  5357.                 lp = first_sign;
  5358.                 continue;
  5359.                 }
  5360.             }
  5361.  
  5362.             sp->sn_typenr = last_sign_typenr--;
  5363.             if (last_sign_typenr == 0)
  5364.                 last_sign_typenr = MAX_TYPENR; /* wrap around */
  5365.             }
  5366.         }
  5367.  
  5368.         /* set values for a defined sign. */
  5369.         for (;;)
  5370.         {
  5371.             arg = skipwhite(p);
  5372.             if (*arg == NUL)
  5373.             break;
  5374.             p = skiptowhite_esc(arg);
  5375.             if (STRNCMP(arg, "icon=", 5) == 0)
  5376.             {
  5377.             arg += 5;
  5378.             vim_free(sp->sn_icon);
  5379.             sp->sn_icon = vim_strnsave(arg, (int)(p - arg));
  5380.             backslash_halve(sp->sn_icon);
  5381. #ifdef FEAT_SIGN_ICONS
  5382.             if (gui.in_use)
  5383.             {
  5384.                 if (sp->sn_image != NULL)
  5385.                 gui_mch_destroy_sign(sp->sn_image);
  5386.                 sp->sn_image = gui_mch_register_sign(sp->sn_icon);
  5387.             }
  5388. #endif
  5389.             }
  5390.             else if (STRNCMP(arg, "text=", 5) == 0)
  5391.             {
  5392.             char_u    *s;
  5393.             int    cells;
  5394.             int    len;
  5395.  
  5396.             arg += 5;
  5397. #ifdef FEAT_MBYTE
  5398.             /* Count cells and check for non-printable chars */
  5399.             if (has_mbyte)
  5400.             {
  5401.                 cells = 0;
  5402.                 for (s = arg; s < p; s += (*mb_ptr2len_check)(s))
  5403.                 {
  5404.                 if (!vim_isprintc((*mb_ptr2char)(s)))
  5405.                     break;
  5406.                 cells += (*mb_ptr2cells)(s);
  5407.                 }
  5408.             }
  5409.             else
  5410. #endif
  5411.             {
  5412.                 for (s = arg; s < p; ++s)
  5413.                 if (!vim_isprintc(*s))
  5414.                     break;
  5415.                 cells = s - arg;
  5416.             }
  5417.             /* Currently must be one or two display cells */
  5418.             if (s != p || cells < 1 || cells > 2)
  5419.             {
  5420.                 *p = NUL;
  5421.                 EMSG2(_("E239: Invalid sign text: %s"), arg);
  5422.                 return;
  5423.             }
  5424.  
  5425.             vim_free(sp->sn_text);
  5426.             /* Allocate one byte more if we need to pad up
  5427.              * with a space. */
  5428.             len = p - arg + ((cells == 1) ? 1 : 0);
  5429.             sp->sn_text = vim_strnsave(arg, len);
  5430.  
  5431.             if (sp->sn_text != NULL && cells == 1)
  5432.                 STRCPY(sp->sn_text + len - 1, " ");
  5433.             }
  5434.             else if (STRNCMP(arg, "linehl=", 7) == 0)
  5435.             {
  5436.             arg += 7;
  5437.             sp->sn_line_hl = syn_check_group(arg, (int)(p - arg));
  5438.             }
  5439.             else if (STRNCMP(arg, "texthl=", 7) == 0)
  5440.             {
  5441.             arg += 7;
  5442.             sp->sn_text_hl = syn_check_group(arg, (int)(p - arg));
  5443.             }
  5444.             else
  5445.             {
  5446.             EMSG2(_(e_invarg2), arg);
  5447.             return;
  5448.             }
  5449.         }
  5450.         }
  5451.         else if (sp == NULL)
  5452.         EMSG2(_("E155: Unknown sign: %s"), arg);
  5453.         else if (idx == SIGNCMD_LIST)
  5454.         /* ":sign list {name}" */
  5455.         sign_list_defined(sp);
  5456.         else
  5457.         {
  5458.         /* ":sign undefine {name}" */
  5459.         vim_free(sp->sn_name);
  5460.         vim_free(sp->sn_icon);
  5461. #ifdef FEAT_SIGN_ICONS
  5462.         if (sp->sn_image != NULL)
  5463.             gui_mch_destroy_sign(sp->sn_image);
  5464. #endif
  5465.         vim_free(sp->sn_text);
  5466.         if (sp_prev == NULL)
  5467.             first_sign = sp->sn_next;
  5468.         else
  5469.             sp_prev->sn_next = sp->sn_next;
  5470.         vim_free(sp);
  5471.         }
  5472.     }
  5473.     }
  5474.     else
  5475.     {
  5476.     int        id = -1;
  5477.     linenr_T    lnum = -1;
  5478.     char_u        *sign_name = NULL;
  5479.     char_u        *arg1;
  5480.  
  5481.     if (*arg == NUL)
  5482.     {
  5483.         if (idx == SIGNCMD_PLACE)
  5484.         {
  5485.         /* ":sign place": list placed signs in all buffers */
  5486.         sign_list_placed(NULL);
  5487.         }
  5488.         else if (idx == SIGNCMD_UNPLACE)
  5489.         {
  5490.         /* ":sign unplace": remove placed sign at cursor */
  5491.         id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum);
  5492.         if (id > 0)
  5493.         {
  5494.             buf_delsign(curwin->w_buffer, id);
  5495.             update_debug_sign(curwin->w_buffer, curwin->w_cursor.lnum);
  5496.         }
  5497.         else
  5498.             EMSG(_("E159: Missing sign number"));
  5499.         }
  5500.         else
  5501.         EMSG(_(e_argreq));
  5502.         return;
  5503.     }
  5504.  
  5505.     if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL)
  5506.     {
  5507.         /* ":sign unplace *": remove all placed signs */
  5508.         buf_delete_all_signs();
  5509.         return;
  5510.     }
  5511.  
  5512.     /* first arg could be placed sign id */
  5513.     arg1 = arg;
  5514.     if (isdigit(*arg))
  5515.     {
  5516.         id = getdigits(&arg);
  5517.         if (!vim_iswhite(*arg) && *arg != NUL)
  5518.         {
  5519.         id = -1;
  5520.         arg = arg1;
  5521.         }
  5522.         else
  5523.         {
  5524.         arg = skipwhite(arg);
  5525.         if (idx == SIGNCMD_UNPLACE && *arg == NUL)
  5526.         {
  5527.             /* ":sign unplace {id}": remove placed sign by number */
  5528.             for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  5529.             if ((lnum = buf_delsign(buf, id)) != 0)
  5530.                 update_debug_sign(buf, lnum);
  5531.             return;
  5532.         }
  5533.         }
  5534.     }
  5535.  
  5536.     /*
  5537.      * Check for line={lnum} name={name} and file={fname} or buffer={nr}.
  5538.      * Leave "arg" pointing to {fname}.
  5539.      */
  5540.     for (;;)
  5541.     {
  5542.         if (STRNCMP(arg, "line=", 5) == 0)
  5543.         {
  5544.         arg += 5;
  5545.         lnum = atoi((char *)arg);
  5546.         arg = skiptowhite(arg);
  5547.         }
  5548.         else if (STRNCMP(arg, "name=", 5) == 0)
  5549.         {
  5550.         arg += 5;
  5551.         sign_name = arg;
  5552.         arg = skiptowhite(arg);
  5553.         if (*arg != NUL)
  5554.             *arg++ = NUL;
  5555.         }
  5556.         else if (STRNCMP(arg, "file=", 5) == 0)
  5557.         {
  5558.         arg += 5;
  5559.         buf = buflist_findname(arg);
  5560.         break;
  5561.         }
  5562.         else if (STRNCMP(arg, "buffer=", 7) == 0)
  5563.         {
  5564.         arg += 7;
  5565.         buf = buflist_findnr(atoi((char *)arg));
  5566.         break;
  5567.         }
  5568.         else
  5569.         {
  5570.         EMSG(_(e_invarg));
  5571.         return;
  5572.         }
  5573.         arg = skipwhite(arg);
  5574.     }
  5575.  
  5576.     if (buf == NULL)
  5577.     {
  5578.         EMSG2(_("E158: Invalid buffer name: %s"), arg);
  5579.     }
  5580.     else if (id <= 0)
  5581.     {
  5582.         if (lnum >= 0 || sign_name != NULL)
  5583.         EMSG(_(e_invarg));
  5584.         else
  5585.         /* ":sign place file={fname}": list placed signs in one file */
  5586.         sign_list_placed(buf);
  5587.     }
  5588.     else if (idx == SIGNCMD_JUMP)
  5589.     {
  5590.         /* ":sign jump {id} file={fname}" */
  5591.         if (lnum >= 0 || sign_name != NULL)
  5592.         EMSG(_(e_invarg));
  5593.         else if ((lnum = buf_findsign(buf, id)) > 0)
  5594.         {                /* goto a sign ... */
  5595.         if (buf_jump_open_win(buf) != NULL)
  5596.         {            /* ... in a current window */
  5597.             curwin->w_cursor.lnum = lnum;
  5598.             check_cursor_lnum();
  5599.             beginline(BL_WHITE);
  5600.         }
  5601.         else
  5602.         {            /* ... not currently in a window */
  5603.             char_u    *cmd;
  5604.  
  5605.             cmd = alloc((unsigned)STRLEN(buf->b_fname) + 25);
  5606.             if (cmd == NULL)
  5607.             return;
  5608.             sprintf((char *)cmd, "e +%ld %s", (long)lnum, buf->b_fname);
  5609.             do_cmdline_cmd(cmd);
  5610.             vim_free(cmd);
  5611.         }
  5612. #ifdef FEAT_FOLDING
  5613.         foldOpenCursor();
  5614. #endif
  5615.         }
  5616.         else
  5617.         EMSGN(_("E157: Invalid sign ID: %ld"), id);
  5618.     }
  5619.     else if (idx == SIGNCMD_UNPLACE)
  5620.     {
  5621.         /* ":sign unplace {id} file={fname}" */
  5622.         if (lnum >= 0 || sign_name != NULL)
  5623.         EMSG(_(e_invarg));
  5624.         else
  5625.         {
  5626.         lnum = buf_delsign(buf, id);
  5627.         update_debug_sign(buf, lnum);
  5628.         }
  5629.     }
  5630.         /* idx == SIGNCMD_PLACE */
  5631.     else if (sign_name != NULL)
  5632.     {
  5633.         for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5634.         if (STRCMP(sp->sn_name, sign_name) == 0)
  5635.             break;
  5636.         if (sp == NULL)
  5637.         {
  5638.         EMSG2(_("E155: Unknown sign: %s"), sign_name);
  5639.         return;
  5640.         }
  5641.         if (lnum > 0)
  5642.         /* ":sign place {id} line={lnum} name={name} file={fname}":
  5643.          * place a sign */
  5644.         buf_addsign(buf, id, lnum, sp->sn_typenr);
  5645.         else
  5646.         /* ":sign place {id} file={fname}": change sign type */
  5647.         lnum = buf_change_sign_type(buf, id, sp->sn_typenr);
  5648.         update_debug_sign(buf, lnum);
  5649.     }
  5650.     else
  5651.         EMSG(_(e_invarg));
  5652.     }
  5653. }
  5654.  
  5655. #if defined(FEAT_SIGN_ICONS) || defined(PROTO)
  5656. /*
  5657.  * Allocate the icons.  Called when the GUI has started.  Allows defining
  5658.  * signs before it starts.
  5659.  */
  5660.     void
  5661. sign_gui_started()
  5662. {
  5663.     sign_T    *sp;
  5664.  
  5665.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5666.     if (sp->sn_icon != NULL)
  5667.         sp->sn_image = gui_mch_register_sign(sp->sn_icon);
  5668. }
  5669. #endif
  5670.  
  5671. /*
  5672.  * List one sign.
  5673.  */
  5674.     static void
  5675. sign_list_defined(sp)
  5676.     sign_T    *sp;
  5677. {
  5678.     char_u    *p;
  5679.  
  5680.     smsg((char_u *)"sign %s", sp->sn_name);
  5681.     if (sp->sn_icon != NULL)
  5682.     {
  5683.     MSG_PUTS(" icon=");
  5684.     msg_outtrans(sp->sn_icon);
  5685. #ifdef FEAT_SIGN_ICONS
  5686.     if (sp->sn_image == NULL)
  5687.         MSG_PUTS(" (NOT FOUND)");
  5688. #else
  5689.     MSG_PUTS(" (not supported)");
  5690. #endif
  5691.     }
  5692.     if (sp->sn_text != NULL)
  5693.     {
  5694.     MSG_PUTS(" text=");
  5695.     msg_outtrans(sp->sn_text);
  5696.     }
  5697.     if (sp->sn_line_hl > 0)
  5698.     {
  5699.     MSG_PUTS(" linehl=");
  5700.     p = get_highlight_name(NULL, sp->sn_line_hl - 1);
  5701.     if (p == NULL)
  5702.         MSG_PUTS("NONE");
  5703.     else
  5704.         msg_puts(p);
  5705.     }
  5706.     if (sp->sn_text_hl > 0)
  5707.     {
  5708.     MSG_PUTS(" texthl=");
  5709.     p = get_highlight_name(NULL, sp->sn_text_hl - 1);
  5710.     if (p == NULL)
  5711.         MSG_PUTS("NONE");
  5712.     else
  5713.         msg_puts(p);
  5714.     }
  5715. }
  5716.  
  5717. /*
  5718.  * Get highlighting attribute for sign "typenr".
  5719.  * If "line" is TRUE: line highl, if FALSE: text highl.
  5720.  */
  5721.     int
  5722. sign_get_attr(typenr, line)
  5723.     int        typenr;
  5724.     int        line;
  5725. {
  5726.     sign_T    *sp;
  5727.  
  5728.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5729.     if (sp->sn_typenr == typenr)
  5730.     {
  5731.         if (line)
  5732.         {
  5733.         if (sp->sn_line_hl > 0)
  5734.             return syn_id2attr(sp->sn_line_hl);
  5735.         }
  5736.         else
  5737.         {
  5738.         if (sp->sn_text_hl > 0)
  5739.             return syn_id2attr(sp->sn_text_hl);
  5740.         }
  5741.         break;
  5742.     }
  5743.     return 0;
  5744. }
  5745.  
  5746. /*
  5747.  * Get text mark for sign "typenr".
  5748.  * Returns NULL if there isn't one.
  5749.  */
  5750.     char_u *
  5751. sign_get_text(typenr)
  5752.     int        typenr;
  5753. {
  5754.     sign_T    *sp;
  5755.  
  5756.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5757.     if (sp->sn_typenr == typenr)
  5758.         return sp->sn_text;
  5759.     return NULL;
  5760. }
  5761.  
  5762. #if defined(FEAT_SIGN_ICONS) || defined(PROTO)
  5763.     void *
  5764. sign_get_image(typenr)
  5765.     int        typenr;        /* the attribute which may have a sign */
  5766. {
  5767.     sign_T    *sp;
  5768.  
  5769.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5770.     if (sp->sn_typenr == typenr)
  5771.         return sp->sn_image;
  5772.     return NULL;
  5773. }
  5774. #endif
  5775.  
  5776. /*
  5777.  * Get the name of a sign by its typenr.
  5778.  */
  5779.     char_u *
  5780. sign_typenr2name(typenr)
  5781.     int        typenr;
  5782. {
  5783.     sign_T    *sp;
  5784.  
  5785.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5786.     if (sp->sn_typenr == typenr)
  5787.         return sp->sn_name;
  5788.     return (char_u *)_("[Deleted]");
  5789. }
  5790.  
  5791. #endif
  5792.  
  5793. #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
  5794. /*
  5795.  * ":drop"
  5796.  * Opens the first argument in a window.  When there are two or more arguments
  5797.  * the argument list is redefined.
  5798.  */
  5799.     void
  5800. ex_drop(eap)
  5801.     exarg_T    *eap;
  5802. {
  5803.     int        split = FALSE;
  5804.     int        incurwin = FALSE;
  5805.     char_u    *arg;
  5806.     char_u    *first = NULL;
  5807.     win_T    *wp;
  5808.     buf_T    *buf;
  5809.  
  5810.     /*
  5811.      * Check if the first argument is already being edited in a window.  If
  5812.      * so, jump to that window.
  5813.      * We would actually need to check all arguments, but that's complicated
  5814.      * and mostly only one file is dropped.
  5815.      * This also ignores wildcards, since it is very unlikely the user is
  5816.      * editing a file name with a wildcard character.
  5817.      */
  5818.     arg = vim_strsave(eap->arg);
  5819.     if (arg != NULL)
  5820.     {
  5821.     /* Get the first argument, remove quotes, make it a full path. */
  5822.     first = fix_fname(arg);
  5823.     if (first != NULL)
  5824.     {
  5825.         buf = buflist_findname(first);
  5826.         FOR_ALL_WINDOWS(wp)
  5827.         {
  5828.         if (wp->w_buffer == buf)
  5829.         {
  5830.             incurwin = TRUE;
  5831. # ifdef FEAT_WINDOWS
  5832.             win_enter(wp, TRUE);
  5833.             break;
  5834. # endif
  5835.         }
  5836.         }
  5837.         vim_free(first);
  5838.  
  5839.         if (incurwin)
  5840.         {
  5841.         /* Already editing the file.  Redefine the argument list. */
  5842.         set_arglist(eap->arg);
  5843.         curwin->w_arg_idx = 0;
  5844.         vim_free(arg);
  5845.         return;
  5846.         }
  5847.     }
  5848.     vim_free(arg);
  5849.     }
  5850.  
  5851.     /*
  5852.      * Check whether the current buffer is changed. If so, we will need
  5853.      * to split the current window or data could be lost.
  5854.      * Skip the check if the 'hidden' option is set, as in this case the
  5855.      * buffer won't be lost.
  5856.      */
  5857.     if (!P_HID(curbuf))
  5858.     {
  5859. # ifdef FEAT_WINDOWS
  5860.     ++emsg_off;
  5861. # endif
  5862.     split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
  5863. # ifdef FEAT_WINDOWS
  5864.     --emsg_off;
  5865. # else
  5866.     if (split)
  5867.         return;
  5868. # endif
  5869.     }
  5870.  
  5871.     /* Fake a ":snext" or ":next" command, redefine the arglist. */
  5872.     if (split)
  5873.     {
  5874.     eap->cmdidx = CMD_snext;
  5875.     eap->cmd[0] = 's';
  5876.     }
  5877.     else
  5878.     eap->cmdidx = CMD_next;
  5879.     ex_next(eap);
  5880. }
  5881. #endif
  5882.