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

编辑器/阅读器

开发平台:

DOS

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8. /*
  9.  * ex_cmds.c: functions for command line commands
  10.  */
  11. #include "vim.h"
  12. #ifdef EX_EXTRA
  13. static int linelen __ARGS((int *has_tab));
  14. #endif
  15. static void do_filter __ARGS((linenr_t line1, linenr_t line2,
  16.     char_u *buff, int do_in, int do_out));
  17. #ifdef VIMINFO
  18. static char_u *viminfo_filename __ARGS((char_u *));
  19. static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info,
  20.      int want_marks, int force_read));
  21. static int read_viminfo_up_to_marks __ARGS((char_u *line, FILE *fp,
  22.    int forceit, int writing));
  23. #endif
  24. static int do_sub_msg __ARGS((void));
  25. static int
  26. #ifdef __BORLANDC__
  27. _RTLENTRYF
  28. #endif
  29. help_compare __ARGS((const void *s1, const void *s2));
  30.     void
  31. do_ascii()
  32. {
  33.     int c;
  34.     char buf1[20];
  35.     char buf2[20];
  36.     char_u buf3[3];
  37. #ifdef MULTI_BYTE
  38.     int c2 = NUL;
  39. #endif
  40.     c = gchar_cursor();
  41.     if (c == NUL)
  42.     {
  43. MSG("empty line");
  44. return;
  45.     }
  46. #ifdef MULTI_BYTE
  47.     /* split lead from trail */
  48.     c2 = (((unsigned)c >> 8) & 0xff);
  49.     c = (c & 0xff);
  50.     if (c2)
  51.     {
  52. buf2[0] = c;
  53. buf2[1] = c2;
  54. buf2[2] = NUL;
  55. sprintf((char *)IObuff, "%s  %d %d,  Hex %02x %02x,  Octal %03o %03o",
  56. buf2, c,c2, c,c2, c,c2);
  57.     }
  58.     else
  59. #endif
  60.     {
  61. if (c == NL)     /* NUL is stored as NL */
  62.     c = NUL;
  63. if (vim_isprintc(c) && (c < ' ' || c > '~'))
  64. {
  65.     transchar_nonprint(buf3, c);
  66.     sprintf(buf1, "  <%s>", (char *)buf3);
  67. }
  68. else
  69.     buf1[0] = NUL;
  70. if (c >= 0x80)
  71.     sprintf(buf2, "  <M-%s>", transchar(c & 0x7f));
  72. else
  73.     buf2[0] = NUL;
  74. sprintf((char *)IObuff, "<%s>%s%s  %d,  Hex %02x,  Octal %03o",
  75. transchar(c), buf1, buf2, c, c, c);
  76.     }
  77.     msg(IObuff);
  78. }
  79. #ifdef EX_EXTRA
  80. /*
  81.  * Handle ":left", ":center" and ":right" commands: align text.
  82.  */
  83.     void
  84. do_align(eap)
  85.     EXARG *eap;
  86. {
  87.     FPOS    save_curpos;
  88.     int     len;
  89.     int     indent = 0;
  90.     int     new_indent;
  91.     int     has_tab;
  92.     int     width;
  93. #ifdef RIGHTLEFT
  94.     if (curwin->w_p_rl)
  95.     {
  96. /* switch left and right aligning */
  97. if (eap->cmdidx == CMD_right)
  98.     eap->cmdidx = CMD_left;
  99. else if (eap->cmdidx == CMD_left)
  100.     eap->cmdidx = CMD_right;
  101.     }
  102. #endif
  103.     width = atoi((char *)eap->arg);
  104.     save_curpos = curwin->w_cursor;
  105.     if (eap->cmdidx == CMD_left)    /* width is used for new indent */
  106.     {
  107. if (width >= 0)
  108.     indent = width;
  109.     }
  110.     else
  111.     {
  112. /*
  113.  * if 'textwidth' set, use it
  114.  * else if 'wrapmargin' set, use it
  115.  * if invalid value, use 80
  116.  */
  117. if (width <= 0)
  118.     width = curbuf->b_p_tw;
  119. if (width == 0 && curbuf->b_p_wm > 0)
  120.     width = Columns - curbuf->b_p_wm;
  121. if (width <= 0)
  122.     width = 80;
  123.     }
  124.     if (u_save((linenr_t)(eap->line1 - 1), (linenr_t)(eap->line2 + 1)) == FAIL)
  125. return;
  126. #ifdef SYNTAX_HL
  127.     /* recompute syntax hl., starting with first line */
  128.     syn_changed(eap->line1);
  129. #endif
  130.     for (curwin->w_cursor.lnum = eap->line1;
  131.  curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum)
  132.     {
  133. if (eap->cmdidx == CMD_left) /* left align */
  134.     new_indent = indent;
  135. else
  136. {
  137.     len = linelen(eap->cmdidx == CMD_right ? &has_tab
  138.    : NULL) - get_indent();
  139.     if (len <= 0) /* skip blank lines */
  140. continue;
  141.     if (eap->cmdidx == CMD_center)
  142. new_indent = (width - len) / 2;
  143.     else
  144.     {
  145. new_indent = width - len; /* right align */
  146. /*
  147.  * Make sure that embedded TABs don't make the text go too far
  148.  * to the right.
  149.  */
  150. if (has_tab)
  151.     while (new_indent > 0)
  152.     {
  153. set_indent(new_indent, TRUE); /* set indent */
  154. if (linelen(NULL) <= width)
  155. {
  156.     /*
  157.      * Now try to move the line as much as possible to
  158.      * the right.  Stop when it moves too far.
  159.      */
  160.     do
  161. set_indent(++new_indent, TRUE); /* set indent */
  162.     while (linelen(NULL) <= width);
  163.     --new_indent;
  164.     break;
  165. }
  166. --new_indent;
  167.     }
  168.     }
  169. }
  170. if (new_indent < 0)
  171.     new_indent = 0;
  172. set_indent(new_indent, TRUE); /* set indent */
  173.     }
  174.     curwin->w_cursor = save_curpos;
  175.     beginline(BL_WHITE | BL_FIX);
  176.     /*
  177.      * If the cursor is after the first changed line, its position needs to be
  178.      * updated.
  179.      */
  180.     if (curwin->w_cursor.lnum > eap->line1)
  181.     {
  182. changed_line_abv_curs();
  183. invalidate_botline();
  184.     }
  185.     else if (curwin->w_cursor.lnum == eap->line1)
  186. changed_cline_bef_curs();
  187.     /*
  188.      * If the start of the aligned lines is before botline, it may have become
  189.      * approximated (lines got longer or shorter).
  190.      */
  191.     if (botline_approximated() && eap->line1 < curwin->w_botline)
  192. approximate_botline();
  193.     update_screen(NOT_VALID);
  194. }
  195. /*
  196.  * Get the length of the current line, excluding trailing white space.
  197.  */
  198.     static int
  199. linelen(has_tab)
  200.     int     *has_tab;
  201. {
  202.     char_u  *line;
  203.     char_u  *first;
  204.     char_u  *last;
  205.     int     save;
  206.     int     len;
  207.     /* find the first non-blank character */
  208.     line = ml_get_curline();
  209.     first = skipwhite(line);
  210.     /* find the character after the last non-blank character */
  211.     for (last = first + STRLEN(first);
  212. last > first && vim_iswhite(last[-1]); --last)
  213. ;
  214.     save = *last;
  215.     *last = NUL;
  216.     len = linetabsize(line); /* get line length */
  217.     if (has_tab != NULL) /* check for embedded TAB */
  218. *has_tab = (vim_strrchr(first, TAB) != NULL);
  219.     *last = save;
  220.     return len;
  221. }
  222. /*
  223.  * Handle ":retab" command.
  224.  */
  225.     void
  226. do_retab(eap)
  227.     EXARG *eap;
  228. {
  229.     linenr_t lnum;
  230.     int got_tab = FALSE;
  231.     long num_spaces = 0;
  232.     long num_tabs;
  233.     long len;
  234.     long col;
  235.     long vcol;
  236.     long start_col = 0; /* For start of white-space string */
  237.     long start_vcol = 0; /* For start of white-space string */
  238.     int temp;
  239.     long old_len;
  240.     char_u *ptr;
  241.     char_u *new_line = (char_u *)1;    /* init to non-NULL */
  242.     int did_something = FALSE;
  243.     int did_undo; /* called u_save for current line */
  244.     int new_ts;
  245.     int save_list;
  246.     save_list = curwin->w_p_list;
  247.     curwin->w_p_list = 0;     /* don't want list mode here */
  248. #ifdef SYNTAX_HL
  249.     /* recompute syntax hl. starting with line1 */
  250.     syn_changed(eap->line1);
  251. #endif
  252.     new_ts = getdigits(&(eap->arg));
  253.     if (new_ts == 0)
  254. new_ts = curbuf->b_p_ts;
  255.     for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
  256.     {
  257. ptr = ml_get(lnum);
  258. col = 0;
  259. vcol = 0;
  260. did_undo = FALSE;
  261. for (;;)
  262. {
  263.     if (vim_iswhite(ptr[col]))
  264.     {
  265. if (!got_tab && num_spaces == 0)
  266. {
  267.     /* First consecutive white-space */
  268.     start_vcol = vcol;
  269.     start_col = col;
  270. }
  271. if (ptr[col] == ' ')
  272.     num_spaces++;
  273. else
  274.     got_tab = TRUE;
  275.     }
  276.     else
  277.     {
  278. if (got_tab || (eap->forceit && num_spaces > 1))
  279. {
  280.     /* Retabulate this string of white-space */
  281.     /* len is virtual length of white string */
  282.     len = num_spaces = vcol - start_vcol;
  283.     num_tabs = 0;
  284.     if (!curbuf->b_p_et)
  285.     {
  286. temp = new_ts - (start_vcol % new_ts);
  287. if (num_spaces >= temp)
  288. {
  289.     num_spaces -= temp;
  290.     num_tabs++;
  291. }
  292. num_tabs += num_spaces / new_ts;
  293. num_spaces -= (num_spaces / new_ts) * new_ts;
  294.     }
  295.     if (curbuf->b_p_et || got_tab ||
  296. (num_spaces + num_tabs < len))
  297.     {
  298. if (did_undo == FALSE)
  299. {
  300.     did_undo = TRUE;
  301.     if (u_save((linenr_t)(lnum - 1),
  302. (linenr_t)(lnum + 1)) == FAIL)
  303.     {
  304. new_line = NULL; /* flag out-of-memory */
  305. break;
  306.     }
  307. }
  308. /* len is actual number of white characters used */
  309. len = num_spaces + num_tabs;
  310. old_len = STRLEN(ptr);
  311. new_line = lalloc(old_len - col + start_col + len + 1,
  312. TRUE);
  313. if (new_line == NULL)
  314.     break;
  315. if (start_col > 0)
  316.     mch_memmove(new_line, ptr, (size_t)start_col);
  317. mch_memmove(new_line + start_col + len,
  318.       ptr + col, (size_t)(old_len - col + 1));
  319. ptr = new_line + start_col;
  320. for (col = 0; col < len; col++)
  321.     ptr[col] = (col < num_tabs) ? 't' : ' ';
  322. ml_replace(lnum, new_line, FALSE);
  323. did_something = TRUE;
  324. ptr = new_line;
  325. col = start_col + len;
  326.     }
  327. }
  328. got_tab = FALSE;
  329. num_spaces = 0;
  330.     }
  331.     if (ptr[col] == NUL)
  332. break;
  333.     vcol += chartabsize(ptr[col++], (colnr_t)vcol);
  334. }
  335. if (new_line == NULL)     /* out of memory */
  336.     break;
  337. line_breakcheck();
  338.     }
  339.     if (got_int)
  340. emsg(e_interr);
  341.     if (did_something)
  342. changed();
  343.     curwin->w_p_list = save_list; /* restore 'list' */
  344.     if (curbuf->b_p_ts != new_ts || did_something)
  345.     {
  346. /*
  347.  * Cursor may need updating when change is before or at the cursor
  348.  * line.  w_botline may be wrong a bit now.
  349.  */
  350. if (curbuf->b_p_ts != new_ts || eap->line1 < curwin->w_cursor.lnum)
  351.     changed_line_abv_curs();     /* recompute cursor pos compl. */
  352. else if (eap->line1 == curwin->w_cursor.lnum)
  353.     changed_cline_bef_curs();     /* recompute curosr pos partly */
  354. approximate_botline();
  355.     }
  356.     curbuf->b_p_ts = new_ts;
  357.     coladvance(curwin->w_curswant);
  358.     u_clearline();
  359.     update_screen(NOT_VALID);
  360. }
  361. #endif
  362. /*
  363.  * :move command - move lines line1-line2 to line dest
  364.  *
  365.  * return FAIL for failure, OK otherwise
  366.  */
  367.     int
  368. do_move(line1, line2, dest)
  369.     linenr_t line1;
  370.     linenr_t line2;
  371.     linenr_t dest;
  372. {
  373.     char_u *str;
  374.     linenr_t l;
  375.     linenr_t extra;     /* Num lines added before line1 */
  376.     linenr_t num_lines;  /* Num lines moved */
  377.     linenr_t last_line;  /* Last line in file after adding new text */
  378.     if (dest >= line1 && dest < line2)
  379.     {
  380. EMSG("Move lines into themselves");
  381. return FAIL;
  382.     }
  383.     num_lines = line2 - line1 + 1;
  384.     /*
  385.      * First we copy the old text to its new location -- webb
  386.      * Also copy the flag that ":global" command uses.
  387.      */
  388.     if (u_save(dest, dest + 1) == FAIL)
  389. return FAIL;
  390.     for (extra = 0, l = line1; l <= line2; l++)
  391.     {
  392. str = vim_strsave(ml_get(l + extra));
  393. if (str != NULL)
  394. {
  395.     ml_append(dest + l - line1, str, (colnr_t)0, FALSE);
  396.     vim_free(str);
  397.     if (dest < line1)
  398. extra++;
  399. }
  400.     }
  401.     /*
  402.      * Now we must be careful adjusting our marks so that we don't overlap our
  403.      * mark_adjust() calls.
  404.      *
  405.      * We adjust the marks within the old text so that they refer to the
  406.      * last lines of the file (temporarily), because we know no other marks
  407.      * will be set there since these line numbers did not exist until we added
  408.      * our new lines.
  409.      *
  410.      * Then we adjust the marks on lines between the old and new text positions
  411.      * (either forwards or backwards).
  412.      *
  413.      * And Finally we adjust the marks we put at the end of the file back to
  414.      * their final destination at the new text position -- webb
  415.      */
  416.     last_line = curbuf->b_ml.ml_line_count;
  417.     mark_adjust(line1, line2, last_line - line2, 0L);
  418.     if (dest >= line2)
  419.     {
  420. mark_adjust(line2 + 1, dest, -num_lines, 0L);
  421. curbuf->b_op_start.lnum = dest - num_lines + 1;
  422. curbuf->b_op_end.lnum = dest;
  423.     }
  424.     else
  425.     {
  426. mark_adjust(dest + 1, line1 - 1, num_lines, 0L);
  427. curbuf->b_op_start.lnum = dest + 1;
  428. curbuf->b_op_end.lnum = dest + num_lines;
  429.     }
  430.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  431.     mark_adjust(last_line - num_lines + 1, last_line,
  432.      -(last_line - dest - extra), 0L);
  433.     /*
  434.      * Now we delete the original text -- webb
  435.      */
  436.     if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
  437. return FAIL;
  438.     for (l = line1; l <= line2; l++)
  439. ml_delete(line1 + extra, TRUE);
  440.     changed();
  441.     if (!global_busy && num_lines > p_report)
  442. smsg((char_u *)"%ld line%s moved", num_lines, plural(num_lines));
  443.     /*
  444.      * Leave the cursor on the last of the moved lines.
  445.      */
  446.     if (dest >= line1)
  447. curwin->w_cursor.lnum = dest;
  448.     else
  449. curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
  450.     changed_line_abv_curs();
  451.     /*
  452.      * TODO: should recompute w_botline for simple situations.
  453.      */
  454.     invalidate_botline();
  455.     return OK;
  456. }
  457. /*
  458.  * :copy command - copy lines line1-line2 to line n
  459.  */
  460.     void
  461. do_copy(line1, line2, n)
  462.     linenr_t line1;
  463.     linenr_t line2;
  464.     linenr_t n;
  465. {
  466.     linenr_t     lnum;
  467.     char_u     *p;
  468.     lnum = line2 - line1 + 1;
  469.     mark_adjust(n + 1, (linenr_t)MAXLNUM, lnum, 0L);
  470.     curbuf->b_op_start.lnum = n + 1;
  471.     curbuf->b_op_end.lnum = n + lnum;
  472.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  473.     /*
  474.      * there are three situations:
  475.      * 1. destination is above line1
  476.      * 2. destination is between line1 and line2
  477.      * 3. destination is below line2
  478.      *
  479.      * n = destination (when starting)
  480.      * curwin->w_cursor.lnum = destination (while copying)
  481.      * line1 = start of source (while copying)
  482.      * line2 = end of source (while copying)
  483.      */
  484.     if (u_save(n, n + 1) == FAIL)
  485. return;
  486.     curwin->w_cursor.lnum = n;
  487.     while (line1 <= line2)
  488.     {
  489. /* need to use vim_strsave() because the line will be unlocked
  490.     within ml_append */
  491. p = vim_strsave(ml_get(line1));
  492. if (p != NULL)
  493. {
  494.     ml_append(curwin->w_cursor.lnum, p, (colnr_t)0, FALSE);
  495.     vim_free(p);
  496. }
  497. /* situation 2: skip already copied lines */
  498. if (line1 == n)
  499.     line1 = curwin->w_cursor.lnum;
  500. ++line1;
  501. if (curwin->w_cursor.lnum < line1)
  502.     ++line1;
  503. if (curwin->w_cursor.lnum < line2)
  504.     ++line2;
  505. ++curwin->w_cursor.lnum;
  506.     }
  507.     changed();
  508.     changed_line_abv_curs();
  509.     /*
  510.      * TODO: should recompute w_botline for simple situations.
  511.      */
  512.     invalidate_botline();
  513.     msgmore((long)lnum);
  514. }
  515. /*
  516.  * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
  517.  * Bangs in the argument are replaced with the previously entered command.
  518.  * Remember the argument.
  519.  *
  520.  * RISCOS: Bangs only replaced when followed by a space, since many
  521.  * pathnames contain one.
  522.  */
  523.     void
  524. do_bang(addr_count, line1, line2, forceit, arg, do_in, do_out)
  525.     int addr_count;
  526.     linenr_t line1, line2;
  527.     int forceit;
  528.     char_u *arg;
  529.     int do_in, do_out;
  530. {
  531.     static  char_u  *prevcmd = NULL;     /* the previous command */
  532.     char_u     *newcmd = NULL;     /* the new command */
  533.     int     free_newcmd = FALSE;    /* need to free() newcmd */
  534.     int     ins_prevcmd;
  535.     char_u     *t;
  536.     char_u     *p;
  537.     char_u     *trailarg;
  538.     int     len;
  539.     int     scroll_save = msg_scroll;
  540.     /*
  541.      * Disallow shell commands for "rvim".
  542.      * Disallow shell commands from .exrc and .vimrc in current directory for
  543.      * security reasons.
  544.      */
  545.     if (check_restricted() || check_secure())
  546. return;
  547.     if (addr_count == 0) /* :! */
  548.     {
  549. msg_scroll = FALSE;     /* don't scroll here */
  550. autowrite_all();
  551. msg_scroll = scroll_save;
  552.     }
  553.     /*
  554.      * Try to find an embedded bang, like in :!<cmd> ! [args]
  555.      * (:!! is indicated by the 'forceit' variable)
  556.      */
  557.     ins_prevcmd = forceit;
  558.     trailarg = arg;
  559.     do
  560.     {
  561. len = STRLEN(trailarg) + 1;
  562. if (newcmd != NULL)
  563.     len += STRLEN(newcmd);
  564. if (ins_prevcmd)
  565. {
  566.     if (prevcmd == NULL)
  567.     {
  568. emsg(e_noprev);
  569. vim_free(newcmd);
  570. return;
  571.     }
  572.     len += STRLEN(prevcmd);
  573. }
  574. if ((t = alloc(len)) == NULL)
  575. {
  576.     vim_free(newcmd);
  577.     return;
  578. }
  579. *t = NUL;
  580. if (newcmd != NULL)
  581.     STRCAT(t, newcmd);
  582. if (ins_prevcmd)
  583.     STRCAT(t, prevcmd);
  584. p = t + STRLEN(t);
  585. STRCAT(t, trailarg);
  586. vim_free(newcmd);
  587. newcmd = t;
  588. /*
  589.  * Scan the rest of the argument for '!', which is replaced by the
  590.  * previous command.  "!" is replaced by "!" (this is vi compatible).
  591.  */
  592. trailarg = NULL;
  593. while (*p)
  594. {
  595.     if (*p == '!'
  596. #ifdef RISCOS
  597. && (p[1] == ' ' || p[1] == NUL)
  598. #endif
  599. )
  600.     {
  601. if (p > newcmd && p[-1] == '\')
  602.     mch_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
  603. else
  604. {
  605.     trailarg = p;
  606.     *trailarg++ = NUL;
  607.     ins_prevcmd = TRUE;
  608.     break;
  609. }
  610.     }
  611.     ++p;
  612. }
  613.     } while (trailarg != NULL);
  614.     vim_free(prevcmd);
  615.     prevcmd = newcmd;
  616.     if (bangredo)     /* put cmd in redo buffer for ! command */
  617.     {
  618. AppendToRedobuff(prevcmd);
  619. AppendToRedobuff((char_u *)"n");
  620. bangredo = FALSE;
  621.     }
  622.     /*
  623.      * Add quotes around the command, for shells that need them.
  624.      */
  625.     if (*p_shq != NUL)
  626.     {
  627. newcmd = alloc((unsigned)(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1));
  628. if (newcmd == NULL)
  629.     return;
  630. STRCPY(newcmd, p_shq);
  631. STRCAT(newcmd, prevcmd);
  632. STRCAT(newcmd, p_shq);
  633. free_newcmd = TRUE;
  634.     }
  635.     if (addr_count == 0) /* :! */
  636.     {
  637.     /* echo the command */
  638. msg_start();
  639. msg_putchar(':');
  640. msg_putchar('!');
  641. msg_outtrans(newcmd);
  642. msg_clr_eos();
  643. windgoto(msg_row, msg_col);
  644. do_shell(newcmd, 0);
  645.     }
  646.     else /* :range! */
  647. /* Careful: This may recursively call do_bang() again! (because of
  648.  * autocommands) */
  649. do_filter(line1, line2, newcmd, do_in, do_out);
  650.     if (free_newcmd)
  651. vim_free(newcmd);
  652. }
  653. /*
  654.  * call a shell to execute a command
  655.  *
  656.  * RISCOS GUI: If cmd starts with '~' then don't output anything, and don't
  657.  * wait for <Return> afterwards.
  658.   */
  659.     void
  660. do_shell(cmd, flags)
  661.     char_u  *cmd;
  662.     int     flags; /* may be SHELL_DOOUT when output is redirected */
  663. {
  664.     BUF     *buf;
  665. #ifndef USE_GUI_WIN32
  666.     int     save_nwr;
  667. #endif
  668. #ifdef WIN32
  669.     int     winstart;
  670. #endif
  671. #ifdef RISCOS
  672.     int     silent = FALSE;
  673. #endif
  674.     /*
  675.      * Disallow shell commands for "rvim".
  676.      * Disallow shell commands from .exrc and .vimrc in current directory for
  677.      * security reasons.
  678.      */
  679.     if (check_restricted() || check_secure())
  680.     {
  681. msg_end();
  682. return;
  683.     }
  684. #ifdef RISCOS
  685.     while (*cmd == ' ')
  686. cmd++;
  687.     if (*cmd == '~')
  688.     {
  689. /* Useful for commands with no output, or those which open
  690.  * another window for their output.
  691.  */
  692. cmd++;
  693. # ifdef USE_GUI
  694. if (gui.in_use)
  695. {
  696.     silent = TRUE;
  697.     flags |= SHELL_FILTER; /* Makes call_shell() silent too */
  698. }
  699. # endif
  700.     }
  701. #endif
  702. #ifdef WIN32
  703.     /*
  704.      * Check if external commands are allowed now.
  705.      */
  706.     if (can_end_termcap_mode(TRUE) == FALSE)
  707. return;
  708.     /*
  709.      * Check if ":!start" is used.
  710.      */
  711.     if (cmd)
  712. winstart = (STRNICMP(cmd, "start ", 6) == 0);
  713. #endif
  714.     /*
  715.      * For autocommands we want to get the output on the current screen, to
  716.      * avoid having to type return below.
  717.      */
  718.     msg_putchar('r'); /* put cursor at start of line */
  719. #ifdef AUTOCMD
  720.     if (!autocmd_busy)
  721. #endif
  722.     {
  723. #ifdef WIN32
  724. if (!winstart)
  725. #endif
  726.     stoptermcap();
  727.     }
  728. #ifdef RISCOS
  729.     if (!silent)
  730. #endif
  731. msg_putchar('n'); /* may shift screen one line up */
  732.     /* warning message before calling the shell */
  733.     if (p_warn
  734. #ifdef AUTOCMD
  735. && !autocmd_busy
  736. #endif
  737. #ifdef RISCOS
  738. && !silent
  739. #endif
  740.    )
  741. for (buf = firstbuf; buf; buf = buf->b_next)
  742.     if (buf_changed(buf))
  743.     {
  744. #ifdef USE_GUI_WIN32
  745. if (!winstart)
  746.     starttermcap();     /* don't want a message box here */
  747. #endif
  748. MSG_PUTS("[No write since last change]n");
  749. #ifdef USE_GUI_WIN32
  750. if (!winstart)
  751.     stoptermcap();
  752. #endif
  753. break;
  754.     }
  755. /* This windgoto is required for when the 'n' resulted in a "delete line 1"
  756.  * command to the terminal. */
  757.     if (!swapping_screen())
  758. windgoto(msg_row, msg_col);
  759.     cursor_on();
  760.     (void)call_shell(cmd, SHELL_COOKED | flags);
  761.     need_check_timestamps = TRUE;
  762. /*
  763.  * put the message cursor at the end of the screen, avoids wait_return() to
  764.  * overwrite the text that the external command showed
  765.  */
  766.     if (!swapping_screen())
  767.     {
  768. msg_row = Rows - 1;
  769. msg_col = 0;
  770.     }
  771. #ifdef AUTOCMD
  772.     if (autocmd_busy)
  773. must_redraw = CLEAR;
  774.     else
  775. #endif
  776.     {
  777. /*
  778.  * For ":sh" there is no need to call wait_return(), just redraw.
  779.  * Also for the Win32 GUI (the output is in a console window).
  780.  * Otherwise there is probably text on the screen that the user wants
  781.  * to read before redrawing, so call wait_return().
  782.  */
  783. #ifndef USE_GUI_WIN32
  784. # ifdef WIN32
  785. if ((cmd == NULL) || (winstart && !need_wait_return))
  786. {
  787.     must_redraw = CLEAR;
  788. # elif defined(RISCOS)
  789. if (cmd == NULL || silent)
  790. {
  791.     if (!silent)
  792. must_redraw = CLEAR;
  793. # else
  794. if (cmd == NULL)
  795. {
  796.     must_redraw = CLEAR;
  797. # endif
  798. #endif
  799.     need_wait_return = FALSE;
  800.     dont_wait_return = TRUE;
  801. #ifndef USE_GUI_WIN32
  802. }
  803. else
  804. {
  805.     /*
  806.      * If we switch screens when starttermcap() is called, we really
  807.      * want to wait for "hit return to continue".
  808.      */
  809.     save_nwr = no_wait_return;
  810.     if (swapping_screen())
  811. no_wait_return = FALSE;
  812. #ifdef AMIGA
  813.     wait_return(term_console ? -1 : TRUE); /* see below */
  814. #else
  815.     wait_return(TRUE);
  816. #endif
  817.     no_wait_return = save_nwr;
  818. }
  819. #endif /* USE_GUI_WIN32 */
  820. #ifdef WIN32
  821. if (!winstart) /*if winstart==TRUE, never stopped termcap!*/
  822. #endif
  823.     starttermcap(); /* start termcap if not done by wait_return() */
  824. /*
  825.  * In an Amiga window redrawing is caused by asking the window size.
  826.  * If we got an interrupt this will not work. The chance that the
  827.  * window size is wrong is very small, but we need to redraw the
  828.  * screen.  Don't do this if ':' hit in wait_return(). THIS IS UGLY
  829.  * but it saves an extra redraw.
  830.  */
  831. #ifdef AMIGA
  832. if (skip_redraw) /* ':' hit in wait_return() */
  833.     must_redraw = CLEAR;
  834. else if (term_console)
  835. {
  836.     OUT_STR("33[0 q"); /* get window size */
  837.     if (got_int)
  838. must_redraw = CLEAR; /* if got_int is TRUE, redraw needed */
  839.     else
  840. must_redraw = 0; /* no extra redraw needed */
  841. }
  842. #endif /* AMIGA */
  843.     }
  844.     /* display any error messages now */
  845.     mch_display_error();
  846. }
  847. /*
  848.  * do_filter: filter lines through a command given by the user
  849.  *
  850.  * We use temp files and the call_shell() routine here. This would normally
  851.  * be done using pipes on a UNIX machine, but this is more portable to
  852.  * non-unix machines. The call_shell() routine needs to be able
  853.  * to deal with redirection somehow, and should handle things like looking
  854.  * at the PATH env. variable, and adding reasonable extensions to the
  855.  * command name given by the user. All reasonable versions of call_shell()
  856.  * do this.
  857.  * We use input redirection if do_in is TRUE.
  858.  * We use output redirection if do_out is TRUE.
  859.  */
  860.     static void
  861. do_filter(line1, line2, buff, do_in, do_out)
  862.     linenr_t line1, line2;
  863.     char_u *buff;
  864.     int do_in, do_out;
  865. {
  866.     char_u *itmp = NULL;
  867.     char_u *otmp = NULL;
  868.     linenr_t linecount;
  869.     FPOS cursor_save;
  870. #ifdef AUTOCMD
  871.     BUF *old_curbuf = curbuf;
  872. #endif
  873.     if (*buff == NUL)     /* no filter command */
  874. return;
  875. #ifdef WIN32
  876.     /*
  877.      * Check if external commands are allowed now.
  878.      */
  879.     if (can_end_termcap_mode(TRUE) == FALSE)
  880. return;
  881. #endif
  882.     cursor_save = curwin->w_cursor;
  883.     linecount = line2 - line1 + 1;
  884.     curwin->w_cursor.lnum = line1;
  885.     curwin->w_cursor.col = 0;
  886.     changed_line_abv_curs();
  887.     invalidate_botline();
  888.     /*
  889.      * 1. Form temp file names
  890.      * 2. Write the lines to a temp file
  891.      * 3. Run the filter command on the temp file
  892.      * 4. Read the output of the command into the buffer
  893.      * 5. Delete the original lines to be filtered
  894.      * 6. Remove the temp files
  895.      */
  896.     if ((do_in && (itmp = vim_tempname('i')) == NULL) ||
  897.        (do_out && (otmp = vim_tempname('o')) == NULL))
  898.     {
  899. emsg(e_notmp);
  900. goto filterend;
  901.     }
  902. /*
  903.  * The writing and reading of temp files will not be shown.
  904.  * Vi also doesn't do this and the messages are not very informative.
  905.  */
  906.     ++no_wait_return; /* don't call wait_return() while busy */
  907.     if (do_in && buf_write(curbuf, itmp, NULL, line1, line2,
  908.    FALSE, FALSE, FALSE, TRUE) == FAIL)
  909.     {
  910. msg_putchar('n');     /* keep message from buf_write() */
  911. --no_wait_return;
  912. (void)emsg2(e_notcreate, itmp);     /* will call wait_return */
  913. goto filterend;
  914.     }
  915. #ifdef AUTOCMD
  916.     if (curbuf != old_curbuf)
  917. goto filterend;
  918. #endif
  919.     if (!do_out)
  920. msg_putchar('n');
  921. #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
  922. /*
  923.  * put braces around the command (for concatenated commands)
  924.  */
  925.     sprintf((char *)IObuff, "(%s)", (char *)buff);
  926.     if (do_in)
  927.     {
  928. STRCAT(IObuff, " < ");
  929. STRCAT(IObuff, itmp);
  930.     }
  931. #else
  932. /*
  933.  * for shells that don't understand braces around commands, at least allow
  934.  * the use of commands in a pipe.
  935.  */
  936.     STRCPY(IObuff, buff);
  937.     if (do_in)
  938.     {
  939. char_u     *p;
  940. /*
  941.  * If there is a pipe, we have to put the '<' in front of it.
  942.  * Don't do this when 'shellquote' is not empty, otherwise the
  943.  * redirection would be inside the quotes.
  944.  */
  945. p = vim_strchr(IObuff, '|');
  946. if (p && *p_shq == NUL)
  947.     *p = NUL;
  948. #ifdef RISCOS
  949. STRCAT(IObuff, " { < ");    /* Use RISC OS notation for input. */
  950. STRCAT(IObuff, itmp);
  951. STRCAT(IObuff, " } ");
  952. #else
  953. STRCAT(IObuff, " <");     /* " < " causes problems on Amiga */
  954. STRCAT(IObuff, itmp);
  955. #endif
  956. p = vim_strchr(buff, '|');
  957. if (p && *p_shq == NUL)
  958.     STRCAT(IObuff, p);
  959.     }
  960. #endif
  961.     if (do_out)
  962.     {
  963. char_u *p;
  964. if ((p = vim_strchr(p_srr, '%')) != NULL && p[1] == 's')
  965. {
  966.     p = IObuff + STRLEN(IObuff);
  967.     *p++ = ' '; /* not really needed? Not with sh, ksh or bash */
  968.     sprintf((char *)p, (char *)p_srr, (char *)otmp);
  969. }
  970. else
  971.     sprintf((char *)IObuff + STRLEN(IObuff),
  972. #ifndef RISCOS
  973.     " %s%s", /* " %s %s" causes problems on Amiga */
  974. #else
  975.     " %s %s", /* But is needed for RISC OS */
  976. #endif
  977.     (char *)p_srr, (char *)otmp);
  978.     }
  979.     windgoto((int)Rows - 1, 0);
  980.     cursor_on();
  981.     /*
  982.      * When not redirecting the output the command can write anything to the
  983.      * screen. If 'shellredir' is equal to ">", screen may be messed up by
  984.      * stderr output of external command. Clear the screen later.
  985.      * If do_in is FALSE, this could be something like ":r !cat", which may
  986.      * also mess up the screen, clear it later.
  987.      */
  988.     if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
  989. must_redraw = CLEAR;
  990.     else
  991. redraw_later(NOT_VALID);
  992.     /*
  993.      * When call_shell() fails wait_return() is called to give the user a
  994.      * chance to read the error messages. Otherwise errors are ignored, so you
  995.      * can see the error messages from the command that appear on stdout; use
  996.      * 'u' to fix the text
  997.      * Switch to cooked mode when not redirecting stdin, avoids that something
  998.      * like ":r !cat" hangs.
  999.      * Pass on the SHELL_DOOUT flag when the output is being redirected.
  1000.      */
  1001.     if (call_shell(IObuff, SHELL_FILTER | SHELL_COOKED |
  1002.   (do_out ? SHELL_DOOUT : 0)))
  1003.     {
  1004. must_redraw = CLEAR;
  1005. wait_return(FALSE);
  1006.     }
  1007.     need_check_timestamps = TRUE;
  1008.     if (do_out)
  1009.     {
  1010. if (u_save((linenr_t)(line2), (linenr_t)(line2 + 1)) == FAIL)
  1011. {
  1012.     goto error;
  1013. }
  1014. if (readfile(otmp, NULL, line2, (linenr_t)0, (linenr_t)MAXLNUM,
  1015.  READ_FILTER) == FAIL)
  1016. {
  1017.     msg_putchar('n');
  1018.     emsg2(e_notread, otmp);
  1019.     goto error;
  1020. }
  1021. #ifdef AUTOCMD
  1022. if (curbuf != old_curbuf)
  1023.     goto filterend;
  1024. #endif
  1025. if (do_in)
  1026. {
  1027.     /*
  1028.      * Put cursor on first filtered line for ":range!cmd".
  1029.      * Adjust '[ and '] (set by buf_write()).
  1030.      */
  1031.     curwin->w_cursor.lnum = line1;
  1032.     del_lines(linecount, TRUE, TRUE);
  1033.     curbuf->b_op_start.lnum -= linecount; /* adjust '[ */
  1034.     curbuf->b_op_end.lnum -= linecount; /* adjust '] */
  1035.     write_lnum_adjust(-linecount); /* adjust last line
  1036.    for next write */
  1037. }
  1038. else
  1039. {
  1040.     /*
  1041.      * Put cursor on last new line for ":r !cmd".
  1042.      */
  1043.     curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
  1044.     linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
  1045. }
  1046. beginline(BL_WHITE | BL_FIX);     /* cursor on first non-blank */
  1047. --no_wait_return;
  1048. if (linecount > p_report)
  1049. {
  1050.     if (do_in)
  1051.     {
  1052. sprintf((char *)msg_buf, "%ld lines filtered", (long)linecount);
  1053. if (msg(msg_buf) && !msg_scroll)
  1054. {
  1055.     keep_msg = msg_buf;     /* display message after redraw */
  1056.     keep_msg_attr = 0;
  1057. }
  1058.     }
  1059.     else
  1060. msgmore((long)linecount);
  1061. }
  1062.     }
  1063.     else
  1064.     {
  1065. error:
  1066. /* put cursor back in same position for ":w !cmd" */
  1067. curwin->w_cursor = cursor_save;
  1068. --no_wait_return;
  1069. wait_return(FALSE);
  1070.     }
  1071. filterend:
  1072. #ifdef AUTOCMD
  1073.     if (curbuf != old_curbuf)
  1074.     {
  1075. --no_wait_return;
  1076. EMSG("*Filter* Autocommands must not change current buffer");
  1077.     }
  1078. #endif
  1079.     if (itmp != NULL)
  1080. mch_remove(itmp);
  1081.     if (otmp != NULL)
  1082. mch_remove(otmp);
  1083.     vim_free(itmp);
  1084.     vim_free(otmp);
  1085. }
  1086. #ifdef VIMINFO
  1087. static int no_viminfo __ARGS((void));
  1088. static int  viminfo_errcnt;
  1089.     static int
  1090. no_viminfo()
  1091. {
  1092.     /* "vim -i NONE" does not read or write a viminfo file */
  1093.     return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
  1094. }
  1095. /*
  1096.  * Report an error for reading a viminfo file.
  1097.  * Count the number of errors. When there are more than 10, return TRUE.
  1098.  */
  1099.     int
  1100. viminfo_error(message, line)
  1101.     char    *message;
  1102.     char_u  *line;
  1103. {
  1104.     sprintf((char *)IObuff, "viminfo: %s in line: ", message);
  1105.     STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
  1106.     emsg(IObuff);
  1107.     if (++viminfo_errcnt >= 10)
  1108.     {
  1109. EMSG("viminfo: Too many errors, skipping rest of file");
  1110. return TRUE;
  1111.     }
  1112.     return FALSE;
  1113. }
  1114. /*
  1115.  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
  1116.  * set are not over-written unless force is TRUE. -- webb
  1117.  */
  1118.     int
  1119. read_viminfo(file, want_info, want_marks, forceit)
  1120.     char_u  *file;
  1121.     int     want_info;
  1122.     int     want_marks;
  1123.     int     forceit;
  1124. {
  1125.     FILE    *fp;
  1126.     if (no_viminfo())
  1127. return FAIL;
  1128.     file = viminfo_filename(file);     /* may set to default if NULL */
  1129.     if ((fp = fopen((char *)file, READBIN)) == NULL)
  1130. return FAIL;
  1131.     if (p_verbose > 0)
  1132. smsg((char_u *)"Reading viminfo file "%s"%s%s", file,
  1133.     want_info ? " info" : "",
  1134.     want_marks ? " marks" : "");
  1135.     viminfo_errcnt = 0;
  1136.     do_viminfo(fp, NULL, want_info, want_marks, forceit);
  1137.     fclose(fp);
  1138.     return OK;
  1139. }
  1140. /*
  1141.  * write_viminfo() -- Write the viminfo file.  The old one is read in first so
  1142.  * that effectively a merge of current info and old info is done.  This allows
  1143.  * multiple vims to run simultaneously, without losing any marks etc.  If
  1144.  * forceit is TRUE, then the old file is not read in, and only internal info is
  1145.  * written to the file. -- webb
  1146.  */
  1147.     void
  1148. write_viminfo(file, forceit)
  1149.     char_u  *file;
  1150.     int     forceit;
  1151. {
  1152.     FILE     *fp_in = NULL; /* input viminfo file, if any */
  1153.     FILE     *fp_out = NULL; /* output viminfo file */
  1154.     char_u     *tempname = NULL; /* name of temp viminfo file */
  1155.     struct stat     st_new; /* stat() of potential new file */
  1156.     char_u     *wp;
  1157. #ifdef UNIX
  1158.     int     shortname = FALSE; /* use 8.3 file name */
  1159.     mode_t     umask_save;
  1160.     struct stat     st_old; /* stat() of existing viminfo file */
  1161. #endif
  1162.     if (no_viminfo())
  1163. return;
  1164.     file = viminfo_filename(file); /* may set to default if NULL */
  1165.     file = vim_strsave(file); /* make a copy, don't want NameBuff */
  1166.     if (file != NULL)
  1167.     {
  1168. fp_in = fopen((char *)file, READBIN);
  1169. if (fp_in == NULL)
  1170. {
  1171.     /* if it does exist, but we can't read it, don't try writing */
  1172.     if (stat((char *)file, &st_new) == 0)
  1173. goto end;
  1174. #ifdef UNIX
  1175.     /*
  1176.      * For Unix we create the .viminfo non-accessible for others,
  1177.      * because it may contain text from non-accessible documents.
  1178.      */
  1179.     umask_save = umask(077);
  1180. #endif
  1181.     fp_out = fopen((char *)file, WRITEBIN);
  1182. #ifdef UNIX
  1183.     (void)umask(umask_save);
  1184. #endif
  1185. }
  1186. else
  1187. {
  1188.     /*
  1189.      * There is an existing viminfo file.  Create a temporary file to
  1190.      * write the new viminfo into, in the same directory as the
  1191.      * existing viminfo file, which will be renamed later.
  1192.      */
  1193. #ifdef UNIX
  1194.     /*
  1195.      * For Unix we check the owner of the file.  It's not very nice to
  1196.      * overwrite a user's viminfo file after a "su root", with a
  1197.      * viminfo file that the user can't read.
  1198.      */
  1199.     st_old.st_dev = st_old.st_ino = 0;
  1200.     st_old.st_mode = 0600;
  1201.     if (stat((char *)file, &st_old) == 0 && getuid() &&
  1202.     !(st_old.st_uid == getuid()
  1203.     ? (st_old.st_mode & 0200)
  1204.     : (st_old.st_gid == getgid()
  1205.     ? (st_old.st_mode & 0020)
  1206.     : (st_old.st_mode & 0002))))
  1207.     {
  1208. int tt;
  1209. /* avoid a wait_return for this message, it's annoying */
  1210. tt = msg_didany;
  1211. EMSG2("Viminfo file is not writable: %s", file);
  1212. msg_didany = tt;
  1213. goto end;
  1214.     }
  1215. #endif
  1216.     /*
  1217.      * Make tempname.
  1218.      * May try twice: Once normal and once with shortname set, just in
  1219.      * case somebody puts his viminfo file in an 8.3 filesystem.
  1220.      */
  1221.     for (;;)
  1222.     {
  1223. tempname = buf_modname(
  1224. #ifdef UNIX
  1225. shortname,
  1226. #else
  1227. # ifdef SHORT_FNAME
  1228. TRUE,
  1229. # else
  1230. #  ifdef USE_GUI_WIN32
  1231. gui_is_win32s(),
  1232. #  else
  1233. FALSE,
  1234. #  endif
  1235. # endif
  1236. #endif
  1237. file,
  1238. #ifdef VMS
  1239. (char_u *)"-tmp",
  1240. #else
  1241. # ifdef RISCOS
  1242. (char_u *)"/tmp",
  1243. # else
  1244. (char_u *)".tmp",
  1245. # endif
  1246. #endif
  1247. FALSE);
  1248. if (tempname == NULL) /* out of memory */
  1249.     break;
  1250. /*
  1251.  * Check if tempfile already exists.  Never overwrite an
  1252.  * existing file!
  1253.  */
  1254. if (stat((char *)tempname, &st_new) == 0)
  1255. {
  1256. #ifdef UNIX
  1257.     /*
  1258.      * Check if tempfile is same as original file.  May happen
  1259.      * when modname gave the same file back.  E.g.  silly
  1260.      * link, or file name-length reached.  Try again with
  1261.      * shortname set.
  1262.      */
  1263.     if (!shortname && st_new.st_dev == st_old.st_dev &&
  1264.     st_new.st_ino == st_old.st_ino)
  1265.     {
  1266. vim_free(tempname);
  1267. tempname = NULL;
  1268. shortname = TRUE;
  1269. continue;
  1270.     }
  1271. #endif
  1272.     /*
  1273.      * Try another name.  Change one character, just before
  1274.      * the extension.  This should also work for an 8.3
  1275.      * file name, when after adding the extension it still is
  1276.      * the same file as the original.
  1277.      */
  1278.     wp = tempname + STRLEN(tempname) - 5;
  1279.     if (wp < gettail(tempname))     /* empty file name? */
  1280. wp = gettail(tempname);
  1281.     for (*wp = 'z'; stat((char *)tempname, &st_new) == 0; --*wp)
  1282.     {
  1283. /*
  1284.  * They all exist?  Must be something wrong! Don't
  1285.  * write the viminfo file then.
  1286.  */
  1287. if (*wp == 'a')
  1288. {
  1289.     vim_free(tempname);
  1290.     tempname = NULL;
  1291.     break;
  1292. }
  1293.     }
  1294. }
  1295. break;
  1296.     }
  1297.     if (tempname != NULL)
  1298.     {
  1299. fp_out = fopen((char *)tempname, WRITEBIN);
  1300. /*
  1301.  * If we can't create in the same directory, try creating a
  1302.  * "normal" temp file.
  1303.  */
  1304. if (fp_out == NULL)
  1305. {
  1306.     vim_free(tempname);
  1307.     if ((tempname = vim_tempname('o')) != NULL)
  1308. fp_out = fopen((char *)tempname, WRITEBIN);
  1309. }
  1310. #ifdef UNIX
  1311. /*
  1312.  * Set file protection same as original file, but strip s-bit
  1313.  * and make sure the owner can read/write it.
  1314.  */
  1315. if (fp_out != NULL)
  1316. {
  1317.     (void)mch_setperm(tempname,
  1318.       (long)((st_old.st_mode & 0777) | 0600));
  1319.     /* this only works for root: */
  1320.     (void)chown((char *)tempname, st_old.st_uid, st_old.st_gid);
  1321. }
  1322. #endif
  1323.     }
  1324. }
  1325.     }
  1326.     /*
  1327.      * Check if the new viminfo file can be written to.
  1328.      */
  1329.     if (file == NULL || fp_out == NULL)
  1330.     {
  1331. EMSG2("Can't write viminfo file %s!", file == NULL ? (char_u *)"" :
  1332.       fp_in == NULL ? file : tempname);
  1333. if (fp_in != NULL)
  1334.     fclose(fp_in);
  1335. goto end;
  1336.     }
  1337.     if (p_verbose > 0)
  1338. smsg((char_u *)"Writing viminfo file "%s"", file);
  1339.     viminfo_errcnt = 0;
  1340.     do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
  1341.     fclose(fp_out);     /* errors are ignored !? */
  1342.     if (fp_in != NULL)
  1343.     {
  1344. fclose(fp_in);
  1345. /*
  1346.  * In case of an error, don't overwrite the original viminfo file.
  1347.  */
  1348. if (viminfo_errcnt || vim_rename(tempname, file) == -1)
  1349.     mch_remove(tempname);
  1350.     }
  1351. end:
  1352.     vim_free(file);
  1353.     vim_free(tempname);
  1354. }
  1355. /*
  1356.  * Get the viminfo file name to use.
  1357.  * If "file" is given and not empty, use it (has already been expanded by
  1358.  * cmdline functions).
  1359.  * Otherwise use "-i file_name", value from 'viminfo' or the default, and
  1360.  * expand environment variables.
  1361.  */
  1362.     static char_u *
  1363. viminfo_filename(file)
  1364.     char_u *file;
  1365. {
  1366.     if (file == NULL || *file == NUL)
  1367.     {
  1368. if (use_viminfo != NULL)
  1369.     file = use_viminfo;
  1370. else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
  1371. {
  1372. #ifdef VIMINFO_FILE2
  1373.     /* don't use $HOME when not defined (turned into "c:/"!). */
  1374.     if (mch_getenv((char_u *)"HOME") == NULL)
  1375.     {
  1376. /* don't use $VIM when not available. */
  1377. expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
  1378. if (STRCMP("$VIM", NameBuff) != 0)  /* $VIM was expanded */
  1379.     file = (char_u *)VIMINFO_FILE2;
  1380. else
  1381.     file = (char_u *)VIMINFO_FILE;
  1382.     }
  1383.     else
  1384. #endif
  1385. file = (char_u *)VIMINFO_FILE;
  1386. }
  1387. expand_env(file, NameBuff, MAXPATHL);
  1388. return NameBuff;
  1389.     }
  1390.     return file;
  1391. }
  1392. /*
  1393.  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
  1394.  */
  1395.     static void
  1396. do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
  1397.     FILE    *fp_in;
  1398.     FILE    *fp_out;
  1399.     int     want_info;
  1400.     int     want_marks;
  1401.     int     force_read;
  1402. {
  1403.     int     count = 0;
  1404.     int     eof = FALSE;
  1405.     char_u  *line;
  1406.     if ((line = alloc(LSIZE)) == NULL)
  1407. return;
  1408.     if (fp_in != NULL)
  1409.     {
  1410. if (want_info)
  1411.     eof = read_viminfo_up_to_marks(line, fp_in, force_read,
  1412.       fp_out != NULL);
  1413. else
  1414.     /* Skip info, find start of marks */
  1415.     while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] != '>')
  1416. ;
  1417.     }
  1418.     if (fp_out != NULL)
  1419.     {
  1420. /* Write the info: */
  1421. fprintf(fp_out, "# This viminfo file was generated by vimn");
  1422. fprintf(fp_out, "# You may edit it if you're careful!nn");
  1423. write_viminfo_search_pattern(fp_out);
  1424. write_viminfo_sub_string(fp_out);
  1425. write_viminfo_history(fp_out);
  1426. write_viminfo_registers(fp_out);
  1427. write_viminfo_filemarks(fp_out);
  1428. write_viminfo_bufferlist(fp_out);
  1429. count = write_viminfo_marks(fp_out);
  1430.     }
  1431.     if (fp_in != NULL && want_marks)
  1432. copy_viminfo_marks(line, fp_in, fp_out, count, eof);
  1433.     vim_free(line);
  1434. }
  1435. /*
  1436.  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
  1437.  * first part of the viminfo file which contains everything but the marks that
  1438.  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
  1439.  */
  1440.     static int
  1441. read_viminfo_up_to_marks(line, fp, forceit, writing)
  1442.     char_u  *line;
  1443.     FILE    *fp;
  1444.     int     forceit;
  1445.     int     writing;
  1446. {
  1447.     int     eof;
  1448.     prepare_viminfo_history(forceit ? 9999 : 0);
  1449.     eof = vim_fgets(line, LSIZE, fp);
  1450.     while (!eof && line[0] != '>')
  1451.     {
  1452. switch (line[0])
  1453. {
  1454. /* Characters reserved for future expansion, ignored now */
  1455.     case '+': /* "+40 /path/dir file", for running vim without args */
  1456.     case '|': /* to be defined */
  1457.     case '-': /* to be defined */
  1458.     case '!': /* to be defined */
  1459.     case '^': /* to be defined */
  1460.     case '*': /* to be defined */
  1461.     case '<': /* to be defined */
  1462. /* A comment */
  1463.     case NUL:
  1464.     case 'r':
  1465.     case 'n':
  1466.     case '#':
  1467. eof = vim_fgets(line, LSIZE, fp);
  1468. break;
  1469.     case '%': /* entry for buffer list */
  1470. eof = read_viminfo_bufferlist(line, fp, writing);
  1471. break;
  1472.     case '"':
  1473. eof = read_viminfo_register(line, fp, forceit);
  1474. break;
  1475.     case '/':     /* Search string */
  1476.     case '&':     /* Substitute search string */
  1477.     case '~':     /* Last search string, followed by '/' or '&' */
  1478. eof = read_viminfo_search_pattern(line, fp, forceit);
  1479. break;
  1480.     case '$':
  1481. eof = read_viminfo_sub_string(line, fp, forceit);
  1482. break;
  1483.     case ':':
  1484.     case '?':
  1485.     case '=':
  1486.     case '@':
  1487. eof = read_viminfo_history(line, fp);
  1488. break;
  1489.     case ''':
  1490. /* How do we have a file mark when the file is not in the
  1491.  * buffer list?
  1492.  */
  1493. eof = read_viminfo_filemark(line, fp, forceit);
  1494. break;
  1495.     default:
  1496. if (viminfo_error("Illegal starting char", line))
  1497.     eof = TRUE;
  1498. else
  1499.     eof = vim_fgets(line, LSIZE, fp);
  1500. break;
  1501. }
  1502.     }
  1503.     finish_viminfo_history();
  1504.     return eof;
  1505. }
  1506. /*
  1507.  * check string read from viminfo file
  1508.  * remove 'n' at the end of the line
  1509.  * - replace CTRL-V CTRL-V with CTRL-V
  1510.  * - replace CTRL-V 'n'    with 'n'
  1511.  */
  1512.     void
  1513. viminfo_readstring(p)
  1514.     char_u *p;
  1515. {
  1516.     while (*p != NUL && *p != 'n')
  1517.     {
  1518. if (*p == Ctrl('V'))
  1519. {
  1520.     if (p[1] == 'n')
  1521. p[0] = 'n';
  1522.     mch_memmove(p + 1, p + 2, STRLEN(p));
  1523. }
  1524. ++p;
  1525.     }
  1526.     *p = NUL;
  1527. }
  1528. /*
  1529.  * write string to viminfo file
  1530.  * - replace CTRL-V with CTRL-V CTRL-V
  1531.  * - replace 'n'   with CTRL-V 'n'
  1532.  * - add a 'n' at the end
  1533.  */
  1534.     void
  1535. viminfo_writestring(fd, p)
  1536.     FILE    *fd;
  1537.     char_u  *p;
  1538. {
  1539.     int     c;
  1540.     while ((c = *p++) != NUL)
  1541.     {
  1542. if (c == Ctrl('V') || c == 'n')
  1543. {
  1544.     putc(Ctrl('V'), fd);
  1545.     if (c == 'n')
  1546. c = 'n';
  1547. }
  1548. putc(c, fd);
  1549.     }
  1550.     putc('n', fd);
  1551. }
  1552. #endif /* VIMINFO */
  1553. /*
  1554.  * Implementation of ":fixdel", also used by get_stty().
  1555.  *  <BS>    resulting <Del>
  1556.  *   ^? ^H
  1557.  * not ^? ^?
  1558.  */
  1559.     void
  1560. do_fixdel()
  1561. {
  1562.     char_u  *p;
  1563.     p = find_termcode((char_u *)"kb");
  1564.     add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ?
  1565.  (char_u *)"10" : (char_u *)"177");
  1566. }
  1567.     void
  1568. print_line_no_prefix(lnum, use_number)
  1569.     linenr_t lnum;
  1570.     int use_number;
  1571. {
  1572.     char_u numbuf[20];
  1573.     if (curwin->w_p_nu || use_number)
  1574.     {
  1575. sprintf((char *)numbuf, "%7ld ", (long)lnum);
  1576. msg_puts_attr(numbuf, hl_attr(HLF_N)); /* Highlight line nrs */
  1577.     }
  1578.     msg_prt_line(ml_get(lnum));
  1579. }
  1580. /*
  1581.  * Print a text line.  Also in silent mode ("ex -s").
  1582.  */
  1583.     void
  1584. print_line(lnum, use_number)
  1585.     linenr_t lnum;
  1586.     int use_number;
  1587. {
  1588.     int save_silent = silent_mode;
  1589.     silent_mode = FALSE;
  1590.     msg_start();
  1591.     print_line_no_prefix(lnum, use_number);
  1592.     if (save_silent)
  1593.     {
  1594. msg_putchar('n');
  1595. cursor_on(); /* msg_start() switches it off */
  1596. out_flush();
  1597. silent_mode = save_silent;
  1598.     }
  1599. }
  1600. /*
  1601.  * Implementation of ":file[!] [fname]".
  1602.  */
  1603.     void
  1604. do_file(arg, forceit)
  1605.     char_u  *arg;
  1606.     int     forceit;
  1607. {
  1608.     char_u *fname, *sfname, *xfname;
  1609.     BUF *buf;
  1610.     if (*arg != NUL)
  1611.     {
  1612. #ifdef AUTOCMD
  1613. buf = curbuf;
  1614. apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
  1615. /* buffer changed, don't change name now */
  1616. if (buf != curbuf)
  1617.     return;
  1618. #endif
  1619. /*
  1620.  * The name of the current buffer will be changed.
  1621.  * A new buffer entry needs to be made to hold the old
  1622.  * file name, which will become the alternate file name.
  1623.  */
  1624. fname = curbuf->b_ffname;
  1625. sfname = curbuf->b_sfname;
  1626. xfname = curbuf->b_fname;
  1627. curbuf->b_ffname = NULL;
  1628. curbuf->b_sfname = NULL;
  1629. if (setfname(arg, NULL, TRUE) == FAIL)
  1630. {
  1631.     curbuf->b_ffname = fname;
  1632.     curbuf->b_sfname = sfname;
  1633.     return;
  1634. }
  1635. curbuf->b_notedited = TRUE;
  1636. buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, FALSE);
  1637. if (buf != NULL)
  1638.     curwin->w_alt_fnum = buf->b_fnum;
  1639. vim_free(fname);
  1640. vim_free(sfname);
  1641. #ifdef AUTOCMD
  1642. apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
  1643. #endif
  1644.     }
  1645.     /* print full file name if :cd used */
  1646.     fileinfo(FALSE, FALSE, forceit);
  1647. }
  1648. /*
  1649.  * Do the Ex mode :insert and :append commands.
  1650.  * "getline" can be NULL, in which case a line is obtained from the user.
  1651.  */
  1652.     void
  1653. do_append(lnum, getline, cookie)
  1654.     linenr_t lnum;
  1655.     char_u *(*getline) __ARGS((int, void *, int));
  1656.     void *cookie; /* argument for getline() */
  1657. {
  1658.     char_u *theline;
  1659.     int did_undo = FALSE;
  1660.     int lfirst = lnum;
  1661.     State = INSERT;     /* behave like in Insert mode */
  1662.     while (1)
  1663.     {
  1664. msg_scroll = TRUE;
  1665. need_wait_return = FALSE;
  1666. if (getline == NULL)
  1667.     theline = getcmdline(NUL, 0L, 0);
  1668. else
  1669.     theline = getline(NUL, cookie, 0);
  1670. lines_left = Rows - 1;
  1671. if (theline == NULL || (theline[0] == '.' && theline[1] == NUL))
  1672.     break;
  1673. if (!did_undo && u_save(lnum, lnum + 1) == FAIL)
  1674.     break;
  1675. did_undo = TRUE;
  1676. mark_adjust(lnum + 1, (linenr_t)MAXLNUM, 1L, 0L);
  1677. ml_append(lnum, theline, (colnr_t)0, FALSE);
  1678. changed();
  1679. vim_free(theline);
  1680. ++lnum;
  1681.     }
  1682.     State = NORMAL;
  1683.     /* "start" is set to lfirst+1 unless that position is invalid (when
  1684.      * lfirst pointed to the end of the buffer and nothig was appended)
  1685.      * "end" is set to lnum when something has been appended, otherwise
  1686.      * it is the same than "start"  -- Acevedo */
  1687.     curbuf->b_op_start.lnum = (lfirst < curbuf->b_ml.ml_line_count) ?
  1688. lfirst + 1 : curbuf->b_ml.ml_line_count;
  1689.     curbuf->b_op_end.lnum = (lfirst < lnum) ? lnum : curbuf->b_op_start.lnum;
  1690.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  1691.     curwin->w_cursor.lnum = lnum;
  1692.     check_cursor_lnum();
  1693.     beginline(BL_SOL | BL_FIX);
  1694.     changed_line_abv_curs();
  1695.     invalidate_botline();
  1696.     dont_wait_return = TRUE;     /* don't use wait_return() now */
  1697.     need_wait_return = FALSE;
  1698.     update_screen(NOT_VALID);
  1699. }
  1700. /*
  1701.  * Do the Ex mode :change command.
  1702.  * "getline" can be NULL, in which case a line is obtained from the user.
  1703.  */
  1704.     void
  1705. do_change(start, end, getline, cookie)
  1706.     linenr_t start;
  1707.     linenr_t end;
  1708.     char_u *(*getline) __ARGS((int, void *, int));
  1709.     void *cookie; /* argument for getline() */
  1710. {
  1711.     if (end >= start && u_save(start - 1, end + 1) == FAIL)
  1712. return;
  1713.     mark_adjust(start, end, (long)MAXLNUM, (long)(start - end - 1));
  1714.     while (end >= start)
  1715.     {
  1716. if (curbuf->b_ml.ml_flags & ML_EMPTY)     /* nothing to delete */
  1717.     break;
  1718. ml_delete(start, FALSE);
  1719. changed();
  1720. end--;
  1721.     }
  1722.     do_append(start - 1, getline, cookie);
  1723. }
  1724.     void
  1725. do_z(line, arg)
  1726.     linenr_t line;
  1727.     char_u *arg;
  1728. {
  1729.     char_u *x;
  1730.     int bigness = curwin->w_height - 3;
  1731.     char_u kind;
  1732.     int minus = 0;
  1733.     linenr_t start, end, curs, i;
  1734.     if (bigness < 1)
  1735. bigness = 1;
  1736.     x = arg;
  1737.     if (*x == '-' || *x == '+' || *x == '=' || *x == '^' || *x == '.')
  1738. x++;
  1739.     if (*x != 0)
  1740.     {
  1741. if (!isdigit(*x))
  1742. {
  1743.     EMSG("non-numeric argument to :z");
  1744.     return;
  1745. }
  1746. else
  1747.     bigness = atoi((char *)x);
  1748.     }
  1749.     kind = *arg;
  1750.     switch (kind)
  1751.     {
  1752. case '-':
  1753.     start = line - bigness;
  1754.     end = line;
  1755.     curs = line;
  1756.     break;
  1757. case '=':
  1758.     start = line - bigness / 2 + 1;
  1759.     end = line + bigness / 2 - 1;
  1760.     curs = line;
  1761.     minus = 1;
  1762.     break;
  1763. case '^':
  1764.     start = line - bigness * 2;
  1765.     end = line - bigness;
  1766.     curs = line - bigness;
  1767.     break;
  1768. case '.':
  1769.     start = line - bigness / 2;
  1770.     end = line + bigness / 2;
  1771.     curs = end;
  1772.     break;
  1773. default:  /* '+' */
  1774.     start = line;
  1775.     end = line + bigness;
  1776.     curs = end;
  1777.     break;
  1778.     }
  1779.     if (start < 1)
  1780. start = 1;
  1781.     if (end > curbuf->b_ml.ml_line_count)
  1782. end = curbuf->b_ml.ml_line_count;
  1783.     if (curs > curbuf->b_ml.ml_line_count)
  1784. curs = curbuf->b_ml.ml_line_count;
  1785.     for (i = start; i <= end; i++)
  1786.     {
  1787. int j;
  1788. if (minus && (i == line))
  1789. {
  1790.     msg_putchar('n');
  1791.     for (j = 1; j < Columns; j++)
  1792. msg_putchar('-');
  1793. }
  1794. print_line(i, FALSE);
  1795. if (minus && (i == line))
  1796. {
  1797.     msg_putchar('n');
  1798.     for (j = 1; j < Columns; j++)
  1799. msg_putchar('-');
  1800. }
  1801.     }
  1802.     curwin->w_cursor.lnum = curs;
  1803. }
  1804. /*
  1805.  * Check if the restricted flag is set.
  1806.  * If so, give an error message and return TRUE.
  1807.  * Otherwise, return FALSE.
  1808.  */
  1809.     int
  1810. check_restricted()
  1811. {
  1812.     if (restricted)
  1813.     {
  1814. EMSG("Shell commands not allowed in rvim");
  1815. return TRUE;
  1816.     }
  1817.     return FALSE;
  1818. }
  1819. /*
  1820.  * Check if the secure flag is set (.exrc or .vimrc in current directory).
  1821.  * If so, give an error message and return TRUE.
  1822.  * Otherwise, return FALSE.
  1823.  */
  1824.     int
  1825. check_secure()
  1826. {
  1827.     if (secure)
  1828.     {
  1829. secure = 2;
  1830. emsg(e_curdir);
  1831. return TRUE;
  1832.     }
  1833.     return FALSE;
  1834. }
  1835. static char_u     *old_sub = NULL; /* previous substitute pattern */
  1836. /*
  1837.  * When ":global" is used to number of substitutions and changed lines is
  1838.  * accumulated until it's finished.
  1839.  */
  1840. static long     sub_nsubs;     /* total number of substitutions */
  1841. static linenr_t     sub_nlines;     /* total number of lines changed */
  1842. /* do_sub()
  1843.  *
  1844.  * Perform a substitution from line eap->line1 to line eap->line2 using the
  1845.  * command pointed to by eap->arg which should be of the form:
  1846.  *
  1847.  * /pattern/substitution/{flags}
  1848.  *
  1849.  * The usual escapes are supported as described in the regexp docs.
  1850.  */
  1851.     void
  1852. do_sub(eap)
  1853.     EXARG *eap;
  1854. {
  1855.     linenr_t     lnum;
  1856.     long     i;
  1857.     char_u    *ptr;
  1858.     char_u    *old_line;
  1859.     vim_regexp    *prog;
  1860.     static int     do_all = FALSE; /* do multiple substitutions per line */
  1861.     static int     do_ask = FALSE; /* ask for confirmation */
  1862.     int     do_error = TRUE; /* if false, ignore errors */
  1863.     int     do_print = FALSE; /* print last line with subst. */
  1864.     int     do_ic = 0; /* ignore case flag */
  1865.     char_u    *pat = NULL, *sub = NULL; /* init for GCC */
  1866.     int     delimiter;
  1867.     int     sublen;
  1868.     int     got_quit = FALSE;
  1869.     int     got_match = FALSE;
  1870.     int     temp;
  1871.     int     which_pat;
  1872.     char_u     *cmd;
  1873.     int     save_reg_ic;
  1874.     int     save_State;
  1875.     cmd = eap->arg;
  1876.     if (!global_busy)
  1877.     {
  1878. sub_nsubs = 0;
  1879. sub_nlines = 0;
  1880.     }
  1881. #ifdef FKMAP     /* reverse the flow of the Farsi characters */
  1882.     if (p_altkeymap && curwin->w_p_rl)
  1883. lrF_sub(cmd);
  1884. #endif
  1885.     if (eap->cmdidx == CMD_tilde)
  1886. which_pat = RE_LAST; /* use last used regexp */
  1887.     else
  1888. which_pat = RE_SUBST; /* use last substitute regexp */
  1889. /* new pattern and substitution */
  1890.     if (eap->cmd[0] == 's' && *cmd != NUL && !vim_iswhite(*cmd)
  1891.     && vim_strchr((char_u *)"0123456789gcr|"", *cmd) == NULL)
  1892.     {
  1893. /* don't accept alphanumeric for separator */
  1894. if (isalpha(*cmd))
  1895. {
  1896.     EMSG("Regular expressions can't be delimited by letters");
  1897.     return;
  1898. }
  1899. /*
  1900.  * undocumented vi feature:
  1901.  *  "/sub/" and "?sub?" use last used search pattern (almost like
  1902.  *  //sub/r).  "&sub&" use last substitute pattern (like //sub/).
  1903.  */
  1904. if (*cmd == '\')
  1905. {
  1906.     ++cmd;
  1907.     if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
  1908.     {
  1909. emsg(e_backslash);
  1910. return;
  1911.     }
  1912.     if (*cmd != '&')
  1913. which_pat = RE_SEARCH;     /* use last '/' pattern */
  1914.     pat = (char_u *)"";     /* empty search pattern */
  1915.     delimiter = *cmd++;     /* remember delimiter character */
  1916. }
  1917. else /* find the end of the regexp */
  1918. {
  1919.     which_pat = RE_LAST;     /* use last used regexp */
  1920.     delimiter = *cmd++;     /* remember delimiter character */
  1921.     pat = cmd;     /* remember start of search pat */
  1922.     cmd = skip_regexp(cmd, delimiter, p_magic);
  1923.     if (cmd[0] == delimiter)     /* end delimiter found */
  1924. *cmd++ = NUL;     /* replace it with a NUL */
  1925. }
  1926. /*
  1927.  * Small incompatibility: vi sees 'n' as end of the command, but in
  1928.  * Vim we want to use 'n' to find/substitute a NUL.
  1929.  */
  1930. sub = cmd;     /* remember the start of the substitution */
  1931. while (cmd[0])
  1932. {
  1933.     if (cmd[0] == delimiter) /* end delimiter found */
  1934.     {
  1935. *cmd++ = NUL; /* replace it with a NUL */
  1936. break;
  1937.     }
  1938.     if (cmd[0] == '\' && cmd[1] != 0) /* skip escaped characters */
  1939. ++cmd;
  1940.     ++cmd;
  1941. }
  1942. if (!eap->skip)
  1943. {
  1944.     vim_free(old_sub);
  1945.     old_sub = vim_strsave(sub);
  1946. }
  1947.     }
  1948.     else if (!eap->skip) /* use previous pattern and substitution */
  1949.     {
  1950. if (old_sub == NULL) /* there is no previous command */
  1951. {
  1952.     emsg(e_nopresub);
  1953.     return;
  1954. }
  1955. pat = NULL; /* search_regcomp() will use previous pattern */
  1956. sub = old_sub;
  1957.     }
  1958.     /*
  1959.      * find trailing options
  1960.      */
  1961.     if (!p_ed)
  1962.     {
  1963. if (p_gd) /* default is global on */
  1964.     do_all = TRUE;
  1965. else
  1966.     do_all = FALSE;
  1967. do_ask = FALSE;
  1968.     }
  1969.     while (*cmd)
  1970.     {
  1971. /*
  1972.  * Note that 'g' and 'c' are always inverted, also when p_ed is off.
  1973.  * 'r' is never inverted.
  1974.  */
  1975. if (*cmd == 'g')
  1976.     do_all = !do_all;
  1977. else if (*cmd == 'c')
  1978.     do_ask = !do_ask;
  1979. else if (*cmd == 'e')
  1980.     do_error = !do_error;
  1981. else if (*cmd == 'r')     /* use last used regexp */
  1982.     which_pat = RE_LAST;
  1983. else if (*cmd == 'p')
  1984.     do_print = TRUE;
  1985. else if (*cmd == 'i')     /* ignore case */
  1986.     do_ic = 'i';
  1987. else if (*cmd == 'I')     /* don't ignore case */
  1988.     do_ic = 'I';
  1989. else
  1990.     break;
  1991. ++cmd;
  1992.     }
  1993.     /*
  1994.      * check for a trailing count
  1995.      */
  1996.     cmd = skipwhite(cmd);
  1997.     if (isdigit(*cmd))
  1998.     {
  1999. i = getdigits(&cmd);
  2000. if (i <= 0 && !eap->skip && do_error)
  2001. {
  2002.     emsg(e_zerocount);
  2003.     return;
  2004. }
  2005. eap->line1 = eap->line2;
  2006. eap->line2 += i - 1;
  2007.     }
  2008.     /*
  2009.      * check for trailing command or garbage
  2010.      */
  2011.     cmd = skipwhite(cmd);
  2012.     if (*cmd && *cmd != '"')     /* if not end-of-line or comment */
  2013.     {
  2014. eap->nextcmd = check_nextcmd(cmd);
  2015. if (eap->nextcmd == NULL)
  2016. {
  2017.     emsg(e_trailing);
  2018.     return;
  2019. }
  2020.     }
  2021.     if (eap->skip)     /* not executing commands, only parsing */
  2022. return;
  2023.     if ((prog = search_regcomp(pat, RE_SUBST, which_pat, SEARCH_HIS)) == NULL)
  2024.     {
  2025. if (do_error)
  2026.     emsg(e_invcmd);
  2027. return;
  2028.     }
  2029.     /* the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' */
  2030.     if (do_ic == 'i')
  2031. reg_ic = TRUE;
  2032.     else if (do_ic == 'I')
  2033. reg_ic = FALSE;
  2034.     /*
  2035.      * ~ in the substitute pattern is replaced with the old pattern.
  2036.      * We do it here once to avoid it to be replaced over and over again.
  2037.      */
  2038.     sub = regtilde(sub, p_magic);
  2039.     old_line = NULL;
  2040.     for (lnum = eap->line1; lnum <= eap->line2 && !(got_int || got_quit);
  2041.        ++lnum)
  2042.     {
  2043. ptr = ml_get(lnum);
  2044. if (vim_regexec(prog, ptr, TRUE))  /* a match on this line */
  2045. {
  2046.     char_u *new_end, *new_start = NULL;
  2047.     char_u *old_match, *old_copy;
  2048.     char_u *prev_old_match = NULL;
  2049.     char_u *p1;
  2050.     int did_sub = FALSE;
  2051.     int match, lastone;
  2052.     unsigned len, needed_len;
  2053.     unsigned new_start_len = 0;
  2054.     /* make a copy of the line, so it won't be taken away when updating
  2055. the screen */
  2056.     if ((old_line = vim_strsave(ptr)) == NULL)
  2057. continue;
  2058.     vim_regexec(prog, old_line, TRUE); /* match again on this line to
  2059.  * update the pointers. TODO:
  2060.  * remove extra vim_regexec() */
  2061.     if (!got_match)
  2062.     {
  2063. setpcmark();
  2064. got_match = TRUE;
  2065.     }
  2066.     old_copy = old_match = old_line;
  2067.     for (;;) /* loop until nothing more to replace */
  2068.     {
  2069. /*
  2070.  * Save the position of the last change for the final cursor
  2071.  * position (just like the real vi).
  2072.  */
  2073. curwin->w_cursor.lnum = lnum;
  2074. curwin->w_cursor.col = (int)(prog->startp[0] - old_line);
  2075. changed_cline_bef_curs();
  2076. /*
  2077.  * Match empty string does not count, except for first match.
  2078.  * This reproduces the strange vi behaviour.
  2079.  * This also catches endless loops.
  2080.  */
  2081. if (old_match == prev_old_match && old_match == prog->endp[0])
  2082. {
  2083.     ++old_match;
  2084.     goto skip;
  2085. }
  2086. old_match = prog->endp[0];
  2087. prev_old_match = old_match;
  2088. /* update_screen() may change reg_ic: save it */
  2089. save_reg_ic = reg_ic;
  2090. /* change State to CONFIRM, so that the mouse works properly */
  2091. save_State = State;
  2092. State = CONFIRM;
  2093. #ifdef USE_MOUSE
  2094. setmouse(); /* disable mouse in xterm */
  2095. #endif
  2096. /*
  2097.  * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
  2098.  */
  2099. while (do_ask)
  2100. {
  2101.     temp = RedrawingDisabled;
  2102.     RedrawingDisabled = FALSE;
  2103.     search_match_len = prog->endp[0] - prog->startp[0];
  2104.     /* invert the matched string
  2105.      * remove the inversion afterwards */
  2106.     if (search_match_len == 0)
  2107. search_match_len = 1;     /* show something! */
  2108.     highlight_match = TRUE;
  2109.     update_topline();
  2110.     validate_cursor();
  2111.     update_screen(NOT_VALID);
  2112.     highlight_match = FALSE;
  2113.     redraw_later(NOT_VALID);
  2114.     if (msg_row == Rows - 1)
  2115. msg_didout = FALSE;     /* avoid a scroll-up */
  2116.     /* write message same highlighting as for wait_return */
  2117.     smsg_attr(hl_attr(HLF_R),
  2118.     (char_u *)"replace with %s (y/n/a/q/^E/^Y)?",
  2119.     sub);
  2120.     showruler(TRUE);
  2121.     RedrawingDisabled = temp;
  2122. #ifdef USE_GUI_WIN32
  2123.     dont_scroll = FALSE; /* allow scrolling here */
  2124. #endif
  2125.     ++no_mapping; /* don't map this key */
  2126.     ++allow_keys; /* allow special keys */
  2127.     i = vgetc();
  2128.     --allow_keys;
  2129.     --no_mapping;
  2130. /* clear the question */
  2131.     msg_didout = FALSE; /* don't scroll up */
  2132.     msg_col = 0;
  2133.     gotocmdline(TRUE);
  2134.     if (i == 'q' || i == ESC || i == Ctrl('C')
  2135. #ifdef UNIX
  2136.     || i == intr_char
  2137. #endif
  2138.     )
  2139.     {
  2140. got_quit = TRUE;
  2141. break;
  2142.     }
  2143.     else if (i == 'n')
  2144. goto skip;
  2145.     else if (i == 'y')
  2146. break;
  2147.     else if (i == 'a')
  2148.     {
  2149. do_ask = FALSE;
  2150. break;
  2151.     }
  2152.     else if (i == Ctrl('E'))
  2153. scrollup_clamp();
  2154.     else if (i == Ctrl('Y'))
  2155. scrolldown_clamp();
  2156. }
  2157. if (got_quit)
  2158.     break;
  2159. reg_ic = save_reg_ic;
  2160. State = save_State;
  2161. #ifdef USE_MOUSE
  2162. setmouse();
  2163. #endif
  2164. /* get length of substitution part */
  2165. sublen = vim_regsub(prog, sub, old_line, FALSE, p_magic);
  2166. if (new_start == NULL)
  2167. {
  2168.     /*
  2169.      * Get some space for a temporary buffer to do the
  2170.      * substitution into (and some extra space to avoid
  2171.      * too many calls to alloc()/free()).
  2172.      */
  2173.     new_start_len = STRLEN(old_copy) + sublen + 25;
  2174.     if ((new_start = alloc_check(new_start_len)) == NULL)
  2175. goto outofmem;
  2176.     *new_start = NUL;
  2177.     new_end = new_start;
  2178. }
  2179. else
  2180. {
  2181.     /*
  2182.      * Extend the temporary buffer to do the substitution into.
  2183.      * Avoid an alloc()/free(), it takes a lot of time.
  2184.      */
  2185.     len = STRLEN(new_start);
  2186.     needed_len = len + STRLEN(old_copy) + sublen + 1;
  2187.     if (needed_len > new_start_len)
  2188.     {
  2189. needed_len += 20; /* get some extra */
  2190. if ((p1 = alloc_check(needed_len)) == NULL)
  2191.     goto outofmem;
  2192. STRCPY(p1, new_start);
  2193. vim_free(new_start);
  2194. new_start = p1;
  2195. new_start_len = needed_len;
  2196.     }
  2197.     new_end = new_start + len;
  2198. }
  2199. /*
  2200.  * copy the text up to the part that matched
  2201.  */
  2202. i = prog->startp[0] - old_copy;
  2203. mch_memmove(new_end, old_copy, (size_t)i);
  2204. new_end += i;
  2205. vim_regsub(prog, sub, new_end, TRUE, p_magic);
  2206. sub_nsubs++;
  2207. did_sub = TRUE;
  2208. /*
  2209.  * Now the trick is to replace CTRL-Ms with a real line break.
  2210.  * This would make it impossible to insert CTRL-Ms in the text.
  2211.  * That is the way vi works. In Vim the line break can be
  2212.  * avoided by preceding the CTRL-M with a CTRL-V. Now you can't
  2213.  * precede a line break with a CTRL-V, big deal.
  2214.  */
  2215. while ((p1 = vim_strchr(new_end, CR)) != NULL)
  2216. {
  2217.     if (p1 == new_end || p1[-1] != Ctrl('V'))
  2218.     {
  2219. if (u_inssub(lnum) == OK)   /* prepare for undo */
  2220. {
  2221.     *p1 = NUL;     /* truncate up to the CR */
  2222.     mark_adjust(lnum, (linenr_t)MAXLNUM, 1L, 0L);
  2223.     ml_append(lnum - 1, new_start,
  2224. (colnr_t)(p1 - new_start + 1), FALSE);
  2225.     ++lnum;
  2226.     ++eap->line2; /* number of lines increases */
  2227.     STRCPY(new_start, p1 + 1); /* copy the rest */
  2228.     new_end = new_start;
  2229. }
  2230.     }
  2231.     else     /* remove CTRL-V */
  2232.     {
  2233. STRCPY(p1 - 1, p1);
  2234. new_end = p1;
  2235.     }
  2236. }
  2237. /* remember next character to be copied */
  2238. old_copy = prog->endp[0];
  2239. /*
  2240.  * continue searching after the match
  2241.  * prevent endless loop with patterns that match empty strings,
  2242.  * e.g. :s/$/pat/g or :s/[a-z]* /(&)/g
  2243.  */
  2244. skip:
  2245. match = -1;
  2246. lastone = (*old_match == NUL || got_int || got_quit || !do_all);
  2247. if (lastone || do_ask ||
  2248.       (match = vim_regexec(prog, old_match, (int)FALSE)) == 0)
  2249. {
  2250.     if (new_start)
  2251.     {
  2252. /*
  2253.  * Copy the rest of the line, that didn't match.
  2254.  * Old_match has to be adjusted, we use the end of the
  2255.  * line as reference, because the substitute may have
  2256.  * changed the number of characters.
  2257.  */
  2258. STRCAT(new_start, old_copy);
  2259. i = old_line + STRLEN(old_line) - old_match;
  2260. if (u_savesub(lnum) == OK)
  2261.     ml_replace(lnum, new_start, TRUE);
  2262. /* When asking, undo is saved each time, must also set
  2263.  * changed flag each time. */
  2264. if (do_ask)
  2265.     changed();
  2266. #ifdef SYNTAX_HL
  2267. /* recompute syntax hl. for this line */
  2268. syn_changed(lnum);
  2269. #endif
  2270. vim_free(old_line);     /* free the temp buffer */
  2271. old_line = new_start;
  2272. new_start = NULL;
  2273. old_match = old_line + STRLEN(old_line) - i;
  2274. if (old_match < old_line) /* safety check */
  2275. {
  2276.     EMSG("do_sub internal error: old_match < old_line");
  2277.     old_match = old_line;
  2278. }
  2279. old_copy = old_line;
  2280.     }
  2281.     if (match == -1 && !lastone)
  2282. match = vim_regexec(prog, old_match, (int)FALSE);
  2283.     if (match <= 0)   /* quit loop if there is no more match */
  2284. break;
  2285. }
  2286. line_breakcheck();
  2287.     }
  2288.     if (did_sub)
  2289. ++sub_nlines;
  2290.     vim_free(old_line);     /* free the copy of the original line */
  2291.     old_line = NULL;
  2292. }
  2293. line_breakcheck();
  2294.     }
  2295.     curbuf->b_op_start.lnum = eap->line1;
  2296.     curbuf->b_op_end.lnum = eap->line2;
  2297.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  2298. outofmem:
  2299.     vim_free(old_line);     /* may have to free an allocated copy of the line */
  2300.     if (sub_nsubs)
  2301.     {
  2302. changed();
  2303. approximate_botline();
  2304. if (!global_busy)
  2305. {
  2306.     update_topline();
  2307.     beginline(BL_WHITE | BL_FIX);
  2308.     update_screen(NOT_VALID); /* need this to update LineSizes */
  2309.     if (!do_sub_msg() && do_ask)
  2310. MSG("");
  2311. }
  2312. if (do_print)
  2313.     print_line(curwin->w_cursor.lnum, FALSE);
  2314.     }
  2315.     else if (!global_busy)
  2316.     {
  2317. if (got_int) /* interrupted */
  2318.     emsg(e_interr);
  2319. else if (got_match) /* did find something but nothing substituted */
  2320.     MSG("");
  2321. else if (do_error) /* nothing found */
  2322.     emsg2(e_patnotf2, pat);
  2323.     }
  2324.     vim_free(prog);
  2325. }
  2326. /*
  2327.  * Give message for number of substitutions.
  2328.  * Can also be used after a ":global" command.
  2329.  * Return TRUE if a message was given.
  2330.  */
  2331.     static int
  2332. do_sub_msg()
  2333. {
  2334.     /*
  2335.      * Only report substitutions when:
  2336.      * - more than 'report' substitutions
  2337.      * - command was typed by user, or number of changed lines > 'report'
  2338.      * - giving messages is not disabled by 'lazyredraw'
  2339.      */
  2340.     if (sub_nsubs > p_report &&
  2341.     (KeyTyped || sub_nlines > 1 || p_report < 1) &&
  2342.     messaging())
  2343.     {
  2344. sprintf((char *)msg_buf, "%s%ld substitution%s on %ld line%s",
  2345. got_int ? "(Interrupted) " : "",
  2346. sub_nsubs, plural(sub_nsubs),
  2347. (long)sub_nlines, plural((long)sub_nlines));
  2348. if (msg(msg_buf))
  2349. {
  2350.     keep_msg = msg_buf;
  2351.     keep_msg_attr = 0;
  2352. }
  2353. return TRUE;
  2354.     }
  2355.     if (got_int)
  2356.     {
  2357. emsg(e_interr);
  2358. return TRUE;
  2359.     }
  2360.     return FALSE;
  2361. }
  2362. /*
  2363.  * do_glob(cmd)
  2364.  *
  2365.  * Execute a global command of the form:
  2366.  *
  2367.  * g/pattern/X : execute X on all lines where pattern matches
  2368.  * v/pattern/X : execute X on all lines where pattern does not match
  2369.  *
  2370.  * where 'X' is an EX command
  2371.  *
  2372.  * The command character (as well as the trailing slash) is optional, and
  2373.  * is assumed to be 'p' if missing.
  2374.  *
  2375.  * This is implemented in two passes: first we scan the file for the pattern and
  2376.  * set a mark for each line that (not) matches. secondly we execute the command
  2377.  * for each line that has a mark. This is required because after deleting
  2378.  * lines we do not know where to search for the next match.
  2379.  */
  2380.     void
  2381. do_glob(eap)
  2382.     EXARG *eap;
  2383. {
  2384.     linenr_t     lnum; /* line number according to old situation */
  2385.     linenr_t     old_lcount; /* b_ml.ml_line_count before the command */
  2386.     int     ndone;
  2387.     int     type; /* first char of cmd: 'v' or 'g' */
  2388.     char_u     *cmd; /* command argument */
  2389.     char_u     delim; /* delimiter, normally '/' */
  2390.     char_u    *pat;
  2391.     vim_regexp    *prog;
  2392.     int     match;
  2393.     int     which_pat;
  2394.     if (global_busy)
  2395.     {
  2396. EMSG("Cannot do :global recursive"); /* will increment global_busy */
  2397. return;
  2398.     }
  2399.     type = *eap->cmd;
  2400.     cmd = eap->arg;
  2401.     which_pat = RE_LAST;     /* default: use last used regexp */
  2402.     sub_nsubs = 0;
  2403.     sub_nlines = 0;
  2404.     /*
  2405.      * undocumented vi feature:
  2406.      * "/" and "?": use previous search pattern.
  2407.      *  "&": use previous substitute pattern.
  2408.      */
  2409.     if (*cmd == '\')
  2410.     {
  2411. ++cmd;
  2412. if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
  2413. {
  2414.     emsg(e_backslash);
  2415.     return;
  2416. }
  2417. if (*cmd == '&')
  2418.     which_pat = RE_SUBST; /* use previous substitute pattern */
  2419. else
  2420.     which_pat = RE_SEARCH; /* use previous search pattern */
  2421. ++cmd;
  2422. pat = (char_u *)"";
  2423.     }
  2424.     else if (*cmd == NUL)
  2425.     {
  2426. EMSG("Regular expression missing from global");
  2427. return;
  2428.     }
  2429.     else
  2430.     {
  2431. delim = *cmd; /* get the delimiter */
  2432. if (delim)
  2433.     ++cmd; /* skip delimiter if there is one */
  2434. pat = cmd; /* remember start of pattern */
  2435. cmd = skip_regexp(cmd, delim, p_magic);
  2436. if (cmd[0] == delim)     /* end delimiter found */
  2437.     *cmd++ = NUL;     /* replace it with a NUL */
  2438.     }
  2439. #ifdef FKMAP /* when in Farsi mode, reverse the character flow */
  2440.     if (p_altkeymap && curwin->w_p_rl)
  2441. lrFswap(pat,0);
  2442. #endif
  2443.     if ((prog = search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS)) == NULL)
  2444.     {
  2445. emsg(e_invcmd);
  2446. return;
  2447.     }
  2448. /*
  2449.  * pass 1: set marks for each (not) matching line
  2450.  */
  2451.     ndone = 0;
  2452.     for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
  2453.     {
  2454. /* a match on this line? */
  2455. match = vim_regexec(prog, ml_get(lnum), (int)TRUE);
  2456. if ((type == 'g' && match) || (type == 'v' && !match))
  2457. {
  2458.     ml_setmarked(lnum);
  2459.     ndone++;
  2460. }
  2461. line_breakcheck();
  2462.     }
  2463. /*
  2464.  * pass 2: execute the command for each line that has been marked
  2465.  */
  2466.     if (got_int)
  2467. MSG(e_interr);
  2468.     else if (ndone == 0)
  2469. smsg(e_patnotf2, pat);
  2470.     else
  2471.     {
  2472. /*
  2473.  * Set current position only once for a global command.
  2474.  * If global_busy is set, setpcmark() will not do anything.
  2475.  * If there is an error, global_busy will be incremented.
  2476.  */
  2477. setpcmark();
  2478. global_busy = 1;
  2479. old_lcount = curbuf->b_ml.ml_line_count;
  2480. while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1)
  2481. {
  2482.     curwin->w_cursor.lnum = lnum;
  2483.     curwin->w_cursor.col = 0;
  2484.     if (*cmd == NUL || *cmd == 'n')
  2485. do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
  2486.     else
  2487. do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
  2488.     ui_breakcheck();
  2489. }
  2490. global_busy = 0;
  2491. adjust_cursor(); /* cursor may be beyond the end of the line */
  2492. /*
  2493.  * Redraw everything.  Could use CLEAR, which is faster in some
  2494.  * situations, but when there are few changes this makes the display
  2495.  * flicker.
  2496.  */
  2497. redraw_later(NOT_VALID);
  2498. /* If subsitutes done, report number of substitues, otherwise report
  2499.  * number of extra or deleted lines. */
  2500. if (!do_sub_msg())
  2501.     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  2502.     }
  2503.     ml_clearmarked();    /* clear rest of the marks */
  2504.     vim_free(prog);
  2505. }
  2506. #ifdef VIMINFO
  2507.     int
  2508. read_viminfo_sub_string(line, fp, force)
  2509.     char_u  *line;
  2510.     FILE    *fp;
  2511.     int     force;
  2512. {
  2513.     if (old_sub != NULL && force)
  2514. vim_free(old_sub);
  2515.     if (force || old_sub == NULL)
  2516.     {
  2517. viminfo_readstring(line);
  2518. old_sub = vim_strsave(line + 1);
  2519.     }
  2520.     return vim_fgets(line, LSIZE, fp);
  2521. }
  2522.     void
  2523. write_viminfo_sub_string(fp)
  2524.     FILE    *fp;
  2525. {
  2526.     if (get_viminfo_parameter('/') != 0 && old_sub != NULL)
  2527.     {
  2528. fprintf(fp, "n# Last Substitute String:n$");
  2529. viminfo_writestring(fp, old_sub);
  2530.     }
  2531. }
  2532. #endif /* VIMINFO */
  2533. /*
  2534.  * ":help": open a read-only window on the help.txt file
  2535.  */
  2536.     void
  2537. do_help(eap)
  2538.     EXARG   *eap;
  2539. {
  2540.     char_u  *arg;
  2541.     FILE    *helpfd; /* file descriptor of help file */
  2542.     int     n;
  2543.     WIN     *wp;
  2544.     int     num_matches;
  2545.     char_u  **matches;
  2546.     int     need_free = FALSE;
  2547.     if (eap != NULL)
  2548.     {
  2549. /*
  2550.  * A ":help" command ends at the first LF, or at a '|' that is
  2551.  * followed by some text.  Set nextcmd to the following command.
  2552.  */
  2553. for (arg = eap->arg; *arg; ++arg)
  2554. {
  2555.     if (*arg == 'n' || *arg == 'r' || (*arg == '|' && arg[1] != NUL))
  2556.     {
  2557. *arg++ = NUL;
  2558. eap->nextcmd = arg;
  2559. break;
  2560.     }
  2561. }
  2562. arg = eap->arg;
  2563. if (eap->skip)     /* not executing commands */
  2564.     return;
  2565.     }
  2566.     else
  2567. arg = (char_u *)"";
  2568.     /*
  2569.      * If an argument is given, check if there is a match for it.
  2570.      */
  2571.     if (*arg != NUL)
  2572.     {
  2573. n = find_help_tags(arg, &num_matches, &matches);
  2574. if (num_matches == 0 || n == FAIL)
  2575. {
  2576.     EMSG2("Sorry, no help for %s", arg);
  2577.     return;
  2578. }
  2579. /* The first match is the best match. */
  2580. arg = vim_strsave(matches[0]);
  2581. need_free = TRUE;
  2582. FreeWild(num_matches, matches);
  2583.     }
  2584. #ifdef USE_GUI
  2585.     need_mouse_correct = TRUE;
  2586. #endif
  2587.     /*
  2588.      * If there is already a help window open, use that one.
  2589.      */
  2590.     if (!curwin->w_buffer->b_help)
  2591.     {
  2592. for (wp = firstwin; wp != NULL; wp = wp->w_next)
  2593.     if (wp->w_buffer != NULL && wp->w_buffer->b_help)
  2594. break;
  2595. if (wp != NULL && wp->w_buffer->b_nwindows > 0)
  2596.     win_enter(wp, TRUE);
  2597. else
  2598. {
  2599.     /*
  2600.      * There is no help buffer yet.
  2601.      * Try to open the file specified by the "helpfile" option.
  2602.      */
  2603.     if ((helpfd = fopen((char *)p_hf, READBIN)) == NULL)
  2604.     {
  2605. smsg((char_u *)"Sorry, help file "%s" not found", p_hf);
  2606. goto erret;
  2607.     }
  2608.     fclose(helpfd);
  2609.     if (win_split(0, FALSE, FALSE) == FAIL)
  2610. goto erret;
  2611.     if (curwin->w_height < p_hh)
  2612. win_setheight((int)p_hh);
  2613. #ifdef RIGHTLEFT
  2614.     curwin->w_p_rl = 0;     /* help window is left-to-right */
  2615. #endif
  2616.     curwin->w_p_nu = 0;     /* no line numbers */
  2617.     /* Save the values of the options we will change.  Do this before
  2618.      * do_ecmd(), because there could be modelines in the help file */
  2619.     vim_free(help_save_isk);
  2620.     help_save_isk = vim_strsave(curbuf->b_p_isk);
  2621.     help_save_ts = curbuf->b_p_ts;
  2622.     /*
  2623.      * open help file (do_ecmd() will set b_help flag, readfile() will
  2624.      * set b_p_ro flag)
  2625.      */
  2626.     (void)do_ecmd(0, p_hf, NULL, NULL, (linenr_t)0,
  2627.    ECMD_HIDE + ECMD_SET_HELP);
  2628.     /* accept all chars for keywords, except ' ', '*', '"', '|' */
  2629.     set_string_option_direct((char_u *)"isk", -1,
  2630.      (char_u *)"!-~,^*,^|,^"", TRUE);
  2631.     curbuf->b_p_ts = 8;
  2632.     curwin->w_p_list = FALSE;
  2633.     check_buf_options(curbuf);
  2634.     (void)init_chartab(); /* needed because 'isk' changed */
  2635. }
  2636.     }
  2637.     if (!p_im)
  2638. restart_edit = 0;     /* don't want insert mode in help file */
  2639.     if (arg == NULL || *arg == NUL)
  2640.     {
  2641. arg = (char_u *)"help.txt";     /* go to the index */
  2642. need_free = FALSE;
  2643.     }
  2644.     do_tag(arg, DT_HELP, 1, FALSE, TRUE);
  2645. erret:
  2646.     if (need_free)
  2647. vim_free(arg);
  2648. }
  2649. /*
  2650.  * Return a heuristic indicating how well the given string matches.  The
  2651.  * smaller the number, the better the match.  This is the order of priorities,
  2652.  * from best match to worst match:
  2653.  * - Match with least alpha-numeric characters is better.
  2654.  * - Match with least total characters is better.
  2655.  * - Match towards the start is better.
  2656.  * - Match starting with "+" is worse (feature instead of command)
  2657.  * Assumption is made that the matched_string passed has already been found to
  2658.  * match some string for which help is requested.  webb.
  2659.  */
  2660.     int
  2661. help_heuristic(matched_string, offset, wrong_case)
  2662.     char_u  *matched_string;
  2663.     int     offset; /* offset for match */
  2664.     int     wrong_case; /* no matching case */
  2665. {
  2666.     int     num_letters;
  2667.     char_u  *p;
  2668.     num_letters = 0;
  2669.     for (p = matched_string; *p; p++)
  2670. if (isalnum(*p))
  2671.     num_letters++;
  2672.     /*
  2673.      * Multiply the number of letters by 100 to give it a much bigger
  2674.      * weighting than the number of characters.
  2675.      * If there only is a match while ignoring case, add 5000.
  2676.      * If the match starts in the middle of a word, add 10000 to put it
  2677.      * somewhere in the last half.
  2678.      * If the match is more than 2 chars from the start, multiply by 200 to
  2679.      * put it after matches at the start.
  2680.      */
  2681.     if (isalnum(matched_string[offset]) && offset > 0 &&
  2682.   isalnum(matched_string[offset - 1]))
  2683. offset += 10000;
  2684.     else if (offset > 2)
  2685. offset *= 200;
  2686.     if (wrong_case)
  2687. offset += 5000;
  2688.     if (matched_string[0] == '+')
  2689. offset += 100;
  2690.     return (int)(100 * num_letters + STRLEN(matched_string) + offset);
  2691. }
  2692. /*
  2693.  * Compare functions for qsort() below, that checks the help heuristics number
  2694.  * that has been put after the tagname by find_tags().
  2695.  */
  2696.     static int
  2697. #ifdef __BORLANDC__
  2698. _RTLENTRYF
  2699. #endif
  2700. help_compare(s1, s2)
  2701.     const void *s1;
  2702.     const void *s2;
  2703. {
  2704.     char    *p1;
  2705.     char    *p2;
  2706.     p1 = *(char **)s1 + strlen(*(char **)s1) + 1;
  2707.     p2 = *(char **)s2 + strlen(*(char **)s2) + 1;
  2708.     return strcmp(p1, p2);
  2709. }
  2710. /*
  2711.  * Find all help tags matching "arg", sort them and return in matches[], with
  2712.  * the number of matches in num_matches.
  2713.  * The matches will be sorted with a "best" match algorithm.
  2714.  */
  2715.     int
  2716. find_help_tags(arg, num_matches, matches)
  2717.     char_u *arg;
  2718.     int *num_matches;
  2719.     char_u ***matches;
  2720. {
  2721.     char_u *s, *d;
  2722.     int i;
  2723.     static char *(mtable[]) = {"*", "g*", "[*", "]*", ":*",
  2724.        "/*", "/\*", "/\(\)",
  2725.        "?", ":?", "?<CR>", ""*",
  2726.        "[count]", "[quotex]", "[range]",
  2727.        "[pattern]"};
  2728.     static char *(rtable[]) = {"star", "gstar", "[star", "]star", ":star",
  2729.        "/star", "/\\star", "/\\(\\)",
  2730.        "?", ":?", "?<CR>", "quotestar",
  2731.        "\[count]", "\[quotex]", "\[range]",
  2732.        "\[pattern]"};
  2733.     d = IObuff;     /* assume IObuff is long enough! */
  2734.     /*
  2735.      * Recognize a few exceptions to the rule. Some strings that contain '*'
  2736.      * with "star".  Otherwise '*' is recognized as a wildcard.
  2737.      */
  2738.     for (i = sizeof(mtable) / sizeof(char *); --i >= 0; )
  2739.     {
  2740. if (STRCMP(arg, mtable[i]) == 0)
  2741. {
  2742.     STRCPY(d, rtable[i]);
  2743.     break;
  2744. }
  2745.     }
  2746.     if (i < 0)     /* no match in table, replace single characters */
  2747.     {
  2748. for (s = arg; *s; ++s)
  2749. {
  2750.     /*
  2751.      * Replace "|" with "bar" and '"' with "quote" to match the name of
  2752.      * the tags for these commands.
  2753.      * Replace "*" with ".*" and "?" with "." to match command line
  2754.      * completion.
  2755.      * Insert a backslash before '~', '$' and '.' to avoid their
  2756.      * special meaning.
  2757.      */
  2758.     if (d - IObuff > IOSIZE - 10) /* getting too long!? */
  2759. break;
  2760.     switch (*s)
  2761.     {
  2762. case '|':   STRCPY(d, "bar");
  2763.     d += 3;
  2764.     continue;
  2765. case '"':  STRCPY(d, "quote");
  2766.     d += 5;
  2767.     continue;
  2768. case '*':   *d++ = '.';
  2769.     break;
  2770. case '?':   *d++ = '.';
  2771.     continue;
  2772. case '$':
  2773. case '.':
  2774. case '~':   *d++ = '\';
  2775.     break;
  2776.     }
  2777.     /*
  2778.      * Replace "^x" by "CTRL-X". Don't do this for "^_" to make
  2779.      * ":help i_^_CTRL-D" work.
  2780.      */
  2781.     if (*s < ' ' || (*s == '^' && s[1] && s[1] != '_')) /* ^x */
  2782.     {
  2783. if (d > IObuff && d[-1] != '_')
  2784.     *d++ = '_'; /* prepend a '_' */
  2785. STRCPY(d, "CTRL-");
  2786. d += 5;
  2787. if (*s < ' ')
  2788.     *d++ = *s + '@';
  2789. else
  2790.     *d++ = *++s;
  2791. if (s[1] != NUL && s[1] != '_')
  2792.     *d++ = '_'; /* append a '_' */
  2793. continue;
  2794.     }
  2795.     else if (*s == '^') /* "^" or "CTRL-^" or "^_" */
  2796. *d++ = '\';
  2797.     /*
  2798.      * Insert a backslash before a backslash after a slash, for search
  2799.      * pattern tags: "/|" --> "/\|".
  2800.      */
  2801.     else if (s[0] == '\' && s[1] != '\' &&
  2802.   *arg == '/' && s == arg + 1)
  2803. *d++ = '\';
  2804.     *d++ = *s;
  2805.     /*
  2806.      * If tag starts with ', toss everything after a second '. Fixes
  2807.      * CTRL-] on 'option'. (would include the trailing '.').
  2808.      */
  2809.     if (*s == ''' && s > arg && *arg == ''')
  2810. break;
  2811. }
  2812. *d = NUL;
  2813.     }
  2814.     *matches = (char_u **)"";
  2815.     *num_matches = 0;
  2816.     if (find_tags(IObuff, num_matches, matches,
  2817. TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE, MAXCOL) == OK)
  2818. #ifdef HAVE_QSORT
  2819. /*
  2820.  * Sort the matches found on the heuristic number that is after the
  2821.  * tag name.  If there is no qsort, the output will be messy!
  2822.  */
  2823. qsort((void *)*matches, (size_t)*num_matches,
  2824.       sizeof(char_u *), help_compare)
  2825. #endif
  2826. ;
  2827.     return OK;
  2828. }