14aea03ebSBram Moolenaar /* vi:set ts=8 sts=4 sw=4 noet:
24aea03ebSBram Moolenaar *
34aea03ebSBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar
44aea03ebSBram Moolenaar *
54aea03ebSBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions.
64aea03ebSBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed.
74aea03ebSBram Moolenaar * See README.txt for an overview of the Vim source code.
84aea03ebSBram Moolenaar */
94aea03ebSBram Moolenaar
104aea03ebSBram Moolenaar /*
114aea03ebSBram Moolenaar * register.c: functions for managing registers
124aea03ebSBram Moolenaar */
134aea03ebSBram Moolenaar
144aea03ebSBram Moolenaar #include "vim.h"
154aea03ebSBram Moolenaar
164aea03ebSBram Moolenaar /*
174aea03ebSBram Moolenaar * Registers:
184aea03ebSBram Moolenaar * 0 = unnamed register, for normal yanks and puts
194aea03ebSBram Moolenaar * 1..9 = registers '1' to '9', for deletes
204aea03ebSBram Moolenaar * 10..35 = registers 'a' to 'z' ('A' to 'Z' for appending)
214aea03ebSBram Moolenaar * 36 = delete register '-'
224aea03ebSBram Moolenaar * 37 = Selection register '*'. Only if FEAT_CLIPBOARD defined
234aea03ebSBram Moolenaar * 38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined
244aea03ebSBram Moolenaar */
254aea03ebSBram Moolenaar static yankreg_T y_regs[NUM_REGISTERS];
264aea03ebSBram Moolenaar
274aea03ebSBram Moolenaar static yankreg_T *y_current; // ptr to current yankreg
284aea03ebSBram Moolenaar static int y_append; // TRUE when appending
294aea03ebSBram Moolenaar static yankreg_T *y_previous = NULL; // ptr to last written yankreg
304aea03ebSBram Moolenaar
314aea03ebSBram Moolenaar static int stuff_yank(int, char_u *);
324aea03ebSBram Moolenaar static void put_reedit_in_typebuf(int silent);
334aea03ebSBram Moolenaar static int put_in_typebuf(char_u *s, int esc, int colon,
344aea03ebSBram Moolenaar int silent);
35544a38e4SChristian Brabandt static int yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space);
364aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
374aea03ebSBram Moolenaar static void copy_yank_reg(yankreg_T *reg);
384aea03ebSBram Moolenaar #endif
394aea03ebSBram Moolenaar static void dis_msg(char_u *p, int skip_esc);
404aea03ebSBram Moolenaar
414aea03ebSBram Moolenaar yankreg_T *
get_y_regs(void)424aea03ebSBram Moolenaar get_y_regs(void)
434aea03ebSBram Moolenaar {
444aea03ebSBram Moolenaar return y_regs;
454aea03ebSBram Moolenaar }
464aea03ebSBram Moolenaar
474aea03ebSBram Moolenaar yankreg_T *
get_y_register(int reg)4845fffdf1SBram Moolenaar get_y_register(int reg)
4945fffdf1SBram Moolenaar {
5045fffdf1SBram Moolenaar return &y_regs[reg];
5145fffdf1SBram Moolenaar }
5245fffdf1SBram Moolenaar
5345fffdf1SBram Moolenaar yankreg_T *
get_y_current(void)544aea03ebSBram Moolenaar get_y_current(void)
554aea03ebSBram Moolenaar {
564aea03ebSBram Moolenaar return y_current;
574aea03ebSBram Moolenaar }
584aea03ebSBram Moolenaar
594aea03ebSBram Moolenaar yankreg_T *
get_y_previous(void)604aea03ebSBram Moolenaar get_y_previous(void)
614aea03ebSBram Moolenaar {
624aea03ebSBram Moolenaar return y_previous;
634aea03ebSBram Moolenaar }
644aea03ebSBram Moolenaar
654aea03ebSBram Moolenaar void
set_y_current(yankreg_T * yreg)6645fffdf1SBram Moolenaar set_y_current(yankreg_T *yreg)
6745fffdf1SBram Moolenaar {
6845fffdf1SBram Moolenaar y_current = yreg;
6945fffdf1SBram Moolenaar }
7045fffdf1SBram Moolenaar
7145fffdf1SBram Moolenaar void
set_y_previous(yankreg_T * yreg)724aea03ebSBram Moolenaar set_y_previous(yankreg_T *yreg)
734aea03ebSBram Moolenaar {
744aea03ebSBram Moolenaar y_previous = yreg;
754aea03ebSBram Moolenaar }
764aea03ebSBram Moolenaar
7778eb9cceSChristian Brabandt void
reset_y_append(void)7878eb9cceSChristian Brabandt reset_y_append(void)
7978eb9cceSChristian Brabandt {
8078eb9cceSChristian Brabandt y_append = FALSE;
8178eb9cceSChristian Brabandt }
8278eb9cceSChristian Brabandt
8378eb9cceSChristian Brabandt
844aea03ebSBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
854aea03ebSBram Moolenaar /*
864aea03ebSBram Moolenaar * Keep the last expression line here, for repeating.
874aea03ebSBram Moolenaar */
884aea03ebSBram Moolenaar static char_u *expr_line = NULL;
89b4bcea47SBram Moolenaar static exarg_T *expr_eap = NULL;
904aea03ebSBram Moolenaar
914aea03ebSBram Moolenaar /*
924aea03ebSBram Moolenaar * Get an expression for the "\"=expr1" or "CTRL-R =expr1"
934aea03ebSBram Moolenaar * Returns '=' when OK, NUL otherwise.
944aea03ebSBram Moolenaar */
954aea03ebSBram Moolenaar int
get_expr_register(void)964aea03ebSBram Moolenaar get_expr_register(void)
974aea03ebSBram Moolenaar {
984aea03ebSBram Moolenaar char_u *new_line;
994aea03ebSBram Moolenaar
1004aea03ebSBram Moolenaar new_line = getcmdline('=', 0L, 0, TRUE);
1014aea03ebSBram Moolenaar if (new_line == NULL)
1024aea03ebSBram Moolenaar return NUL;
1034aea03ebSBram Moolenaar if (*new_line == NUL) // use previous line
1044aea03ebSBram Moolenaar vim_free(new_line);
1054aea03ebSBram Moolenaar else
106b4bcea47SBram Moolenaar set_expr_line(new_line, NULL);
1074aea03ebSBram Moolenaar return '=';
1084aea03ebSBram Moolenaar }
1094aea03ebSBram Moolenaar
1104aea03ebSBram Moolenaar /*
1114aea03ebSBram Moolenaar * Set the expression for the '=' register.
1124aea03ebSBram Moolenaar * Argument must be an allocated string.
113b4bcea47SBram Moolenaar * "eap" may be used if the next line needs to be checked when evaluating the
114b4bcea47SBram Moolenaar * expression.
1154aea03ebSBram Moolenaar */
1164aea03ebSBram Moolenaar void
set_expr_line(char_u * new_line,exarg_T * eap)117b4bcea47SBram Moolenaar set_expr_line(char_u *new_line, exarg_T *eap)
1184aea03ebSBram Moolenaar {
1194aea03ebSBram Moolenaar vim_free(expr_line);
1204aea03ebSBram Moolenaar expr_line = new_line;
121b4bcea47SBram Moolenaar expr_eap = eap;
1224aea03ebSBram Moolenaar }
1234aea03ebSBram Moolenaar
1244aea03ebSBram Moolenaar /*
1254aea03ebSBram Moolenaar * Get the result of the '=' register expression.
1264aea03ebSBram Moolenaar * Returns a pointer to allocated memory, or NULL for failure.
1274aea03ebSBram Moolenaar */
1284aea03ebSBram Moolenaar char_u *
get_expr_line(void)1294aea03ebSBram Moolenaar get_expr_line(void)
1304aea03ebSBram Moolenaar {
1314aea03ebSBram Moolenaar char_u *expr_copy;
1324aea03ebSBram Moolenaar char_u *rv;
1334aea03ebSBram Moolenaar static int nested = 0;
1344aea03ebSBram Moolenaar
1354aea03ebSBram Moolenaar if (expr_line == NULL)
1364aea03ebSBram Moolenaar return NULL;
1374aea03ebSBram Moolenaar
1384aea03ebSBram Moolenaar // Make a copy of the expression, because evaluating it may cause it to be
1394aea03ebSBram Moolenaar // changed.
1404aea03ebSBram Moolenaar expr_copy = vim_strsave(expr_line);
1414aea03ebSBram Moolenaar if (expr_copy == NULL)
1424aea03ebSBram Moolenaar return NULL;
1434aea03ebSBram Moolenaar
1444aea03ebSBram Moolenaar // When we are invoked recursively limit the evaluation to 10 levels.
1454aea03ebSBram Moolenaar // Then return the string as-is.
1464aea03ebSBram Moolenaar if (nested >= 10)
1474aea03ebSBram Moolenaar return expr_copy;
1484aea03ebSBram Moolenaar
1494aea03ebSBram Moolenaar ++nested;
150b4bcea47SBram Moolenaar rv = eval_to_string_eap(expr_copy, TRUE, expr_eap);
1514aea03ebSBram Moolenaar --nested;
1524aea03ebSBram Moolenaar vim_free(expr_copy);
1534aea03ebSBram Moolenaar return rv;
1544aea03ebSBram Moolenaar }
1554aea03ebSBram Moolenaar
1564aea03ebSBram Moolenaar /*
1574aea03ebSBram Moolenaar * Get the '=' register expression itself, without evaluating it.
1584aea03ebSBram Moolenaar */
1594aea03ebSBram Moolenaar static char_u *
get_expr_line_src(void)1604aea03ebSBram Moolenaar get_expr_line_src(void)
1614aea03ebSBram Moolenaar {
1624aea03ebSBram Moolenaar if (expr_line == NULL)
1634aea03ebSBram Moolenaar return NULL;
1644aea03ebSBram Moolenaar return vim_strsave(expr_line);
1654aea03ebSBram Moolenaar }
1664aea03ebSBram Moolenaar #endif // FEAT_EVAL
1674aea03ebSBram Moolenaar
1684aea03ebSBram Moolenaar /*
1694aea03ebSBram Moolenaar * Check if 'regname' is a valid name of a yank register.
1704aea03ebSBram Moolenaar * Note: There is no check for 0 (default register), caller should do this
1714aea03ebSBram Moolenaar */
1724aea03ebSBram Moolenaar int
valid_yank_reg(int regname,int writing)1734aea03ebSBram Moolenaar valid_yank_reg(
1744aea03ebSBram Moolenaar int regname,
1754aea03ebSBram Moolenaar int writing) // if TRUE check for writable registers
1764aea03ebSBram Moolenaar {
1774aea03ebSBram Moolenaar if ( (regname > 0 && ASCII_ISALNUM(regname))
1784aea03ebSBram Moolenaar || (!writing && vim_strchr((char_u *)
1794aea03ebSBram Moolenaar #ifdef FEAT_EVAL
1804aea03ebSBram Moolenaar "/.%:="
1814aea03ebSBram Moolenaar #else
1824aea03ebSBram Moolenaar "/.%:"
1834aea03ebSBram Moolenaar #endif
1844aea03ebSBram Moolenaar , regname) != NULL)
1854aea03ebSBram Moolenaar || regname == '#'
1864aea03ebSBram Moolenaar || regname == '"'
1874aea03ebSBram Moolenaar || regname == '-'
1884aea03ebSBram Moolenaar || regname == '_'
1894aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
1904aea03ebSBram Moolenaar || regname == '*'
1914aea03ebSBram Moolenaar || regname == '+'
1924aea03ebSBram Moolenaar #endif
1934aea03ebSBram Moolenaar #ifdef FEAT_DND
1944aea03ebSBram Moolenaar || (!writing && regname == '~')
1954aea03ebSBram Moolenaar #endif
1964aea03ebSBram Moolenaar )
1974aea03ebSBram Moolenaar return TRUE;
1984aea03ebSBram Moolenaar return FALSE;
1994aea03ebSBram Moolenaar }
2004aea03ebSBram Moolenaar
2014aea03ebSBram Moolenaar /*
2024aea03ebSBram Moolenaar * Set y_current and y_append, according to the value of "regname".
2034aea03ebSBram Moolenaar * Cannot handle the '_' register.
2044aea03ebSBram Moolenaar * Must only be called with a valid register name!
2054aea03ebSBram Moolenaar *
2064aea03ebSBram Moolenaar * If regname is 0 and writing, use register 0
2074aea03ebSBram Moolenaar * If regname is 0 and reading, use previous register
2084aea03ebSBram Moolenaar *
2094aea03ebSBram Moolenaar * Return TRUE when the register should be inserted literally (selection or
2104aea03ebSBram Moolenaar * clipboard).
2114aea03ebSBram Moolenaar */
2124aea03ebSBram Moolenaar int
get_yank_register(int regname,int writing)2134aea03ebSBram Moolenaar get_yank_register(int regname, int writing)
2144aea03ebSBram Moolenaar {
2154aea03ebSBram Moolenaar int i;
2164aea03ebSBram Moolenaar int ret = FALSE;
2174aea03ebSBram Moolenaar
2184aea03ebSBram Moolenaar y_append = FALSE;
2194aea03ebSBram Moolenaar if ((regname == 0 || regname == '"') && !writing && y_previous != NULL)
2204aea03ebSBram Moolenaar {
2214aea03ebSBram Moolenaar y_current = y_previous;
2224aea03ebSBram Moolenaar return ret;
2234aea03ebSBram Moolenaar }
2244aea03ebSBram Moolenaar i = regname;
2254aea03ebSBram Moolenaar if (VIM_ISDIGIT(i))
2264aea03ebSBram Moolenaar i -= '0';
2274aea03ebSBram Moolenaar else if (ASCII_ISLOWER(i))
2284aea03ebSBram Moolenaar i = CharOrdLow(i) + 10;
2294aea03ebSBram Moolenaar else if (ASCII_ISUPPER(i))
2304aea03ebSBram Moolenaar {
2314aea03ebSBram Moolenaar i = CharOrdUp(i) + 10;
2324aea03ebSBram Moolenaar y_append = TRUE;
2334aea03ebSBram Moolenaar }
2344aea03ebSBram Moolenaar else if (regname == '-')
2354aea03ebSBram Moolenaar i = DELETION_REGISTER;
2364aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
2374aea03ebSBram Moolenaar // When selection is not available, use register 0 instead of '*'
2384aea03ebSBram Moolenaar else if (clip_star.available && regname == '*')
2394aea03ebSBram Moolenaar {
2404aea03ebSBram Moolenaar i = STAR_REGISTER;
2414aea03ebSBram Moolenaar ret = TRUE;
2424aea03ebSBram Moolenaar }
2434aea03ebSBram Moolenaar // When clipboard is not available, use register 0 instead of '+'
2444aea03ebSBram Moolenaar else if (clip_plus.available && regname == '+')
2454aea03ebSBram Moolenaar {
2464aea03ebSBram Moolenaar i = PLUS_REGISTER;
2474aea03ebSBram Moolenaar ret = TRUE;
2484aea03ebSBram Moolenaar }
2494aea03ebSBram Moolenaar #endif
2504aea03ebSBram Moolenaar #ifdef FEAT_DND
2514aea03ebSBram Moolenaar else if (!writing && regname == '~')
2524aea03ebSBram Moolenaar i = TILDE_REGISTER;
2534aea03ebSBram Moolenaar #endif
2544aea03ebSBram Moolenaar else // not 0-9, a-z, A-Z or '-': use register 0
2554aea03ebSBram Moolenaar i = 0;
2564aea03ebSBram Moolenaar y_current = &(y_regs[i]);
2574aea03ebSBram Moolenaar if (writing) // remember the register we write into for do_put()
2584aea03ebSBram Moolenaar y_previous = y_current;
2594aea03ebSBram Moolenaar return ret;
2604aea03ebSBram Moolenaar }
2614aea03ebSBram Moolenaar
2624aea03ebSBram Moolenaar /*
2634aea03ebSBram Moolenaar * Obtain the contents of a "normal" register. The register is made empty.
2644aea03ebSBram Moolenaar * The returned pointer has allocated memory, use put_register() later.
2654aea03ebSBram Moolenaar */
2664aea03ebSBram Moolenaar void *
get_register(int name,int copy)2674aea03ebSBram Moolenaar get_register(
2684aea03ebSBram Moolenaar int name,
2694aea03ebSBram Moolenaar int copy) // make a copy, if FALSE make register empty.
2704aea03ebSBram Moolenaar {
2714aea03ebSBram Moolenaar yankreg_T *reg;
2724aea03ebSBram Moolenaar int i;
2734aea03ebSBram Moolenaar
2744aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
2754aea03ebSBram Moolenaar // When Visual area changed, may have to update selection. Obtain the
2764aea03ebSBram Moolenaar // selection too.
2774aea03ebSBram Moolenaar if (name == '*' && clip_star.available)
2784aea03ebSBram Moolenaar {
2794aea03ebSBram Moolenaar if (clip_isautosel_star())
2804aea03ebSBram Moolenaar clip_update_selection(&clip_star);
2814aea03ebSBram Moolenaar may_get_selection(name);
2824aea03ebSBram Moolenaar }
2834aea03ebSBram Moolenaar if (name == '+' && clip_plus.available)
2844aea03ebSBram Moolenaar {
2854aea03ebSBram Moolenaar if (clip_isautosel_plus())
2864aea03ebSBram Moolenaar clip_update_selection(&clip_plus);
2874aea03ebSBram Moolenaar may_get_selection(name);
2884aea03ebSBram Moolenaar }
2894aea03ebSBram Moolenaar #endif
2904aea03ebSBram Moolenaar
2914aea03ebSBram Moolenaar get_yank_register(name, 0);
2924aea03ebSBram Moolenaar reg = ALLOC_ONE(yankreg_T);
2934aea03ebSBram Moolenaar if (reg != NULL)
2944aea03ebSBram Moolenaar {
2954aea03ebSBram Moolenaar *reg = *y_current;
2964aea03ebSBram Moolenaar if (copy)
2974aea03ebSBram Moolenaar {
2984aea03ebSBram Moolenaar // If we run out of memory some or all of the lines are empty.
2994aea03ebSBram Moolenaar if (reg->y_size == 0)
3004aea03ebSBram Moolenaar reg->y_array = NULL;
3014aea03ebSBram Moolenaar else
3024aea03ebSBram Moolenaar reg->y_array = ALLOC_MULT(char_u *, reg->y_size);
3034aea03ebSBram Moolenaar if (reg->y_array != NULL)
3044aea03ebSBram Moolenaar {
3054aea03ebSBram Moolenaar for (i = 0; i < reg->y_size; ++i)
3064aea03ebSBram Moolenaar reg->y_array[i] = vim_strsave(y_current->y_array[i]);
3074aea03ebSBram Moolenaar }
3084aea03ebSBram Moolenaar }
3094aea03ebSBram Moolenaar else
3104aea03ebSBram Moolenaar y_current->y_array = NULL;
3114aea03ebSBram Moolenaar }
3124aea03ebSBram Moolenaar return (void *)reg;
3134aea03ebSBram Moolenaar }
3144aea03ebSBram Moolenaar
3154aea03ebSBram Moolenaar /*
3164aea03ebSBram Moolenaar * Put "reg" into register "name". Free any previous contents and "reg".
3174aea03ebSBram Moolenaar */
3184aea03ebSBram Moolenaar void
put_register(int name,void * reg)3194aea03ebSBram Moolenaar put_register(int name, void *reg)
3204aea03ebSBram Moolenaar {
3214aea03ebSBram Moolenaar get_yank_register(name, 0);
3224aea03ebSBram Moolenaar free_yank_all();
3234aea03ebSBram Moolenaar *y_current = *(yankreg_T *)reg;
3244aea03ebSBram Moolenaar vim_free(reg);
3254aea03ebSBram Moolenaar
3264aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
3274aea03ebSBram Moolenaar // Send text written to clipboard register to the clipboard.
3284aea03ebSBram Moolenaar may_set_selection();
3294aea03ebSBram Moolenaar #endif
3304aea03ebSBram Moolenaar }
3314aea03ebSBram Moolenaar
332fccbf068SBram Moolenaar #if defined(FEAT_CLIPBOARD) || defined(PROTO)
3334aea03ebSBram Moolenaar void
free_register(void * reg)3344aea03ebSBram Moolenaar free_register(void *reg)
3354aea03ebSBram Moolenaar {
3364aea03ebSBram Moolenaar yankreg_T tmp;
3374aea03ebSBram Moolenaar
3384aea03ebSBram Moolenaar tmp = *y_current;
3394aea03ebSBram Moolenaar *y_current = *(yankreg_T *)reg;
3404aea03ebSBram Moolenaar free_yank_all();
3414aea03ebSBram Moolenaar vim_free(reg);
3424aea03ebSBram Moolenaar *y_current = tmp;
3434aea03ebSBram Moolenaar }
3444aea03ebSBram Moolenaar #endif
3454aea03ebSBram Moolenaar
3464aea03ebSBram Moolenaar /*
3474aea03ebSBram Moolenaar * return TRUE if the current yank register has type MLINE
3484aea03ebSBram Moolenaar */
3494aea03ebSBram Moolenaar int
yank_register_mline(int regname)3504aea03ebSBram Moolenaar yank_register_mline(int regname)
3514aea03ebSBram Moolenaar {
3524aea03ebSBram Moolenaar if (regname != 0 && !valid_yank_reg(regname, FALSE))
3534aea03ebSBram Moolenaar return FALSE;
3544aea03ebSBram Moolenaar if (regname == '_') // black hole is always empty
3554aea03ebSBram Moolenaar return FALSE;
3564aea03ebSBram Moolenaar get_yank_register(regname, FALSE);
3574aea03ebSBram Moolenaar return (y_current->y_type == MLINE);
3584aea03ebSBram Moolenaar }
3594aea03ebSBram Moolenaar
3604aea03ebSBram Moolenaar /*
3614aea03ebSBram Moolenaar * Start or stop recording into a yank register.
3624aea03ebSBram Moolenaar *
3634aea03ebSBram Moolenaar * Return FAIL for failure, OK otherwise.
3644aea03ebSBram Moolenaar */
3654aea03ebSBram Moolenaar int
do_record(int c)3664aea03ebSBram Moolenaar do_record(int c)
3674aea03ebSBram Moolenaar {
3684aea03ebSBram Moolenaar char_u *p;
3694aea03ebSBram Moolenaar static int regname;
3704aea03ebSBram Moolenaar yankreg_T *old_y_previous, *old_y_current;
3714aea03ebSBram Moolenaar int retval;
3724aea03ebSBram Moolenaar
3734aea03ebSBram Moolenaar if (reg_recording == 0) // start recording
3744aea03ebSBram Moolenaar {
3754aea03ebSBram Moolenaar // registers 0-9, a-z and " are allowed
3764aea03ebSBram Moolenaar if (c < 0 || (!ASCII_ISALNUM(c) && c != '"'))
3774aea03ebSBram Moolenaar retval = FAIL;
3784aea03ebSBram Moolenaar else
3794aea03ebSBram Moolenaar {
3804aea03ebSBram Moolenaar reg_recording = c;
3814aea03ebSBram Moolenaar showmode();
3824aea03ebSBram Moolenaar regname = c;
3834aea03ebSBram Moolenaar retval = OK;
3844aea03ebSBram Moolenaar }
3854aea03ebSBram Moolenaar }
3864aea03ebSBram Moolenaar else // stop recording
3874aea03ebSBram Moolenaar {
3884aea03ebSBram Moolenaar // Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
3894aea03ebSBram Moolenaar // needs to be removed again to put it in a register. exec_reg then
3904aea03ebSBram Moolenaar // adds the escaping back later.
3914aea03ebSBram Moolenaar reg_recording = 0;
3924aea03ebSBram Moolenaar msg("");
3934aea03ebSBram Moolenaar p = get_recorded();
3944aea03ebSBram Moolenaar if (p == NULL)
3954aea03ebSBram Moolenaar retval = FAIL;
3964aea03ebSBram Moolenaar else
3974aea03ebSBram Moolenaar {
3984aea03ebSBram Moolenaar // Remove escaping for CSI and K_SPECIAL in multi-byte chars.
3994aea03ebSBram Moolenaar vim_unescape_csi(p);
4004aea03ebSBram Moolenaar
4014aea03ebSBram Moolenaar // We don't want to change the default register here, so save and
4024aea03ebSBram Moolenaar // restore the current register name.
4034aea03ebSBram Moolenaar old_y_previous = y_previous;
4044aea03ebSBram Moolenaar old_y_current = y_current;
4054aea03ebSBram Moolenaar
4064aea03ebSBram Moolenaar retval = stuff_yank(regname, p);
4074aea03ebSBram Moolenaar
4084aea03ebSBram Moolenaar y_previous = old_y_previous;
4094aea03ebSBram Moolenaar y_current = old_y_current;
4104aea03ebSBram Moolenaar }
4114aea03ebSBram Moolenaar }
4124aea03ebSBram Moolenaar return retval;
4134aea03ebSBram Moolenaar }
4144aea03ebSBram Moolenaar
4154aea03ebSBram Moolenaar /*
4164aea03ebSBram Moolenaar * Stuff string "p" into yank register "regname" as a single line (append if
4174aea03ebSBram Moolenaar * uppercase). "p" must have been alloced.
4184aea03ebSBram Moolenaar *
4194aea03ebSBram Moolenaar * return FAIL for failure, OK otherwise
4204aea03ebSBram Moolenaar */
4214aea03ebSBram Moolenaar static int
stuff_yank(int regname,char_u * p)4224aea03ebSBram Moolenaar stuff_yank(int regname, char_u *p)
4234aea03ebSBram Moolenaar {
4244aea03ebSBram Moolenaar char_u *lp;
4254aea03ebSBram Moolenaar char_u **pp;
4264aea03ebSBram Moolenaar
4274aea03ebSBram Moolenaar // check for read-only register
4284aea03ebSBram Moolenaar if (regname != 0 && !valid_yank_reg(regname, TRUE))
4294aea03ebSBram Moolenaar {
4304aea03ebSBram Moolenaar vim_free(p);
4314aea03ebSBram Moolenaar return FAIL;
4324aea03ebSBram Moolenaar }
4334aea03ebSBram Moolenaar if (regname == '_') // black hole: don't do anything
4344aea03ebSBram Moolenaar {
4354aea03ebSBram Moolenaar vim_free(p);
4364aea03ebSBram Moolenaar return OK;
4374aea03ebSBram Moolenaar }
4384aea03ebSBram Moolenaar get_yank_register(regname, TRUE);
4394aea03ebSBram Moolenaar if (y_append && y_current->y_array != NULL)
4404aea03ebSBram Moolenaar {
4414aea03ebSBram Moolenaar pp = &(y_current->y_array[y_current->y_size - 1]);
4424aea03ebSBram Moolenaar lp = alloc(STRLEN(*pp) + STRLEN(p) + 1);
4434aea03ebSBram Moolenaar if (lp == NULL)
4444aea03ebSBram Moolenaar {
4454aea03ebSBram Moolenaar vim_free(p);
4464aea03ebSBram Moolenaar return FAIL;
4474aea03ebSBram Moolenaar }
4484aea03ebSBram Moolenaar STRCPY(lp, *pp);
4494aea03ebSBram Moolenaar STRCAT(lp, p);
4504aea03ebSBram Moolenaar vim_free(p);
4514aea03ebSBram Moolenaar vim_free(*pp);
4524aea03ebSBram Moolenaar *pp = lp;
4534aea03ebSBram Moolenaar }
4544aea03ebSBram Moolenaar else
4554aea03ebSBram Moolenaar {
4564aea03ebSBram Moolenaar free_yank_all();
4574aea03ebSBram Moolenaar if ((y_current->y_array = ALLOC_ONE(char_u *)) == NULL)
4584aea03ebSBram Moolenaar {
4594aea03ebSBram Moolenaar vim_free(p);
4604aea03ebSBram Moolenaar return FAIL;
4614aea03ebSBram Moolenaar }
4624aea03ebSBram Moolenaar y_current->y_array[0] = p;
4634aea03ebSBram Moolenaar y_current->y_size = 1;
4644aea03ebSBram Moolenaar y_current->y_type = MCHAR; // used to be MLINE, why?
4654aea03ebSBram Moolenaar #ifdef FEAT_VIMINFO
4664aea03ebSBram Moolenaar y_current->y_time_set = vim_time();
4674aea03ebSBram Moolenaar #endif
4684aea03ebSBram Moolenaar }
4694aea03ebSBram Moolenaar return OK;
4704aea03ebSBram Moolenaar }
4714aea03ebSBram Moolenaar
47241a7f82dSYegappan Lakshmanan /*
47341a7f82dSYegappan Lakshmanan * Last executed register (@ command)
47441a7f82dSYegappan Lakshmanan */
4754aea03ebSBram Moolenaar static int execreg_lastc = NUL;
4764aea03ebSBram Moolenaar
4774aea03ebSBram Moolenaar int
get_execreg_lastc(void)4784aea03ebSBram Moolenaar get_execreg_lastc(void)
4794aea03ebSBram Moolenaar {
4804aea03ebSBram Moolenaar return execreg_lastc;
4814aea03ebSBram Moolenaar }
4824aea03ebSBram Moolenaar
4834aea03ebSBram Moolenaar void
set_execreg_lastc(int lastc)4844aea03ebSBram Moolenaar set_execreg_lastc(int lastc)
4854aea03ebSBram Moolenaar {
4864aea03ebSBram Moolenaar execreg_lastc = lastc;
4874aea03ebSBram Moolenaar }
4884aea03ebSBram Moolenaar
4894aea03ebSBram Moolenaar /*
490856c1110SBram Moolenaar * When executing a register as a series of ex-commands, if the
491856c1110SBram Moolenaar * line-continuation character is used for a line, then join it with one or
492856c1110SBram Moolenaar * more previous lines. Note that lines are processed backwards starting from
493856c1110SBram Moolenaar * the last line in the register.
494856c1110SBram Moolenaar *
495856c1110SBram Moolenaar * Arguments:
496856c1110SBram Moolenaar * lines - list of lines in the register
497856c1110SBram Moolenaar * idx - index of the line starting with \ or "\. Join this line with all the
498856c1110SBram Moolenaar * immediate predecessor lines that start with a \ and the first line
499856c1110SBram Moolenaar * that doesn't start with a \. Lines that start with a comment "\
500856c1110SBram Moolenaar * character are ignored.
501856c1110SBram Moolenaar *
502856c1110SBram Moolenaar * Returns the concatenated line. The index of the line that should be
503856c1110SBram Moolenaar * processed next is returned in idx.
504856c1110SBram Moolenaar */
505856c1110SBram Moolenaar static char_u *
execreg_line_continuation(char_u ** lines,long * idx)506856c1110SBram Moolenaar execreg_line_continuation(char_u **lines, long *idx)
507856c1110SBram Moolenaar {
508856c1110SBram Moolenaar garray_T ga;
509856c1110SBram Moolenaar long i = *idx;
510856c1110SBram Moolenaar char_u *p;
511856c1110SBram Moolenaar int cmd_start;
512856c1110SBram Moolenaar int cmd_end = i;
513856c1110SBram Moolenaar int j;
514856c1110SBram Moolenaar char_u *str;
515856c1110SBram Moolenaar
516856c1110SBram Moolenaar ga_init2(&ga, (int)sizeof(char_u), 400);
517856c1110SBram Moolenaar
518856c1110SBram Moolenaar // search backwards to find the first line of this command.
519856c1110SBram Moolenaar // Any line not starting with \ or "\ is the start of the
520856c1110SBram Moolenaar // command.
521856c1110SBram Moolenaar while (--i > 0)
522856c1110SBram Moolenaar {
523856c1110SBram Moolenaar p = skipwhite(lines[i]);
524856c1110SBram Moolenaar if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' '))
525856c1110SBram Moolenaar break;
526856c1110SBram Moolenaar }
527856c1110SBram Moolenaar cmd_start = i;
528856c1110SBram Moolenaar
529856c1110SBram Moolenaar // join all the lines
530856c1110SBram Moolenaar ga_concat(&ga, lines[cmd_start]);
531856c1110SBram Moolenaar for (j = cmd_start + 1; j <= cmd_end; j++)
532856c1110SBram Moolenaar {
533856c1110SBram Moolenaar p = skipwhite(lines[j]);
534856c1110SBram Moolenaar if (*p == '\\')
535856c1110SBram Moolenaar {
536856c1110SBram Moolenaar // Adjust the growsize to the current length to
537856c1110SBram Moolenaar // speed up concatenating many lines.
538856c1110SBram Moolenaar if (ga.ga_len > 400)
539856c1110SBram Moolenaar {
540856c1110SBram Moolenaar if (ga.ga_len > 8000)
541856c1110SBram Moolenaar ga.ga_growsize = 8000;
542856c1110SBram Moolenaar else
543856c1110SBram Moolenaar ga.ga_growsize = ga.ga_len;
544856c1110SBram Moolenaar }
545856c1110SBram Moolenaar ga_concat(&ga, p + 1);
546856c1110SBram Moolenaar }
547856c1110SBram Moolenaar }
548856c1110SBram Moolenaar ga_append(&ga, NUL);
549856c1110SBram Moolenaar str = vim_strsave(ga.ga_data);
550856c1110SBram Moolenaar ga_clear(&ga);
551856c1110SBram Moolenaar
552856c1110SBram Moolenaar *idx = i;
553856c1110SBram Moolenaar return str;
554856c1110SBram Moolenaar }
555856c1110SBram Moolenaar
556856c1110SBram Moolenaar /*
5574aea03ebSBram Moolenaar * Execute a yank register: copy it into the stuff buffer.
5584aea03ebSBram Moolenaar *
5594aea03ebSBram Moolenaar * Return FAIL for failure, OK otherwise.
5604aea03ebSBram Moolenaar */
5614aea03ebSBram Moolenaar int
do_execreg(int regname,int colon,int addcr,int silent)5624aea03ebSBram Moolenaar do_execreg(
5634aea03ebSBram Moolenaar int regname,
5644aea03ebSBram Moolenaar int colon, // insert ':' before each line
5654aea03ebSBram Moolenaar int addcr, // always add '\n' to end of line
5664aea03ebSBram Moolenaar int silent) // set "silent" flag in typeahead buffer
5674aea03ebSBram Moolenaar {
5684aea03ebSBram Moolenaar long i;
5694aea03ebSBram Moolenaar char_u *p;
5704aea03ebSBram Moolenaar int retval = OK;
5714aea03ebSBram Moolenaar int remap;
5724aea03ebSBram Moolenaar
5734aea03ebSBram Moolenaar // repeat previous one
5744aea03ebSBram Moolenaar if (regname == '@')
5754aea03ebSBram Moolenaar {
5764aea03ebSBram Moolenaar if (execreg_lastc == NUL)
5774aea03ebSBram Moolenaar {
5784aea03ebSBram Moolenaar emsg(_("E748: No previously used register"));
5794aea03ebSBram Moolenaar return FAIL;
5804aea03ebSBram Moolenaar }
5814aea03ebSBram Moolenaar regname = execreg_lastc;
5824aea03ebSBram Moolenaar }
5834aea03ebSBram Moolenaar // check for valid regname
5844aea03ebSBram Moolenaar if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
5854aea03ebSBram Moolenaar {
5864aea03ebSBram Moolenaar emsg_invreg(regname);
5874aea03ebSBram Moolenaar return FAIL;
5884aea03ebSBram Moolenaar }
5894aea03ebSBram Moolenaar execreg_lastc = regname;
5904aea03ebSBram Moolenaar
5914aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
5924aea03ebSBram Moolenaar regname = may_get_selection(regname);
5934aea03ebSBram Moolenaar #endif
5944aea03ebSBram Moolenaar
5954aea03ebSBram Moolenaar // black hole: don't stuff anything
5964aea03ebSBram Moolenaar if (regname == '_')
5974aea03ebSBram Moolenaar return OK;
5984aea03ebSBram Moolenaar
5994aea03ebSBram Moolenaar // use last command line
6004aea03ebSBram Moolenaar if (regname == ':')
6014aea03ebSBram Moolenaar {
6024aea03ebSBram Moolenaar if (last_cmdline == NULL)
6034aea03ebSBram Moolenaar {
604e29a27f6SBram Moolenaar emsg(_(e_no_previous_command_line));
6054aea03ebSBram Moolenaar return FAIL;
6064aea03ebSBram Moolenaar }
6074aea03ebSBram Moolenaar // don't keep the cmdline containing @:
6084aea03ebSBram Moolenaar VIM_CLEAR(new_last_cmdline);
6094aea03ebSBram Moolenaar // Escape all control characters with a CTRL-V
6104aea03ebSBram Moolenaar p = vim_strsave_escaped_ext(last_cmdline,
6114aea03ebSBram Moolenaar (char_u *)"\001\002\003\004\005\006\007"
6124aea03ebSBram Moolenaar "\010\011\012\013\014\015\016\017"
6134aea03ebSBram Moolenaar "\020\021\022\023\024\025\026\027"
6144aea03ebSBram Moolenaar "\030\031\032\033\034\035\036\037",
6154aea03ebSBram Moolenaar Ctrl_V, FALSE);
6164aea03ebSBram Moolenaar if (p != NULL)
6174aea03ebSBram Moolenaar {
6184aea03ebSBram Moolenaar // When in Visual mode "'<,'>" will be prepended to the command.
6194aea03ebSBram Moolenaar // Remove it when it's already there.
6204aea03ebSBram Moolenaar if (VIsual_active && STRNCMP(p, "'<,'>", 5) == 0)
6214aea03ebSBram Moolenaar retval = put_in_typebuf(p + 5, TRUE, TRUE, silent);
6224aea03ebSBram Moolenaar else
6234aea03ebSBram Moolenaar retval = put_in_typebuf(p, TRUE, TRUE, silent);
6244aea03ebSBram Moolenaar }
6254aea03ebSBram Moolenaar vim_free(p);
6264aea03ebSBram Moolenaar }
6274aea03ebSBram Moolenaar #ifdef FEAT_EVAL
6284aea03ebSBram Moolenaar else if (regname == '=')
6294aea03ebSBram Moolenaar {
6304aea03ebSBram Moolenaar p = get_expr_line();
6314aea03ebSBram Moolenaar if (p == NULL)
6324aea03ebSBram Moolenaar return FAIL;
6334aea03ebSBram Moolenaar retval = put_in_typebuf(p, TRUE, colon, silent);
6344aea03ebSBram Moolenaar vim_free(p);
6354aea03ebSBram Moolenaar }
6364aea03ebSBram Moolenaar #endif
6374aea03ebSBram Moolenaar else if (regname == '.') // use last inserted text
6384aea03ebSBram Moolenaar {
6394aea03ebSBram Moolenaar p = get_last_insert_save();
6404aea03ebSBram Moolenaar if (p == NULL)
6414aea03ebSBram Moolenaar {
642e29a27f6SBram Moolenaar emsg(_(e_no_inserted_text_yet));
6434aea03ebSBram Moolenaar return FAIL;
6444aea03ebSBram Moolenaar }
6454aea03ebSBram Moolenaar retval = put_in_typebuf(p, FALSE, colon, silent);
6464aea03ebSBram Moolenaar vim_free(p);
6474aea03ebSBram Moolenaar }
6484aea03ebSBram Moolenaar else
6494aea03ebSBram Moolenaar {
6504aea03ebSBram Moolenaar get_yank_register(regname, FALSE);
6514aea03ebSBram Moolenaar if (y_current->y_array == NULL)
6524aea03ebSBram Moolenaar return FAIL;
6534aea03ebSBram Moolenaar
6544b96df5aSBram Moolenaar // Disallow remapping for ":@r".
6554aea03ebSBram Moolenaar remap = colon ? REMAP_NONE : REMAP_YES;
6564aea03ebSBram Moolenaar
6574aea03ebSBram Moolenaar // Insert lines into typeahead buffer, from last one to first one.
6584aea03ebSBram Moolenaar put_reedit_in_typebuf(silent);
6594aea03ebSBram Moolenaar for (i = y_current->y_size; --i >= 0; )
6604aea03ebSBram Moolenaar {
6614aea03ebSBram Moolenaar char_u *escaped;
662856c1110SBram Moolenaar char_u *str;
663856c1110SBram Moolenaar int free_str = FALSE;
6644aea03ebSBram Moolenaar
6654aea03ebSBram Moolenaar // insert NL between lines and after last line if type is MLINE
6664aea03ebSBram Moolenaar if (y_current->y_type == MLINE || i < y_current->y_size - 1
6674aea03ebSBram Moolenaar || addcr)
6684aea03ebSBram Moolenaar {
6694aea03ebSBram Moolenaar if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL)
6704aea03ebSBram Moolenaar return FAIL;
6714aea03ebSBram Moolenaar }
672856c1110SBram Moolenaar
673856c1110SBram Moolenaar // Handle line-continuation for :@<register>
674856c1110SBram Moolenaar str = y_current->y_array[i];
675856c1110SBram Moolenaar if (colon && i > 0)
676856c1110SBram Moolenaar {
677856c1110SBram Moolenaar p = skipwhite(str);
678856c1110SBram Moolenaar if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' '))
679856c1110SBram Moolenaar {
680856c1110SBram Moolenaar str = execreg_line_continuation(y_current->y_array, &i);
681856c1110SBram Moolenaar if (str == NULL)
682856c1110SBram Moolenaar return FAIL;
683856c1110SBram Moolenaar free_str = TRUE;
684856c1110SBram Moolenaar }
685856c1110SBram Moolenaar }
686856c1110SBram Moolenaar escaped = vim_strsave_escape_csi(str);
687856c1110SBram Moolenaar if (free_str)
688856c1110SBram Moolenaar vim_free(str);
6894aea03ebSBram Moolenaar if (escaped == NULL)
6904aea03ebSBram Moolenaar return FAIL;
6914aea03ebSBram Moolenaar retval = ins_typebuf(escaped, remap, 0, TRUE, silent);
6924aea03ebSBram Moolenaar vim_free(escaped);
6934aea03ebSBram Moolenaar if (retval == FAIL)
6944aea03ebSBram Moolenaar return FAIL;
6954aea03ebSBram Moolenaar if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, silent)
6964aea03ebSBram Moolenaar == FAIL)
6974aea03ebSBram Moolenaar return FAIL;
6984aea03ebSBram Moolenaar }
6994aea03ebSBram Moolenaar reg_executing = regname == 0 ? '"' : regname; // disable "q" command
7004aea03ebSBram Moolenaar }
7014aea03ebSBram Moolenaar return retval;
7024aea03ebSBram Moolenaar }
7034aea03ebSBram Moolenaar
7044aea03ebSBram Moolenaar /*
7054aea03ebSBram Moolenaar * If "restart_edit" is not zero, put it in the typeahead buffer, so that it's
7064aea03ebSBram Moolenaar * used only after other typeahead has been processed.
7074aea03ebSBram Moolenaar */
7084aea03ebSBram Moolenaar static void
put_reedit_in_typebuf(int silent)7094aea03ebSBram Moolenaar put_reedit_in_typebuf(int silent)
7104aea03ebSBram Moolenaar {
7114aea03ebSBram Moolenaar char_u buf[3];
7124aea03ebSBram Moolenaar
7134aea03ebSBram Moolenaar if (restart_edit != NUL)
7144aea03ebSBram Moolenaar {
7154aea03ebSBram Moolenaar if (restart_edit == 'V')
7164aea03ebSBram Moolenaar {
7174aea03ebSBram Moolenaar buf[0] = 'g';
7184aea03ebSBram Moolenaar buf[1] = 'R';
7194aea03ebSBram Moolenaar buf[2] = NUL;
7204aea03ebSBram Moolenaar }
7214aea03ebSBram Moolenaar else
7224aea03ebSBram Moolenaar {
7234aea03ebSBram Moolenaar buf[0] = restart_edit == 'I' ? 'i' : restart_edit;
7244aea03ebSBram Moolenaar buf[1] = NUL;
7254aea03ebSBram Moolenaar }
7264aea03ebSBram Moolenaar if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, silent) == OK)
7274aea03ebSBram Moolenaar restart_edit = NUL;
7284aea03ebSBram Moolenaar }
7294aea03ebSBram Moolenaar }
7304aea03ebSBram Moolenaar
7314aea03ebSBram Moolenaar /*
7324aea03ebSBram Moolenaar * Insert register contents "s" into the typeahead buffer, so that it will be
7334aea03ebSBram Moolenaar * executed again.
7344aea03ebSBram Moolenaar * When "esc" is TRUE it is to be taken literally: Escape CSI characters and
7354aea03ebSBram Moolenaar * no remapping.
7364aea03ebSBram Moolenaar */
7374aea03ebSBram Moolenaar static int
put_in_typebuf(char_u * s,int esc,int colon,int silent)7384aea03ebSBram Moolenaar put_in_typebuf(
7394aea03ebSBram Moolenaar char_u *s,
7404aea03ebSBram Moolenaar int esc,
7414aea03ebSBram Moolenaar int colon, // add ':' before the line
7424aea03ebSBram Moolenaar int silent)
7434aea03ebSBram Moolenaar {
7444aea03ebSBram Moolenaar int retval = OK;
7454aea03ebSBram Moolenaar
7464aea03ebSBram Moolenaar put_reedit_in_typebuf(silent);
7474aea03ebSBram Moolenaar if (colon)
7484aea03ebSBram Moolenaar retval = ins_typebuf((char_u *)"\n", REMAP_NONE, 0, TRUE, silent);
7494aea03ebSBram Moolenaar if (retval == OK)
7504aea03ebSBram Moolenaar {
7514aea03ebSBram Moolenaar char_u *p;
7524aea03ebSBram Moolenaar
7534aea03ebSBram Moolenaar if (esc)
7544aea03ebSBram Moolenaar p = vim_strsave_escape_csi(s);
7554aea03ebSBram Moolenaar else
7564aea03ebSBram Moolenaar p = s;
7574aea03ebSBram Moolenaar if (p == NULL)
7584aea03ebSBram Moolenaar retval = FAIL;
7594aea03ebSBram Moolenaar else
7604aea03ebSBram Moolenaar retval = ins_typebuf(p, esc ? REMAP_NONE : REMAP_YES,
7614aea03ebSBram Moolenaar 0, TRUE, silent);
7624aea03ebSBram Moolenaar if (esc)
7634aea03ebSBram Moolenaar vim_free(p);
7644aea03ebSBram Moolenaar }
7654aea03ebSBram Moolenaar if (colon && retval == OK)
7664aea03ebSBram Moolenaar retval = ins_typebuf((char_u *)":", REMAP_NONE, 0, TRUE, silent);
7674aea03ebSBram Moolenaar return retval;
7684aea03ebSBram Moolenaar }
7694aea03ebSBram Moolenaar
7704aea03ebSBram Moolenaar /*
7714aea03ebSBram Moolenaar * Insert a yank register: copy it into the Read buffer.
7724aea03ebSBram Moolenaar * Used by CTRL-R command and middle mouse button in insert mode.
7734aea03ebSBram Moolenaar *
7744aea03ebSBram Moolenaar * return FAIL for failure, OK otherwise
7754aea03ebSBram Moolenaar */
7764aea03ebSBram Moolenaar int
insert_reg(int regname,int literally_arg)7774aea03ebSBram Moolenaar insert_reg(
7784aea03ebSBram Moolenaar int regname,
7794aea03ebSBram Moolenaar int literally_arg) // insert literally, not as if typed
7804aea03ebSBram Moolenaar {
7814aea03ebSBram Moolenaar long i;
7824aea03ebSBram Moolenaar int retval = OK;
7834aea03ebSBram Moolenaar char_u *arg;
7844aea03ebSBram Moolenaar int allocated;
7854aea03ebSBram Moolenaar int literally = literally_arg;
7864aea03ebSBram Moolenaar
7874aea03ebSBram Moolenaar // It is possible to get into an endless loop by having CTRL-R a in
7884aea03ebSBram Moolenaar // register a and then, in insert mode, doing CTRL-R a.
7894aea03ebSBram Moolenaar // If you hit CTRL-C, the loop will be broken here.
7904aea03ebSBram Moolenaar ui_breakcheck();
7914aea03ebSBram Moolenaar if (got_int)
7924aea03ebSBram Moolenaar return FAIL;
7934aea03ebSBram Moolenaar
7944aea03ebSBram Moolenaar // check for valid regname
7954aea03ebSBram Moolenaar if (regname != NUL && !valid_yank_reg(regname, FALSE))
7964aea03ebSBram Moolenaar return FAIL;
7974aea03ebSBram Moolenaar
7984aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
7994aea03ebSBram Moolenaar regname = may_get_selection(regname);
8004aea03ebSBram Moolenaar #endif
8014aea03ebSBram Moolenaar
8024aea03ebSBram Moolenaar if (regname == '.') // insert last inserted text
8034aea03ebSBram Moolenaar retval = stuff_inserted(NUL, 1L, TRUE);
8044aea03ebSBram Moolenaar else if (get_spec_reg(regname, &arg, &allocated, TRUE))
8054aea03ebSBram Moolenaar {
8064aea03ebSBram Moolenaar if (arg == NULL)
8074aea03ebSBram Moolenaar return FAIL;
8084aea03ebSBram Moolenaar stuffescaped(arg, literally);
8094aea03ebSBram Moolenaar if (allocated)
8104aea03ebSBram Moolenaar vim_free(arg);
8114aea03ebSBram Moolenaar }
8124aea03ebSBram Moolenaar else // name or number register
8134aea03ebSBram Moolenaar {
8144aea03ebSBram Moolenaar if (get_yank_register(regname, FALSE))
8154aea03ebSBram Moolenaar literally = TRUE;
8164aea03ebSBram Moolenaar if (y_current->y_array == NULL)
8174aea03ebSBram Moolenaar retval = FAIL;
8184aea03ebSBram Moolenaar else
8194aea03ebSBram Moolenaar {
8204aea03ebSBram Moolenaar for (i = 0; i < y_current->y_size; ++i)
8214aea03ebSBram Moolenaar {
822032a2d05SBram Moolenaar if (regname == '-')
823032a2d05SBram Moolenaar {
824032a2d05SBram Moolenaar AppendCharToRedobuff(Ctrl_R);
825032a2d05SBram Moolenaar AppendCharToRedobuff(regname);
826032a2d05SBram Moolenaar do_put(regname, NULL, BACKWARD, 1L, PUT_CURSEND);
827032a2d05SBram Moolenaar }
828032a2d05SBram Moolenaar else
8294aea03ebSBram Moolenaar stuffescaped(y_current->y_array[i], literally);
8304aea03ebSBram Moolenaar // Insert a newline between lines and after last line if
8314aea03ebSBram Moolenaar // y_type is MLINE.
8324aea03ebSBram Moolenaar if (y_current->y_type == MLINE || i < y_current->y_size - 1)
8334aea03ebSBram Moolenaar stuffcharReadbuff('\n');
8344aea03ebSBram Moolenaar }
8354aea03ebSBram Moolenaar }
8364aea03ebSBram Moolenaar }
8374aea03ebSBram Moolenaar
8384aea03ebSBram Moolenaar return retval;
8394aea03ebSBram Moolenaar }
8404aea03ebSBram Moolenaar
8414aea03ebSBram Moolenaar /*
8424aea03ebSBram Moolenaar * If "regname" is a special register, return TRUE and store a pointer to its
8434aea03ebSBram Moolenaar * value in "argp".
8444aea03ebSBram Moolenaar */
8454aea03ebSBram Moolenaar int
get_spec_reg(int regname,char_u ** argp,int * allocated,int errmsg)8464aea03ebSBram Moolenaar get_spec_reg(
8474aea03ebSBram Moolenaar int regname,
8484aea03ebSBram Moolenaar char_u **argp,
8494aea03ebSBram Moolenaar int *allocated, // return: TRUE when value was allocated
8504aea03ebSBram Moolenaar int errmsg) // give error message when failing
8514aea03ebSBram Moolenaar {
8524aea03ebSBram Moolenaar int cnt;
8534aea03ebSBram Moolenaar
8544aea03ebSBram Moolenaar *argp = NULL;
8554aea03ebSBram Moolenaar *allocated = FALSE;
8564aea03ebSBram Moolenaar switch (regname)
8574aea03ebSBram Moolenaar {
8584aea03ebSBram Moolenaar case '%': // file name
8594aea03ebSBram Moolenaar if (errmsg)
8604aea03ebSBram Moolenaar check_fname(); // will give emsg if not set
8614aea03ebSBram Moolenaar *argp = curbuf->b_fname;
8624aea03ebSBram Moolenaar return TRUE;
8634aea03ebSBram Moolenaar
8644aea03ebSBram Moolenaar case '#': // alternate file name
8654aea03ebSBram Moolenaar *argp = getaltfname(errmsg); // may give emsg if not set
8664aea03ebSBram Moolenaar return TRUE;
8674aea03ebSBram Moolenaar
8684aea03ebSBram Moolenaar #ifdef FEAT_EVAL
8694aea03ebSBram Moolenaar case '=': // result of expression
8704aea03ebSBram Moolenaar *argp = get_expr_line();
8714aea03ebSBram Moolenaar *allocated = TRUE;
8724aea03ebSBram Moolenaar return TRUE;
8734aea03ebSBram Moolenaar #endif
8744aea03ebSBram Moolenaar
8754aea03ebSBram Moolenaar case ':': // last command line
8764aea03ebSBram Moolenaar if (last_cmdline == NULL && errmsg)
877e29a27f6SBram Moolenaar emsg(_(e_no_previous_command_line));
8784aea03ebSBram Moolenaar *argp = last_cmdline;
8794aea03ebSBram Moolenaar return TRUE;
8804aea03ebSBram Moolenaar
8814aea03ebSBram Moolenaar case '/': // last search-pattern
8824aea03ebSBram Moolenaar if (last_search_pat() == NULL && errmsg)
883e29a27f6SBram Moolenaar emsg(_(e_no_previous_regular_expression));
8844aea03ebSBram Moolenaar *argp = last_search_pat();
8854aea03ebSBram Moolenaar return TRUE;
8864aea03ebSBram Moolenaar
8874aea03ebSBram Moolenaar case '.': // last inserted text
8884aea03ebSBram Moolenaar *argp = get_last_insert_save();
8894aea03ebSBram Moolenaar *allocated = TRUE;
8904aea03ebSBram Moolenaar if (*argp == NULL && errmsg)
891e29a27f6SBram Moolenaar emsg(_(e_no_inserted_text_yet));
8924aea03ebSBram Moolenaar return TRUE;
8934aea03ebSBram Moolenaar
8944aea03ebSBram Moolenaar #ifdef FEAT_SEARCHPATH
8954aea03ebSBram Moolenaar case Ctrl_F: // Filename under cursor
8964aea03ebSBram Moolenaar case Ctrl_P: // Path under cursor, expand via "path"
8974aea03ebSBram Moolenaar if (!errmsg)
8984aea03ebSBram Moolenaar return FALSE;
8994aea03ebSBram Moolenaar *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
9004aea03ebSBram Moolenaar | (regname == Ctrl_P ? FNAME_EXP : 0), 1L, NULL);
9014aea03ebSBram Moolenaar *allocated = TRUE;
9024aea03ebSBram Moolenaar return TRUE;
9034aea03ebSBram Moolenaar #endif
9044aea03ebSBram Moolenaar
9054aea03ebSBram Moolenaar case Ctrl_W: // word under cursor
9064aea03ebSBram Moolenaar case Ctrl_A: // WORD (mnemonic All) under cursor
9074aea03ebSBram Moolenaar if (!errmsg)
9084aea03ebSBram Moolenaar return FALSE;
9094aea03ebSBram Moolenaar cnt = find_ident_under_cursor(argp, regname == Ctrl_W
9104aea03ebSBram Moolenaar ? (FIND_IDENT|FIND_STRING) : FIND_STRING);
9114aea03ebSBram Moolenaar *argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
9124aea03ebSBram Moolenaar *allocated = TRUE;
9134aea03ebSBram Moolenaar return TRUE;
9144aea03ebSBram Moolenaar
9154aea03ebSBram Moolenaar case Ctrl_L: // Line under cursor
9164aea03ebSBram Moolenaar if (!errmsg)
9174aea03ebSBram Moolenaar return FALSE;
9184aea03ebSBram Moolenaar
9194aea03ebSBram Moolenaar *argp = ml_get_buf(curwin->w_buffer,
9204aea03ebSBram Moolenaar curwin->w_cursor.lnum, FALSE);
9214aea03ebSBram Moolenaar return TRUE;
9224aea03ebSBram Moolenaar
9234aea03ebSBram Moolenaar case '_': // black hole: always empty
9244aea03ebSBram Moolenaar *argp = (char_u *)"";
9254aea03ebSBram Moolenaar return TRUE;
9264aea03ebSBram Moolenaar }
9274aea03ebSBram Moolenaar
9284aea03ebSBram Moolenaar return FALSE;
9294aea03ebSBram Moolenaar }
9304aea03ebSBram Moolenaar
9314aea03ebSBram Moolenaar /*
9324aea03ebSBram Moolenaar * Paste a yank register into the command line.
9334aea03ebSBram Moolenaar * Only for non-special registers.
9344aea03ebSBram Moolenaar * Used by CTRL-R command in command-line mode
9354aea03ebSBram Moolenaar * insert_reg() can't be used here, because special characters from the
9364aea03ebSBram Moolenaar * register contents will be interpreted as commands.
9374aea03ebSBram Moolenaar *
9384aea03ebSBram Moolenaar * return FAIL for failure, OK otherwise
9394aea03ebSBram Moolenaar */
9404aea03ebSBram Moolenaar int
cmdline_paste_reg(int regname,int literally_arg,int remcr)9414aea03ebSBram Moolenaar cmdline_paste_reg(
9424aea03ebSBram Moolenaar int regname,
9434aea03ebSBram Moolenaar int literally_arg, // Insert text literally instead of "as typed"
9444aea03ebSBram Moolenaar int remcr) // don't add CR characters
9454aea03ebSBram Moolenaar {
9464aea03ebSBram Moolenaar long i;
9474aea03ebSBram Moolenaar int literally = literally_arg;
9484aea03ebSBram Moolenaar
9494aea03ebSBram Moolenaar if (get_yank_register(regname, FALSE))
9504aea03ebSBram Moolenaar literally = TRUE;
9514aea03ebSBram Moolenaar if (y_current->y_array == NULL)
9524aea03ebSBram Moolenaar return FAIL;
9534aea03ebSBram Moolenaar
9544aea03ebSBram Moolenaar for (i = 0; i < y_current->y_size; ++i)
9554aea03ebSBram Moolenaar {
9564aea03ebSBram Moolenaar cmdline_paste_str(y_current->y_array[i], literally);
9574aea03ebSBram Moolenaar
9584aea03ebSBram Moolenaar // Insert ^M between lines and after last line if type is MLINE.
9594aea03ebSBram Moolenaar // Don't do this when "remcr" is TRUE.
9604aea03ebSBram Moolenaar if ((y_current->y_type == MLINE || i < y_current->y_size - 1) && !remcr)
9614aea03ebSBram Moolenaar cmdline_paste_str((char_u *)"\r", literally);
9624aea03ebSBram Moolenaar
9634aea03ebSBram Moolenaar // Check for CTRL-C, in case someone tries to paste a few thousand
9644aea03ebSBram Moolenaar // lines and gets bored.
9654aea03ebSBram Moolenaar ui_breakcheck();
9664aea03ebSBram Moolenaar if (got_int)
9674aea03ebSBram Moolenaar return FAIL;
9684aea03ebSBram Moolenaar }
9694aea03ebSBram Moolenaar return OK;
9704aea03ebSBram Moolenaar }
9714aea03ebSBram Moolenaar
9724aea03ebSBram Moolenaar /*
9734aea03ebSBram Moolenaar * Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
9744aea03ebSBram Moolenaar */
9754aea03ebSBram Moolenaar void
shift_delete_registers()9764aea03ebSBram Moolenaar shift_delete_registers()
9774aea03ebSBram Moolenaar {
9784aea03ebSBram Moolenaar int n;
9794aea03ebSBram Moolenaar
9804aea03ebSBram Moolenaar y_current = &y_regs[9];
9814aea03ebSBram Moolenaar free_yank_all(); // free register nine
9824aea03ebSBram Moolenaar for (n = 9; n > 1; --n)
9834aea03ebSBram Moolenaar y_regs[n] = y_regs[n - 1];
9844aea03ebSBram Moolenaar y_current = &y_regs[1];
9854aea03ebSBram Moolenaar if (!y_append)
9864aea03ebSBram Moolenaar y_previous = y_current;
9874aea03ebSBram Moolenaar y_regs[1].y_array = NULL; // set register one to empty
9884aea03ebSBram Moolenaar }
9894aea03ebSBram Moolenaar
9904aea03ebSBram Moolenaar #if defined(FEAT_EVAL)
9914aea03ebSBram Moolenaar void
yank_do_autocmd(oparg_T * oap,yankreg_T * reg)9924aea03ebSBram Moolenaar yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
9934aea03ebSBram Moolenaar {
9944aea03ebSBram Moolenaar static int recursive = FALSE;
9954aea03ebSBram Moolenaar dict_T *v_event;
9964aea03ebSBram Moolenaar list_T *list;
9974aea03ebSBram Moolenaar int n;
9984aea03ebSBram Moolenaar char_u buf[NUMBUFLEN + 2];
9994aea03ebSBram Moolenaar long reglen = 0;
1000*3075a455SBram Moolenaar save_v_event_T save_v_event;
10014aea03ebSBram Moolenaar
10024aea03ebSBram Moolenaar if (recursive)
10034aea03ebSBram Moolenaar return;
10044aea03ebSBram Moolenaar
1005*3075a455SBram Moolenaar v_event = get_v_event(&save_v_event);
10064aea03ebSBram Moolenaar
10074aea03ebSBram Moolenaar list = list_alloc();
10084aea03ebSBram Moolenaar if (list == NULL)
10094aea03ebSBram Moolenaar return;
10104aea03ebSBram Moolenaar for (n = 0; n < reg->y_size; n++)
10114aea03ebSBram Moolenaar list_append_string(list, reg->y_array[n], -1);
10124aea03ebSBram Moolenaar list->lv_lock = VAR_FIXED;
10136d90c61cSBram Moolenaar (void)dict_add_list(v_event, "regcontents", list);
10144aea03ebSBram Moolenaar
10154aea03ebSBram Moolenaar buf[0] = (char_u)oap->regname;
10164aea03ebSBram Moolenaar buf[1] = NUL;
10176d90c61cSBram Moolenaar (void)dict_add_string(v_event, "regname", buf);
10184aea03ebSBram Moolenaar
10194aea03ebSBram Moolenaar buf[0] = get_op_char(oap->op_type);
10204aea03ebSBram Moolenaar buf[1] = get_extra_op_char(oap->op_type);
10214aea03ebSBram Moolenaar buf[2] = NUL;
10226d90c61cSBram Moolenaar (void)dict_add_string(v_event, "operator", buf);
10234aea03ebSBram Moolenaar
10244aea03ebSBram Moolenaar buf[0] = NUL;
10254aea03ebSBram Moolenaar buf[1] = NUL;
10264aea03ebSBram Moolenaar switch (get_reg_type(oap->regname, ®len))
10274aea03ebSBram Moolenaar {
10284aea03ebSBram Moolenaar case MLINE: buf[0] = 'V'; break;
10294aea03ebSBram Moolenaar case MCHAR: buf[0] = 'v'; break;
10304aea03ebSBram Moolenaar case MBLOCK:
10314aea03ebSBram Moolenaar vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
10324aea03ebSBram Moolenaar reglen + 1);
10334aea03ebSBram Moolenaar break;
10344aea03ebSBram Moolenaar }
10356d90c61cSBram Moolenaar (void)dict_add_string(v_event, "regtype", buf);
10364aea03ebSBram Moolenaar
10376d90c61cSBram Moolenaar (void)dict_add_bool(v_event, "visual", oap->is_VIsual);
103837d1673cSBram Moolenaar
10394aea03ebSBram Moolenaar // Lock the dictionary and its keys
10404aea03ebSBram Moolenaar dict_set_items_ro(v_event);
10414aea03ebSBram Moolenaar
10424aea03ebSBram Moolenaar recursive = TRUE;
10436adb9ea0SBram Moolenaar textwinlock++;
10444aea03ebSBram Moolenaar apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
10456adb9ea0SBram Moolenaar textwinlock--;
10464aea03ebSBram Moolenaar recursive = FALSE;
10474aea03ebSBram Moolenaar
10484aea03ebSBram Moolenaar // Empty the dictionary, v:event is still valid
1049*3075a455SBram Moolenaar restore_v_event(v_event, &save_v_event);
10504aea03ebSBram Moolenaar }
10514aea03ebSBram Moolenaar #endif
10524aea03ebSBram Moolenaar
10534aea03ebSBram Moolenaar /*
10544aea03ebSBram Moolenaar * set all the yank registers to empty (called from main())
10554aea03ebSBram Moolenaar */
10564aea03ebSBram Moolenaar void
init_yank(void)10574aea03ebSBram Moolenaar init_yank(void)
10584aea03ebSBram Moolenaar {
10594aea03ebSBram Moolenaar int i;
10604aea03ebSBram Moolenaar
10614aea03ebSBram Moolenaar for (i = 0; i < NUM_REGISTERS; ++i)
10624aea03ebSBram Moolenaar y_regs[i].y_array = NULL;
10634aea03ebSBram Moolenaar }
10644aea03ebSBram Moolenaar
10654aea03ebSBram Moolenaar #if defined(EXITFREE) || defined(PROTO)
10664aea03ebSBram Moolenaar void
clear_registers(void)10674aea03ebSBram Moolenaar clear_registers(void)
10684aea03ebSBram Moolenaar {
10694aea03ebSBram Moolenaar int i;
10704aea03ebSBram Moolenaar
10714aea03ebSBram Moolenaar for (i = 0; i < NUM_REGISTERS; ++i)
10724aea03ebSBram Moolenaar {
10734aea03ebSBram Moolenaar y_current = &y_regs[i];
10744aea03ebSBram Moolenaar if (y_current->y_array != NULL)
10754aea03ebSBram Moolenaar free_yank_all();
10764aea03ebSBram Moolenaar }
10774aea03ebSBram Moolenaar }
10784aea03ebSBram Moolenaar #endif
10794aea03ebSBram Moolenaar
10804aea03ebSBram Moolenaar /*
10814aea03ebSBram Moolenaar * Free "n" lines from the current yank register.
10824aea03ebSBram Moolenaar * Called for normal freeing and in case of error.
10834aea03ebSBram Moolenaar */
10844aea03ebSBram Moolenaar static void
free_yank(long n)10854aea03ebSBram Moolenaar free_yank(long n)
10864aea03ebSBram Moolenaar {
10874aea03ebSBram Moolenaar if (y_current->y_array != NULL)
10884aea03ebSBram Moolenaar {
10894aea03ebSBram Moolenaar long i;
10904aea03ebSBram Moolenaar
10914aea03ebSBram Moolenaar for (i = n; --i >= 0; )
10924aea03ebSBram Moolenaar {
10934aea03ebSBram Moolenaar #ifdef AMIGA // only for very slow machines
10944aea03ebSBram Moolenaar if ((i & 1023) == 1023) // this may take a while
10954aea03ebSBram Moolenaar {
10964aea03ebSBram Moolenaar // This message should never cause a hit-return message.
10974aea03ebSBram Moolenaar // Overwrite this message with any next message.
10984aea03ebSBram Moolenaar ++no_wait_return;
10994aea03ebSBram Moolenaar smsg(_("freeing %ld lines"), i + 1);
11004aea03ebSBram Moolenaar --no_wait_return;
11014aea03ebSBram Moolenaar msg_didout = FALSE;
11024aea03ebSBram Moolenaar msg_col = 0;
11034aea03ebSBram Moolenaar }
11044aea03ebSBram Moolenaar #endif
11054aea03ebSBram Moolenaar vim_free(y_current->y_array[i]);
11064aea03ebSBram Moolenaar }
11074aea03ebSBram Moolenaar VIM_CLEAR(y_current->y_array);
11084aea03ebSBram Moolenaar #ifdef AMIGA
11094aea03ebSBram Moolenaar if (n >= 1000)
11104aea03ebSBram Moolenaar msg("");
11114aea03ebSBram Moolenaar #endif
11124aea03ebSBram Moolenaar }
11134aea03ebSBram Moolenaar }
11144aea03ebSBram Moolenaar
111545fffdf1SBram Moolenaar void
free_yank_all(void)11164aea03ebSBram Moolenaar free_yank_all(void)
11174aea03ebSBram Moolenaar {
11184aea03ebSBram Moolenaar free_yank(y_current->y_size);
11194aea03ebSBram Moolenaar }
11204aea03ebSBram Moolenaar
11214aea03ebSBram Moolenaar /*
11224aea03ebSBram Moolenaar * Yank the text between "oap->start" and "oap->end" into a yank register.
11234aea03ebSBram Moolenaar * If we are to append (uppercase register), we first yank into a new yank
11244aea03ebSBram Moolenaar * register and then concatenate the old and the new one (so we keep the old
11254aea03ebSBram Moolenaar * one in case of out-of-memory).
11264aea03ebSBram Moolenaar *
11274aea03ebSBram Moolenaar * Return FAIL for failure, OK otherwise.
11284aea03ebSBram Moolenaar */
11294aea03ebSBram Moolenaar int
op_yank(oparg_T * oap,int deleting,int mess)11304aea03ebSBram Moolenaar op_yank(oparg_T *oap, int deleting, int mess)
11314aea03ebSBram Moolenaar {
11324aea03ebSBram Moolenaar long y_idx; // index in y_array[]
11334aea03ebSBram Moolenaar yankreg_T *curr; // copy of y_current
11344aea03ebSBram Moolenaar yankreg_T newreg; // new yank register when appending
11354aea03ebSBram Moolenaar char_u **new_ptr;
11364aea03ebSBram Moolenaar linenr_T lnum; // current line number
11374aea03ebSBram Moolenaar long j;
11384aea03ebSBram Moolenaar int yanktype = oap->motion_type;
11394aea03ebSBram Moolenaar long yanklines = oap->line_count;
11404aea03ebSBram Moolenaar linenr_T yankendlnum = oap->end.lnum;
11414aea03ebSBram Moolenaar char_u *p;
11424aea03ebSBram Moolenaar char_u *pnew;
11434aea03ebSBram Moolenaar struct block_def bd;
11444aea03ebSBram Moolenaar #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
11454aea03ebSBram Moolenaar int did_star = FALSE;
11464aea03ebSBram Moolenaar #endif
11474aea03ebSBram Moolenaar
11484aea03ebSBram Moolenaar // check for read-only register
11494aea03ebSBram Moolenaar if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
11504aea03ebSBram Moolenaar {
11514aea03ebSBram Moolenaar beep_flush();
11524aea03ebSBram Moolenaar return FAIL;
11534aea03ebSBram Moolenaar }
11544aea03ebSBram Moolenaar if (oap->regname == '_') // black hole: nothing to do
11554aea03ebSBram Moolenaar return OK;
11564aea03ebSBram Moolenaar
11574aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
11584aea03ebSBram Moolenaar if (!clip_star.available && oap->regname == '*')
11594aea03ebSBram Moolenaar oap->regname = 0;
11604aea03ebSBram Moolenaar else if (!clip_plus.available && oap->regname == '+')
11614aea03ebSBram Moolenaar oap->regname = 0;
11624aea03ebSBram Moolenaar #endif
11634aea03ebSBram Moolenaar
11644aea03ebSBram Moolenaar if (!deleting) // op_delete() already set y_current
11654aea03ebSBram Moolenaar get_yank_register(oap->regname, TRUE);
11664aea03ebSBram Moolenaar
11674aea03ebSBram Moolenaar curr = y_current;
11684aea03ebSBram Moolenaar // append to existing contents
11694aea03ebSBram Moolenaar if (y_append && y_current->y_array != NULL)
11704aea03ebSBram Moolenaar y_current = &newreg;
11714aea03ebSBram Moolenaar else
11724aea03ebSBram Moolenaar free_yank_all(); // free previously yanked lines
11734aea03ebSBram Moolenaar
11744aea03ebSBram Moolenaar // If the cursor was in column 1 before and after the movement, and the
11754aea03ebSBram Moolenaar // operator is not inclusive, the yank is always linewise.
11764aea03ebSBram Moolenaar if ( oap->motion_type == MCHAR
11774aea03ebSBram Moolenaar && oap->start.col == 0
11784aea03ebSBram Moolenaar && !oap->inclusive
11794aea03ebSBram Moolenaar && (!oap->is_VIsual || *p_sel == 'o')
11804aea03ebSBram Moolenaar && !oap->block_mode
11814aea03ebSBram Moolenaar && oap->end.col == 0
11824aea03ebSBram Moolenaar && yanklines > 1)
11834aea03ebSBram Moolenaar {
11844aea03ebSBram Moolenaar yanktype = MLINE;
11854aea03ebSBram Moolenaar --yankendlnum;
11864aea03ebSBram Moolenaar --yanklines;
11874aea03ebSBram Moolenaar }
11884aea03ebSBram Moolenaar
11894aea03ebSBram Moolenaar y_current->y_size = yanklines;
11904aea03ebSBram Moolenaar y_current->y_type = yanktype; // set the yank register type
11914aea03ebSBram Moolenaar y_current->y_width = 0;
11924aea03ebSBram Moolenaar y_current->y_array = lalloc_clear(sizeof(char_u *) * yanklines, TRUE);
11934aea03ebSBram Moolenaar if (y_current->y_array == NULL)
11944aea03ebSBram Moolenaar {
11954aea03ebSBram Moolenaar y_current = curr;
11964aea03ebSBram Moolenaar return FAIL;
11974aea03ebSBram Moolenaar }
11984aea03ebSBram Moolenaar #ifdef FEAT_VIMINFO
11994aea03ebSBram Moolenaar y_current->y_time_set = vim_time();
12004aea03ebSBram Moolenaar #endif
12014aea03ebSBram Moolenaar
12024aea03ebSBram Moolenaar y_idx = 0;
12034aea03ebSBram Moolenaar lnum = oap->start.lnum;
12044aea03ebSBram Moolenaar
12054aea03ebSBram Moolenaar if (oap->block_mode)
12064aea03ebSBram Moolenaar {
12074aea03ebSBram Moolenaar // Visual block mode
12084aea03ebSBram Moolenaar y_current->y_type = MBLOCK; // set the yank register type
12094aea03ebSBram Moolenaar y_current->y_width = oap->end_vcol - oap->start_vcol;
12104aea03ebSBram Moolenaar
12114aea03ebSBram Moolenaar if (curwin->w_curswant == MAXCOL && y_current->y_width > 0)
12124aea03ebSBram Moolenaar y_current->y_width--;
12134aea03ebSBram Moolenaar }
12144aea03ebSBram Moolenaar
12154aea03ebSBram Moolenaar for ( ; lnum <= yankendlnum; lnum++, y_idx++)
12164aea03ebSBram Moolenaar {
12174aea03ebSBram Moolenaar switch (y_current->y_type)
12184aea03ebSBram Moolenaar {
12194aea03ebSBram Moolenaar case MBLOCK:
12204aea03ebSBram Moolenaar block_prep(oap, &bd, lnum, FALSE);
1221544a38e4SChristian Brabandt if (yank_copy_line(&bd, y_idx, oap->excl_tr_ws) == FAIL)
12224aea03ebSBram Moolenaar goto fail;
12234aea03ebSBram Moolenaar break;
12244aea03ebSBram Moolenaar
12254aea03ebSBram Moolenaar case MLINE:
12264aea03ebSBram Moolenaar if ((y_current->y_array[y_idx] =
12274aea03ebSBram Moolenaar vim_strsave(ml_get(lnum))) == NULL)
12284aea03ebSBram Moolenaar goto fail;
12294aea03ebSBram Moolenaar break;
12304aea03ebSBram Moolenaar
12314aea03ebSBram Moolenaar case MCHAR:
12324aea03ebSBram Moolenaar {
12334aea03ebSBram Moolenaar colnr_T startcol = 0, endcol = MAXCOL;
12344aea03ebSBram Moolenaar int is_oneChar = FALSE;
12354aea03ebSBram Moolenaar colnr_T cs, ce;
12364aea03ebSBram Moolenaar
12374aea03ebSBram Moolenaar p = ml_get(lnum);
12384aea03ebSBram Moolenaar bd.startspaces = 0;
12394aea03ebSBram Moolenaar bd.endspaces = 0;
12404aea03ebSBram Moolenaar
12414aea03ebSBram Moolenaar if (lnum == oap->start.lnum)
12424aea03ebSBram Moolenaar {
12434aea03ebSBram Moolenaar startcol = oap->start.col;
12444aea03ebSBram Moolenaar if (virtual_op)
12454aea03ebSBram Moolenaar {
12464aea03ebSBram Moolenaar getvcol(curwin, &oap->start, &cs, NULL, &ce);
12474aea03ebSBram Moolenaar if (ce != cs && oap->start.coladd > 0)
12484aea03ebSBram Moolenaar {
12494aea03ebSBram Moolenaar // Part of a tab selected -- but don't
12504aea03ebSBram Moolenaar // double-count it.
12514aea03ebSBram Moolenaar bd.startspaces = (ce - cs + 1)
12524aea03ebSBram Moolenaar - oap->start.coladd;
12534aea03ebSBram Moolenaar startcol++;
12544aea03ebSBram Moolenaar }
12554aea03ebSBram Moolenaar }
12564aea03ebSBram Moolenaar }
12574aea03ebSBram Moolenaar
12584aea03ebSBram Moolenaar if (lnum == oap->end.lnum)
12594aea03ebSBram Moolenaar {
12604aea03ebSBram Moolenaar endcol = oap->end.col;
12614aea03ebSBram Moolenaar if (virtual_op)
12624aea03ebSBram Moolenaar {
12634aea03ebSBram Moolenaar getvcol(curwin, &oap->end, &cs, NULL, &ce);
12644aea03ebSBram Moolenaar if (p[endcol] == NUL || (cs + oap->end.coladd < ce
12654aea03ebSBram Moolenaar // Don't add space for double-wide
12664aea03ebSBram Moolenaar // char; endcol will be on last byte
12674aea03ebSBram Moolenaar // of multi-byte char.
12684aea03ebSBram Moolenaar && (*mb_head_off)(p, p + endcol) == 0))
12694aea03ebSBram Moolenaar {
12704aea03ebSBram Moolenaar if (oap->start.lnum == oap->end.lnum
12714aea03ebSBram Moolenaar && oap->start.col == oap->end.col)
12724aea03ebSBram Moolenaar {
12734aea03ebSBram Moolenaar // Special case: inside a single char
12744aea03ebSBram Moolenaar is_oneChar = TRUE;
12754aea03ebSBram Moolenaar bd.startspaces = oap->end.coladd
12764aea03ebSBram Moolenaar - oap->start.coladd + oap->inclusive;
12774aea03ebSBram Moolenaar endcol = startcol;
12784aea03ebSBram Moolenaar }
12794aea03ebSBram Moolenaar else
12804aea03ebSBram Moolenaar {
12814aea03ebSBram Moolenaar bd.endspaces = oap->end.coladd
12824aea03ebSBram Moolenaar + oap->inclusive;
12834aea03ebSBram Moolenaar endcol -= oap->inclusive;
12844aea03ebSBram Moolenaar }
12854aea03ebSBram Moolenaar }
12864aea03ebSBram Moolenaar }
12874aea03ebSBram Moolenaar }
12884aea03ebSBram Moolenaar if (endcol == MAXCOL)
12894aea03ebSBram Moolenaar endcol = (colnr_T)STRLEN(p);
12904aea03ebSBram Moolenaar if (startcol > endcol || is_oneChar)
12914aea03ebSBram Moolenaar bd.textlen = 0;
12924aea03ebSBram Moolenaar else
12934aea03ebSBram Moolenaar bd.textlen = endcol - startcol + oap->inclusive;
12944aea03ebSBram Moolenaar bd.textstart = p + startcol;
1295544a38e4SChristian Brabandt if (yank_copy_line(&bd, y_idx, FALSE) == FAIL)
12964aea03ebSBram Moolenaar goto fail;
12974aea03ebSBram Moolenaar break;
12984aea03ebSBram Moolenaar }
12994aea03ebSBram Moolenaar // NOTREACHED
13004aea03ebSBram Moolenaar }
13014aea03ebSBram Moolenaar }
13024aea03ebSBram Moolenaar
13034aea03ebSBram Moolenaar if (curr != y_current) // append the new block to the old block
13044aea03ebSBram Moolenaar {
13054aea03ebSBram Moolenaar new_ptr = ALLOC_MULT(char_u *, curr->y_size + y_current->y_size);
13064aea03ebSBram Moolenaar if (new_ptr == NULL)
13074aea03ebSBram Moolenaar goto fail;
13084aea03ebSBram Moolenaar for (j = 0; j < curr->y_size; ++j)
13094aea03ebSBram Moolenaar new_ptr[j] = curr->y_array[j];
13104aea03ebSBram Moolenaar vim_free(curr->y_array);
13114aea03ebSBram Moolenaar curr->y_array = new_ptr;
13124aea03ebSBram Moolenaar #ifdef FEAT_VIMINFO
13134aea03ebSBram Moolenaar curr->y_time_set = vim_time();
13144aea03ebSBram Moolenaar #endif
13154aea03ebSBram Moolenaar
13164aea03ebSBram Moolenaar if (yanktype == MLINE) // MLINE overrides MCHAR and MBLOCK
13174aea03ebSBram Moolenaar curr->y_type = MLINE;
13184aea03ebSBram Moolenaar
13194aea03ebSBram Moolenaar // Concatenate the last line of the old block with the first line of
13204aea03ebSBram Moolenaar // the new block, unless being Vi compatible.
13214aea03ebSBram Moolenaar if (curr->y_type == MCHAR && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL)
13224aea03ebSBram Moolenaar {
13234aea03ebSBram Moolenaar pnew = alloc(STRLEN(curr->y_array[curr->y_size - 1])
13244aea03ebSBram Moolenaar + STRLEN(y_current->y_array[0]) + 1);
13254aea03ebSBram Moolenaar if (pnew == NULL)
13264aea03ebSBram Moolenaar {
13274aea03ebSBram Moolenaar y_idx = y_current->y_size - 1;
13284aea03ebSBram Moolenaar goto fail;
13294aea03ebSBram Moolenaar }
13304aea03ebSBram Moolenaar STRCPY(pnew, curr->y_array[--j]);
13314aea03ebSBram Moolenaar STRCAT(pnew, y_current->y_array[0]);
13324aea03ebSBram Moolenaar vim_free(curr->y_array[j]);
13334aea03ebSBram Moolenaar vim_free(y_current->y_array[0]);
13344aea03ebSBram Moolenaar curr->y_array[j++] = pnew;
13354aea03ebSBram Moolenaar y_idx = 1;
13364aea03ebSBram Moolenaar }
13374aea03ebSBram Moolenaar else
13384aea03ebSBram Moolenaar y_idx = 0;
13394aea03ebSBram Moolenaar while (y_idx < y_current->y_size)
13404aea03ebSBram Moolenaar curr->y_array[j++] = y_current->y_array[y_idx++];
13414aea03ebSBram Moolenaar curr->y_size = j;
13424aea03ebSBram Moolenaar vim_free(y_current->y_array);
13434aea03ebSBram Moolenaar y_current = curr;
13444aea03ebSBram Moolenaar }
13454aea03ebSBram Moolenaar if (curwin->w_p_rnu)
13464aea03ebSBram Moolenaar redraw_later(SOME_VALID); // cursor moved to start
13474aea03ebSBram Moolenaar if (mess) // Display message about yank?
13484aea03ebSBram Moolenaar {
13494aea03ebSBram Moolenaar if (yanktype == MCHAR
13504aea03ebSBram Moolenaar && !oap->block_mode
13514aea03ebSBram Moolenaar && yanklines == 1)
13524aea03ebSBram Moolenaar yanklines = 0;
13534aea03ebSBram Moolenaar // Some versions of Vi use ">=" here, some don't...
13544aea03ebSBram Moolenaar if (yanklines > p_report)
13554aea03ebSBram Moolenaar {
13564aea03ebSBram Moolenaar char namebuf[100];
13574aea03ebSBram Moolenaar
13584aea03ebSBram Moolenaar if (oap->regname == NUL)
13594aea03ebSBram Moolenaar *namebuf = NUL;
13604aea03ebSBram Moolenaar else
13614aea03ebSBram Moolenaar vim_snprintf(namebuf, sizeof(namebuf),
13624aea03ebSBram Moolenaar _(" into \"%c"), oap->regname);
13634aea03ebSBram Moolenaar
13644aea03ebSBram Moolenaar // redisplay now, so message is not deleted
13654aea03ebSBram Moolenaar update_topline_redraw();
13664aea03ebSBram Moolenaar if (oap->block_mode)
13674aea03ebSBram Moolenaar {
13684aea03ebSBram Moolenaar smsg(NGETTEXT("block of %ld line yanked%s",
13694aea03ebSBram Moolenaar "block of %ld lines yanked%s", yanklines),
13704aea03ebSBram Moolenaar yanklines, namebuf);
13714aea03ebSBram Moolenaar }
13724aea03ebSBram Moolenaar else
13734aea03ebSBram Moolenaar {
13744aea03ebSBram Moolenaar smsg(NGETTEXT("%ld line yanked%s",
13754aea03ebSBram Moolenaar "%ld lines yanked%s", yanklines),
13764aea03ebSBram Moolenaar yanklines, namebuf);
13774aea03ebSBram Moolenaar }
13784aea03ebSBram Moolenaar }
13794aea03ebSBram Moolenaar }
13804aea03ebSBram Moolenaar
1381e1004401SBram Moolenaar if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
1382f4a1d1c0SBram Moolenaar {
13834aea03ebSBram Moolenaar // Set "'[" and "']" marks.
13844aea03ebSBram Moolenaar curbuf->b_op_start = oap->start;
13854aea03ebSBram Moolenaar curbuf->b_op_end = oap->end;
13864aea03ebSBram Moolenaar if (yanktype == MLINE && !oap->block_mode)
13874aea03ebSBram Moolenaar {
13884aea03ebSBram Moolenaar curbuf->b_op_start.col = 0;
13894aea03ebSBram Moolenaar curbuf->b_op_end.col = MAXCOL;
13904aea03ebSBram Moolenaar }
1391f4a1d1c0SBram Moolenaar }
13924aea03ebSBram Moolenaar
13934aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
13944aea03ebSBram Moolenaar // If we were yanking to the '*' register, send result to clipboard.
13954aea03ebSBram Moolenaar // If no register was specified, and "unnamed" in 'clipboard', make a copy
13964aea03ebSBram Moolenaar // to the '*' register.
13974aea03ebSBram Moolenaar if (clip_star.available
13984aea03ebSBram Moolenaar && (curr == &(y_regs[STAR_REGISTER])
13994aea03ebSBram Moolenaar || (!deleting && oap->regname == 0
14004aea03ebSBram Moolenaar && ((clip_unnamed | clip_unnamed_saved) & CLIP_UNNAMED))))
14014aea03ebSBram Moolenaar {
14024aea03ebSBram Moolenaar if (curr != &(y_regs[STAR_REGISTER]))
14034aea03ebSBram Moolenaar // Copy the text from register 0 to the clipboard register.
14044aea03ebSBram Moolenaar copy_yank_reg(&(y_regs[STAR_REGISTER]));
14054aea03ebSBram Moolenaar
14064aea03ebSBram Moolenaar clip_own_selection(&clip_star);
14074aea03ebSBram Moolenaar clip_gen_set_selection(&clip_star);
14084aea03ebSBram Moolenaar # ifdef FEAT_X11
14094aea03ebSBram Moolenaar did_star = TRUE;
14104aea03ebSBram Moolenaar # endif
14114aea03ebSBram Moolenaar }
14124aea03ebSBram Moolenaar
14134aea03ebSBram Moolenaar # ifdef FEAT_X11
14144aea03ebSBram Moolenaar // If we were yanking to the '+' register, send result to selection.
141537096afdSBram Moolenaar // Also copy to the '*' register, in case auto-select is off. But not when
141637096afdSBram Moolenaar // 'clipboard' has "unnamedplus" and not "unnamed".
14174aea03ebSBram Moolenaar if (clip_plus.available
14184aea03ebSBram Moolenaar && (curr == &(y_regs[PLUS_REGISTER])
14194aea03ebSBram Moolenaar || (!deleting && oap->regname == 0
14204aea03ebSBram Moolenaar && ((clip_unnamed | clip_unnamed_saved) &
14214aea03ebSBram Moolenaar CLIP_UNNAMED_PLUS))))
14224aea03ebSBram Moolenaar {
14234aea03ebSBram Moolenaar if (curr != &(y_regs[PLUS_REGISTER]))
14244aea03ebSBram Moolenaar // Copy the text from register 0 to the clipboard register.
14254aea03ebSBram Moolenaar copy_yank_reg(&(y_regs[PLUS_REGISTER]));
14264aea03ebSBram Moolenaar
14274aea03ebSBram Moolenaar clip_own_selection(&clip_plus);
14284aea03ebSBram Moolenaar clip_gen_set_selection(&clip_plus);
142937096afdSBram Moolenaar if (!clip_isautosel_star()
143037096afdSBram Moolenaar && !clip_isautosel_plus()
143137096afdSBram Moolenaar && !((clip_unnamed | clip_unnamed_saved) == CLIP_UNNAMED_PLUS)
143237096afdSBram Moolenaar && !did_star
143337096afdSBram Moolenaar && curr == &(y_regs[PLUS_REGISTER]))
14344aea03ebSBram Moolenaar {
14354aea03ebSBram Moolenaar copy_yank_reg(&(y_regs[STAR_REGISTER]));
14364aea03ebSBram Moolenaar clip_own_selection(&clip_star);
14374aea03ebSBram Moolenaar clip_gen_set_selection(&clip_star);
14384aea03ebSBram Moolenaar }
14394aea03ebSBram Moolenaar }
14404aea03ebSBram Moolenaar # endif
14414aea03ebSBram Moolenaar #endif
14424aea03ebSBram Moolenaar
14434aea03ebSBram Moolenaar #if defined(FEAT_EVAL)
14444aea03ebSBram Moolenaar if (!deleting && has_textyankpost())
14454aea03ebSBram Moolenaar yank_do_autocmd(oap, y_current);
14464aea03ebSBram Moolenaar #endif
14474aea03ebSBram Moolenaar
14484aea03ebSBram Moolenaar return OK;
14494aea03ebSBram Moolenaar
14504aea03ebSBram Moolenaar fail: // free the allocated lines
14514aea03ebSBram Moolenaar free_yank(y_idx + 1);
14524aea03ebSBram Moolenaar y_current = curr;
14534aea03ebSBram Moolenaar return FAIL;
14544aea03ebSBram Moolenaar }
14554aea03ebSBram Moolenaar
1456544a38e4SChristian Brabandt /*
1457544a38e4SChristian Brabandt * Copy a block range into a register.
1458544a38e4SChristian Brabandt * If "exclude_trailing_space" is set, do not copy trailing whitespaces.
1459544a38e4SChristian Brabandt */
14604aea03ebSBram Moolenaar static int
yank_copy_line(struct block_def * bd,long y_idx,int exclude_trailing_space)1461544a38e4SChristian Brabandt yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space)
14624aea03ebSBram Moolenaar {
14634aea03ebSBram Moolenaar char_u *pnew;
14644aea03ebSBram Moolenaar
14657d7bcc6bSBram Moolenaar if (exclude_trailing_space)
14667d7bcc6bSBram Moolenaar bd->endspaces = 0;
14674aea03ebSBram Moolenaar if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1))
14684aea03ebSBram Moolenaar == NULL)
14694aea03ebSBram Moolenaar return FAIL;
14704aea03ebSBram Moolenaar y_current->y_array[y_idx] = pnew;
14714aea03ebSBram Moolenaar vim_memset(pnew, ' ', (size_t)bd->startspaces);
14724aea03ebSBram Moolenaar pnew += bd->startspaces;
14734aea03ebSBram Moolenaar mch_memmove(pnew, bd->textstart, (size_t)bd->textlen);
14744aea03ebSBram Moolenaar pnew += bd->textlen;
14754aea03ebSBram Moolenaar vim_memset(pnew, ' ', (size_t)bd->endspaces);
14764aea03ebSBram Moolenaar pnew += bd->endspaces;
1477544a38e4SChristian Brabandt if (exclude_trailing_space)
1478544a38e4SChristian Brabandt {
1479544a38e4SChristian Brabandt int s = bd->textlen + bd->endspaces;
1480544a38e4SChristian Brabandt
1481544a38e4SChristian Brabandt while (VIM_ISWHITE(*(bd->textstart + s - 1)) && s > 0)
1482544a38e4SChristian Brabandt {
1483544a38e4SChristian Brabandt s = s - (*mb_head_off)(bd->textstart, bd->textstart + s - 1) - 1;
1484544a38e4SChristian Brabandt pnew--;
1485544a38e4SChristian Brabandt }
1486544a38e4SChristian Brabandt }
14874aea03ebSBram Moolenaar *pnew = NUL;
14884aea03ebSBram Moolenaar return OK;
14894aea03ebSBram Moolenaar }
14904aea03ebSBram Moolenaar
14914aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
14924aea03ebSBram Moolenaar /*
14934aea03ebSBram Moolenaar * Make a copy of the y_current register to register "reg".
14944aea03ebSBram Moolenaar */
14954aea03ebSBram Moolenaar static void
copy_yank_reg(yankreg_T * reg)14964aea03ebSBram Moolenaar copy_yank_reg(yankreg_T *reg)
14974aea03ebSBram Moolenaar {
14984aea03ebSBram Moolenaar yankreg_T *curr = y_current;
14994aea03ebSBram Moolenaar long j;
15004aea03ebSBram Moolenaar
15014aea03ebSBram Moolenaar y_current = reg;
15024aea03ebSBram Moolenaar free_yank_all();
15034aea03ebSBram Moolenaar *y_current = *curr;
15044aea03ebSBram Moolenaar y_current->y_array = lalloc_clear(
15054aea03ebSBram Moolenaar sizeof(char_u *) * y_current->y_size, TRUE);
15064aea03ebSBram Moolenaar if (y_current->y_array == NULL)
15074aea03ebSBram Moolenaar y_current->y_size = 0;
15084aea03ebSBram Moolenaar else
15094aea03ebSBram Moolenaar for (j = 0; j < y_current->y_size; ++j)
15104aea03ebSBram Moolenaar if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL)
15114aea03ebSBram Moolenaar {
15124aea03ebSBram Moolenaar free_yank(j);
15134aea03ebSBram Moolenaar y_current->y_size = 0;
15144aea03ebSBram Moolenaar break;
15154aea03ebSBram Moolenaar }
15164aea03ebSBram Moolenaar y_current = curr;
15174aea03ebSBram Moolenaar }
15184aea03ebSBram Moolenaar #endif
15194aea03ebSBram Moolenaar
15204aea03ebSBram Moolenaar /*
15214aea03ebSBram Moolenaar * Put contents of register "regname" into the text.
15224aea03ebSBram Moolenaar * Caller must check "regname" to be valid!
15234aea03ebSBram Moolenaar * "flags": PUT_FIXINDENT make indent look nice
15244aea03ebSBram Moolenaar * PUT_CURSEND leave cursor after end of new text
15254aea03ebSBram Moolenaar * PUT_LINE force linewise put (":put")
15262fa9384cSChristian Brabandt * PUT_BLOCK_INNER in block mode, do not add trailing spaces
15274aea03ebSBram Moolenaar */
15284aea03ebSBram Moolenaar void
do_put(int regname,char_u * expr_result,int dir,long count,int flags)15294aea03ebSBram Moolenaar do_put(
15304aea03ebSBram Moolenaar int regname,
1531c3516f7eSBram Moolenaar char_u *expr_result, // result for regname "=" when compiled
15324aea03ebSBram Moolenaar int dir, // BACKWARD for 'P', FORWARD for 'p'
15334aea03ebSBram Moolenaar long count,
15344aea03ebSBram Moolenaar int flags)
15354aea03ebSBram Moolenaar {
15364aea03ebSBram Moolenaar char_u *ptr;
15374aea03ebSBram Moolenaar char_u *newp, *oldp;
15384aea03ebSBram Moolenaar int yanklen;
15394aea03ebSBram Moolenaar int totlen = 0; // init for gcc
15404aea03ebSBram Moolenaar linenr_T lnum;
15414aea03ebSBram Moolenaar colnr_T col;
15424aea03ebSBram Moolenaar long i; // index in y_array[]
15434aea03ebSBram Moolenaar int y_type;
15444aea03ebSBram Moolenaar long y_size;
15454aea03ebSBram Moolenaar int oldlen;
15464aea03ebSBram Moolenaar long y_width = 0;
15474aea03ebSBram Moolenaar colnr_T vcol;
15484aea03ebSBram Moolenaar int delcount;
15494aea03ebSBram Moolenaar int incr = 0;
15504aea03ebSBram Moolenaar long j;
15514aea03ebSBram Moolenaar struct block_def bd;
15524aea03ebSBram Moolenaar char_u **y_array = NULL;
15534aea03ebSBram Moolenaar long nr_lines = 0;
15544aea03ebSBram Moolenaar pos_T new_cursor;
15554aea03ebSBram Moolenaar int indent;
15564aea03ebSBram Moolenaar int orig_indent = 0; // init for gcc
15574aea03ebSBram Moolenaar int indent_diff = 0; // init for gcc
15584aea03ebSBram Moolenaar int first_indent = TRUE;
15594aea03ebSBram Moolenaar int lendiff = 0;
15604aea03ebSBram Moolenaar pos_T old_pos;
15614aea03ebSBram Moolenaar char_u *insert_string = NULL;
15624aea03ebSBram Moolenaar int allocated = FALSE;
15634aea03ebSBram Moolenaar long cnt;
1564f4a1d1c0SBram Moolenaar pos_T orig_start = curbuf->b_op_start;
1565f4a1d1c0SBram Moolenaar pos_T orig_end = curbuf->b_op_end;
156653ba05b0SGary Johnson unsigned int cur_ve_flags = get_ve_flags();
15674aea03ebSBram Moolenaar
15684aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
15694aea03ebSBram Moolenaar // Adjust register name for "unnamed" in 'clipboard'.
15704aea03ebSBram Moolenaar adjust_clip_reg(®name);
15714aea03ebSBram Moolenaar (void)may_get_selection(regname);
15724aea03ebSBram Moolenaar #endif
15734aea03ebSBram Moolenaar
15744aea03ebSBram Moolenaar if (flags & PUT_FIXINDENT)
15754aea03ebSBram Moolenaar orig_indent = get_indent();
15764aea03ebSBram Moolenaar
15774aea03ebSBram Moolenaar curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
15784aea03ebSBram Moolenaar curbuf->b_op_end = curwin->w_cursor; // default for '] mark
15794aea03ebSBram Moolenaar
15804aea03ebSBram Moolenaar // Using inserted text works differently, because the register includes
15814aea03ebSBram Moolenaar // special characters (newlines, etc.).
15824aea03ebSBram Moolenaar if (regname == '.')
15834aea03ebSBram Moolenaar {
15844aea03ebSBram Moolenaar if (VIsual_active)
15854aea03ebSBram Moolenaar stuffcharReadbuff(VIsual_mode);
15864aea03ebSBram Moolenaar (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
15874aea03ebSBram Moolenaar (count == -1 ? 'O' : 'i')), count, FALSE);
15884aea03ebSBram Moolenaar // Putting the text is done later, so can't really move the cursor to
15894aea03ebSBram Moolenaar // the next character. Use "l" to simulate it.
15904aea03ebSBram Moolenaar if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
15914aea03ebSBram Moolenaar stuffcharReadbuff('l');
15924aea03ebSBram Moolenaar return;
15934aea03ebSBram Moolenaar }
15944aea03ebSBram Moolenaar
15954aea03ebSBram Moolenaar // For special registers '%' (file name), '#' (alternate file name) and
15964aea03ebSBram Moolenaar // ':' (last command line), etc. we have to create a fake yank register.
1597c3516f7eSBram Moolenaar // For compiled code "expr_result" holds the expression result.
1598c3516f7eSBram Moolenaar if (regname == '=' && expr_result != NULL)
1599c3516f7eSBram Moolenaar insert_string = expr_result;
1600c3516f7eSBram Moolenaar else if (get_spec_reg(regname, &insert_string, &allocated, TRUE)
1601c3516f7eSBram Moolenaar && insert_string == NULL)
16024aea03ebSBram Moolenaar return;
16034aea03ebSBram Moolenaar
16044aea03ebSBram Moolenaar // Autocommands may be executed when saving lines for undo. This might
16054aea03ebSBram Moolenaar // make "y_array" invalid, so we start undo now to avoid that.
16064aea03ebSBram Moolenaar if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL)
16074aea03ebSBram Moolenaar goto end;
16084aea03ebSBram Moolenaar
16094aea03ebSBram Moolenaar if (insert_string != NULL)
16104aea03ebSBram Moolenaar {
16114aea03ebSBram Moolenaar y_type = MCHAR;
16124aea03ebSBram Moolenaar #ifdef FEAT_EVAL
16134aea03ebSBram Moolenaar if (regname == '=')
16144aea03ebSBram Moolenaar {
16154aea03ebSBram Moolenaar // For the = register we need to split the string at NL
16164aea03ebSBram Moolenaar // characters.
16174aea03ebSBram Moolenaar // Loop twice: count the number of lines and save them.
16184aea03ebSBram Moolenaar for (;;)
16194aea03ebSBram Moolenaar {
16204aea03ebSBram Moolenaar y_size = 0;
16214aea03ebSBram Moolenaar ptr = insert_string;
16224aea03ebSBram Moolenaar while (ptr != NULL)
16234aea03ebSBram Moolenaar {
16244aea03ebSBram Moolenaar if (y_array != NULL)
16254aea03ebSBram Moolenaar y_array[y_size] = ptr;
16264aea03ebSBram Moolenaar ++y_size;
16274aea03ebSBram Moolenaar ptr = vim_strchr(ptr, '\n');
16284aea03ebSBram Moolenaar if (ptr != NULL)
16294aea03ebSBram Moolenaar {
16304aea03ebSBram Moolenaar if (y_array != NULL)
16314aea03ebSBram Moolenaar *ptr = NUL;
16324aea03ebSBram Moolenaar ++ptr;
16334aea03ebSBram Moolenaar // A trailing '\n' makes the register linewise.
16344aea03ebSBram Moolenaar if (*ptr == NUL)
16354aea03ebSBram Moolenaar {
16364aea03ebSBram Moolenaar y_type = MLINE;
16374aea03ebSBram Moolenaar break;
16384aea03ebSBram Moolenaar }
16394aea03ebSBram Moolenaar }
16404aea03ebSBram Moolenaar }
16414aea03ebSBram Moolenaar if (y_array != NULL)
16424aea03ebSBram Moolenaar break;
16434aea03ebSBram Moolenaar y_array = ALLOC_MULT(char_u *, y_size);
16444aea03ebSBram Moolenaar if (y_array == NULL)
16454aea03ebSBram Moolenaar goto end;
16464aea03ebSBram Moolenaar }
16474aea03ebSBram Moolenaar }
16484aea03ebSBram Moolenaar else
16494aea03ebSBram Moolenaar #endif
16504aea03ebSBram Moolenaar {
16514aea03ebSBram Moolenaar y_size = 1; // use fake one-line yank register
16524aea03ebSBram Moolenaar y_array = &insert_string;
16534aea03ebSBram Moolenaar }
16544aea03ebSBram Moolenaar }
16554aea03ebSBram Moolenaar else
16564aea03ebSBram Moolenaar {
16574aea03ebSBram Moolenaar get_yank_register(regname, FALSE);
16584aea03ebSBram Moolenaar
16594aea03ebSBram Moolenaar y_type = y_current->y_type;
16604aea03ebSBram Moolenaar y_width = y_current->y_width;
16614aea03ebSBram Moolenaar y_size = y_current->y_size;
16624aea03ebSBram Moolenaar y_array = y_current->y_array;
16634aea03ebSBram Moolenaar }
16644aea03ebSBram Moolenaar
16654aea03ebSBram Moolenaar if (y_type == MLINE)
16664aea03ebSBram Moolenaar {
16674aea03ebSBram Moolenaar if (flags & PUT_LINE_SPLIT)
16684aea03ebSBram Moolenaar {
16694aea03ebSBram Moolenaar char_u *p;
16704aea03ebSBram Moolenaar
16714aea03ebSBram Moolenaar // "p" or "P" in Visual mode: split the lines to put the text in
16724aea03ebSBram Moolenaar // between.
16734aea03ebSBram Moolenaar if (u_save_cursor() == FAIL)
16744aea03ebSBram Moolenaar goto end;
16754aea03ebSBram Moolenaar p = ml_get_cursor();
16764aea03ebSBram Moolenaar if (dir == FORWARD && *p != NUL)
16774aea03ebSBram Moolenaar MB_PTR_ADV(p);
16784aea03ebSBram Moolenaar ptr = vim_strsave(p);
16794aea03ebSBram Moolenaar if (ptr == NULL)
16804aea03ebSBram Moolenaar goto end;
16814aea03ebSBram Moolenaar ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE);
16824aea03ebSBram Moolenaar vim_free(ptr);
16834aea03ebSBram Moolenaar
16844aea03ebSBram Moolenaar oldp = ml_get_curline();
16854aea03ebSBram Moolenaar p = oldp + curwin->w_cursor.col;
16864aea03ebSBram Moolenaar if (dir == FORWARD && *p != NUL)
16874aea03ebSBram Moolenaar MB_PTR_ADV(p);
16884aea03ebSBram Moolenaar ptr = vim_strnsave(oldp, p - oldp);
16894aea03ebSBram Moolenaar if (ptr == NULL)
16904aea03ebSBram Moolenaar goto end;
16914aea03ebSBram Moolenaar ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
16924aea03ebSBram Moolenaar ++nr_lines;
16934aea03ebSBram Moolenaar dir = FORWARD;
16944aea03ebSBram Moolenaar }
16954aea03ebSBram Moolenaar if (flags & PUT_LINE_FORWARD)
16964aea03ebSBram Moolenaar {
16974aea03ebSBram Moolenaar // Must be "p" for a Visual block, put lines below the block.
16984aea03ebSBram Moolenaar curwin->w_cursor = curbuf->b_visual.vi_end;
16994aea03ebSBram Moolenaar dir = FORWARD;
17004aea03ebSBram Moolenaar }
17014aea03ebSBram Moolenaar curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
17024aea03ebSBram Moolenaar curbuf->b_op_end = curwin->w_cursor; // default for '] mark
17034aea03ebSBram Moolenaar }
17044aea03ebSBram Moolenaar
17054aea03ebSBram Moolenaar if (flags & PUT_LINE) // :put command or "p" in Visual line mode.
17064aea03ebSBram Moolenaar y_type = MLINE;
17074aea03ebSBram Moolenaar
17084aea03ebSBram Moolenaar if (y_size == 0 || y_array == NULL)
17094aea03ebSBram Moolenaar {
17104aea03ebSBram Moolenaar semsg(_("E353: Nothing in register %s"),
17114aea03ebSBram Moolenaar regname == 0 ? (char_u *)"\"" : transchar(regname));
17124aea03ebSBram Moolenaar goto end;
17134aea03ebSBram Moolenaar }
17144aea03ebSBram Moolenaar
17154aea03ebSBram Moolenaar if (y_type == MBLOCK)
17164aea03ebSBram Moolenaar {
17174aea03ebSBram Moolenaar lnum = curwin->w_cursor.lnum + y_size + 1;
17184aea03ebSBram Moolenaar if (lnum > curbuf->b_ml.ml_line_count)
17194aea03ebSBram Moolenaar lnum = curbuf->b_ml.ml_line_count + 1;
17204aea03ebSBram Moolenaar if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
17214aea03ebSBram Moolenaar goto end;
17224aea03ebSBram Moolenaar }
17234aea03ebSBram Moolenaar else if (y_type == MLINE)
17244aea03ebSBram Moolenaar {
17254aea03ebSBram Moolenaar lnum = curwin->w_cursor.lnum;
17264aea03ebSBram Moolenaar #ifdef FEAT_FOLDING
17274aea03ebSBram Moolenaar // Correct line number for closed fold. Don't move the cursor yet,
17284aea03ebSBram Moolenaar // u_save() uses it.
17294aea03ebSBram Moolenaar if (dir == BACKWARD)
17304aea03ebSBram Moolenaar (void)hasFolding(lnum, &lnum, NULL);
17314aea03ebSBram Moolenaar else
17324aea03ebSBram Moolenaar (void)hasFolding(lnum, NULL, &lnum);
17334aea03ebSBram Moolenaar #endif
17344aea03ebSBram Moolenaar if (dir == FORWARD)
17354aea03ebSBram Moolenaar ++lnum;
17364aea03ebSBram Moolenaar // In an empty buffer the empty line is going to be replaced, include
17374aea03ebSBram Moolenaar // it in the saved lines.
17384aea03ebSBram Moolenaar if ((BUFEMPTY() ? u_save(0, 2) : u_save(lnum - 1, lnum)) == FAIL)
17394aea03ebSBram Moolenaar goto end;
17404aea03ebSBram Moolenaar #ifdef FEAT_FOLDING
17414aea03ebSBram Moolenaar if (dir == FORWARD)
17424aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum - 1;
17434aea03ebSBram Moolenaar else
17444aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum;
17454aea03ebSBram Moolenaar curbuf->b_op_start = curwin->w_cursor; // for mark_adjust()
17464aea03ebSBram Moolenaar #endif
17474aea03ebSBram Moolenaar }
17484aea03ebSBram Moolenaar else if (u_save_cursor() == FAIL)
17494aea03ebSBram Moolenaar goto end;
17504aea03ebSBram Moolenaar
17514aea03ebSBram Moolenaar yanklen = (int)STRLEN(y_array[0]);
17524aea03ebSBram Moolenaar
175353ba05b0SGary Johnson if (cur_ve_flags == VE_ALL && y_type == MCHAR)
17544aea03ebSBram Moolenaar {
17554aea03ebSBram Moolenaar if (gchar_cursor() == TAB)
17564aea03ebSBram Moolenaar {
17576f1f0ca3SBram Moolenaar int viscol = getviscol();
17586f1f0ca3SBram Moolenaar int ts = curbuf->b_p_ts;
17596f1f0ca3SBram Moolenaar
17604aea03ebSBram Moolenaar // Don't need to insert spaces when "p" on the last position of a
17614aea03ebSBram Moolenaar // tab or "P" on the first position.
17626f1f0ca3SBram Moolenaar if (dir == FORWARD ?
17634aea03ebSBram Moolenaar #ifdef FEAT_VARTABS
17646f1f0ca3SBram Moolenaar tabstop_padding(viscol, ts, curbuf->b_p_vts_array) != 1
17656f1f0ca3SBram Moolenaar #else
17666f1f0ca3SBram Moolenaar ts - (viscol % ts) != 1
17676f1f0ca3SBram Moolenaar #endif
17684aea03ebSBram Moolenaar : curwin->w_cursor.coladd > 0)
17694aea03ebSBram Moolenaar coladvance_force(viscol);
17704aea03ebSBram Moolenaar else
17714aea03ebSBram Moolenaar curwin->w_cursor.coladd = 0;
17724aea03ebSBram Moolenaar }
17734aea03ebSBram Moolenaar else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL)
17744aea03ebSBram Moolenaar coladvance_force(getviscol() + (dir == FORWARD));
17754aea03ebSBram Moolenaar }
17764aea03ebSBram Moolenaar
17774aea03ebSBram Moolenaar lnum = curwin->w_cursor.lnum;
17784aea03ebSBram Moolenaar col = curwin->w_cursor.col;
17794aea03ebSBram Moolenaar
17804aea03ebSBram Moolenaar // Block mode
17814aea03ebSBram Moolenaar if (y_type == MBLOCK)
17824aea03ebSBram Moolenaar {
17834aea03ebSBram Moolenaar int c = gchar_cursor();
17844aea03ebSBram Moolenaar colnr_T endcol2 = 0;
17854aea03ebSBram Moolenaar
17864aea03ebSBram Moolenaar if (dir == FORWARD && c != NUL)
17874aea03ebSBram Moolenaar {
178853ba05b0SGary Johnson if (cur_ve_flags == VE_ALL)
17894aea03ebSBram Moolenaar getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
17904aea03ebSBram Moolenaar else
17914aea03ebSBram Moolenaar getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
17924aea03ebSBram Moolenaar
17934aea03ebSBram Moolenaar if (has_mbyte)
17944aea03ebSBram Moolenaar // move to start of next multi-byte character
17954aea03ebSBram Moolenaar curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor());
17964aea03ebSBram Moolenaar else
179753ba05b0SGary Johnson if (c != TAB || cur_ve_flags != VE_ALL)
17984aea03ebSBram Moolenaar ++curwin->w_cursor.col;
17994aea03ebSBram Moolenaar ++col;
18004aea03ebSBram Moolenaar }
18014aea03ebSBram Moolenaar else
18024aea03ebSBram Moolenaar getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
18034aea03ebSBram Moolenaar
18044aea03ebSBram Moolenaar col += curwin->w_cursor.coladd;
180553ba05b0SGary Johnson if (cur_ve_flags == VE_ALL
18064aea03ebSBram Moolenaar && (curwin->w_cursor.coladd > 0
18074aea03ebSBram Moolenaar || endcol2 == curwin->w_cursor.col))
18084aea03ebSBram Moolenaar {
18094aea03ebSBram Moolenaar if (dir == FORWARD && c == NUL)
18104aea03ebSBram Moolenaar ++col;
1811ef85a9b2SBram Moolenaar if (dir != FORWARD && c != NUL && curwin->w_cursor.coladd > 0)
18124aea03ebSBram Moolenaar ++curwin->w_cursor.col;
18134aea03ebSBram Moolenaar if (c == TAB)
18144aea03ebSBram Moolenaar {
18154aea03ebSBram Moolenaar if (dir == BACKWARD && curwin->w_cursor.col)
18164aea03ebSBram Moolenaar curwin->w_cursor.col--;
18174aea03ebSBram Moolenaar if (dir == FORWARD && col - 1 == endcol2)
18184aea03ebSBram Moolenaar curwin->w_cursor.col++;
18194aea03ebSBram Moolenaar }
18204aea03ebSBram Moolenaar }
18214aea03ebSBram Moolenaar curwin->w_cursor.coladd = 0;
18224aea03ebSBram Moolenaar bd.textcol = 0;
18234aea03ebSBram Moolenaar for (i = 0; i < y_size; ++i)
18244aea03ebSBram Moolenaar {
18252fa9384cSChristian Brabandt int spaces = 0;
18264aea03ebSBram Moolenaar char shortline;
18274aea03ebSBram Moolenaar
18284aea03ebSBram Moolenaar bd.startspaces = 0;
18294aea03ebSBram Moolenaar bd.endspaces = 0;
18304aea03ebSBram Moolenaar vcol = 0;
18314aea03ebSBram Moolenaar delcount = 0;
18324aea03ebSBram Moolenaar
18334aea03ebSBram Moolenaar // add a new line
18344aea03ebSBram Moolenaar if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
18354aea03ebSBram Moolenaar {
18364aea03ebSBram Moolenaar if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
18374aea03ebSBram Moolenaar (colnr_T)1, FALSE) == FAIL)
18384aea03ebSBram Moolenaar break;
18394aea03ebSBram Moolenaar ++nr_lines;
18404aea03ebSBram Moolenaar }
18414aea03ebSBram Moolenaar // get the old line and advance to the position to insert at
18424aea03ebSBram Moolenaar oldp = ml_get_curline();
18434aea03ebSBram Moolenaar oldlen = (int)STRLEN(oldp);
18444aea03ebSBram Moolenaar for (ptr = oldp; vcol < col && *ptr; )
18454aea03ebSBram Moolenaar {
18464aea03ebSBram Moolenaar // Count a tab for what it's worth (if list mode not on)
18474aea03ebSBram Moolenaar incr = lbr_chartabsize_adv(oldp, &ptr, (colnr_T)vcol);
18484aea03ebSBram Moolenaar vcol += incr;
18494aea03ebSBram Moolenaar }
18504aea03ebSBram Moolenaar bd.textcol = (colnr_T)(ptr - oldp);
18514aea03ebSBram Moolenaar
18524aea03ebSBram Moolenaar shortline = (vcol < col) || (vcol == col && !*ptr) ;
18534aea03ebSBram Moolenaar
18544aea03ebSBram Moolenaar if (vcol < col) // line too short, padd with spaces
18554aea03ebSBram Moolenaar bd.startspaces = col - vcol;
18564aea03ebSBram Moolenaar else if (vcol > col)
18574aea03ebSBram Moolenaar {
18584aea03ebSBram Moolenaar bd.endspaces = vcol - col;
18594aea03ebSBram Moolenaar bd.startspaces = incr - bd.endspaces;
18604aea03ebSBram Moolenaar --bd.textcol;
18614aea03ebSBram Moolenaar delcount = 1;
18624aea03ebSBram Moolenaar if (has_mbyte)
18634aea03ebSBram Moolenaar bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol);
18644aea03ebSBram Moolenaar if (oldp[bd.textcol] != TAB)
18654aea03ebSBram Moolenaar {
18664aea03ebSBram Moolenaar // Only a Tab can be split into spaces. Other
18674aea03ebSBram Moolenaar // characters will have to be moved to after the
18684aea03ebSBram Moolenaar // block, causing misalignment.
18694aea03ebSBram Moolenaar delcount = 0;
18704aea03ebSBram Moolenaar bd.endspaces = 0;
18714aea03ebSBram Moolenaar }
18724aea03ebSBram Moolenaar }
18734aea03ebSBram Moolenaar
18744aea03ebSBram Moolenaar yanklen = (int)STRLEN(y_array[i]);
18754aea03ebSBram Moolenaar
18762fa9384cSChristian Brabandt if ((flags & PUT_BLOCK_INNER) == 0)
18772fa9384cSChristian Brabandt {
18782fa9384cSChristian Brabandt // calculate number of spaces required to fill right side of
18792fa9384cSChristian Brabandt // block
18804aea03ebSBram Moolenaar spaces = y_width + 1;
18814aea03ebSBram Moolenaar for (j = 0; j < yanklen; j++)
18824aea03ebSBram Moolenaar spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0);
18834aea03ebSBram Moolenaar if (spaces < 0)
18844aea03ebSBram Moolenaar spaces = 0;
18852fa9384cSChristian Brabandt }
18864aea03ebSBram Moolenaar
1887fa537223Sichizok // Insert the new text.
1888fa537223Sichizok // First check for multiplication overflow.
1889fa537223Sichizok if (yanklen + spaces != 0
1890fa537223Sichizok && count > ((INT_MAX - (bd.startspaces + bd.endspaces))
1891fa537223Sichizok / (yanklen + spaces)))
1892fa537223Sichizok {
1893fa537223Sichizok emsg(_(e_resulting_text_too_long));
1894fa537223Sichizok break;
1895fa537223Sichizok }
1896fa537223Sichizok
18974aea03ebSBram Moolenaar totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
18984aea03ebSBram Moolenaar newp = alloc(totlen + oldlen + 1);
18994aea03ebSBram Moolenaar if (newp == NULL)
19004aea03ebSBram Moolenaar break;
1901fa537223Sichizok
19024aea03ebSBram Moolenaar // copy part up to cursor to new line
19034aea03ebSBram Moolenaar ptr = newp;
19044aea03ebSBram Moolenaar mch_memmove(ptr, oldp, (size_t)bd.textcol);
19054aea03ebSBram Moolenaar ptr += bd.textcol;
1906fa537223Sichizok
19074aea03ebSBram Moolenaar // may insert some spaces before the new text
19084aea03ebSBram Moolenaar vim_memset(ptr, ' ', (size_t)bd.startspaces);
19094aea03ebSBram Moolenaar ptr += bd.startspaces;
1910fa537223Sichizok
19114aea03ebSBram Moolenaar // insert the new text
19124aea03ebSBram Moolenaar for (j = 0; j < count; ++j)
19134aea03ebSBram Moolenaar {
19144aea03ebSBram Moolenaar mch_memmove(ptr, y_array[i], (size_t)yanklen);
19154aea03ebSBram Moolenaar ptr += yanklen;
19164aea03ebSBram Moolenaar
19174aea03ebSBram Moolenaar // insert block's trailing spaces only if there's text behind
19184aea03ebSBram Moolenaar if ((j < count - 1 || !shortline) && spaces)
19194aea03ebSBram Moolenaar {
19204aea03ebSBram Moolenaar vim_memset(ptr, ' ', (size_t)spaces);
19214aea03ebSBram Moolenaar ptr += spaces;
19224aea03ebSBram Moolenaar }
19234aea03ebSBram Moolenaar }
1924fa537223Sichizok
19254aea03ebSBram Moolenaar // may insert some spaces after the new text
19264aea03ebSBram Moolenaar vim_memset(ptr, ' ', (size_t)bd.endspaces);
19274aea03ebSBram Moolenaar ptr += bd.endspaces;
1928fa537223Sichizok
19294aea03ebSBram Moolenaar // move the text after the cursor to the end of the line.
19304aea03ebSBram Moolenaar mch_memmove(ptr, oldp + bd.textcol + delcount,
19314aea03ebSBram Moolenaar (size_t)(oldlen - bd.textcol - delcount + 1));
19324aea03ebSBram Moolenaar ml_replace(curwin->w_cursor.lnum, newp, FALSE);
19334aea03ebSBram Moolenaar
19344aea03ebSBram Moolenaar ++curwin->w_cursor.lnum;
19354aea03ebSBram Moolenaar if (i == 0)
19364aea03ebSBram Moolenaar curwin->w_cursor.col += bd.startspaces;
19374aea03ebSBram Moolenaar }
19384aea03ebSBram Moolenaar
19394aea03ebSBram Moolenaar changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines);
19404aea03ebSBram Moolenaar
19414aea03ebSBram Moolenaar // Set '[ mark.
19424aea03ebSBram Moolenaar curbuf->b_op_start = curwin->w_cursor;
19434aea03ebSBram Moolenaar curbuf->b_op_start.lnum = lnum;
19444aea03ebSBram Moolenaar
19454aea03ebSBram Moolenaar // adjust '] mark
19464aea03ebSBram Moolenaar curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
19474aea03ebSBram Moolenaar curbuf->b_op_end.col = bd.textcol + totlen - 1;
19484aea03ebSBram Moolenaar curbuf->b_op_end.coladd = 0;
19494aea03ebSBram Moolenaar if (flags & PUT_CURSEND)
19504aea03ebSBram Moolenaar {
19514aea03ebSBram Moolenaar colnr_T len;
19524aea03ebSBram Moolenaar
19534aea03ebSBram Moolenaar curwin->w_cursor = curbuf->b_op_end;
19544aea03ebSBram Moolenaar curwin->w_cursor.col++;
19554aea03ebSBram Moolenaar
19564aea03ebSBram Moolenaar // in Insert mode we might be after the NUL, correct for that
19574aea03ebSBram Moolenaar len = (colnr_T)STRLEN(ml_get_curline());
19584aea03ebSBram Moolenaar if (curwin->w_cursor.col > len)
19594aea03ebSBram Moolenaar curwin->w_cursor.col = len;
19604aea03ebSBram Moolenaar }
19614aea03ebSBram Moolenaar else
19624aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum;
19634aea03ebSBram Moolenaar }
19644aea03ebSBram Moolenaar else
19654aea03ebSBram Moolenaar {
19664aea03ebSBram Moolenaar // Character or Line mode
19674aea03ebSBram Moolenaar if (y_type == MCHAR)
19684aea03ebSBram Moolenaar {
19694aea03ebSBram Moolenaar // if type is MCHAR, FORWARD is the same as BACKWARD on the next
19704aea03ebSBram Moolenaar // char
19714aea03ebSBram Moolenaar if (dir == FORWARD && gchar_cursor() != NUL)
19724aea03ebSBram Moolenaar {
19734aea03ebSBram Moolenaar if (has_mbyte)
19744aea03ebSBram Moolenaar {
19754aea03ebSBram Moolenaar int bytelen = (*mb_ptr2len)(ml_get_cursor());
19764aea03ebSBram Moolenaar
19774aea03ebSBram Moolenaar // put it on the next of the multi-byte character.
19784aea03ebSBram Moolenaar col += bytelen;
19794aea03ebSBram Moolenaar if (yanklen)
19804aea03ebSBram Moolenaar {
19814aea03ebSBram Moolenaar curwin->w_cursor.col += bytelen;
19824aea03ebSBram Moolenaar curbuf->b_op_end.col += bytelen;
19834aea03ebSBram Moolenaar }
19844aea03ebSBram Moolenaar }
19854aea03ebSBram Moolenaar else
19864aea03ebSBram Moolenaar {
19874aea03ebSBram Moolenaar ++col;
19884aea03ebSBram Moolenaar if (yanklen)
19894aea03ebSBram Moolenaar {
19904aea03ebSBram Moolenaar ++curwin->w_cursor.col;
19914aea03ebSBram Moolenaar ++curbuf->b_op_end.col;
19924aea03ebSBram Moolenaar }
19934aea03ebSBram Moolenaar }
19944aea03ebSBram Moolenaar }
19954aea03ebSBram Moolenaar curbuf->b_op_start = curwin->w_cursor;
19964aea03ebSBram Moolenaar }
19974aea03ebSBram Moolenaar // Line mode: BACKWARD is the same as FORWARD on the previous line
19984aea03ebSBram Moolenaar else if (dir == BACKWARD)
19994aea03ebSBram Moolenaar --lnum;
20004aea03ebSBram Moolenaar new_cursor = curwin->w_cursor;
20014aea03ebSBram Moolenaar
2002cd94277fSBram Moolenaar // simple case: insert into one line at a time
20034aea03ebSBram Moolenaar if (y_type == MCHAR && y_size == 1)
20044aea03ebSBram Moolenaar {
20054aea03ebSBram Moolenaar linenr_T end_lnum = 0; // init for gcc
2006cd94277fSBram Moolenaar linenr_T start_lnum = lnum;
20074aea03ebSBram Moolenaar
20084aea03ebSBram Moolenaar if (VIsual_active)
20094aea03ebSBram Moolenaar {
20104aea03ebSBram Moolenaar end_lnum = curbuf->b_visual.vi_end.lnum;
20114aea03ebSBram Moolenaar if (end_lnum < curbuf->b_visual.vi_start.lnum)
20124aea03ebSBram Moolenaar end_lnum = curbuf->b_visual.vi_start.lnum;
2013cd94277fSBram Moolenaar if (end_lnum > start_lnum)
2014cd94277fSBram Moolenaar {
2015cd94277fSBram Moolenaar pos_T pos;
2016cd94277fSBram Moolenaar
2017cd94277fSBram Moolenaar // "col" is valid for the first line, in following lines
2018cd94277fSBram Moolenaar // the virtual column needs to be used. Matters for
2019cd94277fSBram Moolenaar // multi-byte characters.
2020cd94277fSBram Moolenaar pos.lnum = lnum;
2021cd94277fSBram Moolenaar pos.col = col;
2022cd94277fSBram Moolenaar pos.coladd = 0;
2023cd94277fSBram Moolenaar getvcol(curwin, &pos, NULL, &vcol, NULL);
2024cd94277fSBram Moolenaar }
20254aea03ebSBram Moolenaar }
20264aea03ebSBram Moolenaar
2027fa537223Sichizok if (count == 0 || yanklen == 0)
2028eeed1c7aSBram Moolenaar {
2029fa537223Sichizok if (VIsual_active)
2030fa537223Sichizok lnum = end_lnum;
2031eeed1c7aSBram Moolenaar }
2032fa537223Sichizok else if (count > INT_MAX / yanklen)
2033fa537223Sichizok // multiplication overflow
2034fa537223Sichizok emsg(_(e_resulting_text_too_long));
2035fa537223Sichizok else
20364aea03ebSBram Moolenaar {
2037fa537223Sichizok totlen = count * yanklen;
2038fa537223Sichizok do {
20394aea03ebSBram Moolenaar oldp = ml_get(lnum);
2040fa537223Sichizok oldlen = (int)STRLEN(oldp);
2041cd94277fSBram Moolenaar if (lnum > start_lnum)
2042cd94277fSBram Moolenaar {
2043cd94277fSBram Moolenaar pos_T pos;
2044cd94277fSBram Moolenaar
2045cd94277fSBram Moolenaar pos.lnum = lnum;
2046cd94277fSBram Moolenaar if (getvpos(&pos, vcol) == OK)
2047cd94277fSBram Moolenaar col = pos.col;
2048cd94277fSBram Moolenaar else
2049cd94277fSBram Moolenaar col = MAXCOL;
2050cd94277fSBram Moolenaar }
2051fa537223Sichizok if (VIsual_active && col > oldlen)
20524aea03ebSBram Moolenaar {
20534aea03ebSBram Moolenaar lnum++;
20544aea03ebSBram Moolenaar continue;
20554aea03ebSBram Moolenaar }
2056fa537223Sichizok newp = alloc(totlen + oldlen + 1);
20574aea03ebSBram Moolenaar if (newp == NULL)
20584aea03ebSBram Moolenaar goto end; // alloc() gave an error message
20594aea03ebSBram Moolenaar mch_memmove(newp, oldp, (size_t)col);
20604aea03ebSBram Moolenaar ptr = newp + col;
20614aea03ebSBram Moolenaar for (i = 0; i < count; ++i)
20624aea03ebSBram Moolenaar {
20634aea03ebSBram Moolenaar mch_memmove(ptr, y_array[0], (size_t)yanklen);
20644aea03ebSBram Moolenaar ptr += yanklen;
20654aea03ebSBram Moolenaar }
20664aea03ebSBram Moolenaar STRMOVE(ptr, oldp + col);
20674aea03ebSBram Moolenaar ml_replace(lnum, newp, FALSE);
20684aea03ebSBram Moolenaar // Place cursor on last putted char.
20694aea03ebSBram Moolenaar if (lnum == curwin->w_cursor.lnum)
20704aea03ebSBram Moolenaar {
20714aea03ebSBram Moolenaar // make sure curwin->w_virtcol is updated
20724aea03ebSBram Moolenaar changed_cline_bef_curs();
20734aea03ebSBram Moolenaar curwin->w_cursor.col += (colnr_T)(totlen - 1);
20744aea03ebSBram Moolenaar }
20754aea03ebSBram Moolenaar if (VIsual_active)
20764aea03ebSBram Moolenaar lnum++;
20774aea03ebSBram Moolenaar } while (VIsual_active && lnum <= end_lnum);
20784aea03ebSBram Moolenaar
20794aea03ebSBram Moolenaar if (VIsual_active) // reset lnum to the last visual line
20804aea03ebSBram Moolenaar lnum--;
2081fa537223Sichizok }
20824aea03ebSBram Moolenaar
20834aea03ebSBram Moolenaar curbuf->b_op_end = curwin->w_cursor;
20844aea03ebSBram Moolenaar // For "CTRL-O p" in Insert mode, put cursor after last char
20854aea03ebSBram Moolenaar if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
20864aea03ebSBram Moolenaar ++curwin->w_cursor.col;
20874aea03ebSBram Moolenaar changed_bytes(lnum, col);
20884aea03ebSBram Moolenaar }
20894aea03ebSBram Moolenaar else
20904aea03ebSBram Moolenaar {
209123003e51SBram Moolenaar linenr_T new_lnum = new_cursor.lnum;
209223003e51SBram Moolenaar
20934aea03ebSBram Moolenaar // Insert at least one line. When y_type is MCHAR, break the first
20944aea03ebSBram Moolenaar // line in two.
20954aea03ebSBram Moolenaar for (cnt = 1; cnt <= count; ++cnt)
20964aea03ebSBram Moolenaar {
20974aea03ebSBram Moolenaar i = 0;
20984aea03ebSBram Moolenaar if (y_type == MCHAR)
20994aea03ebSBram Moolenaar {
21004aea03ebSBram Moolenaar // Split the current line in two at the insert position.
21014aea03ebSBram Moolenaar // First insert y_array[size - 1] in front of second line.
21024aea03ebSBram Moolenaar // Then append y_array[0] to first line.
21034aea03ebSBram Moolenaar lnum = new_cursor.lnum;
21044aea03ebSBram Moolenaar ptr = ml_get(lnum) + col;
21054aea03ebSBram Moolenaar totlen = (int)STRLEN(y_array[y_size - 1]);
21064aea03ebSBram Moolenaar newp = alloc(STRLEN(ptr) + totlen + 1);
21074aea03ebSBram Moolenaar if (newp == NULL)
21084aea03ebSBram Moolenaar goto error;
21094aea03ebSBram Moolenaar STRCPY(newp, y_array[y_size - 1]);
21104aea03ebSBram Moolenaar STRCAT(newp, ptr);
21114aea03ebSBram Moolenaar // insert second line
21124aea03ebSBram Moolenaar ml_append(lnum, newp, (colnr_T)0, FALSE);
211323003e51SBram Moolenaar ++new_lnum;
21144aea03ebSBram Moolenaar vim_free(newp);
21154aea03ebSBram Moolenaar
21164aea03ebSBram Moolenaar oldp = ml_get(lnum);
21174aea03ebSBram Moolenaar newp = alloc(col + yanklen + 1);
21184aea03ebSBram Moolenaar if (newp == NULL)
21194aea03ebSBram Moolenaar goto error;
21204aea03ebSBram Moolenaar // copy first part of line
21214aea03ebSBram Moolenaar mch_memmove(newp, oldp, (size_t)col);
21224aea03ebSBram Moolenaar // append to first line
21234aea03ebSBram Moolenaar mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
21244aea03ebSBram Moolenaar ml_replace(lnum, newp, FALSE);
21254aea03ebSBram Moolenaar
21264aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum;
21274aea03ebSBram Moolenaar i = 1;
21284aea03ebSBram Moolenaar }
21294aea03ebSBram Moolenaar
21304aea03ebSBram Moolenaar for (; i < y_size; ++i)
21314aea03ebSBram Moolenaar {
213223003e51SBram Moolenaar if (y_type != MCHAR || i < y_size - 1)
213323003e51SBram Moolenaar {
213423003e51SBram Moolenaar if (ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
21354aea03ebSBram Moolenaar == FAIL)
21364aea03ebSBram Moolenaar goto error;
213723003e51SBram Moolenaar new_lnum++;
213823003e51SBram Moolenaar }
21394aea03ebSBram Moolenaar lnum++;
21404aea03ebSBram Moolenaar ++nr_lines;
21414aea03ebSBram Moolenaar if (flags & PUT_FIXINDENT)
21424aea03ebSBram Moolenaar {
21434aea03ebSBram Moolenaar old_pos = curwin->w_cursor;
21444aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum;
21454aea03ebSBram Moolenaar ptr = ml_get(lnum);
21464aea03ebSBram Moolenaar if (cnt == count && i == y_size - 1)
21474aea03ebSBram Moolenaar lendiff = (int)STRLEN(ptr);
21484aea03ebSBram Moolenaar #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
21494aea03ebSBram Moolenaar if (*ptr == '#' && preprocs_left())
21504aea03ebSBram Moolenaar indent = 0; // Leave # lines at start
21514aea03ebSBram Moolenaar else
21524aea03ebSBram Moolenaar #endif
21534aea03ebSBram Moolenaar if (*ptr == NUL)
21544aea03ebSBram Moolenaar indent = 0; // Ignore empty lines
21554aea03ebSBram Moolenaar else if (first_indent)
21564aea03ebSBram Moolenaar {
21574aea03ebSBram Moolenaar indent_diff = orig_indent - get_indent();
21584aea03ebSBram Moolenaar indent = orig_indent;
21594aea03ebSBram Moolenaar first_indent = FALSE;
21604aea03ebSBram Moolenaar }
21614aea03ebSBram Moolenaar else if ((indent = get_indent() + indent_diff) < 0)
21624aea03ebSBram Moolenaar indent = 0;
21634aea03ebSBram Moolenaar (void)set_indent(indent, 0);
21644aea03ebSBram Moolenaar curwin->w_cursor = old_pos;
21654aea03ebSBram Moolenaar // remember how many chars were removed
21664aea03ebSBram Moolenaar if (cnt == count && i == y_size - 1)
21674aea03ebSBram Moolenaar lendiff -= (int)STRLEN(ml_get(lnum));
21684aea03ebSBram Moolenaar }
21694aea03ebSBram Moolenaar }
217023003e51SBram Moolenaar if (cnt == 1)
217123003e51SBram Moolenaar new_lnum = lnum;
21724aea03ebSBram Moolenaar }
21734aea03ebSBram Moolenaar
21744aea03ebSBram Moolenaar error:
21754aea03ebSBram Moolenaar // Adjust marks.
21764aea03ebSBram Moolenaar if (y_type == MLINE)
21774aea03ebSBram Moolenaar {
21784aea03ebSBram Moolenaar curbuf->b_op_start.col = 0;
21794aea03ebSBram Moolenaar if (dir == FORWARD)
21804aea03ebSBram Moolenaar curbuf->b_op_start.lnum++;
21814aea03ebSBram Moolenaar }
21824aea03ebSBram Moolenaar // Skip mark_adjust when adding lines after the last one, there
21834aea03ebSBram Moolenaar // can't be marks there. But still needed in diff mode.
21844aea03ebSBram Moolenaar if (curbuf->b_op_start.lnum + (y_type == MCHAR) - 1 + nr_lines
21854aea03ebSBram Moolenaar < curbuf->b_ml.ml_line_count
21864aea03ebSBram Moolenaar #ifdef FEAT_DIFF
21874aea03ebSBram Moolenaar || curwin->w_p_diff
21884aea03ebSBram Moolenaar #endif
21894aea03ebSBram Moolenaar )
21904aea03ebSBram Moolenaar mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
21914aea03ebSBram Moolenaar (linenr_T)MAXLNUM, nr_lines, 0L);
21924aea03ebSBram Moolenaar
21934aea03ebSBram Moolenaar // note changed text for displaying and folding
21944aea03ebSBram Moolenaar if (y_type == MCHAR)
21954aea03ebSBram Moolenaar changed_lines(curwin->w_cursor.lnum, col,
21964aea03ebSBram Moolenaar curwin->w_cursor.lnum + 1, nr_lines);
21974aea03ebSBram Moolenaar else
21984aea03ebSBram Moolenaar changed_lines(curbuf->b_op_start.lnum, 0,
21994aea03ebSBram Moolenaar curbuf->b_op_start.lnum, nr_lines);
22004aea03ebSBram Moolenaar
22014aea03ebSBram Moolenaar // put '] mark at last inserted character
2202f47ebf1eSBram Moolenaar curbuf->b_op_end.lnum = new_lnum;
22034aea03ebSBram Moolenaar // correct length for change in indent
22044aea03ebSBram Moolenaar col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
22054aea03ebSBram Moolenaar if (col > 1)
22064aea03ebSBram Moolenaar curbuf->b_op_end.col = col - 1;
22074aea03ebSBram Moolenaar else
22084aea03ebSBram Moolenaar curbuf->b_op_end.col = 0;
22094aea03ebSBram Moolenaar
22104aea03ebSBram Moolenaar if (flags & PUT_CURSLINE)
22114aea03ebSBram Moolenaar {
22124aea03ebSBram Moolenaar // ":put": put cursor on last inserted line
22134aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum;
22144aea03ebSBram Moolenaar beginline(BL_WHITE | BL_FIX);
22154aea03ebSBram Moolenaar }
22164aea03ebSBram Moolenaar else if (flags & PUT_CURSEND)
22174aea03ebSBram Moolenaar {
22184aea03ebSBram Moolenaar // put cursor after inserted text
22194aea03ebSBram Moolenaar if (y_type == MLINE)
22204aea03ebSBram Moolenaar {
22214aea03ebSBram Moolenaar if (lnum >= curbuf->b_ml.ml_line_count)
22224aea03ebSBram Moolenaar curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
22234aea03ebSBram Moolenaar else
22244aea03ebSBram Moolenaar curwin->w_cursor.lnum = lnum + 1;
22254aea03ebSBram Moolenaar curwin->w_cursor.col = 0;
22264aea03ebSBram Moolenaar }
22274aea03ebSBram Moolenaar else
22284aea03ebSBram Moolenaar {
222923003e51SBram Moolenaar curwin->w_cursor.lnum = new_lnum;
22304aea03ebSBram Moolenaar curwin->w_cursor.col = col;
223156858e4eSBram Moolenaar curbuf->b_op_end = curwin->w_cursor;
223256858e4eSBram Moolenaar if (col > 1)
223356858e4eSBram Moolenaar curbuf->b_op_end.col = col - 1;
22344aea03ebSBram Moolenaar }
22354aea03ebSBram Moolenaar }
22364aea03ebSBram Moolenaar else if (y_type == MLINE)
22374aea03ebSBram Moolenaar {
22384aea03ebSBram Moolenaar // put cursor on first non-blank in first inserted line
22394aea03ebSBram Moolenaar curwin->w_cursor.col = 0;
22404aea03ebSBram Moolenaar if (dir == FORWARD)
22414aea03ebSBram Moolenaar ++curwin->w_cursor.lnum;
22424aea03ebSBram Moolenaar beginline(BL_WHITE | BL_FIX);
22434aea03ebSBram Moolenaar }
22444aea03ebSBram Moolenaar else // put cursor on first inserted character
22454aea03ebSBram Moolenaar curwin->w_cursor = new_cursor;
22464aea03ebSBram Moolenaar }
22474aea03ebSBram Moolenaar }
22484aea03ebSBram Moolenaar
22494aea03ebSBram Moolenaar msgmore(nr_lines);
22504aea03ebSBram Moolenaar curwin->w_set_curswant = TRUE;
22514aea03ebSBram Moolenaar
22524aea03ebSBram Moolenaar end:
2253e1004401SBram Moolenaar if (cmdmod.cmod_flags & CMOD_LOCKMARKS)
2254f4a1d1c0SBram Moolenaar {
2255f4a1d1c0SBram Moolenaar curbuf->b_op_start = orig_start;
2256f4a1d1c0SBram Moolenaar curbuf->b_op_end = orig_end;
2257f4a1d1c0SBram Moolenaar }
22584aea03ebSBram Moolenaar if (allocated)
22594aea03ebSBram Moolenaar vim_free(insert_string);
22604aea03ebSBram Moolenaar if (regname == '=')
22614aea03ebSBram Moolenaar vim_free(y_array);
22624aea03ebSBram Moolenaar
22634aea03ebSBram Moolenaar VIsual_active = FALSE;
22644aea03ebSBram Moolenaar
22654aea03ebSBram Moolenaar // If the cursor is past the end of the line put it at the end.
22664aea03ebSBram Moolenaar adjust_cursor_eol();
22674aea03ebSBram Moolenaar }
22684aea03ebSBram Moolenaar
22694aea03ebSBram Moolenaar /*
22704aea03ebSBram Moolenaar * Return the character name of the register with the given number.
22714aea03ebSBram Moolenaar */
22724aea03ebSBram Moolenaar int
get_register_name(int num)22734aea03ebSBram Moolenaar get_register_name(int num)
22744aea03ebSBram Moolenaar {
22754aea03ebSBram Moolenaar if (num == -1)
22764aea03ebSBram Moolenaar return '"';
22774aea03ebSBram Moolenaar else if (num < 10)
22784aea03ebSBram Moolenaar return num + '0';
22794aea03ebSBram Moolenaar else if (num == DELETION_REGISTER)
22804aea03ebSBram Moolenaar return '-';
22814aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
22824aea03ebSBram Moolenaar else if (num == STAR_REGISTER)
22834aea03ebSBram Moolenaar return '*';
22844aea03ebSBram Moolenaar else if (num == PLUS_REGISTER)
22854aea03ebSBram Moolenaar return '+';
22864aea03ebSBram Moolenaar #endif
22874aea03ebSBram Moolenaar else
22884aea03ebSBram Moolenaar {
22894aea03ebSBram Moolenaar #ifdef EBCDIC
22904aea03ebSBram Moolenaar int i;
22914aea03ebSBram Moolenaar
22924aea03ebSBram Moolenaar // EBCDIC is really braindead ...
22934aea03ebSBram Moolenaar i = 'a' + (num - 10);
22944aea03ebSBram Moolenaar if (i > 'i')
22954aea03ebSBram Moolenaar i += 7;
22964aea03ebSBram Moolenaar if (i > 'r')
22974aea03ebSBram Moolenaar i += 8;
22984aea03ebSBram Moolenaar return i;
22994aea03ebSBram Moolenaar #else
23004aea03ebSBram Moolenaar return num + 'a' - 10;
23014aea03ebSBram Moolenaar #endif
23024aea03ebSBram Moolenaar }
23034aea03ebSBram Moolenaar }
23044aea03ebSBram Moolenaar
23054aea03ebSBram Moolenaar /*
2306bb861e29SBram Moolenaar * Return the index of the register "" points to.
2307bb861e29SBram Moolenaar */
2308bb861e29SBram Moolenaar int
get_unname_register()2309bb861e29SBram Moolenaar get_unname_register()
2310bb861e29SBram Moolenaar {
2311bb861e29SBram Moolenaar return y_previous == NULL ? -1 : y_previous - &y_regs[0];
2312bb861e29SBram Moolenaar }
2313bb861e29SBram Moolenaar
2314bb861e29SBram Moolenaar /*
23154aea03ebSBram Moolenaar * ":dis" and ":registers": Display the contents of the yank registers.
23164aea03ebSBram Moolenaar */
23174aea03ebSBram Moolenaar void
ex_display(exarg_T * eap)23184aea03ebSBram Moolenaar ex_display(exarg_T *eap)
23194aea03ebSBram Moolenaar {
23204aea03ebSBram Moolenaar int i, n;
23214aea03ebSBram Moolenaar long j;
23224aea03ebSBram Moolenaar char_u *p;
23234aea03ebSBram Moolenaar yankreg_T *yb;
23244aea03ebSBram Moolenaar int name;
23254aea03ebSBram Moolenaar int attr;
23264aea03ebSBram Moolenaar char_u *arg = eap->arg;
23274aea03ebSBram Moolenaar int clen;
23288fc42964SBram Moolenaar int type;
23294aea03ebSBram Moolenaar
23304aea03ebSBram Moolenaar if (arg != NULL && *arg == NUL)
23314aea03ebSBram Moolenaar arg = NULL;
23324aea03ebSBram Moolenaar attr = HL_ATTR(HLF_8);
23334aea03ebSBram Moolenaar
23344aea03ebSBram Moolenaar // Highlight title
23353691f1eeSBram Moolenaar msg_puts_title(_("\nType Name Content"));
23364aea03ebSBram Moolenaar for (i = -1; i < NUM_REGISTERS && !got_int; ++i)
23374aea03ebSBram Moolenaar {
23384aea03ebSBram Moolenaar name = get_register_name(i);
23393691f1eeSBram Moolenaar switch (get_reg_type(name, NULL))
23403691f1eeSBram Moolenaar {
23418fc42964SBram Moolenaar case MLINE: type = 'l'; break;
23428fc42964SBram Moolenaar case MCHAR: type = 'c'; break;
23438fc42964SBram Moolenaar default: type = 'b'; break;
23443691f1eeSBram Moolenaar }
23454aea03ebSBram Moolenaar if (arg != NULL && vim_strchr(arg, name) == NULL
23464aea03ebSBram Moolenaar #ifdef ONE_CLIPBOARD
23474aea03ebSBram Moolenaar // Star register and plus register contain the same thing.
23484aea03ebSBram Moolenaar && (name != '*' || vim_strchr(arg, '+') == NULL)
23494aea03ebSBram Moolenaar #endif
23504aea03ebSBram Moolenaar )
23514aea03ebSBram Moolenaar continue; // did not ask for this register
23524aea03ebSBram Moolenaar
23534aea03ebSBram Moolenaar #ifdef FEAT_CLIPBOARD
23544aea03ebSBram Moolenaar // Adjust register name for "unnamed" in 'clipboard'.
23554aea03ebSBram Moolenaar // When it's a clipboard register, fill it with the current contents
23564aea03ebSBram Moolenaar // of the clipboard.
23574aea03ebSBram Moolenaar adjust_clip_reg(&name);
23584aea03ebSBram Moolenaar (void)may_get_selection(name);
23594aea03ebSBram Moolenaar #endif
23604aea03ebSBram Moolenaar
23614aea03ebSBram Moolenaar if (i == -1)
23624aea03ebSBram Moolenaar {
23634aea03ebSBram Moolenaar if (y_previous != NULL)
23644aea03ebSBram Moolenaar yb = y_previous;
23654aea03ebSBram Moolenaar else
23664aea03ebSBram Moolenaar yb = &(y_regs[0]);
23674aea03ebSBram Moolenaar }
23684aea03ebSBram Moolenaar else
23694aea03ebSBram Moolenaar yb = &(y_regs[i]);
23704aea03ebSBram Moolenaar
23714aea03ebSBram Moolenaar #ifdef FEAT_EVAL
23724aea03ebSBram Moolenaar if (name == MB_TOLOWER(redir_reg)
23734aea03ebSBram Moolenaar || (redir_reg == '"' && yb == y_previous))
23744aea03ebSBram Moolenaar continue; // do not list register being written to, the
23754aea03ebSBram Moolenaar // pointer can be freed
23764aea03ebSBram Moolenaar #endif
23774aea03ebSBram Moolenaar
23784aea03ebSBram Moolenaar if (yb->y_array != NULL)
23794aea03ebSBram Moolenaar {
23808fc42964SBram Moolenaar int do_show = FALSE;
23818fc42964SBram Moolenaar
23828fc42964SBram Moolenaar for (j = 0; !do_show && j < yb->y_size; ++j)
23838fc42964SBram Moolenaar do_show = !message_filtered(yb->y_array[j]);
23848fc42964SBram Moolenaar
23858fc42964SBram Moolenaar if (do_show || yb->y_size == 0)
23868fc42964SBram Moolenaar {
23874aea03ebSBram Moolenaar msg_putchar('\n');
23883691f1eeSBram Moolenaar msg_puts(" ");
23898fc42964SBram Moolenaar msg_putchar(type);
23903691f1eeSBram Moolenaar msg_puts(" ");
23914aea03ebSBram Moolenaar msg_putchar('"');
23924aea03ebSBram Moolenaar msg_putchar(name);
23934aea03ebSBram Moolenaar msg_puts(" ");
23944aea03ebSBram Moolenaar
23953691f1eeSBram Moolenaar n = (int)Columns - 11;
23964aea03ebSBram Moolenaar for (j = 0; j < yb->y_size && n > 1; ++j)
23974aea03ebSBram Moolenaar {
23984aea03ebSBram Moolenaar if (j)
23994aea03ebSBram Moolenaar {
24004aea03ebSBram Moolenaar msg_puts_attr("^J", attr);
24014aea03ebSBram Moolenaar n -= 2;
24024aea03ebSBram Moolenaar }
24038fc42964SBram Moolenaar for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0;
24048fc42964SBram Moolenaar ++p)
24054aea03ebSBram Moolenaar {
24064aea03ebSBram Moolenaar clen = (*mb_ptr2len)(p);
24074aea03ebSBram Moolenaar msg_outtrans_len(p, clen);
24084aea03ebSBram Moolenaar p += clen - 1;
24094aea03ebSBram Moolenaar }
24104aea03ebSBram Moolenaar }
24114aea03ebSBram Moolenaar if (n > 1 && yb->y_type == MLINE)
24124aea03ebSBram Moolenaar msg_puts_attr("^J", attr);
24134aea03ebSBram Moolenaar out_flush(); // show one line at a time
24144aea03ebSBram Moolenaar }
24154aea03ebSBram Moolenaar ui_breakcheck();
24164aea03ebSBram Moolenaar }
24178fc42964SBram Moolenaar }
24184aea03ebSBram Moolenaar
24194aea03ebSBram Moolenaar // display last inserted text
24204aea03ebSBram Moolenaar if ((p = get_last_insert()) != NULL
24218fc42964SBram Moolenaar && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int
24228fc42964SBram Moolenaar && !message_filtered(p))
24234aea03ebSBram Moolenaar {
24243691f1eeSBram Moolenaar msg_puts("\n c \". ");
24254aea03ebSBram Moolenaar dis_msg(p, TRUE);
24264aea03ebSBram Moolenaar }
24274aea03ebSBram Moolenaar
24284aea03ebSBram Moolenaar // display last command line
24294aea03ebSBram Moolenaar if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
24308fc42964SBram Moolenaar && !got_int && !message_filtered(last_cmdline))
24314aea03ebSBram Moolenaar {
24323691f1eeSBram Moolenaar msg_puts("\n c \": ");
24334aea03ebSBram Moolenaar dis_msg(last_cmdline, FALSE);
24344aea03ebSBram Moolenaar }
24354aea03ebSBram Moolenaar
24364aea03ebSBram Moolenaar // display current file name
24374aea03ebSBram Moolenaar if (curbuf->b_fname != NULL
24388fc42964SBram Moolenaar && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int
24398fc42964SBram Moolenaar && !message_filtered(curbuf->b_fname))
24404aea03ebSBram Moolenaar {
24413691f1eeSBram Moolenaar msg_puts("\n c \"% ");
24424aea03ebSBram Moolenaar dis_msg(curbuf->b_fname, FALSE);
24434aea03ebSBram Moolenaar }
24444aea03ebSBram Moolenaar
24454aea03ebSBram Moolenaar // display alternate file name
24464aea03ebSBram Moolenaar if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
24474aea03ebSBram Moolenaar {
24484aea03ebSBram Moolenaar char_u *fname;
24494aea03ebSBram Moolenaar linenr_T dummy;
24504aea03ebSBram Moolenaar
24518fc42964SBram Moolenaar if (buflist_name_nr(0, &fname, &dummy) != FAIL
24528fc42964SBram Moolenaar && !message_filtered(fname))
24534aea03ebSBram Moolenaar {
24543691f1eeSBram Moolenaar msg_puts("\n c \"# ");
24554aea03ebSBram Moolenaar dis_msg(fname, FALSE);
24564aea03ebSBram Moolenaar }
24574aea03ebSBram Moolenaar }
24584aea03ebSBram Moolenaar
24594aea03ebSBram Moolenaar // display last search pattern
24604aea03ebSBram Moolenaar if (last_search_pat() != NULL
24618fc42964SBram Moolenaar && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int
24628fc42964SBram Moolenaar && !message_filtered(last_search_pat()))
24634aea03ebSBram Moolenaar {
24643691f1eeSBram Moolenaar msg_puts("\n c \"/ ");
24654aea03ebSBram Moolenaar dis_msg(last_search_pat(), FALSE);
24664aea03ebSBram Moolenaar }
24674aea03ebSBram Moolenaar
24684aea03ebSBram Moolenaar #ifdef FEAT_EVAL
24694aea03ebSBram Moolenaar // display last used expression
24704aea03ebSBram Moolenaar if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
24718fc42964SBram Moolenaar && !got_int && !message_filtered(expr_line))
24724aea03ebSBram Moolenaar {
24733691f1eeSBram Moolenaar msg_puts("\n c \"= ");
24744aea03ebSBram Moolenaar dis_msg(expr_line, FALSE);
24754aea03ebSBram Moolenaar }
24764aea03ebSBram Moolenaar #endif
24774aea03ebSBram Moolenaar }
24784aea03ebSBram Moolenaar
24794aea03ebSBram Moolenaar /*
24804aea03ebSBram Moolenaar * display a string for do_dis()
24814aea03ebSBram Moolenaar * truncate at end of screen line
24824aea03ebSBram Moolenaar */
24834aea03ebSBram Moolenaar static void
dis_msg(char_u * p,int skip_esc)24844aea03ebSBram Moolenaar dis_msg(
24854aea03ebSBram Moolenaar char_u *p,
24864aea03ebSBram Moolenaar int skip_esc) // if TRUE, ignore trailing ESC
24874aea03ebSBram Moolenaar {
24884aea03ebSBram Moolenaar int n;
24894aea03ebSBram Moolenaar int l;
24904aea03ebSBram Moolenaar
24914aea03ebSBram Moolenaar n = (int)Columns - 6;
24924aea03ebSBram Moolenaar while (*p != NUL
24934aea03ebSBram Moolenaar && !(*p == ESC && skip_esc && *(p + 1) == NUL)
24944aea03ebSBram Moolenaar && (n -= ptr2cells(p)) >= 0)
24954aea03ebSBram Moolenaar {
24964aea03ebSBram Moolenaar if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
24974aea03ebSBram Moolenaar {
24984aea03ebSBram Moolenaar msg_outtrans_len(p, l);
24994aea03ebSBram Moolenaar p += l;
25004aea03ebSBram Moolenaar }
25014aea03ebSBram Moolenaar else
25024aea03ebSBram Moolenaar msg_outtrans_len(p++, 1);
25034aea03ebSBram Moolenaar }
25044aea03ebSBram Moolenaar ui_breakcheck();
25054aea03ebSBram Moolenaar }
25064aea03ebSBram Moolenaar
25074aea03ebSBram Moolenaar #if defined(FEAT_DND) || defined(PROTO)
25084aea03ebSBram Moolenaar /*
25094aea03ebSBram Moolenaar * Replace the contents of the '~' register with str.
25104aea03ebSBram Moolenaar */
25114aea03ebSBram Moolenaar void
dnd_yank_drag_data(char_u * str,long len)25124aea03ebSBram Moolenaar dnd_yank_drag_data(char_u *str, long len)
25134aea03ebSBram Moolenaar {
25144aea03ebSBram Moolenaar yankreg_T *curr;
25154aea03ebSBram Moolenaar
25164aea03ebSBram Moolenaar curr = y_current;
25174aea03ebSBram Moolenaar y_current = &y_regs[TILDE_REGISTER];
25184aea03ebSBram Moolenaar free_yank_all();
25194aea03ebSBram Moolenaar str_to_reg(y_current, MCHAR, str, len, 0L, FALSE);
25204aea03ebSBram Moolenaar y_current = curr;
25214aea03ebSBram Moolenaar }
25224aea03ebSBram Moolenaar #endif
25234aea03ebSBram Moolenaar
25244aea03ebSBram Moolenaar
25254aea03ebSBram Moolenaar /*
25264aea03ebSBram Moolenaar * Return the type of a register.
25274aea03ebSBram Moolenaar * Used for getregtype()
25284aea03ebSBram Moolenaar * Returns MAUTO for error.
25294aea03ebSBram Moolenaar */
25304aea03ebSBram Moolenaar char_u
get_reg_type(int regname,long * reglen)25314aea03ebSBram Moolenaar get_reg_type(int regname, long *reglen)
25324aea03ebSBram Moolenaar {
25334aea03ebSBram Moolenaar switch (regname)
25344aea03ebSBram Moolenaar {
25354aea03ebSBram Moolenaar case '%': // file name
25364aea03ebSBram Moolenaar case '#': // alternate file name
25374aea03ebSBram Moolenaar case '=': // expression
25384aea03ebSBram Moolenaar case ':': // last command line
25394aea03ebSBram Moolenaar case '/': // last search-pattern
25404aea03ebSBram Moolenaar case '.': // last inserted text
25414aea03ebSBram Moolenaar # ifdef FEAT_SEARCHPATH
25424aea03ebSBram Moolenaar case Ctrl_F: // Filename under cursor
25434aea03ebSBram Moolenaar case Ctrl_P: // Path under cursor, expand via "path"
25444aea03ebSBram Moolenaar # endif
25454aea03ebSBram Moolenaar case Ctrl_W: // word under cursor
25464aea03ebSBram Moolenaar case Ctrl_A: // WORD (mnemonic All) under cursor
25474aea03ebSBram Moolenaar case '_': // black hole: always empty
25484aea03ebSBram Moolenaar return MCHAR;
25494aea03ebSBram Moolenaar }
25504aea03ebSBram Moolenaar
25514aea03ebSBram Moolenaar # ifdef FEAT_CLIPBOARD
25524aea03ebSBram Moolenaar regname = may_get_selection(regname);
25534aea03ebSBram Moolenaar # endif
25544aea03ebSBram Moolenaar
25554aea03ebSBram Moolenaar if (regname != NUL && !valid_yank_reg(regname, FALSE))
25564aea03ebSBram Moolenaar return MAUTO;
25574aea03ebSBram Moolenaar
25584aea03ebSBram Moolenaar get_yank_register(regname, FALSE);
25594aea03ebSBram Moolenaar
25604aea03ebSBram Moolenaar if (y_current->y_array != NULL)
25614aea03ebSBram Moolenaar {
25624aea03ebSBram Moolenaar if (reglen != NULL && y_current->y_type == MBLOCK)
25634aea03ebSBram Moolenaar *reglen = y_current->y_width;
25644aea03ebSBram Moolenaar return y_current->y_type;
25654aea03ebSBram Moolenaar }
25664aea03ebSBram Moolenaar return MAUTO;
25674aea03ebSBram Moolenaar }
25684aea03ebSBram Moolenaar
25693691f1eeSBram Moolenaar #if defined(FEAT_EVAL) || defined(PROTO)
25704aea03ebSBram Moolenaar /*
25714aea03ebSBram Moolenaar * When "flags" has GREG_LIST return a list with text "s".
25724aea03ebSBram Moolenaar * Otherwise just return "s".
25734aea03ebSBram Moolenaar */
25744aea03ebSBram Moolenaar static char_u *
getreg_wrap_one_line(char_u * s,int flags)25754aea03ebSBram Moolenaar getreg_wrap_one_line(char_u *s, int flags)
25764aea03ebSBram Moolenaar {
25774aea03ebSBram Moolenaar if (flags & GREG_LIST)
25784aea03ebSBram Moolenaar {
25794aea03ebSBram Moolenaar list_T *list = list_alloc();
25804aea03ebSBram Moolenaar
25814aea03ebSBram Moolenaar if (list != NULL)
25824aea03ebSBram Moolenaar {
25834aea03ebSBram Moolenaar if (list_append_string(list, NULL, -1) == FAIL)
25844aea03ebSBram Moolenaar {
25854aea03ebSBram Moolenaar list_free(list);
25864aea03ebSBram Moolenaar return NULL;
25874aea03ebSBram Moolenaar }
25884aea03ebSBram Moolenaar list->lv_first->li_tv.vval.v_string = s;
25894aea03ebSBram Moolenaar }
25904aea03ebSBram Moolenaar return (char_u *)list;
25914aea03ebSBram Moolenaar }
25924aea03ebSBram Moolenaar return s;
25934aea03ebSBram Moolenaar }
25944aea03ebSBram Moolenaar
25954aea03ebSBram Moolenaar /*
2596d672dde5SBram Moolenaar * Return the contents of a register as a single allocated string or as a list.
25974aea03ebSBram Moolenaar * Used for "@r" in expressions and for getreg().
25984aea03ebSBram Moolenaar * Returns NULL for error.
25994aea03ebSBram Moolenaar * Flags:
26004aea03ebSBram Moolenaar * GREG_NO_EXPR Do not allow expression register
26014aea03ebSBram Moolenaar * GREG_EXPR_SRC For the expression register: return expression itself,
26024aea03ebSBram Moolenaar * not the result of its evaluation.
2603d672dde5SBram Moolenaar * GREG_LIST Return a list of lines instead of a single string.
26044aea03ebSBram Moolenaar */
26054aea03ebSBram Moolenaar char_u *
get_reg_contents(int regname,int flags)26064aea03ebSBram Moolenaar get_reg_contents(int regname, int flags)
26074aea03ebSBram Moolenaar {
26084aea03ebSBram Moolenaar long i;
26094aea03ebSBram Moolenaar char_u *retval;
26104aea03ebSBram Moolenaar int allocated;
26114aea03ebSBram Moolenaar long len;
26124aea03ebSBram Moolenaar
26134aea03ebSBram Moolenaar // Don't allow using an expression register inside an expression
26144aea03ebSBram Moolenaar if (regname == '=')
26154aea03ebSBram Moolenaar {
26164aea03ebSBram Moolenaar if (flags & GREG_NO_EXPR)
26174aea03ebSBram Moolenaar return NULL;
26184aea03ebSBram Moolenaar if (flags & GREG_EXPR_SRC)
26194aea03ebSBram Moolenaar return getreg_wrap_one_line(get_expr_line_src(), flags);
26204aea03ebSBram Moolenaar return getreg_wrap_one_line(get_expr_line(), flags);
26214aea03ebSBram Moolenaar }
26224aea03ebSBram Moolenaar
26234aea03ebSBram Moolenaar if (regname == '@') // "@@" is used for unnamed register
26244aea03ebSBram Moolenaar regname = '"';
26254aea03ebSBram Moolenaar
26264aea03ebSBram Moolenaar // check for valid regname
26274aea03ebSBram Moolenaar if (regname != NUL && !valid_yank_reg(regname, FALSE))
26284aea03ebSBram Moolenaar return NULL;
26294aea03ebSBram Moolenaar
26304aea03ebSBram Moolenaar # ifdef FEAT_CLIPBOARD
26314aea03ebSBram Moolenaar regname = may_get_selection(regname);
26324aea03ebSBram Moolenaar # endif
26334aea03ebSBram Moolenaar
26344aea03ebSBram Moolenaar if (get_spec_reg(regname, &retval, &allocated, FALSE))
26354aea03ebSBram Moolenaar {
26364aea03ebSBram Moolenaar if (retval == NULL)
26374aea03ebSBram Moolenaar return NULL;
26384aea03ebSBram Moolenaar if (allocated)
26394aea03ebSBram Moolenaar return getreg_wrap_one_line(retval, flags);
26404aea03ebSBram Moolenaar return getreg_wrap_one_line(vim_strsave(retval), flags);
26414aea03ebSBram Moolenaar }
26424aea03ebSBram Moolenaar
26434aea03ebSBram Moolenaar get_yank_register(regname, FALSE);
26444aea03ebSBram Moolenaar if (y_current->y_array == NULL)
26454aea03ebSBram Moolenaar return NULL;
26464aea03ebSBram Moolenaar
26474aea03ebSBram Moolenaar if (flags & GREG_LIST)
26484aea03ebSBram Moolenaar {
26494aea03ebSBram Moolenaar list_T *list = list_alloc();
26504aea03ebSBram Moolenaar int error = FALSE;
26514aea03ebSBram Moolenaar
26524aea03ebSBram Moolenaar if (list == NULL)
26534aea03ebSBram Moolenaar return NULL;
26544aea03ebSBram Moolenaar for (i = 0; i < y_current->y_size; ++i)
26554aea03ebSBram Moolenaar if (list_append_string(list, y_current->y_array[i], -1) == FAIL)
26564aea03ebSBram Moolenaar error = TRUE;
26574aea03ebSBram Moolenaar if (error)
26584aea03ebSBram Moolenaar {
26594aea03ebSBram Moolenaar list_free(list);
26604aea03ebSBram Moolenaar return NULL;
26614aea03ebSBram Moolenaar }
26624aea03ebSBram Moolenaar return (char_u *)list;
26634aea03ebSBram Moolenaar }
26644aea03ebSBram Moolenaar
26654aea03ebSBram Moolenaar // Compute length of resulting string.
26664aea03ebSBram Moolenaar len = 0;
26674aea03ebSBram Moolenaar for (i = 0; i < y_current->y_size; ++i)
26684aea03ebSBram Moolenaar {
26694aea03ebSBram Moolenaar len += (long)STRLEN(y_current->y_array[i]);
26704aea03ebSBram Moolenaar // Insert a newline between lines and after last line if
26714aea03ebSBram Moolenaar // y_type is MLINE.
26724aea03ebSBram Moolenaar if (y_current->y_type == MLINE || i < y_current->y_size - 1)
26734aea03ebSBram Moolenaar ++len;
26744aea03ebSBram Moolenaar }
26754aea03ebSBram Moolenaar
26764aea03ebSBram Moolenaar retval = alloc(len + 1);
26774aea03ebSBram Moolenaar
26784aea03ebSBram Moolenaar // Copy the lines of the yank register into the string.
26794aea03ebSBram Moolenaar if (retval != NULL)
26804aea03ebSBram Moolenaar {
26814aea03ebSBram Moolenaar len = 0;
26824aea03ebSBram Moolenaar for (i = 0; i < y_current->y_size; ++i)
26834aea03ebSBram Moolenaar {
26844aea03ebSBram Moolenaar STRCPY(retval + len, y_current->y_array[i]);
26854aea03ebSBram Moolenaar len += (long)STRLEN(retval + len);
26864aea03ebSBram Moolenaar
26874aea03ebSBram Moolenaar // Insert a NL between lines and after the last line if y_type is
26884aea03ebSBram Moolenaar // MLINE.
26894aea03ebSBram Moolenaar if (y_current->y_type == MLINE || i < y_current->y_size - 1)
26904aea03ebSBram Moolenaar retval[len++] = '\n';
26914aea03ebSBram Moolenaar }
26924aea03ebSBram Moolenaar retval[len] = NUL;
26934aea03ebSBram Moolenaar }
26944aea03ebSBram Moolenaar
26954aea03ebSBram Moolenaar return retval;
26964aea03ebSBram Moolenaar }
26974aea03ebSBram Moolenaar
26984aea03ebSBram Moolenaar static int
init_write_reg(int name,yankreg_T ** old_y_previous,yankreg_T ** old_y_current,int must_append,int * yank_type UNUSED)26994aea03ebSBram Moolenaar init_write_reg(
27004aea03ebSBram Moolenaar int name,
27014aea03ebSBram Moolenaar yankreg_T **old_y_previous,
27024aea03ebSBram Moolenaar yankreg_T **old_y_current,
27034aea03ebSBram Moolenaar int must_append,
27044aea03ebSBram Moolenaar int *yank_type UNUSED)
27054aea03ebSBram Moolenaar {
27064aea03ebSBram Moolenaar if (!valid_yank_reg(name, TRUE)) // check for valid reg name
27074aea03ebSBram Moolenaar {
27084aea03ebSBram Moolenaar emsg_invreg(name);
27094aea03ebSBram Moolenaar return FAIL;
27104aea03ebSBram Moolenaar }
27114aea03ebSBram Moolenaar
27124aea03ebSBram Moolenaar // Don't want to change the current (unnamed) register
27134aea03ebSBram Moolenaar *old_y_previous = y_previous;
27144aea03ebSBram Moolenaar *old_y_current = y_current;
27154aea03ebSBram Moolenaar
27164aea03ebSBram Moolenaar get_yank_register(name, TRUE);
27174aea03ebSBram Moolenaar if (!y_append && !must_append)
27184aea03ebSBram Moolenaar free_yank_all();
27194aea03ebSBram Moolenaar return OK;
27204aea03ebSBram Moolenaar }
27214aea03ebSBram Moolenaar
27224aea03ebSBram Moolenaar static void
finish_write_reg(int name,yankreg_T * old_y_previous,yankreg_T * old_y_current)27234aea03ebSBram Moolenaar finish_write_reg(
27244aea03ebSBram Moolenaar int name,
27254aea03ebSBram Moolenaar yankreg_T *old_y_previous,
27264aea03ebSBram Moolenaar yankreg_T *old_y_current)
27274aea03ebSBram Moolenaar {
27284aea03ebSBram Moolenaar # ifdef FEAT_CLIPBOARD
27294aea03ebSBram Moolenaar // Send text of clipboard register to the clipboard.
27304aea03ebSBram Moolenaar may_set_selection();
27314aea03ebSBram Moolenaar # endif
27324aea03ebSBram Moolenaar
27334aea03ebSBram Moolenaar // ':let @" = "val"' should change the meaning of the "" register
27344aea03ebSBram Moolenaar if (name != '"')
27354aea03ebSBram Moolenaar y_previous = old_y_previous;
27364aea03ebSBram Moolenaar y_current = old_y_current;
27374aea03ebSBram Moolenaar }
27384aea03ebSBram Moolenaar
27394aea03ebSBram Moolenaar /*
27404aea03ebSBram Moolenaar * Store string "str" in register "name".
27414aea03ebSBram Moolenaar * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
27424aea03ebSBram Moolenaar * If "must_append" is TRUE, always append to the register. Otherwise append
27434aea03ebSBram Moolenaar * if "name" is an uppercase letter.
27444aea03ebSBram Moolenaar * Note: "maxlen" and "must_append" don't work for the "/" register.
27454aea03ebSBram Moolenaar * Careful: 'str' is modified, you may have to use a copy!
27464aea03ebSBram Moolenaar * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
27474aea03ebSBram Moolenaar */
27484aea03ebSBram Moolenaar void
write_reg_contents(int name,char_u * str,int maxlen,int must_append)27494aea03ebSBram Moolenaar write_reg_contents(
27504aea03ebSBram Moolenaar int name,
27514aea03ebSBram Moolenaar char_u *str,
27524aea03ebSBram Moolenaar int maxlen,
27534aea03ebSBram Moolenaar int must_append)
27544aea03ebSBram Moolenaar {
27554aea03ebSBram Moolenaar write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
27564aea03ebSBram Moolenaar }
27574aea03ebSBram Moolenaar
27584aea03ebSBram Moolenaar void
write_reg_contents_lst(int name,char_u ** strings,int maxlen UNUSED,int must_append,int yank_type,long block_len)27594aea03ebSBram Moolenaar write_reg_contents_lst(
27604aea03ebSBram Moolenaar int name,
27614aea03ebSBram Moolenaar char_u **strings,
27624aea03ebSBram Moolenaar int maxlen UNUSED,
27634aea03ebSBram Moolenaar int must_append,
27644aea03ebSBram Moolenaar int yank_type,
27654aea03ebSBram Moolenaar long block_len)
27664aea03ebSBram Moolenaar {
27674aea03ebSBram Moolenaar yankreg_T *old_y_previous, *old_y_current;
27684aea03ebSBram Moolenaar
27694aea03ebSBram Moolenaar if (name == '/' || name == '=')
27704aea03ebSBram Moolenaar {
27714aea03ebSBram Moolenaar char_u *s;
27724aea03ebSBram Moolenaar
27734aea03ebSBram Moolenaar if (strings[0] == NULL)
27744aea03ebSBram Moolenaar s = (char_u *)"";
27754aea03ebSBram Moolenaar else if (strings[1] != NULL)
27764aea03ebSBram Moolenaar {
27774aea03ebSBram Moolenaar emsg(_("E883: search pattern and expression register may not "
27784aea03ebSBram Moolenaar "contain two or more lines"));
27794aea03ebSBram Moolenaar return;
27804aea03ebSBram Moolenaar }
27814aea03ebSBram Moolenaar else
27824aea03ebSBram Moolenaar s = strings[0];
27834aea03ebSBram Moolenaar write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
27844aea03ebSBram Moolenaar return;
27854aea03ebSBram Moolenaar }
27864aea03ebSBram Moolenaar
27874aea03ebSBram Moolenaar if (name == '_') // black hole: nothing to do
27884aea03ebSBram Moolenaar return;
27894aea03ebSBram Moolenaar
27904aea03ebSBram Moolenaar if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
27914aea03ebSBram Moolenaar &yank_type) == FAIL)
27924aea03ebSBram Moolenaar return;
27934aea03ebSBram Moolenaar
27944aea03ebSBram Moolenaar str_to_reg(y_current, yank_type, (char_u *)strings, -1, block_len, TRUE);
27954aea03ebSBram Moolenaar
27964aea03ebSBram Moolenaar finish_write_reg(name, old_y_previous, old_y_current);
27974aea03ebSBram Moolenaar }
27984aea03ebSBram Moolenaar
27994aea03ebSBram Moolenaar void
write_reg_contents_ex(int name,char_u * str,int maxlen,int must_append,int yank_type,long block_len)28004aea03ebSBram Moolenaar write_reg_contents_ex(
28014aea03ebSBram Moolenaar int name,
28024aea03ebSBram Moolenaar char_u *str,
28034aea03ebSBram Moolenaar int maxlen,
28044aea03ebSBram Moolenaar int must_append,
28054aea03ebSBram Moolenaar int yank_type,
28064aea03ebSBram Moolenaar long block_len)
28074aea03ebSBram Moolenaar {
28084aea03ebSBram Moolenaar yankreg_T *old_y_previous, *old_y_current;
28094aea03ebSBram Moolenaar long len;
28104aea03ebSBram Moolenaar
28114aea03ebSBram Moolenaar if (maxlen >= 0)
28124aea03ebSBram Moolenaar len = maxlen;
28134aea03ebSBram Moolenaar else
28144aea03ebSBram Moolenaar len = (long)STRLEN(str);
28154aea03ebSBram Moolenaar
28164aea03ebSBram Moolenaar // Special case: '/' search pattern
28174aea03ebSBram Moolenaar if (name == '/')
28184aea03ebSBram Moolenaar {
28194aea03ebSBram Moolenaar set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
28204aea03ebSBram Moolenaar return;
28214aea03ebSBram Moolenaar }
28224aea03ebSBram Moolenaar
28234aea03ebSBram Moolenaar if (name == '#')
28244aea03ebSBram Moolenaar {
28254aea03ebSBram Moolenaar buf_T *buf;
28264aea03ebSBram Moolenaar
28274aea03ebSBram Moolenaar if (VIM_ISDIGIT(*str))
28284aea03ebSBram Moolenaar {
28294aea03ebSBram Moolenaar int num = atoi((char *)str);
28304aea03ebSBram Moolenaar
28314aea03ebSBram Moolenaar buf = buflist_findnr(num);
28324aea03ebSBram Moolenaar if (buf == NULL)
28334aea03ebSBram Moolenaar semsg(_(e_nobufnr), (long)num);
28344aea03ebSBram Moolenaar }
28354aea03ebSBram Moolenaar else
28364aea03ebSBram Moolenaar buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
28374aea03ebSBram Moolenaar TRUE, FALSE, FALSE));
28384aea03ebSBram Moolenaar if (buf == NULL)
28394aea03ebSBram Moolenaar return;
28404aea03ebSBram Moolenaar curwin->w_alt_fnum = buf->b_fnum;
28414aea03ebSBram Moolenaar return;
28424aea03ebSBram Moolenaar }
28434aea03ebSBram Moolenaar
28444aea03ebSBram Moolenaar if (name == '=')
28454aea03ebSBram Moolenaar {
28464aea03ebSBram Moolenaar char_u *p, *s;
28474aea03ebSBram Moolenaar
284871ccd03eSBram Moolenaar p = vim_strnsave(str, len);
28494aea03ebSBram Moolenaar if (p == NULL)
28504aea03ebSBram Moolenaar return;
28516b649ac4SBram Moolenaar if (must_append && expr_line != NULL)
28524aea03ebSBram Moolenaar {
28536b649ac4SBram Moolenaar s = concat_str(expr_line, p);
28544aea03ebSBram Moolenaar vim_free(p);
28554aea03ebSBram Moolenaar p = s;
28564aea03ebSBram Moolenaar }
2857b4bcea47SBram Moolenaar set_expr_line(p, NULL);
28584aea03ebSBram Moolenaar return;
28594aea03ebSBram Moolenaar }
28604aea03ebSBram Moolenaar
28614aea03ebSBram Moolenaar if (name == '_') // black hole: nothing to do
28624aea03ebSBram Moolenaar return;
28634aea03ebSBram Moolenaar
28644aea03ebSBram Moolenaar if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
28654aea03ebSBram Moolenaar &yank_type) == FAIL)
28664aea03ebSBram Moolenaar return;
28674aea03ebSBram Moolenaar
28684aea03ebSBram Moolenaar str_to_reg(y_current, yank_type, str, len, block_len, FALSE);
28694aea03ebSBram Moolenaar
28704aea03ebSBram Moolenaar finish_write_reg(name, old_y_previous, old_y_current);
28714aea03ebSBram Moolenaar }
28724aea03ebSBram Moolenaar #endif // FEAT_EVAL
28734aea03ebSBram Moolenaar
28744aea03ebSBram Moolenaar #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
28754aea03ebSBram Moolenaar /*
28764aea03ebSBram Moolenaar * Put a string into a register. When the register is not empty, the string
28774aea03ebSBram Moolenaar * is appended.
28784aea03ebSBram Moolenaar */
287945fffdf1SBram Moolenaar void
str_to_reg(yankreg_T * y_ptr,int yank_type,char_u * str,long len,long blocklen,int str_list)28804aea03ebSBram Moolenaar str_to_reg(
28814aea03ebSBram Moolenaar yankreg_T *y_ptr, // pointer to yank register
28824aea03ebSBram Moolenaar int yank_type, // MCHAR, MLINE, MBLOCK, MAUTO
28834aea03ebSBram Moolenaar char_u *str, // string to put in register
28844aea03ebSBram Moolenaar long len, // length of string
28854aea03ebSBram Moolenaar long blocklen, // width of Visual block
28864aea03ebSBram Moolenaar int str_list) // TRUE if str is char_u **
28874aea03ebSBram Moolenaar {
28884aea03ebSBram Moolenaar int type; // MCHAR, MLINE or MBLOCK
28894aea03ebSBram Moolenaar int lnum;
28904aea03ebSBram Moolenaar long start;
28914aea03ebSBram Moolenaar long i;
28924aea03ebSBram Moolenaar int extra;
28934aea03ebSBram Moolenaar int newlines; // number of lines added
28944aea03ebSBram Moolenaar int extraline = 0; // extra line at the end
28954aea03ebSBram Moolenaar int append = FALSE; // append to last line in register
28964aea03ebSBram Moolenaar char_u *s;
28974aea03ebSBram Moolenaar char_u **ss;
28984aea03ebSBram Moolenaar char_u **pp;
28994aea03ebSBram Moolenaar long maxlen;
29004aea03ebSBram Moolenaar
29014aea03ebSBram Moolenaar if (y_ptr->y_array == NULL) // NULL means empty register
29024aea03ebSBram Moolenaar y_ptr->y_size = 0;
29034aea03ebSBram Moolenaar
29044aea03ebSBram Moolenaar if (yank_type == MAUTO)
29054aea03ebSBram Moolenaar type = ((str_list || (len > 0 && (str[len - 1] == NL
29064aea03ebSBram Moolenaar || str[len - 1] == CAR)))
29074aea03ebSBram Moolenaar ? MLINE : MCHAR);
29084aea03ebSBram Moolenaar else
29094aea03ebSBram Moolenaar type = yank_type;
29104aea03ebSBram Moolenaar
29114aea03ebSBram Moolenaar // Count the number of lines within the string
29124aea03ebSBram Moolenaar newlines = 0;
29134aea03ebSBram Moolenaar if (str_list)
29144aea03ebSBram Moolenaar {
29154aea03ebSBram Moolenaar for (ss = (char_u **) str; *ss != NULL; ++ss)
29164aea03ebSBram Moolenaar ++newlines;
29174aea03ebSBram Moolenaar }
29184aea03ebSBram Moolenaar else
29194aea03ebSBram Moolenaar {
29204aea03ebSBram Moolenaar for (i = 0; i < len; i++)
29214aea03ebSBram Moolenaar if (str[i] == '\n')
29224aea03ebSBram Moolenaar ++newlines;
29234aea03ebSBram Moolenaar if (type == MCHAR || len == 0 || str[len - 1] != '\n')
29244aea03ebSBram Moolenaar {
29254aea03ebSBram Moolenaar extraline = 1;
29264aea03ebSBram Moolenaar ++newlines; // count extra newline at the end
29274aea03ebSBram Moolenaar }
29284aea03ebSBram Moolenaar if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
29294aea03ebSBram Moolenaar {
29304aea03ebSBram Moolenaar append = TRUE;
29314aea03ebSBram Moolenaar --newlines; // uncount newline when appending first line
29324aea03ebSBram Moolenaar }
29334aea03ebSBram Moolenaar }
29344aea03ebSBram Moolenaar
29354aea03ebSBram Moolenaar // Without any lines make the register empty.
29364aea03ebSBram Moolenaar if (y_ptr->y_size + newlines == 0)
29374aea03ebSBram Moolenaar {
29384aea03ebSBram Moolenaar VIM_CLEAR(y_ptr->y_array);
29394aea03ebSBram Moolenaar return;
29404aea03ebSBram Moolenaar }
29414aea03ebSBram Moolenaar
29424aea03ebSBram Moolenaar // Allocate an array to hold the pointers to the new register lines.
29434aea03ebSBram Moolenaar // If the register was not empty, move the existing lines to the new array.
29444aea03ebSBram Moolenaar pp = lalloc_clear((y_ptr->y_size + newlines) * sizeof(char_u *), TRUE);
29454aea03ebSBram Moolenaar if (pp == NULL) // out of memory
29464aea03ebSBram Moolenaar return;
29474aea03ebSBram Moolenaar for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
29484aea03ebSBram Moolenaar pp[lnum] = y_ptr->y_array[lnum];
29494aea03ebSBram Moolenaar vim_free(y_ptr->y_array);
29504aea03ebSBram Moolenaar y_ptr->y_array = pp;
29514aea03ebSBram Moolenaar maxlen = 0;
29524aea03ebSBram Moolenaar
29534aea03ebSBram Moolenaar // Find the end of each line and save it into the array.
29544aea03ebSBram Moolenaar if (str_list)
29554aea03ebSBram Moolenaar {
29564aea03ebSBram Moolenaar for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum)
29574aea03ebSBram Moolenaar {
29586c4c404cSBram Moolenaar pp[lnum] = vim_strsave(*ss);
29596c4c404cSBram Moolenaar if (type == MBLOCK)
29606c4c404cSBram Moolenaar {
29616c4c404cSBram Moolenaar int charlen = mb_string2cells(*ss, -1);
29626c4c404cSBram Moolenaar
29636e0b553fSBram Moolenaar if (charlen > maxlen)
29646e0b553fSBram Moolenaar maxlen = charlen;
29654aea03ebSBram Moolenaar }
29664aea03ebSBram Moolenaar }
29676c4c404cSBram Moolenaar }
29684aea03ebSBram Moolenaar else
29694aea03ebSBram Moolenaar {
29704aea03ebSBram Moolenaar for (start = 0; start < len + extraline; start += i + 1)
29714aea03ebSBram Moolenaar {
29726c4c404cSBram Moolenaar int charlen = 0;
29736c4c404cSBram Moolenaar
29744aea03ebSBram Moolenaar for (i = start; i < len; ++i) // find the end of the line
297524951a67SBram Moolenaar {
29764aea03ebSBram Moolenaar if (str[i] == '\n')
29774aea03ebSBram Moolenaar break;
29786c4c404cSBram Moolenaar if (type == MBLOCK)
297924951a67SBram Moolenaar charlen += mb_ptr2cells_len(str + i, len - i);
298024951a67SBram Moolenaar }
29814aea03ebSBram Moolenaar i -= start; // i is now length of line
29826e0b553fSBram Moolenaar if (charlen > maxlen)
29836e0b553fSBram Moolenaar maxlen = charlen;
29844aea03ebSBram Moolenaar if (append)
29854aea03ebSBram Moolenaar {
29864aea03ebSBram Moolenaar --lnum;
29874aea03ebSBram Moolenaar extra = (int)STRLEN(y_ptr->y_array[lnum]);
29884aea03ebSBram Moolenaar }
29894aea03ebSBram Moolenaar else
29904aea03ebSBram Moolenaar extra = 0;
29914aea03ebSBram Moolenaar s = alloc(i + extra + 1);
29924aea03ebSBram Moolenaar if (s == NULL)
29934aea03ebSBram Moolenaar break;
29944aea03ebSBram Moolenaar if (extra)
29954aea03ebSBram Moolenaar mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
29964aea03ebSBram Moolenaar if (append)
29974aea03ebSBram Moolenaar vim_free(y_ptr->y_array[lnum]);
299824951a67SBram Moolenaar if (i > 0)
29994aea03ebSBram Moolenaar mch_memmove(s + extra, str + start, (size_t)i);
30004aea03ebSBram Moolenaar extra += i;
30014aea03ebSBram Moolenaar s[extra] = NUL;
30024aea03ebSBram Moolenaar y_ptr->y_array[lnum++] = s;
30034aea03ebSBram Moolenaar while (--extra >= 0)
30044aea03ebSBram Moolenaar {
30054aea03ebSBram Moolenaar if (*s == NUL)
30064aea03ebSBram Moolenaar *s = '\n'; // replace NUL with newline
30074aea03ebSBram Moolenaar ++s;
30084aea03ebSBram Moolenaar }
30094aea03ebSBram Moolenaar append = FALSE; // only first line is appended
30104aea03ebSBram Moolenaar }
30114aea03ebSBram Moolenaar }
30124aea03ebSBram Moolenaar y_ptr->y_type = type;
30134aea03ebSBram Moolenaar y_ptr->y_size = lnum;
30144aea03ebSBram Moolenaar if (type == MBLOCK)
30154aea03ebSBram Moolenaar y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
30164aea03ebSBram Moolenaar else
30174aea03ebSBram Moolenaar y_ptr->y_width = 0;
30184aea03ebSBram Moolenaar # ifdef FEAT_VIMINFO
30194aea03ebSBram Moolenaar y_ptr->y_time_set = vim_time();
30204aea03ebSBram Moolenaar # endif
30214aea03ebSBram Moolenaar }
30224aea03ebSBram Moolenaar #endif // FEAT_CLIPBOARD || FEAT_EVAL || PROTO
3023