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

编辑器/阅读器

开发平台:

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.  * ops.c: implementation of various operators: op_shift, op_delete, op_tilde,
  10.  *   op_change, op_yank, do_put, do_join
  11.  */
  12. #include "vim.h"
  13. /*
  14.  * Number of registers.
  15.  * 0 = unnamed register, for normal yanks and puts
  16.  *   1..9 = number registers, for deletes
  17.  * 10..35 = named registers
  18.  *     36 = delete register (-)
  19.  *     37 = Clipboard register (*). Only if USE_CLIPBOARD defined
  20.  */
  21. #ifdef USE_CLIPBOARD
  22. # define NUM_REGISTERS 38
  23. #else
  24. # define NUM_REGISTERS 37
  25. #endif
  26. /*
  27.  * Symbolic names for some registers.
  28.  */
  29. #define DELETION_REGISTER 36
  30. #ifdef USE_CLIPBOARD
  31. # define CLIPBOARD_REGISTER 37
  32. #endif
  33. /*
  34.  * Each yank register is an array of pointers to lines.
  35.  */
  36. static struct yankreg
  37. {
  38.     char_u **y_array; /* pointer to array of line pointers */
  39.     linenr_t y_size; /* number of lines in y_array */
  40.     char_u y_type; /* MLINE, MCHAR or MBLOCK */
  41. } y_regs[NUM_REGISTERS];
  42. static struct yankreg *y_current;     /* ptr to current yankreg */
  43. static int y_append;     /* TRUE when appending */
  44. static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */
  45. /*
  46.  * structure used by block_prep, op_delete and op_yank for blockwise operators
  47.  */
  48. struct block_def
  49. {
  50.     int startspaces;
  51.     int endspaces;
  52.     int textlen;
  53.     char_u *textstart;
  54.     colnr_t textcol;
  55. };
  56. #ifdef WANT_EVAL
  57. static char_u *get_expr_line __ARGS((void));
  58. #endif
  59. static void get_yank_register __ARGS((int regname, int writing));
  60. static int stuff_yank __ARGS((int, char_u *));
  61. static int put_in_typebuf __ARGS((char_u *s, int colon));
  62. static void stuffescaped __ARGS((char_u *arg));
  63. static int get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg));
  64. static void free_yank __ARGS((long));
  65. static void free_yank_all __ARGS((void));
  66. static void block_prep __ARGS((OPARG *oap, struct block_def *, linenr_t, int));
  67. #if defined(USE_CLIPBOARD) || defined(WANT_EVAL)
  68. static void str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len));
  69. #endif
  70. static int same_leader __ARGS((int, char_u *, int, char_u *));
  71. static int fmt_check_par __ARGS((linenr_t, int *, char_u **));
  72. /*
  73.  * op_shift - handle a shift operation
  74.  */
  75.     void
  76. op_shift(oap, curs_top, amount)
  77.     OPARG     *oap;
  78.     int     curs_top;
  79.     int     amount;
  80. {
  81.     long     i;
  82.     int     first_char;
  83.     if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
  84.  (linenr_t)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
  85. return;
  86. #ifdef SYNTAX_HL
  87.     /* recompute syntax hl., starting with current line */
  88.     syn_changed(curwin->w_cursor.lnum);
  89. #endif
  90.     for (i = oap->line_count; --i >= 0; )
  91.     {
  92. first_char = *ml_get_curline();
  93. if (first_char == NUL) /* empty line */
  94.     curwin->w_cursor.col = 0;
  95. /*
  96.  * Don't move the line right if it starts with # and p_si is set.
  97.  */
  98. else
  99. #if defined(SMARTINDENT) || defined(CINDENT)
  100.     if (first_char != '#' || (
  101. # ifdef SMARTINDENT
  102.  !curbuf->b_p_si
  103. # endif
  104. # if defined(SMARTINDENT) && defined(CINDENT)
  105.     &&
  106. # endif
  107. # ifdef CINDENT
  108.  (!curbuf->b_p_cin || !in_cinkeys('#', ' ', TRUE))
  109. # endif
  110. ))
  111. #endif
  112. {
  113.     /* if (oap->block_mode)
  114.     shift the block, not the whole line
  115.     else */
  116. shift_line(oap->op_type == OP_LSHIFT, p_sr, amount);
  117. }
  118. ++curwin->w_cursor.lnum;
  119.     }
  120.     if (curs_top)     /* put cursor on first line, for ">>" */
  121.     {
  122. curwin->w_cursor.lnum -= oap->line_count;
  123. beginline(BL_SOL | BL_FIX);   /* shift_line() may have set cursor.col */
  124.     }
  125.     else
  126. --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */
  127.     update_topline();
  128.     update_screen(NOT_VALID);
  129.     if (oap->line_count > p_report)
  130.        smsg((char_u *)"%ld line%s %ced %d time%s", oap->line_count,
  131.       plural(oap->line_count), (oap->op_type == OP_RSHIFT) ? '>' : '<',
  132.  amount, plural((long)amount));
  133.     /*
  134.      * Set "'[" and "']" marks.
  135.      */
  136.     curbuf->b_op_start = oap->start;
  137.     curbuf->b_op_end = oap->end;
  138. }
  139. /*
  140.  * shift the current line one shiftwidth left (if left != 0) or right
  141.  * leaves cursor on first blank in the line
  142.  */
  143.     void
  144. shift_line(left, round, amount)
  145.     int left;
  146.     int round;
  147.     int amount;
  148. {
  149.     int     count;
  150.     int     i, j;
  151.     int     p_sw = (int)curbuf->b_p_sw;
  152.     count = get_indent();     /* get current indent */
  153.     if (round)     /* round off indent */
  154.     {
  155. i = count / p_sw;     /* number of p_sw rounded down */
  156. j = count % p_sw;     /* extra spaces */
  157. if (j && left)     /* first remove extra spaces */
  158.     --amount;
  159. if (left)
  160. {
  161.     i -= amount;
  162.     if (i < 0)
  163. i = 0;
  164. }
  165. else
  166.     i += amount;
  167. count = i * p_sw;
  168.     }
  169.     else /* original vi indent */
  170.     {
  171. if (left)
  172. {
  173.     count -= p_sw * amount;
  174.     if (count < 0)
  175. count = 0;
  176. }
  177. else
  178.     count += p_sw * amount;
  179.     }
  180.     set_indent(count, TRUE);     /* set new indent */
  181. }
  182. #if defined(LISPINDENT) || defined(CINDENT)
  183. /*
  184.  * op_reindent - handle reindenting a block of lines for C or lisp.
  185.  *
  186.  * mechanism copied from op_shift, above
  187.  */
  188.     void
  189. op_reindent(oap, how)
  190.     OPARG *oap;
  191.     int (*how) __ARGS((void));
  192. {
  193.     long i;
  194.     char_u *l;
  195.     int count;
  196.     if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
  197.  (linenr_t)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
  198. return;
  199. #ifdef SYNTAX_HL
  200.     /* recompute syntax hl., starting with current line */
  201.     syn_changed(curwin->w_cursor.lnum);
  202. #endif
  203.     for (i = oap->line_count; --i >= 0 && !got_int; )
  204.     {
  205. /* it's a slow thing to do, so give feedback so there's no worry that
  206.  * the computer's just hung. */
  207. if (    (i % 50 == 0
  208.     || i == oap->line_count - 1)
  209. && oap->line_count > p_report)
  210.     smsg((char_u *)"%ld line%s to indent... ", i, plural(i));
  211. /*
  212.  * Be vi-compatible: For lisp indenting the first line is not
  213.  * indented, unless there is only one line.
  214.  */
  215. #ifdef LISPINDENT
  216. if (i != oap->line_count - 1 || oap->line_count == 1 ||
  217.        how != get_lisp_indent)
  218. #endif
  219. {
  220.     l = skipwhite(ml_get_curline());
  221.     if (*l == NUL)     /* empty or blank line */
  222. count = 0;
  223.     else
  224. count = how();     /* get the indent for this line */
  225.     set_indent(count, TRUE);
  226. }
  227. ++curwin->w_cursor.lnum;
  228.     }
  229.     /* put cursor on first non-blank of indented line */
  230.     curwin->w_cursor.lnum -= oap->line_count;
  231.     beginline(BL_SOL | BL_FIX);
  232.     update_topline();
  233.     update_screen(NOT_VALID);
  234.     if (oap->line_count > p_report)
  235.     {
  236. i = oap->line_count - (i + 1);
  237. smsg((char_u *)"%ld line%s indented ", i, plural(i));
  238.     }
  239.     /* set '[ and '] marks */
  240.     curbuf->b_op_start = oap->start;
  241.     curbuf->b_op_end = oap->end;
  242. }
  243. #endif /* defined(LISPINDENT) || defined(CINDENT) */
  244. #ifdef WANT_EVAL
  245. /*
  246.  * Keep the last expression line here, for repeating.
  247.  */
  248. static char_u *expr_line = NULL;
  249. /*
  250.  * Get an expression for the ""=expr1" or "CTRL-R =expr1"
  251.  * Returns '=' when OK, NUL otherwise.
  252.  */
  253.     int
  254. get_expr_register()
  255. {
  256.     char_u *new_line;
  257.     new_line = getcmdline('=', 0L, 0);
  258.     if (new_line == NULL)
  259. return NUL;
  260.     if (*new_line == NUL) /* use previous line */
  261. vim_free(new_line);
  262.     else
  263. set_expr_line(new_line);
  264.     return '=';
  265. }
  266. /*
  267.  * Set the expression for the '=' register.
  268.  * Argument must be an allocated string.
  269.  */
  270.     void
  271. set_expr_line(new_line)
  272.     char_u *new_line;
  273. {
  274.     vim_free(expr_line);
  275.     expr_line = new_line;
  276. }
  277. /*
  278.  * Get the result of the '=' register expression.
  279.  * Returns a pointer to allocated memory, or NULL for failure.
  280.  */
  281.     static char_u *
  282. get_expr_line()
  283. {
  284.     if (expr_line == NULL)
  285. return NULL;
  286.     return eval_to_string(expr_line, NULL);
  287. }
  288. #endif /* WANT_EVAL */
  289. /*
  290.  * Check if 'regname' is a valid name of a yank register.
  291.  * Note: There is no check for 0 (default register), caller should do this
  292.  */
  293.     int
  294. valid_yank_reg(regname, writing)
  295.     int     regname;
  296.     int     writing;     /* if TRUE check for writable registers */
  297. {
  298.     if (regname > '~')
  299. return FALSE;
  300.     if (       isalnum(regname)
  301.     || (!writing && vim_strchr((char_u *)
  302. #ifdef WANT_EVAL
  303.     ".%#:="
  304. #else
  305.     ".%#:"
  306. #endif
  307. , regname) != NULL)
  308.     || regname == '"'
  309.     || regname == '-'
  310.     || regname == '_'
  311. #ifdef USE_CLIPBOARD
  312.     || (clipboard.available && regname == '*')
  313. #endif
  314. )
  315. return TRUE;
  316.     return FALSE;
  317. }
  318. /*
  319.  * Set y_current and y_append, according to the value of "regname".
  320.  * Cannot handle the '_' register.
  321.  *
  322.  * If regname is 0 and writing, use register 0
  323.  * If regname is 0 and reading, use previous register
  324.  */
  325.     static void
  326. get_yank_register(regname, writing)
  327.     int     regname;
  328.     int     writing;
  329. {
  330.     int     i;
  331.     y_append = FALSE;
  332.     if (((regname == 0 && !writing) || regname == '"') && y_previous != NULL)
  333.     {
  334. y_current = y_previous;
  335. return;
  336.     }
  337.     i = regname;
  338.     if (isdigit(i))
  339. i -= '0';
  340.     else if (islower(i))
  341. i -= 'a' - 10;
  342.     else if (isupper(i))
  343.     {
  344. i -= 'A' - 10;
  345. y_append = TRUE;
  346.     }
  347.     else if (regname == '-')
  348. i = DELETION_REGISTER;
  349. #ifdef USE_CLIPBOARD
  350.     else if (clipboard.available && regname == '*')
  351. i = CLIPBOARD_REGISTER;
  352. #endif
  353.     else /* not 0-9, a-z, A-Z or '-': use register 0 */
  354. i = 0;
  355.     y_current = &(y_regs[i]);
  356.     if (writing) /* remember the register we write into for do_put() */
  357. y_previous = y_current;
  358. }
  359. /*
  360.  * return TRUE if the current yank register has type MLINE
  361.  */
  362.     int
  363. yank_register_mline(regname)
  364.     int     regname;
  365. {
  366.     if (regname != 0 && !valid_yank_reg(regname, FALSE))
  367. return FALSE;
  368.     if (regname == '_') /* black hole is always empty */
  369. return FALSE;
  370.     get_yank_register(regname, FALSE);
  371.     return (y_current->y_type == MLINE);
  372. }
  373. /*
  374.  * start or stop recording into a yank register
  375.  *
  376.  * return FAIL for failure, OK otherwise
  377.  */
  378.     int
  379. do_record(c)
  380.     int c;
  381. {
  382.     char_u *p;
  383.     static int regname;
  384.     struct yankreg *old_y_previous, *old_y_current;
  385.     int retval;
  386.     if (Recording == FALSE)     /* start recording */
  387.     {
  388. /* registers 0-9, a-z and " are allowed */
  389. if (c > '~' || (!isalnum(c) && c != '"'))
  390.     retval = FAIL;
  391. else
  392. {
  393.     Recording = TRUE;
  394.     showmode();
  395.     regname = c;
  396.     retval = OK;
  397. }
  398.     }
  399.     else     /* stop recording */
  400.     {
  401. Recording = FALSE;
  402. MSG("");
  403. p = get_recorded();
  404. if (p == NULL)
  405.     retval = FAIL;
  406. else
  407. {
  408.     /*
  409.      * We don't want to change the default register here, so save and
  410.      * restore the current register name.
  411.      */
  412.     old_y_previous = y_previous;
  413.     old_y_current = y_current;
  414.     retval = stuff_yank(regname, p);
  415.     y_previous = old_y_previous;
  416.     y_current = old_y_current;
  417. }
  418.     }
  419.     return retval;
  420. }
  421. /*
  422.  * Stuff string 'p' into yank register 'regname' as a single line (append if
  423.  * uppercase). 'p' must have been alloced.
  424.  *
  425.  * return FAIL for failure, OK otherwise
  426.  */
  427.     static int
  428. stuff_yank(regname, p)
  429.     int regname;
  430.     char_u *p;
  431. {
  432.     char_u *lp;
  433.     char_u **pp;
  434.     /* check for read-only register */
  435.     if (regname != 0 && !valid_yank_reg(regname, TRUE))
  436.     {
  437. vim_free(p);
  438. return FAIL;
  439.     }
  440.     if (regname == '_')     /* black hole: don't do anything */
  441.     {
  442. vim_free(p);
  443. return OK;
  444.     }
  445.     get_yank_register(regname, TRUE);
  446.     if (y_append && y_current->y_array != NULL)
  447.     {
  448. pp = &(y_current->y_array[y_current->y_size - 1]);
  449. lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
  450. if (lp == NULL)
  451. {
  452.     vim_free(p);
  453.     return FAIL;
  454. }
  455. STRCPY(lp, *pp);
  456. STRCAT(lp, p);
  457. vim_free(p);
  458. vim_free(*pp);
  459. *pp = lp;
  460.     }
  461.     else
  462.     {
  463. free_yank_all();
  464. if ((y_current->y_array =
  465. (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
  466. {
  467.     vim_free(p);
  468.     return FAIL;
  469. }
  470. y_current->y_array[0] = p;
  471. y_current->y_size = 1;
  472. y_current->y_type = MCHAR;  /* used to be MLINE, why? */
  473.     }
  474.     return OK;
  475. }
  476. /*
  477.  * execute a yank register: copy it into the stuff buffer
  478.  *
  479.  * return FAIL for failure, OK otherwise
  480.  */
  481.     int
  482. do_execreg(regname, colon, addcr)
  483.     int     regname;
  484.     int     colon; /* insert ':' before each line */
  485.     int     addcr; /* always add 'n' to end of line */
  486. {
  487.     static int lastc = NUL;
  488.     long i;
  489.     char_u *p;
  490.     int retval = OK;
  491.     if (regname == '@') /* repeat previous one */
  492. regname = lastc;
  493. /* check for valid regname */
  494.     if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
  495. return FAIL;
  496.     lastc = regname;
  497.     if (regname == '_') /* black hole: don't stuff anything */
  498. return OK;
  499.     if (regname == ':') /* use last command line */
  500.     {
  501. if (last_cmdline == NULL)
  502. {
  503.     EMSG(e_nolastcmd);
  504.     return FAIL;
  505. }
  506. vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */
  507. new_last_cmdline = NULL;
  508. retval = put_in_typebuf(last_cmdline, TRUE);
  509.     }
  510. #ifdef WANT_EVAL
  511.     else if (regname == '=')
  512.     {
  513. p = get_expr_line();
  514. if (p == NULL)
  515.     return FAIL;
  516. retval = put_in_typebuf(p, colon);
  517. vim_free(p);
  518.     }
  519. #endif
  520.     else if (regname == '.') /* use last inserted text */
  521.     {
  522. p = get_last_insert_save();
  523. if (p == NULL)
  524. {
  525.     EMSG(e_noinstext);
  526.     return FAIL;
  527. }
  528. retval = put_in_typebuf(p, colon);
  529. vim_free(p);
  530.     }
  531.     else
  532.     {
  533. get_yank_register(regname, FALSE);
  534. if (y_current->y_array == NULL)
  535.     return FAIL;
  536. /*
  537.  * Insert lines into typeahead buffer, from last one to first one.
  538.  */
  539. for (i = y_current->y_size; --i >= 0; )
  540. {
  541. /* insert newline between lines and after last line if type is MLINE */
  542.     if (y_current->y_type == MLINE || i < y_current->y_size - 1
  543.      || addcr)
  544.     {
  545. if (ins_typebuf((char_u *)"n", FALSE, 0, TRUE) == FAIL)
  546.     return FAIL;
  547.     }
  548.     if (ins_typebuf(y_current->y_array[i], FALSE, 0, TRUE) == FAIL)
  549. return FAIL;
  550.     if (colon && ins_typebuf((char_u *)":", FALSE, 0, TRUE) == FAIL)
  551. return FAIL;
  552. }
  553. Exec_reg = TRUE; /* disable the 'q' command */
  554.     }
  555.     return retval;
  556. }
  557.     static int
  558. put_in_typebuf(s, colon)
  559.     char_u *s;
  560.     int colon;     /* add ':' before the line */
  561. {
  562.     int retval = OK;
  563.     if (colon)
  564. retval = ins_typebuf((char_u *)"n", FALSE, 0, TRUE);
  565.     if (retval == OK)
  566. retval = ins_typebuf(s, FALSE, 0, TRUE);
  567.     if (colon && retval == OK)
  568. retval = ins_typebuf((char_u *)":", FALSE, 0, TRUE);
  569.     return retval;
  570. }
  571. /*
  572.  * Insert a yank register: copy it into the Read buffer.
  573.  * Used by CTRL-R command and middle mouse button in insert mode.
  574.  *
  575.  * return FAIL for failure, OK otherwise
  576.  */
  577.     int
  578. insert_reg(regname, literally)
  579.     int regname;
  580.     int literally; /* insert literally, not as if typed */
  581. {
  582.     long    i;
  583.     int     retval = OK;
  584.     char_u  *arg;
  585.     int     allocated;
  586.     /*
  587.      * It is possible to get into an endless loop by having CTRL-R a in
  588.      * register a and then, in insert mode, doing CTRL-R a.
  589.      * If you hit CTRL-C, the loop will be broken here.
  590.      */
  591.     ui_breakcheck();
  592.     if (got_int)
  593. return FAIL;
  594.     /* check for valid regname */
  595.     if (regname != NUL && !valid_yank_reg(regname, FALSE))
  596. return FAIL;
  597. #ifdef USE_CLIPBOARD
  598.     if (regname == '*')
  599. clip_get_selection(); /* may fill * register */
  600. #endif
  601.     if (regname == '.') /* insert last inserted text */
  602. retval = stuff_inserted(NUL, 1L, TRUE);
  603.     else if (get_spec_reg(regname, &arg, &allocated, TRUE))
  604.     {
  605. if (arg == NULL)
  606.     return FAIL;
  607. if (literally)
  608.     stuffescaped(arg);
  609. else
  610.     stuffReadbuff(arg);
  611. if (allocated)
  612.     vim_free(arg);
  613.     }
  614.     else /* name or number register */
  615.     {
  616. get_yank_register(regname, FALSE);
  617. if (y_current->y_array == NULL)
  618.     retval = FAIL;
  619. else
  620. {
  621.     for (i = 0; i < y_current->y_size; ++i)
  622.     {
  623. if (literally)
  624.     stuffescaped(y_current->y_array[i]);
  625. else
  626.     stuffReadbuff(y_current->y_array[i]);
  627. /*
  628.  * Insert a newline between lines and after last line if
  629.  * y_type is MLINE.
  630.  */
  631. if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  632.     stuffcharReadbuff('n');
  633.     }
  634. }
  635.     }
  636.     return retval;
  637. }
  638. /*
  639.  * Stuff a string into the typeahead buffer, such that edit() will insert it
  640.  * literally.
  641.  */
  642.     static void
  643. stuffescaped(arg)
  644.     char_u *arg;
  645. {
  646.     while (*arg)
  647.     {
  648. if ((*arg < ' ' && *arg != TAB) || *arg > '~')
  649.     stuffcharReadbuff(Ctrl('V'));
  650. stuffcharReadbuff(*arg++);
  651.     }
  652. }
  653. /*
  654.  * If "regname" is a special register, return a pointer to its value.
  655.  */
  656.     static int
  657. get_spec_reg(regname, argp, allocated, errmsg)
  658.     int regname;
  659.     char_u **argp;
  660.     int *allocated;
  661.     int errmsg; /* give error message when failing */
  662. {
  663.     *argp = NULL;
  664.     *allocated = FALSE;
  665.     switch (regname)
  666.     {
  667. case '%': /* file name */
  668.     if (errmsg)
  669. check_fname(); /* will give emsg if not set */
  670.     *argp = curbuf->b_fname;
  671.     return TRUE;
  672. case '#': /* alternate file name */
  673.     *argp = getaltfname(errmsg); /* may give emsg if not set */
  674.     return TRUE;
  675. #ifdef WANT_EVAL
  676. case '=': /* result of expression */
  677.     *argp = get_expr_line();
  678.     *allocated = TRUE;
  679.     return TRUE;
  680. #endif
  681. case ':': /* last command line */
  682.     if (last_cmdline == NULL && errmsg)
  683. EMSG(e_nolastcmd);
  684.     *argp = last_cmdline;
  685.     return TRUE;
  686. case '.': /* last inserted text */
  687.     *argp = get_last_insert_save();
  688.     *allocated = TRUE;
  689.     if (*argp == NULL && errmsg)
  690. EMSG(e_noinstext);
  691.     return TRUE;
  692. case '_': /* black hole: always empty */
  693.     *argp = (char_u *)"";
  694.     return TRUE;
  695.     }
  696.     return FALSE;
  697. }
  698. /*
  699.  * paste a yank register into the command line.
  700.  * used by CTRL-R command in command-line mode
  701.  * insert_reg() can't be used here, because special characters from the
  702.  * register contents will be interpreted as commands.
  703.  *
  704.  * return FAIL for failure, OK otherwise
  705.  */
  706.     int
  707. cmdline_paste(regname)
  708.     int regname;
  709. {
  710.     long i;
  711.     char_u *arg;
  712.     int allocated;
  713.     if (!valid_yank_reg(regname, FALSE)) /* check for valid regname */
  714. return FAIL;
  715. #ifdef USE_CLIPBOARD
  716.     if (regname == '*')
  717. clip_get_selection();
  718. #endif
  719.     if (regname == '.') /* insert last inserted text */
  720. return FAIL; /* Unimplemented */
  721.     if (get_spec_reg(regname, &arg, &allocated, TRUE))
  722.     {
  723. if (arg == NULL)
  724.     return FAIL;
  725. i = put_on_cmdline(arg, -1, TRUE);
  726. if (allocated)
  727.     vim_free(arg);
  728. return (int)i;
  729.     }
  730.     get_yank_register(regname, FALSE);
  731.     if (y_current->y_array == NULL)
  732. return FAIL;
  733.     for (i = 0; i < y_current->y_size; ++i)
  734.     {
  735. put_on_cmdline(y_current->y_array[i], -1, FALSE);
  736. /* insert ^M between lines and after last line if type is MLINE */
  737. if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  738.     put_on_cmdline((char_u *)"r", 1, FALSE);
  739.     }
  740.     return OK;
  741. }
  742. /*
  743.  * op_delete - handle a delete operation
  744.  *
  745.  * return FAIL if undo failed, OK otherwise.
  746.  */
  747.     int
  748. op_delete(oap)
  749.     OPARG   *oap;
  750. {
  751.     int n;
  752.     linenr_t lnum;
  753.     char_u *ptr;
  754.     char_u *newp, *oldp;
  755.     linenr_t old_lcount = curbuf->b_ml.ml_line_count;
  756.     int did_yank = FALSE;
  757.     struct block_def bd;
  758.     if (curbuf->b_ml.ml_flags & ML_EMPTY)     /* nothing to do */
  759. return OK;
  760.     /* Nothing to delete, return here. Do prepare undo, for op_change(). */
  761.     if (oap->empty)
  762.     {
  763. return u_save_cursor();
  764.     }
  765. #ifdef MULTI_BYTE
  766.     if (is_dbcs)
  767.     {
  768. char_u *p;
  769. if (oap->end.col >= oap->start.col)
  770. {
  771.     p = ml_get(oap->end.lnum);
  772.     if (IsTrailByte(p, p + oap->end.col + oap->inclusive))
  773. oap->end.col++;
  774. }
  775. else
  776. {
  777.     p = ml_get(oap->start.lnum);
  778.     if (IsTrailByte(p, p + oap->start.col + oap->inclusive))
  779. oap->start.col++;
  780. }
  781.     }
  782. #endif
  783. /*
  784.  * Imitate the strange Vi behaviour: If the delete spans more than one line
  785.  * and motion_type == MCHAR and the result is a blank line, make the delete
  786.  * linewise.  Don't do this for the change command or Visual mode.
  787.  */
  788.     if (       oap->motion_type == MCHAR
  789.     && !oap->is_VIsual
  790.     && oap->line_count > 1
  791.     && oap->op_type == OP_DELETE)
  792.     {
  793. ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive;
  794. ptr = skipwhite(ptr);
  795. if (*ptr == NUL && inindent(0))
  796.     oap->motion_type = MLINE;
  797.     }
  798. /*
  799.  * Check for trying to delete (e.g. "D") in an empty line.
  800.  * Note: For the change operator it is ok.
  801.  */
  802.     if (       oap->motion_type == MCHAR
  803.     && oap->line_count == 1
  804.     && oap->op_type == OP_DELETE
  805.     && *ml_get(oap->start.lnum) == NUL)
  806.     {
  807. /*
  808.  * It's an error to operate on an empty region, when 'E' inclucded in
  809.  * 'cpoptions' (Vi compatible).
  810.  */
  811. if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL)
  812.     beep_flush();
  813. return OK;
  814.     }
  815. /*
  816.  * Do a yank of whatever we're about to delete.
  817.  * If a yank register was specified, put the deleted text into that register.
  818.  * For the black hole register '_' don't yank anything.
  819.  */
  820.     if (oap->regname != '_')
  821.     {
  822. if (oap->regname != 0)
  823. {
  824.     /* check for read-only register */
  825.     if (!valid_yank_reg(oap->regname, TRUE))
  826.     {
  827. beep_flush();
  828. return OK;
  829.     }
  830.     get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */
  831.     if (op_yank(oap, TRUE, FALSE) == OK)   /* yank without message */
  832. did_yank = TRUE;
  833. }
  834. /*
  835.  * Put deleted text into register 1 and shift number registers if the
  836.  * delete contains a line break, or when a regname has been specified!
  837.  */
  838. if (oap->regname != 0 || oap->motion_type == MLINE
  839.        || oap->line_count > 1)
  840. {
  841.     y_current = &y_regs[9];
  842.     free_yank_all(); /* free register nine */
  843.     for (n = 9; n > 1; --n)
  844. y_regs[n] = y_regs[n - 1];
  845.     y_previous = y_current = &y_regs[1];
  846.     y_regs[1].y_array = NULL; /* set register one to empty */
  847.     oap->regname = 0;
  848. }
  849. else if (oap->regname == 0) /* yank into unnamed register */
  850. {
  851.     oap->regname = '-'; /* use special delete register */
  852.     get_yank_register(oap->regname, TRUE);
  853.     oap->regname = 0;
  854. }
  855. if (oap->regname == 0 && op_yank(oap, TRUE, FALSE) == OK)
  856.     did_yank = TRUE;
  857. /*
  858.  * If there's too much stuff to fit in the yank register, then get a
  859.  * confirmation before doing the delete. This is crude, but simple.
  860.  * And it avoids doing a delete of something we can't put back if we
  861.  * want.
  862.  */
  863. if (!did_yank)
  864. {
  865.     if (ask_yesno((char_u *)"cannot yank; delete anyway", TRUE) != 'y')
  866.     {
  867. emsg(e_abort);
  868. return FAIL;
  869.     }
  870. }
  871.     }
  872. /*
  873.  * block mode delete
  874.  */
  875.     if (oap->block_mode)
  876.     {
  877. if (u_save((linenr_t)(oap->start.lnum - 1),
  878.        (linenr_t)(oap->end.lnum + 1)) == FAIL)
  879.     return FAIL;
  880. #ifdef SYNTAX_HL
  881. /* recompute syntax hl., starting with this line */
  882. syn_changed(curwin->w_cursor.lnum);
  883. #endif
  884. for (lnum = curwin->w_cursor.lnum;
  885.        curwin->w_cursor.lnum <= oap->end.lnum;
  886.       ++curwin->w_cursor.lnum)
  887. {
  888.     block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
  889.     if (bd.textlen == 0) /* nothing to delete */
  890. continue;
  891.     /* n == number of chars deleted
  892.      * If we delete a TAB, it may be replaced by several characters.
  893.      * Thus the number of characters may increase!
  894.      */
  895.     n = bd.textlen - bd.startspaces - bd.endspaces;
  896.     oldp = ml_get_curline();
  897.     newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
  898.     if (newp == NULL)
  899. continue;
  900.     /* copy up to deleted part */
  901.     mch_memmove(newp, oldp, (size_t)bd.textcol);
  902.     /* insert spaces */
  903.     copy_spaces(newp + bd.textcol,
  904.      (size_t)(bd.startspaces + bd.endspaces));
  905.     /* copy the part after the deleted part */
  906.     oldp += bd.textcol + bd.textlen;
  907.     mch_memmove(newp + bd.textcol + bd.startspaces + bd.endspaces,
  908.       oldp, STRLEN(oldp) + 1);
  909.     /* replace the line */
  910.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  911. }
  912. curwin->w_cursor.lnum = lnum;
  913. changed_cline_bef_curs(); /* recompute cursor pos. on screen */
  914. approximate_botline(); /* w_botline may be wrong now */
  915. adjust_cursor();
  916. changed();
  917. update_screen(VALID_TO_CURSCHAR);
  918. oap->line_count = 0;     /* no lines deleted */
  919.     }
  920.     else if (oap->motion_type == MLINE)
  921.     {
  922. if (oap->op_type == OP_CHANGE)
  923. {
  924.     /* Delete the lines except the first one.  Temporarily move the
  925.      * cursor to the next line.  Save the current line number, if the
  926.      * last line is deleted it may be changed.
  927.      */
  928.     if (oap->line_count > 1)
  929.     {
  930. lnum = curwin->w_cursor.lnum;
  931. ++curwin->w_cursor.lnum;
  932. del_lines((long)(oap->line_count - 1), TRUE, TRUE);
  933. curwin->w_cursor.lnum = lnum;
  934.     }
  935.     if (u_save_cursor() == FAIL)
  936. return FAIL;
  937.     if (curbuf->b_p_ai)     /* don't delete indent */
  938.     {
  939. beginline(BL_WHITE);     /* cursor on first non-white */
  940. did_ai = TRUE;     /* delete the indent when ESC hit */
  941.     }
  942.     else
  943. beginline(0);     /* cursor in column 0 */
  944. #ifdef SYNTAX_HL
  945.     /* recompute syntax hl., starting with current line */
  946.     syn_changed(curwin->w_cursor.lnum);
  947. #endif
  948.     truncate_line(FALSE);   /* delete the rest of the line */
  949.     /* leave cursor past last char in line */
  950. }
  951. else
  952. {
  953.     del_lines(oap->line_count, TRUE, TRUE);
  954.     beginline(BL_WHITE | BL_FIX);
  955. }
  956. u_clearline(); /* "U" command should not be possible after "dd" */
  957.     }
  958.     else if (oap->line_count == 1) /* delete characters within one line */
  959.     {
  960. if (u_save_cursor() == FAIL)
  961.     return FAIL;
  962.     /* if 'cpoptions' contains '$', display '$' at end of change */
  963. if (    vim_strchr(p_cpo, CPO_DOLLAR) != NULL
  964. && oap->op_type == OP_CHANGE
  965. && oap->end.lnum == curwin->w_cursor.lnum
  966. && !oap->is_VIsual)
  967.     display_dollar(oap->end.col - !oap->inclusive);
  968. n = oap->end.col - oap->start.col + 1 - !oap->inclusive;
  969. (void)del_chars((long)n, restart_edit == NUL);
  970.     }
  971.     else /* delete characters between lines */
  972.     {
  973. if (u_save_cursor() == FAIL) /* save first line for undo */
  974.     return FAIL;
  975. #ifdef SYNTAX_HL
  976. /* recompute syntax hl., starting with current line */
  977. syn_changed(curwin->w_cursor.lnum);
  978. #endif
  979. truncate_line(TRUE); /* delete from cursor to end of line */
  980. oap->start = curwin->w_cursor; /* remember curwin->w_cursor */
  981. ++curwin->w_cursor.lnum;
  982. /* includes save for undo */
  983. del_lines((long)(oap->line_count - 2), TRUE, TRUE);
  984. if (u_save_cursor() == FAIL) /* save last line for undo */
  985.     return FAIL;
  986. /* delete from start of line until op_end */
  987. curwin->w_cursor.col = 0;
  988. (void)del_chars((long)(oap->end.col + 1 - !oap->inclusive),
  989.  restart_edit == NUL);
  990. curwin->w_cursor = oap->start; /* restore curwin->w_cursor */
  991. (void)do_join(FALSE, TRUE);
  992.     }
  993.     /*
  994.      * For a change within one line, the screen is updated differently (to
  995.      * take care of 'dollar').
  996.      */
  997.     if (oap->motion_type == MCHAR && oap->line_count == 1)
  998.     {
  999. if (dollar_vcol)
  1000.     must_redraw = 0;     /* don't want a redraw now */
  1001. else
  1002.     update_screenline();
  1003.     }
  1004.     else if (!global_busy)     /* no need to update screen for :global */
  1005.     {
  1006. update_topline();
  1007. update_screen(NOT_VALID);
  1008.     }
  1009.     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  1010.     /*
  1011.      * Set "'[" and "']" marks.
  1012.      */
  1013.     curbuf->b_op_start = oap->start;
  1014.     if (oap->block_mode)
  1015.     {
  1016. curbuf->b_op_end.lnum = oap->end.lnum;
  1017. curbuf->b_op_end.col = oap->start.col;
  1018.     }
  1019.     else
  1020. curbuf->b_op_end = oap->start;
  1021.     return OK;
  1022. }
  1023. /*
  1024.  * op_tilde - handle the (non-standard vi) tilde operator
  1025.  */
  1026.     void
  1027. op_tilde(oap)
  1028.     OPARG *oap;
  1029. {
  1030.     FPOS pos;
  1031.     struct block_def bd;
  1032.     if (u_save((linenr_t)(oap->start.lnum - 1),
  1033.        (linenr_t)(oap->end.lnum + 1)) == FAIL)
  1034. return;
  1035.     /*
  1036.      * Set '[ and '] marks.
  1037.      */
  1038.     curbuf->b_op_start = oap->start;
  1039.     curbuf->b_op_end = oap->end;
  1040.     pos = oap->start;
  1041.     if (oap->block_mode)     /* Visual block mode */
  1042.     {
  1043. for (; pos.lnum <= oap->end.lnum; ++pos.lnum)
  1044. {
  1045.     block_prep(oap, &bd, pos.lnum, FALSE);
  1046.     pos.col = bd.textcol;
  1047.     while (--bd.textlen >= 0)
  1048.     {
  1049. swapchar(oap->op_type, &pos);
  1050. if (inc(&pos) == -1)     /* at end of file */
  1051.     break;
  1052.     }
  1053. }
  1054.     }
  1055.     else     /* not block mode */
  1056.     {
  1057. if (oap->motion_type == MLINE)
  1058. {
  1059.     pos.col = 0;
  1060.     oap->end.col = STRLEN(ml_get(oap->end.lnum));
  1061.     if (oap->end.col)
  1062. --oap->end.col;
  1063. }
  1064. else if (!oap->inclusive)
  1065.     dec(&(oap->end));
  1066. while (ltoreq(pos, oap->end))
  1067. {
  1068.     swapchar(oap->op_type, &pos);
  1069.     if (inc(&pos) == -1)    /* at end of file */
  1070. break;
  1071. }
  1072.     }
  1073.     if (oap->motion_type == MCHAR && oap->line_count == 1 && !oap->block_mode)
  1074. update_screenline();
  1075.     else
  1076.     {
  1077. #ifdef SYNTAX_HL
  1078. /* recompute syntax hl., starting with current line */
  1079. syn_changed(oap->start.lnum);
  1080. #endif
  1081. update_topline();
  1082. update_screen(NOT_VALID);
  1083.     }
  1084.     if (oap->line_count > p_report)
  1085. smsg((char_u *)"%ld line%s ~ed",
  1086.     oap->line_count, plural(oap->line_count));
  1087. }
  1088. /*
  1089.  * If op_type == OP_UPPER: make uppercase,
  1090.  * if op_type == OP_LOWER: make lowercase,
  1091.  * else swap case of character at 'pos'
  1092.  */
  1093.     void
  1094. swapchar(op_type, pos)
  1095.     int     op_type;
  1096.     FPOS    *pos;
  1097. {
  1098.     int     c;
  1099.     c = gchar(pos);
  1100.     if (islower(c) && op_type != OP_LOWER)
  1101.     {
  1102. pchar(*pos, TO_UPPER(c));
  1103. changed();
  1104.     }
  1105.     else if (isupper(c) && op_type != OP_UPPER)
  1106.     {
  1107. pchar(*pos, TO_LOWER(c));
  1108. changed();
  1109.     }
  1110. }
  1111. /*
  1112.  * op_change - handle a change operation
  1113.  *
  1114.  * return TRUE if edit() returns because of a CTRL-O command
  1115.  */
  1116.     int
  1117. op_change(oap)
  1118.     OPARG *oap;
  1119. {
  1120.     colnr_t        l;
  1121.     l = oap->start.col;
  1122.     if (oap->motion_type == MLINE)
  1123.     {
  1124. l = 0;
  1125. #ifdef SMARTINDENT
  1126. if (curbuf->b_p_si)
  1127.     can_si = TRUE; /* It's like opening a new line, do si */
  1128. #endif
  1129.     }
  1130.     /* First delete the text in the region.  In an empty buffer only need to
  1131.      * save for undo */
  1132.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  1133.     {
  1134. if (u_save_cursor() == FAIL)
  1135.     return FALSE;
  1136.     }
  1137.     else if (op_delete(oap) == FAIL)
  1138. return FALSE;
  1139.     if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum))
  1140. inc_cursor();
  1141. #if defined(LISPINDENT) || defined(CINDENT)
  1142.     if (oap->motion_type == MLINE)
  1143.     {
  1144. # ifdef LISPINDENT
  1145. if (curbuf->b_p_lisp && curbuf->b_p_ai)
  1146.     fixthisline(get_lisp_indent);
  1147. # endif
  1148. # if defined(LISPINDENT) && defined(CINDENT)
  1149. else
  1150. # endif
  1151. # ifdef CINDENT
  1152. if (curbuf->b_p_cin)
  1153.     fixthisline(get_c_indent);
  1154. # endif
  1155.     }
  1156. #endif
  1157.     return edit(NUL, FALSE, (linenr_t)1);
  1158. }
  1159. /*
  1160.  * set all the yank registers to empty (called from main())
  1161.  */
  1162.     void
  1163. init_yank()
  1164. {
  1165.     int i;
  1166.     for (i = 0; i < NUM_REGISTERS; ++i)
  1167. y_regs[i].y_array = NULL;
  1168. }
  1169. /*
  1170.  * Free "n" lines from the current yank register.
  1171.  * Called for normal freeing and in case of error.
  1172.  */
  1173.     static void
  1174. free_yank(n)
  1175.     long n;
  1176. {
  1177.     if (y_current->y_array != NULL)
  1178.     {
  1179. long     i;
  1180. for (i = n; --i >= 0; )
  1181. {
  1182.     if ((i & 1023) == 1023)     /* this may take a while */
  1183.     {
  1184. /*
  1185.  * This message should never cause a hit-return message.
  1186.  * Overwrite this message with any next message.
  1187.  */
  1188. ++no_wait_return;
  1189. smsg((char_u *)"freeing %ld lines", i + 1);
  1190. --no_wait_return;
  1191. msg_didout = FALSE;
  1192. msg_col = 0;
  1193.     }
  1194.     vim_free(y_current->y_array[i]);
  1195. }
  1196. vim_free(y_current->y_array);
  1197. y_current->y_array = NULL;
  1198. if (n >= 1000)
  1199.     MSG("");
  1200.     }
  1201. }
  1202.     static void
  1203. free_yank_all()
  1204. {
  1205.     free_yank(y_current->y_size);
  1206. }
  1207. /*
  1208.  * Yank the text between curwin->w_cursor and startpos into a yank register.
  1209.  * If we are to append (uppercase register), we first yank into a new yank
  1210.  * register and then concatenate the old and the new one (so we keep the old
  1211.  * one in case of out-of-memory).
  1212.  *
  1213.  * return FAIL for failure, OK otherwise
  1214.  */
  1215.     int
  1216. op_yank(oap, deleting, mess)
  1217.     OPARG   *oap;
  1218.     int     deleting;
  1219.     int     mess;
  1220. {
  1221.     long y_idx; /* index in y_array[] */
  1222.     struct yankreg *curr; /* copy of y_current */
  1223.     struct yankreg newreg; /* new yank register when appending */
  1224.     char_u **new_ptr;
  1225.     linenr_t lnum; /* current line number */
  1226.     long j;
  1227.     long len;
  1228.     int yanktype = oap->motion_type;
  1229.     long yanklines = oap->line_count;
  1230.     linenr_t yankendlnum = oap->end.lnum;
  1231.     char_u *p;
  1232.     char_u *pnew;
  1233.     struct block_def bd;
  1234.     /* check for read-only register */
  1235.     if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
  1236.     {
  1237. beep_flush();
  1238. return FAIL;
  1239.     }
  1240.     if (oap->regname == '_')     /* black hole: nothing to do */
  1241. return OK;
  1242.     if (!deleting)     /* op_delete() already set y_current */
  1243. get_yank_register(oap->regname, TRUE);
  1244.     curr = y_current;
  1245.     /* append to existing contents */
  1246.     if (y_append && y_current->y_array != NULL)
  1247. y_current = &newreg;
  1248.     else
  1249. free_yank_all();     /* free previously yanked lines */
  1250. /*
  1251.  * If the cursor was in column 1 before and after the movement, and the
  1252.  * operator is not inclusive, the yank is always linewise.
  1253.  */
  1254.     if (       oap->motion_type == MCHAR
  1255.     && oap->start.col == 0
  1256.     && !oap->inclusive
  1257.     && (!oap->is_VIsual || *p_sel == 'o')
  1258.     && oap->end.col == 0
  1259.     && yanklines > 1)
  1260.     {
  1261. yanktype = MLINE;
  1262. --yankendlnum;
  1263. --yanklines;
  1264.     }
  1265.     y_current->y_size = yanklines;
  1266.     y_current->y_type = yanktype;   /* set the yank register type */
  1267.     y_current->y_array = (char_u **)lalloc_clear((long_u)(sizeof(char_u *) *
  1268.     yanklines), TRUE);
  1269.     if (y_current->y_array == NULL)
  1270.     {
  1271. y_current = curr;
  1272. return FAIL;
  1273.     }
  1274.     y_idx = 0;
  1275.     lnum = oap->start.lnum;
  1276. /*
  1277.  * Visual block mode
  1278.  */
  1279.     if (oap->block_mode)
  1280.     {
  1281. y_current->y_type = MBLOCK;     /* set the yank register type */
  1282. for ( ; lnum <= yankendlnum; ++lnum)
  1283. {
  1284.     block_prep(oap, &bd, lnum, FALSE);
  1285.     if ((pnew = alloc(bd.startspaces + bd.endspaces +
  1286.   bd.textlen + 1)) == NULL)
  1287. goto fail;
  1288.     y_current->y_array[y_idx++] = pnew;
  1289.     copy_spaces(pnew, (size_t)bd.startspaces);
  1290.     pnew += bd.startspaces;
  1291.     mch_memmove(pnew, bd.textstart, (size_t)bd.textlen);
  1292.     pnew += bd.textlen;
  1293.     copy_spaces(pnew, (size_t)bd.endspaces);
  1294.     pnew += bd.endspaces;
  1295.     *pnew = NUL;
  1296. }
  1297.     }
  1298.     else
  1299.     {
  1300. /*
  1301.  * there are three parts for non-block mode:
  1302.  * 1. if yanktype != MLINE yank last part of the top line
  1303.  * 2. yank the lines between op_start and op_end, inclusive when
  1304.  *    yanktype == MLINE
  1305.  * 3. if yanktype != MLINE yank first part of the bot line
  1306.  */
  1307. if (yanktype != MLINE)
  1308. {
  1309.     if (yanklines == 1)     /* op_start and op_end on same line */
  1310.     {
  1311. j = oap->end.col - oap->start.col + 1 - !oap->inclusive;
  1312. /* Watch out for very big endcol (MAXCOL) */
  1313. p = ml_get(lnum) + oap->start.col;
  1314. len = STRLEN(p);
  1315. if (j > len || j < 0)
  1316.     j = len;
  1317. if ((y_current->y_array[0] = vim_strnsave(p, (int)j)) == NULL)
  1318. {
  1319. fail:
  1320.     free_yank(y_idx); /* free the allocated lines */
  1321.     y_current = curr;
  1322.     return FAIL;
  1323. }
  1324. goto success;
  1325.     }
  1326.     if ((y_current->y_array[0] =
  1327. vim_strsave(ml_get(lnum++) + oap->start.col)) == NULL)
  1328. goto fail;
  1329.     ++y_idx;
  1330. }
  1331. while (yanktype == MLINE ? (lnum <= yankendlnum) : (lnum < yankendlnum))
  1332. {
  1333.     if ((y_current->y_array[y_idx] =
  1334.  vim_strsave(ml_get(lnum++))) == NULL)
  1335. goto fail;
  1336.     ++y_idx;
  1337. }
  1338. if (yanktype != MLINE)
  1339. {
  1340.     if ((y_current->y_array[y_idx] = vim_strnsave(ml_get(yankendlnum),
  1341.  oap->end.col + 1 - !oap->inclusive)) == NULL)
  1342. goto fail;
  1343. }
  1344.     }
  1345. success:
  1346.     if (curr != y_current) /* append the new block to the old block */
  1347.     {
  1348. new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) *
  1349.    (curr->y_size + y_current->y_size)), TRUE);
  1350. if (new_ptr == NULL)
  1351.     goto fail;
  1352. for (j = 0; j < curr->y_size; ++j)
  1353.     new_ptr[j] = curr->y_array[j];
  1354. vim_free(curr->y_array);
  1355. curr->y_array = new_ptr;
  1356. if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */
  1357.     curr->y_type = MLINE;
  1358. /* concatenate the last line of the old block with the first line of
  1359.  * the new block */
  1360. if (curr->y_type == MCHAR)
  1361. {
  1362.     pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1])
  1363.       + STRLEN(y_current->y_array[0]) + 1), TRUE);
  1364.     if (pnew == NULL)
  1365.     {
  1366.     y_idx = y_current->y_size - 1;
  1367.     goto fail;
  1368.     }
  1369.     STRCPY(pnew, curr->y_array[--j]);
  1370.     STRCAT(pnew, y_current->y_array[0]);
  1371.     vim_free(curr->y_array[j]);
  1372.     vim_free(y_current->y_array[0]);
  1373.     curr->y_array[j++] = pnew;
  1374.     y_idx = 1;
  1375. }
  1376. else
  1377.     y_idx = 0;
  1378. while (y_idx < y_current->y_size)
  1379.     curr->y_array[j++] = y_current->y_array[y_idx++];
  1380. curr->y_size = j;
  1381. vim_free(y_current->y_array);
  1382. y_current = curr;
  1383.     }
  1384.     if (mess) /* Display message about yank? */
  1385.     {
  1386. if (yanktype == MCHAR && !oap->block_mode && yanklines == 1)
  1387.     yanklines = 0;
  1388. /* Some versions of Vi use ">=" here, some don't...  */
  1389. if (yanklines > p_report)
  1390. {
  1391.     /* redisplay now, so message is not deleted */
  1392.     update_topline_redraw();
  1393.     smsg((char_u *)"%ld line%s yanked", yanklines, plural(yanklines));
  1394. }
  1395.     }
  1396.     /*
  1397.      * Set "'[" and "']" marks.
  1398.      */
  1399.     curbuf->b_op_start = oap->start;
  1400.     curbuf->b_op_end = oap->end;
  1401. #ifdef USE_CLIPBOARD
  1402.     /*
  1403.      * If we were yanking to the clipboard register, send result to clipboard.
  1404.      */
  1405.     if (curr == &(y_regs[CLIPBOARD_REGISTER]))
  1406.     {
  1407. clip_own_selection();
  1408. clip_mch_set_selection();
  1409.     }
  1410. #endif
  1411.     return OK;
  1412. }
  1413. /*
  1414.  * put contents of register "regname" into the text
  1415.  * For ":put" command count == -1.
  1416.  * flags: PUT_FIXINDENT make indent look nice
  1417.  *   PUT_CURSEND leave cursor after end of new text
  1418.  */
  1419.     void
  1420. do_put(regname, dir, count, flags)
  1421.     int regname;
  1422.     int dir; /* BACKWARD for 'P', FORWARD for 'p' */
  1423.     long count;
  1424.     int flags;
  1425. {
  1426.     char_u *ptr;
  1427.     char_u *newp, *oldp;
  1428.     int yanklen;
  1429.     int oldlen;
  1430.     int totlen = 0; /* init for gcc */
  1431.     linenr_t lnum;
  1432.     colnr_t col;
  1433.     long i; /* index in y_array[] */
  1434.     int y_type;
  1435.     long y_size;
  1436.     char_u **y_array = NULL;
  1437.     long nr_lines = 0;
  1438.     colnr_t vcol;
  1439.     int delcount;
  1440.     int incr = 0;
  1441.     long j;
  1442.     FPOS new_cursor;
  1443.     int indent;
  1444.     int orig_indent = 0; /* init for gcc */
  1445.     int indent_diff = 0; /* init for gcc */
  1446.     int first_indent = TRUE;
  1447.     FPOS old_pos;
  1448.     struct block_def bd;
  1449.     char_u *insert_string = NULL;
  1450.     int allocated = FALSE;
  1451. #ifdef MULTI_BYTE
  1452.     int bMultiByteCode = 0;
  1453. #endif
  1454. #ifdef USE_CLIPBOARD
  1455.     if (regname == '*')
  1456. clip_get_selection();
  1457. #endif
  1458.     if (flags & PUT_FIXINDENT)
  1459. orig_indent = get_indent();
  1460.     curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */
  1461.     if (dir == FORWARD)
  1462.     {
  1463. #ifdef MULTI_BYTE
  1464. /* put it on the next of the multi-byte character. */
  1465. if (is_dbcs)
  1466. {
  1467.     ptr = ml_get(curwin->w_cursor.lnum) + curwin->w_cursor.col;
  1468.     if (IsLeadByte(*ptr) && (*(ptr + 1) != ''))
  1469.     {
  1470. bMultiByteCode = 1;
  1471. curbuf->b_op_start.col++;
  1472.     }
  1473. }
  1474. #endif
  1475. curbuf->b_op_start.col++;
  1476.     }
  1477.     curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */
  1478.     /*
  1479.      * Using inserted text works differently, because the register includes
  1480.      * special characters (newlines, etc.).
  1481.      */
  1482.     if (regname == '.')
  1483.     {
  1484. (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
  1485.     (count == -1 ? 'O' : 'i')), count, FALSE);
  1486. /* Putting the text is done later, so can't really move the cursor to
  1487.  * the nex character.  Use "l" to simulate it. */
  1488. if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
  1489.     stuffcharReadbuff('l');
  1490. return;
  1491.     }
  1492.     /*
  1493.      * For special registers '%' (file name), '#' (alternate file name) and
  1494.      * ':' (last command line), etc. we have to create a fake yank register.
  1495.      */
  1496.     if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
  1497.     {
  1498. if (insert_string == NULL)
  1499.     return;
  1500.     }
  1501.     if (insert_string != NULL)
  1502.     {
  1503. y_type = MCHAR;
  1504. if (regname == '=')
  1505. {
  1506.     /* For the = register we need to split the string at NL
  1507.      * characters. */
  1508.     /* Loop twice: count the number of lines and save them. */
  1509.     for (;;)
  1510.     {
  1511. y_size = 0;
  1512. ptr = insert_string;
  1513. while (ptr != NULL)
  1514. {
  1515.     if (y_array != NULL)
  1516. y_array[y_size] = ptr;
  1517.     ++y_size;
  1518.     ptr = vim_strchr(ptr, 'n');
  1519.     if (ptr != NULL)
  1520.     {
  1521. if (y_array != NULL)
  1522.     *ptr = NUL;
  1523. ++ptr;
  1524. /* A trailing 'n' makes the string linewise */
  1525. if (*ptr == NUL)
  1526. {
  1527.     y_type = MLINE;
  1528.     break;
  1529. }
  1530.     }
  1531. }
  1532. if (y_array != NULL)
  1533.     break;
  1534. y_array = (char_u **)alloc((unsigned)
  1535.  (y_size * sizeof(char_u *)));
  1536. if (y_array == NULL)
  1537.     goto end;
  1538.     }
  1539. }
  1540. else
  1541. {
  1542.     y_size = 1; /* use fake one-line yank register */
  1543.     y_array = &insert_string;
  1544. }
  1545.     }
  1546.     else
  1547.     {
  1548. get_yank_register(regname, FALSE);
  1549. y_type = y_current->y_type;
  1550. y_size = y_current->y_size;
  1551. y_array = y_current->y_array;
  1552.     }
  1553.     if (count == -1)     /* :put command */
  1554.     {
  1555. y_type = MLINE;
  1556. count = 1;
  1557.     }
  1558.     if (y_size == 0 || y_array == NULL)
  1559.     {
  1560. EMSG2("Nothing in register %s",
  1561.   regname == 0 ? (char_u *)""" : transchar(regname));
  1562. goto end;
  1563.     }
  1564.     if (y_type == MBLOCK)
  1565.     {
  1566. lnum = curwin->w_cursor.lnum + y_size + 1;
  1567. if (lnum > curbuf->b_ml.ml_line_count)
  1568.     lnum = curbuf->b_ml.ml_line_count + 1;
  1569. if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
  1570.     goto end;
  1571.     }
  1572.     else if (u_save_cursor() == FAIL)
  1573. goto end;
  1574.     yanklen = STRLEN(y_array[0]);
  1575.     changed();
  1576.     lnum = curwin->w_cursor.lnum;
  1577.     col = curwin->w_cursor.col;
  1578.     approximate_botline();     /* w_botline might not be valid now */
  1579.     changed_cline_bef_curs();     /* cursor posn on screen may change */
  1580. /*
  1581.  * block mode
  1582.  */
  1583.     if (y_type == MBLOCK)
  1584.     {
  1585. if (dir == FORWARD && gchar_cursor() != NUL)
  1586. {
  1587.     getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
  1588. #ifdef MULTI_BYTE
  1589.     if (is_dbcs)
  1590.     {
  1591. /* put it on the next of the multi-byte character. */
  1592. col += bMultiByteCode + 1;
  1593. curwin->w_cursor.col += bMultiByteCode + 1;
  1594.     }
  1595.     else
  1596. #endif
  1597.     {
  1598. ++col;
  1599. ++curwin->w_cursor.col;
  1600.     }
  1601. }
  1602. else
  1603.     getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
  1604. #ifdef SYNTAX_HL
  1605. /* recompute syntax hl., starting with current line */
  1606. syn_changed(curwin->w_cursor.lnum);
  1607. #endif
  1608. for (i = 0; i < y_size; ++i)
  1609. {
  1610.     bd.startspaces = 0;
  1611.     bd.endspaces = 0;
  1612.     bd.textcol = 0;
  1613.     vcol = 0;
  1614.     delcount = 0;
  1615.     /* add a new line */
  1616.     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  1617.     {
  1618. ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
  1619.    (colnr_t)1, FALSE);
  1620. ++nr_lines;
  1621.     }
  1622.     oldp = ml_get_curline();
  1623.     oldlen = STRLEN(oldp);
  1624.     for (ptr = oldp; vcol < col && *ptr; ++ptr)
  1625.     {
  1626. /* Count a tab for what it's worth (if list mode not on) */
  1627. incr = lbr_chartabsize(ptr, (colnr_t)vcol);
  1628. vcol += incr;
  1629. ++bd.textcol;
  1630.     }
  1631.     if (vcol < col) /* line too short, padd with spaces */
  1632.     {
  1633. bd.startspaces = col - vcol;
  1634.     }
  1635.     else if (vcol > col)
  1636.     {
  1637. bd.endspaces = vcol - col;
  1638. bd.startspaces = incr - bd.endspaces;
  1639. --bd.textcol;
  1640. delcount = 1;
  1641.     }
  1642.     yanklen = STRLEN(y_array[i]);
  1643.     totlen = count * yanklen + bd.startspaces + bd.endspaces;
  1644.     newp = alloc_check((unsigned)totlen + oldlen + 1);
  1645.     if (newp == NULL)
  1646. break;
  1647.     /* copy part up to cursor to new line */
  1648.     ptr = newp;
  1649.     mch_memmove(ptr, oldp, (size_t)bd.textcol);
  1650.     ptr += bd.textcol;
  1651.     /* may insert some spaces before the new text */
  1652.     copy_spaces(ptr, (size_t)bd.startspaces);
  1653.     ptr += bd.startspaces;
  1654.     /* insert the new text */
  1655.     for (j = 0; j < count; ++j)
  1656.     {
  1657. mch_memmove(ptr, y_array[i], (size_t)yanklen);
  1658. ptr += yanklen;
  1659.     }
  1660.     /* may insert some spaces after the new text */
  1661.     copy_spaces(ptr, (size_t)bd.endspaces);
  1662.     ptr += bd.endspaces;
  1663.     /* move the text after the cursor to the end of the line. */
  1664.     mch_memmove(ptr, oldp + bd.textcol + delcount,
  1665. (size_t)(oldlen - bd.textcol - delcount + 1));
  1666.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  1667.     ++curwin->w_cursor.lnum;
  1668.     if (i == 0)
  1669. curwin->w_cursor.col += bd.startspaces;
  1670. }
  1671. /* adjust '] mark */
  1672. curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
  1673. curbuf->b_op_end.col = bd.textcol + totlen - 1;
  1674. if (flags & PUT_CURSEND)
  1675. {
  1676.     curwin->w_cursor = curbuf->b_op_end;
  1677.     curwin->w_cursor.col++;
  1678. }
  1679. else
  1680.     curwin->w_cursor.lnum = lnum;
  1681. update_topline();
  1682. if (flags & PUT_CURSEND)
  1683.     update_screen(NOT_VALID);
  1684. else
  1685.     update_screen(VALID_TO_CURSCHAR);
  1686.     }
  1687.     else /* not block mode */
  1688.     {
  1689. if (y_type == MCHAR)
  1690. {
  1691.     /* if type is MCHAR, FORWARD is the same as BACKWARD on the next char */
  1692.     if (dir == FORWARD && gchar_cursor() != NUL)
  1693.     {
  1694. #ifdef MULTI_BYTE
  1695. if (is_dbcs)
  1696. {
  1697.     /* put it on the next of the multi-byte character. */
  1698.     col += bMultiByteCode + 1;
  1699.     if (yanklen)
  1700.     {
  1701. curwin->w_cursor.col += bMultiByteCode + 1;
  1702. curbuf->b_op_end.col += bMultiByteCode + 1;
  1703.     }
  1704. }
  1705. else
  1706. #endif
  1707. {
  1708.     ++col;
  1709.     if (yanklen)
  1710.     {
  1711. ++curwin->w_cursor.col;
  1712. ++curbuf->b_op_end.col;
  1713.     }
  1714. }
  1715.     }
  1716.     new_cursor = curwin->w_cursor;
  1717. }
  1718. else if (dir == BACKWARD)
  1719.     /* if type is MLINE, BACKWARD is the same as FORWARD on the previous line */
  1720.     --lnum;
  1721. /*
  1722.  * simple case: insert into current line
  1723.  */
  1724. if (y_type == MCHAR && y_size == 1)
  1725. {
  1726.     totlen = count * yanklen;
  1727.     if (totlen)
  1728.     {
  1729. oldp = ml_get(lnum);
  1730. newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1));
  1731. if (newp == NULL)
  1732.     goto end; /* alloc() will give error message */
  1733. mch_memmove(newp, oldp, (size_t)col);
  1734. ptr = newp + col;
  1735. for (i = 0; i < count; ++i)
  1736. {
  1737.     mch_memmove(ptr, y_array[0], (size_t)yanklen);
  1738.     ptr += yanklen;
  1739. }
  1740. mch_memmove(ptr, oldp + col, STRLEN(oldp + col) + 1);
  1741. ml_replace(lnum, newp, FALSE);
  1742. /* Put cursor on last putted char. */
  1743. curwin->w_cursor.col += (colnr_t)(totlen - 1);
  1744.     }
  1745.     curbuf->b_op_end = curwin->w_cursor;
  1746.     /* For "CTRL-O p" in Insert mode, put cursor after last char */
  1747.     if (totlen && (restart_edit || (flags & PUT_CURSEND)))
  1748. ++curwin->w_cursor.col;
  1749.     update_screenline();
  1750. }
  1751. else
  1752. {
  1753. #ifdef SYNTAX_HL
  1754.     /* recompute syntax hl., starting with current line */
  1755.     syn_changed(lnum);
  1756. #endif
  1757.     while (--count >= 0)
  1758.     {
  1759. i = 0;
  1760. if (y_type == MCHAR)
  1761. {
  1762.     /*
  1763.      * Split the current line in two at the insert position.
  1764.      * First insert y_array[size - 1] in front of second line.
  1765.      * Then append y_array[0] to first line.
  1766.      */
  1767.     ptr = ml_get(lnum) + col;
  1768.     totlen = STRLEN(y_array[y_size - 1]);
  1769.     newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1));
  1770.     if (newp == NULL)
  1771. goto error;
  1772.     STRCPY(newp, y_array[y_size - 1]);
  1773.     STRCAT(newp, ptr);
  1774. /* insert second line */
  1775.     ml_append(lnum, newp, (colnr_t)0, FALSE);
  1776.     vim_free(newp);
  1777.     oldp = ml_get(lnum);
  1778.     newp = alloc_check((unsigned)(col + yanklen + 1));
  1779.     if (newp == NULL)
  1780. goto error;
  1781.     /* copy first part of line */
  1782.     mch_memmove(newp, oldp, (size_t)col);
  1783.     /* append to first line */
  1784.     mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
  1785.     ml_replace(lnum, newp, FALSE);
  1786.     curwin->w_cursor.lnum = lnum;
  1787.     i = 1;
  1788. }
  1789. while (i < y_size)
  1790. {
  1791.     if ((y_type != MCHAR || i < y_size - 1) &&
  1792. ml_append(lnum, y_array[i], (colnr_t)0, FALSE) == FAIL)
  1793.     goto error;
  1794.     lnum++;
  1795.     i++;
  1796.     if (flags & PUT_FIXINDENT)
  1797.     {
  1798. old_pos = curwin->w_cursor;
  1799. curwin->w_cursor.lnum = lnum;
  1800. ptr = ml_get(lnum);
  1801. #if defined(SMARTINDENT) || defined(CINDENT)
  1802. if (*ptr == '#'
  1803. # ifdef SMARTINDENT
  1804.    && curbuf->b_p_si
  1805. # endif
  1806. # ifdef CINDENT
  1807.    && curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE)
  1808. # endif
  1809.     )
  1810.     indent = 0;     /* Leave # lines at start */
  1811. else
  1812. #endif
  1813.      if (*ptr == NUL)
  1814.     indent = 0;     /* Ignore empty lines */
  1815. else if (first_indent)
  1816. {
  1817.     indent_diff = orig_indent - get_indent();
  1818.     indent = orig_indent;
  1819.     first_indent = FALSE;
  1820. }
  1821. else if ((indent = get_indent() + indent_diff) < 0)
  1822.     indent = 0;
  1823. set_indent(indent, TRUE);
  1824. curwin->w_cursor = old_pos;
  1825.     }
  1826.     ++nr_lines;
  1827. }
  1828.     }
  1829.     /* put '] mark at last inserted character */
  1830.     curbuf->b_op_end.lnum = lnum;
  1831.     col = STRLEN(y_array[y_size - 1]);
  1832.     if (col > 1)
  1833. curbuf->b_op_end.col = col - 1;
  1834.     else
  1835. curbuf->b_op_end.col = 0;
  1836.     if (flags & PUT_CURSEND)
  1837.     {
  1838. /* put cursor after inserted text */
  1839. if (y_type == MLINE)
  1840. {
  1841.     if (lnum >= curbuf->b_ml.ml_line_count)
  1842. curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  1843.     else
  1844. curwin->w_cursor.lnum = lnum + 1;
  1845.     curwin->w_cursor.col = 0;
  1846. }
  1847. else
  1848. {
  1849.     curwin->w_cursor.lnum = lnum;
  1850.     curwin->w_cursor.col = col;
  1851. }
  1852. /* the text before the cursor needs redrawing */
  1853. redraw_curbuf_later(NOT_VALID);
  1854.     }
  1855.     else if (y_type == MLINE)
  1856.     {
  1857. /* put cursor onfirst non-blank in first inserted line */
  1858. curwin->w_cursor.col = 0;
  1859. if (dir == FORWARD)
  1860.     ++curwin->w_cursor.lnum;
  1861. beginline(BL_WHITE | BL_FIX);
  1862.     }
  1863.     else /* put cursor on first inserted character */
  1864. curwin->w_cursor = new_cursor;
  1865. error:
  1866.     if (y_type == MLINE) /* adjust '[ mark */
  1867.     {
  1868. curbuf->b_op_start.col = 0;
  1869. if (dir == FORWARD)
  1870.     curbuf->b_op_start.lnum++;
  1871.     }
  1872.     mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
  1873.      (linenr_t)MAXLNUM, nr_lines, 0L);
  1874.     update_topline();
  1875.     update_screen(VALID_TO_CURSCHAR);
  1876. }
  1877.     }
  1878.     msgmore(nr_lines);
  1879.     curwin->w_set_curswant = TRUE;
  1880. end:
  1881.     if (allocated)
  1882.     {
  1883. vim_free(insert_string);
  1884. if (regname == '=')
  1885.     vim_free(y_array);
  1886.     }
  1887.     if ((flags & PUT_CURSEND) && gchar_cursor() == NUL && curwin->w_cursor.col
  1888.        && !(restart_edit || (State & INSERT)))
  1889. --curwin->w_cursor.col;
  1890. }
  1891. /* Return the character name of the register with the given number */
  1892.     int
  1893. get_register_name(num)
  1894.     int num;
  1895. {
  1896.     if (num == -1)
  1897. return '"';
  1898.     else if (num < 10)
  1899. return num + '0';
  1900.     else if (num == DELETION_REGISTER)
  1901. return '-';
  1902. #ifdef USE_CLIPBOARD
  1903.     else if (num == CLIPBOARD_REGISTER)
  1904. return '*';
  1905. #endif
  1906.     else
  1907. return num + 'a' - 10;
  1908. }
  1909. /*
  1910.  * display the contents of the yank registers
  1911.  */
  1912.     void
  1913. do_dis(arg)
  1914.     char_u *arg;
  1915. {
  1916.     int     i, n;
  1917.     long     j;
  1918.     char_u     *p;
  1919.     struct yankreg  *yb;
  1920.     char_u     name;
  1921.     int     attr;
  1922.     if (arg != NULL && *arg == NUL)
  1923. arg = NULL;
  1924.     attr = hl_attr(HLF_8);
  1925.     /* Highlight title */
  1926.     MSG_PUTS_TITLE("n--- Registers ---");
  1927.     for (i = -1; i < NUM_REGISTERS; ++i)
  1928.     {
  1929. if (i == -1)
  1930. {
  1931.     if (y_previous != NULL)
  1932. yb = y_previous;
  1933.     else
  1934. yb = &(y_regs[0]);
  1935. }
  1936. else
  1937.     yb = &(y_regs[i]);
  1938. name = get_register_name(i);
  1939. if (yb->y_array != NULL && (arg == NULL ||
  1940.        vim_strchr(arg, name) != NULL))
  1941. {
  1942.     msg_putchar('n');
  1943.     msg_putchar('"');
  1944.     msg_putchar(name);
  1945.     MSG_PUTS("   ");
  1946.     n = (int)Columns - 6;
  1947.     for (j = 0; j < yb->y_size && n > 1; ++j)
  1948.     {
  1949. if (j)
  1950. {
  1951.     MSG_PUTS_ATTR("^J", attr);
  1952.     n -= 2;
  1953. }
  1954. for (p = yb->y_array[j]; *p && (n -= charsize(*p)) >= 0; ++p)
  1955.     msg_outtrans_len(p, 1);
  1956.     }
  1957.     if (n > 1 && yb->y_type == MLINE)
  1958. MSG_PUTS_ATTR("^J", attr);
  1959.     out_flush();     /* show one line at a time */
  1960. }
  1961.     }
  1962.     /*
  1963.      * display last inserted text
  1964.      */
  1965.     if ((p = get_last_insert()) != NULL &&
  1966. (arg == NULL || vim_strchr(arg, '.') != NULL))
  1967.     {
  1968. MSG_PUTS("n".   ");
  1969. dis_msg(p, TRUE);
  1970.     }
  1971.     /*
  1972.      * display last command line
  1973.      */
  1974.     if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL))
  1975.     {
  1976. MSG_PUTS("n":   ");
  1977. dis_msg(last_cmdline, FALSE);
  1978.     }
  1979.     /*
  1980.      * display current file name
  1981.      */
  1982.     if (curbuf->b_fname != NULL &&
  1983. (arg == NULL || vim_strchr(arg, '%') != NULL))
  1984.     {
  1985. MSG_PUTS("n"%   ");
  1986. dis_msg(curbuf->b_fname, FALSE);
  1987.     }
  1988.     /*
  1989.      * display alternate file name
  1990.      */
  1991.     if (arg == NULL || vim_strchr(arg, '%') != NULL)
  1992.     {
  1993. char_u     *fname;
  1994. linenr_t    dummy;
  1995. if (buflist_name_nr(0, &fname, &dummy) != FAIL)
  1996. {
  1997.     MSG_PUTS("n"#   ");
  1998.     dis_msg(fname, FALSE);
  1999. }
  2000.     }
  2001. #ifdef WANT_EVAL
  2002.     /*
  2003.      * display last used expression
  2004.      */
  2005.     if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL))
  2006.     {
  2007. MSG_PUTS("n"=   ");
  2008. dis_msg(expr_line, FALSE);
  2009.     }
  2010. #endif
  2011. }
  2012. /*
  2013.  * display a string for do_dis()
  2014.  * truncate at end of screen line
  2015.  */
  2016.     void
  2017. dis_msg(p, skip_esc)
  2018.     char_u *p;
  2019.     int skip_esc;     /* if TRUE, ignore trailing ESC */
  2020. {
  2021.     int     n;
  2022.     n = (int)Columns - 6;
  2023.     while (*p && !(*p == ESC && skip_esc && *(p + 1) == NUL) &&
  2024. (n -= charsize(*p)) >= 0)
  2025. msg_outtrans_len(p++, 1);
  2026. }
  2027. /*
  2028.  * join 'count' lines (minimal 2), including u_save()
  2029.  */
  2030.     void
  2031. do_do_join(count, insert_space, redraw)
  2032.     long    count;
  2033.     int     insert_space;
  2034.     int     redraw;     /* can redraw, curwin->w_wcol valid */
  2035. {
  2036.     if (u_save((linenr_t)(curwin->w_cursor.lnum - 1),
  2037.     (linenr_t)(curwin->w_cursor.lnum + count)) == FAIL)
  2038. return;
  2039.     if (count > 10)
  2040. redraw = FALSE;     /* don't redraw each small change */
  2041.     while (--count > 0)
  2042.     {
  2043. line_breakcheck();
  2044. if (got_int || do_join(insert_space, redraw) == FAIL)
  2045. {
  2046.     beep_flush();
  2047.     break;
  2048. }
  2049.     }
  2050.     redraw_later(VALID_TO_CURSCHAR);
  2051.     /*
  2052.      * Need to update the screen if the line where the cursor is became too
  2053.      * long to fit on the screen.
  2054.      */
  2055.     update_topline_redraw();
  2056. }
  2057. /*
  2058.  * Join two lines at the cursor position.
  2059.  * "redraw" is TRUE when the screen should be updated.
  2060.  *
  2061.  * return FAIL for failure, OK ohterwise
  2062.  */
  2063.     int
  2064. do_join(insert_space, redraw)
  2065.     int insert_space;
  2066.     int redraw;
  2067. {
  2068.     char_u *curr;
  2069.     char_u *next;
  2070.     char_u *newp;
  2071.     int endcurr1, endcurr2;
  2072.     int currsize; /* size of the current line */
  2073.     int nextsize; /* size of the next line */
  2074.     int spaces; /* number of spaces to insert */
  2075.     int rows_to_del = 0;/* number of rows on screen to delete */
  2076.     linenr_t t;
  2077.     if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
  2078. return FAIL; /* can't join on last line */
  2079.     if (redraw)
  2080.     {
  2081. /*
  2082.  * Check if we can really redraw:  w_cline_row and w_cline_height need
  2083.  * to be valid.  Try to make them valid by calling may_validate_crow()
  2084.  */
  2085. if (may_validate_crow() == OK)
  2086.     rows_to_del = plines_m(curwin->w_cursor.lnum,
  2087.    curwin->w_cursor.lnum + 1);
  2088. else
  2089.     redraw = FALSE;
  2090.     }
  2091.     curr = ml_get_curline();
  2092.     currsize = STRLEN(curr);
  2093.     endcurr1 = endcurr2 = NUL;
  2094.     if (currsize > 0)
  2095.     {
  2096. endcurr1 = *(curr + currsize - 1);
  2097. if (currsize > 1)
  2098.     endcurr2 = *(curr + currsize - 2);
  2099.     }
  2100.     next = ml_get((linenr_t)(curwin->w_cursor.lnum + 1));
  2101.     spaces = 0;
  2102.     if (insert_space)
  2103.     {
  2104. next = skipwhite(next);
  2105. if (*next != ')' && currsize != 0 && endcurr1 != TAB)
  2106. {
  2107.     /* don't add a space if the line is inding in a space */
  2108.     if (endcurr1 == ' ')
  2109. endcurr1 = endcurr2;
  2110.     else
  2111. ++spaces;
  2112.     /* extra space when 'joinspaces' set and line ends in '.' */
  2113.     if (       p_js
  2114.     && (endcurr1 == '.'
  2115. || (vim_strchr(p_cpo, CPO_JOINSP) == NULL
  2116.     && (endcurr1 == '?' || endcurr1 == '!'))))
  2117. ++spaces;
  2118. }
  2119.     }
  2120.     nextsize = STRLEN(next);
  2121.     newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
  2122.     if (newp == NULL)
  2123. return FAIL;
  2124.     /*
  2125.      * Insert the next line first, because we already have that pointer.
  2126.      * Curr has to be obtained again, because getting next will have
  2127.      * invalidated it.
  2128.      */
  2129.     mch_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));
  2130.     curr = ml_get_curline();
  2131.     mch_memmove(newp, curr, (size_t)currsize);
  2132.     copy_spaces(newp + currsize, (size_t)spaces);
  2133.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  2134. #ifdef SYNTAX_HL
  2135.     /* recompute syntax hl. for current line */
  2136.     syn_changed(curwin->w_cursor.lnum);
  2137. #endif
  2138.     /*
  2139.      * Delete the following line. To do this we move the cursor there
  2140.      * briefly, and then move it back. After del_lines() the cursor may
  2141.      * have moved up (last line deleted), so the current lnum is kept in t.
  2142.      */
  2143.     t = curwin->w_cursor.lnum;
  2144.     ++curwin->w_cursor.lnum;
  2145.     del_lines(1L, FALSE, FALSE);
  2146.     curwin->w_cursor.lnum = t;
  2147.     /*
  2148.      * the number of rows on the screen is reduced by the difference
  2149.      * in number of rows of the two old lines and the one new line
  2150.      */
  2151.     if (redraw)
  2152.     {
  2153. rows_to_del -= plines(curwin->w_cursor.lnum);
  2154. if (rows_to_del > 0)
  2155.     win_del_lines(curwin, curwin->w_cline_row + curwin->w_cline_height,
  2156.      rows_to_del, TRUE, TRUE);
  2157.     }
  2158.     /*
  2159.      * go to first character of the joined line
  2160.      */
  2161.     if (currsize == 0)
  2162. curwin->w_cursor.col = 0;
  2163.     else
  2164.     {
  2165. curwin->w_cursor.col = currsize - 1;
  2166. (void)oneright();
  2167.     }
  2168.     changed();
  2169.     return OK;
  2170. }
  2171. /*
  2172.  * Return TRUE if the two comment leaders given are the same.  The cursor is
  2173.  * in the first line.  White-space is ignored. Note that the whole of
  2174.  * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
  2175.  */
  2176.     static int
  2177. same_leader(leader1_len, leader1_flags, leader2_len, leader2_flags)
  2178.     int     leader1_len;
  2179.     char_u  *leader1_flags;
  2180.     int     leader2_len;
  2181.     char_u  *leader2_flags;
  2182. {
  2183.     int     idx1 = 0, idx2 = 0;
  2184.     char_u  *p;
  2185.     char_u  *line1;
  2186.     char_u  *line2;
  2187.     if (leader1_len == 0)
  2188. return (leader2_len == 0);
  2189.     /*
  2190.      * If first leader has 'f' flag, the lines can be joined only if the
  2191.      * second line does not have a leader.
  2192.      * If first leader has 'e' flag, the lines can never be joined.
  2193.      * If fist leader has 's' flag, the lines can only be joined if there is
  2194.      * some text after it and the second line has the 'm' flag.
  2195.      */
  2196.     if (leader1_flags != NULL)
  2197.     {
  2198. for (p = leader1_flags; *p && *p != ':'; ++p)
  2199. {
  2200.     if (*p == COM_FIRST)
  2201. return (leader2_len == 0);
  2202.     if (*p == COM_END)
  2203. return FALSE;
  2204.     if (*p == COM_START)
  2205.     {
  2206. if (*(ml_get_curline() + leader1_len) == NUL)
  2207.     return FALSE;
  2208. if (leader2_flags == NULL || leader2_len == 0)
  2209.     return FALSE;
  2210. for (p = leader2_flags; *p && *p != ':'; ++p)
  2211.     if (*p == COM_MIDDLE)
  2212. return TRUE;
  2213. return FALSE;
  2214.     }
  2215. }
  2216.     }
  2217.     /*
  2218.      * Get current line and next line, compare the leaders.
  2219.      * The first line has to be saved, only one line can be locked at a time.
  2220.      */
  2221.     line1 = vim_strsave(ml_get_curline());
  2222.     if (line1 != NULL)
  2223.     {
  2224. for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
  2225.     ;
  2226. line2 = ml_get(curwin->w_cursor.lnum + 1);
  2227. for (idx2 = 0; idx2 < leader2_len; ++idx2)
  2228. {
  2229.     if (!vim_iswhite(line2[idx2]))
  2230.     {
  2231. if (line1[idx1++] != line2[idx2])
  2232.     break;
  2233.     }
  2234.     else
  2235. while (vim_iswhite(line1[idx1]))
  2236.     ++idx1;
  2237. }
  2238. vim_free(line1);
  2239.     }
  2240.     return (idx2 == leader2_len && idx1 == leader1_len);
  2241. }
  2242. /*
  2243.  * implementation of the format operator 'gq'
  2244.  */
  2245.     void
  2246. op_format(oap)
  2247.     OPARG *oap;
  2248. {
  2249.     long old_line_count = curbuf->b_ml.ml_line_count;
  2250.     int is_not_par; /* current line not part of parag. */
  2251.     int next_is_not_par; /* next line not part of paragraph */
  2252.     int is_end_par; /* at end of paragraph */
  2253.     int prev_is_end_par = FALSE;/* prev. line not part of parag. */
  2254.     int leader_len = 0; /* leader len of current line */
  2255.     int next_leader_len; /* leader len of next line */
  2256.     char_u *leader_flags = NULL; /* flags for leader of current line */
  2257.     char_u *next_leader_flags; /* flags for leader of next line */
  2258.     int advance = TRUE;
  2259.     int second_indent = -1;
  2260.     int do_second_indent;
  2261.     int first_par_line = TRUE;
  2262.     int smd_save;
  2263.     long count;
  2264.     int need_set_indent = TRUE; /* set indent of next paragraph */
  2265.     int force_format = FALSE;
  2266.     int max_len;
  2267.     int screenlines = -1;
  2268.     if (u_save((linenr_t)(oap->start.lnum - 1),
  2269.        (linenr_t)(oap->end.lnum + 1)) == FAIL)
  2270. return;
  2271.     /* When formatting less than a screenfull, will try to speed up redrawing
  2272.      * by inserting/deleting screen lines */
  2273.     if (oap->end.lnum - oap->start.lnum < Rows)
  2274. screenlines = plines_m(oap->start.lnum, oap->end.lnum);
  2275.     /* length of a line to force formatting: 3 * 'tw' */
  2276.     max_len = comp_textwidth(TRUE) * 3;
  2277.     /* Set '[ mark at the start of the formatted area */
  2278.     curbuf->b_op_start = oap->start;
  2279.     /* check for 'q' and '2' in 'formatoptions' */
  2280.     fo_do_comments = has_format_option(FO_Q_COMS);
  2281.     do_second_indent = has_format_option(FO_Q_SECOND);
  2282.     /*
  2283.      * Get info about the previous and current line.
  2284.      */
  2285.     if (curwin->w_cursor.lnum > 1)
  2286. is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1,
  2287.   &leader_len, &leader_flags);
  2288.     else
  2289. is_not_par = TRUE;
  2290.     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum,
  2291. &next_leader_len, &next_leader_flags);
  2292.     is_end_par = (is_not_par || next_is_not_par);
  2293.     curwin->w_cursor.lnum--;
  2294.     for (count = oap->line_count; count > 0 && !got_int; --count)
  2295.     {
  2296. /*
  2297.  * Advance to next paragraph.
  2298.  */
  2299. if (advance)
  2300. {
  2301.     curwin->w_cursor.lnum++;
  2302.     prev_is_end_par = is_end_par;
  2303.     is_not_par = next_is_not_par;
  2304.     leader_len = next_leader_len;
  2305.     leader_flags = next_leader_flags;
  2306. }
  2307. /*
  2308.  * The last line to be formatted.
  2309.  */
  2310. if (count == 1)
  2311. {
  2312.     next_is_not_par = TRUE;
  2313.     next_leader_len = 0;
  2314.     next_leader_flags = NULL;
  2315. }
  2316. else
  2317.     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1,
  2318. &next_leader_len, &next_leader_flags);
  2319. advance = TRUE;
  2320. is_end_par = (is_not_par || next_is_not_par);
  2321. /*
  2322.  * Skip lines that are not in a paragraph.
  2323.  */
  2324. if (!is_not_par)
  2325. {
  2326.     /*
  2327.      * For the first line of a paragraph, check indent of second line.
  2328.      * Don't do this for comments and empty lines.
  2329.      */
  2330.     if (first_par_line
  2331.     && do_second_indent
  2332.     && prev_is_end_par
  2333.     && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
  2334.     && leader_len == 0
  2335.     && next_leader_len == 0
  2336.     && !lineempty(curwin->w_cursor.lnum + 1))
  2337. second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
  2338.     /*
  2339.      * When the comment leader changes, it's the end of the paragraph.
  2340.      */
  2341.     if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
  2342.     || !same_leader(leader_len, leader_flags,
  2343.   next_leader_len, next_leader_flags))
  2344. is_end_par = TRUE;
  2345.     /*
  2346.      * If we have got to the end of a paragraph, or the line is
  2347.      * getting long, format it.
  2348.      */
  2349.     if (is_end_par || force_format)
  2350.     {
  2351. if (need_set_indent)
  2352.     /* replace indent in first line with minimal number of
  2353.      * tabs and spaces, according to current options */
  2354.     set_indent(get_indent(), TRUE);
  2355. /* put cursor on last non-space */
  2356. coladvance(MAXCOL);
  2357. while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
  2358.     dec_cursor();
  2359. #ifdef SYNTAX_HL
  2360. /* recompute syntax hl., starting with current line */
  2361. syn_changed(curwin->w_cursor.lnum);
  2362. #endif
  2363. /* do the formatting, without 'showmode' */
  2364. State = INSERT; /* for open_line() */
  2365. smd_save = p_smd;
  2366. p_smd = FALSE;
  2367. insertchar(NUL, TRUE, second_indent, FALSE);
  2368. State = NORMAL;
  2369. p_smd = smd_save;
  2370. second_indent = -1;
  2371. /* at end of par.: need to set indent of next par. */
  2372. need_set_indent = is_end_par;
  2373. if (is_end_par)
  2374.     first_par_line = TRUE;
  2375. force_format = FALSE;
  2376.     }
  2377.     /*
  2378.      * When still in same paragraph, join the lines together.  But
  2379.      * first delete the comment leader from the second line.
  2380.      */
  2381.     if (!is_end_par)
  2382.     {
  2383. advance = FALSE;
  2384. curwin->w_cursor.lnum++;
  2385. curwin->w_cursor.col = 0;
  2386. (void)del_chars((long)next_leader_len, FALSE);
  2387. curwin->w_cursor.lnum--;
  2388. if (do_join(TRUE, FALSE) == FAIL)
  2389. {
  2390.     beep_flush();
  2391.     break;
  2392. }
  2393. first_par_line = FALSE;
  2394. /* If the line is getting long, format it next time */
  2395. if (STRLEN(ml_get_curline()) > (size_t)max_len)
  2396.     force_format = TRUE;
  2397. else
  2398.     force_format = FALSE;
  2399.     }
  2400. }
  2401. line_breakcheck();
  2402.     }
  2403.     fo_do_comments = FALSE;
  2404.     /*
  2405.      * Try to correct the number of lines on the screen, to speed up
  2406.      * displaying.
  2407.      */
  2408.     if (screenlines > 0)
  2409.     {
  2410. screenlines -= plines_m(oap->start.lnum, curwin->w_cursor.lnum);
  2411. if (screenlines > 0)
  2412.     win_del_lines(curwin, curwin->w_cline_row, screenlines,
  2413.  FALSE, TRUE);
  2414. else if (screenlines < 0)
  2415.     win_ins_lines(curwin, curwin->w_cline_row, screenlines,
  2416.  FALSE, TRUE);
  2417.     }
  2418.     /*
  2419.      * Leave the cursor at the first non-blank of the last formatted line.
  2420.      * If the cursor was moved one line back (e.g. with "Q}") go to the next
  2421.      * line, so "." will do the next lines.
  2422.      */
  2423.     if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  2424. ++curwin->w_cursor.lnum;
  2425.     beginline(BL_WHITE | BL_FIX);
  2426.     update_screen(NOT_VALID);
  2427.     msgmore(curbuf->b_ml.ml_line_count - old_line_count);
  2428.     /* put '] mark on the end of the formatted area */
  2429.     curbuf->b_op_end = curwin->w_cursor;
  2430. }
  2431. /*
  2432.  * Blank lines, and lines containing only the comment leader, are left
  2433.  * untouched by the formatting.  The function returns TRUE in this
  2434.  * case.  It also returns TRUE when a line starts with the end of a comment
  2435.  * ('e' in comment flags), so that this line is skipped, and not joined to the
  2436.  * previous line.  A new paragraph starts after a blank line, or when the
  2437.  * comment leader changes -- webb.
  2438.  */
  2439.     static int
  2440. fmt_check_par(lnum, leader_len, leader_flags)
  2441.     linenr_t lnum;
  2442.     int *leader_len;
  2443.     char_u **leader_flags;
  2444. {
  2445.     char_u *flags = NULL;     /* init for GCC */
  2446.     char_u *ptr;
  2447.     ptr = ml_get(lnum);
  2448.     *leader_len = get_leader_len(ptr, leader_flags);
  2449.     if (*leader_len > 0)
  2450.     {
  2451. /*
  2452.  * Search for 'e' flag in comment leader flags.
  2453.  */
  2454. flags = *leader_flags;
  2455. while (*flags && *flags != ':' && *flags != COM_END)
  2456.     ++flags;
  2457.     }
  2458.     return (ptr[*leader_len] == NUL ||
  2459.     (*leader_len > 0 && *flags == COM_END) ||
  2460.      startPS(lnum, NUL, FALSE));
  2461. }
  2462. /*
  2463.  * prepare a few things for block mode yank/delete/tilde
  2464.  *
  2465.  * for delete:
  2466.  * - textlen includes the first/last char to be (partly) deleted
  2467.  * - start/endspaces is the number of columns that are taken by the
  2468.  *   first/last deleted char minus the number of columns that have to be
  2469.  *   deleted.  for yank and tilde:
  2470.  * - textlen includes the first/last char to be wholly yanked
  2471.  * - start/endspaces is the number of columns of the first/last yanked char
  2472.  *   that are to be yanked.
  2473.  */
  2474.     static void
  2475. block_prep(oap, bd, lnum, is_del)
  2476.     OPARG *oap;
  2477.     struct block_def *bd;
  2478.     linenr_t lnum;
  2479.     int is_del;
  2480. {
  2481.     colnr_t vcol;
  2482.     int incr = 0;
  2483.     char_u *pend;
  2484.     char_u *pstart;
  2485.     bd->startspaces = 0;
  2486.     bd->endspaces = 0;
  2487.     bd->textlen = 0;
  2488.     bd->textcol = 0;
  2489.     vcol = 0;
  2490.     pstart = ml_get(lnum);
  2491.     while (vcol < oap->start_vcol && *pstart)
  2492.     {
  2493. /* Count a tab for what it's worth (if list mode not on) */
  2494. incr = lbr_chartabsize(pstart, (colnr_t)vcol);
  2495. vcol += incr;
  2496. ++pstart;
  2497. ++bd->textcol;
  2498.     }
  2499.     if (vcol < oap->start_vcol) /* line too short */
  2500.     {
  2501. if (!is_del)
  2502.     bd->endspaces = oap->end_vcol - oap->start_vcol + 1;
  2503.     }
  2504.     else /* vcol >= oap->start_vcol */
  2505.     {
  2506. bd->startspaces = vcol - oap->start_vcol;
  2507. if (is_del && vcol > oap->start_vcol)
  2508.     bd->startspaces = incr - bd->startspaces;
  2509. pend = pstart;
  2510. if (vcol > oap->end_vcol) /* it's all in one character */
  2511. {
  2512.     bd->startspaces = oap->end_vcol - oap->start_vcol + 1;
  2513.     if (is_del)
  2514. bd->startspaces = incr - bd->startspaces;
  2515. }
  2516. else
  2517. {
  2518.     while (vcol <= oap->end_vcol && *pend)
  2519.     {
  2520. /* Count a tab for what it's worth (if list mode not on) */
  2521. incr = lbr_chartabsize(pend, (colnr_t)vcol);
  2522. vcol += incr;
  2523. ++pend;
  2524.     }
  2525.     if (vcol < oap->end_vcol && !is_del)    /* line too short */
  2526.     {
  2527. bd->endspaces = oap->end_vcol - vcol;
  2528.     }
  2529.     else if (vcol > oap->end_vcol)
  2530.     {
  2531. bd->endspaces = vcol - oap->end_vcol - 1;
  2532. if (!is_del && pend != pstart && bd->endspaces)
  2533.     --pend;
  2534.     }
  2535. }
  2536. if (is_del && bd->startspaces)
  2537. {
  2538.     --pstart;
  2539.     --bd->textcol;
  2540. }
  2541. bd->textlen = (int)(pend - pstart);
  2542.     }
  2543.     bd->textstart = pstart;
  2544. }
  2545. #ifdef RIGHTLEFT
  2546. static void reverse_line __ARGS((char_u *s));
  2547.     static void
  2548. reverse_line(s)
  2549.     char_u *s;
  2550. {
  2551.     int     i, j;
  2552.     char_u  c;
  2553.     if ((i = STRLEN(s) - 1) <= 0)
  2554. return;
  2555.     curwin->w_cursor.col = i - curwin->w_cursor.col;
  2556.     for (j = 0; j < i; j++, i--)
  2557.     {
  2558. c = s[i]; s[i] = s[j]; s[j] = c;
  2559.     }
  2560. }
  2561. # define RLADDSUBFIX() if (curwin->w_p_rl) reverse_line(ptr);
  2562. #else
  2563. # define RLADDSUBFIX()
  2564. #endif
  2565. /*
  2566.  * add or subtract 'Prenum1' from a number in a line
  2567.  * 'command' is CTRL-A for add, CTRL-X for subtract
  2568.  *
  2569.  * return FAIL for failure, OK otherwise
  2570.  */
  2571.     int
  2572. do_addsub(command, Prenum1)
  2573.     int command;
  2574.     linenr_t Prenum1;
  2575. {
  2576.     int     col;
  2577.     char_u     buf1[NUMBUFLEN];
  2578.     char_u     buf2[NUMBUFLEN];
  2579.     int     hex; /* 'X' or 'x': hex; '0': octal */
  2580.     static int     hexupper = FALSE; /* 0xABC */
  2581.     unsigned long   n;
  2582.     unsigned long   oldn;
  2583.     char_u     *ptr;
  2584.     int     c;
  2585.     int     length = 0; /* character length of the number */
  2586.     int     todel;
  2587.     int     dohex;
  2588.     int     dooct;
  2589.     int     firstdigit;
  2590.     int     negative;
  2591.     int     subtract;
  2592.     dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL);
  2593.     dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL);
  2594.     ptr = ml_get_curline();
  2595.     RLADDSUBFIX();
  2596.     /*
  2597.      * First check if we are on a hexadecimal number, after the "0x".
  2598.      */
  2599.     col = curwin->w_cursor.col;
  2600.     if (dohex)
  2601. while (col > 0 && isxdigit(ptr[col]))
  2602.     --col;
  2603.     if (       dohex
  2604.     && col > 0
  2605.     && (ptr[col] == 'X'
  2606. || ptr[col] == 'x')
  2607.     && ptr[col - 1] == '0'
  2608.     && isxdigit(ptr[col + 1]))
  2609.     {
  2610. /*
  2611.  * Found hexadecimal number, move to its start.
  2612.  */
  2613. --col;
  2614.     }
  2615.     else
  2616.     {
  2617. /*
  2618.  * Search forward and then backward to find the start of number.
  2619.  */
  2620. col = curwin->w_cursor.col;
  2621. while (ptr[col] != NUL && !isdigit(ptr[col]))
  2622.     ++col;
  2623. while (col > 0 && isdigit(ptr[col - 1]))
  2624.     --col;
  2625.     }
  2626.     /*
  2627.      * If a number was found, and saving for undo works, replace the number.
  2628.      */
  2629.     firstdigit = ptr[col];
  2630.     RLADDSUBFIX();
  2631.     if (!isdigit(firstdigit) || u_save_cursor() != OK)
  2632.     {
  2633. beep_flush();
  2634. return FAIL;
  2635.     }
  2636.     /* get ptr again, because u_save() may have changed it */
  2637.     ptr = ml_get_curline();
  2638.     RLADDSUBFIX();
  2639.     negative = FALSE;
  2640.     if (col > 0 && ptr[col - 1] == '-')     /* negative number */
  2641.     {
  2642. --col;
  2643. negative = TRUE;
  2644.     }
  2645.     /* get the number value (unsigned) */
  2646.     vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
  2647.     /* ignore leading '-' for hex and octal numbers */
  2648.     if (hex && negative)
  2649.     {
  2650. ++col;
  2651. --length;
  2652. negative = FALSE;
  2653.     }
  2654.     /* add or subtract */
  2655.     subtract = FALSE;
  2656.     if (command == Ctrl('X'))
  2657. subtract ^= TRUE;
  2658.     if (negative)
  2659. subtract ^= TRUE;
  2660.     oldn = n;
  2661.     if (subtract)
  2662. n -= (unsigned long)Prenum1;
  2663.     else
  2664. n += (unsigned long)Prenum1;
  2665.     /* handle wraparound for decimal numbers */
  2666.     if (!hex)
  2667.     {
  2668. if (subtract)
  2669. {
  2670.     if (n > oldn)
  2671.     {
  2672. n = 1 + (n ^ (unsigned long)-1);
  2673. negative ^= TRUE;
  2674.     }
  2675. }
  2676. else /* add */
  2677. {
  2678.     if (n < oldn)
  2679.     {
  2680. n = (n ^ (unsigned long)-1);
  2681. negative ^= TRUE;
  2682.     }
  2683. }
  2684. if (n == 0)
  2685.     negative = FALSE;
  2686.     }
  2687.     /*
  2688.      * Delete the old number.
  2689.      */
  2690.     curwin->w_cursor.col = col;
  2691.     todel = length;
  2692.     c = gchar_cursor();
  2693.     /*
  2694.      * Don't include the '-' in the length, only the length of the part
  2695.      * after it is kept the same.
  2696.      */
  2697.     if (c == '-')
  2698. --length;
  2699.     while (todel-- > 0)
  2700.     {
  2701. if (isalpha(c))
  2702. {
  2703.     if (isupper(c))
  2704. hexupper = TRUE;
  2705.     else
  2706. hexupper = FALSE;
  2707. }
  2708. (void)del_char(FALSE);
  2709. c = gchar_cursor();
  2710.     }
  2711.     /*
  2712.      * Prepare the leading characters in buf1[].
  2713.      */
  2714.     ptr = buf1;
  2715.     if (negative)
  2716.     {
  2717. *ptr++ = '-';
  2718.     }
  2719.     if (hex)
  2720.     {
  2721. *ptr++ = '0';
  2722. --length;
  2723.     }
  2724.     if (hex == 'x' || hex == 'X')
  2725.     {
  2726. *ptr++ = hex;
  2727. --length;
  2728.     }
  2729.     /*
  2730.      * Put the number characters in buf2[].
  2731.      */
  2732.     if (hex == 0)
  2733. sprintf((char *)buf2, "%lu", n);
  2734.     else if (hex == '0')
  2735. sprintf((char *)buf2, "%lo", n);
  2736.     else if (hex && hexupper)
  2737. sprintf((char *)buf2, "%lX", n);
  2738.     else
  2739. sprintf((char *)buf2, "%lx", n);
  2740.     length -= STRLEN(buf2);
  2741.     /*
  2742.      * adjust number of zeros to the new number of digits, so the
  2743.      * total length of the number remains the same
  2744.      */
  2745.     if (firstdigit == '0')
  2746. while (length-- > 0)
  2747.     *ptr++ = '0';
  2748.     *ptr = NUL;
  2749.     STRCAT(buf1, buf2);
  2750.     ins_str(buf1);     /* insert the new number */
  2751.     --curwin->w_cursor.col;
  2752.     curwin->w_set_curswant = TRUE;
  2753. #ifdef RIGHTLEFT
  2754.     ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
  2755.     RLADDSUBFIX();
  2756. #endif
  2757.     update_screenline();
  2758.     return OK;
  2759. }
  2760. #ifdef VIMINFO
  2761.     int
  2762. read_viminfo_register(line, fp, force)
  2763.     char_u  *line;
  2764.     FILE    *fp;
  2765.     int     force;
  2766. {
  2767.     int     eof;
  2768.     int     do_it = TRUE;
  2769.     int     size;
  2770.     int     limit;
  2771.     int     i;
  2772.     int     set_prev = FALSE;
  2773.     char_u  *str;
  2774.     char_u  **array = NULL;
  2775.     /* We only get here (hopefully) if line[0] == '"' */
  2776.     str = line + 1;
  2777.     if (*str == '"')
  2778.     {
  2779. set_prev = TRUE;
  2780. str++;
  2781.     }
  2782.     if (!isalnum(*str) && *str != '-')
  2783.     {
  2784. if (viminfo_error("Illegal register name", line))
  2785.     return TRUE; /* too many errors, pretend end-of-file */
  2786. do_it = FALSE;
  2787.     }
  2788.     get_yank_register(*str++, FALSE);
  2789.     if (!force && y_current->y_array != NULL)
  2790. do_it = FALSE;
  2791.     size = 0;
  2792.     limit = 100; /* Optimized for registers containing <= 100 lines */
  2793.     if (do_it)
  2794.     {
  2795. if (set_prev)
  2796.     y_previous = y_current;
  2797. vim_free(y_current->y_array);
  2798. array = y_current->y_array =
  2799.        (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
  2800. str = skipwhite(str);
  2801. if (STRNCMP(str, "CHAR", 4) == 0)
  2802.     y_current->y_type = MCHAR;
  2803. else if (STRNCMP(str, "BLOCK", 5) == 0)
  2804.     y_current->y_type = MBLOCK;
  2805. else
  2806.     y_current->y_type = MLINE;
  2807.     }
  2808.     while (!(eof = vim_fgets(line, LSIZE, fp)) && line[0] == TAB)
  2809.     {
  2810. if (do_it)
  2811. {
  2812.     if (size >= limit)
  2813.     {
  2814. y_current->y_array = (char_u **)
  2815.       alloc((unsigned)(limit * 2 * sizeof(char_u *)));
  2816. for (i = 0; i < limit; i++)
  2817.     y_current->y_array[i] = array[i];
  2818. vim_free(array);
  2819. limit *= 2;
  2820. array = y_current->y_array;
  2821.     }
  2822.     viminfo_readstring(line);
  2823.     str = vim_strsave(line + 1);
  2824.     if (str != NULL)
  2825. array[size++] = str;
  2826.     else
  2827. do_it = FALSE;
  2828. }
  2829.     }
  2830.     if (do_it)
  2831.     {
  2832. if (size == 0)
  2833. {
  2834.     vim_free(array);
  2835.     y_current->y_array = NULL;
  2836. }
  2837. else if (size < limit)
  2838. {
  2839.     y_current->y_array =
  2840. (char_u **)alloc((unsigned)(size * sizeof(char_u *)));
  2841.     for (i = 0; i < size; i++)
  2842. y_current->y_array[i] = array[i];
  2843.     vim_free(array);
  2844. }
  2845. y_current->y_size = size;
  2846.     }
  2847.     return eof;
  2848. }
  2849.     void
  2850. write_viminfo_registers(fp)
  2851.     FILE    *fp;
  2852. {
  2853.     int     i, j;
  2854.     char_u  *type;
  2855.     char_u  c;
  2856.     int     num_lines;
  2857.     int     max_num_lines;
  2858.     fprintf(fp, "n# Registers:n");
  2859.     max_num_lines = get_viminfo_parameter('"');
  2860.     if (max_num_lines == 0)
  2861. return;
  2862.     for (i = 0; i < NUM_REGISTERS; i++)
  2863.     {
  2864. if (y_regs[i].y_array == NULL)
  2865.     continue;
  2866. #ifdef USE_CLIPBOARD
  2867. /* Skip '*' register, we don't want it back next time */
  2868. if (i == CLIPBOARD_REGISTER)
  2869.     continue;
  2870. #endif
  2871. switch (y_regs[i].y_type)
  2872. {
  2873.     case MLINE:
  2874. type = (char_u *)"LINE";
  2875. break;
  2876.     case MCHAR:
  2877. type = (char_u *)"CHAR";
  2878. break;
  2879.     case MBLOCK:
  2880. type = (char_u *)"BLOCK";
  2881. break;
  2882.     default:
  2883. sprintf((char *)IObuff, "Unknown register type %d",
  2884.     y_regs[i].y_type);
  2885. emsg(IObuff);
  2886. type = (char_u *)"LINE";
  2887. break;
  2888. }
  2889. if (y_previous == &y_regs[i])
  2890.     fprintf(fp, """);
  2891. if (i == DELETION_REGISTER)
  2892.     c = '-';
  2893. else if (i < 10)
  2894.     c = '0' + i;
  2895. else
  2896.     c = 'a' + i - 10;
  2897. fprintf(fp, ""%ct%sn", c, type);
  2898. num_lines = y_regs[i].y_size;
  2899. /* If max_num_lines < 0, then we save ALL the lines in the register */
  2900. if (max_num_lines > 0 && num_lines > max_num_lines)
  2901.     num_lines = max_num_lines;
  2902. for (j = 0; j < num_lines; j++)
  2903. {
  2904.     putc('t', fp);
  2905.     viminfo_writestring(fp, y_regs[i].y_array[j]);
  2906. }
  2907.     }
  2908. }
  2909. #endif /* VIMINFO */
  2910. #if defined(USE_CLIPBOARD) || defined(PROTO)
  2911. /*
  2912.  * Text selection stuff that uses the GUI selection register '*'.  When using a
  2913.  * GUI this may be text from another window, otherwise it is the last text we
  2914.  * had highlighted with VIsual mode.  With mouse support, clicking the middle
  2915.  * button performs the paste, otherwise you will need to do <"*p>.
  2916.  */
  2917.     void
  2918. clip_free_selection()
  2919. {
  2920.     struct yankreg *y_ptr = y_current;
  2921.     y_current = &y_regs[CLIPBOARD_REGISTER];     /* '*' register */
  2922.     free_yank_all();
  2923.     y_current->y_size = 0;
  2924.     y_current = y_ptr;
  2925. }
  2926. /*
  2927.  * Get the selected text and put it in the gui text register '*'.
  2928.  */
  2929.     void
  2930. clip_get_selection()
  2931. {
  2932.     struct yankreg *old_y_previous, *old_y_current;
  2933.     FPOS    old_cursor, old_visual;
  2934.     int     old_visual_mode;
  2935.     colnr_t old_curswant;
  2936.     int     old_set_curswant;
  2937.     OPARG   oa;
  2938.     CMDARG  ca;
  2939.     if (clipboard.owned)
  2940.     {
  2941. if (y_regs[CLIPBOARD_REGISTER].y_array != NULL)
  2942.     return;
  2943. /* Get the text between clipboard.start & clipboard.end */
  2944. old_y_previous = y_previous;
  2945. old_y_current = y_current;
  2946. old_cursor = curwin->w_cursor;
  2947. old_curswant = curwin->w_curswant;
  2948. old_set_curswant = curwin->w_set_curswant;
  2949. old_visual = VIsual;
  2950. old_visual_mode = VIsual_mode;
  2951. clear_oparg(&oa);
  2952. oa.regname = '*';
  2953. oa.op_type = OP_YANK;
  2954. vim_memset(&ca, 0, sizeof(ca));
  2955. ca.oap = &oa;
  2956. ca.cmdchar = 'y';
  2957. ca.count1 = 1;
  2958. do_pending_operator(&ca, NULL, NULL, 0, TRUE, TRUE);
  2959. y_previous = old_y_previous;
  2960. y_current = old_y_current;
  2961. curwin->w_cursor = old_cursor;
  2962. curwin->w_curswant = old_curswant;
  2963. curwin->w_set_curswant = old_set_curswant;
  2964. VIsual = old_visual;
  2965. VIsual_mode = old_visual_mode;
  2966.     }
  2967.     else
  2968.     {
  2969. clip_free_selection();
  2970. /* Try to get selected text from another window */
  2971. clip_mch_request_selection();
  2972.     }
  2973. }
  2974. /* Convert from the GUI selection string into the '*' register */
  2975.     void
  2976. clip_yank_selection(type, str, len)
  2977.     int     type;
  2978.     char_u  *str;
  2979.     long    len;
  2980. {
  2981.     struct yankreg *y_ptr = &y_regs[CLIPBOARD_REGISTER];    /* '*' register */
  2982.     clip_free_selection();
  2983.     str_to_reg(y_ptr, type, str, len);
  2984. }
  2985. /*
  2986.  * Convert the '*' register into a GUI selection string returned in *str with
  2987.  * length *len.
  2988.  */
  2989.     int
  2990. clip_convert_selection(str, len)
  2991.     char_u  **str;
  2992.     long_u  *len;
  2993. {
  2994.     struct yankreg *y_ptr = &y_regs[CLIPBOARD_REGISTER];    /* '*' register */
  2995.     char_u  *p;
  2996.     int     lnum;
  2997.     int     i, j;
  2998.     int_u   eolsize;
  2999. #ifdef USE_CRNL
  3000.     eolsize = 2;
  3001. #else
  3002.     eolsize = 1;
  3003. #endif
  3004.     *str = NULL;
  3005.     *len = 0;
  3006.     if (y_ptr->y_array == NULL)
  3007. return -1;
  3008.     for (i = 0; i < y_ptr->y_size; i++)
  3009. *len += STRLEN(y_ptr->y_array[i]) + eolsize;
  3010.     /*
  3011.      * Don't want newline character at end of last line if we're in MCHAR mode.
  3012.      */
  3013.     if (y_ptr->y_type == MCHAR && *len > eolsize)
  3014. *len -= eolsize;
  3015.     p = *str = lalloc(*len, TRUE);
  3016.     if (p == NULL)
  3017. return -1;
  3018.     lnum = 0;
  3019.     for (i = 0, j = 0; i < (int)*len; i++, j++)
  3020.     {
  3021. if (y_ptr->y_array[lnum][j] == 'n')
  3022.     p[i] = NUL;
  3023. else if (y_ptr->y_array[lnum][j] == NUL)
  3024. {
  3025. #ifdef USE_CRNL
  3026.     p[i++] = 'r';
  3027. #endif
  3028. #ifdef USE_CR
  3029.     p[i] = 'r';
  3030. #else
  3031.     p[i] = 'n';
  3032. #endif
  3033.     lnum++;
  3034.     j = -1;
  3035. }
  3036. else
  3037.     p[i] = y_ptr->y_array[lnum][j];
  3038.     }
  3039.     return y_ptr->y_type;
  3040. }
  3041. #endif /* USE_CLIPBOARD || PROTO */
  3042. #ifdef WANT_EVAL
  3043. /*
  3044.  * Return the contents of a register as a single allocated string.
  3045.  * Used for "@r" in expressions.
  3046.  * Returns NULL for error.
  3047.  */
  3048.     char_u *
  3049. get_reg_contents(regname)
  3050.     int     regname;
  3051. {
  3052.     long    i;
  3053.     char_u  *retval;
  3054.     int     allocated;
  3055.     long    len;
  3056.     /* Don't allow using an expression register inside an expression */
  3057.     if (regname == '=')
  3058. return NULL;
  3059.     if (regname == '@')     /* "@@" is used for unnamed register */
  3060. regname = '"';
  3061.     /* check for valid regname */
  3062.     if (regname != NUL && !valid_yank_reg(regname, FALSE))
  3063. return NULL;
  3064. #ifdef USE_CLIPBOARD
  3065.     if (regname == '*')
  3066. clip_get_selection(); /* may fill * register */
  3067. #endif
  3068.     if (get_spec_reg(regname, &retval, &allocated, FALSE))
  3069.     {
  3070. if (retval == NULL)
  3071.     return NULL;
  3072. if (!allocated)
  3073.     retval = vim_strsave(retval);
  3074. return retval;
  3075.     }
  3076.     get_yank_register(regname, FALSE);
  3077.     if (y_current->y_array == NULL)
  3078. return NULL;
  3079.     /*
  3080.      * Compute length of resulting string.
  3081.      */
  3082.     len = 0;
  3083.     for (i = 0; i < y_current->y_size; ++i)
  3084.     {
  3085. len += STRLEN(y_current->y_array[i]);
  3086. /*
  3087.  * Insert a newline between lines and after last line if
  3088.  * y_type is MLINE.
  3089.  */
  3090. if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  3091.     ++len;
  3092.     }
  3093.     retval = lalloc(len + 1, TRUE);
  3094.     /*
  3095.      * Copy the lines of the yank register into the string.
  3096.      */
  3097.     if (retval != NULL)
  3098.     {
  3099. len = 0;
  3100. for (i = 0; i < y_current->y_size; ++i)
  3101. {
  3102.     STRCPY(retval + len, y_current->y_array[i]);
  3103.     len += STRLEN(retval + len);
  3104.     /*
  3105.      * Insert a NL between lines and after the last line if y_type is
  3106.      * MLINE.
  3107.      */
  3108.     if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  3109. retval[len++] = 'n';
  3110. }
  3111. retval[len] = NUL;
  3112.     }
  3113.     return retval;
  3114. }
  3115. /*
  3116.  * Store string 'str' in register 'name'.
  3117.  * Careful: 'str' is modified, you may have to use a copy!
  3118.  * If 'str' ends in 'n' or 'r', use linewise, otherwise use characterwise.
  3119.  */
  3120.     void
  3121. write_reg_contents(name, str)
  3122.     int     name;
  3123.     char_u  *str;
  3124. {
  3125.     struct yankreg  *old_y_previous, *old_y_current;
  3126.     long     len;
  3127.     if (!valid_yank_reg(name, TRUE))     /* check for valid reg name */
  3128.     {
  3129. EMSG2("Invalid register name: '%s'", transchar(name));
  3130. return;
  3131.     }
  3132.     if (name == '_')     /* black hole: nothing to do */
  3133. return;
  3134.     /* Don't want to change the current (unnamed) register */
  3135.     old_y_previous = y_previous;
  3136.     old_y_current = y_current;
  3137.     get_yank_register(name, TRUE);
  3138.     if (!y_append)
  3139. free_yank_all();
  3140.     len = STRLEN(str);
  3141.     str_to_reg(y_current,
  3142.     (len > 0 && (str[len - 1] == 'n' || str[len -1] == 'r'))
  3143.      ? MLINE : MCHAR, str, len);
  3144.     y_previous = old_y_previous;
  3145.     y_current = old_y_current;
  3146. }
  3147. #endif /* WANT_EVAL */
  3148. #if defined(USE_CLIPBOARD) || defined(WANT_EVAL)
  3149. /*
  3150.  * Put a string into a register.  When the register is not empty, the string
  3151.  * is appended.
  3152.  */
  3153.     static void
  3154. str_to_reg(y_ptr, type, str, len)
  3155.     struct yankreg *y_ptr; /* pointer to yank register */
  3156.     int type; /* MCHAR or MLINE */
  3157.     char_u *str; /* string to put in register */
  3158.     long len; /* lenght of string */
  3159. {
  3160.     int     lnum;
  3161.     long    start;
  3162.     long    i;
  3163.     int     extra;
  3164.     int     newlines; /* number of lines added */
  3165.     int     extraline = 0; /* extra line at the end */
  3166.     int     append = FALSE; /* append to last line in register */
  3167.     char_u  *s;
  3168.     char_u  **pp;
  3169.     if (y_ptr->y_array == NULL) /* NULL means emtpy register */
  3170. y_ptr->y_size = 0;
  3171.     /*
  3172.      * Count the number of lines within the string
  3173.      */
  3174.     newlines = 0;
  3175.     for (i = 0; i < len; i++)
  3176. if (str[i] == 'n')
  3177.     ++newlines;
  3178.     if (type == MCHAR || len == 0 || str[len - 1] != 'n')
  3179.     {
  3180. extraline = 1;
  3181. ++newlines; /* count extra newline at the end */
  3182.     }
  3183.     if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
  3184.     {
  3185. append = TRUE;
  3186. --newlines; /* uncount newline when appending first line */
  3187.     }
  3188.     /*
  3189.      * Allocate an array to hold the pointers to the new register lines.
  3190.      * If the register was not empty, move the existing lines to the new array.
  3191.      */
  3192.     pp = (char_u **)lalloc_clear((y_ptr->y_size + newlines)
  3193.     * sizeof(char_u *), TRUE);
  3194.     if (pp == NULL) /* out of memory */
  3195. return;
  3196.     for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
  3197. pp[lnum] = y_ptr->y_array[lnum];
  3198.     vim_free(y_ptr->y_array);
  3199.     y_ptr->y_array = pp;
  3200.     /*
  3201.      * Find the end of each line and save it into the array.
  3202.      */
  3203.     for (start = 0; start < len + extraline; start += i + 1)
  3204.     {
  3205. for (i = start; i < len; ++i) /* find the end of the line */
  3206.     if (str[i] == 'n')
  3207. break;
  3208. i -= start; /* i is now length of line */
  3209. if (append)
  3210. {
  3211.     --lnum;
  3212.     extra = STRLEN(y_ptr->y_array[lnum]);
  3213. }
  3214. else
  3215.     extra = 0;
  3216. s = alloc((unsigned)(i + extra + 1));
  3217. if (s == NULL)
  3218.     break;
  3219. if (extra)
  3220. {
  3221.     mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
  3222.     vim_free(y_ptr->y_array[lnum]);
  3223. }
  3224. if (i)
  3225.     mch_memmove(s + extra, str + start, (size_t)i);
  3226. extra += i;
  3227. s[extra] = NUL;
  3228. y_ptr->y_array[lnum++] = s;
  3229. while (--extra >= 0)
  3230. {
  3231.     if (*s == NUL)
  3232. *s = 'n';     /* replace NUL with newline */
  3233.     ++s;
  3234. }
  3235. append = FALSE;     /* only first line is appended */
  3236.     }
  3237.     y_ptr->y_type = type;
  3238.     y_ptr->y_size = lnum;
  3239. }
  3240. #endif /* USE_CLIPBOARD || WANT_EVAL || PROTO */
  3241.     void
  3242. clear_oparg(oap)
  3243.     OPARG *oap;
  3244. {
  3245.     vim_memset(oap, 0, sizeof(OPARG));
  3246. }