home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / ops.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-23  |  140.3 KB  |  5,885 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * ops.c: implementation of various operators: op_shift, op_delete, op_tilde,
  12.  *      op_change, op_yank, do_put, do_join
  13.  */
  14.  
  15. #include "vim.h"
  16.  
  17. /*
  18.  * Number of registers.
  19.  *    0 = unnamed register, for normal yanks and puts
  20.  *   1..9 = registers '1' to '9', for deletes
  21.  * 10..35 = registers 'a' to 'z'
  22.  *     36 = delete register '-'
  23.  *     37 = Selection register '*'. Only if FEAT_CLIPBOARD defined
  24.  *     38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined
  25.  */
  26. /*
  27.  * Symbolic names for some registers.
  28.  */
  29. #define DELETION_REGISTER    36
  30. #ifdef FEAT_CLIPBOARD
  31. # define STAR_REGISTER        37
  32. #  ifdef FEAT_X11
  33. #   define PLUS_REGISTER    38
  34. #  else
  35. #   define PLUS_REGISTER    STAR_REGISTER        /* there is only one */
  36. #  endif
  37. #endif
  38. #ifdef FEAT_DND
  39. # define TILDE_REGISTER        (PLUS_REGISTER + 1)
  40. #endif
  41.  
  42. #ifdef FEAT_CLIPBOARD
  43. # ifdef FEAT_DND
  44. #  define NUM_REGISTERS        (TILDE_REGISTER + 1)
  45. # else
  46. #  define NUM_REGISTERS        (PLUS_REGISTER + 1)
  47. # endif
  48. #else
  49. # define NUM_REGISTERS        37
  50. #endif
  51.  
  52. /*
  53.  * Each yank register is an array of pointers to lines.
  54.  */
  55. static struct yankreg
  56. {
  57.     char_u    **y_array;    /* pointer to array of line pointers */
  58.     linenr_T    y_size;        /* number of lines in y_array */
  59.     char_u    y_type;        /* MLINE, MCHAR or MBLOCK */
  60. #ifdef FEAT_VISUAL
  61.     colnr_T    y_width;    /* only set if y_type == MBLOCK */
  62. #endif
  63. } y_regs[NUM_REGISTERS];
  64.  
  65. static struct yankreg    *y_current;        /* ptr to current yankreg */
  66. static int        y_append;        /* TRUE when appending */
  67. static struct yankreg    *y_previous = NULL; /* ptr to last written yankreg */
  68.  
  69. /*
  70.  * structure used by block_prep, op_delete and op_yank for blockwise operators
  71.  * also op_change, op_shift, op_insert, op_replace - AKelly
  72.  */
  73. struct block_def
  74. {
  75.     int        startspaces;    /* 'extra' cols of first char */
  76.     int        endspaces;    /* 'extra' cols of first char */
  77.     int        textlen;    /* chars in block */
  78.     char_u    *textstart;    /* pointer to 1st char in block */
  79.     colnr_T    textcol;    /* cols of chars (at least part.) in block */
  80.     colnr_T    start_vcol;    /* start col of 1st char wholly inside block */
  81.     colnr_T    end_vcol;    /* start col of 1st char wholly after block */
  82. #ifdef FEAT_VISUALEXTRA
  83.     int        is_short;    /* TRUE if line is too short to fit in block */
  84.     int        is_MAX;        /* TRUE if curswant==MAXCOL when starting */
  85.     int        is_oneChar;    /* TRUE if block within one character */
  86.     int        pre_whitesp;    /* screen cols of ws before block */
  87.     int        pre_whitesp_c;    /* chars of ws before block */
  88.     colnr_T    end_char_vcols;    /* number of vcols of post-block char */
  89. #endif
  90.     colnr_T    start_char_vcols; /* number of vcols of pre-block char */
  91. };
  92.  
  93. #ifdef FEAT_VISUALEXTRA
  94. static void shift_block __ARGS((oparg_T *oap, int amount));
  95. static void block_insert __ARGS((oparg_T *oap, char_u *s, int b_insert, struct block_def*bdp));
  96. #endif
  97. #ifdef FEAT_EVAL
  98. static char_u    *get_expr_line __ARGS((void));
  99. #endif
  100. static void    get_yank_register __ARGS((int regname, int writing));
  101. static int    stuff_yank __ARGS((int, char_u *));
  102. static int    put_in_typebuf __ARGS((char_u *s, int colon));
  103. static void    stuffescaped __ARGS((char_u *arg, int literally));
  104. static int    get_spec_reg __ARGS((int regname, char_u **argp, int *allocated, int errmsg));
  105. static void    cmdline_paste_str __ARGS((char_u *s, int literally));
  106. #ifdef FEAT_MBYTE
  107. static void    mb_adjust_opend __ARGS((oparg_T *oap));
  108. #endif
  109. static void    free_yank __ARGS((long));
  110. static void    free_yank_all __ARGS((void));
  111. static int    yank_copy_line __ARGS((struct block_def *bd, long y_idx));
  112. #ifdef FEAT_CLIPBOARD
  113. static void    copy_yank_reg __ARGS((struct yankreg *reg));
  114. # if defined(FEAT_VISUAL) || defined(FEAT_EVAL)
  115. static void    may_set_selection __ARGS((void));
  116. # endif
  117. #endif
  118. static void    dis_msg __ARGS((char_u *p, int skip_esc));
  119. #ifdef FEAT_VISUAL
  120. static void    block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int));
  121. #endif
  122. #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
  123. static void    str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen));
  124. #endif
  125. static int    ends_in_white __ARGS((linenr_T lnum));
  126. #ifdef FEAT_COMMENTS
  127. static int    same_leader __ARGS((int, char_u *, int, char_u *));
  128. static int    fmt_check_par __ARGS((linenr_T, int *, char_u **, int do_comments));
  129. #else
  130. static int    fmt_check_par __ARGS((linenr_T));
  131. #endif
  132.  
  133. /*
  134.  * The names of operators.
  135.  * IMPORTANT: Index must correspond with defines in vim.h!!!
  136.  * The third field indicates whether the operator always works on lines.
  137.  */
  138. static char opchars[][3] =
  139. {
  140.     {NUL, NUL, FALSE},    /* OP_NOP */
  141.     {'d', NUL, FALSE},    /* OP_DELETE */
  142.     {'y', NUL, FALSE},    /* OP_YANK */
  143.     {'c', NUL, FALSE},    /* OP_CHANGE */
  144.     {'<', NUL, TRUE},    /* OP_LSHIFT */
  145.     {'>', NUL, TRUE},    /* OP_RSHIFT */
  146.     {'!', NUL, TRUE},    /* OP_FILTER */
  147.     {'g', '~', FALSE},    /* OP_TILDE */
  148.     {'=', NUL, TRUE},    /* OP_INDENT */
  149.     {'g', 'q', TRUE},    /* OP_FORMAT */
  150.     {':', NUL, TRUE},    /* OP_COLON */
  151.     {'g', 'U', FALSE},    /* OP_UPPER */
  152.     {'g', 'u', FALSE},    /* OP_LOWER */
  153.     {'J', NUL, TRUE},    /* DO_JOIN */
  154.     {'g', 'J', TRUE},    /* DO_JOIN_NS */
  155.     {'g', '?', FALSE},    /* OP_ROT13 */
  156.     {'r', NUL, FALSE},    /* OP_REPLACE */
  157.     {'I', NUL, FALSE},    /* OP_INSERT */
  158.     {'A', NUL, FALSE},    /* OP_APPEND */
  159.     {'z', 'f', TRUE},    /* OP_FOLD */
  160.     {'z', 'o', TRUE},    /* OP_FOLDOPEN */
  161.     {'z', 'O', TRUE},    /* OP_FOLDOPENREC */
  162.     {'z', 'c', TRUE},    /* OP_FOLDCLOSE */
  163.     {'z', 'C', TRUE},    /* OP_FOLDCLOSEREC */
  164.     {'z', 'd', TRUE},    /* OP_FOLDDEL */
  165.     {'z', 'D', TRUE},    /* OP_FOLDDELREC */
  166. };
  167.  
  168. /*
  169.  * Translate a command name into an operator type.
  170.  * Must only be called with a valid operator name!
  171.  */
  172.     int
  173. get_op_type(char1, char2)
  174.     int        char1;
  175.     int        char2;
  176. {
  177.     int        i;
  178.  
  179.     if (char1 == 'r')        /* ignore second character */
  180.     return OP_REPLACE;
  181.     if (char1 == '~')        /* when tilde is an operator */
  182.     return OP_TILDE;
  183.     for (i = 0; ; ++i)
  184.     if (opchars[i][0] == char1 && opchars[i][1] == char2)
  185.         break;
  186.     return i;
  187. }
  188.  
  189. #if defined(FEAT_VISUAL) || defined(PROTO)
  190. /*
  191.  * Return TRUE if operator "op" always works on whole lines.
  192.  */
  193.     int
  194. op_on_lines(op)
  195.     int op;
  196. {
  197.     return opchars[op][2];
  198. }
  199. #endif
  200.  
  201. /*
  202.  * Get first operator command character.
  203.  * Returns 'g' or 'z' if there is another command character.
  204.  */
  205.     int
  206. get_op_char(optype)
  207.     int        optype;
  208. {
  209.     return opchars[optype][0];
  210. }
  211.  
  212. /*
  213.  * Get second operator command character.
  214.  */
  215.     int
  216. get_extra_op_char(optype)
  217.     int        optype;
  218. {
  219.     return opchars[optype][1];
  220. }
  221.  
  222. /*
  223.  * op_shift - handle a shift operation
  224.  */
  225.     void
  226. op_shift(oap, curs_top, amount)
  227.     oparg_T        *oap;
  228.     int            curs_top;
  229.     int            amount;
  230. {
  231.     long        i;
  232.     int            first_char;
  233.     char_u        *s;
  234. #ifdef FEAT_VISUAL
  235.     int            block_col = 0;
  236. #endif
  237.  
  238.     if (u_save((linenr_T)(oap->start.lnum - 1),
  239.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  240.     return;
  241.  
  242. #ifdef FEAT_VISUAL
  243.     if (oap->block_mode)
  244.     block_col = curwin->w_cursor.col;
  245. #endif
  246.  
  247.     for (i = oap->line_count; --i >= 0; )
  248.     {
  249.     first_char = *ml_get_curline();
  250.     if (first_char == NUL)                /* empty line */
  251.         curwin->w_cursor.col = 0;
  252. #ifdef FEAT_VISUALEXTRA
  253.     else if (oap->block_mode)
  254.         shift_block(oap, amount);
  255. #endif
  256.     else
  257.         /* Move the line right if it doesn't start with '#', 'smartindent'
  258.          * isn't set or 'cindent' isn't set or '#' isn't in 'cino'. */
  259. #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
  260.         if (first_char != '#' || !preprocs_left())
  261. #endif
  262.     {
  263.         shift_line(oap->op_type == OP_LSHIFT, p_sr, amount);
  264.     }
  265.     ++curwin->w_cursor.lnum;
  266.     }
  267.  
  268.     changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
  269.  
  270. #ifdef FEAT_VISUAL
  271.     if (oap->block_mode)
  272.     {
  273.     curwin->w_cursor.lnum = oap->start.lnum;
  274.     curwin->w_cursor.col = block_col;
  275.     }
  276.     else
  277. #endif
  278.     if (curs_top)        /* put cursor on first line, for ">>" */
  279.     {
  280.     curwin->w_cursor.lnum = oap->start.lnum;
  281.     beginline(BL_SOL | BL_FIX);   /* shift_line() may have set cursor.col */
  282.     }
  283.     else
  284.     --curwin->w_cursor.lnum;    /* put cursor on last line, for ":>" */
  285.  
  286.     if (oap->line_count > p_report)
  287.     {
  288.     if (oap->op_type == OP_RSHIFT)
  289.         s = (char_u *)">";
  290.     else
  291.         s = (char_u *)"<";
  292.     if (oap->line_count == 1)
  293.     {
  294.         if (amount == 1)
  295.         sprintf((char *)IObuff, _("1 line %sed 1 time"), s);
  296.         else
  297.         sprintf((char *)IObuff, _("1 line %sed %d times"), s, amount);
  298.     }
  299.     else
  300.     {
  301.         if (amount == 1)
  302.         sprintf((char *)IObuff, _("%ld lines %sed 1 time"),
  303.                               oap->line_count, s);
  304.         else
  305.         sprintf((char *)IObuff, _("%ld lines %sed %d times"),
  306.                           oap->line_count, s, amount);
  307.     }
  308.     msg(IObuff);
  309.     }
  310.  
  311.     /*
  312.      * Set "'[" and "']" marks.
  313.      */
  314.     curbuf->b_op_start = oap->start;
  315.     curbuf->b_op_end.lnum = oap->end.lnum;
  316.     curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  317.     if (curbuf->b_op_end.col > 0)
  318.     --curbuf->b_op_end.col;
  319. }
  320.  
  321. /*
  322.  * shift the current line one shiftwidth left (if left != 0) or right
  323.  * leaves cursor on first blank in the line
  324.  */
  325.     void
  326. shift_line(left, round, amount)
  327.     int    left;
  328.     int    round;
  329.     int    amount;
  330. {
  331.     int        count;
  332.     int        i, j;
  333.     int        p_sw = (int)curbuf->b_p_sw;
  334.  
  335.     count = get_indent();    /* get current indent */
  336.  
  337.     if (round)            /* round off indent */
  338.     {
  339.     i = count / p_sw;    /* number of p_sw rounded down */
  340.     j = count % p_sw;    /* extra spaces */
  341.     if (j && left)        /* first remove extra spaces */
  342.         --amount;
  343.     if (left)
  344.     {
  345.         i -= amount;
  346.         if (i < 0)
  347.         i = 0;
  348.     }
  349.     else
  350.         i += amount;
  351.     count = i * p_sw;
  352.     }
  353.     else        /* original vi indent */
  354.     {
  355.     if (left)
  356.     {
  357.         count -= p_sw * amount;
  358.         if (count < 0)
  359.         count = 0;
  360.     }
  361.     else
  362.         count += p_sw * amount;
  363.     }
  364.  
  365.     /* Set new indent */
  366. #ifdef FEAT_VREPLACE
  367.     if (State & VREPLACE_FLAG)
  368.     change_indent(INDENT_SET, count, FALSE, NUL);
  369.     else
  370. #endif
  371.     (void)set_indent(count, SIN_CHANGED);
  372. }
  373.  
  374. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  375. /*
  376.  * Shift one line of the current block one shiftwidth right or left.
  377.  * Leaves cursor on first character in block.
  378.  */
  379.     static void
  380. shift_block(oap, amount)
  381.     oparg_T    *oap;
  382.     int        amount;
  383. {
  384.     int            left = (oap->op_type == OP_LSHIFT);
  385.     int            oldstate = State;
  386.     int            total, split;
  387.     char_u        *newp, *oldp, *midp, *ptr;
  388.     int            oldcol = curwin->w_cursor.col;
  389.     int            p_sw = (int)curbuf->b_p_sw;
  390.     int            p_ts = (int)curbuf->b_p_ts;
  391.     struct block_def    bd;
  392.     int            internal = 0;
  393.     int            incr;
  394.     colnr_T        vcol, col = 0, ws_vcol;
  395.     int            i = 0, j = 0;
  396.     int            len;
  397.  
  398. #ifdef FEAT_RIGHTLEFT
  399.     int            old_p_ri = p_ri;
  400.  
  401.     p_ri = 0;            /* don't want revins in ident */
  402. #endif
  403.  
  404.     State = INSERT;        /* don't want REPLACE for State */
  405.     block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
  406.     if (bd.is_short)
  407.     return;
  408.  
  409.     /* total is number of screen columns to be inserted/removed */
  410.     total = amount * p_sw;
  411.     oldp = ml_get_curline();
  412.  
  413.     if (!left)
  414.     {
  415.     /*
  416.      *  1. Get start vcol
  417.      *  2. Total ws vcols
  418.      *  3. Divvy into TABs & spp
  419.      *  4. Construct new string
  420.      */
  421.     total += bd.pre_whitesp; /* all virtual WS upto & incl a split TAB */
  422.     ws_vcol = bd.start_vcol - bd.pre_whitesp;
  423.     if (bd.startspaces)
  424.     {
  425. #ifdef FEAT_MBYTE
  426.         if (has_mbyte)
  427.         bd.textstart += (*mb_ptr2len_check)(bd.textstart);
  428. #endif
  429.         ++bd.textstart;
  430.     }
  431.     for ( ; vim_iswhite(*bd.textstart); )
  432.     {
  433.         incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol));
  434.         total += incr;
  435.         bd.start_vcol += incr;
  436.     }
  437.     /* OK, now total=all the VWS reqd, and textstart points at the 1st
  438.      * non-ws char in the block. */
  439.     if (!curbuf->b_p_et)
  440.         i = ((ws_vcol % p_ts) + total) / p_ts; /* number of tabs */
  441.     if (i)
  442.         j = ((ws_vcol % p_ts) + total) % p_ts; /* number of spp */
  443.     else
  444.         j = total;
  445.     /* if we're splitting a TAB, allow for it */
  446.     bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0);
  447.     len = (int)STRLEN(bd.textstart) + 1;
  448.     newp = alloc_check((unsigned)(bd.textcol + i + j + len));
  449.     if (newp == NULL)
  450.         return;
  451.     vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len));
  452.     mch_memmove(newp, oldp, (size_t)bd.textcol);
  453.     copy_chars(newp + bd.textcol, (size_t)i, TAB);
  454.     copy_spaces(newp + bd.textcol + i, (size_t)j);
  455.     /* the end */
  456.     mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len);
  457.     }
  458.     else /* left */
  459.     {
  460.     vcol = oap->start_vcol;
  461.     /* walk vcol past ws to be removed */
  462.     for (midp = oldp + bd.textcol;
  463.           vcol < (oap->start_vcol + total) && vim_iswhite(*midp); )
  464.     {
  465.         incr = lbr_chartabsize_adv(&midp, (colnr_T)vcol);
  466.         vcol += incr;
  467.     }
  468.     /* internal is the block-internal ws replacing a split TAB */
  469.     if (vcol > (oap->start_vcol + total))
  470.     {
  471.         /* we have to split the TAB *(midp-1) */
  472.         internal = vcol - (oap->start_vcol + total);
  473.     }
  474.     /* if 'expandtab' is not set, use TABs */
  475.  
  476.     split = bd.startspaces + internal;
  477.     if (split > 0)
  478.     {
  479.         if (!curbuf->b_p_et)
  480.         {
  481.         for (ptr = oldp, col = 0; ptr < oldp+bd.textcol; )
  482.             col += lbr_chartabsize_adv(&ptr, (colnr_T)col);
  483.  
  484.         /* col+1 now equals the start col of the first char of the
  485.          * block (may be < oap.start_vcol if we're splitting a TAB) */
  486.         i = ((col % p_ts) + split) / p_ts; /* number of tabs */
  487.         }
  488.         if (i)
  489.         j = ((col % p_ts) + split) % p_ts; /* number of spp */
  490.         else
  491.         j = split;
  492.     }
  493.  
  494.     newp = alloc_check(bd.textcol + i + j + (unsigned)STRLEN(midp) + 1);
  495.     if (newp == NULL)
  496.         return;
  497.     vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + STRLEN(midp) + 1));
  498.  
  499.     /* copy first part we want to keep */
  500.     mch_memmove(newp, oldp, (size_t)bd.textcol);
  501.     /* Now copy any TABS and spp to ensure correct alignment! */
  502.     while (vim_iswhite(*midp))
  503.     {
  504.         if (*midp == TAB)
  505.         i++;
  506.         else /*space */
  507.         j++;
  508.         midp++;
  509.     }
  510.     /* We might have an extra TAB worth of spp now! */
  511.     if (j / p_ts && !curbuf->b_p_et)
  512.     {
  513.         i++;
  514.         j -= p_ts;
  515.     }
  516.     copy_chars(newp + bd.textcol, (size_t)i, TAB);
  517.     copy_spaces(newp + bd.textcol + i, (size_t)j);
  518.  
  519.     /* the end */
  520.     mch_memmove(newp + STRLEN(newp), midp, (size_t)STRLEN(midp) + 1);
  521.     }
  522.     /* replace the line */
  523.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  524.     changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol);
  525.     State = oldstate;
  526.     curwin->w_cursor.col = oldcol;
  527. #ifdef FEAT_RIGHTLEFT
  528.     p_ri = old_p_ri;
  529. #endif
  530. }
  531. #endif
  532.  
  533. #ifdef FEAT_VISUALEXTRA
  534. /*
  535.  * Insert string "s" (b_insert ? before : after) block :AKelly
  536.  * Caller must prepare for undo.
  537.  */
  538.     static void
  539. block_insert(oap, s, b_insert, bdp)
  540.     oparg_T        *oap;
  541.     char_u        *s;
  542.     int            b_insert;
  543.     struct block_def    *bdp;
  544. {
  545.     int        p_ts;
  546.     int        count = 0;    /* extra spaces to replace a cut TAB */
  547.     int        spaces = 0;    /* non-zero if cutting a TAB */
  548.     colnr_T    offset;        /* pointer along new line */
  549.     unsigned    s_len;        /* STRLEN(s) */
  550.     char_u    *newp, *oldp;    /* new, old lines */
  551.     linenr_T    lnum;        /* loop var */
  552.     int        oldstate = State;
  553.  
  554.     State = INSERT;        /* don't want REPLACE for State */
  555.     s_len = (unsigned)STRLEN(s);
  556.  
  557.     for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++)
  558.     {
  559.     block_prep(oap, bdp, lnum, TRUE);
  560.     if (bdp->is_short && b_insert)
  561.         continue;    /* OP_INSERT, line ends before block start */
  562.  
  563.     oldp = ml_get(lnum);
  564.  
  565.     if (b_insert)
  566.     {
  567.         p_ts = bdp->start_char_vcols;
  568.         spaces = bdp->startspaces;
  569.         if (spaces != 0)
  570.         count = p_ts - 1; /* we're cutting a TAB */
  571.         offset = bdp->textcol;
  572.     }
  573.     else /* append */
  574.     {
  575.         p_ts = bdp->end_char_vcols;
  576.         if (!bdp->is_short) /* spaces = padding after block */
  577.         {
  578.         spaces = (bdp->endspaces ? p_ts - bdp->endspaces : 0);
  579.         if (spaces != 0)
  580.             count = p_ts - 1; /* we're cutting a TAB */
  581.         offset = bdp->textcol + bdp->textlen - (spaces != 0);
  582.         }
  583.         else /* spaces = padding to block edge */
  584.         {
  585.         /* if $ used, just append to EOL (ie spaces==0) */
  586.         if (!bdp->is_MAX)
  587.             spaces = (oap->end_vcol - bdp->end_vcol) + 1;
  588.         count = spaces;
  589.         offset = bdp->textcol + bdp->textlen;
  590.         }
  591.     }
  592.  
  593.     newp = alloc_check((unsigned)(STRLEN(oldp)) + s_len + count + 1);
  594.     if (newp == NULL)
  595.         continue;
  596.  
  597.     /* copy up to shifted part */
  598.     mch_memmove(newp, oldp, (size_t)(offset));
  599.     oldp += offset;
  600.  
  601.     /* insert pre-padding */
  602.     copy_spaces(newp + offset, (size_t)spaces);
  603.  
  604.     /* copy the new text */
  605.     mch_memmove(newp + offset + spaces, s, (size_t)s_len);
  606.     offset += s_len;
  607.  
  608.     if (spaces && !bdp->is_short)
  609.     {
  610.         /* insert post-padding */
  611.         copy_spaces(newp + offset + spaces, (size_t)(p_ts - spaces));
  612.         /* We're splitting a TAB, don't copy it. */
  613.         oldp++;
  614.         /* We allowed for that TAB, remember this now */
  615.         count++;
  616.     }
  617.  
  618.     if (spaces > 0)
  619.         offset += count;
  620.     mch_memmove(newp + offset, oldp, (size_t)(STRLEN(oldp) + 1));
  621.  
  622.     ml_replace(lnum, newp, FALSE);
  623.  
  624.     if (lnum == oap->end.lnum)
  625.     {
  626.         /* Set "']" mark to the end of the block instead of the end of
  627.          * the insert in the first line.  */
  628.         curbuf->b_op_end.lnum = oap->end.lnum;
  629.         curbuf->b_op_end.col = offset;
  630.     }
  631.     } /* for all lnum */
  632.  
  633.     changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L);
  634.  
  635.     State = oldstate;
  636. }
  637. #endif
  638.  
  639. #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
  640. /*
  641.  * op_reindent - handle reindenting a block of lines.
  642.  */
  643.     void
  644. op_reindent(oap, how)
  645.     oparg_T    *oap;
  646.     int        (*how) __ARGS((void));
  647. {
  648.     long    i;
  649.     char_u    *l;
  650.     int        count;
  651.     linenr_T    first_changed = 0;
  652.     linenr_T    last_changed = 0;
  653.     linenr_T    start_lnum = curwin->w_cursor.lnum;
  654.  
  655.     for (i = oap->line_count; --i >= 0 && !got_int; )
  656.     {
  657.     /* it's a slow thing to do, so give feedback so there's no worry that
  658.      * the computer's just hung. */
  659.  
  660.     if (i > 1
  661.         && (i % 50 == 0 || i == oap->line_count - 1)
  662.         && oap->line_count > p_report)
  663.         smsg((char_u *)_("%ld lines to indent... "), i);
  664.  
  665.     /*
  666.      * Be vi-compatible: For lisp indenting the first line is not
  667.      * indented, unless there is only one line.
  668.      */
  669. #ifdef FEAT_LISP
  670.     if (i != oap->line_count - 1 || oap->line_count == 1
  671.                             || how != get_lisp_indent)
  672. #endif
  673.     {
  674.         l = skipwhite(ml_get_curline());
  675.         if (*l == NUL)            /* empty or blank line */
  676.         count = 0;
  677.         else
  678.         count = how();            /* get the indent for this line */
  679.  
  680.         if (set_indent(count, SIN_UNDO))
  681.         {
  682.         /* did change the indent, call changed_lines() later */
  683.         if (first_changed == 0)
  684.             first_changed = curwin->w_cursor.lnum;
  685.         last_changed = curwin->w_cursor.lnum;
  686.         }
  687.     }
  688.     ++curwin->w_cursor.lnum;
  689.     }
  690.  
  691.     /* put cursor on first non-blank of indented line */
  692.     curwin->w_cursor.lnum = start_lnum;
  693.     beginline(BL_SOL | BL_FIX);
  694.  
  695.     /* Mark changed lines so that they will be redrawn.  When Visual
  696.      * highlighting was present, need to continue until the last line.  When
  697.      * there is no change still need to remove the Visual highlighting. */
  698.     if (last_changed != 0)
  699.     changed_lines(first_changed, 0,
  700. #ifdef FEAT_VISUAL
  701.         oap->is_VIsual ? start_lnum + oap->line_count :
  702. #endif
  703.         last_changed + 1, 0L);
  704. #ifdef FEAT_VISUAL
  705.     else if (oap->is_VIsual)
  706.     redraw_curbuf_later(INVERTED);
  707. #endif
  708.  
  709.     if (oap->line_count > p_report)
  710.     {
  711.     i = oap->line_count - (i + 1);
  712.     if (i == 1)
  713.         MSG(_("1 line indented "));
  714.     else
  715.         smsg((char_u *)_("%ld lines indented "), i);
  716.     }
  717.     /* set '[ and '] marks */
  718.     curbuf->b_op_start = oap->start;
  719.     curbuf->b_op_end = oap->end;
  720. }
  721. #endif /* defined(FEAT_LISP) || defined(FEAT_CINDENT) */
  722.  
  723. #ifdef FEAT_EVAL
  724. /*
  725.  * Keep the last expression line here, for repeating.
  726.  */
  727. static char_u    *expr_line = NULL;
  728.  
  729. /*
  730.  * Get an expression for the "\"=expr1" or "CTRL-R =expr1"
  731.  * Returns '=' when OK, NUL otherwise.
  732.  */
  733.     int
  734. get_expr_register()
  735. {
  736.     char_u    *new_line;
  737.  
  738.     new_line = getcmdline('=', 0L, 0);
  739.     if (new_line == NULL)
  740.     return NUL;
  741.     if (*new_line == NUL)    /* use previous line */
  742.     vim_free(new_line);
  743.     else
  744.     set_expr_line(new_line);
  745.     return '=';
  746. }
  747.  
  748. /*
  749.  * Set the expression for the '=' register.
  750.  * Argument must be an allocated string.
  751.  */
  752.     void
  753. set_expr_line(new_line)
  754.     char_u    *new_line;
  755. {
  756.     vim_free(expr_line);
  757.     expr_line = new_line;
  758. }
  759.  
  760. /*
  761.  * Get the result of the '=' register expression.
  762.  * Returns a pointer to allocated memory, or NULL for failure.
  763.  */
  764.     static char_u *
  765. get_expr_line()
  766. {
  767.     char_u    *expr_copy;
  768.     char_u    *rv;
  769.  
  770.     if (expr_line == NULL)
  771.     return NULL;
  772.  
  773.     /* Make a copy of the expression, because evaluating it may cause it to be
  774.      * changed. */
  775.     expr_copy = vim_strsave(expr_line);
  776.     if (expr_copy == NULL)
  777.     return NULL;
  778.  
  779.     rv = eval_to_string(expr_copy, NULL);
  780.     vim_free(expr_copy);
  781.     return rv;
  782. }
  783. #endif /* FEAT_EVAL */
  784.  
  785. /*
  786.  * Check if 'regname' is a valid name of a yank register.
  787.  * Note: There is no check for 0 (default register), caller should do this
  788.  */
  789.     int
  790. valid_yank_reg(regname, writing)
  791.     int        regname;
  792.     int        writing;        /* if TRUE check for writable registers */
  793. {
  794.     if (       (regname > 0 && ASCII_ISALNUM(regname))
  795.         || (!writing && vim_strchr((char_u *)
  796. #ifdef FEAT_EVAL
  797.                     "/.%#:="
  798. #else
  799.                     "/.%#:"
  800. #endif
  801.                     , regname) != NULL)
  802.         || regname == '"'
  803.         || regname == '-'
  804.         || regname == '_'
  805. #ifdef FEAT_CLIPBOARD
  806.         || regname == '*'
  807.         || regname == '+'
  808. #endif
  809. #ifdef FEAT_DND
  810.         || (!writing && regname == '~')
  811. #endif
  812.                             )
  813.     return TRUE;
  814.     return FALSE;
  815. }
  816.  
  817. /*
  818.  * Set y_current and y_append, according to the value of "regname".
  819.  * Cannot handle the '_' register.
  820.  *
  821.  * If regname is 0 and writing, use register 0
  822.  * If regname is 0 and reading, use previous register
  823.  */
  824.     static void
  825. get_yank_register(regname, writing)
  826.     int        regname;
  827.     int        writing;
  828. {
  829.     int        i;
  830.  
  831.     y_append = FALSE;
  832.     if ((regname == 0 || regname == '"') && !writing && y_previous != NULL)
  833.     {
  834.     y_current = y_previous;
  835.     return;
  836.     }
  837.     i = regname;
  838.     if (isdigit(i))
  839.     i -= '0';
  840.     else if (ASCII_ISLOWER(i))
  841.     i = CharOrdLow(i) + 10;
  842.     else if (ASCII_ISUPPER(i))
  843.     {
  844.     i = CharOrdUp(i) + 10;
  845.     y_append = TRUE;
  846.     }
  847.     else if (regname == '-')
  848.     i = DELETION_REGISTER;
  849. #ifdef FEAT_CLIPBOARD
  850.     /* When selection is not available, use register 0 instead of '*' */
  851.     else if (clip_star.available && regname == '*')
  852.     i = STAR_REGISTER;
  853.     /* When clipboard is not available, use register 0 instead of '+' */
  854.     else if (clip_plus.available && regname == '+')
  855.     i = PLUS_REGISTER;
  856. #endif
  857. #ifdef FEAT_DND
  858.     else if (!writing && regname == '~')
  859.     i = TILDE_REGISTER;
  860. #endif
  861.     else        /* not 0-9, a-z, A-Z or '-': use register 0 */
  862.     i = 0;
  863.     y_current = &(y_regs[i]);
  864.     if (writing)    /* remember the register we write into for do_put() */
  865.     y_previous = y_current;
  866. }
  867.  
  868. #if defined(FEAT_VISUAL) || defined(PROTO)
  869. /*
  870.  * Obtain the contents of a "normal" register. The register is made empty.
  871.  * The returned pointer has allocated memory, use put_register() later.
  872.  */
  873.     void *
  874. get_register(name, copy)
  875.     int        name;
  876.     int        copy;    /* make a copy, if FALSE make register empty. */
  877. {
  878.     static struct yankreg    *reg;
  879.     int                i;
  880.  
  881.     get_yank_register(name, 0);
  882.     reg = (struct yankreg *)alloc((unsigned)sizeof(struct yankreg));
  883.     if (reg != NULL)
  884.     {
  885.     *reg = *y_current;
  886.     if (copy)
  887.     {
  888.         /* If we run out of memory some or all of the lines are empty. */
  889.         reg->y_array = (char_u **)alloc((unsigned)(sizeof(char_u *)
  890.                                    * reg->y_size));
  891.         if (reg->y_array != NULL)
  892.         {
  893.         for (i = 0; i < reg->y_size; ++i)
  894.             reg->y_array[i] = vim_strsave(y_current->y_array[i]);
  895.         }
  896.     }
  897.     else
  898.         y_current->y_array = NULL;
  899.     }
  900.     return (void *)reg;
  901. }
  902.  
  903. /*
  904.  * Put "reg" into register "name".  Free any previous contents.
  905.  */
  906.     void
  907. put_register(name, reg)
  908.     int        name;
  909.     void    *reg;
  910. {
  911.     get_yank_register(name, 0);
  912.     free_yank_all();
  913.     *y_current = *(struct yankreg *)reg;
  914.  
  915. # ifdef FEAT_CLIPBOARD
  916.     /* Send text written to clipboard register to the clipboard. */
  917.     may_set_selection();
  918. # endif
  919. }
  920. #endif
  921.  
  922. #if defined(FEAT_MOUSE) || defined(PROTO)
  923. /*
  924.  * return TRUE if the current yank register has type MLINE
  925.  */
  926.     int
  927. yank_register_mline(regname)
  928.     int        regname;
  929. {
  930.     if (regname != 0 && !valid_yank_reg(regname, FALSE))
  931.     return FALSE;
  932.     if (regname == '_')        /* black hole is always empty */
  933.     return FALSE;
  934.     get_yank_register(regname, FALSE);
  935.     return (y_current->y_type == MLINE);
  936. }
  937. #endif
  938.  
  939. /*
  940.  * start or stop recording into a yank register
  941.  *
  942.  * return FAIL for failure, OK otherwise
  943.  */
  944.     int
  945. do_record(c)
  946.     int c;
  947. {
  948.     char_u    *p;
  949.     static int    regname;
  950.     struct yankreg *old_y_previous, *old_y_current;
  951.     int        retval;
  952.  
  953.     if (Recording == FALSE)        /* start recording */
  954.     {
  955.             /* registers 0-9, a-z and " are allowed */
  956.     if (c < 0 || (!ASCII_ISALNUM(c) && c != '"'))
  957.         retval = FAIL;
  958.     else
  959.     {
  960.         Recording = TRUE;
  961.         showmode();
  962.         regname = c;
  963.         retval = OK;
  964.     }
  965.     }
  966.     else                /* stop recording */
  967.     {
  968.     /*
  969.      * Get the recorded key hits.  K_SPECIAL and CSI will be escaped, so
  970.      * that the register can be put into the typeahead buffer without
  971.      * translation.
  972.      */
  973.     Recording = FALSE;
  974.     MSG("");
  975.     p = get_recorded();
  976.     if (p == NULL)
  977.         retval = FAIL;
  978.     else
  979.     {
  980.         /*
  981.          * We don't want to change the default register here, so save and
  982.          * restore the current register name.
  983.          */
  984.         old_y_previous = y_previous;
  985.         old_y_current = y_current;
  986.  
  987.         retval = stuff_yank(regname, p);
  988.  
  989.         y_previous = old_y_previous;
  990.         y_current = old_y_current;
  991.     }
  992.     }
  993.     return retval;
  994. }
  995.  
  996. /*
  997.  * Stuff string "p" into yank register "regname" as a single line (append if
  998.  * uppercase).    "p" must have been alloced.
  999.  *
  1000.  * return FAIL for failure, OK otherwise
  1001.  */
  1002.     static int
  1003. stuff_yank(regname, p)
  1004.     int        regname;
  1005.     char_u    *p;
  1006. {
  1007.     char_u    *lp;
  1008.     char_u    **pp;
  1009.  
  1010.     /* check for read-only register */
  1011.     if (regname != 0 && !valid_yank_reg(regname, TRUE))
  1012.     {
  1013.     vim_free(p);
  1014.     return FAIL;
  1015.     }
  1016.     if (regname == '_')            /* black hole: don't do anything */
  1017.     {
  1018.     vim_free(p);
  1019.     return OK;
  1020.     }
  1021.     get_yank_register(regname, TRUE);
  1022.     if (y_append && y_current->y_array != NULL)
  1023.     {
  1024.     pp = &(y_current->y_array[y_current->y_size - 1]);
  1025.     lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE);
  1026.     if (lp == NULL)
  1027.     {
  1028.         vim_free(p);
  1029.         return FAIL;
  1030.     }
  1031.     STRCPY(lp, *pp);
  1032.     STRCAT(lp, p);
  1033.     vim_free(p);
  1034.     vim_free(*pp);
  1035.     *pp = lp;
  1036.     }
  1037.     else
  1038.     {
  1039.     free_yank_all();
  1040.     if ((y_current->y_array =
  1041.             (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL)
  1042.     {
  1043.         vim_free(p);
  1044.         return FAIL;
  1045.     }
  1046.     y_current->y_array[0] = p;
  1047.     y_current->y_size = 1;
  1048.     y_current->y_type = MCHAR;  /* used to be MLINE, why? */
  1049.     }
  1050.     return OK;
  1051. }
  1052.  
  1053. #ifdef FEAT_CLIPBOARD
  1054. /*
  1055.  * When "regname" is a clipboard register, obtain the selection.  If it's not
  1056.  * available return zero, otherwise return "regname".
  1057.  */
  1058. static int may_get_selection __ARGS((int regname));
  1059.  
  1060.     static int
  1061. may_get_selection(regname)
  1062.     int regname;
  1063. {
  1064.     if (regname == '*')
  1065.     {
  1066.     if (!clip_star.available)
  1067.         regname = 0;
  1068.     else
  1069.         clip_get_selection(&clip_star);
  1070.     }
  1071.     else if (regname == '+')
  1072.     {
  1073.     if (!clip_plus.available)
  1074.         regname = 0;
  1075.     else
  1076.         clip_get_selection(&clip_plus);
  1077.     }
  1078.     return regname;
  1079. }
  1080. #endif
  1081.  
  1082. /*
  1083.  * execute a yank register: copy it into the stuff buffer
  1084.  *
  1085.  * return FAIL for failure, OK otherwise
  1086.  */
  1087.     int
  1088. do_execreg(regname, colon, addcr)
  1089.     int        regname;
  1090.     int        colon;        /* insert ':' before each line */
  1091.     int        addcr;        /* always add '\n' to end of line */
  1092. {
  1093.     static int    lastc = NUL;
  1094.     long    i;
  1095.     char_u    *p;
  1096.     int        retval = OK;
  1097.     int        remap;
  1098.  
  1099.     if (regname == '@')            /* repeat previous one */
  1100.     regname = lastc;
  1101.                     /* check for valid regname */
  1102.     if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
  1103.     return FAIL;
  1104.     lastc = regname;
  1105.  
  1106. #ifdef FEAT_CLIPBOARD
  1107.     regname = may_get_selection(regname);
  1108. #endif
  1109.  
  1110.     if (regname == '_')            /* black hole: don't stuff anything */
  1111.     return OK;
  1112.  
  1113. #ifdef FEAT_CMDHIST
  1114.     if (regname == ':')            /* use last command line */
  1115.     {
  1116.     if (last_cmdline == NULL)
  1117.     {
  1118.         EMSG(_(e_nolastcmd));
  1119.         return FAIL;
  1120.     }
  1121.     vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */
  1122.     new_last_cmdline = NULL;
  1123.     retval = put_in_typebuf(last_cmdline, TRUE);
  1124.     }
  1125. #endif
  1126. #ifdef FEAT_EVAL
  1127.     else if (regname == '=')
  1128.     {
  1129.     p = get_expr_line();
  1130.     if (p == NULL)
  1131.         return FAIL;
  1132.     retval = put_in_typebuf(p, colon);
  1133.     vim_free(p);
  1134.     }
  1135. #endif
  1136.     else if (regname == '.')        /* use last inserted text */
  1137.     {
  1138.     p = get_last_insert_save();
  1139.     if (p == NULL)
  1140.     {
  1141.         EMSG(_(e_noinstext));
  1142.         return FAIL;
  1143.     }
  1144.     retval = put_in_typebuf(p, colon);
  1145.     vim_free(p);
  1146.     }
  1147.     else
  1148.     {
  1149.     get_yank_register(regname, FALSE);
  1150.     if (y_current->y_array == NULL)
  1151.         return FAIL;
  1152.  
  1153.     /* Disallow remaping for ":@r". */
  1154.     remap = colon ? REMAP_NONE : REMAP_YES;
  1155.  
  1156.     /*
  1157.      * Insert lines into typeahead buffer, from last one to first one.
  1158.      */
  1159.     for (i = y_current->y_size; --i >= 0; )
  1160.     {
  1161.         /* insert NL between lines and after last line if type is MLINE */
  1162.         if (y_current->y_type == MLINE || i < y_current->y_size - 1
  1163.                                      || addcr)
  1164.         {
  1165.         if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, FALSE) == FAIL)
  1166.             return FAIL;
  1167.         }
  1168.         if (ins_typebuf(y_current->y_array[i], remap, 0, TRUE, FALSE)
  1169.                                       == FAIL)
  1170.         return FAIL;
  1171.         if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, FALSE)
  1172.                                       == FAIL)
  1173.         return FAIL;
  1174.     }
  1175.     Exec_reg = TRUE;    /* disable the 'q' command */
  1176.     }
  1177.     return retval;
  1178. }
  1179.  
  1180.     static int
  1181. put_in_typebuf(s, colon)
  1182.     char_u    *s;
  1183.     int        colon;        /* add ':' before the line */
  1184. {
  1185.     int        retval = OK;
  1186.  
  1187.     if (colon)
  1188.     retval = ins_typebuf((char_u *)"\n", REMAP_YES, 0, TRUE, FALSE);
  1189.     if (retval == OK)
  1190.     retval = ins_typebuf(s, REMAP_YES, 0, TRUE, FALSE);
  1191.     if (colon && retval == OK)
  1192.     retval = ins_typebuf((char_u *)":", REMAP_YES, 0, TRUE, FALSE);
  1193.     return retval;
  1194. }
  1195.  
  1196. /*
  1197.  * Insert a yank register: copy it into the Read buffer.
  1198.  * Used by CTRL-R command and middle mouse button in insert mode.
  1199.  *
  1200.  * return FAIL for failure, OK otherwise
  1201.  */
  1202.     int
  1203. insert_reg(regname, literally)
  1204.     int        regname;
  1205.     int        literally;    /* insert literally, not as if typed */
  1206. {
  1207.     long    i;
  1208.     int        retval = OK;
  1209.     char_u    *arg;
  1210.     int        allocated;
  1211.  
  1212.     /*
  1213.      * It is possible to get into an endless loop by having CTRL-R a in
  1214.      * register a and then, in insert mode, doing CTRL-R a.
  1215.      * If you hit CTRL-C, the loop will be broken here.
  1216.      */
  1217.     ui_breakcheck();
  1218.     if (got_int)
  1219.     return FAIL;
  1220.  
  1221.     /* check for valid regname */
  1222.     if (regname != NUL && !valid_yank_reg(regname, FALSE))
  1223.     return FAIL;
  1224.  
  1225. #ifdef FEAT_CLIPBOARD
  1226.     regname = may_get_selection(regname);
  1227. #endif
  1228.  
  1229.     if (regname == '.')            /* insert last inserted text */
  1230.     retval = stuff_inserted(NUL, 1L, TRUE);
  1231.     else if (get_spec_reg(regname, &arg, &allocated, TRUE))
  1232.     {
  1233.     if (arg == NULL)
  1234.         return FAIL;
  1235.     stuffescaped(arg, literally);
  1236.     if (allocated)
  1237.         vim_free(arg);
  1238.     }
  1239.     else                /* name or number register */
  1240.     {
  1241.     get_yank_register(regname, FALSE);
  1242.     if (y_current->y_array == NULL)
  1243.         retval = FAIL;
  1244.     else
  1245.     {
  1246.         for (i = 0; i < y_current->y_size; ++i)
  1247.         {
  1248.         stuffescaped(y_current->y_array[i], literally);
  1249.         /*
  1250.          * Insert a newline between lines and after last line if
  1251.          * y_type is MLINE.
  1252.          */
  1253.         if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  1254.             stuffcharReadbuff('\n');
  1255.         }
  1256.     }
  1257.     }
  1258.  
  1259.     return retval;
  1260. }
  1261.  
  1262. /*
  1263.  * Stuff a string into the typeahead buffer, such that edit() will insert it
  1264.  * literally ("literally" TRUE) or interpret is as typed characters.
  1265.  */
  1266.     static void
  1267. stuffescaped(arg, literally)
  1268.     char_u    *arg;
  1269.     int        literally;
  1270. {
  1271.     int        c;
  1272.     char_u    *start;
  1273.  
  1274.     while (*arg != NUL)
  1275.     {
  1276.     /* Stuff a sequence of normal ASCII characters, that's fast.  Also
  1277.      * stuff K_SPECIAL to get the effect of a special key when "literally"
  1278.      * is TRUE. */
  1279.     start = arg;
  1280.     while ((*arg >= ' '
  1281. #ifndef EBCDIC
  1282.             && *arg < DEL /* EBCDIC: chars above space are normal */
  1283. #endif
  1284.             )
  1285.         || (*arg == K_SPECIAL && !literally))
  1286.         ++arg;
  1287.     if (arg > start)
  1288.         stuffReadbuffLen(start, (long)(arg - start));
  1289.  
  1290.     /* stuff a single special character */
  1291.     if (*arg != NUL)
  1292.     {
  1293. #ifdef FEAT_MBYTE
  1294.         if (has_mbyte)
  1295.         c = mb_ptr2char_adv(&arg);
  1296.         else
  1297. #endif
  1298.         c = *arg++;
  1299.         if (literally && ((c < ' ' && c != TAB) || c == DEL))
  1300.         stuffcharReadbuff(Ctrl_V);
  1301.         stuffcharReadbuff(c);
  1302.     }
  1303.     }
  1304. }
  1305.  
  1306. /*
  1307.  * If "regname" is a special register, return a pointer to its value.
  1308.  */
  1309.     static int
  1310. get_spec_reg(regname, argp, allocated, errmsg)
  1311.     int        regname;
  1312.     char_u    **argp;
  1313.     int        *allocated;
  1314.     int        errmsg;        /* give error message when failing */
  1315. {
  1316.     int        cnt;
  1317.  
  1318.     *argp = NULL;
  1319.     *allocated = FALSE;
  1320.     switch (regname)
  1321.     {
  1322.     case '%':        /* file name */
  1323.         if (errmsg)
  1324.         check_fname();    /* will give emsg if not set */
  1325.         *argp = curbuf->b_fname;
  1326.         return TRUE;
  1327.  
  1328.     case '#':        /* alternate file name */
  1329.         *argp = getaltfname(errmsg);    /* may give emsg if not set */
  1330.         return TRUE;
  1331.  
  1332. #ifdef FEAT_EVAL
  1333.     case '=':        /* result of expression */
  1334.         *argp = get_expr_line();
  1335.         *allocated = TRUE;
  1336.         return TRUE;
  1337. #endif
  1338.  
  1339.     case ':':        /* last command line */
  1340.         if (last_cmdline == NULL && errmsg)
  1341.         EMSG(_(e_nolastcmd));
  1342.         *argp = last_cmdline;
  1343.         return TRUE;
  1344.  
  1345.     case '/':        /* last search-pattern */
  1346.         if (last_search_pat() == NULL && errmsg)
  1347.         EMSG(_(e_noprevre));
  1348.         *argp = last_search_pat();
  1349.         return TRUE;
  1350.  
  1351.     case '.':        /* last inserted text */
  1352.         *argp = get_last_insert_save();
  1353.         *allocated = TRUE;
  1354.         if (*argp == NULL && errmsg)
  1355.         EMSG(_(e_noinstext));
  1356.         return TRUE;
  1357.  
  1358. #ifdef FEAT_SEARCHPATH
  1359.     case Ctrl_F:        /* Filename under cursor */
  1360.     case Ctrl_P:        /* Path under cursor, expand via "path" */
  1361.         if (!errmsg)
  1362.         return FALSE;
  1363.         *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
  1364.                 | (regname == Ctrl_P ? FNAME_EXP : 0), 1L);
  1365.         *allocated = TRUE;
  1366.         return TRUE;
  1367. #endif
  1368.  
  1369.     case Ctrl_W:        /* word under cursor */
  1370.     case Ctrl_A:        /* WORD (mnemonic All) under cursor */
  1371.         if (!errmsg)
  1372.         return FALSE;
  1373.         cnt = find_ident_under_cursor(argp, regname == Ctrl_W
  1374.                    ?  (FIND_IDENT|FIND_STRING) : FIND_STRING);
  1375.         *argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
  1376.         *allocated = TRUE;
  1377.         return TRUE;
  1378.  
  1379.     case '_':        /* black hole: always empty */
  1380.         *argp = (char_u *)"";
  1381.         return TRUE;
  1382.     }
  1383.  
  1384.     return FALSE;
  1385. }
  1386.  
  1387. /*
  1388.  * paste a yank register into the command line.
  1389.  * used by CTRL-R command in command-line mode
  1390.  * insert_reg() can't be used here, because special characters from the
  1391.  * register contents will be interpreted as commands.
  1392.  *
  1393.  * return FAIL for failure, OK otherwise
  1394.  */
  1395.     int
  1396. cmdline_paste(regname, literally)
  1397.     int regname;
  1398.     int literally;    /* Insert text literally instead of "as typed" */
  1399. {
  1400.     long    i;
  1401.     char_u    *arg;
  1402.     int        allocated;
  1403.  
  1404.     /* check for valid regname; also accept special characters for CTRL-R in
  1405.      * the command line */
  1406.     if (regname != Ctrl_F && regname != Ctrl_P && regname != Ctrl_W
  1407.         && regname != Ctrl_A && !valid_yank_reg(regname, FALSE))
  1408.     return FAIL;
  1409.  
  1410.     /* A register containing CTRL-R can cause an endless loop.  Allow using
  1411.      * CTRL-C to break the loop. */
  1412.     line_breakcheck();
  1413.     if (got_int)
  1414.     return FAIL;
  1415.  
  1416. #ifdef FEAT_CLIPBOARD
  1417.     regname = may_get_selection(regname);
  1418. #endif
  1419.  
  1420.     if (get_spec_reg(regname, &arg, &allocated, TRUE))
  1421.     {
  1422.     if (arg == NULL)
  1423.         return FAIL;
  1424.     cmdline_paste_str(arg, literally);
  1425.     if (allocated)
  1426.         vim_free(arg);
  1427.     return OK;
  1428.     }
  1429.  
  1430.     get_yank_register(regname, FALSE);
  1431.     if (y_current->y_array == NULL)
  1432.     return FAIL;
  1433.  
  1434.     for (i = 0; i < y_current->y_size; ++i)
  1435.     {
  1436.     cmdline_paste_str(y_current->y_array[i], literally);
  1437.  
  1438.     /* insert ^M between lines and after last line if type is MLINE */
  1439.     if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  1440.         cmdline_paste_str((char_u *)"\r", literally);
  1441.  
  1442.     /* Check for CTRL-C, in case someone tries to paste a few thousand
  1443.      * lines and gets bored. */
  1444.     ui_breakcheck();
  1445.     if (got_int)
  1446.         return FAIL;
  1447.     }
  1448.     return OK;
  1449. }
  1450.  
  1451. /*
  1452.  * Put a string on the command line.
  1453.  * When "literally" is TRUE, insert literally.
  1454.  * When "literally" is FALSE, insert as typed, but don't leave the command
  1455.  * line.
  1456.  */
  1457.     static void
  1458. cmdline_paste_str(s, literally)
  1459.     char_u    *s;
  1460.     int        literally;
  1461. {
  1462.     int        c, cv;
  1463.  
  1464.     if (literally)
  1465.     put_on_cmdline(s, -1, TRUE);
  1466.     else
  1467.     while (*s != NUL)
  1468.     {
  1469.         cv = *s;
  1470.         if (cv == Ctrl_V && s[1])
  1471.         ++s;
  1472. #ifdef FEAT_MBYTE
  1473.         if (has_mbyte)
  1474.         {
  1475.         c = mb_ptr2char(s);
  1476.         s += mb_char2len(c);
  1477.         }
  1478.         else
  1479. #endif
  1480.         c = *s++;
  1481.         if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CR || c == NL
  1482. #ifdef UNIX
  1483.             || c == intr_char
  1484. #endif
  1485.             || (c == Ctrl_BSL && *s == Ctrl_N))
  1486.         stuffcharReadbuff(Ctrl_V);
  1487.         stuffcharReadbuff(c);
  1488.     }
  1489. }
  1490.  
  1491. #if defined(FEAT_CLIPBOARD) || defined(PROTO)
  1492. /*
  1493.  * Adjust the register name pointed to with "rp" for the clipboard being
  1494.  * used always and the clipboard being available.
  1495.  */
  1496.     void
  1497. adjust_clip_reg(rp)
  1498.     int        *rp;
  1499. {
  1500.     /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */
  1501.     if (*rp == 0 && clip_unnamed)
  1502.     *rp = '*';
  1503.     if (!clip_star.available && *rp == '*')
  1504.     *rp = 0;
  1505.     if (!clip_plus.available && *rp == '+')
  1506.     *rp = 0;
  1507. }
  1508. #endif
  1509.  
  1510. /*
  1511.  * op_delete - handle a delete operation
  1512.  *
  1513.  * return FAIL if undo failed, OK otherwise.
  1514.  */
  1515.     int
  1516. op_delete(oap)
  1517.     oparg_T   *oap;
  1518. {
  1519.     int            n;
  1520.     linenr_T        lnum;
  1521.     char_u        *ptr;
  1522. #ifdef FEAT_VISUAL
  1523.     char_u        *newp, *oldp;
  1524.     struct block_def    bd;
  1525. #endif
  1526.     linenr_T        old_lcount = curbuf->b_ml.ml_line_count;
  1527.     int            did_yank = FALSE;
  1528.  
  1529.     if (curbuf->b_ml.ml_flags & ML_EMPTY)        /* nothing to do */
  1530.     return OK;
  1531.  
  1532.     /* Nothing to delete, return here.    Do prepare undo, for op_change(). */
  1533.     if (oap->empty)
  1534.     return u_save_cursor();
  1535.  
  1536.     if (!curbuf->b_p_ma)
  1537.     {
  1538.     EMSG(_(e_modifiable));
  1539.     return FAIL;
  1540.     }
  1541.  
  1542. #ifdef FEAT_CLIPBOARD
  1543.     adjust_clip_reg(&oap->regname);
  1544. #endif
  1545.  
  1546. #ifdef FEAT_MBYTE
  1547.     if (has_mbyte)
  1548.     mb_adjust_opend(oap);
  1549. #endif
  1550.  
  1551. /*
  1552.  * Imitate the strange Vi behaviour: If the delete spans more than one line
  1553.  * and motion_type == MCHAR and the result is a blank line, make the delete
  1554.  * linewise.  Don't do this for the change command or Visual mode.
  1555.  */
  1556.     if (       oap->motion_type == MCHAR
  1557. #ifdef FEAT_VISUAL
  1558.         && !oap->is_VIsual
  1559. #endif
  1560.         && oap->line_count > 1
  1561.         && oap->op_type == OP_DELETE)
  1562.     {
  1563.     ptr = ml_get(oap->end.lnum) + oap->end.col + oap->inclusive;
  1564.     ptr = skipwhite(ptr);
  1565.     if (*ptr == NUL && inindent(0))
  1566.         oap->motion_type = MLINE;
  1567.     }
  1568.  
  1569. /*
  1570.  * Check for trying to delete (e.g. "D") in an empty line.
  1571.  * Note: For the change operator it is ok.
  1572.  */
  1573.     if (       oap->motion_type == MCHAR
  1574.         && oap->line_count == 1
  1575.         && oap->op_type == OP_DELETE
  1576.         && *ml_get(oap->start.lnum) == NUL)
  1577.     {
  1578.     /*
  1579.      * It's an error to operate on an empty region, when 'E' inclucded in
  1580.      * 'cpoptions' (Vi compatible).
  1581.      */
  1582.     if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL)
  1583.         beep_flush();
  1584.     return OK;
  1585.     }
  1586.  
  1587. /*
  1588.  * Do a yank of whatever we're about to delete.
  1589.  * If a yank register was specified, put the deleted text into that register.
  1590.  * For the black hole register '_' don't yank anything.
  1591.  */
  1592.     if (oap->regname != '_')
  1593.     {
  1594.     if (oap->regname != 0)
  1595.     {
  1596.         /* check for read-only register */
  1597.         if (!valid_yank_reg(oap->regname, TRUE))
  1598.         {
  1599.         beep_flush();
  1600.         return OK;
  1601.         }
  1602.         get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */
  1603.         if (op_yank(oap, TRUE, FALSE) == OK)   /* yank without message */
  1604.         did_yank = TRUE;
  1605.     }
  1606.  
  1607.     /*
  1608.      * Put deleted text into register 1 and shift number registers if the
  1609.      * delete contains a line break, or when a regname has been specified.
  1610.      */
  1611.     if (oap->regname != 0 || oap->motion_type == MLINE
  1612.                    || oap->line_count > 1 || oap->use_reg_one)
  1613.     {
  1614.         y_current = &y_regs[9];
  1615.         free_yank_all();            /* free register nine */
  1616.         for (n = 9; n > 1; --n)
  1617.         y_regs[n] = y_regs[n - 1];
  1618.         y_previous = y_current = &y_regs[1];
  1619.         y_regs[1].y_array = NULL;        /* set register one to empty */
  1620.         if (op_yank(oap, TRUE, FALSE) == OK)
  1621.         did_yank = TRUE;
  1622.     }
  1623.  
  1624.     /* Yank into small delete register when no register specified and the
  1625.      * delete is within one line. */
  1626.     if (oap->regname == 0 && oap->motion_type != MLINE
  1627.                               && oap->line_count == 1)
  1628.     {
  1629.         oap->regname = '-';
  1630.         get_yank_register(oap->regname, TRUE);
  1631.         if (op_yank(oap, TRUE, FALSE) == OK)
  1632.         did_yank = TRUE;
  1633.         oap->regname = 0;
  1634.     }
  1635.  
  1636.     /*
  1637.      * If there's too much stuff to fit in the yank register, then get a
  1638.      * confirmation before doing the delete. This is crude, but simple.
  1639.      * And it avoids doing a delete of something we can't put back if we
  1640.      * want.
  1641.      */
  1642.     if (!did_yank)
  1643.     {
  1644.         int msg_silent_save = msg_silent;
  1645.  
  1646.         msg_silent = 0;    /* must display the prompt */
  1647.         n = ask_yesno((char_u *)_("cannot yank; delete anyway"), TRUE);
  1648.         msg_silent = msg_silent_save;
  1649.         if (n != 'y')
  1650.         {
  1651.         EMSG(_(e_abort));
  1652.         return FAIL;
  1653.         }
  1654.     }
  1655.     }
  1656.  
  1657. #ifdef FEAT_VISUAL
  1658. /*
  1659.  * block mode delete
  1660.  */
  1661.     if (oap->block_mode)
  1662.     {
  1663.     if (u_save((linenr_T)(oap->start.lnum - 1),
  1664.                    (linenr_T)(oap->end.lnum + 1)) == FAIL)
  1665.         return FAIL;
  1666.  
  1667.     for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum)
  1668.     {
  1669.         block_prep(oap, &bd, lnum, TRUE);
  1670.         if (bd.textlen == 0)    /* nothing to delete */
  1671.         continue;
  1672.  
  1673.         /* Adjust cursor position for tab replaced by spaces and 'lbr'. */
  1674.         if (lnum == curwin->w_cursor.lnum)
  1675.         {
  1676.         curwin->w_cursor.col = bd.textcol + bd.startspaces;
  1677. # ifdef FEAT_VIRTUALEDIT
  1678.         curwin->w_cursor.coladd = 0;
  1679. # endif
  1680.         }
  1681.  
  1682.         /* n == number of chars deleted
  1683.          * If we delete a TAB, it may be replaced by several characters.
  1684.          * Thus the number of characters may increase!
  1685.          */
  1686.         n = bd.textlen - bd.startspaces - bd.endspaces;
  1687.         oldp = ml_get(lnum);
  1688.         newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n);
  1689.         if (newp == NULL)
  1690.         continue;
  1691.         /* copy up to deleted part */
  1692.         mch_memmove(newp, oldp, (size_t)bd.textcol);
  1693.         /* insert spaces */
  1694.         copy_spaces(newp + bd.textcol,
  1695.                      (size_t)(bd.startspaces + bd.endspaces));
  1696.         /* copy the part after the deleted part */
  1697.         oldp += bd.textcol + bd.textlen;
  1698.         mch_memmove(newp + bd.textcol + bd.startspaces + bd.endspaces,
  1699.                               oldp, STRLEN(oldp) + 1);
  1700.         /* replace the line */
  1701.         ml_replace(lnum, newp, FALSE);
  1702.     }
  1703.  
  1704.     check_cursor_col();
  1705.     changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col,
  1706.                                oap->end.lnum + 1, 0L);
  1707.     oap->line_count = 0;        /* no lines deleted */
  1708.     }
  1709.     else
  1710. #endif
  1711.     if (oap->motion_type == MLINE)
  1712.     {
  1713.     if (oap->op_type == OP_CHANGE)
  1714.     {
  1715.         /* Delete the lines except the first one.  Temporarily move the
  1716.          * cursor to the next line.  Save the current line number, if the
  1717.          * last line is deleted it may be changed.
  1718.          */
  1719.         if (oap->line_count > 1)
  1720.         {
  1721.         lnum = curwin->w_cursor.lnum;
  1722.         ++curwin->w_cursor.lnum;
  1723.         del_lines((long)(oap->line_count - 1), TRUE);
  1724.         curwin->w_cursor.lnum = lnum;
  1725.         }
  1726.         if (u_save_cursor() == FAIL)
  1727.         return FAIL;
  1728.         if (curbuf->b_p_ai)            /* don't delete indent */
  1729.         {
  1730.         beginline(BL_WHITE);        /* cursor on first non-white */
  1731.         did_ai = TRUE;            /* delete the indent when ESC hit */
  1732.         ai_col = curwin->w_cursor.col;
  1733.         }
  1734.         else
  1735.         beginline(0);            /* cursor in column 0 */
  1736.         truncate_line(FALSE);   /* delete the rest of the line */
  1737.                     /* leave cursor past last char in line */
  1738.         if (oap->line_count > 1)
  1739.         u_clearline();        /* "U" command not possible after "2cc" */
  1740.     }
  1741.     else
  1742.     {
  1743.         del_lines(oap->line_count, TRUE);
  1744.         beginline(BL_WHITE | BL_FIX);
  1745.         u_clearline();    /* "U" command not possible after "dd" */
  1746.     }
  1747.     }
  1748.     else
  1749.     {
  1750. #ifdef FEAT_VIRTUALEDIT
  1751.     if (virtual_op)
  1752.     {
  1753.         int        endcol = 0;
  1754.  
  1755.         /* For virtualedit: break the tabs that are partly included. */
  1756.         if (gchar_pos(&oap->start) == '\t')
  1757.         {
  1758.         if (u_save_cursor() == FAIL)    /* save first line for undo */
  1759.             return FAIL;
  1760.         if (oap->line_count == 1)
  1761.             endcol = getviscol2(oap->end.col, oap->end.coladd);
  1762.         coladvance_force(getviscol2(oap->start.col, oap->start.coladd));
  1763.         oap->start = curwin->w_cursor;
  1764.         if (oap->line_count == 1)
  1765.         {
  1766.             coladvance(endcol);
  1767.             oap->end.col = curwin->w_cursor.col;
  1768.             oap->end.coladd = curwin->w_cursor.coladd;
  1769.             curwin->w_cursor = oap->start;
  1770.         }
  1771.         }
  1772.  
  1773.         /* Break a tab only when it's included in the area. */
  1774.         if (gchar_pos(&oap->end) == '\t'
  1775.                      && (int)oap->end.coladd < oap->inclusive)
  1776.         {
  1777.         /* save last line for undo */
  1778.         if (u_save((linenr_T)(oap->end.lnum - 1),
  1779.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  1780.             return FAIL;
  1781.         curwin->w_cursor = oap->end;
  1782.         coladvance_force(getviscol2(oap->end.col, oap->end.coladd));
  1783.         oap->end = curwin->w_cursor;
  1784.         curwin->w_cursor = oap->start;
  1785.         }
  1786.     }
  1787. #endif
  1788.  
  1789.     if (oap->line_count == 1)    /* delete characters within one line */
  1790.     {
  1791.         if (u_save_cursor() == FAIL)    /* save line for undo */
  1792.         return FAIL;
  1793.  
  1794.         /* if 'cpoptions' contains '$', display '$' at end of change */
  1795.         if (       vim_strchr(p_cpo, CPO_DOLLAR) != NULL
  1796.             && oap->op_type == OP_CHANGE
  1797.             && oap->end.lnum == curwin->w_cursor.lnum
  1798. #ifdef FEAT_VISUAL
  1799.             && !oap->is_VIsual
  1800. #endif
  1801.             )
  1802.         display_dollar(oap->end.col - !oap->inclusive);
  1803.  
  1804.         n = oap->end.col - oap->start.col + 1 - !oap->inclusive;
  1805.  
  1806. #ifdef FEAT_VIRTUALEDIT
  1807.         if (virtual_op)
  1808.         {
  1809.         /* fix up things for virtualedit-delete:
  1810.          * break the tabs which are going to get in our way
  1811.          */
  1812.         char_u        *curline = ml_get_curline();
  1813.         int        len = (int)STRLEN(curline);
  1814.  
  1815.         if (oap->end.coladd != 0
  1816.             && (int)oap->end.col >= len - 1
  1817.             && !(oap->start.coladd && (int)oap->end.col >= len - 1))
  1818.             n++;
  1819.         /* Delete at least one char (e.g, when on a control char). */
  1820.         if (n == 0 && oap->start.coladd != oap->end.coladd)
  1821.             n = 1;
  1822.  
  1823.         /* When deleted a char in the line, reset coladd. */
  1824.         if (gchar_cursor() != NUL)
  1825.             curwin->w_cursor.coladd = 0;
  1826.         }
  1827. #endif
  1828.         (void)del_bytes((long)n, restart_edit == NUL && !virtual_op);
  1829.     }
  1830.     else                /* delete characters between lines */
  1831.     {
  1832.         pos_T   curpos;
  1833.  
  1834.         /* save deleted and changed lines for undo */
  1835.         if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
  1836.          (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
  1837.         return FAIL;
  1838.  
  1839.         truncate_line(TRUE);    /* delete from cursor to end of line */
  1840.  
  1841.         curpos = curwin->w_cursor;    /* remember curwin->w_cursor */
  1842.         ++curwin->w_cursor.lnum;
  1843.         del_lines((long)(oap->line_count - 2), FALSE);
  1844.  
  1845.         /* delete from start of line until op_end */
  1846.         curwin->w_cursor.col = 0;
  1847.         (void)del_bytes((long)(oap->end.col + 1 - !oap->inclusive),
  1848.                     restart_edit == NUL && !virtual_op);
  1849.         curwin->w_cursor = curpos;        /* restore curwin->w_cursor */
  1850.  
  1851.         (void)do_join(FALSE);
  1852.     }
  1853.     }
  1854.  
  1855.     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  1856.  
  1857. #ifdef FEAT_VISUAL
  1858.     if (oap->block_mode)
  1859.     {
  1860.     curbuf->b_op_end.lnum = oap->end.lnum;
  1861.     curbuf->b_op_end.col = oap->start.col;
  1862.     }
  1863.     else
  1864. #endif
  1865.     curbuf->b_op_end = oap->start;
  1866.     curbuf->b_op_start = oap->start;
  1867.  
  1868.     return OK;
  1869. }
  1870.  
  1871. #ifdef FEAT_MBYTE
  1872. /*
  1873.  * Adjust end of operating area for ending on a multi-byte character.
  1874.  * Used for deletion.
  1875.  */
  1876.     static void
  1877. mb_adjust_opend(oap)
  1878.     oparg_T    *oap;
  1879. {
  1880.     char_u    *p;
  1881.  
  1882.     if (oap->inclusive)
  1883.     {
  1884.     p = ml_get(oap->end.lnum);
  1885.     oap->end.col += mb_tail_off(p, p + oap->end.col);
  1886.     }
  1887. }
  1888. #endif
  1889.  
  1890. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  1891. /*
  1892.  * Replace a whole area with one character.
  1893.  */
  1894.     int
  1895. op_replace(oap, c)
  1896.     oparg_T   *oap;
  1897.     int        c;
  1898. {
  1899.     int            n, numc;
  1900.     char_u        *newp, *oldp;
  1901.     size_t        oldlen;
  1902.     struct block_def    bd;
  1903.  
  1904.     if ((curbuf->b_ml.ml_flags & ML_EMPTY ) || oap->empty)
  1905.     return OK;        /* nothing to do */
  1906.  
  1907. #ifdef FEAT_MBYTE
  1908.     if (has_mbyte)
  1909.     mb_adjust_opend(oap);
  1910. #endif
  1911.  
  1912.     if (u_save((linenr_T)(oap->start.lnum - 1),
  1913.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  1914.     return FAIL;
  1915.  
  1916.     /*
  1917.      * block mode replace
  1918.      */
  1919.     if (oap->block_mode)
  1920.     {
  1921.     bd.is_MAX = (curwin->w_curswant == MAXCOL);
  1922.     for ( ; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum)
  1923.     {
  1924.         block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE);
  1925.         if (bd.textlen == 0 && !virtual_op)    /* nothing to delete */
  1926.         continue;
  1927.  
  1928.         /* n == number of extra chars required
  1929.          * If we split a TAB, it may be replaced by several characters.
  1930.          * Thus the number of characters may increase!
  1931.          */
  1932. #ifdef FEAT_VIRTUALEDIT
  1933.         /* If the range starts in virtual space, count the initial
  1934.          * coladd offset as part of "startspaces" */
  1935.         if (virtual_op && bd.is_short && *bd.textstart == NUL)
  1936.         {
  1937.         pos_T vpos;
  1938.  
  1939.         getvpos(&vpos, oap->start_vcol);
  1940.         bd.startspaces += vpos.coladd;
  1941.         n = bd.startspaces;
  1942.         }
  1943.         else
  1944. #endif
  1945.         /* allow for pre spaces */
  1946.         n = (bd.startspaces ? bd.start_char_vcols - 1 : 0);
  1947.  
  1948.         /* allow for post spp */
  1949.         n += (bd.endspaces
  1950. #ifdef FEAT_VIRTUALEDIT
  1951.             && !bd.is_oneChar
  1952. #endif
  1953.             && bd.end_char_vcols > 0 ? bd.end_char_vcols - 1 : 0);
  1954.         /* Figure out how many characters to replace. */
  1955.         numc = oap->end_vcol - oap->start_vcol + 1;
  1956.         if (bd.is_short && (!virtual_op || bd.is_MAX))
  1957.         numc -= (oap->end_vcol - bd.end_vcol) + 1;
  1958.         /* oldlen includes textlen, so don't double count */
  1959.         n += numc - bd.textlen;
  1960.  
  1961.         oldp = ml_get_curline();
  1962.         oldlen = STRLEN(oldp);
  1963.         newp = alloc_check((unsigned)oldlen + 1 + n);
  1964.         if (newp == NULL)
  1965.         continue;
  1966.         vim_memset(newp, NUL, (size_t)(oldlen + 1 + n));
  1967.         /* copy up to deleted part */
  1968.         mch_memmove(newp, oldp, (size_t)bd.textcol);
  1969.         oldp += bd.textcol + bd.textlen;
  1970.         /* insert pre-spaces */
  1971.         copy_spaces(newp + bd.textcol, (size_t)bd.startspaces);
  1972.         /* insert replacement chars CHECK FOR ALLOCATED SPACE */
  1973.         copy_chars(newp + STRLEN(newp), (size_t)numc, c);
  1974.         if (!bd.is_short)
  1975.         {
  1976.         /* insert post-spaces */
  1977.         copy_spaces(newp + STRLEN(newp), (size_t)bd.endspaces);
  1978.         /* copy the part after the changed part */
  1979.         mch_memmove(newp + STRLEN(newp), oldp, STRLEN(oldp) + 1);
  1980.         }
  1981.         /* replace the line */
  1982.         ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  1983.     }
  1984.     }
  1985.     else
  1986.     {
  1987.     /*
  1988.      * MCHAR and MLINE motion replace.
  1989.      */
  1990.     if (oap->motion_type == MLINE)
  1991.     {
  1992.         oap->start.col = 0;
  1993.         curwin->w_cursor.col = 0;
  1994.         oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  1995.         if (oap->end.col)
  1996.         --oap->end.col;
  1997.     }
  1998.     else if (!oap->inclusive)
  1999.         dec(&(oap->end));
  2000.  
  2001.     while (ltoreq(curwin->w_cursor, oap->end))
  2002.     {
  2003.         n = gchar_cursor();
  2004.         if (n != NUL)
  2005.         {
  2006. #ifdef FEAT_MBYTE
  2007.         if ((*mb_char2len)(c) > 1 || (*mb_char2len)(n) > 1)
  2008.         {
  2009.             /* This is slow, but it handles replacing a single-byte
  2010.              * with a multi-byte and the other way around. */
  2011.             n = State;
  2012.             State = REPLACE;
  2013.             ins_char(c);
  2014.             State = n;
  2015.         }
  2016.         else
  2017. #endif
  2018.         {
  2019. #ifdef FEAT_VIRTUALEDIT
  2020.             if (n == TAB)
  2021.             {
  2022.             int end_vcol = 0;
  2023.  
  2024.             if (curwin->w_cursor.lnum == oap->end.lnum)
  2025.             {
  2026.                 /* oap->end has to be recalculated when
  2027.                  * the tab breaks */
  2028.                 end_vcol = getviscol2(oap->end.col,
  2029.                                  oap->end.coladd);
  2030.             }
  2031.             coladvance_force(getviscol());
  2032.             if (curwin->w_cursor.lnum == oap->end.lnum)
  2033.                 getvpos(&oap->end, end_vcol);
  2034.             }
  2035. #endif
  2036.             pchar(curwin->w_cursor, c);
  2037.         }
  2038.         }
  2039. #ifdef FEAT_VIRTUALEDIT
  2040.         else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum)
  2041.         {
  2042.         int virtcols = oap->end.coladd;
  2043.  
  2044.         if (curwin->w_cursor.lnum == oap->start.lnum
  2045.             && oap->start.col == oap->end.col && oap->start.coladd)
  2046.             virtcols -= oap->start.coladd;
  2047.  
  2048.         /* oap->end has been trimmed so it's effectively inclusive;
  2049.          * as a result an extra +1 must be counted so we don't
  2050.          * trample the NUL byte. */
  2051.         coladvance_force(getviscol2(oap->end.col, oap->end.coladd) + 1);
  2052.         curwin->w_cursor.col -= (virtcols + 1);
  2053.         for (; virtcols >= 0; virtcols--)
  2054.         {
  2055.             pchar(curwin->w_cursor, c);
  2056.             if (inc(&curwin->w_cursor) == -1)
  2057.             break;
  2058.         }
  2059.         }
  2060. #endif
  2061.  
  2062.         /* Advance to next character, stop at the end of the file. */
  2063.         if (inc(&curwin->w_cursor) == -1)
  2064.         break;
  2065.     }
  2066.     }
  2067.  
  2068.     curwin->w_cursor = oap->start;
  2069.     check_cursor();
  2070.     changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L);
  2071.  
  2072.     /* Set "'[" and "']" marks. */
  2073.     curbuf->b_op_start = oap->start;
  2074.     curbuf->b_op_end = oap->end;
  2075.  
  2076.     return OK;
  2077. }
  2078. #endif
  2079.  
  2080. /*
  2081.  * Handle the (non-standard vi) tilde operator.  Also for "gu", "gU" and "g?".
  2082.  */
  2083.     void
  2084. op_tilde(oap)
  2085.     oparg_T    *oap;
  2086. {
  2087.     pos_T        pos;
  2088. #ifdef FEAT_VISUAL
  2089.     struct block_def    bd;
  2090. #endif
  2091.     int            did_change = 0;
  2092.  
  2093.     if (u_save((linenr_T)(oap->start.lnum - 1),
  2094.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  2095.     return;
  2096.  
  2097.     pos = oap->start;
  2098. #ifdef FEAT_VISUAL
  2099.     if (oap->block_mode)            /* Visual block mode */
  2100.     {
  2101.     for (; pos.lnum <= oap->end.lnum; ++pos.lnum)
  2102.     {
  2103.         block_prep(oap, &bd, pos.lnum, FALSE);
  2104.         pos.col = bd.textcol;
  2105.         while (--bd.textlen >= 0)
  2106.         {
  2107.         did_change |= swapchar(oap->op_type, &pos);
  2108.         if (inc(&pos) == -1)        /* at end of file */
  2109.             break;
  2110.         }
  2111.     }
  2112.     if (did_change)
  2113.         changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
  2114.     }
  2115.     else                    /* not block mode */
  2116. #endif
  2117.     {
  2118.     if (oap->motion_type == MLINE)
  2119.     {
  2120.         oap->start.col = 0;
  2121.         pos.col = 0;
  2122.         oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  2123.         if (oap->end.col)
  2124.         --oap->end.col;
  2125.     }
  2126.     else if (!oap->inclusive)
  2127.         dec(&(oap->end));
  2128.  
  2129.     while (ltoreq(pos, oap->end))
  2130.     {
  2131.         did_change |= swapchar(oap->op_type, &pos);
  2132.         if (inc(&pos) == -1)    /* at end of file */
  2133.         break;
  2134.     }
  2135.     if (did_change)
  2136.         changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1,
  2137.                                       0L);
  2138.     }
  2139.  
  2140. #ifdef FEAT_VISUAL
  2141.     if (!did_change && oap->is_VIsual)
  2142.     /* No change: need to remove the Visual selection */
  2143.     redraw_curbuf_later(INVERTED);
  2144. #endif
  2145.  
  2146.     /*
  2147.      * Set '[ and '] marks.
  2148.      */
  2149.     curbuf->b_op_start = oap->start;
  2150.     curbuf->b_op_end = oap->end;
  2151.  
  2152.     if (oap->line_count > p_report)
  2153.     {
  2154.     if (oap->line_count == 1)
  2155.         MSG(_("1 line changed"));
  2156.     else
  2157.         smsg((char_u *)_("%ld lines changed"), oap->line_count);
  2158.     }
  2159. }
  2160.  
  2161. /*
  2162.  * If op_type == OP_UPPER: make uppercase,
  2163.  * if op_type == OP_LOWER: make lowercase,
  2164.  * if op_type == OP_ROT13: do rot13 encoding,
  2165.  * else swap case of character at 'pos'
  2166.  * returns TRUE when something actually changed.
  2167.  */
  2168.     int
  2169. swapchar(op_type, pos)
  2170.     int        op_type;
  2171.     pos_T    *pos;
  2172. {
  2173.     int        c;
  2174.     int        nc;
  2175.  
  2176.     c = gchar_pos(pos);
  2177.  
  2178.     /* Only do rot13 encoding for ASCII characters. */
  2179.     if (c >= 0x80 && op_type == OP_ROT13)
  2180.     return FALSE;
  2181.  
  2182. #ifdef FEAT_MBYTE
  2183.     if (enc_dbcs != 0 && c >= 0x100)    /* No lower/uppercase letter */
  2184.     return FALSE;
  2185. #endif
  2186.     nc = c;
  2187.     if (MB_ISLOWER(c))
  2188.     {
  2189.     if (op_type == OP_ROT13)
  2190.         nc = ROT13(c, 'a');
  2191.     else if (op_type != OP_LOWER)
  2192.         nc = MB_TOUPPER(c);
  2193.     }
  2194.     else if (MB_ISUPPER(c))
  2195.     {
  2196.     if (op_type == OP_ROT13)
  2197.         nc = ROT13(c, 'A');
  2198.     else if (op_type != OP_UPPER)
  2199.         nc = MB_TOLOWER(c);
  2200.     }
  2201.     if (nc != c)
  2202.     {
  2203. #ifdef FEAT_MBYTE
  2204.     if (enc_utf8 && (c >= 0x80 || nc >= 0x80))
  2205.     {
  2206.         pos_T   sp = curwin->w_cursor;
  2207.  
  2208.         curwin->w_cursor = *pos;
  2209.         del_char(FALSE);
  2210.         ins_char(nc);
  2211.         curwin->w_cursor = sp;
  2212.     }
  2213.     else
  2214. #endif
  2215.         pchar(*pos, nc);
  2216.     return TRUE;
  2217.     }
  2218.     return FALSE;
  2219. }
  2220.  
  2221. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  2222. /*
  2223.  * op_insert - Insert and append operators for Visual mode.
  2224.  */
  2225.     void
  2226. op_insert(oap, count1)
  2227.     oparg_T    *oap;
  2228.     long    count1;
  2229. {
  2230.     long        ins_len, pre_textlen = 0;
  2231.     char_u        *firstline, *ins_text;
  2232.     struct block_def    bd;
  2233.     int            i;
  2234.  
  2235.     /* edit() changes this - record it for OP_APPEND */
  2236.     bd.is_MAX = (curwin->w_curswant == MAXCOL);
  2237.  
  2238.     /* vis block is still marked. Get rid of it now. */
  2239.     curwin->w_cursor.lnum = oap->start.lnum;
  2240.     update_screen(INVERTED);
  2241.  
  2242.     if (oap->block_mode)
  2243.     {
  2244. #ifdef FEAT_VIRTUALEDIT
  2245.     /* When 'virtualedit' is used, need to insert the extra spaces before
  2246.      * doing block_prep().  When only "block" is used, virtual edit is
  2247.      * already disabled, but still need it when calling
  2248.      * coladvance_force(). */
  2249.     if (curwin->w_cursor.coladd > 0)
  2250.     {
  2251.         int        old_ve_flags = ve_flags;
  2252.  
  2253.         ve_flags = VE_ALL;
  2254.         if (u_save_cursor() == FAIL)
  2255.         return;
  2256.         coladvance_force(oap->op_type == OP_APPEND
  2257.                        ? oap->end_vcol + 1 : getviscol());
  2258.         if (oap->op_type == OP_APPEND)
  2259.         --curwin->w_cursor.col;
  2260.         ve_flags = old_ve_flags;
  2261.     }
  2262. #endif
  2263.     /* Get the info about the block before entering the text */
  2264.     block_prep(oap, &bd, oap->start.lnum, TRUE);
  2265.     firstline = ml_get(oap->start.lnum) + bd.textcol;
  2266.     if (oap->op_type == OP_APPEND)
  2267.         firstline += bd.textlen;
  2268.     pre_textlen = (long)STRLEN(firstline);
  2269.     }
  2270.  
  2271.     if (oap->op_type == OP_APPEND)
  2272.     {
  2273.     if (oap->block_mode
  2274. #ifdef FEAT_VIRTUALEDIT
  2275.         && curwin->w_cursor.coladd == 0
  2276. #endif
  2277.        )
  2278.     {
  2279.         /* Move the cursor to the character right of the block. */
  2280.         curwin->w_set_curswant = TRUE;
  2281.         while (*ml_get_cursor() != NUL
  2282.             && (curwin->w_cursor.col < bd.textcol + bd.textlen))
  2283.         ++curwin->w_cursor.col;
  2284.         if (bd.is_short && !bd.is_MAX)
  2285.         {
  2286.         /* First line was too short, make it longer and adjust the
  2287.          * values in "bd". */
  2288.         if (u_save_cursor() == FAIL)
  2289.             return;
  2290.         for (i = 0; i < bd.endspaces; ++i)
  2291.             ins_char(' ');
  2292.         bd.textlen += bd.endspaces;
  2293.         }
  2294.     }
  2295.     else
  2296.     {
  2297.         curwin->w_cursor = oap->end;
  2298.  
  2299.         /* Works just like an 'i'nsert on the next character. */
  2300.         if (!lineempty(curwin->w_cursor.lnum)
  2301.             && oap->start_vcol != oap->end_vcol)
  2302.         inc_cursor();
  2303.     }
  2304.     }
  2305.  
  2306.     edit(NUL, FALSE, (linenr_T)count1);
  2307.  
  2308.     /* if user has moved off this line, we don't know what to do, so do
  2309.      * nothing */
  2310.     if (curwin->w_cursor.lnum != oap->start.lnum)
  2311.     return;
  2312.  
  2313.     if (oap->block_mode)
  2314.     {
  2315.     struct block_def    bd2;
  2316.  
  2317.     /*
  2318.      * Spaces and tabs in the indent may have changed to other spaces and
  2319.      * tabs.  Get the starting column again and correct the lenght.
  2320.      * Don't do this when "$" used, end-of-line will have changed.
  2321.      */
  2322.     block_prep(oap, &bd2, oap->start.lnum, TRUE);
  2323.     if (!bd.is_MAX || bd2.textlen < bd.textlen)
  2324.     {
  2325.         if (oap->op_type == OP_APPEND)
  2326.         {
  2327.         pre_textlen += bd2.textlen - bd.textlen;
  2328.         if (bd2.endspaces)
  2329.             --bd2.textlen;
  2330.         }
  2331.         bd.textcol = bd2.textcol;
  2332.         bd.textlen = bd2.textlen;
  2333.     }
  2334.  
  2335.     /*
  2336.      * Subsequent calls to ml_get() flush the firstline data - take a
  2337.      * copy of the required string.
  2338.      */
  2339.     firstline = ml_get(oap->start.lnum) + bd.textcol;
  2340.     if (oap->op_type == OP_APPEND)
  2341.         firstline += bd.textlen;
  2342.     if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
  2343.     {
  2344.         ins_text = vim_strnsave(firstline, (int)ins_len);
  2345.         if (ins_text != NULL)
  2346.         {
  2347.         /* block handled here */
  2348.         if (u_save(oap->start.lnum,
  2349.                      (linenr_T)(oap->end.lnum + 1)) == OK)
  2350.             block_insert(oap, ins_text, (oap->op_type == OP_INSERT),
  2351.                                      &bd);
  2352.  
  2353.         curwin->w_cursor.col = oap->start.col;
  2354.         check_cursor();
  2355.         vim_free(ins_text);
  2356.         }
  2357.     }
  2358.     }
  2359. }
  2360. #endif
  2361.  
  2362. /*
  2363.  * op_change - handle a change operation
  2364.  *
  2365.  * return TRUE if edit() returns because of a CTRL-O command
  2366.  */
  2367.     int
  2368. op_change(oap)
  2369.     oparg_T    *oap;
  2370. {
  2371.     colnr_T        l;
  2372.     int            retval;
  2373. #ifdef FEAT_VISUALEXTRA
  2374.     long        offset;
  2375.     linenr_T        linenr;
  2376.     long        ins_len, pre_textlen = 0;
  2377.     char_u        *firstline;
  2378.     char_u        *ins_text, *newp, *oldp;
  2379.     struct block_def    bd;
  2380. #endif
  2381.  
  2382.     l = oap->start.col;
  2383.     if (oap->motion_type == MLINE)
  2384.     {
  2385.     l = 0;
  2386. #ifdef FEAT_SMARTINDENT
  2387.     if (!p_paste && curbuf->b_p_si
  2388. # ifdef FEAT_CINDENT
  2389.         && !curbuf->b_p_cin
  2390. # endif
  2391.         )
  2392.         can_si = TRUE;    /* It's like opening a new line, do si */
  2393. #endif
  2394.     }
  2395.  
  2396.     /* First delete the text in the region.  In an empty buffer only need to
  2397.      * save for undo */
  2398.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  2399.     {
  2400.     if (u_save_cursor() == FAIL)
  2401.         return FALSE;
  2402.     }
  2403.     else if (op_delete(oap) == FAIL)
  2404.     return FALSE;
  2405.  
  2406.     if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum)
  2407.                              && !virtual_op)
  2408.     inc_cursor();
  2409.  
  2410. #ifdef FEAT_VISUALEXTRA
  2411.     /* check for still on same line (<CR> in inserted text meaningless) */
  2412.     /* skip blank lines too */
  2413.     if (oap->block_mode)
  2414.     {
  2415. # ifdef FEAT_VIRTUALEDIT
  2416.     /* Add spaces before getting the current line length. */
  2417.     if (virtual_op && (curwin->w_cursor.coladd > 0
  2418.                             || gchar_cursor() == NUL))
  2419.         coladvance_force(getviscol());
  2420. # endif
  2421.     pre_textlen = (long)STRLEN(ml_get(oap->start.lnum));
  2422.     bd.textcol = curwin->w_cursor.col;
  2423.     }
  2424. #endif
  2425.  
  2426. #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
  2427.     if (oap->motion_type == MLINE)
  2428.     fix_indent();
  2429. #endif
  2430.  
  2431.     retval = edit(NUL, FALSE, (linenr_T)1);
  2432.  
  2433. #ifdef FEAT_VISUALEXTRA
  2434.     /*
  2435.      * In Visual block mode, handle copying the next text to all lines of the
  2436.      * block.
  2437.      */
  2438.     if (oap->block_mode && oap->start.lnum != oap->end.lnum)
  2439.     {
  2440.     firstline = ml_get(oap->start.lnum);
  2441.     /*
  2442.      * Subsequent calls to ml_get() flush the firstline data - take a
  2443.      * copy of the required bit.
  2444.      */
  2445.     if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
  2446.     {
  2447.         if ((ins_text = alloc_check((unsigned)(ins_len + 1))) != NULL)
  2448.         {
  2449.         STRNCPY(ins_text, firstline + bd.textcol, ins_len);
  2450.         ins_text[ins_len] = NUL;
  2451.         for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum;
  2452.                                      linenr++)
  2453.         {
  2454.             block_prep(oap, &bd, linenr, TRUE);
  2455.             if (!bd.is_short || virtual_op)
  2456.             {
  2457. # ifdef FEAT_VIRTUALEDIT
  2458.             pos_T vpos;
  2459.  
  2460.             /* If the block starts in virtual space, count the
  2461.              * initial coladd offset as part of "startspaces" */
  2462.             if (bd.is_short)
  2463.             {
  2464.                 linenr_T lnum = curwin->w_cursor.lnum;
  2465.  
  2466.                 curwin->w_cursor.lnum = linenr;
  2467.                 (void)getvpos(&vpos, oap->start_vcol);
  2468.                 curwin->w_cursor.lnum = lnum;
  2469.             }
  2470.             else
  2471.                 vpos.coladd = 0;
  2472. # endif
  2473.             oldp = ml_get(linenr);
  2474.             newp = alloc_check((unsigned)(STRLEN(oldp)
  2475. # ifdef FEAT_VIRTUALEDIT
  2476.                             + vpos.coladd
  2477. # endif
  2478.                                   + ins_len + 1));
  2479.             if (newp == NULL)
  2480.                 continue;
  2481.             /* copy up to block start */
  2482.             mch_memmove(newp, oldp, (size_t)bd.textcol);
  2483.             offset = bd.textcol;
  2484. # ifdef FEAT_VIRTUALEDIT
  2485.             copy_spaces(newp + offset, (size_t)vpos.coladd);
  2486.             offset += vpos.coladd;
  2487. # endif
  2488.             mch_memmove(newp + offset, ins_text, (size_t)ins_len);
  2489.             offset += ins_len;
  2490.             oldp += bd.textcol;
  2491.             mch_memmove(newp + offset, oldp, STRLEN(oldp) + 1);
  2492.             ml_replace(linenr, newp, FALSE);
  2493.             }
  2494.         }
  2495.         check_cursor();
  2496.  
  2497.         changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L);
  2498.         }
  2499.         vim_free(ins_text);
  2500.     }
  2501.     }
  2502. #endif
  2503.  
  2504.     return retval;
  2505. }
  2506.  
  2507. /*
  2508.  * set all the yank registers to empty (called from main())
  2509.  */
  2510.     void
  2511. init_yank()
  2512. {
  2513.     int        i;
  2514.  
  2515.     for (i = 0; i < NUM_REGISTERS; ++i)
  2516.     y_regs[i].y_array = NULL;
  2517. }
  2518.  
  2519. /*
  2520.  * Free "n" lines from the current yank register.
  2521.  * Called for normal freeing and in case of error.
  2522.  */
  2523.     static void
  2524. free_yank(n)
  2525.     long    n;
  2526. {
  2527.     if (y_current->y_array != NULL)
  2528.     {
  2529.     long        i;
  2530.  
  2531.     for (i = n; --i >= 0; )
  2532.     {
  2533. #ifdef AMIGA        /* only for very slow machines */
  2534.         if ((i & 1023) == 1023)  /* this may take a while */
  2535.         {
  2536.         /*
  2537.          * This message should never cause a hit-return message.
  2538.          * Overwrite this message with any next message.
  2539.          */
  2540.         ++no_wait_return;
  2541.         smsg((char_u *)_("freeing %ld lines"), i + 1);
  2542.         --no_wait_return;
  2543.         msg_didout = FALSE;
  2544.         msg_col = 0;
  2545.         }
  2546. #endif
  2547.         vim_free(y_current->y_array[i]);
  2548.     }
  2549.     vim_free(y_current->y_array);
  2550.     y_current->y_array = NULL;
  2551. #ifdef AMIGA
  2552.     if (n >= 1000)
  2553.         MSG("");
  2554. #endif
  2555.     }
  2556. }
  2557.  
  2558.     static void
  2559. free_yank_all()
  2560. {
  2561.     free_yank(y_current->y_size);
  2562. }
  2563.  
  2564. /*
  2565.  * Yank the text between curwin->w_cursor and startpos into a yank register.
  2566.  * If we are to append (uppercase register), we first yank into a new yank
  2567.  * register and then concatenate the old and the new one (so we keep the old
  2568.  * one in case of out-of-memory).
  2569.  *
  2570.  * return FAIL for failure, OK otherwise
  2571.  */
  2572.     int
  2573. op_yank(oap, deleting, mess)
  2574.     oparg_T   *oap;
  2575.     int        deleting;
  2576.     int        mess;
  2577. {
  2578.     long        y_idx;        /* index in y_array[] */
  2579.     struct yankreg    *curr;        /* copy of y_current */
  2580.     struct yankreg    newreg;        /* new yank register when appending */
  2581.     char_u        **new_ptr;
  2582.     linenr_T        lnum;        /* current line number */
  2583.     long        j;
  2584.     int            yanktype = oap->motion_type;
  2585.     long        yanklines = oap->line_count;
  2586.     linenr_T        yankendlnum = oap->end.lnum;
  2587.     char_u        *p;
  2588.     char_u        *pnew;
  2589.     struct block_def    bd;
  2590.  
  2591.                     /* check for read-only register */
  2592.     if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
  2593.     {
  2594.     beep_flush();
  2595.     return FAIL;
  2596.     }
  2597.     if (oap->regname == '_')        /* black hole: nothing to do */
  2598.     return OK;
  2599.  
  2600. #ifdef FEAT_CLIPBOARD
  2601.     if (!clip_star.available && oap->regname == '*')
  2602.     oap->regname = 0;
  2603.     else if (!clip_plus.available && oap->regname == '+')
  2604.     oap->regname = 0;
  2605. #endif
  2606.  
  2607.     if (!deleting)            /* op_delete() already set y_current */
  2608.     get_yank_register(oap->regname, TRUE);
  2609.  
  2610.     curr = y_current;
  2611.                     /* append to existing contents */
  2612.     if (y_append && y_current->y_array != NULL)
  2613.     y_current = &newreg;
  2614.     else
  2615.     free_yank_all();        /* free previously yanked lines */
  2616.  
  2617. /*
  2618.  * If the cursor was in column 1 before and after the movement, and the
  2619.  * operator is not inclusive, the yank is always linewise.
  2620.  */
  2621.     if (       oap->motion_type == MCHAR
  2622.         && oap->start.col == 0
  2623.         && !oap->inclusive
  2624. #ifdef FEAT_VISUAL
  2625.         && (!oap->is_VIsual || *p_sel == 'o')
  2626. #endif
  2627.         && oap->end.col == 0
  2628.         && yanklines > 1)
  2629.     {
  2630.     yanktype = MLINE;
  2631.     --yankendlnum;
  2632.     --yanklines;
  2633.     }
  2634.  
  2635.     y_current->y_size = yanklines;
  2636.     y_current->y_type = yanktype;   /* set the yank register type */
  2637. #ifdef FEAT_VISUAL
  2638.     y_current->y_width = 0;
  2639. #endif
  2640.     y_current->y_array = (char_u **)lalloc_clear((long_u)(sizeof(char_u *) *
  2641.                                 yanklines), TRUE);
  2642.  
  2643.     if (y_current->y_array == NULL)
  2644.     {
  2645.     y_current = curr;
  2646.     return FAIL;
  2647.     }
  2648.  
  2649.     y_idx = 0;
  2650.     lnum = oap->start.lnum;
  2651.  
  2652. #ifdef FEAT_VISUAL
  2653.     if (oap->block_mode)
  2654.     {
  2655.     /* Visual block mode */
  2656.     y_current->y_type = MBLOCK;        /* set the yank register type */
  2657.     y_current->y_width = oap->end_vcol - oap->start_vcol;
  2658.  
  2659.     if (curwin->w_curswant == MAXCOL && y_current->y_width > 0)
  2660.         y_current->y_width--;
  2661.     }
  2662. #endif
  2663.  
  2664.     for ( ; lnum <= yankendlnum; lnum++, y_idx++)
  2665.     {
  2666.     switch (y_current->y_type)
  2667.     {
  2668. #ifdef FEAT_VISUAL
  2669.         case MBLOCK:
  2670.         block_prep(oap, &bd, lnum, FALSE);
  2671.         if (yank_copy_line(&bd, y_idx) == FAIL)
  2672.             goto fail;
  2673.         break;
  2674. #endif
  2675.  
  2676.         case MLINE:
  2677.         if ((y_current->y_array[y_idx] =
  2678.                 vim_strsave(ml_get(lnum))) == NULL)
  2679.             goto fail;
  2680.         break;
  2681.  
  2682.         case MCHAR:
  2683.         {
  2684.             colnr_T startcol = 0, endcol = MAXCOL;
  2685. #ifdef FEAT_VIRTUALEDIT
  2686.             int is_oneChar = FALSE;
  2687.             colnr_T cs, ce;
  2688. #endif
  2689.             p = ml_get(lnum);
  2690.             bd.startspaces = 0;
  2691.             bd.endspaces = 0;
  2692.  
  2693.             if (lnum == oap->start.lnum)
  2694.             {
  2695.             startcol = oap->start.col;
  2696. #ifdef FEAT_VIRTUALEDIT
  2697.             if (virtual_op)
  2698.             {
  2699.                 getvcol(curwin, &oap->start, &cs, NUL, &ce);
  2700.                 if (ce != cs && oap->start.coladd > 0)
  2701.                 {
  2702.                 /* Part of a tab selected -- but don't
  2703.                  * double-count it. */
  2704.                 bd.startspaces = (ce - cs + 1)
  2705.                               - oap->start.coladd;
  2706.                 startcol++;
  2707.                 }
  2708.             }
  2709. #endif
  2710.             }
  2711.  
  2712.             if (lnum == oap->end.lnum)
  2713.             {
  2714.             endcol = oap->end.col;
  2715. #ifdef FEAT_VIRTUALEDIT
  2716.             if (virtual_op)
  2717.             {
  2718.                 getvcol(curwin, &oap->end, &cs, NUL, &ce);
  2719.                 if (p[endcol] == NUL || (cs + oap->end.coladd < ce
  2720. # ifdef FEAT_MBYTE
  2721.                     /* Don't add space for double-wide
  2722.                      * char; endcol will be on last byte
  2723.                      * of multi-byte char. */
  2724.                     && (*mb_head_off)(p, p + endcol) == 0
  2725. # endif
  2726.                     ))
  2727.                 {
  2728.                 if (oap->start.lnum == oap->end.lnum
  2729.                         && oap->start.col == oap->end.col)
  2730.                 {
  2731.                     /* Special case: inside a single char */
  2732.                     is_oneChar = TRUE;
  2733.                     bd.startspaces = oap->end.coladd
  2734.                      - oap->start.coladd + oap->inclusive;
  2735.                     endcol = startcol;
  2736.                 }
  2737.                 else
  2738.                 {
  2739.                     bd.endspaces = oap->end.coladd
  2740.                                  + oap->inclusive;
  2741.                     endcol -= oap->inclusive;
  2742.                 }
  2743.                 }
  2744.             }
  2745. #endif
  2746.             }
  2747.             if (startcol > endcol
  2748. #ifdef FEAT_VIRTUALEDIT
  2749.                 || is_oneChar
  2750. #endif
  2751.                 )
  2752.             bd.textlen = 0;
  2753.             else
  2754.             {
  2755.             if (endcol == MAXCOL)
  2756.                 endcol = STRLEN(p);
  2757.             bd.textlen = endcol - startcol + oap->inclusive;
  2758.             }
  2759.             bd.textstart = p + startcol;
  2760.             if (yank_copy_line(&bd, y_idx) == FAIL)
  2761.             goto fail;
  2762.             break;
  2763.         }
  2764.         /* NOTREACHED */
  2765.     }
  2766.     }
  2767.  
  2768.     if (curr != y_current)    /* append the new block to the old block */
  2769.     {
  2770.     new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) *
  2771.                    (curr->y_size + y_current->y_size)), TRUE);
  2772.     if (new_ptr == NULL)
  2773.         goto fail;
  2774.     for (j = 0; j < curr->y_size; ++j)
  2775.         new_ptr[j] = curr->y_array[j];
  2776.     vim_free(curr->y_array);
  2777.     curr->y_array = new_ptr;
  2778.  
  2779.     if (yanktype == MLINE)    /* MLINE overrides MCHAR and MBLOCK */
  2780.         curr->y_type = MLINE;
  2781.  
  2782.     /* concatenate the last line of the old block with the first line of
  2783.      * the new block */
  2784.     if (curr->y_type == MCHAR)
  2785.     {
  2786.         pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1])
  2787.                   + STRLEN(y_current->y_array[0]) + 1), TRUE);
  2788.         if (pnew == NULL)
  2789.         {
  2790.         y_idx = y_current->y_size - 1;
  2791.         goto fail;
  2792.         }
  2793.         STRCPY(pnew, curr->y_array[--j]);
  2794.         STRCAT(pnew, y_current->y_array[0]);
  2795.         vim_free(curr->y_array[j]);
  2796.         vim_free(y_current->y_array[0]);
  2797.         curr->y_array[j++] = pnew;
  2798.         y_idx = 1;
  2799.     }
  2800.     else
  2801.         y_idx = 0;
  2802.     while (y_idx < y_current->y_size)
  2803.         curr->y_array[j++] = y_current->y_array[y_idx++];
  2804.     curr->y_size = j;
  2805.     vim_free(y_current->y_array);
  2806.     y_current = curr;
  2807.     }
  2808.     if (mess)            /* Display message about yank? */
  2809.     {
  2810.     if (yanktype == MCHAR
  2811. #ifdef FEAT_VISUAL
  2812.         && !oap->block_mode
  2813. #endif
  2814.         && yanklines == 1)
  2815.         yanklines = 0;
  2816.     /* Some versions of Vi use ">=" here, some don't...  */
  2817.     if (yanklines > p_report)
  2818.     {
  2819.         /* redisplay now, so message is not deleted */
  2820.         update_topline_redraw();
  2821.         if (yanklines == 1)
  2822.         MSG(_("1 line yanked"));
  2823.         else
  2824.         smsg((char_u *)_("%ld lines yanked"), yanklines);
  2825.     }
  2826.     }
  2827.  
  2828.     /*
  2829.      * Set "'[" and "']" marks.
  2830.      */
  2831.     curbuf->b_op_start = oap->start;
  2832.     curbuf->b_op_end = oap->end;
  2833.  
  2834. #ifdef FEAT_CLIPBOARD
  2835.     /*
  2836.      * If we were yanking to the '*' register, send result to clipboard.
  2837.      * If no register was specified, and "unnamed" in 'clipboard', make a copy
  2838.      * to the '*' register.
  2839.      */
  2840.     if (clip_star.available
  2841.         && (curr == &(y_regs[STAR_REGISTER])
  2842.         || (!deleting && oap->regname == 0 && clip_unnamed)))
  2843.     {
  2844.     if (curr != &(y_regs[STAR_REGISTER]))
  2845.         /* Copy the text from register 0 to the clipboard register. */
  2846.         copy_yank_reg(&(y_regs[STAR_REGISTER]));
  2847.  
  2848.     clip_own_selection(&clip_star);
  2849.     clip_gen_set_selection(&clip_star);
  2850.     }
  2851.  
  2852. # ifdef FEAT_X11
  2853.     /*
  2854.      * If we were yanking to the '+' register, send result to selection.
  2855.      * Also copy to the '*' register, in case auto-select is off.
  2856.      */
  2857.     else if (clip_plus.available && curr == &(y_regs[PLUS_REGISTER]))
  2858.     {
  2859.     /* No need to copy to * register upon 'unnamed' now - see below */
  2860.     clip_own_selection(&clip_plus);
  2861.     clip_gen_set_selection(&clip_plus);
  2862.     if (!clip_isautosel())
  2863.     {
  2864.         copy_yank_reg(&(y_regs[STAR_REGISTER]));
  2865.         clip_own_selection(&clip_star);
  2866.         clip_gen_set_selection(&clip_star);
  2867.     }
  2868.     }
  2869. # endif
  2870. #endif
  2871.  
  2872.     return OK;
  2873.  
  2874. fail:        /* free the allocated lines */
  2875.     free_yank(y_idx + 1);
  2876.     y_current = curr;
  2877.     return FAIL;
  2878. }
  2879.  
  2880.     static int
  2881. yank_copy_line(bd, y_idx)
  2882.     struct block_def    *bd;
  2883.     long        y_idx;
  2884. {
  2885.     char_u    *pnew;
  2886.  
  2887.     if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1))
  2888.                                       == NULL)
  2889.     return FAIL;
  2890.     y_current->y_array[y_idx] = pnew;
  2891.     copy_spaces(pnew, (size_t)bd->startspaces);
  2892.     pnew += bd->startspaces;
  2893.     mch_memmove(pnew, bd->textstart, (size_t)bd->textlen);
  2894.     pnew += bd->textlen;
  2895.     copy_spaces(pnew, (size_t)bd->endspaces);
  2896.     pnew += bd->endspaces;
  2897.     *pnew = NUL;
  2898.     return OK;
  2899. }
  2900.  
  2901. #ifdef FEAT_CLIPBOARD
  2902. /*
  2903.  * Make a copy of the y_current register to register "reg".
  2904.  */
  2905.     static void
  2906. copy_yank_reg(reg)
  2907.     struct yankreg *reg;
  2908. {
  2909.     struct yankreg    *curr = y_current;
  2910.     long        j;
  2911.  
  2912.     y_current = reg;
  2913.     free_yank_all();
  2914.     *y_current = *curr;
  2915.     y_current->y_array = (char_u **)lalloc_clear(
  2916.             (long_u)(sizeof(char_u *) * y_current->y_size), TRUE);
  2917.     if (y_current->y_array == NULL)
  2918.     y_current->y_size = 0;
  2919.     else
  2920.     for (j = 0; j < y_current->y_size; ++j)
  2921.         if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL)
  2922.         {
  2923.         free_yank(j);
  2924.         y_current->y_size = 0;
  2925.         break;
  2926.         }
  2927.     y_current = curr;
  2928. }
  2929. #endif
  2930.  
  2931. /*
  2932.  * put contents of register "regname" into the text
  2933.  * flags: PUT_FIXINDENT    make indent look nice
  2934.  *      PUT_CURSEND    leave cursor after end of new text
  2935.  *      PUT_LINE    force linewise put (":put")
  2936.  */
  2937.     void
  2938. do_put(regname, dir, count, flags)
  2939.     int        regname;
  2940.     int        dir;        /* BACKWARD for 'P', FORWARD for 'p' */
  2941.     long    count;
  2942.     int        flags;
  2943. {
  2944.     char_u    *ptr;
  2945.     char_u    *newp, *oldp;
  2946.     int        yanklen;
  2947.     int        totlen = 0;        /* init for gcc */
  2948.     linenr_T    lnum;
  2949.     colnr_T    col;
  2950.     long    i;            /* index in y_array[] */
  2951.     int        y_type;
  2952.     long    y_size;
  2953. #ifdef FEAT_VISUAL
  2954.     int        oldlen;
  2955.     long    y_width = 0;
  2956.     colnr_T    vcol;
  2957.     int        delcount;
  2958.     int        incr = 0;
  2959.     long    j;
  2960.     struct block_def bd;
  2961. #endif
  2962.     char_u    **y_array = NULL;
  2963.     long    nr_lines = 0;
  2964.     pos_T    new_cursor;
  2965.     int        indent;
  2966.     int        orig_indent = 0;    /* init for gcc */
  2967.     int        indent_diff = 0;    /* init for gcc */
  2968.     int        first_indent = TRUE;
  2969.     int        lendiff = 0;
  2970.     pos_T    old_pos;
  2971.     char_u    *insert_string = NULL;
  2972.     int        allocated = FALSE;
  2973.     long    cnt;
  2974.  
  2975. #ifdef FEAT_CLIPBOARD
  2976.     /* Adjust register name for "unnamed" in 'clipboard'. */
  2977.     adjust_clip_reg(®name);
  2978.     (void)may_get_selection(regname);
  2979. #endif
  2980.  
  2981.     if (flags & PUT_FIXINDENT)
  2982.     orig_indent = get_indent();
  2983.  
  2984.     curbuf->b_op_start = curwin->w_cursor;    /* default for '[ mark */
  2985.     curbuf->b_op_end = curwin->w_cursor;    /* default for '] mark */
  2986.  
  2987.     /*
  2988.      * Using inserted text works differently, because the register includes
  2989.      * special characters (newlines, etc.).
  2990.      */
  2991.     if (regname == '.')
  2992.     {
  2993.     (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
  2994.                     (count == -1 ? 'O' : 'i')), count, FALSE);
  2995.     /* Putting the text is done later, so can't really move the cursor to
  2996.      * the next character.  Use "l" to simulate it. */
  2997.     if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
  2998.         stuffcharReadbuff('l');
  2999.     return;
  3000.     }
  3001.  
  3002.     /*
  3003.      * For special registers '%' (file name), '#' (alternate file name) and
  3004.      * ':' (last command line), etc. we have to create a fake yank register.
  3005.      */
  3006.     if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
  3007.     {
  3008.     if (insert_string == NULL)
  3009.         return;
  3010.     }
  3011.  
  3012.     if (insert_string != NULL)
  3013.     {
  3014.     y_type = MCHAR;
  3015. #ifdef FEAT_EVAL
  3016.     if (regname == '=')
  3017.     {
  3018.         /* For the = register we need to split the string at NL
  3019.          * characters. */
  3020.         /* Loop twice: count the number of lines and save them. */
  3021.         for (;;)
  3022.         {
  3023.         y_size = 0;
  3024.         ptr = insert_string;
  3025.         while (ptr != NULL)
  3026.         {
  3027.             if (y_array != NULL)
  3028.             y_array[y_size] = ptr;
  3029.             ++y_size;
  3030.             ptr = vim_strchr(ptr, '\n');
  3031.             if (ptr != NULL)
  3032.             {
  3033.             if (y_array != NULL)
  3034.                 *ptr = NUL;
  3035.             ++ptr;
  3036.             /* A trailing '\n' makes the string linewise */
  3037.             if (*ptr == NUL)
  3038.             {
  3039.                 y_type = MLINE;
  3040.                 break;
  3041.             }
  3042.             }
  3043.         }
  3044.         if (y_array != NULL)
  3045.             break;
  3046.         y_array = (char_u **)alloc((unsigned)
  3047.                          (y_size * sizeof(char_u *)));
  3048.         if (y_array == NULL)
  3049.             goto end;
  3050.         }
  3051.     }
  3052.     else
  3053. #endif
  3054.     {
  3055.         y_size = 1;        /* use fake one-line yank register */
  3056.         y_array = &insert_string;
  3057.     }
  3058.     }
  3059.     else
  3060.     {
  3061.     get_yank_register(regname, FALSE);
  3062.  
  3063.     y_type = y_current->y_type;
  3064. #ifdef FEAT_VISUAL
  3065.     y_width = y_current->y_width;
  3066. #endif
  3067.     y_size = y_current->y_size;
  3068.     y_array = y_current->y_array;
  3069.     }
  3070.  
  3071. #ifdef FEAT_VISUAL
  3072.     if (y_type == MLINE)
  3073.     {
  3074.     if (flags & PUT_LINE_SPLIT)
  3075.     {
  3076.         /* "p" or "P" in Visual mode: split the lines to put the text in
  3077.          * between. */
  3078.         if (u_save_cursor() == FAIL)
  3079.         goto end;
  3080.         ptr = vim_strsave(ml_get_cursor());
  3081.         if (ptr == NULL)
  3082.         goto end;
  3083.         ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE);
  3084.         vim_free(ptr);
  3085.  
  3086.         ptr = vim_strnsave(ml_get_curline(), curwin->w_cursor.col);
  3087.         if (ptr == NULL)
  3088.         goto end;
  3089.         ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
  3090.         ++nr_lines;
  3091.         dir = FORWARD;
  3092.     }
  3093.     if (flags & PUT_LINE_FORWARD)
  3094.     {
  3095.         /* Must be "p" for a Visual block, put lines below the block. */
  3096.         curwin->w_cursor = curbuf->b_visual_end;
  3097.         dir = FORWARD;
  3098.     }
  3099.     curbuf->b_op_start = curwin->w_cursor;    /* default for '[ mark */
  3100.     curbuf->b_op_end = curwin->w_cursor;    /* default for '] mark */
  3101.     }
  3102. #endif
  3103.  
  3104.     if (flags & PUT_LINE)    /* :put command or "p" in Visual line mode. */
  3105.     y_type = MLINE;
  3106.  
  3107.     if (y_size == 0 || y_array == NULL)
  3108.     {
  3109.     EMSG2(_("E353: Nothing in register %s"),
  3110.           regname == 0 ? (char_u *)"\"" : transchar(regname));
  3111.     goto end;
  3112.     }
  3113.  
  3114. #ifdef FEAT_VISUAL
  3115.     if (y_type == MBLOCK)
  3116.     {
  3117.     lnum = curwin->w_cursor.lnum + y_size + 1;
  3118.     if (lnum > curbuf->b_ml.ml_line_count)
  3119.         lnum = curbuf->b_ml.ml_line_count + 1;
  3120.     if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
  3121.         goto end;
  3122.     }
  3123.     else
  3124. #endif
  3125.     if (y_type == MLINE)
  3126.     {
  3127.     lnum = curwin->w_cursor.lnum;
  3128. #ifdef FEAT_FOLDING
  3129.     /* Correct line number for closed fold.  Don't move the cursor yet,
  3130.      * u_save() uses it. */
  3131.     if (dir == BACKWARD)
  3132.         (void)hasFolding(lnum, &lnum, NULL);
  3133.     else
  3134.         (void)hasFolding(lnum, NULL, &lnum);
  3135. #endif
  3136.     if (dir == FORWARD)
  3137.         ++lnum;
  3138.     if (u_save(lnum - 1, lnum) == FAIL)
  3139.         goto end;
  3140. #ifdef FEAT_FOLDING
  3141.     if (dir == FORWARD)
  3142.         curwin->w_cursor.lnum = lnum - 1;
  3143.     else
  3144.         curwin->w_cursor.lnum = lnum;
  3145. #endif
  3146.     }
  3147.     else if (u_save_cursor() == FAIL)
  3148.     goto end;
  3149.  
  3150.     yanklen = (int)STRLEN(y_array[0]);
  3151.  
  3152. #ifdef FEAT_VIRTUALEDIT
  3153.     if (ve_flags == VE_ALL && y_type == MCHAR)
  3154.     {
  3155.     if (gchar_cursor() == TAB)
  3156.     {
  3157.         /* Don't need to insert spaces when "p" on the last position of a
  3158.          * tab or "P" on the first position. */
  3159.         if (dir == FORWARD
  3160.             ? (int)curwin->w_cursor.coladd < curbuf->b_p_ts - 1
  3161.                         : curwin->w_cursor.coladd > 0)
  3162.         coladvance_force(getviscol());
  3163.         else
  3164.         curwin->w_cursor.coladd = 0;
  3165.     }
  3166.     else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL)
  3167.         coladvance_force(getviscol() + (dir == FORWARD));
  3168.     }
  3169. #endif
  3170.  
  3171.     lnum = curwin->w_cursor.lnum;
  3172.     col = curwin->w_cursor.col;
  3173.  
  3174. #ifdef FEAT_VISUAL
  3175.     /*
  3176.      * Block mode
  3177.      */
  3178.     if (y_type == MBLOCK)
  3179.     {
  3180.     char    c = gchar_cursor();
  3181.     colnr_T    endcol2 = 0;
  3182.  
  3183.     if (dir == FORWARD && c != NUL)
  3184.     {
  3185. #ifdef FEAT_VIRTUALEDIT
  3186.         if (ve_flags == VE_ALL)
  3187.         getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
  3188.         else
  3189. #endif
  3190.         getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
  3191.  
  3192. #ifdef FEAT_MBYTE
  3193.         if (has_mbyte)
  3194.         /* move to start of next multi-byte character */
  3195.         curwin->w_cursor.col += (*mb_ptr2len_check)(ml_get_cursor());
  3196.         else
  3197. #endif
  3198. #ifdef FEAT_VIRTUALEDIT
  3199.         if (c != TAB || ve_flags != VE_ALL)
  3200. #endif
  3201.         ++curwin->w_cursor.col;
  3202.         ++col;
  3203.     }
  3204.     else
  3205.         getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
  3206.  
  3207. #ifdef FEAT_VIRTUALEDIT
  3208.     col += curwin->w_cursor.coladd;
  3209.     if (ve_flags == VE_ALL && curwin->w_cursor.coladd > 0)
  3210.     {
  3211.         if (dir == FORWARD && c == NUL)
  3212.         ++col;
  3213.         if (dir != FORWARD && c != NUL)
  3214.         ++curwin->w_cursor.col;
  3215.         if (c == TAB)
  3216.         {
  3217.         if (dir == BACKWARD && curwin->w_cursor.col)
  3218.             curwin->w_cursor.col--;
  3219.         if (dir == FORWARD && col - 1 == endcol2)
  3220.             curwin->w_cursor.col++;
  3221.         }
  3222.     }
  3223.     curwin->w_cursor.coladd = 0;
  3224. #endif
  3225.     for (i = 0; i < y_size; ++i)
  3226.     {
  3227.         int spaces;
  3228.         char shortline;
  3229.  
  3230.         bd.startspaces = 0;
  3231.         bd.endspaces = 0;
  3232.         bd.textcol = 0;
  3233.         vcol = 0;
  3234.         delcount = 0;
  3235.  
  3236.         /* add a new line */
  3237.         if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  3238.         {
  3239.         if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
  3240.                            (colnr_T)1, FALSE) == FAIL)
  3241.             break;
  3242.         ++nr_lines;
  3243.         }
  3244.         /* get the old line and advance to the position to insert at */
  3245.         oldp = ml_get_curline();
  3246.         oldlen = (int)STRLEN(oldp);
  3247.         for (ptr = oldp; vcol < col && *ptr; )
  3248.         {
  3249.         /* Count a tab for what it's worth (if list mode not on) */
  3250.         incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol);
  3251.         vcol += incr;
  3252.         }
  3253.         bd.textcol = (colnr_T)(ptr - oldp);
  3254.  
  3255.         shortline = (vcol < col) || (vcol == col && !*ptr) ;
  3256.  
  3257.         if (vcol < col) /* line too short, padd with spaces */
  3258.         bd.startspaces = col - vcol;
  3259.         else if (vcol > col)
  3260.         {
  3261.         bd.endspaces = vcol - col;
  3262.         bd.startspaces = incr - bd.endspaces;
  3263.         --bd.textcol;
  3264.         delcount = 1;
  3265. #ifdef FEAT_MBYTE
  3266.         if (has_mbyte)
  3267.             bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol);
  3268. #endif
  3269.         if (oldp[bd.textcol] != TAB)
  3270.         {
  3271.             /* Only a Tab can be split into spaces.  Other
  3272.              * characters will have to be moved to after the
  3273.              * block, causing misalignment. */
  3274.             delcount = 0;
  3275.             bd.endspaces = 0;
  3276.         }
  3277.         }
  3278.  
  3279.         yanklen = (int)STRLEN(y_array[i]);
  3280.  
  3281.         /* calculate number of spaces required to fill right side of block*/
  3282.         spaces = y_width + 1;
  3283.         for (j = 0; j < yanklen; j++)
  3284.         spaces -= lbr_chartabsize(&y_array[i][j], 0);
  3285.         if (spaces < 0)
  3286.         spaces = 0;
  3287.  
  3288.         /* insert the new text */
  3289.         totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
  3290.         newp = alloc_check((unsigned)totlen + oldlen + 1);
  3291.         if (newp == NULL)
  3292.         break;
  3293.         /* copy part up to cursor to new line */
  3294.         ptr = newp;
  3295.         mch_memmove(ptr, oldp, (size_t)bd.textcol);
  3296.         ptr += bd.textcol;
  3297.         /* may insert some spaces before the new text */
  3298.         copy_spaces(ptr, (size_t)bd.startspaces);
  3299.         ptr += bd.startspaces;
  3300.         /* insert the new text */
  3301.         for (j = 0; j < count; ++j)
  3302.         {
  3303.         mch_memmove(ptr, y_array[i], (size_t)yanklen);
  3304.         ptr += yanklen;
  3305.  
  3306.         /* insert block's trailing spaces only if there's text behind */
  3307.         if ((j < count - 1 || !shortline) && spaces)
  3308.         {
  3309.             copy_spaces(ptr, (size_t)spaces);
  3310.             ptr += spaces;
  3311.         }
  3312.         }
  3313.         /* may insert some spaces after the new text */
  3314.         copy_spaces(ptr, (size_t)bd.endspaces);
  3315.         ptr += bd.endspaces;
  3316.         /* move the text after the cursor to the end of the line. */
  3317.         mch_memmove(ptr, oldp + bd.textcol + delcount,
  3318.                 (size_t)(oldlen - bd.textcol - delcount + 1));
  3319.         ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  3320.  
  3321.         ++curwin->w_cursor.lnum;
  3322.         if (i == 0)
  3323.         curwin->w_cursor.col += bd.startspaces;
  3324.     }
  3325.  
  3326.     changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines);
  3327.  
  3328.     /* Set '[ mark. */
  3329.     curbuf->b_op_start = curwin->w_cursor;
  3330.     curbuf->b_op_start.lnum = lnum;
  3331.  
  3332.     /* adjust '] mark */
  3333.     curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
  3334.     curbuf->b_op_end.col = bd.textcol + totlen - 1;
  3335. #ifdef FEAT_VIRTUALEDIT
  3336.     curbuf->b_op_end.coladd = 0;
  3337. #endif
  3338.     if (flags & PUT_CURSEND)
  3339.     {
  3340.         curwin->w_cursor = curbuf->b_op_end;
  3341.         curwin->w_cursor.col++;
  3342.     }
  3343.     else
  3344.         curwin->w_cursor.lnum = lnum;
  3345.     }
  3346.     else
  3347. #endif
  3348.     {
  3349.     /*
  3350.      * Character or Line mode
  3351.      */
  3352.     if (y_type == MCHAR)
  3353.     {
  3354.         /* if type is MCHAR, FORWARD is the same as BACKWARD on the next
  3355.          * char */
  3356.         if (dir == FORWARD && gchar_cursor() != NUL)
  3357.         {
  3358. #ifdef FEAT_MBYTE
  3359.         if (has_mbyte)
  3360.         {
  3361.             int bytelen = (*mb_ptr2len_check)(ml_get_cursor());
  3362.  
  3363.             /* put it on the next of the multi-byte character. */
  3364.             col += bytelen;
  3365.             if (yanklen)
  3366.             {
  3367.             curwin->w_cursor.col += bytelen;
  3368.             curbuf->b_op_end.col += bytelen;
  3369.             }
  3370.         }
  3371.         else
  3372. #endif
  3373.         {
  3374.             ++col;
  3375.             if (yanklen)
  3376.             {
  3377.             ++curwin->w_cursor.col;
  3378.             ++curbuf->b_op_end.col;
  3379.             }
  3380.         }
  3381.         }
  3382.         new_cursor = curwin->w_cursor;
  3383.         curbuf->b_op_start = curwin->w_cursor;
  3384.     }
  3385.     /*
  3386.      * Line mode: BACKWARD is the same as FORWARD on the previous line
  3387.      */
  3388.     else if (dir == BACKWARD)
  3389.         --lnum;
  3390.  
  3391.     /*
  3392.      * simple case: insert into current line
  3393.      */
  3394.     if (y_type == MCHAR && y_size == 1)
  3395.     {
  3396.         totlen = count * yanklen;
  3397.         if (totlen)
  3398.         {
  3399.         oldp = ml_get(lnum);
  3400.         newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1));
  3401.         if (newp == NULL)
  3402.             goto end;        /* alloc() will give error message */
  3403.         mch_memmove(newp, oldp, (size_t)col);
  3404.         ptr = newp + col;
  3405.         for (i = 0; i < count; ++i)
  3406.         {
  3407.             mch_memmove(ptr, y_array[0], (size_t)yanklen);
  3408.             ptr += yanklen;
  3409.         }
  3410.         mch_memmove(ptr, oldp + col, STRLEN(oldp + col) + 1);
  3411.         ml_replace(lnum, newp, FALSE);
  3412.         /* Put cursor on last putted char. */
  3413.         curwin->w_cursor.col += (colnr_T)(totlen - 1);
  3414.         }
  3415.         curbuf->b_op_end = curwin->w_cursor;
  3416.         /* For "CTRL-O p" in Insert mode, put cursor after last char */
  3417.         if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
  3418.         ++curwin->w_cursor.col;
  3419.         changed_bytes(lnum, col);
  3420.     }
  3421.     else
  3422.     {
  3423.         /*
  3424.          * Insert at least one line.  When y_type is MCHAR, break the first
  3425.          * line in two.
  3426.          */
  3427.         for (cnt = 1; cnt <= count; ++cnt)
  3428.         {
  3429.         i = 0;
  3430.         if (y_type == MCHAR)
  3431.         {
  3432.             /*
  3433.              * Split the current line in two at the insert position.
  3434.              * First insert y_array[size - 1] in front of second line.
  3435.              * Then append y_array[0] to first line.
  3436.              */
  3437.             ptr = ml_get(lnum) + col;
  3438.             totlen = (int)STRLEN(y_array[y_size - 1]);
  3439.             newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1));
  3440.             if (newp == NULL)
  3441.             goto error;
  3442.             STRCPY(newp, y_array[y_size - 1]);
  3443.             STRCAT(newp, ptr);
  3444.             /* insert second line */
  3445.             ml_append(lnum, newp, (colnr_T)0, FALSE);
  3446.             vim_free(newp);
  3447.  
  3448.             oldp = ml_get(lnum);
  3449.             newp = alloc_check((unsigned)(col + yanklen + 1));
  3450.             if (newp == NULL)
  3451.             goto error;
  3452.                         /* copy first part of line */
  3453.             mch_memmove(newp, oldp, (size_t)col);
  3454.                         /* append to first line */
  3455.             mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
  3456.             ml_replace(lnum, newp, FALSE);
  3457.  
  3458.             curwin->w_cursor.lnum = lnum;
  3459.             i = 1;
  3460.         }
  3461.  
  3462.         for (; i < y_size; ++i)
  3463.         {
  3464.             if ((y_type != MCHAR || i < y_size - 1)
  3465.                 && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
  3466.                                       == FAIL)
  3467.                 goto error;
  3468.             lnum++;
  3469.             ++nr_lines;
  3470.             if (flags & PUT_FIXINDENT)
  3471.             {
  3472.             old_pos = curwin->w_cursor;
  3473.             curwin->w_cursor.lnum = lnum;
  3474.             ptr = ml_get(lnum);
  3475.             if (cnt == count && i == y_size - 1)
  3476.                 lendiff = (int)STRLEN(ptr);
  3477. #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
  3478.             if (*ptr == '#' && preprocs_left())
  3479.                 indent = 0;     /* Leave # lines at start */
  3480.             else
  3481. #endif
  3482.                  if (*ptr == NUL)
  3483.                 indent = 0;     /* Ignore empty lines */
  3484.             else if (first_indent)
  3485.             {
  3486.                 indent_diff = orig_indent - get_indent();
  3487.                 indent = orig_indent;
  3488.                 first_indent = FALSE;
  3489.             }
  3490.             else if ((indent = get_indent() + indent_diff) < 0)
  3491.                 indent = 0;
  3492.             (void)set_indent(indent, 0);
  3493.             curwin->w_cursor = old_pos;
  3494.             /* remember how many chars were removed */
  3495.             if (cnt == count && i == y_size - 1)
  3496.                 lendiff -= (int)STRLEN(ml_get(lnum));
  3497.             }
  3498.         }
  3499.         }
  3500.  
  3501. error:
  3502.         /* Adjust marks. */
  3503.         if (y_type == MLINE)
  3504.         {
  3505.         curbuf->b_op_start.col = 0;
  3506.         if (dir == FORWARD)
  3507.         {
  3508. #ifdef FEAT_FOLDING
  3509.             /* a "p" inside a closed fold is like a "p" in the last
  3510.              * line of the fold */
  3511.             (void)hasFolding(curbuf->b_op_start.lnum, NULL,
  3512.                             &curbuf->b_op_start.lnum);
  3513. #endif
  3514.             curbuf->b_op_start.lnum++;
  3515.         }
  3516.         }
  3517.         mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
  3518.                          (linenr_T)MAXLNUM, nr_lines, 0L);
  3519.  
  3520.         /* note changed text for displaying and folding */
  3521.         if (y_type == MCHAR)
  3522.         changed_lines(curwin->w_cursor.lnum, col,
  3523.                      curwin->w_cursor.lnum + 1, nr_lines);
  3524.         else
  3525.         changed_lines(curbuf->b_op_start.lnum, 0,
  3526.                        curbuf->b_op_start.lnum, nr_lines);
  3527.  
  3528.         /* put '] mark at last inserted character */
  3529.         curbuf->b_op_end.lnum = lnum;
  3530.         /* correct length for change in indent */
  3531.         col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
  3532.         if (col > 1)
  3533.         curbuf->b_op_end.col = col - 1;
  3534.         else
  3535.         curbuf->b_op_end.col = 0;
  3536.  
  3537.         if (flags & PUT_CURSEND)
  3538.         {
  3539.         /* put cursor after inserted text */
  3540.         if (y_type == MLINE)
  3541.         {
  3542.             if (lnum >= curbuf->b_ml.ml_line_count)
  3543.             curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  3544.             else
  3545.             curwin->w_cursor.lnum = lnum + 1;
  3546.             curwin->w_cursor.col = 0;
  3547.         }
  3548.         else
  3549.         {
  3550.             curwin->w_cursor.lnum = lnum;
  3551.             curwin->w_cursor.col = col;
  3552.         }
  3553.         }
  3554.         else if (y_type == MLINE)
  3555.         {
  3556.         /* put cursor onfirst non-blank in first inserted line */
  3557.         curwin->w_cursor.col = 0;
  3558.         if (dir == FORWARD)
  3559.             ++curwin->w_cursor.lnum;
  3560.         beginline(BL_WHITE | BL_FIX);
  3561.         }
  3562.         else    /* put cursor on first inserted character */
  3563.         curwin->w_cursor = new_cursor;
  3564.     }
  3565.     }
  3566.  
  3567.     msgmore(nr_lines);
  3568.     curwin->w_set_curswant = TRUE;
  3569.  
  3570. end:
  3571.     if (allocated)
  3572.     {
  3573.     vim_free(insert_string);
  3574.     if (regname == '=')
  3575.         vim_free(y_array);
  3576.     }
  3577.     if (gchar_cursor() == NUL
  3578.         && curwin->w_cursor.col > 0
  3579.         && !(restart_edit || (State & INSERT)))
  3580.     {
  3581.     --curwin->w_cursor.col;
  3582. #ifdef FEAT_VIRTUALEDIT
  3583.     if (ve_flags == VE_ALL)
  3584.         ++curwin->w_cursor.coladd;
  3585. #endif
  3586.     }
  3587. }
  3588.  
  3589. #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) || defined(PROTO)
  3590. /*
  3591.  * Return TRUE if lines starting with '#' should be left aligned.
  3592.  */
  3593.     int
  3594. preprocs_left()
  3595. {
  3596.     return
  3597. # ifdef FEAT_SMARTINDENT
  3598. #  ifdef FEAT_CINDENT
  3599.     (curbuf->b_p_si && !curbuf->b_p_cin) ||
  3600. #  else
  3601.     curbuf->b_p_si
  3602. #  endif
  3603. # endif
  3604. # ifdef FEAT_CINDENT
  3605.     (curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE))
  3606. # endif
  3607.     ;
  3608. }
  3609. #endif
  3610.  
  3611. /* Return the character name of the register with the given number */
  3612.     int
  3613. get_register_name(num)
  3614.     int num;
  3615. {
  3616.     if (num == -1)
  3617.     return '"';
  3618.     else if (num < 10)
  3619.     return num + '0';
  3620.     else if (num == DELETION_REGISTER)
  3621.     return '-';
  3622. #ifdef FEAT_CLIPBOARD
  3623.     else if (num == STAR_REGISTER)
  3624.     return '*';
  3625.     else if (num == PLUS_REGISTER)
  3626.     return '+';
  3627. #endif
  3628.     else
  3629.     {
  3630. #ifdef EBCDIC
  3631.     int i;
  3632.  
  3633.     /* EBCDIC is really braindead ... */
  3634.     i = 'a' + (num - 10);
  3635.     if (i > 'i')
  3636.         i += 7;
  3637.     if (i > 'r')
  3638.         i += 8;
  3639.     return i;
  3640. #else
  3641.     return num + 'a' - 10;
  3642. #endif
  3643.     }
  3644. }
  3645.  
  3646. /*
  3647.  * ":dis" and ":registers": Display the contents of the yank registers.
  3648.  */
  3649.     void
  3650. ex_display(eap)
  3651.     exarg_T    *eap;
  3652. {
  3653.     int            i, n;
  3654.     long        j;
  3655.     char_u        *p;
  3656.     struct yankreg    *yb;
  3657.     char_u        name;
  3658.     int            attr;
  3659.     char_u        *arg = eap->arg;
  3660.  
  3661.     if (arg != NULL && *arg == NUL)
  3662.     arg = NULL;
  3663.     attr = hl_attr(HLF_8);
  3664.  
  3665.     /* Highlight title */
  3666.     MSG_PUTS_TITLE(_("\n--- Registers ---"));
  3667.     for (i = -1; i < NUM_REGISTERS && !got_int; ++i)
  3668.     {
  3669.     if (i == -1)
  3670.     {
  3671.         if (y_previous != NULL)
  3672.         yb = y_previous;
  3673.         else
  3674.         yb = &(y_regs[0]);
  3675.     }
  3676.     else
  3677.         yb = &(y_regs[i]);
  3678.     name = get_register_name(i);
  3679.     if (yb->y_array != NULL
  3680.         && (arg == NULL || vim_strchr(arg, name) != NULL))
  3681.     {
  3682.         msg_putchar('\n');
  3683.         msg_putchar('"');
  3684.         msg_putchar(name);
  3685.         MSG_PUTS("   ");
  3686.  
  3687.         n = (int)Columns - 6;
  3688.         for (j = 0; j < yb->y_size && n > 1; ++j)
  3689.         {
  3690.         if (j)
  3691.         {
  3692.             MSG_PUTS_ATTR("^J", attr);
  3693.             n -= 2;
  3694.         }
  3695.         for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; ++p)
  3696.         {
  3697.             msg_outtrans_len(p, 1);
  3698. #ifdef FEAT_MBYTE
  3699.             if (has_mbyte)
  3700.             p += (*mb_ptr2len_check)(p) - 1;
  3701. #endif
  3702.         }
  3703.         }
  3704.         if (n > 1 && yb->y_type == MLINE)
  3705.         MSG_PUTS_ATTR("^J", attr);
  3706.         out_flush();            /* show one line at a time */
  3707.     }
  3708.     ui_breakcheck();
  3709.     }
  3710.  
  3711.     /*
  3712.      * display last inserted text
  3713.      */
  3714.     if ((p = get_last_insert()) != NULL
  3715.          && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int)
  3716.     {
  3717.     MSG_PUTS("\n\".   ");
  3718.     dis_msg(p, TRUE);
  3719.     }
  3720.  
  3721.     /*
  3722.      * display last command line
  3723.      */
  3724.     if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
  3725.                                   && !got_int)
  3726.     {
  3727.     MSG_PUTS("\n\":   ");
  3728.     dis_msg(last_cmdline, FALSE);
  3729.     }
  3730.  
  3731.     /*
  3732.      * display current file name
  3733.      */
  3734.     if (curbuf->b_fname != NULL
  3735.         && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
  3736.     {
  3737.     MSG_PUTS("\n\"%   ");
  3738.     dis_msg(curbuf->b_fname, FALSE);
  3739.     }
  3740.  
  3741.     /*
  3742.      * display alternate file name
  3743.      */
  3744.     if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
  3745.     {
  3746.     char_u        *fname;
  3747.     linenr_T    dummy;
  3748.  
  3749.     if (buflist_name_nr(0, &fname, &dummy) != FAIL)
  3750.     {
  3751.         MSG_PUTS("\n\"#   ");
  3752.         dis_msg(fname, FALSE);
  3753.     }
  3754.     }
  3755.  
  3756.     /*
  3757.      * display last search pattern
  3758.      */
  3759.     if (last_search_pat() != NULL
  3760.          && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int)
  3761.     {
  3762.     MSG_PUTS("\n\"/   ");
  3763.     dis_msg(last_search_pat(), FALSE);
  3764.     }
  3765.  
  3766. #ifdef FEAT_EVAL
  3767.     /*
  3768.      * display last used expression
  3769.      */
  3770.     if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
  3771.                                   && !got_int)
  3772.     {
  3773.     MSG_PUTS("\n\"=   ");
  3774.     dis_msg(expr_line, FALSE);
  3775.     }
  3776. #endif
  3777. }
  3778.  
  3779. /*
  3780.  * display a string for do_dis()
  3781.  * truncate at end of screen line
  3782.  */
  3783.     static void
  3784. dis_msg(p, skip_esc)
  3785.     char_u    *p;
  3786.     int        skip_esc;        /* if TRUE, ignore trailing ESC */
  3787. {
  3788.     int        n;
  3789. #ifdef FEAT_MBYTE
  3790.     int        l;
  3791. #endif
  3792.  
  3793.     n = (int)Columns - 6;
  3794.     while (*p != NUL
  3795.         && !(*p == ESC && skip_esc && *(p + 1) == NUL)
  3796.         && (n -= ptr2cells(p)) >= 0)
  3797.     {
  3798. #ifdef FEAT_MBYTE
  3799.     if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
  3800.     {
  3801.         msg_outtrans_len(p, l);
  3802.         p += l;
  3803.     }
  3804.     else
  3805. #endif
  3806.         msg_outtrans_len(p++, 1);
  3807.     }
  3808.     ui_breakcheck();
  3809. }
  3810.  
  3811. /*
  3812.  * join 'count' lines (minimal 2), including u_save()
  3813.  */
  3814.     void
  3815. do_do_join(count, insert_space)
  3816.     long    count;
  3817.     int        insert_space;
  3818. {
  3819.     if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
  3820.             (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
  3821.     return;
  3822.  
  3823.     while (--count > 0)
  3824.     {
  3825.     line_breakcheck();
  3826.     if (got_int || do_join(insert_space) == FAIL)
  3827.     {
  3828.         beep_flush();
  3829.         break;
  3830.     }
  3831.     }
  3832.  
  3833. #if 0
  3834.     /*
  3835.      * Need to update the screen if the line where the cursor is became too
  3836.      * long to fit on the screen.
  3837.      */
  3838.     update_topline_redraw();
  3839. #endif
  3840. }
  3841.  
  3842. /*
  3843.  * Join two lines at the cursor position.
  3844.  * "redraw" is TRUE when the screen should be updated.
  3845.  * Caller must have setup for undo.
  3846.  *
  3847.  * return FAIL for failure, OK ohterwise
  3848.  */
  3849.     int
  3850. do_join(insert_space)
  3851.     int        insert_space;
  3852. {
  3853.     char_u    *curr;
  3854.     char_u    *next;
  3855.     char_u    *newp;
  3856.     int        endcurr1, endcurr2;
  3857.     int        currsize;    /* size of the current line */
  3858.     int        nextsize;    /* size of the next line */
  3859.     int        spaces;        /* number of spaces to insert */
  3860.     linenr_T    t;
  3861.  
  3862.     if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
  3863.     return FAIL;        /* can't join on last line */
  3864.  
  3865.     curr = ml_get_curline();
  3866.     currsize = (int)STRLEN(curr);
  3867.     endcurr1 = endcurr2 = NUL;
  3868.     if (insert_space && currsize > 0)
  3869.     {
  3870. #ifdef FEAT_MBYTE
  3871.     if (has_mbyte)
  3872.     {
  3873.         next = curr + currsize - 1;
  3874.         next -= (*mb_head_off)(curr, next);
  3875.         endcurr1 = (*mb_ptr2char)(next);
  3876.         if (next > curr)
  3877.         {
  3878.         --next;
  3879.         next -= (*mb_head_off)(curr, next);
  3880.         endcurr2 = (*mb_ptr2char)(next);
  3881.         }
  3882.     }
  3883.     else
  3884. #endif
  3885.     {
  3886.         endcurr1 = *(curr + currsize - 1);
  3887.         if (currsize > 1)
  3888.         endcurr2 = *(curr + currsize - 2);
  3889.     }
  3890.     }
  3891.  
  3892.     next = ml_get((linenr_T)(curwin->w_cursor.lnum + 1));
  3893.     spaces = 0;
  3894.     if (insert_space)
  3895.     {
  3896.     next = skipwhite(next);
  3897.     if (*next != ')' && currsize != 0 && endcurr1 != TAB
  3898. #ifdef FEAT_MBYTE
  3899.         && (!has_format_option(FO_MBYTE_JOIN)
  3900.             || (mb_ptr2char(next) < 0x100 && endcurr1 < 0x100))
  3901.         && (!has_format_option(FO_MBYTE_JOIN2)
  3902.             || mb_ptr2char(next) < 0x100 || endcurr1 < 0x100)
  3903. #endif
  3904.         )
  3905.     {
  3906.         /* don't add a space if the line is ending in a space */
  3907.         if (endcurr1 == ' ')
  3908.         endcurr1 = endcurr2;
  3909.         else
  3910.         ++spaces;
  3911.         /* extra space when 'joinspaces' set and line ends in '.' */
  3912.         if (       p_js
  3913.             && (endcurr1 == '.'
  3914.             || (vim_strchr(p_cpo, CPO_JOINSP) == NULL
  3915.                 && (endcurr1 == '?' || endcurr1 == '!'))))
  3916.         ++spaces;
  3917.     }
  3918.     }
  3919.     nextsize = (int)STRLEN(next);
  3920.  
  3921.     newp = alloc_check((unsigned)(currsize + nextsize + spaces + 1));
  3922.     if (newp == NULL)
  3923.     return FAIL;
  3924.  
  3925.     /*
  3926.      * Insert the next line first, because we already have that pointer.
  3927.      * Curr has to be obtained again, because getting next will have
  3928.      * invalidated it.
  3929.      */
  3930.     mch_memmove(newp + currsize + spaces, next, (size_t)(nextsize + 1));
  3931.  
  3932.     curr = ml_get_curline();
  3933.     mch_memmove(newp, curr, (size_t)currsize);
  3934.  
  3935.     copy_spaces(newp + currsize, (size_t)spaces);
  3936.  
  3937.     ml_replace(curwin->w_cursor.lnum, newp, FALSE);
  3938.  
  3939.     /* Only report the change in the first line here, del_lines() will report
  3940.      * the deleted line. */
  3941.     changed_lines(curwin->w_cursor.lnum, currsize,
  3942.                            curwin->w_cursor.lnum + 1, 0L);
  3943.  
  3944.     /*
  3945.      * Delete the following line. To do this we move the cursor there
  3946.      * briefly, and then move it back. After del_lines() the cursor may
  3947.      * have moved up (last line deleted), so the current lnum is kept in t.
  3948.      */
  3949.     t = curwin->w_cursor.lnum;
  3950.     ++curwin->w_cursor.lnum;
  3951.     del_lines(1L, FALSE);
  3952.     curwin->w_cursor.lnum = t;
  3953.  
  3954.     /*
  3955.      * go to first character of the joined line
  3956.      */
  3957.     curwin->w_cursor.col = currsize;
  3958.     check_cursor_col();
  3959. #ifdef FEAT_VIRTUALEDIT
  3960.     curwin->w_cursor.coladd = 0;
  3961. #endif
  3962.     curwin->w_set_curswant = TRUE;
  3963.  
  3964.     return OK;
  3965. }
  3966.  
  3967. #ifdef FEAT_COMMENTS
  3968. /*
  3969.  * Return TRUE if the two comment leaders given are the same.  The cursor is
  3970.  * in the first line.  White-space is ignored.    Note that the whole of
  3971.  * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
  3972.  */
  3973.     static int
  3974. same_leader(leader1_len, leader1_flags, leader2_len, leader2_flags)
  3975.     int        leader1_len;
  3976.     char_u  *leader1_flags;
  3977.     int        leader2_len;
  3978.     char_u  *leader2_flags;
  3979. {
  3980.     int        idx1 = 0, idx2 = 0;
  3981.     char_u  *p;
  3982.     char_u  *line1;
  3983.     char_u  *line2;
  3984.  
  3985.     if (leader1_len == 0)
  3986.     return (leader2_len == 0);
  3987.  
  3988.     /*
  3989.      * If first leader has 'f' flag, the lines can be joined only if the
  3990.      * second line does not have a leader.
  3991.      * If first leader has 'e' flag, the lines can never be joined.
  3992.      * If fist leader has 's' flag, the lines can only be joined if there is
  3993.      * some text after it and the second line has the 'm' flag.
  3994.      */
  3995.     if (leader1_flags != NULL)
  3996.     {
  3997.     for (p = leader1_flags; *p && *p != ':'; ++p)
  3998.     {
  3999.         if (*p == COM_FIRST)
  4000.         return (leader2_len == 0);
  4001.         if (*p == COM_END)
  4002.         return FALSE;
  4003.         if (*p == COM_START)
  4004.         {
  4005.         if (*(ml_get_curline() + leader1_len) == NUL)
  4006.             return FALSE;
  4007.         if (leader2_flags == NULL || leader2_len == 0)
  4008.             return FALSE;
  4009.         for (p = leader2_flags; *p && *p != ':'; ++p)
  4010.             if (*p == COM_MIDDLE)
  4011.             return TRUE;
  4012.         return FALSE;
  4013.         }
  4014.     }
  4015.     }
  4016.  
  4017.     /*
  4018.      * Get current line and next line, compare the leaders.
  4019.      * The first line has to be saved, only one line can be locked at a time.
  4020.      */
  4021.     line1 = vim_strsave(ml_get_curline());
  4022.     if (line1 != NULL)
  4023.     {
  4024.     for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1)
  4025.         ;
  4026.     line2 = ml_get(curwin->w_cursor.lnum + 1);
  4027.     for (idx2 = 0; idx2 < leader2_len; ++idx2)
  4028.     {
  4029.         if (!vim_iswhite(line2[idx2]))
  4030.         {
  4031.         if (line1[idx1++] != line2[idx2])
  4032.             break;
  4033.         }
  4034.         else
  4035.         while (vim_iswhite(line1[idx1]))
  4036.             ++idx1;
  4037.     }
  4038.     vim_free(line1);
  4039.     }
  4040.     return (idx2 == leader2_len && idx1 == leader1_len);
  4041. }
  4042. #endif
  4043.  
  4044. /*
  4045.  * implementation of the format operator 'gq'
  4046.  */
  4047.     void
  4048. op_format(oap)
  4049.     oparg_T    *oap;
  4050. {
  4051.     long    old_line_count = curbuf->b_ml.ml_line_count;
  4052.  
  4053.     if (u_save((linenr_T)(oap->start.lnum - 1),
  4054.                        (linenr_T)(oap->end.lnum + 1)) == FAIL)
  4055.     return;
  4056.  
  4057. #ifdef FEAT_VISUAL
  4058.     if (oap->is_VIsual)
  4059.     /* When there is no change: need to remove the Visual selection */
  4060.     redraw_curbuf_later(INVERTED);
  4061. #endif
  4062.  
  4063.     /* Set '[ mark at the start of the formatted area */
  4064.     curbuf->b_op_start = oap->start;
  4065.  
  4066.     format_lines(oap->line_count);
  4067.  
  4068.     /*
  4069.      * Leave the cursor at the first non-blank of the last formatted line.
  4070.      * If the cursor was moved one line back (e.g. with "Q}") go to the next
  4071.      * line, so "." will do the next lines.
  4072.      */
  4073.     if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  4074.     ++curwin->w_cursor.lnum;
  4075.     beginline(BL_WHITE | BL_FIX);
  4076.     old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
  4077.     msgmore(old_line_count);
  4078.  
  4079.     /* put '] mark on the end of the formatted area */
  4080.     curbuf->b_op_end = curwin->w_cursor;
  4081.  
  4082. #ifdef FEAT_VISUAL
  4083.     if (oap->is_VIsual)
  4084.     {
  4085.     win_T    *wp;
  4086.  
  4087.     FOR_ALL_WINDOWS(wp)
  4088.     {
  4089.         if (wp->w_old_cursor_lnum != 0)
  4090.         {
  4091.         /* When lines have been inserted or deleted, adjust the end of
  4092.          * the Visual area to be redrawn. */
  4093.         if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum)
  4094.             wp->w_old_cursor_lnum += old_line_count;
  4095.         else
  4096.             wp->w_old_visual_lnum += old_line_count;
  4097.         }
  4098.     }
  4099.     }
  4100. #endif
  4101. }
  4102.  
  4103. /*
  4104.  * Format "line_count" lines, starting at the cursor position.
  4105.  * When "line_count" is negative, format until the end of the paragraph.
  4106.  * Lines after the cursor line are saved for undo, caller must have saved the
  4107.  * first line.
  4108.  */
  4109.     void
  4110. format_lines(line_count)
  4111.     linenr_T    line_count;
  4112. {
  4113.     int        max_len;
  4114.     int        is_not_par;        /* current line not part of parag. */
  4115.     int        next_is_not_par;    /* next line not part of paragraph */
  4116.     int        is_end_par;        /* at end of paragraph */
  4117.     int        prev_is_end_par = FALSE;/* prev. line not part of parag. */
  4118.     int        next_is_start_par = FALSE;
  4119. #ifdef FEAT_COMMENTS
  4120.     int        leader_len = 0;        /* leader len of current line */
  4121.     int        next_leader_len;    /* leader len of next line */
  4122.     char_u    *leader_flags = NULL;    /* flags for leader of current line */
  4123.     char_u    *next_leader_flags;    /* flags for leader of next line */
  4124.     int        do_comments;        /* format comments */
  4125. #endif
  4126.     int        advance = TRUE;
  4127.     int        second_indent = -1;
  4128.     int        do_second_indent;
  4129.     int        do_number_indent;
  4130.     int        do_trail_white;
  4131.     int        first_par_line = TRUE;
  4132.     int        smd_save;
  4133.     long    count;
  4134.     int        need_set_indent = TRUE;    /* set indent of next paragraph */
  4135.     int        force_format = FALSE;
  4136.     int        old_State = State;
  4137.  
  4138.     /* length of a line to force formatting: 3 * 'tw' */
  4139.     max_len = comp_textwidth(TRUE) * 3;
  4140.  
  4141.     /* check for 'q', '2' and '1' in 'formatoptions' */
  4142. #ifdef FEAT_COMMENTS
  4143.     do_comments = has_format_option(FO_Q_COMS);
  4144. #endif
  4145.     do_second_indent = has_format_option(FO_Q_SECOND);
  4146.     do_number_indent = has_format_option(FO_Q_NUMBER);
  4147.     do_trail_white = has_format_option(FO_WHITE_PAR);
  4148.  
  4149.     /*
  4150.      * Get info about the previous and current line.
  4151.      */
  4152.     if (curwin->w_cursor.lnum > 1)
  4153.     is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
  4154. #ifdef FEAT_COMMENTS
  4155.                 , &leader_len, &leader_flags, do_comments
  4156. #endif
  4157.                 );
  4158.     else
  4159.     is_not_par = TRUE;
  4160.     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
  4161. #ifdef FEAT_COMMENTS
  4162.                , &next_leader_len, &next_leader_flags, do_comments
  4163. #endif
  4164.                 );
  4165.     is_end_par = (is_not_par || next_is_not_par);
  4166.     if (!is_end_par && do_trail_white)
  4167.     is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
  4168.  
  4169.     curwin->w_cursor.lnum--;
  4170.     for (count = line_count; count != 0 && !got_int; --count)
  4171.     {
  4172.     /*
  4173.      * Advance to next paragraph.
  4174.      */
  4175.     if (advance)
  4176.     {
  4177.         curwin->w_cursor.lnum++;
  4178.         prev_is_end_par = is_end_par;
  4179.         is_not_par = next_is_not_par;
  4180. #ifdef FEAT_COMMENTS
  4181.         leader_len = next_leader_len;
  4182.         leader_flags = next_leader_flags;
  4183. #endif
  4184.     }
  4185.  
  4186.     /*
  4187.      * The last line to be formatted.
  4188.      */
  4189.     if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
  4190.     {
  4191.         next_is_not_par = TRUE;
  4192. #ifdef FEAT_COMMENTS
  4193.         next_leader_len = 0;
  4194.         next_leader_flags = NULL;
  4195. #endif
  4196.     }
  4197.     else
  4198.     {
  4199.         next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
  4200. #ifdef FEAT_COMMENTS
  4201.                , &next_leader_len, &next_leader_flags, do_comments
  4202. #endif
  4203.                     );
  4204.         if (do_number_indent)
  4205.         next_is_start_par =
  4206.                (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
  4207.     }
  4208.     advance = TRUE;
  4209.     is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
  4210.     if (!is_end_par && do_trail_white)
  4211.         is_end_par = !ends_in_white(curwin->w_cursor.lnum);
  4212.  
  4213.     /*
  4214.      * Skip lines that are not in a paragraph.
  4215.      */
  4216.     if (is_not_par)
  4217.     {
  4218.         if (line_count < 0)
  4219.         break;
  4220.     }
  4221.     else
  4222.     {
  4223.         /*
  4224.          * For the first line of a paragraph, check indent of second line.
  4225.          * Don't do this for comments and empty lines.
  4226.          */
  4227.         if (first_par_line
  4228.             && (do_second_indent || do_number_indent)
  4229.             && prev_is_end_par
  4230.             && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
  4231. #ifdef FEAT_COMMENTS
  4232.             && leader_len == 0
  4233.             && next_leader_len == 0
  4234. #endif
  4235.             )
  4236.         {
  4237.         if (do_second_indent
  4238.             && !lineempty(curwin->w_cursor.lnum + 1))
  4239.             second_indent = get_indent_lnum(curwin->w_cursor.lnum + 1);
  4240.         else if (do_number_indent)
  4241.             second_indent = get_number_indent(curwin->w_cursor.lnum);
  4242.         }
  4243.  
  4244.         /*
  4245.          * When the comment leader changes, it's the end of the paragraph.
  4246.          */
  4247.         if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
  4248. #ifdef FEAT_COMMENTS
  4249.             || !same_leader(leader_len, leader_flags,
  4250.                       next_leader_len, next_leader_flags)
  4251. #endif
  4252.             )
  4253.         is_end_par = TRUE;
  4254.  
  4255.         /*
  4256.          * If we have got to the end of a paragraph, or the line is
  4257.          * getting long, format it.
  4258.          */
  4259.         if (is_end_par || force_format)
  4260.         {
  4261.         if (need_set_indent)
  4262.             /* replace indent in first line with minimal number of
  4263.              * tabs and spaces, according to current options */
  4264.             (void)set_indent(get_indent(), SIN_CHANGED);
  4265.  
  4266.         /* put cursor on last non-space */
  4267.         State = NORMAL;    /* don't go past end-of-line */
  4268.         coladvance((colnr_T)MAXCOL);
  4269.         while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
  4270.             dec_cursor();
  4271.  
  4272.         /* do the formatting, without 'showmode' */
  4273.         State = INSERT;    /* for open_line() */
  4274.         smd_save = p_smd;
  4275.         p_smd = FALSE;
  4276.         insertchar(NUL, INSCHAR_FORMAT
  4277. #ifdef FEAT_COMMENTS
  4278.             + (do_comments ? INSCHAR_DO_COM : 0)
  4279. #endif
  4280.             , second_indent);
  4281.         State = old_State;
  4282.         p_smd = smd_save;
  4283.         second_indent = -1;
  4284.         /* at end of par.: need to set indent of next par. */
  4285.         need_set_indent = is_end_par;
  4286.         if (is_end_par)
  4287.         {
  4288.             /* When called with a negative line count, break at the
  4289.              * end of the paragraph. */
  4290.             if (line_count < 0)
  4291.             break;
  4292.             first_par_line = TRUE;
  4293.         }
  4294.         force_format = FALSE;
  4295.         }
  4296.  
  4297.         /*
  4298.          * When still in same paragraph, join the lines together.  But
  4299.          * first delete the comment leader from the second line.
  4300.          */
  4301.         if (!is_end_par)
  4302.         {
  4303.         advance = FALSE;
  4304.         curwin->w_cursor.lnum++;
  4305.         curwin->w_cursor.col = 0;
  4306.         if (line_count < 0 && u_save_cursor() == FAIL)
  4307.             break;
  4308. #ifdef FEAT_COMMENTS
  4309.         (void)del_bytes((long)next_leader_len, FALSE);
  4310. #endif
  4311.         curwin->w_cursor.lnum--;
  4312.         if (do_join(TRUE) == FAIL)
  4313.         {
  4314.             beep_flush();
  4315.             break;
  4316.         }
  4317.         first_par_line = FALSE;
  4318.         /* If the line is getting long, format it next time */
  4319.         if (STRLEN(ml_get_curline()) > (size_t)max_len)
  4320.             force_format = TRUE;
  4321.         else
  4322.             force_format = FALSE;
  4323.         }
  4324.     }
  4325.     line_breakcheck();
  4326.     }
  4327. }
  4328.  
  4329. /*
  4330.  * Return TRUE if line "lnum" ends in a white character.
  4331.  */
  4332.     static int
  4333. ends_in_white(lnum)
  4334.     linenr_T    lnum;
  4335. {
  4336.     char_u    *s = ml_get(lnum);
  4337.  
  4338.     return (*s != NUL && vim_iswhite(s[STRLEN(s) - 1]));
  4339. }
  4340.  
  4341. /*
  4342.  * Blank lines, and lines containing only the comment leader, are left
  4343.  * untouched by the formatting.  The function returns TRUE in this
  4344.  * case.  It also returns TRUE when a line starts with the end of a comment
  4345.  * ('e' in comment flags), so that this line is skipped, and not joined to the
  4346.  * previous line.  A new paragraph starts after a blank line, or when the
  4347.  * comment leader changes -- webb.
  4348.  */
  4349. #ifdef FEAT_COMMENTS
  4350.     static int
  4351. fmt_check_par(lnum, leader_len, leader_flags, do_comments)
  4352.     linenr_T    lnum;
  4353.     int        *leader_len;
  4354.     char_u    **leader_flags;
  4355.     int        do_comments;
  4356. {
  4357.     char_u    *flags = NULL;        /* init for GCC */
  4358.     char_u    *ptr;
  4359.  
  4360.     ptr = ml_get(lnum);
  4361.     if (do_comments)
  4362.     *leader_len = get_leader_len(ptr, leader_flags, FALSE);
  4363.     else
  4364.     *leader_len = 0;
  4365.  
  4366.     if (*leader_len > 0)
  4367.     {
  4368.     /*
  4369.      * Search for 'e' flag in comment leader flags.
  4370.      */
  4371.     flags = *leader_flags;
  4372.     while (*flags && *flags != ':' && *flags != COM_END)
  4373.         ++flags;
  4374.     }
  4375.  
  4376.     return (*skipwhite(ptr + *leader_len) == NUL
  4377.         || (*leader_len > 0 && *flags == COM_END)
  4378.         || startPS(lnum, NUL, FALSE));
  4379. }
  4380. #else
  4381.     static int
  4382. fmt_check_par(lnum)
  4383.     linenr_T    lnum;
  4384. {
  4385.     return (*skipwhite(ml_get(lnum)) == NUL || startPS(lnum, NUL, FALSE));
  4386. }
  4387. #endif
  4388.  
  4389. #ifdef FEAT_VISUAL
  4390. /*
  4391.  * prepare a few things for block mode yank/delete/tilde
  4392.  *
  4393.  * for delete:
  4394.  * - textlen includes the first/last char to be (partly) deleted
  4395.  * - start/endspaces is the number of columns that are taken by the
  4396.  *   first/last deleted char minus the number of columns that have to be
  4397.  *   deleted.  for yank and tilde:
  4398.  * - textlen includes the first/last char to be wholly yanked
  4399.  * - start/endspaces is the number of columns of the first/last yanked char
  4400.  *   that are to be yanked.
  4401.  */
  4402.     static void
  4403. block_prep(oap, bdp, lnum, is_del)
  4404.     oparg_T        *oap;
  4405.     struct block_def    *bdp;
  4406.     linenr_T        lnum;
  4407.     int            is_del;
  4408. {
  4409.     int        incr = 0;
  4410.     char_u    *pend;
  4411.     char_u    *pstart;
  4412.     char_u    *line;
  4413.     char_u    *prev_pstart;
  4414.     char_u    *prev_pend;
  4415.  
  4416.     bdp->startspaces = 0;
  4417.     bdp->endspaces = 0;
  4418.     bdp->textlen = 0;
  4419.     bdp->start_vcol = 0;
  4420.     bdp->end_vcol = 0;
  4421. #ifdef FEAT_VISUALEXTRA
  4422.     bdp->is_short = FALSE;
  4423.     bdp->is_oneChar = FALSE;
  4424.     bdp->pre_whitesp = 0;
  4425.     bdp->pre_whitesp_c = 0;
  4426.     bdp->end_char_vcols = 0;
  4427. #endif
  4428.     bdp->start_char_vcols = 0;
  4429.  
  4430.     line = ml_get(lnum);
  4431.     pstart = line;
  4432.     prev_pstart = line;
  4433.     while (bdp->start_vcol < oap->start_vcol && *pstart)
  4434.     {
  4435.     /* Count a tab for what it's worth (if list mode not on) */
  4436.     incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol);
  4437.     bdp->start_vcol += incr;
  4438. #ifdef FEAT_VISUALEXTRA
  4439.     if (vim_iswhite(*pstart))
  4440.     {
  4441.         bdp->pre_whitesp += incr;
  4442.         bdp->pre_whitesp_c++;
  4443.     }
  4444.     else
  4445.     {
  4446.         bdp->pre_whitesp = 0;
  4447.         bdp->pre_whitesp_c = 0;
  4448.     }
  4449. #endif
  4450.     prev_pstart = pstart;
  4451. #ifdef FEAT_MBYTE
  4452.     if (has_mbyte)
  4453.         pstart += (*mb_ptr2len_check)(pstart);
  4454.     else
  4455. #endif
  4456.         ++pstart;
  4457.     }
  4458.     bdp->start_char_vcols = incr;
  4459.     if (bdp->start_vcol < oap->start_vcol)    /* line too short */
  4460.     {
  4461.     bdp->end_vcol = bdp->start_vcol;
  4462. #ifdef FEAT_VISUALEXTRA
  4463.     bdp->is_short = TRUE;
  4464. #endif
  4465.     if (!is_del || oap->op_type == OP_APPEND)
  4466.         bdp->endspaces = oap->end_vcol - oap->start_vcol + 1;
  4467.     }
  4468.     else
  4469.     {
  4470.     /* notice: this converts partly selected Multibyte characters to
  4471.      * spaces, too. */
  4472.     bdp->startspaces = bdp->start_vcol - oap->start_vcol;
  4473.     if (is_del && bdp->startspaces)
  4474.         bdp->startspaces = bdp->start_char_vcols - bdp->startspaces;
  4475.     pend = pstart;
  4476.     bdp->end_vcol = bdp->start_vcol;
  4477.     if (bdp->end_vcol > oap->end_vcol)    /* it's all in one character */
  4478.     {
  4479. #ifdef FEAT_VISUALEXTRA
  4480.         bdp->is_oneChar = TRUE;
  4481. #endif
  4482.         if (oap->op_type == OP_INSERT)
  4483.         bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
  4484.         else if (oap->op_type == OP_APPEND)
  4485.         {
  4486.         bdp->startspaces += oap->end_vcol - oap->start_vcol + 1;
  4487.         bdp->endspaces = bdp->start_char_vcols - bdp->startspaces;
  4488.         }
  4489.         else
  4490.         {
  4491.         bdp->startspaces = oap->end_vcol - oap->start_vcol + 1;
  4492.         if (is_del && oap->op_type != OP_LSHIFT)
  4493.         {
  4494.             /* just putting the sum of those two into
  4495.              * bdp->startspaces doesn't work for Visual replace,
  4496.              * so we have to split the tab in two */
  4497.             bdp->startspaces = bdp->start_char_vcols
  4498.                     - (bdp->start_vcol - oap->start_vcol);
  4499.             bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
  4500.         }
  4501.         }
  4502.     }
  4503.     else
  4504.     {
  4505.         prev_pend = pend;
  4506.         while (bdp->end_vcol <= oap->end_vcol && *pend != NUL)
  4507.         {
  4508.         /* Count a tab for what it's worth (if list mode not on) */
  4509.         prev_pend = pend;
  4510.         incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol);
  4511.         bdp->end_vcol += incr;
  4512.         }
  4513.         if (bdp->end_vcol <= oap->end_vcol
  4514.             && (!is_del
  4515.             || oap->op_type == OP_APPEND
  4516.             || oap->op_type == OP_REPLACE)) /* line too short */
  4517.         {
  4518. #ifdef FEAT_VISUALEXTRA
  4519.         bdp->is_short = TRUE;
  4520. #endif
  4521.         /* Alternative: include spaces to fill up the block.
  4522.          * Disadvantage: can lead to trailing spaces when the line is
  4523.          * short where the text is put */
  4524.         /* if (!is_del || oap->op_type == OP_APPEND) */
  4525.         if (oap->op_type == OP_APPEND || virtual_op)
  4526.             bdp->endspaces = oap->end_vcol - bdp->end_vcol
  4527.                     + oap->inclusive;
  4528.         else
  4529.             bdp->endspaces = 0; /* replace doesn't add characters */
  4530.         }
  4531.         else if (bdp->end_vcol > oap->end_vcol)
  4532.         {
  4533.         bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1;
  4534.         if (!is_del && bdp->endspaces)
  4535.         {
  4536.             bdp->endspaces = incr - bdp->endspaces;
  4537.             if (pend != pstart)
  4538.             pend = prev_pend;
  4539.         }
  4540.         }
  4541.     }
  4542. #ifdef FEAT_VISUALEXTRA
  4543.     bdp->end_char_vcols = incr;
  4544. #endif
  4545.     if (is_del && bdp->startspaces)
  4546.         pstart = prev_pstart;
  4547.     bdp->textlen = (int)(pend - pstart);
  4548.     }
  4549.     bdp->textcol = (colnr_T) (pstart - line);
  4550.     bdp->textstart = pstart;
  4551. }
  4552. #endif /* FEAT_VISUAL */
  4553.  
  4554. #ifdef FEAT_RIGHTLEFT
  4555. static void reverse_line __ARGS((char_u *s));
  4556.  
  4557.     static void
  4558. reverse_line(s)
  4559.     char_u *s;
  4560. {
  4561.     int        i, j;
  4562.     char_u  c;
  4563.  
  4564.     if ((i = (int)STRLEN(s) - 1) <= 0)
  4565.     return;
  4566.  
  4567.     curwin->w_cursor.col = i - curwin->w_cursor.col;
  4568.     for (j = 0; j < i; j++, i--)
  4569.     {
  4570.     c = s[i]; s[i] = s[j]; s[j] = c;
  4571.     }
  4572. }
  4573.  
  4574. # define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr);
  4575. #else
  4576. # define RLADDSUBFIX(ptr)
  4577. #endif
  4578.  
  4579. /*
  4580.  * add or subtract 'Prenum1' from a number in a line
  4581.  * 'command' is CTRL-A for add, CTRL-X for subtract
  4582.  *
  4583.  * return FAIL for failure, OK otherwise
  4584.  */
  4585.     int
  4586. do_addsub(command, Prenum1)
  4587.     int        command;
  4588.     linenr_T    Prenum1;
  4589. {
  4590.     int        col;
  4591.     char_u    *buf1;
  4592.     char_u    buf2[NUMBUFLEN];
  4593.     int        hex;        /* 'X' or 'x': hex; '0': octal */
  4594.     static int    hexupper = FALSE;    /* 0xABC */
  4595.     long_u    n;
  4596.     long_u    oldn;
  4597.     char_u    *ptr;
  4598.     int        c;
  4599.     int        length = 0;        /* character length of the number */
  4600.     int        todel;
  4601.     int        dohex;
  4602.     int        dooct;
  4603.     int        doalp;
  4604.     int        firstdigit;
  4605.     int        negative;
  4606.     int        subtract;
  4607.  
  4608.     dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL);    /* "heX" */
  4609.     dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL);    /* "Octal" */
  4610.     doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL);    /* "alPha" */
  4611.  
  4612.     ptr = ml_get_curline();
  4613.     RLADDSUBFIX(ptr);
  4614.  
  4615.     /*
  4616.      * First check if we are on a hexadecimal number, after the "0x".
  4617.      */
  4618.     col = curwin->w_cursor.col;
  4619.     if (dohex)
  4620.     while (col > 0 && isxdigit(ptr[col]))
  4621.         --col;
  4622.     if (       dohex
  4623.         && col > 0
  4624.         && (ptr[col] == 'X'
  4625.         || ptr[col] == 'x')
  4626.         && ptr[col - 1] == '0'
  4627.         && isxdigit(ptr[col + 1]))
  4628.     {
  4629.     /*
  4630.      * Found hexadecimal number, move to its start.
  4631.      */
  4632.     --col;
  4633.     }
  4634.     else
  4635.     {
  4636.     /*
  4637.      * Search forward and then backward to find the start of number.
  4638.      */
  4639.     col = curwin->w_cursor.col;
  4640.  
  4641.     while (ptr[col] != NUL
  4642.         && !isdigit(ptr[col])
  4643.         && !(doalp && ASCII_ISALPHA(ptr[col])))
  4644.         ++col;
  4645.  
  4646.     while (col > 0
  4647.         && isdigit(ptr[col - 1])
  4648.         && !(doalp && ASCII_ISALPHA(ptr[col])))
  4649.         --col;
  4650.     }
  4651.  
  4652.     /* truncate to max length of a number */
  4653.     if (length >= NUMBUFLEN - 1)
  4654.     length = NUMBUFLEN - 2;
  4655.  
  4656.     /*
  4657.      * If a number was found, and saving for undo works, replace the number.
  4658.      */
  4659.     firstdigit = ptr[col];
  4660.     RLADDSUBFIX(ptr);
  4661.     if ((!isdigit(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
  4662.         || u_save_cursor() != OK)
  4663.     {
  4664.     beep_flush();
  4665.     return FAIL;
  4666.     }
  4667.  
  4668.     /* get ptr again, because u_save() may have changed it */
  4669.     ptr = ml_get_curline();
  4670.     RLADDSUBFIX(ptr);
  4671.  
  4672.     if (doalp && ASCII_ISALPHA(firstdigit))
  4673.     {
  4674.     /* decrement or increment alphabetic character */
  4675.     if (command == Ctrl_X)
  4676.     {
  4677.         if (CharOrd(firstdigit) < Prenum1)
  4678.         {
  4679.         if (isupper(firstdigit))
  4680.             firstdigit = 'A';
  4681.         else
  4682.             firstdigit = 'a';
  4683.         }
  4684.         else
  4685. #ifdef EBCDIC
  4686.         firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
  4687. #else
  4688.         firstdigit -= Prenum1;
  4689. #endif
  4690.     }
  4691.     else
  4692.     {
  4693.         if (26 - CharOrd(firstdigit) - 1 < Prenum1)
  4694.         {
  4695.         if (isupper(firstdigit))
  4696.             firstdigit = 'Z';
  4697.         else
  4698.             firstdigit = 'z';
  4699.         }
  4700.         else
  4701. #ifdef EBCDIC
  4702.         firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
  4703. #else
  4704.         firstdigit += Prenum1;
  4705. #endif
  4706.     }
  4707.     curwin->w_cursor.col = col;
  4708.     (void)del_char(FALSE);
  4709.     ins_char(firstdigit);
  4710.     }
  4711.     else
  4712.     {
  4713.     negative = FALSE;
  4714.     if (col > 0 && ptr[col - 1] == '-')        /* negative number */
  4715.     {
  4716.         --col;
  4717.         negative = TRUE;
  4718.     }
  4719.  
  4720.     /* get the number value (unsigned) */
  4721.     vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
  4722.  
  4723.     /* ignore leading '-' for hex and octal numbers */
  4724.     if (hex && negative)
  4725.     {
  4726.         ++col;
  4727.         --length;
  4728.         negative = FALSE;
  4729.     }
  4730.  
  4731.     /* add or subtract */
  4732.     subtract = FALSE;
  4733.     if (command == Ctrl_X)
  4734.         subtract ^= TRUE;
  4735.     if (negative)
  4736.         subtract ^= TRUE;
  4737.  
  4738.     oldn = n;
  4739.     if (subtract)
  4740.         n -= (unsigned long)Prenum1;
  4741.     else
  4742.         n += (unsigned long)Prenum1;
  4743.  
  4744.     /* handle wraparound for decimal numbers */
  4745.     if (!hex)
  4746.     {
  4747.         if (subtract)
  4748.         {
  4749.         if (n > oldn)
  4750.         {
  4751.             n = 1 + (n ^ (unsigned long)-1);
  4752.             negative ^= TRUE;
  4753.         }
  4754.         }
  4755.         else /* add */
  4756.         {
  4757.         if (n < oldn)
  4758.         {
  4759.             n = (n ^ (unsigned long)-1);
  4760.             negative ^= TRUE;
  4761.         }
  4762.         }
  4763.         if (n == 0)
  4764.         negative = FALSE;
  4765.     }
  4766.  
  4767.     /*
  4768.      * Delete the old number.
  4769.      */
  4770.     curwin->w_cursor.col = col;
  4771.     todel = length;
  4772.     c = gchar_cursor();
  4773.     /*
  4774.      * Don't include the '-' in the length, only the length of the part
  4775.      * after it is kept the same.
  4776.      */
  4777.     if (c == '-')
  4778.         --length;
  4779.     while (todel-- > 0)
  4780.     {
  4781.         if (c < 0x100 && isalpha(c))
  4782.         {
  4783.         if (isupper(c))
  4784.             hexupper = TRUE;
  4785.         else
  4786.             hexupper = FALSE;
  4787.         }
  4788.         /* del_char() will mark line needing displaying */
  4789.         (void)del_char(FALSE);
  4790.         c = gchar_cursor();
  4791.     }
  4792.  
  4793.     /*
  4794.      * Prepare the leading characters in buf1[].
  4795.      * When there are many leading zeros it could be very long.  Allocate
  4796.      * a bit too much.
  4797.      */
  4798.     buf1 = alloc((unsigned)length + NUMBUFLEN);
  4799.     if (buf1 == NULL)
  4800.         return FAIL;
  4801.     ptr = buf1;
  4802.     if (negative)
  4803.     {
  4804.         *ptr++ = '-';
  4805.     }
  4806.     if (hex)
  4807.     {
  4808.         *ptr++ = '0';
  4809.         --length;
  4810.     }
  4811.     if (hex == 'x' || hex == 'X')
  4812.     {
  4813.         *ptr++ = hex;
  4814.         --length;
  4815.     }
  4816.  
  4817.     /*
  4818.      * Put the number characters in buf2[].
  4819.      */
  4820.     if (hex == 0)
  4821.         sprintf((char *)buf2, "%lu", n);
  4822.     else if (hex == '0')
  4823.         sprintf((char *)buf2, "%lo", n);
  4824.     else if (hex && hexupper)
  4825.         sprintf((char *)buf2, "%lX", n);
  4826.     else
  4827.         sprintf((char *)buf2, "%lx", n);
  4828.     length -= (int)STRLEN(buf2);
  4829.  
  4830.     /*
  4831.      * adjust number of zeros to the new number of digits, so the
  4832.      * total length of the number remains the same
  4833.      */
  4834.     if (firstdigit == '0')
  4835.         while (length-- > 0)
  4836.         *ptr++ = '0';
  4837.     *ptr = NUL;
  4838.     STRCAT(buf1, buf2);
  4839.     ins_str(buf1);        /* insert the new number */
  4840.     vim_free(buf1);
  4841.     }
  4842.     --curwin->w_cursor.col;
  4843.     curwin->w_set_curswant = TRUE;
  4844. #ifdef FEAT_RIGHTLEFT
  4845.     ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
  4846.     RLADDSUBFIX(ptr);
  4847. #endif
  4848.     return OK;
  4849. }
  4850.  
  4851. #ifdef FEAT_VIMINFO
  4852.     int
  4853. read_viminfo_register(virp, force)
  4854.     vir_T    *virp;
  4855.     int        force;
  4856. {
  4857.     int        eof;
  4858.     int        do_it = TRUE;
  4859.     int        size;
  4860.     int        limit;
  4861.     int        i;
  4862.     int        set_prev = FALSE;
  4863.     char_u    *str;
  4864.     char_u    **array = NULL;
  4865.  
  4866.     /* We only get here (hopefully) if line[0] == '"' */
  4867.     str = virp->vir_line + 1;
  4868.     if (*str == '"')
  4869.     {
  4870.     set_prev = TRUE;
  4871.     str++;
  4872.     }
  4873.     if (!ASCII_ISALNUM(*str) && *str != '-')
  4874.     {
  4875.     if (viminfo_error("E577: ", _("Illegal register name"), virp->vir_line))
  4876.         return TRUE;    /* too many errors, pretend end-of-file */
  4877.     do_it = FALSE;
  4878.     }
  4879.     get_yank_register(*str++, FALSE);
  4880.     if (!force && y_current->y_array != NULL)
  4881.     do_it = FALSE;
  4882.     size = 0;
  4883.     limit = 100;    /* Optimized for registers containing <= 100 lines */
  4884.     if (do_it)
  4885.     {
  4886.     if (set_prev)
  4887.         y_previous = y_current;
  4888.     vim_free(y_current->y_array);
  4889.     array = y_current->y_array =
  4890.                (char_u **)alloc((unsigned)(limit * sizeof(char_u *)));
  4891.     str = skipwhite(str);
  4892.     if (STRNCMP(str, "CHAR", 4) == 0)
  4893.         y_current->y_type = MCHAR;
  4894. #ifdef FEAT_VISUAL
  4895.     else if (STRNCMP(str, "BLOCK", 5) == 0)
  4896.         y_current->y_type = MBLOCK;
  4897. #endif
  4898.     else
  4899.         y_current->y_type = MLINE;
  4900.     /* get the block width; if it's missing we get a zero, which is OK */
  4901.     str = skipwhite(skiptowhite(str));
  4902. #ifdef FEAT_VISUAL
  4903.     y_current->y_width = getdigits(&str);
  4904. #else
  4905.     (void)getdigits(&str);
  4906. #endif
  4907.     }
  4908.  
  4909.     while (!(eof = viminfo_readline(virp))
  4910.             && (virp->vir_line[0] == TAB || virp->vir_line[0] == '<'))
  4911.     {
  4912.     if (do_it)
  4913.     {
  4914.         if (size >= limit)
  4915.         {
  4916.         y_current->y_array = (char_u **)
  4917.                   alloc((unsigned)(limit * 2 * sizeof(char_u *)));
  4918.         for (i = 0; i < limit; i++)
  4919.             y_current->y_array[i] = array[i];
  4920.         vim_free(array);
  4921.         limit *= 2;
  4922.         array = y_current->y_array;
  4923.         }
  4924.         str = viminfo_readstring(virp, 1, TRUE);
  4925.         if (str != NULL)
  4926.         array[size++] = str;
  4927.         else
  4928.         do_it = FALSE;
  4929.     }
  4930.     }
  4931.     if (do_it)
  4932.     {
  4933.     if (size == 0)
  4934.     {
  4935.         vim_free(array);
  4936.         y_current->y_array = NULL;
  4937.     }
  4938.     else if (size < limit)
  4939.     {
  4940.         y_current->y_array =
  4941.             (char_u **)alloc((unsigned)(size * sizeof(char_u *)));
  4942.         for (i = 0; i < size; i++)
  4943.         y_current->y_array[i] = array[i];
  4944.         vim_free(array);
  4945.     }
  4946.     y_current->y_size = size;
  4947.     }
  4948.     return eof;
  4949. }
  4950.  
  4951.     void
  4952. write_viminfo_registers(fp)
  4953.     FILE    *fp;
  4954. {
  4955.     int        i, j;
  4956.     char_u  *type;
  4957.     char_u  c;
  4958.     int        num_lines;
  4959.     int        max_num_lines;
  4960.  
  4961.     fprintf(fp, _("\n# Registers:\n"));
  4962.  
  4963.     max_num_lines = get_viminfo_parameter('"');
  4964.     if (max_num_lines == 0)
  4965.     return;
  4966.     for (i = 0; i < NUM_REGISTERS; i++)
  4967.     {
  4968.     if (y_regs[i].y_array == NULL)
  4969.         continue;
  4970. #ifdef FEAT_CLIPBOARD
  4971.     /* Skip '*'/'+' register, we don't want them back next time */
  4972.     if (i == STAR_REGISTER || i == PLUS_REGISTER)
  4973.         continue;
  4974. #endif
  4975. #ifdef FEAT_DND
  4976.     /* Neither do we want the '~' register */
  4977.     if (i == TILDE_REGISTER)
  4978.         continue;
  4979. #endif
  4980.     switch (y_regs[i].y_type)
  4981.     {
  4982.         case MLINE:
  4983.         type = (char_u *)"LINE";
  4984.         break;
  4985.         case MCHAR:
  4986.         type = (char_u *)"CHAR";
  4987.         break;
  4988. #ifdef FEAT_VISUAL
  4989.         case MBLOCK:
  4990.         type = (char_u *)"BLOCK";
  4991.         break;
  4992. #endif
  4993.         default:
  4994.         sprintf((char *)IObuff, _("E574: Unknown register type %d"),
  4995.             y_regs[i].y_type);
  4996.         emsg(IObuff);
  4997.         type = (char_u *)"LINE";
  4998.         break;
  4999.     }
  5000.     if (y_previous == &y_regs[i])
  5001.         fprintf(fp, "\"");
  5002.     c = get_register_name(i);
  5003.     fprintf(fp, "\"%c\t%s\t%d\n", c, type,
  5004. #ifdef FEAT_VISUAL
  5005.             (int)y_regs[i].y_width
  5006. #else
  5007.             0
  5008. #endif
  5009.             );
  5010.     num_lines = y_regs[i].y_size;
  5011.  
  5012.     /* If max_num_lines < 0, then we save ALL the lines in the register */
  5013.     if (max_num_lines > 0 && num_lines > max_num_lines)
  5014.         num_lines = max_num_lines;
  5015.     for (j = 0; j < num_lines; j++)
  5016.     {
  5017.         putc('\t', fp);
  5018.         viminfo_writestring(fp, y_regs[i].y_array[j]);
  5019.     }
  5020.     }
  5021. }
  5022. #endif /* FEAT_VIMINFO */
  5023.  
  5024. #if defined(FEAT_CLIPBOARD) || defined(PROTO)
  5025. /*
  5026.  * SELECTION / PRIMARY ('*')
  5027.  *
  5028.  * Text selection stuff that uses the GUI selection register '*'.  When using a
  5029.  * GUI this may be text from another window, otherwise it is the last text we
  5030.  * had highlighted with VIsual mode.  With mouse support, clicking the middle
  5031.  * button performs the paste, otherwise you will need to do <"*p>. "
  5032.  * If not under X, it is synonymous with the clipboard register '+'.
  5033.  *
  5034.  * X CLIPBOARD ('+')
  5035.  *
  5036.  * Text selection stuff that uses the GUI clipboard register '+'.
  5037.  * Under X, this matches the standard cut/paste buffer CLIPBOARD selection.
  5038.  * It will be used for unnamed cut/pasting is 'clipboard' contains "unnamed",
  5039.  * otherwise you will need to do <"+p>. "
  5040.  * If not under X, it is synonymous with the selection register '*'.
  5041.  */
  5042.  
  5043. /*
  5044.  * Routine to export any final X selection we had to the environment
  5045.  * so that the text is still available after vim has exited. X selections
  5046.  * only exist while the owning application exists, so we write to the
  5047.  * permanent (while X runs) store CUT_BUFFER0.
  5048.  * Dump the CLIPBOARD selection if we own it (it's logically the more
  5049.  * 'permanent' of the two), otherwise the PRIMARY one.
  5050.  * For now, use a hard-coded sanity limit of 1Mb of data.
  5051.  */
  5052. #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
  5053.     void
  5054. x11_export_final_selection()
  5055. {
  5056.     Display    *dpy;
  5057.     char_u    *str = NULL;
  5058.     long_u    len = 0;
  5059.     int        motion_type = -1;
  5060.  
  5061. # ifdef FEAT_GUI
  5062.     if (gui.in_use)
  5063.     dpy = X_DISPLAY;
  5064.     else
  5065. # endif
  5066. # ifdef FEAT_XCLIPBOARD
  5067.     dpy = xterm_dpy;
  5068. # else
  5069.     return;
  5070. # endif
  5071.  
  5072.     /* Get selection to export */
  5073.     if (clip_plus.owned)
  5074.     motion_type = clip_convert_selection(&str, &len, &clip_plus);
  5075.     else if (clip_star.owned)
  5076.     motion_type = clip_convert_selection(&str, &len, &clip_star);
  5077.  
  5078.     /* Check it's OK */
  5079.     if (dpy != NULL && str != NULL && motion_type >= 0
  5080.                            && len < 1024*1024 && len > 0)
  5081.     {
  5082.     XStoreBuffer(dpy, (char *)str, (int)len, 0);
  5083.     XFlush(dpy);
  5084.     }
  5085.  
  5086.     vim_free(str);
  5087. }
  5088. #endif
  5089.  
  5090.     void
  5091. clip_free_selection(cbd)
  5092.     VimClipboard    *cbd;
  5093. {
  5094.     struct yankreg *y_ptr = y_current;
  5095.  
  5096.     if (cbd == &clip_plus)
  5097.     y_current = &y_regs[PLUS_REGISTER];
  5098.     else
  5099.     y_current = &y_regs[STAR_REGISTER];
  5100.     free_yank_all();
  5101.     y_current->y_size = 0;
  5102.     y_current = y_ptr;
  5103. }
  5104.  
  5105. /*
  5106.  * Get the selected text and put it in the gui selection register '*' or '+'.
  5107.  */
  5108.     void
  5109. clip_get_selection(cbd)
  5110.     VimClipboard    *cbd;
  5111. {
  5112.     struct yankreg *old_y_previous, *old_y_current;
  5113.     pos_T    old_cursor;
  5114. #ifdef FEAT_VISUAL
  5115.     pos_T    old_visual;
  5116.     int        old_visual_mode;
  5117. #endif
  5118.     colnr_T    old_curswant;
  5119.     int        old_set_curswant;
  5120.     pos_T    old_op_start, old_op_end;
  5121.     oparg_T    oa;
  5122.     cmdarg_T    ca;
  5123.  
  5124.     if (cbd->owned)
  5125.     {
  5126.     if ((cbd == &clip_plus && y_regs[PLUS_REGISTER].y_array != NULL)
  5127.         || (cbd == &clip_star && y_regs[STAR_REGISTER].y_array != NULL))
  5128.         return;
  5129.  
  5130.     /* Get the text between clip_star.start & clip_star.end */
  5131.     old_y_previous = y_previous;
  5132.     old_y_current = y_current;
  5133.     old_cursor = curwin->w_cursor;
  5134.     old_curswant = curwin->w_curswant;
  5135.     old_set_curswant = curwin->w_set_curswant;
  5136.     old_op_start = curbuf->b_op_start;
  5137.     old_op_end = curbuf->b_op_end;
  5138. #ifdef FEAT_VISUAL
  5139.     old_visual = VIsual;
  5140.     old_visual_mode = VIsual_mode;
  5141. #endif
  5142.     clear_oparg(&oa);
  5143.     oa.regname = (cbd == &clip_plus ? '+' : '*');
  5144.     oa.op_type = OP_YANK;
  5145.     vim_memset(&ca, 0, sizeof(ca));
  5146.     ca.oap = &oa;
  5147.     ca.cmdchar = 'y';
  5148.     ca.count1 = 1;
  5149.     ca.retval = CA_NO_ADJ_OP_END;
  5150.     do_pending_operator(&ca, 0, TRUE);
  5151.     y_previous = old_y_previous;
  5152.     y_current = old_y_current;
  5153.     curwin->w_cursor = old_cursor;
  5154.     curwin->w_curswant = old_curswant;
  5155.     curwin->w_set_curswant = old_set_curswant;
  5156.     curbuf->b_op_start = old_op_start;
  5157.     curbuf->b_op_end = old_op_end;
  5158. #ifdef FEAT_VISUAL
  5159.     VIsual = old_visual;
  5160.     VIsual_mode = old_visual_mode;
  5161. #endif
  5162.     }
  5163.     else
  5164.     {
  5165.     clip_free_selection(cbd);
  5166.  
  5167.     /* Try to get selected text from another window */
  5168.     clip_gen_request_selection(cbd);
  5169.     }
  5170. }
  5171.  
  5172. /* Convert from the GUI selection string into the '*'/'+' register */
  5173.     void
  5174. clip_yank_selection(type, str, len, cbd)
  5175.     int        type;
  5176.     char_u    *str;
  5177.     long    len;
  5178.     VimClipboard *cbd;
  5179. {
  5180.     struct yankreg *y_ptr;
  5181.  
  5182.     if (cbd == &clip_plus)
  5183.     y_ptr = &y_regs[PLUS_REGISTER];
  5184.     else
  5185.     y_ptr = &y_regs[STAR_REGISTER];
  5186.  
  5187.     clip_free_selection(cbd);
  5188.  
  5189.     str_to_reg(y_ptr, type, str, len, 0L);
  5190. }
  5191.  
  5192. /*
  5193.  * Convert the '*'/'*' register into a GUI selection string returned in *str
  5194.  * with length *len.
  5195.  * Returns the motion type, or -1 for failure.
  5196.  */
  5197.     int
  5198. clip_convert_selection(str, len, cbd)
  5199.     char_u    **str;
  5200.     long_u    *len;
  5201.     VimClipboard *cbd;
  5202. {
  5203.     char_u    *p;
  5204.     int        lnum;
  5205.     int        i, j;
  5206.     int_u    eolsize;
  5207.     struct yankreg *y_ptr;
  5208.  
  5209.     if (cbd == &clip_plus)
  5210.     y_ptr = &y_regs[PLUS_REGISTER];
  5211.     else
  5212.     y_ptr = &y_regs[STAR_REGISTER];
  5213.  
  5214. #ifdef USE_CRNL
  5215.     eolsize = 2;
  5216. #else
  5217.     eolsize = 1;
  5218. #endif
  5219.  
  5220.     *str = NULL;
  5221.     *len = 0;
  5222.     if (y_ptr->y_array == NULL)
  5223.     return -1;
  5224.  
  5225.     for (i = 0; i < y_ptr->y_size; i++)
  5226.     *len += (long_u)STRLEN(y_ptr->y_array[i]) + eolsize;
  5227.  
  5228.     /*
  5229.      * Don't want newline character at end of last line if we're in MCHAR mode.
  5230.      */
  5231.     if (y_ptr->y_type == MCHAR && *len > eolsize)
  5232.     *len -= eolsize;
  5233.  
  5234.     p = *str = lalloc(*len, TRUE);
  5235.     if (p == NULL)
  5236.     return -1;
  5237.     lnum = 0;
  5238.     for (i = 0, j = 0; i < (int)*len; i++, j++)
  5239.     {
  5240.     if (y_ptr->y_array[lnum][j] == '\n')
  5241.         p[i] = NUL;
  5242.     else if (y_ptr->y_array[lnum][j] == NUL)
  5243.     {
  5244. #ifdef USE_CRNL
  5245.         p[i++] = '\r';
  5246. #endif
  5247. #ifdef USE_CR
  5248.         p[i] = '\r';
  5249. #else
  5250.         p[i] = '\n';
  5251. #endif
  5252.         lnum++;
  5253.         j = -1;
  5254.     }
  5255.     else
  5256.         p[i] = y_ptr->y_array[lnum][j];
  5257.     }
  5258.     return y_ptr->y_type;
  5259. }
  5260.  
  5261.  
  5262. # if defined(FEAT_VISUAL) || defined(FEAT_EVAL)
  5263. /*
  5264.  * If we have written to a clipboard register, send the text to the clipboard.
  5265.  */
  5266.     static void
  5267. may_set_selection()
  5268. {
  5269.     if (y_current == &(y_regs[STAR_REGISTER]) && clip_star.available)
  5270.     {
  5271.     clip_own_selection(&clip_star);
  5272.     clip_gen_set_selection(&clip_star);
  5273.     }
  5274.     else if (y_current == &(y_regs[PLUS_REGISTER]) && clip_plus.available)
  5275.     {
  5276.     clip_own_selection(&clip_plus);
  5277.     clip_gen_set_selection(&clip_plus);
  5278.     }
  5279. }
  5280. # endif
  5281.  
  5282. #endif /* FEAT_CLIPBOARD || PROTO */
  5283.  
  5284.  
  5285. #if defined(FEAT_DND) || defined(PROTO)
  5286. /*
  5287.  * Replace the contents of the '~' register with str.
  5288.  */
  5289.     void
  5290. dnd_yank_drag_data(str, len)
  5291.     char_u    *str;
  5292.     long    len;
  5293. {
  5294.     struct yankreg *curr;
  5295.  
  5296.     curr = y_current;
  5297.     y_current = &y_regs[TILDE_REGISTER];
  5298.     free_yank_all();
  5299.     str_to_reg(y_current, MCHAR, str, len, 0L);
  5300.     y_current = curr;
  5301. }
  5302. #endif
  5303.  
  5304.  
  5305. #if defined(FEAT_EVAL) || defined(PROTO)
  5306. /*
  5307.  * Return the type of a register.
  5308.  * Used for getregtype()
  5309.  * Returns MAUTO for error.
  5310.  */
  5311.     char_u
  5312. get_reg_type(regname, reglen)
  5313.     int        regname;
  5314.     long    *reglen;
  5315. {
  5316.     switch (regname)
  5317.     {
  5318.     case '%':        /* file name */
  5319.     case '#':        /* alternate file name */
  5320.     case '=':        /* expression */
  5321.     case ':':        /* last command line */
  5322.     case '/':        /* last search-pattern */
  5323.     case '.':        /* last inserted text */
  5324. #ifdef FEAT_SEARCHPATH
  5325.     case Ctrl_F:        /* Filename under cursor */
  5326.     case Ctrl_P:        /* Path under cursor, expand via "path" */
  5327. #endif
  5328.     case Ctrl_W:        /* word under cursor */
  5329.     case Ctrl_A:        /* WORD (mnemonic All) under cursor */
  5330.     case '_':        /* black hole: always empty */
  5331.         return MCHAR;
  5332.     }
  5333.  
  5334. #ifdef FEAT_CLIPBOARD
  5335.     regname = may_get_selection(regname);
  5336. #endif
  5337.  
  5338.     /* Should we check for a valid name? */
  5339.     get_yank_register(regname, FALSE);
  5340.  
  5341.     if (y_current->y_array != NULL)
  5342.     {
  5343. #ifdef FEAT_VISUAL
  5344.     if (reglen != NULL && y_current->y_type == MBLOCK)
  5345.         *reglen = y_current->y_width;
  5346. #endif
  5347.     return y_current->y_type;
  5348.     }
  5349.     return MAUTO;
  5350. }
  5351.  
  5352. /*
  5353.  * Return the contents of a register as a single allocated string.
  5354.  * Used for "@r" in expressions and for getreg().
  5355.  * Returns NULL for error.
  5356.  */
  5357.     char_u *
  5358. get_reg_contents(regname, allowexpr)
  5359.     int        regname;
  5360.     int        allowexpr;    /* allow "=" register. */
  5361. {
  5362.     long    i;
  5363.     char_u    *retval;
  5364.     int        allocated;
  5365.     long    len;
  5366.  
  5367.     /* Don't allow using an expression register inside an expression */
  5368.     if (regname == '=')
  5369.     {
  5370.     if (allowexpr)
  5371.         return get_expr_line();
  5372.     return NULL;
  5373.     }
  5374.  
  5375.     if (regname == '@')        /* "@@" is used for unnamed register */
  5376.     regname = '"';
  5377.  
  5378.     /* check for valid regname */
  5379.     if (regname != NUL && !valid_yank_reg(regname, FALSE))
  5380.     return NULL;
  5381.  
  5382. #ifdef FEAT_CLIPBOARD
  5383.     regname = may_get_selection(regname);
  5384. #endif
  5385.  
  5386.     if (get_spec_reg(regname, &retval, &allocated, FALSE))
  5387.     {
  5388.     if (retval == NULL)
  5389.         return NULL;
  5390.     if (!allocated)
  5391.         retval = vim_strsave(retval);
  5392.     return retval;
  5393.     }
  5394.  
  5395.     get_yank_register(regname, FALSE);
  5396.     if (y_current->y_array == NULL)
  5397.     return NULL;
  5398.  
  5399.     /*
  5400.      * Compute length of resulting string.
  5401.      */
  5402.     len = 0;
  5403.     for (i = 0; i < y_current->y_size; ++i)
  5404.     {
  5405.     len += (long)STRLEN(y_current->y_array[i]);
  5406.     /*
  5407.      * Insert a newline between lines and after last line if
  5408.      * y_type is MLINE.
  5409.      */
  5410.     if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  5411.         ++len;
  5412.     }
  5413.  
  5414.     retval = lalloc(len + 1, TRUE);
  5415.  
  5416.     /*
  5417.      * Copy the lines of the yank register into the string.
  5418.      */
  5419.     if (retval != NULL)
  5420.     {
  5421.     len = 0;
  5422.     for (i = 0; i < y_current->y_size; ++i)
  5423.     {
  5424.         STRCPY(retval + len, y_current->y_array[i]);
  5425.         len += (long)STRLEN(retval + len);
  5426.  
  5427.         /*
  5428.          * Insert a NL between lines and after the last line if y_type is
  5429.          * MLINE.
  5430.          */
  5431.         if (y_current->y_type == MLINE || i < y_current->y_size - 1)
  5432.         retval[len++] = '\n';
  5433.     }
  5434.     retval[len] = NUL;
  5435.     }
  5436.  
  5437.     return retval;
  5438. }
  5439.  
  5440. /*
  5441.  * Store string "str" in register "name".
  5442.  * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
  5443.  * If "must_append" is TRUE, always append to the register.  Otherwise append
  5444.  * if "name" is an uppercase letter.
  5445.  * Note: "maxlen" and "must_append" don't work for the "/" register.
  5446.  * Careful: 'str' is modified, you may have to use a copy!
  5447.  * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
  5448.  */
  5449.     void
  5450. write_reg_contents(name, str, maxlen, must_append)
  5451.     int        name;
  5452.     char_u    *str;
  5453.     int        maxlen;
  5454.     int        must_append;
  5455. {
  5456.     write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
  5457. }
  5458.  
  5459.     void
  5460. write_reg_contents_ex(name, str, maxlen, must_append, yank_type, block_len)
  5461.     int        name;
  5462.     char_u    *str;
  5463.     int        maxlen;
  5464.     int        must_append;
  5465.     int        yank_type;
  5466.     long    block_len;
  5467. {
  5468.     struct yankreg  *old_y_previous, *old_y_current;
  5469.     long        len;
  5470.  
  5471.     /* Special case: '/' search pattern */
  5472.     if (name == '/')
  5473.     {
  5474.     set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
  5475.     return;
  5476.     }
  5477.  
  5478.     if (!valid_yank_reg(name, TRUE))        /* check for valid reg name */
  5479.     {
  5480.     EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
  5481.     return;
  5482.     }
  5483.  
  5484.     if (name == '_')        /* black hole: nothing to do */
  5485.     return;
  5486.  
  5487.     /* Don't want to change the current (unnamed) register */
  5488.     old_y_previous = y_previous;
  5489.     old_y_current = y_current;
  5490.  
  5491.     get_yank_register(name, TRUE);
  5492.     if (!y_append && !must_append)
  5493.     free_yank_all();
  5494.     if (maxlen >= 0)
  5495.     len = maxlen;
  5496.     else
  5497.     len = (long)STRLEN(str);
  5498. #ifndef FEAT_VISUAL
  5499.     /* Just in case - make sure we don't use MBLOCK */
  5500.     if (yank_type == MBLOCK)
  5501.     yank_type = MAUTO;
  5502. #endif
  5503.     if (yank_type == MAUTO)
  5504.     yank_type = ((len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r'))
  5505.                                  ? MLINE : MCHAR);
  5506.     str_to_reg(y_current, yank_type, str, len, block_len);
  5507.  
  5508. # ifdef FEAT_CLIPBOARD
  5509.     /* Send text of clipboard register to the clipboard. */
  5510.     may_set_selection();
  5511. # endif
  5512.  
  5513.     /* ':let @" = "val"' should change the meaning of the "" register */
  5514.     if (name != '"')
  5515.     y_previous = old_y_previous;
  5516.     y_current = old_y_current;
  5517. }
  5518. #endif    /* FEAT_EVAL */
  5519.  
  5520. #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
  5521. /*
  5522.  * Put a string into a register.  When the register is not empty, the string
  5523.  * is appended.
  5524.  */
  5525.     static void
  5526. str_to_reg(y_ptr, type, str, len, blocklen)
  5527.     struct yankreg    *y_ptr;        /* pointer to yank register */
  5528.     int            type;        /* MCHAR, MLINE or MBLOCK */
  5529.     char_u        *str;        /* string to put in register */
  5530.     long        len;        /* length of string */
  5531.     long        blocklen;    /* width of Visual block */
  5532. {
  5533.     int        lnum;
  5534.     long    start;
  5535.     long    i;
  5536.     int        extra;
  5537.     int        newlines;        /* number of lines added */
  5538.     int        extraline = 0;        /* extra line at the end */
  5539.     int        append = FALSE;        /* append to last line in register */
  5540.     char_u    *s;
  5541.     char_u    **pp;
  5542. #ifdef FEAT_VISUAL
  5543.     long    maxlen;
  5544. #endif
  5545.  
  5546.     if (y_ptr->y_array == NULL)        /* NULL means emtpy register */
  5547.     y_ptr->y_size = 0;
  5548.  
  5549.     /*
  5550.      * Count the number of lines within the string
  5551.      */
  5552.     newlines = 0;
  5553.     for (i = 0; i < len; i++)
  5554.     if (str[i] == '\n')
  5555.         ++newlines;
  5556.     if (type == MCHAR || len == 0 || str[len - 1] != '\n')
  5557.     {
  5558.     extraline = 1;
  5559.     ++newlines;    /* count extra newline at the end */
  5560.     }
  5561.     if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
  5562.     {
  5563.     append = TRUE;
  5564.     --newlines;    /* uncount newline when appending first line */
  5565.     }
  5566.  
  5567.     /*
  5568.      * Allocate an array to hold the pointers to the new register lines.
  5569.      * If the register was not empty, move the existing lines to the new array.
  5570.      */
  5571.     pp = (char_u **)lalloc_clear((y_ptr->y_size + newlines)
  5572.                             * sizeof(char_u *), TRUE);
  5573.     if (pp == NULL)    /* out of memory */
  5574.     return;
  5575.     for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
  5576.     pp[lnum] = y_ptr->y_array[lnum];
  5577.     vim_free(y_ptr->y_array);
  5578.     y_ptr->y_array = pp;
  5579. #ifdef FEAT_VISUAL
  5580.     maxlen = 0;
  5581. #endif
  5582.  
  5583.     /*
  5584.      * Find the end of each line and save it into the array.
  5585.      */
  5586.     for (start = 0; start < len + extraline; start += i + 1)
  5587.     {
  5588.     for (i = start; i < len; ++i)    /* find the end of the line */
  5589.         if (str[i] == '\n')
  5590.         break;
  5591.     i -= start;            /* i is now length of line */
  5592. #ifdef FEAT_VISUAL
  5593.     if (i > maxlen)
  5594.         maxlen = i;
  5595. #endif
  5596.     if (append)
  5597.     {
  5598.         --lnum;
  5599.         extra = (int)STRLEN(y_ptr->y_array[lnum]);
  5600.     }
  5601.     else
  5602.         extra = 0;
  5603.     s = alloc((unsigned)(i + extra + 1));
  5604.     if (s == NULL)
  5605.         break;
  5606.     if (extra)
  5607.     {
  5608.         mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
  5609.         vim_free(y_ptr->y_array[lnum]);
  5610.     }
  5611.     if (i)
  5612.         mch_memmove(s + extra, str + start, (size_t)i);
  5613.     extra += i;
  5614.     s[extra] = NUL;
  5615.     y_ptr->y_array[lnum++] = s;
  5616.     while (--extra >= 0)
  5617.     {
  5618.         if (*s == NUL)
  5619.         *s = '\n';        /* replace NUL with newline */
  5620.         ++s;
  5621.     }
  5622.     append = FALSE;            /* only first line is appended */
  5623.     }
  5624.     y_ptr->y_type = type;
  5625.     y_ptr->y_size = lnum;
  5626. # ifdef FEAT_VISUAL
  5627.     if (type == MBLOCK)
  5628.     y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
  5629.     else
  5630.     y_ptr->y_width = 0;
  5631. # endif
  5632. }
  5633. #endif /* FEAT_CLIPBOARD || FEAT_EVAL || PROTO */
  5634.  
  5635.     void
  5636. clear_oparg(oap)
  5637.     oparg_T    *oap;
  5638. {
  5639.     vim_memset(oap, 0, sizeof(oparg_T));
  5640. }
  5641.  
  5642. static long    line_count_info __ARGS((char_u *line, long *wc, long limit, int eol_size));
  5643.  
  5644. /*
  5645.  *  Count the number of characters and "words" in a line.
  5646.  *
  5647.  *  "Words" are counted by looking for boundaries between non-space and
  5648.  *  space characters.  (it seems to produce results that match 'wc'.)
  5649.  *
  5650.  *  Return value is character count; word count for the line is ADDED
  5651.  *  to "*wc".
  5652.  *
  5653.  *  The function will only examine the first "limit" characters in the
  5654.  *  line, stopping if it encounters an end-of-line (NUL byte).  In that
  5655.  *  case, eol_size will be added to the character count to account for
  5656.  *  the size of the EOL character.
  5657.  */
  5658.     static long
  5659. line_count_info(line, wc, limit, eol_size)
  5660.     char_u    *line;
  5661.     long    *wc;
  5662.     long    limit;
  5663.     int        eol_size;
  5664. {
  5665.     long    i, words = 0;
  5666.     int        is_word = 0;
  5667.  
  5668.     for (i = 0; line[i] && i < limit; i++)
  5669.     {
  5670.     if (is_word)
  5671.     {
  5672.         if (vim_isspace(line[i]))
  5673.         {
  5674.         words++;
  5675.         is_word = 0;
  5676.         }
  5677.     }
  5678.     else if (!vim_isspace(line[i]))
  5679.         is_word = 1;
  5680.     }
  5681.  
  5682.     if (is_word)
  5683.     words++;
  5684.     *wc += words;
  5685.  
  5686.     /* Add eol_size if the end of line was reached before hitting limit. */
  5687.     if (!line[i] && i < limit)
  5688.     i += eol_size;
  5689.     return i;
  5690. }
  5691.  
  5692. /*
  5693.  * Give some info about the position of the cursor (for "g CTRL-G").
  5694.  * In Visual mode, give some info about the selected region.  (In this case,
  5695.  * the *_count_cursor variables store running totals for the selection.)
  5696.  */
  5697.     void
  5698. cursor_pos_info()
  5699. {
  5700.     char_u    *p;
  5701.     char_u    buf1[20];
  5702.     char_u    buf2[20];
  5703.     linenr_T    lnum;
  5704.     long    char_count = 0;
  5705.     long    char_count_cursor = 0;
  5706.     int        eol_size;
  5707.     long    last_check = 100000L;
  5708.     long    word_count = 0;
  5709.     long    word_count_cursor = 0;
  5710. #ifdef FEAT_VISUAL
  5711.     long    line_count_selected = 0;
  5712.     pos_T    min_pos, max_pos;
  5713.     oparg_T    oparg;
  5714.     struct block_def    bd;
  5715. #endif
  5716.  
  5717.     /*
  5718.      * Compute the length of the file in characters.
  5719.      */
  5720.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  5721.     {
  5722.     MSG(_(no_lines_msg));
  5723.     }
  5724.     else
  5725.     {
  5726.     if (get_fileformat(curbuf) == EOL_DOS)
  5727.         eol_size = 2;
  5728.     else
  5729.         eol_size = 1;
  5730.  
  5731. #ifdef FEAT_VISUAL
  5732.     if (VIsual_active)
  5733.     {
  5734.         if (lt(VIsual, curwin->w_cursor))
  5735.         {
  5736.         min_pos = VIsual;
  5737.         max_pos = curwin->w_cursor;
  5738.         }
  5739.         else
  5740.         {
  5741.         min_pos = curwin->w_cursor;
  5742.         max_pos = VIsual;
  5743.         }
  5744.         if (*p_sel == 'e' && max_pos.col > 0)
  5745.         --max_pos.col;
  5746.  
  5747.         if (VIsual_mode == Ctrl_V)
  5748.         {
  5749.         oparg.is_VIsual = 1;
  5750.         oparg.block_mode = TRUE;
  5751.         oparg.op_type = OP_NOP;
  5752.         getvcols(curwin, &min_pos, &max_pos,
  5753.             &oparg.start_vcol, &oparg.end_vcol);
  5754.         /* Swap the start, end vcol if needed */
  5755.         if (oparg.end_vcol < oparg.start_vcol)
  5756.         {
  5757.             oparg.end_vcol += oparg.start_vcol;
  5758.             oparg.start_vcol = oparg.end_vcol - oparg.start_vcol;
  5759.             oparg.end_vcol -= oparg.start_vcol;
  5760.         }
  5761.         }
  5762.         line_count_selected = max_pos.lnum - min_pos.lnum + 1;
  5763.     }
  5764. #endif
  5765.  
  5766.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  5767.     {
  5768.         /* Check for a CTRL-C every 100000 characters. */
  5769.         if (char_count > last_check)
  5770.         {
  5771.         ui_breakcheck();
  5772.         if (got_int)
  5773.             return;
  5774.         last_check = char_count + 100000L;
  5775.         }
  5776.  
  5777. #ifdef FEAT_VISUAL
  5778.         /* Do extra processing for VIsual mode. */
  5779.         if (VIsual_active
  5780.             && lnum >= min_pos.lnum && lnum <= max_pos.lnum)
  5781.         {
  5782.         switch (VIsual_mode)
  5783.         {
  5784.             case Ctrl_V:
  5785. # ifdef FEAT_VIRTUALEDIT
  5786.             virtual_op = virtual_active();
  5787. # endif
  5788.             block_prep(&oparg, &bd, lnum, 0);
  5789. # ifdef FEAT_VIRTUALEDIT
  5790.             virtual_op = MAYBE;
  5791. # endif
  5792.             char_count_cursor += line_count_info(bd.textstart,
  5793.                 &word_count_cursor, (long)bd.textlen, eol_size);
  5794.             break;
  5795.             case 'V':
  5796.             char_count_cursor += line_count_info(ml_get(lnum),
  5797.                 &word_count_cursor, (long)MAXCOL, eol_size);
  5798.             break;
  5799.             case 'v':
  5800.             {
  5801.                 colnr_T start_col = (lnum == min_pos.lnum)
  5802.                                ? min_pos.col : 0;
  5803.                 colnr_T end_col = (lnum == max_pos.lnum)
  5804.                       ? max_pos.col - start_col + 1 : MAXCOL;
  5805.  
  5806.                 char_count_cursor +=
  5807.                 line_count_info(ml_get(lnum) + start_col,
  5808.                  &word_count_cursor, (long)end_col, eol_size);
  5809.             }
  5810.             break;
  5811.         }
  5812.         }
  5813.         else
  5814. #endif
  5815.         {
  5816.         /* In non-visual mode, check for the line the cursor is on */
  5817.         if (lnum == curwin->w_cursor.lnum)
  5818.         {
  5819.             word_count_cursor += word_count;
  5820.             char_count_cursor = char_count +
  5821.             line_count_info(ml_get(lnum), &word_count_cursor,
  5822.                   (long)(curwin->w_cursor.col + 1), eol_size);
  5823.         }
  5824.         }
  5825.         /* Add to the running totals */
  5826.         char_count += line_count_info(ml_get(lnum), &word_count,
  5827.                               (long)MAXCOL, eol_size);
  5828.     }
  5829.  
  5830.     /* Correction for when last line doesn't have an EOL. */
  5831.     if (!curbuf->b_p_eol && curbuf->b_p_bin)
  5832.         char_count -= eol_size;
  5833.  
  5834. #ifdef FEAT_VISUAL
  5835.     if (VIsual_active)
  5836.     {
  5837.         if (VIsual_mode == Ctrl_V)
  5838.         {
  5839.         getvcols(curwin, &min_pos, &max_pos, &min_pos.col,
  5840.             &max_pos.col);
  5841.         sprintf((char *)buf1, _("%ld Cols; "),
  5842.             (long)(oparg.end_vcol - oparg.start_vcol + 1));
  5843.         }
  5844.         else
  5845.         buf1[0] = NUL;
  5846.  
  5847.         sprintf((char *)IObuff,
  5848.         _("Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"),
  5849.             buf1, line_count_selected,
  5850.             (long)curbuf->b_ml.ml_line_count,
  5851.             word_count_cursor, word_count,
  5852.             char_count_cursor, char_count);
  5853.     }
  5854.     else
  5855. #endif
  5856.     {
  5857.         p = ml_get_curline();
  5858.         validate_virtcol();
  5859.         col_print(buf1, (int)curwin->w_cursor.col + 1,
  5860.             (int)curwin->w_virtcol + 1);
  5861.         col_print(buf2, (int)STRLEN(p), linetabsize(p));
  5862.  
  5863.         sprintf((char *)IObuff,
  5864.         _("Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"),
  5865.             (char *)buf1, (char *)buf2,
  5866.             (long)curwin->w_cursor.lnum,
  5867.             (long)curbuf->b_ml.ml_line_count,
  5868.             word_count_cursor, word_count,
  5869.             char_count_cursor, char_count);
  5870.     }
  5871.  
  5872. #ifdef FEAT_MBYTE
  5873.     char_count = bomb_size();
  5874.     if (char_count > 0)
  5875.         sprintf((char *)IObuff + STRLEN(IObuff), _("(+%ld for BOM)"),
  5876.                                   char_count);
  5877. #endif
  5878.     /* Don't shorten this message, the user asked for it. */
  5879.     p = p_shm;
  5880.     p_shm = (char_u *)"";
  5881.     msg(IObuff);
  5882.     p_shm = p;
  5883.     }
  5884. }
  5885.