blob: c30787afefdc350315b5248d59f4280489faf1b2 [file] [log] [blame]
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * register.c: functions for managing registers
12 */
13
14#include "vim.h"
15
16/*
17 * Registers:
18 * 0 = unnamed register, for normal yanks and puts
19 * 1..9 = registers '1' to '9', for deletes
20 * 10..35 = registers 'a' to 'z' ('A' to 'Z' for appending)
21 * 36 = delete register '-'
22 * 37 = Selection register '*'. Only if FEAT_CLIPBOARD defined
23 * 38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined
24 */
25static yankreg_T y_regs[NUM_REGISTERS];
26
27static yankreg_T *y_current; // ptr to current yankreg
28static int y_append; // TRUE when appending
29static yankreg_T *y_previous = NULL; // ptr to last written yankreg
30
31static int stuff_yank(int, char_u *);
32static void put_reedit_in_typebuf(int silent);
33static int put_in_typebuf(char_u *s, int esc, int colon,
34 int silent);
Christian Brabandt544a38e2021-06-10 19:39:11 +020035static int yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +020036#ifdef FEAT_CLIPBOARD
37static void copy_yank_reg(yankreg_T *reg);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +020038#endif
39static void dis_msg(char_u *p, int skip_esc);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +020040
41 yankreg_T *
42get_y_regs(void)
43{
44 return y_regs;
45}
46
47 yankreg_T *
Bram Moolenaar45fffdf2020-03-24 21:42:01 +010048get_y_register(int reg)
49{
50 return &y_regs[reg];
51}
52
53 yankreg_T *
Bram Moolenaar4aea03e2019-09-25 22:37:17 +020054get_y_current(void)
55{
56 return y_current;
57}
58
59 yankreg_T *
60get_y_previous(void)
61{
62 return y_previous;
63}
64
65 void
Bram Moolenaar45fffdf2020-03-24 21:42:01 +010066set_y_current(yankreg_T *yreg)
67{
68 y_current = yreg;
69}
70
71 void
Bram Moolenaar4aea03e2019-09-25 22:37:17 +020072set_y_previous(yankreg_T *yreg)
73{
74 y_previous = yreg;
75}
76
77#if defined(FEAT_EVAL) || defined(PROTO)
78/*
79 * Keep the last expression line here, for repeating.
80 */
81static char_u *expr_line = NULL;
Bram Moolenaarb4bcea42020-10-28 13:53:50 +010082static exarg_T *expr_eap = NULL;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +020083
84/*
85 * Get an expression for the "\"=expr1" or "CTRL-R =expr1"
86 * Returns '=' when OK, NUL otherwise.
87 */
88 int
89get_expr_register(void)
90{
91 char_u *new_line;
92
93 new_line = getcmdline('=', 0L, 0, TRUE);
94 if (new_line == NULL)
95 return NUL;
96 if (*new_line == NUL) // use previous line
97 vim_free(new_line);
98 else
Bram Moolenaarb4bcea42020-10-28 13:53:50 +010099 set_expr_line(new_line, NULL);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200100 return '=';
101}
102
103/*
104 * Set the expression for the '=' register.
105 * Argument must be an allocated string.
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100106 * "eap" may be used if the next line needs to be checked when evaluating the
107 * expression.
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200108 */
109 void
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100110set_expr_line(char_u *new_line, exarg_T *eap)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200111{
112 vim_free(expr_line);
113 expr_line = new_line;
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100114 expr_eap = eap;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200115}
116
117/*
118 * Get the result of the '=' register expression.
119 * Returns a pointer to allocated memory, or NULL for failure.
120 */
121 char_u *
122get_expr_line(void)
123{
124 char_u *expr_copy;
125 char_u *rv;
126 static int nested = 0;
127
128 if (expr_line == NULL)
129 return NULL;
130
131 // Make a copy of the expression, because evaluating it may cause it to be
132 // changed.
133 expr_copy = vim_strsave(expr_line);
134 if (expr_copy == NULL)
135 return NULL;
136
137 // When we are invoked recursively limit the evaluation to 10 levels.
138 // Then return the string as-is.
139 if (nested >= 10)
140 return expr_copy;
141
142 ++nested;
Bram Moolenaarb4bcea42020-10-28 13:53:50 +0100143 rv = eval_to_string_eap(expr_copy, TRUE, expr_eap);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200144 --nested;
145 vim_free(expr_copy);
146 return rv;
147}
148
149/*
150 * Get the '=' register expression itself, without evaluating it.
151 */
152 static char_u *
153get_expr_line_src(void)
154{
155 if (expr_line == NULL)
156 return NULL;
157 return vim_strsave(expr_line);
158}
159#endif // FEAT_EVAL
160
161/*
162 * Check if 'regname' is a valid name of a yank register.
163 * Note: There is no check for 0 (default register), caller should do this
164 */
165 int
166valid_yank_reg(
167 int regname,
168 int writing) // if TRUE check for writable registers
169{
170 if ( (regname > 0 && ASCII_ISALNUM(regname))
171 || (!writing && vim_strchr((char_u *)
172#ifdef FEAT_EVAL
173 "/.%:="
174#else
175 "/.%:"
176#endif
177 , regname) != NULL)
178 || regname == '#'
179 || regname == '"'
180 || regname == '-'
181 || regname == '_'
182#ifdef FEAT_CLIPBOARD
183 || regname == '*'
184 || regname == '+'
185#endif
186#ifdef FEAT_DND
187 || (!writing && regname == '~')
188#endif
189 )
190 return TRUE;
191 return FALSE;
192}
193
194/*
195 * Set y_current and y_append, according to the value of "regname".
196 * Cannot handle the '_' register.
197 * Must only be called with a valid register name!
198 *
199 * If regname is 0 and writing, use register 0
200 * If regname is 0 and reading, use previous register
201 *
202 * Return TRUE when the register should be inserted literally (selection or
203 * clipboard).
204 */
205 int
206get_yank_register(int regname, int writing)
207{
208 int i;
209 int ret = FALSE;
210
211 y_append = FALSE;
212 if ((regname == 0 || regname == '"') && !writing && y_previous != NULL)
213 {
214 y_current = y_previous;
215 return ret;
216 }
217 i = regname;
218 if (VIM_ISDIGIT(i))
219 i -= '0';
220 else if (ASCII_ISLOWER(i))
221 i = CharOrdLow(i) + 10;
222 else if (ASCII_ISUPPER(i))
223 {
224 i = CharOrdUp(i) + 10;
225 y_append = TRUE;
226 }
227 else if (regname == '-')
228 i = DELETION_REGISTER;
229#ifdef FEAT_CLIPBOARD
230 // When selection is not available, use register 0 instead of '*'
231 else if (clip_star.available && regname == '*')
232 {
233 i = STAR_REGISTER;
234 ret = TRUE;
235 }
236 // When clipboard is not available, use register 0 instead of '+'
237 else if (clip_plus.available && regname == '+')
238 {
239 i = PLUS_REGISTER;
240 ret = TRUE;
241 }
242#endif
243#ifdef FEAT_DND
244 else if (!writing && regname == '~')
245 i = TILDE_REGISTER;
246#endif
247 else // not 0-9, a-z, A-Z or '-': use register 0
248 i = 0;
249 y_current = &(y_regs[i]);
250 if (writing) // remember the register we write into for do_put()
251 y_previous = y_current;
252 return ret;
253}
254
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200255/*
256 * Obtain the contents of a "normal" register. The register is made empty.
257 * The returned pointer has allocated memory, use put_register() later.
258 */
259 void *
260get_register(
261 int name,
262 int copy) // make a copy, if FALSE make register empty.
263{
264 yankreg_T *reg;
265 int i;
266
267#ifdef FEAT_CLIPBOARD
268 // When Visual area changed, may have to update selection. Obtain the
269 // selection too.
270 if (name == '*' && clip_star.available)
271 {
272 if (clip_isautosel_star())
273 clip_update_selection(&clip_star);
274 may_get_selection(name);
275 }
276 if (name == '+' && clip_plus.available)
277 {
278 if (clip_isautosel_plus())
279 clip_update_selection(&clip_plus);
280 may_get_selection(name);
281 }
282#endif
283
284 get_yank_register(name, 0);
285 reg = ALLOC_ONE(yankreg_T);
286 if (reg != NULL)
287 {
288 *reg = *y_current;
289 if (copy)
290 {
291 // If we run out of memory some or all of the lines are empty.
292 if (reg->y_size == 0)
293 reg->y_array = NULL;
294 else
295 reg->y_array = ALLOC_MULT(char_u *, reg->y_size);
296 if (reg->y_array != NULL)
297 {
298 for (i = 0; i < reg->y_size; ++i)
299 reg->y_array[i] = vim_strsave(y_current->y_array[i]);
300 }
301 }
302 else
303 y_current->y_array = NULL;
304 }
305 return (void *)reg;
306}
307
308/*
309 * Put "reg" into register "name". Free any previous contents and "reg".
310 */
311 void
312put_register(int name, void *reg)
313{
314 get_yank_register(name, 0);
315 free_yank_all();
316 *y_current = *(yankreg_T *)reg;
317 vim_free(reg);
318
319#ifdef FEAT_CLIPBOARD
320 // Send text written to clipboard register to the clipboard.
321 may_set_selection();
322#endif
323}
324
Bram Moolenaarfccbf062020-11-26 20:34:00 +0100325#if defined(FEAT_CLIPBOARD) || defined(PROTO)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200326 void
327free_register(void *reg)
328{
329 yankreg_T tmp;
330
331 tmp = *y_current;
332 *y_current = *(yankreg_T *)reg;
333 free_yank_all();
334 vim_free(reg);
335 *y_current = tmp;
336}
337#endif
338
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200339/*
340 * return TRUE if the current yank register has type MLINE
341 */
342 int
343yank_register_mline(int regname)
344{
345 if (regname != 0 && !valid_yank_reg(regname, FALSE))
346 return FALSE;
347 if (regname == '_') // black hole is always empty
348 return FALSE;
349 get_yank_register(regname, FALSE);
350 return (y_current->y_type == MLINE);
351}
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200352
353/*
354 * Start or stop recording into a yank register.
355 *
356 * Return FAIL for failure, OK otherwise.
357 */
358 int
359do_record(int c)
360{
361 char_u *p;
362 static int regname;
363 yankreg_T *old_y_previous, *old_y_current;
364 int retval;
365
366 if (reg_recording == 0) // start recording
367 {
368 // registers 0-9, a-z and " are allowed
369 if (c < 0 || (!ASCII_ISALNUM(c) && c != '"'))
370 retval = FAIL;
371 else
372 {
373 reg_recording = c;
374 showmode();
375 regname = c;
376 retval = OK;
377 }
378 }
379 else // stop recording
380 {
381 // Get the recorded key hits. K_SPECIAL and CSI will be escaped, this
382 // needs to be removed again to put it in a register. exec_reg then
383 // adds the escaping back later.
384 reg_recording = 0;
385 msg("");
386 p = get_recorded();
387 if (p == NULL)
388 retval = FAIL;
389 else
390 {
391 // Remove escaping for CSI and K_SPECIAL in multi-byte chars.
392 vim_unescape_csi(p);
393
394 // We don't want to change the default register here, so save and
395 // restore the current register name.
396 old_y_previous = y_previous;
397 old_y_current = y_current;
398
399 retval = stuff_yank(regname, p);
400
401 y_previous = old_y_previous;
402 y_current = old_y_current;
403 }
404 }
405 return retval;
406}
407
408/*
409 * Stuff string "p" into yank register "regname" as a single line (append if
410 * uppercase). "p" must have been alloced.
411 *
412 * return FAIL for failure, OK otherwise
413 */
414 static int
415stuff_yank(int regname, char_u *p)
416{
417 char_u *lp;
418 char_u **pp;
419
420 // check for read-only register
421 if (regname != 0 && !valid_yank_reg(regname, TRUE))
422 {
423 vim_free(p);
424 return FAIL;
425 }
426 if (regname == '_') // black hole: don't do anything
427 {
428 vim_free(p);
429 return OK;
430 }
431 get_yank_register(regname, TRUE);
432 if (y_append && y_current->y_array != NULL)
433 {
434 pp = &(y_current->y_array[y_current->y_size - 1]);
435 lp = alloc(STRLEN(*pp) + STRLEN(p) + 1);
436 if (lp == NULL)
437 {
438 vim_free(p);
439 return FAIL;
440 }
441 STRCPY(lp, *pp);
442 STRCAT(lp, p);
443 vim_free(p);
444 vim_free(*pp);
445 *pp = lp;
446 }
447 else
448 {
449 free_yank_all();
450 if ((y_current->y_array = ALLOC_ONE(char_u *)) == NULL)
451 {
452 vim_free(p);
453 return FAIL;
454 }
455 y_current->y_array[0] = p;
456 y_current->y_size = 1;
457 y_current->y_type = MCHAR; // used to be MLINE, why?
458#ifdef FEAT_VIMINFO
459 y_current->y_time_set = vim_time();
460#endif
461 }
462 return OK;
463}
464
465static int execreg_lastc = NUL;
466
467 int
468get_execreg_lastc(void)
469{
470 return execreg_lastc;
471}
472
473 void
474set_execreg_lastc(int lastc)
475{
476 execreg_lastc = lastc;
477}
478
479/*
Bram Moolenaar856c1112020-06-17 21:47:23 +0200480 * When executing a register as a series of ex-commands, if the
481 * line-continuation character is used for a line, then join it with one or
482 * more previous lines. Note that lines are processed backwards starting from
483 * the last line in the register.
484 *
485 * Arguments:
486 * lines - list of lines in the register
487 * idx - index of the line starting with \ or "\. Join this line with all the
488 * immediate predecessor lines that start with a \ and the first line
489 * that doesn't start with a \. Lines that start with a comment "\
490 * character are ignored.
491 *
492 * Returns the concatenated line. The index of the line that should be
493 * processed next is returned in idx.
494 */
495 static char_u *
496execreg_line_continuation(char_u **lines, long *idx)
497{
498 garray_T ga;
499 long i = *idx;
500 char_u *p;
501 int cmd_start;
502 int cmd_end = i;
503 int j;
504 char_u *str;
505
506 ga_init2(&ga, (int)sizeof(char_u), 400);
507
508 // search backwards to find the first line of this command.
509 // Any line not starting with \ or "\ is the start of the
510 // command.
511 while (--i > 0)
512 {
513 p = skipwhite(lines[i]);
514 if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' '))
515 break;
516 }
517 cmd_start = i;
518
519 // join all the lines
520 ga_concat(&ga, lines[cmd_start]);
521 for (j = cmd_start + 1; j <= cmd_end; j++)
522 {
523 p = skipwhite(lines[j]);
524 if (*p == '\\')
525 {
526 // Adjust the growsize to the current length to
527 // speed up concatenating many lines.
528 if (ga.ga_len > 400)
529 {
530 if (ga.ga_len > 8000)
531 ga.ga_growsize = 8000;
532 else
533 ga.ga_growsize = ga.ga_len;
534 }
535 ga_concat(&ga, p + 1);
536 }
537 }
538 ga_append(&ga, NUL);
539 str = vim_strsave(ga.ga_data);
540 ga_clear(&ga);
541
542 *idx = i;
543 return str;
544}
545
546/*
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200547 * Execute a yank register: copy it into the stuff buffer.
548 *
549 * Return FAIL for failure, OK otherwise.
550 */
551 int
552do_execreg(
553 int regname,
554 int colon, // insert ':' before each line
555 int addcr, // always add '\n' to end of line
556 int silent) // set "silent" flag in typeahead buffer
557{
558 long i;
559 char_u *p;
560 int retval = OK;
561 int remap;
562
563 // repeat previous one
564 if (regname == '@')
565 {
566 if (execreg_lastc == NUL)
567 {
568 emsg(_("E748: No previously used register"));
569 return FAIL;
570 }
571 regname = execreg_lastc;
572 }
573 // check for valid regname
574 if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
575 {
576 emsg_invreg(regname);
577 return FAIL;
578 }
579 execreg_lastc = regname;
580
581#ifdef FEAT_CLIPBOARD
582 regname = may_get_selection(regname);
583#endif
584
585 // black hole: don't stuff anything
586 if (regname == '_')
587 return OK;
588
589 // use last command line
590 if (regname == ':')
591 {
592 if (last_cmdline == NULL)
593 {
594 emsg(_(e_nolastcmd));
595 return FAIL;
596 }
597 // don't keep the cmdline containing @:
598 VIM_CLEAR(new_last_cmdline);
599 // Escape all control characters with a CTRL-V
600 p = vim_strsave_escaped_ext(last_cmdline,
601 (char_u *)"\001\002\003\004\005\006\007"
602 "\010\011\012\013\014\015\016\017"
603 "\020\021\022\023\024\025\026\027"
604 "\030\031\032\033\034\035\036\037",
605 Ctrl_V, FALSE);
606 if (p != NULL)
607 {
608 // When in Visual mode "'<,'>" will be prepended to the command.
609 // Remove it when it's already there.
610 if (VIsual_active && STRNCMP(p, "'<,'>", 5) == 0)
611 retval = put_in_typebuf(p + 5, TRUE, TRUE, silent);
612 else
613 retval = put_in_typebuf(p, TRUE, TRUE, silent);
614 }
615 vim_free(p);
616 }
617#ifdef FEAT_EVAL
618 else if (regname == '=')
619 {
620 p = get_expr_line();
621 if (p == NULL)
622 return FAIL;
623 retval = put_in_typebuf(p, TRUE, colon, silent);
624 vim_free(p);
625 }
626#endif
627 else if (regname == '.') // use last inserted text
628 {
629 p = get_last_insert_save();
630 if (p == NULL)
631 {
632 emsg(_(e_noinstext));
633 return FAIL;
634 }
635 retval = put_in_typebuf(p, FALSE, colon, silent);
636 vim_free(p);
637 }
638 else
639 {
640 get_yank_register(regname, FALSE);
641 if (y_current->y_array == NULL)
642 return FAIL;
643
Bram Moolenaar4b96df52020-01-26 22:00:26 +0100644 // Disallow remapping for ":@r".
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200645 remap = colon ? REMAP_NONE : REMAP_YES;
646
647 // Insert lines into typeahead buffer, from last one to first one.
648 put_reedit_in_typebuf(silent);
649 for (i = y_current->y_size; --i >= 0; )
650 {
651 char_u *escaped;
Bram Moolenaar856c1112020-06-17 21:47:23 +0200652 char_u *str;
653 int free_str = FALSE;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200654
655 // insert NL between lines and after last line if type is MLINE
656 if (y_current->y_type == MLINE || i < y_current->y_size - 1
657 || addcr)
658 {
659 if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL)
660 return FAIL;
661 }
Bram Moolenaar856c1112020-06-17 21:47:23 +0200662
663 // Handle line-continuation for :@<register>
664 str = y_current->y_array[i];
665 if (colon && i > 0)
666 {
667 p = skipwhite(str);
668 if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' '))
669 {
670 str = execreg_line_continuation(y_current->y_array, &i);
671 if (str == NULL)
672 return FAIL;
673 free_str = TRUE;
674 }
675 }
676 escaped = vim_strsave_escape_csi(str);
677 if (free_str)
678 vim_free(str);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200679 if (escaped == NULL)
680 return FAIL;
681 retval = ins_typebuf(escaped, remap, 0, TRUE, silent);
682 vim_free(escaped);
683 if (retval == FAIL)
684 return FAIL;
685 if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, silent)
686 == FAIL)
687 return FAIL;
688 }
689 reg_executing = regname == 0 ? '"' : regname; // disable "q" command
690 }
691 return retval;
692}
693
694/*
695 * If "restart_edit" is not zero, put it in the typeahead buffer, so that it's
696 * used only after other typeahead has been processed.
697 */
698 static void
699put_reedit_in_typebuf(int silent)
700{
701 char_u buf[3];
702
703 if (restart_edit != NUL)
704 {
705 if (restart_edit == 'V')
706 {
707 buf[0] = 'g';
708 buf[1] = 'R';
709 buf[2] = NUL;
710 }
711 else
712 {
713 buf[0] = restart_edit == 'I' ? 'i' : restart_edit;
714 buf[1] = NUL;
715 }
716 if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, silent) == OK)
717 restart_edit = NUL;
718 }
719}
720
721/*
722 * Insert register contents "s" into the typeahead buffer, so that it will be
723 * executed again.
724 * When "esc" is TRUE it is to be taken literally: Escape CSI characters and
725 * no remapping.
726 */
727 static int
728put_in_typebuf(
729 char_u *s,
730 int esc,
731 int colon, // add ':' before the line
732 int silent)
733{
734 int retval = OK;
735
736 put_reedit_in_typebuf(silent);
737 if (colon)
738 retval = ins_typebuf((char_u *)"\n", REMAP_NONE, 0, TRUE, silent);
739 if (retval == OK)
740 {
741 char_u *p;
742
743 if (esc)
744 p = vim_strsave_escape_csi(s);
745 else
746 p = s;
747 if (p == NULL)
748 retval = FAIL;
749 else
750 retval = ins_typebuf(p, esc ? REMAP_NONE : REMAP_YES,
751 0, TRUE, silent);
752 if (esc)
753 vim_free(p);
754 }
755 if (colon && retval == OK)
756 retval = ins_typebuf((char_u *)":", REMAP_NONE, 0, TRUE, silent);
757 return retval;
758}
759
760/*
761 * Insert a yank register: copy it into the Read buffer.
762 * Used by CTRL-R command and middle mouse button in insert mode.
763 *
764 * return FAIL for failure, OK otherwise
765 */
766 int
767insert_reg(
768 int regname,
769 int literally_arg) // insert literally, not as if typed
770{
771 long i;
772 int retval = OK;
773 char_u *arg;
774 int allocated;
775 int literally = literally_arg;
776
777 // It is possible to get into an endless loop by having CTRL-R a in
778 // register a and then, in insert mode, doing CTRL-R a.
779 // If you hit CTRL-C, the loop will be broken here.
780 ui_breakcheck();
781 if (got_int)
782 return FAIL;
783
784 // check for valid regname
785 if (regname != NUL && !valid_yank_reg(regname, FALSE))
786 return FAIL;
787
788#ifdef FEAT_CLIPBOARD
789 regname = may_get_selection(regname);
790#endif
791
792 if (regname == '.') // insert last inserted text
793 retval = stuff_inserted(NUL, 1L, TRUE);
794 else if (get_spec_reg(regname, &arg, &allocated, TRUE))
795 {
796 if (arg == NULL)
797 return FAIL;
798 stuffescaped(arg, literally);
799 if (allocated)
800 vim_free(arg);
801 }
802 else // name or number register
803 {
804 if (get_yank_register(regname, FALSE))
805 literally = TRUE;
806 if (y_current->y_array == NULL)
807 retval = FAIL;
808 else
809 {
810 for (i = 0; i < y_current->y_size; ++i)
811 {
Bram Moolenaar032a2d02020-12-22 17:59:35 +0100812 if (regname == '-')
813 {
814 AppendCharToRedobuff(Ctrl_R);
815 AppendCharToRedobuff(regname);
816 do_put(regname, NULL, BACKWARD, 1L, PUT_CURSEND);
817 }
818 else
819 stuffescaped(y_current->y_array[i], literally);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200820 // Insert a newline between lines and after last line if
821 // y_type is MLINE.
822 if (y_current->y_type == MLINE || i < y_current->y_size - 1)
823 stuffcharReadbuff('\n');
824 }
825 }
826 }
827
828 return retval;
829}
830
831/*
832 * If "regname" is a special register, return TRUE and store a pointer to its
833 * value in "argp".
834 */
835 int
836get_spec_reg(
837 int regname,
838 char_u **argp,
839 int *allocated, // return: TRUE when value was allocated
840 int errmsg) // give error message when failing
841{
842 int cnt;
843
844 *argp = NULL;
845 *allocated = FALSE;
846 switch (regname)
847 {
848 case '%': // file name
849 if (errmsg)
850 check_fname(); // will give emsg if not set
851 *argp = curbuf->b_fname;
852 return TRUE;
853
854 case '#': // alternate file name
855 *argp = getaltfname(errmsg); // may give emsg if not set
856 return TRUE;
857
858#ifdef FEAT_EVAL
859 case '=': // result of expression
860 *argp = get_expr_line();
861 *allocated = TRUE;
862 return TRUE;
863#endif
864
865 case ':': // last command line
866 if (last_cmdline == NULL && errmsg)
867 emsg(_(e_nolastcmd));
868 *argp = last_cmdline;
869 return TRUE;
870
871 case '/': // last search-pattern
872 if (last_search_pat() == NULL && errmsg)
873 emsg(_(e_noprevre));
874 *argp = last_search_pat();
875 return TRUE;
876
877 case '.': // last inserted text
878 *argp = get_last_insert_save();
879 *allocated = TRUE;
880 if (*argp == NULL && errmsg)
881 emsg(_(e_noinstext));
882 return TRUE;
883
884#ifdef FEAT_SEARCHPATH
885 case Ctrl_F: // Filename under cursor
886 case Ctrl_P: // Path under cursor, expand via "path"
887 if (!errmsg)
888 return FALSE;
889 *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
890 | (regname == Ctrl_P ? FNAME_EXP : 0), 1L, NULL);
891 *allocated = TRUE;
892 return TRUE;
893#endif
894
895 case Ctrl_W: // word under cursor
896 case Ctrl_A: // WORD (mnemonic All) under cursor
897 if (!errmsg)
898 return FALSE;
899 cnt = find_ident_under_cursor(argp, regname == Ctrl_W
900 ? (FIND_IDENT|FIND_STRING) : FIND_STRING);
901 *argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
902 *allocated = TRUE;
903 return TRUE;
904
905 case Ctrl_L: // Line under cursor
906 if (!errmsg)
907 return FALSE;
908
909 *argp = ml_get_buf(curwin->w_buffer,
910 curwin->w_cursor.lnum, FALSE);
911 return TRUE;
912
913 case '_': // black hole: always empty
914 *argp = (char_u *)"";
915 return TRUE;
916 }
917
918 return FALSE;
919}
920
921/*
922 * Paste a yank register into the command line.
923 * Only for non-special registers.
924 * Used by CTRL-R command in command-line mode
925 * insert_reg() can't be used here, because special characters from the
926 * register contents will be interpreted as commands.
927 *
928 * return FAIL for failure, OK otherwise
929 */
930 int
931cmdline_paste_reg(
932 int regname,
933 int literally_arg, // Insert text literally instead of "as typed"
934 int remcr) // don't add CR characters
935{
936 long i;
937 int literally = literally_arg;
938
939 if (get_yank_register(regname, FALSE))
940 literally = TRUE;
941 if (y_current->y_array == NULL)
942 return FAIL;
943
944 for (i = 0; i < y_current->y_size; ++i)
945 {
946 cmdline_paste_str(y_current->y_array[i], literally);
947
948 // Insert ^M between lines and after last line if type is MLINE.
949 // Don't do this when "remcr" is TRUE.
950 if ((y_current->y_type == MLINE || i < y_current->y_size - 1) && !remcr)
951 cmdline_paste_str((char_u *)"\r", literally);
952
953 // Check for CTRL-C, in case someone tries to paste a few thousand
954 // lines and gets bored.
955 ui_breakcheck();
956 if (got_int)
957 return FAIL;
958 }
959 return OK;
960}
961
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200962/*
963 * Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
964 */
965 void
966shift_delete_registers()
967{
968 int n;
969
970 y_current = &y_regs[9];
971 free_yank_all(); // free register nine
972 for (n = 9; n > 1; --n)
973 y_regs[n] = y_regs[n - 1];
974 y_current = &y_regs[1];
975 if (!y_append)
976 y_previous = y_current;
977 y_regs[1].y_array = NULL; // set register one to empty
978}
979
980#if defined(FEAT_EVAL)
981 void
982yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
983{
984 static int recursive = FALSE;
985 dict_T *v_event;
986 list_T *list;
987 int n;
988 char_u buf[NUMBUFLEN + 2];
989 long reglen = 0;
990
991 if (recursive)
992 return;
993
994 v_event = get_vim_var_dict(VV_EVENT);
995
996 list = list_alloc();
997 if (list == NULL)
998 return;
999 for (n = 0; n < reg->y_size; n++)
1000 list_append_string(list, reg->y_array[n], -1);
1001 list->lv_lock = VAR_FIXED;
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001002 (void)dict_add_list(v_event, "regcontents", list);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001003
1004 buf[0] = (char_u)oap->regname;
1005 buf[1] = NUL;
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001006 (void)dict_add_string(v_event, "regname", buf);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001007
1008 buf[0] = get_op_char(oap->op_type);
1009 buf[1] = get_extra_op_char(oap->op_type);
1010 buf[2] = NUL;
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001011 (void)dict_add_string(v_event, "operator", buf);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001012
1013 buf[0] = NUL;
1014 buf[1] = NUL;
1015 switch (get_reg_type(oap->regname, &reglen))
1016 {
1017 case MLINE: buf[0] = 'V'; break;
1018 case MCHAR: buf[0] = 'v'; break;
1019 case MBLOCK:
1020 vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
1021 reglen + 1);
1022 break;
1023 }
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001024 (void)dict_add_string(v_event, "regtype", buf);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001025
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001026 (void)dict_add_bool(v_event, "visual", oap->is_VIsual);
Bram Moolenaar37d16732020-06-12 22:09:01 +02001027
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001028 // Lock the dictionary and its keys
1029 dict_set_items_ro(v_event);
1030
1031 recursive = TRUE;
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02001032 textwinlock++;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001033 apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02001034 textwinlock--;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001035 recursive = FALSE;
1036
1037 // Empty the dictionary, v:event is still valid
1038 dict_free_contents(v_event);
1039 hash_init(&v_event->dv_hashtab);
1040}
1041#endif
1042
1043/*
1044 * set all the yank registers to empty (called from main())
1045 */
1046 void
1047init_yank(void)
1048{
1049 int i;
1050
1051 for (i = 0; i < NUM_REGISTERS; ++i)
1052 y_regs[i].y_array = NULL;
1053}
1054
1055#if defined(EXITFREE) || defined(PROTO)
1056 void
1057clear_registers(void)
1058{
1059 int i;
1060
1061 for (i = 0; i < NUM_REGISTERS; ++i)
1062 {
1063 y_current = &y_regs[i];
1064 if (y_current->y_array != NULL)
1065 free_yank_all();
1066 }
1067}
1068#endif
1069
1070/*
1071 * Free "n" lines from the current yank register.
1072 * Called for normal freeing and in case of error.
1073 */
1074 static void
1075free_yank(long n)
1076{
1077 if (y_current->y_array != NULL)
1078 {
1079 long i;
1080
1081 for (i = n; --i >= 0; )
1082 {
1083#ifdef AMIGA // only for very slow machines
1084 if ((i & 1023) == 1023) // this may take a while
1085 {
1086 // This message should never cause a hit-return message.
1087 // Overwrite this message with any next message.
1088 ++no_wait_return;
1089 smsg(_("freeing %ld lines"), i + 1);
1090 --no_wait_return;
1091 msg_didout = FALSE;
1092 msg_col = 0;
1093 }
1094#endif
1095 vim_free(y_current->y_array[i]);
1096 }
1097 VIM_CLEAR(y_current->y_array);
1098#ifdef AMIGA
1099 if (n >= 1000)
1100 msg("");
1101#endif
1102 }
1103}
1104
Bram Moolenaar45fffdf2020-03-24 21:42:01 +01001105 void
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001106free_yank_all(void)
1107{
1108 free_yank(y_current->y_size);
1109}
1110
1111/*
1112 * Yank the text between "oap->start" and "oap->end" into a yank register.
1113 * If we are to append (uppercase register), we first yank into a new yank
1114 * register and then concatenate the old and the new one (so we keep the old
1115 * one in case of out-of-memory).
1116 *
1117 * Return FAIL for failure, OK otherwise.
1118 */
1119 int
1120op_yank(oparg_T *oap, int deleting, int mess)
1121{
1122 long y_idx; // index in y_array[]
1123 yankreg_T *curr; // copy of y_current
1124 yankreg_T newreg; // new yank register when appending
1125 char_u **new_ptr;
1126 linenr_T lnum; // current line number
1127 long j;
1128 int yanktype = oap->motion_type;
1129 long yanklines = oap->line_count;
1130 linenr_T yankendlnum = oap->end.lnum;
1131 char_u *p;
1132 char_u *pnew;
1133 struct block_def bd;
1134#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1135 int did_star = FALSE;
1136#endif
1137
1138 // check for read-only register
1139 if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
1140 {
1141 beep_flush();
1142 return FAIL;
1143 }
1144 if (oap->regname == '_') // black hole: nothing to do
1145 return OK;
1146
1147#ifdef FEAT_CLIPBOARD
1148 if (!clip_star.available && oap->regname == '*')
1149 oap->regname = 0;
1150 else if (!clip_plus.available && oap->regname == '+')
1151 oap->regname = 0;
1152#endif
1153
1154 if (!deleting) // op_delete() already set y_current
1155 get_yank_register(oap->regname, TRUE);
1156
1157 curr = y_current;
1158 // append to existing contents
1159 if (y_append && y_current->y_array != NULL)
1160 y_current = &newreg;
1161 else
1162 free_yank_all(); // free previously yanked lines
1163
1164 // If the cursor was in column 1 before and after the movement, and the
1165 // operator is not inclusive, the yank is always linewise.
1166 if ( oap->motion_type == MCHAR
1167 && oap->start.col == 0
1168 && !oap->inclusive
1169 && (!oap->is_VIsual || *p_sel == 'o')
1170 && !oap->block_mode
1171 && oap->end.col == 0
1172 && yanklines > 1)
1173 {
1174 yanktype = MLINE;
1175 --yankendlnum;
1176 --yanklines;
1177 }
1178
1179 y_current->y_size = yanklines;
1180 y_current->y_type = yanktype; // set the yank register type
1181 y_current->y_width = 0;
1182 y_current->y_array = lalloc_clear(sizeof(char_u *) * yanklines, TRUE);
1183 if (y_current->y_array == NULL)
1184 {
1185 y_current = curr;
1186 return FAIL;
1187 }
1188#ifdef FEAT_VIMINFO
1189 y_current->y_time_set = vim_time();
1190#endif
1191
1192 y_idx = 0;
1193 lnum = oap->start.lnum;
1194
1195 if (oap->block_mode)
1196 {
1197 // Visual block mode
1198 y_current->y_type = MBLOCK; // set the yank register type
1199 y_current->y_width = oap->end_vcol - oap->start_vcol;
1200
1201 if (curwin->w_curswant == MAXCOL && y_current->y_width > 0)
1202 y_current->y_width--;
1203 }
1204
1205 for ( ; lnum <= yankendlnum; lnum++, y_idx++)
1206 {
1207 switch (y_current->y_type)
1208 {
1209 case MBLOCK:
1210 block_prep(oap, &bd, lnum, FALSE);
Christian Brabandt544a38e2021-06-10 19:39:11 +02001211 if (yank_copy_line(&bd, y_idx, oap->excl_tr_ws) == FAIL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001212 goto fail;
1213 break;
1214
1215 case MLINE:
1216 if ((y_current->y_array[y_idx] =
Christian Brabandt544a38e2021-06-10 19:39:11 +02001217 vim_strsave(ml_get(lnum))) == NULL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001218 goto fail;
1219 break;
1220
1221 case MCHAR:
1222 {
1223 colnr_T startcol = 0, endcol = MAXCOL;
Christian Brabandt544a38e2021-06-10 19:39:11 +02001224 int is_oneChar = FALSE;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001225 colnr_T cs, ce;
1226
1227 p = ml_get(lnum);
1228 bd.startspaces = 0;
1229 bd.endspaces = 0;
1230
1231 if (lnum == oap->start.lnum)
1232 {
1233 startcol = oap->start.col;
1234 if (virtual_op)
1235 {
1236 getvcol(curwin, &oap->start, &cs, NULL, &ce);
1237 if (ce != cs && oap->start.coladd > 0)
1238 {
1239 // Part of a tab selected -- but don't
1240 // double-count it.
1241 bd.startspaces = (ce - cs + 1)
1242 - oap->start.coladd;
1243 startcol++;
1244 }
1245 }
1246 }
1247
1248 if (lnum == oap->end.lnum)
1249 {
1250 endcol = oap->end.col;
1251 if (virtual_op)
1252 {
1253 getvcol(curwin, &oap->end, &cs, NULL, &ce);
1254 if (p[endcol] == NUL || (cs + oap->end.coladd < ce
1255 // Don't add space for double-wide
1256 // char; endcol will be on last byte
1257 // of multi-byte char.
1258 && (*mb_head_off)(p, p + endcol) == 0))
1259 {
1260 if (oap->start.lnum == oap->end.lnum
1261 && oap->start.col == oap->end.col)
1262 {
1263 // Special case: inside a single char
1264 is_oneChar = TRUE;
1265 bd.startspaces = oap->end.coladd
1266 - oap->start.coladd + oap->inclusive;
1267 endcol = startcol;
1268 }
1269 else
1270 {
1271 bd.endspaces = oap->end.coladd
1272 + oap->inclusive;
1273 endcol -= oap->inclusive;
1274 }
1275 }
1276 }
1277 }
1278 if (endcol == MAXCOL)
1279 endcol = (colnr_T)STRLEN(p);
1280 if (startcol > endcol || is_oneChar)
1281 bd.textlen = 0;
1282 else
1283 bd.textlen = endcol - startcol + oap->inclusive;
1284 bd.textstart = p + startcol;
Christian Brabandt544a38e2021-06-10 19:39:11 +02001285 if (yank_copy_line(&bd, y_idx, FALSE) == FAIL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001286 goto fail;
1287 break;
1288 }
1289 // NOTREACHED
1290 }
1291 }
1292
1293 if (curr != y_current) // append the new block to the old block
1294 {
1295 new_ptr = ALLOC_MULT(char_u *, curr->y_size + y_current->y_size);
1296 if (new_ptr == NULL)
1297 goto fail;
1298 for (j = 0; j < curr->y_size; ++j)
1299 new_ptr[j] = curr->y_array[j];
1300 vim_free(curr->y_array);
1301 curr->y_array = new_ptr;
1302#ifdef FEAT_VIMINFO
1303 curr->y_time_set = vim_time();
1304#endif
1305
1306 if (yanktype == MLINE) // MLINE overrides MCHAR and MBLOCK
1307 curr->y_type = MLINE;
1308
1309 // Concatenate the last line of the old block with the first line of
1310 // the new block, unless being Vi compatible.
1311 if (curr->y_type == MCHAR && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL)
1312 {
1313 pnew = alloc(STRLEN(curr->y_array[curr->y_size - 1])
1314 + STRLEN(y_current->y_array[0]) + 1);
1315 if (pnew == NULL)
1316 {
1317 y_idx = y_current->y_size - 1;
1318 goto fail;
1319 }
1320 STRCPY(pnew, curr->y_array[--j]);
1321 STRCAT(pnew, y_current->y_array[0]);
1322 vim_free(curr->y_array[j]);
1323 vim_free(y_current->y_array[0]);
1324 curr->y_array[j++] = pnew;
1325 y_idx = 1;
1326 }
1327 else
1328 y_idx = 0;
1329 while (y_idx < y_current->y_size)
1330 curr->y_array[j++] = y_current->y_array[y_idx++];
1331 curr->y_size = j;
1332 vim_free(y_current->y_array);
1333 y_current = curr;
1334 }
1335 if (curwin->w_p_rnu)
1336 redraw_later(SOME_VALID); // cursor moved to start
1337 if (mess) // Display message about yank?
1338 {
1339 if (yanktype == MCHAR
1340 && !oap->block_mode
1341 && yanklines == 1)
1342 yanklines = 0;
Bram Moolenaar32aa1022019-11-02 22:54:41 +01001343 // Some versions of Vi use ">=" here, some don't...
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001344 if (yanklines > p_report)
1345 {
1346 char namebuf[100];
1347
1348 if (oap->regname == NUL)
1349 *namebuf = NUL;
1350 else
1351 vim_snprintf(namebuf, sizeof(namebuf),
1352 _(" into \"%c"), oap->regname);
1353
1354 // redisplay now, so message is not deleted
1355 update_topline_redraw();
1356 if (oap->block_mode)
1357 {
1358 smsg(NGETTEXT("block of %ld line yanked%s",
1359 "block of %ld lines yanked%s", yanklines),
1360 yanklines, namebuf);
1361 }
1362 else
1363 {
1364 smsg(NGETTEXT("%ld line yanked%s",
1365 "%ld lines yanked%s", yanklines),
1366 yanklines, namebuf);
1367 }
1368 }
1369 }
1370
Bram Moolenaare1004402020-10-24 20:49:43 +02001371 if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001372 {
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001373 // Set "'[" and "']" marks.
1374 curbuf->b_op_start = oap->start;
1375 curbuf->b_op_end = oap->end;
1376 if (yanktype == MLINE && !oap->block_mode)
1377 {
1378 curbuf->b_op_start.col = 0;
1379 curbuf->b_op_end.col = MAXCOL;
1380 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001381 }
1382
1383#ifdef FEAT_CLIPBOARD
1384 // If we were yanking to the '*' register, send result to clipboard.
1385 // If no register was specified, and "unnamed" in 'clipboard', make a copy
1386 // to the '*' register.
1387 if (clip_star.available
1388 && (curr == &(y_regs[STAR_REGISTER])
1389 || (!deleting && oap->regname == 0
1390 && ((clip_unnamed | clip_unnamed_saved) & CLIP_UNNAMED))))
1391 {
1392 if (curr != &(y_regs[STAR_REGISTER]))
1393 // Copy the text from register 0 to the clipboard register.
1394 copy_yank_reg(&(y_regs[STAR_REGISTER]));
1395
1396 clip_own_selection(&clip_star);
1397 clip_gen_set_selection(&clip_star);
1398# ifdef FEAT_X11
1399 did_star = TRUE;
1400# endif
1401 }
1402
1403# ifdef FEAT_X11
1404 // If we were yanking to the '+' register, send result to selection.
Bram Moolenaar37096af2021-03-02 19:04:11 +01001405 // Also copy to the '*' register, in case auto-select is off. But not when
1406 // 'clipboard' has "unnamedplus" and not "unnamed".
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001407 if (clip_plus.available
1408 && (curr == &(y_regs[PLUS_REGISTER])
1409 || (!deleting && oap->regname == 0
1410 && ((clip_unnamed | clip_unnamed_saved) &
Bram Moolenaar37096af2021-03-02 19:04:11 +01001411 CLIP_UNNAMED_PLUS))))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001412 {
1413 if (curr != &(y_regs[PLUS_REGISTER]))
1414 // Copy the text from register 0 to the clipboard register.
1415 copy_yank_reg(&(y_regs[PLUS_REGISTER]));
1416
1417 clip_own_selection(&clip_plus);
1418 clip_gen_set_selection(&clip_plus);
Bram Moolenaar37096af2021-03-02 19:04:11 +01001419 if (!clip_isautosel_star()
1420 && !clip_isautosel_plus()
1421 && !((clip_unnamed | clip_unnamed_saved) == CLIP_UNNAMED_PLUS)
1422 && !did_star
1423 && curr == &(y_regs[PLUS_REGISTER]))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001424 {
1425 copy_yank_reg(&(y_regs[STAR_REGISTER]));
1426 clip_own_selection(&clip_star);
1427 clip_gen_set_selection(&clip_star);
1428 }
1429 }
1430# endif
1431#endif
1432
1433#if defined(FEAT_EVAL)
1434 if (!deleting && has_textyankpost())
1435 yank_do_autocmd(oap, y_current);
1436#endif
1437
1438 return OK;
1439
1440fail: // free the allocated lines
1441 free_yank(y_idx + 1);
1442 y_current = curr;
1443 return FAIL;
1444}
1445
Christian Brabandt544a38e2021-06-10 19:39:11 +02001446/*
1447 * Copy a block range into a register.
1448 * If "exclude_trailing_space" is set, do not copy trailing whitespaces.
1449 */
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001450 static int
Christian Brabandt544a38e2021-06-10 19:39:11 +02001451yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001452{
1453 char_u *pnew;
1454
1455 if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1))
1456 == NULL)
1457 return FAIL;
1458 y_current->y_array[y_idx] = pnew;
1459 vim_memset(pnew, ' ', (size_t)bd->startspaces);
1460 pnew += bd->startspaces;
1461 mch_memmove(pnew, bd->textstart, (size_t)bd->textlen);
1462 pnew += bd->textlen;
1463 vim_memset(pnew, ' ', (size_t)bd->endspaces);
1464 pnew += bd->endspaces;
Christian Brabandt544a38e2021-06-10 19:39:11 +02001465 if (exclude_trailing_space)
1466 {
1467 int s = bd->textlen + bd->endspaces;
1468
1469 while (VIM_ISWHITE(*(bd->textstart + s - 1)) && s > 0)
1470 {
1471 s = s - (*mb_head_off)(bd->textstart, bd->textstart + s - 1) - 1;
1472 pnew--;
1473 }
1474 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001475 *pnew = NUL;
1476 return OK;
1477}
1478
1479#ifdef FEAT_CLIPBOARD
1480/*
1481 * Make a copy of the y_current register to register "reg".
1482 */
1483 static void
1484copy_yank_reg(yankreg_T *reg)
1485{
1486 yankreg_T *curr = y_current;
1487 long j;
1488
1489 y_current = reg;
1490 free_yank_all();
1491 *y_current = *curr;
1492 y_current->y_array = lalloc_clear(
1493 sizeof(char_u *) * y_current->y_size, TRUE);
1494 if (y_current->y_array == NULL)
1495 y_current->y_size = 0;
1496 else
1497 for (j = 0; j < y_current->y_size; ++j)
1498 if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL)
1499 {
1500 free_yank(j);
1501 y_current->y_size = 0;
1502 break;
1503 }
1504 y_current = curr;
1505}
1506#endif
1507
1508/*
1509 * Put contents of register "regname" into the text.
1510 * Caller must check "regname" to be valid!
1511 * "flags": PUT_FIXINDENT make indent look nice
1512 * PUT_CURSEND leave cursor after end of new text
1513 * PUT_LINE force linewise put (":put")
Christian Brabandt2fa93842021-05-30 22:17:25 +02001514 * PUT_BLOCK_INNER in block mode, do not add trailing spaces
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001515 */
1516 void
1517do_put(
1518 int regname,
Bram Moolenaarc3516f72020-09-08 22:45:35 +02001519 char_u *expr_result, // result for regname "=" when compiled
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001520 int dir, // BACKWARD for 'P', FORWARD for 'p'
1521 long count,
1522 int flags)
1523{
1524 char_u *ptr;
1525 char_u *newp, *oldp;
1526 int yanklen;
1527 int totlen = 0; // init for gcc
1528 linenr_T lnum;
1529 colnr_T col;
1530 long i; // index in y_array[]
1531 int y_type;
1532 long y_size;
1533 int oldlen;
1534 long y_width = 0;
1535 colnr_T vcol;
1536 int delcount;
1537 int incr = 0;
1538 long j;
1539 struct block_def bd;
1540 char_u **y_array = NULL;
1541 long nr_lines = 0;
1542 pos_T new_cursor;
1543 int indent;
1544 int orig_indent = 0; // init for gcc
1545 int indent_diff = 0; // init for gcc
1546 int first_indent = TRUE;
1547 int lendiff = 0;
1548 pos_T old_pos;
1549 char_u *insert_string = NULL;
1550 int allocated = FALSE;
1551 long cnt;
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001552 pos_T orig_start = curbuf->b_op_start;
1553 pos_T orig_end = curbuf->b_op_end;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001554
1555#ifdef FEAT_CLIPBOARD
1556 // Adjust register name for "unnamed" in 'clipboard'.
1557 adjust_clip_reg(&regname);
1558 (void)may_get_selection(regname);
1559#endif
1560
1561 if (flags & PUT_FIXINDENT)
1562 orig_indent = get_indent();
1563
1564 curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
1565 curbuf->b_op_end = curwin->w_cursor; // default for '] mark
1566
1567 // Using inserted text works differently, because the register includes
1568 // special characters (newlines, etc.).
1569 if (regname == '.')
1570 {
1571 if (VIsual_active)
1572 stuffcharReadbuff(VIsual_mode);
1573 (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
1574 (count == -1 ? 'O' : 'i')), count, FALSE);
1575 // Putting the text is done later, so can't really move the cursor to
1576 // the next character. Use "l" to simulate it.
1577 if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
1578 stuffcharReadbuff('l');
1579 return;
1580 }
1581
1582 // For special registers '%' (file name), '#' (alternate file name) and
1583 // ':' (last command line), etc. we have to create a fake yank register.
Bram Moolenaarc3516f72020-09-08 22:45:35 +02001584 // For compiled code "expr_result" holds the expression result.
1585 if (regname == '=' && expr_result != NULL)
1586 insert_string = expr_result;
1587 else if (get_spec_reg(regname, &insert_string, &allocated, TRUE)
1588 && insert_string == NULL)
1589 return;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001590
1591 // Autocommands may be executed when saving lines for undo. This might
1592 // make "y_array" invalid, so we start undo now to avoid that.
1593 if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL)
1594 goto end;
1595
1596 if (insert_string != NULL)
1597 {
1598 y_type = MCHAR;
1599#ifdef FEAT_EVAL
1600 if (regname == '=')
1601 {
1602 // For the = register we need to split the string at NL
1603 // characters.
1604 // Loop twice: count the number of lines and save them.
1605 for (;;)
1606 {
1607 y_size = 0;
1608 ptr = insert_string;
1609 while (ptr != NULL)
1610 {
1611 if (y_array != NULL)
1612 y_array[y_size] = ptr;
1613 ++y_size;
1614 ptr = vim_strchr(ptr, '\n');
1615 if (ptr != NULL)
1616 {
1617 if (y_array != NULL)
1618 *ptr = NUL;
1619 ++ptr;
1620 // A trailing '\n' makes the register linewise.
1621 if (*ptr == NUL)
1622 {
1623 y_type = MLINE;
1624 break;
1625 }
1626 }
1627 }
1628 if (y_array != NULL)
1629 break;
1630 y_array = ALLOC_MULT(char_u *, y_size);
1631 if (y_array == NULL)
1632 goto end;
1633 }
1634 }
1635 else
1636#endif
1637 {
1638 y_size = 1; // use fake one-line yank register
1639 y_array = &insert_string;
1640 }
1641 }
1642 else
1643 {
1644 get_yank_register(regname, FALSE);
1645
1646 y_type = y_current->y_type;
1647 y_width = y_current->y_width;
1648 y_size = y_current->y_size;
1649 y_array = y_current->y_array;
1650 }
1651
1652 if (y_type == MLINE)
1653 {
1654 if (flags & PUT_LINE_SPLIT)
1655 {
1656 char_u *p;
1657
1658 // "p" or "P" in Visual mode: split the lines to put the text in
1659 // between.
1660 if (u_save_cursor() == FAIL)
1661 goto end;
1662 p = ml_get_cursor();
1663 if (dir == FORWARD && *p != NUL)
1664 MB_PTR_ADV(p);
1665 ptr = vim_strsave(p);
1666 if (ptr == NULL)
1667 goto end;
1668 ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE);
1669 vim_free(ptr);
1670
1671 oldp = ml_get_curline();
1672 p = oldp + curwin->w_cursor.col;
1673 if (dir == FORWARD && *p != NUL)
1674 MB_PTR_ADV(p);
1675 ptr = vim_strnsave(oldp, p - oldp);
1676 if (ptr == NULL)
1677 goto end;
1678 ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
1679 ++nr_lines;
1680 dir = FORWARD;
1681 }
1682 if (flags & PUT_LINE_FORWARD)
1683 {
1684 // Must be "p" for a Visual block, put lines below the block.
1685 curwin->w_cursor = curbuf->b_visual.vi_end;
1686 dir = FORWARD;
1687 }
1688 curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
1689 curbuf->b_op_end = curwin->w_cursor; // default for '] mark
1690 }
1691
1692 if (flags & PUT_LINE) // :put command or "p" in Visual line mode.
1693 y_type = MLINE;
1694
1695 if (y_size == 0 || y_array == NULL)
1696 {
1697 semsg(_("E353: Nothing in register %s"),
1698 regname == 0 ? (char_u *)"\"" : transchar(regname));
1699 goto end;
1700 }
1701
1702 if (y_type == MBLOCK)
1703 {
1704 lnum = curwin->w_cursor.lnum + y_size + 1;
1705 if (lnum > curbuf->b_ml.ml_line_count)
1706 lnum = curbuf->b_ml.ml_line_count + 1;
1707 if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
1708 goto end;
1709 }
1710 else if (y_type == MLINE)
1711 {
1712 lnum = curwin->w_cursor.lnum;
1713#ifdef FEAT_FOLDING
1714 // Correct line number for closed fold. Don't move the cursor yet,
1715 // u_save() uses it.
1716 if (dir == BACKWARD)
1717 (void)hasFolding(lnum, &lnum, NULL);
1718 else
1719 (void)hasFolding(lnum, NULL, &lnum);
1720#endif
1721 if (dir == FORWARD)
1722 ++lnum;
1723 // In an empty buffer the empty line is going to be replaced, include
1724 // it in the saved lines.
1725 if ((BUFEMPTY() ? u_save(0, 2) : u_save(lnum - 1, lnum)) == FAIL)
1726 goto end;
1727#ifdef FEAT_FOLDING
1728 if (dir == FORWARD)
1729 curwin->w_cursor.lnum = lnum - 1;
1730 else
1731 curwin->w_cursor.lnum = lnum;
1732 curbuf->b_op_start = curwin->w_cursor; // for mark_adjust()
1733#endif
1734 }
1735 else if (u_save_cursor() == FAIL)
1736 goto end;
1737
1738 yanklen = (int)STRLEN(y_array[0]);
1739
1740 if (ve_flags == VE_ALL && y_type == MCHAR)
1741 {
1742 if (gchar_cursor() == TAB)
1743 {
Bram Moolenaar6f1f0ca2019-12-01 18:16:18 +01001744 int viscol = getviscol();
1745 int ts = curbuf->b_p_ts;
1746
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001747 // Don't need to insert spaces when "p" on the last position of a
1748 // tab or "P" on the first position.
Bram Moolenaar6f1f0ca2019-12-01 18:16:18 +01001749 if (dir == FORWARD ?
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001750#ifdef FEAT_VARTABS
Bram Moolenaar6f1f0ca2019-12-01 18:16:18 +01001751 tabstop_padding(viscol, ts, curbuf->b_p_vts_array) != 1
1752#else
1753 ts - (viscol % ts) != 1
1754#endif
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001755 : curwin->w_cursor.coladd > 0)
1756 coladvance_force(viscol);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001757 else
1758 curwin->w_cursor.coladd = 0;
1759 }
1760 else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL)
1761 coladvance_force(getviscol() + (dir == FORWARD));
1762 }
1763
1764 lnum = curwin->w_cursor.lnum;
1765 col = curwin->w_cursor.col;
1766
1767 // Block mode
1768 if (y_type == MBLOCK)
1769 {
1770 int c = gchar_cursor();
1771 colnr_T endcol2 = 0;
1772
1773 if (dir == FORWARD && c != NUL)
1774 {
1775 if (ve_flags == VE_ALL)
1776 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
1777 else
1778 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
1779
1780 if (has_mbyte)
1781 // move to start of next multi-byte character
1782 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor());
1783 else
1784 if (c != TAB || ve_flags != VE_ALL)
1785 ++curwin->w_cursor.col;
1786 ++col;
1787 }
1788 else
1789 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
1790
1791 col += curwin->w_cursor.coladd;
1792 if (ve_flags == VE_ALL
1793 && (curwin->w_cursor.coladd > 0
1794 || endcol2 == curwin->w_cursor.col))
1795 {
1796 if (dir == FORWARD && c == NUL)
1797 ++col;
Bram Moolenaaref85a9b2020-07-10 20:24:07 +02001798 if (dir != FORWARD && c != NUL && curwin->w_cursor.coladd > 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001799 ++curwin->w_cursor.col;
1800 if (c == TAB)
1801 {
1802 if (dir == BACKWARD && curwin->w_cursor.col)
1803 curwin->w_cursor.col--;
1804 if (dir == FORWARD && col - 1 == endcol2)
1805 curwin->w_cursor.col++;
1806 }
1807 }
1808 curwin->w_cursor.coladd = 0;
1809 bd.textcol = 0;
1810 for (i = 0; i < y_size; ++i)
1811 {
Christian Brabandt2fa93842021-05-30 22:17:25 +02001812 int spaces = 0;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001813 char shortline;
1814
1815 bd.startspaces = 0;
1816 bd.endspaces = 0;
1817 vcol = 0;
1818 delcount = 0;
1819
1820 // add a new line
1821 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
1822 {
1823 if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
1824 (colnr_T)1, FALSE) == FAIL)
1825 break;
1826 ++nr_lines;
1827 }
1828 // get the old line and advance to the position to insert at
1829 oldp = ml_get_curline();
1830 oldlen = (int)STRLEN(oldp);
1831 for (ptr = oldp; vcol < col && *ptr; )
1832 {
1833 // Count a tab for what it's worth (if list mode not on)
1834 incr = lbr_chartabsize_adv(oldp, &ptr, (colnr_T)vcol);
1835 vcol += incr;
1836 }
1837 bd.textcol = (colnr_T)(ptr - oldp);
1838
1839 shortline = (vcol < col) || (vcol == col && !*ptr) ;
1840
1841 if (vcol < col) // line too short, padd with spaces
1842 bd.startspaces = col - vcol;
1843 else if (vcol > col)
1844 {
1845 bd.endspaces = vcol - col;
1846 bd.startspaces = incr - bd.endspaces;
1847 --bd.textcol;
1848 delcount = 1;
1849 if (has_mbyte)
1850 bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol);
1851 if (oldp[bd.textcol] != TAB)
1852 {
1853 // Only a Tab can be split into spaces. Other
1854 // characters will have to be moved to after the
1855 // block, causing misalignment.
1856 delcount = 0;
1857 bd.endspaces = 0;
1858 }
1859 }
1860
1861 yanklen = (int)STRLEN(y_array[i]);
1862
Christian Brabandt2fa93842021-05-30 22:17:25 +02001863 if ((flags & PUT_BLOCK_INNER) == 0)
1864 {
1865 // calculate number of spaces required to fill right side of
1866 // block
1867 spaces = y_width + 1;
1868 for (j = 0; j < yanklen; j++)
1869 spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0);
1870 if (spaces < 0)
1871 spaces = 0;
1872 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001873
1874 // insert the new text
1875 totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
1876 newp = alloc(totlen + oldlen + 1);
1877 if (newp == NULL)
1878 break;
1879 // copy part up to cursor to new line
1880 ptr = newp;
1881 mch_memmove(ptr, oldp, (size_t)bd.textcol);
1882 ptr += bd.textcol;
1883 // may insert some spaces before the new text
1884 vim_memset(ptr, ' ', (size_t)bd.startspaces);
1885 ptr += bd.startspaces;
1886 // insert the new text
1887 for (j = 0; j < count; ++j)
1888 {
1889 mch_memmove(ptr, y_array[i], (size_t)yanklen);
1890 ptr += yanklen;
1891
1892 // insert block's trailing spaces only if there's text behind
1893 if ((j < count - 1 || !shortline) && spaces)
1894 {
1895 vim_memset(ptr, ' ', (size_t)spaces);
1896 ptr += spaces;
1897 }
1898 }
1899 // may insert some spaces after the new text
1900 vim_memset(ptr, ' ', (size_t)bd.endspaces);
1901 ptr += bd.endspaces;
1902 // move the text after the cursor to the end of the line.
1903 mch_memmove(ptr, oldp + bd.textcol + delcount,
1904 (size_t)(oldlen - bd.textcol - delcount + 1));
1905 ml_replace(curwin->w_cursor.lnum, newp, FALSE);
1906
1907 ++curwin->w_cursor.lnum;
1908 if (i == 0)
1909 curwin->w_cursor.col += bd.startspaces;
1910 }
1911
1912 changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines);
1913
1914 // Set '[ mark.
1915 curbuf->b_op_start = curwin->w_cursor;
1916 curbuf->b_op_start.lnum = lnum;
1917
1918 // adjust '] mark
1919 curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
1920 curbuf->b_op_end.col = bd.textcol + totlen - 1;
1921 curbuf->b_op_end.coladd = 0;
1922 if (flags & PUT_CURSEND)
1923 {
1924 colnr_T len;
1925
1926 curwin->w_cursor = curbuf->b_op_end;
1927 curwin->w_cursor.col++;
1928
1929 // in Insert mode we might be after the NUL, correct for that
1930 len = (colnr_T)STRLEN(ml_get_curline());
1931 if (curwin->w_cursor.col > len)
1932 curwin->w_cursor.col = len;
1933 }
1934 else
1935 curwin->w_cursor.lnum = lnum;
1936 }
1937 else
1938 {
1939 // Character or Line mode
1940 if (y_type == MCHAR)
1941 {
1942 // if type is MCHAR, FORWARD is the same as BACKWARD on the next
1943 // char
1944 if (dir == FORWARD && gchar_cursor() != NUL)
1945 {
1946 if (has_mbyte)
1947 {
1948 int bytelen = (*mb_ptr2len)(ml_get_cursor());
1949
1950 // put it on the next of the multi-byte character.
1951 col += bytelen;
1952 if (yanklen)
1953 {
1954 curwin->w_cursor.col += bytelen;
1955 curbuf->b_op_end.col += bytelen;
1956 }
1957 }
1958 else
1959 {
1960 ++col;
1961 if (yanklen)
1962 {
1963 ++curwin->w_cursor.col;
1964 ++curbuf->b_op_end.col;
1965 }
1966 }
1967 }
1968 curbuf->b_op_start = curwin->w_cursor;
1969 }
1970 // Line mode: BACKWARD is the same as FORWARD on the previous line
1971 else if (dir == BACKWARD)
1972 --lnum;
1973 new_cursor = curwin->w_cursor;
1974
Bram Moolenaarcd942772020-08-22 21:08:44 +02001975 // simple case: insert into one line at a time
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001976 if (y_type == MCHAR && y_size == 1)
1977 {
Bram Moolenaarcd942772020-08-22 21:08:44 +02001978 linenr_T end_lnum = 0; // init for gcc
1979 linenr_T start_lnum = lnum;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001980
1981 if (VIsual_active)
1982 {
1983 end_lnum = curbuf->b_visual.vi_end.lnum;
1984 if (end_lnum < curbuf->b_visual.vi_start.lnum)
1985 end_lnum = curbuf->b_visual.vi_start.lnum;
Bram Moolenaarcd942772020-08-22 21:08:44 +02001986 if (end_lnum > start_lnum)
1987 {
1988 pos_T pos;
1989
1990 // "col" is valid for the first line, in following lines
1991 // the virtual column needs to be used. Matters for
1992 // multi-byte characters.
1993 pos.lnum = lnum;
1994 pos.col = col;
1995 pos.coladd = 0;
1996 getvcol(curwin, &pos, NULL, &vcol, NULL);
1997 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001998 }
1999
2000 do {
2001 totlen = count * yanklen;
2002 if (totlen > 0)
2003 {
2004 oldp = ml_get(lnum);
Bram Moolenaarcd942772020-08-22 21:08:44 +02002005 if (lnum > start_lnum)
2006 {
2007 pos_T pos;
2008
2009 pos.lnum = lnum;
2010 if (getvpos(&pos, vcol) == OK)
2011 col = pos.col;
2012 else
2013 col = MAXCOL;
2014 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002015 if (VIsual_active && col > (int)STRLEN(oldp))
2016 {
2017 lnum++;
2018 continue;
2019 }
2020 newp = alloc(STRLEN(oldp) + totlen + 1);
2021 if (newp == NULL)
2022 goto end; // alloc() gave an error message
2023 mch_memmove(newp, oldp, (size_t)col);
2024 ptr = newp + col;
2025 for (i = 0; i < count; ++i)
2026 {
2027 mch_memmove(ptr, y_array[0], (size_t)yanklen);
2028 ptr += yanklen;
2029 }
2030 STRMOVE(ptr, oldp + col);
2031 ml_replace(lnum, newp, FALSE);
2032 // Place cursor on last putted char.
2033 if (lnum == curwin->w_cursor.lnum)
2034 {
2035 // make sure curwin->w_virtcol is updated
2036 changed_cline_bef_curs();
2037 curwin->w_cursor.col += (colnr_T)(totlen - 1);
2038 }
2039 }
2040 if (VIsual_active)
2041 lnum++;
2042 } while (VIsual_active && lnum <= end_lnum);
2043
2044 if (VIsual_active) // reset lnum to the last visual line
2045 lnum--;
2046
2047 curbuf->b_op_end = curwin->w_cursor;
2048 // For "CTRL-O p" in Insert mode, put cursor after last char
2049 if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
2050 ++curwin->w_cursor.col;
2051 changed_bytes(lnum, col);
2052 }
2053 else
2054 {
2055 // Insert at least one line. When y_type is MCHAR, break the first
2056 // line in two.
2057 for (cnt = 1; cnt <= count; ++cnt)
2058 {
2059 i = 0;
2060 if (y_type == MCHAR)
2061 {
2062 // Split the current line in two at the insert position.
2063 // First insert y_array[size - 1] in front of second line.
2064 // Then append y_array[0] to first line.
2065 lnum = new_cursor.lnum;
2066 ptr = ml_get(lnum) + col;
2067 totlen = (int)STRLEN(y_array[y_size - 1]);
2068 newp = alloc(STRLEN(ptr) + totlen + 1);
2069 if (newp == NULL)
2070 goto error;
2071 STRCPY(newp, y_array[y_size - 1]);
2072 STRCAT(newp, ptr);
2073 // insert second line
2074 ml_append(lnum, newp, (colnr_T)0, FALSE);
2075 vim_free(newp);
2076
2077 oldp = ml_get(lnum);
2078 newp = alloc(col + yanklen + 1);
2079 if (newp == NULL)
2080 goto error;
2081 // copy first part of line
2082 mch_memmove(newp, oldp, (size_t)col);
2083 // append to first line
2084 mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
2085 ml_replace(lnum, newp, FALSE);
2086
2087 curwin->w_cursor.lnum = lnum;
2088 i = 1;
2089 }
2090
2091 for (; i < y_size; ++i)
2092 {
2093 if ((y_type != MCHAR || i < y_size - 1)
2094 && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
2095 == FAIL)
2096 goto error;
2097 lnum++;
2098 ++nr_lines;
2099 if (flags & PUT_FIXINDENT)
2100 {
2101 old_pos = curwin->w_cursor;
2102 curwin->w_cursor.lnum = lnum;
2103 ptr = ml_get(lnum);
2104 if (cnt == count && i == y_size - 1)
2105 lendiff = (int)STRLEN(ptr);
2106#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
2107 if (*ptr == '#' && preprocs_left())
2108 indent = 0; // Leave # lines at start
2109 else
2110#endif
2111 if (*ptr == NUL)
2112 indent = 0; // Ignore empty lines
2113 else if (first_indent)
2114 {
2115 indent_diff = orig_indent - get_indent();
2116 indent = orig_indent;
2117 first_indent = FALSE;
2118 }
2119 else if ((indent = get_indent() + indent_diff) < 0)
2120 indent = 0;
2121 (void)set_indent(indent, 0);
2122 curwin->w_cursor = old_pos;
2123 // remember how many chars were removed
2124 if (cnt == count && i == y_size - 1)
2125 lendiff -= (int)STRLEN(ml_get(lnum));
2126 }
2127 }
2128 }
2129
2130error:
2131 // Adjust marks.
2132 if (y_type == MLINE)
2133 {
2134 curbuf->b_op_start.col = 0;
2135 if (dir == FORWARD)
2136 curbuf->b_op_start.lnum++;
2137 }
2138 // Skip mark_adjust when adding lines after the last one, there
2139 // can't be marks there. But still needed in diff mode.
2140 if (curbuf->b_op_start.lnum + (y_type == MCHAR) - 1 + nr_lines
2141 < curbuf->b_ml.ml_line_count
2142#ifdef FEAT_DIFF
2143 || curwin->w_p_diff
2144#endif
2145 )
2146 mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
2147 (linenr_T)MAXLNUM, nr_lines, 0L);
2148
2149 // note changed text for displaying and folding
2150 if (y_type == MCHAR)
2151 changed_lines(curwin->w_cursor.lnum, col,
2152 curwin->w_cursor.lnum + 1, nr_lines);
2153 else
2154 changed_lines(curbuf->b_op_start.lnum, 0,
2155 curbuf->b_op_start.lnum, nr_lines);
2156
2157 // put '] mark at last inserted character
2158 curbuf->b_op_end.lnum = lnum;
2159 // correct length for change in indent
2160 col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
2161 if (col > 1)
2162 curbuf->b_op_end.col = col - 1;
2163 else
2164 curbuf->b_op_end.col = 0;
2165
2166 if (flags & PUT_CURSLINE)
2167 {
2168 // ":put": put cursor on last inserted line
2169 curwin->w_cursor.lnum = lnum;
2170 beginline(BL_WHITE | BL_FIX);
2171 }
2172 else if (flags & PUT_CURSEND)
2173 {
2174 // put cursor after inserted text
2175 if (y_type == MLINE)
2176 {
2177 if (lnum >= curbuf->b_ml.ml_line_count)
2178 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
2179 else
2180 curwin->w_cursor.lnum = lnum + 1;
2181 curwin->w_cursor.col = 0;
2182 }
2183 else
2184 {
2185 curwin->w_cursor.lnum = lnum;
2186 curwin->w_cursor.col = col;
2187 }
2188 }
2189 else if (y_type == MLINE)
2190 {
2191 // put cursor on first non-blank in first inserted line
2192 curwin->w_cursor.col = 0;
2193 if (dir == FORWARD)
2194 ++curwin->w_cursor.lnum;
2195 beginline(BL_WHITE | BL_FIX);
2196 }
2197 else // put cursor on first inserted character
2198 curwin->w_cursor = new_cursor;
2199 }
2200 }
2201
2202 msgmore(nr_lines);
2203 curwin->w_set_curswant = TRUE;
2204
2205end:
Bram Moolenaare1004402020-10-24 20:49:43 +02002206 if (cmdmod.cmod_flags & CMOD_LOCKMARKS)
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01002207 {
2208 curbuf->b_op_start = orig_start;
2209 curbuf->b_op_end = orig_end;
2210 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002211 if (allocated)
2212 vim_free(insert_string);
2213 if (regname == '=')
2214 vim_free(y_array);
2215
2216 VIsual_active = FALSE;
2217
2218 // If the cursor is past the end of the line put it at the end.
2219 adjust_cursor_eol();
2220}
2221
2222/*
2223 * Return the character name of the register with the given number.
2224 */
2225 int
2226get_register_name(int num)
2227{
2228 if (num == -1)
2229 return '"';
2230 else if (num < 10)
2231 return num + '0';
2232 else if (num == DELETION_REGISTER)
2233 return '-';
2234#ifdef FEAT_CLIPBOARD
2235 else if (num == STAR_REGISTER)
2236 return '*';
2237 else if (num == PLUS_REGISTER)
2238 return '+';
2239#endif
2240 else
2241 {
2242#ifdef EBCDIC
2243 int i;
2244
2245 // EBCDIC is really braindead ...
2246 i = 'a' + (num - 10);
2247 if (i > 'i')
2248 i += 7;
2249 if (i > 'r')
2250 i += 8;
2251 return i;
2252#else
2253 return num + 'a' - 10;
2254#endif
2255 }
2256}
2257
2258/*
Bram Moolenaarbb861e22020-06-07 18:16:36 +02002259 * Return the index of the register "" points to.
2260 */
2261 int
2262get_unname_register()
2263{
2264 return y_previous == NULL ? -1 : y_previous - &y_regs[0];
2265}
2266
2267/*
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002268 * ":dis" and ":registers": Display the contents of the yank registers.
2269 */
2270 void
2271ex_display(exarg_T *eap)
2272{
2273 int i, n;
2274 long j;
2275 char_u *p;
2276 yankreg_T *yb;
2277 int name;
2278 int attr;
2279 char_u *arg = eap->arg;
2280 int clen;
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002281 int type;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002282
2283 if (arg != NULL && *arg == NUL)
2284 arg = NULL;
2285 attr = HL_ATTR(HLF_8);
2286
2287 // Highlight title
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002288 msg_puts_title(_("\nType Name Content"));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002289 for (i = -1; i < NUM_REGISTERS && !got_int; ++i)
2290 {
2291 name = get_register_name(i);
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002292 switch (get_reg_type(name, NULL))
2293 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002294 case MLINE: type = 'l'; break;
2295 case MCHAR: type = 'c'; break;
2296 default: type = 'b'; break;
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002297 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002298 if (arg != NULL && vim_strchr(arg, name) == NULL
2299#ifdef ONE_CLIPBOARD
2300 // Star register and plus register contain the same thing.
2301 && (name != '*' || vim_strchr(arg, '+') == NULL)
2302#endif
2303 )
2304 continue; // did not ask for this register
2305
2306#ifdef FEAT_CLIPBOARD
2307 // Adjust register name for "unnamed" in 'clipboard'.
2308 // When it's a clipboard register, fill it with the current contents
2309 // of the clipboard.
2310 adjust_clip_reg(&name);
2311 (void)may_get_selection(name);
2312#endif
2313
2314 if (i == -1)
2315 {
2316 if (y_previous != NULL)
2317 yb = y_previous;
2318 else
2319 yb = &(y_regs[0]);
2320 }
2321 else
2322 yb = &(y_regs[i]);
2323
2324#ifdef FEAT_EVAL
2325 if (name == MB_TOLOWER(redir_reg)
2326 || (redir_reg == '"' && yb == y_previous))
2327 continue; // do not list register being written to, the
2328 // pointer can be freed
2329#endif
2330
2331 if (yb->y_array != NULL)
2332 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002333 int do_show = FALSE;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002334
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002335 for (j = 0; !do_show && j < yb->y_size; ++j)
2336 do_show = !message_filtered(yb->y_array[j]);
2337
2338 if (do_show || yb->y_size == 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002339 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002340 msg_putchar('\n');
2341 msg_puts(" ");
2342 msg_putchar(type);
2343 msg_puts(" ");
2344 msg_putchar('"');
2345 msg_putchar(name);
2346 msg_puts(" ");
2347
2348 n = (int)Columns - 11;
2349 for (j = 0; j < yb->y_size && n > 1; ++j)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002350 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002351 if (j)
2352 {
2353 msg_puts_attr("^J", attr);
2354 n -= 2;
2355 }
2356 for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0;
2357 ++p)
2358 {
2359 clen = (*mb_ptr2len)(p);
2360 msg_outtrans_len(p, clen);
2361 p += clen - 1;
2362 }
2363 }
2364 if (n > 1 && yb->y_type == MLINE)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002365 msg_puts_attr("^J", attr);
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002366 out_flush(); // show one line at a time
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002367 }
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002368 ui_breakcheck();
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002369 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002370 }
2371
2372 // display last inserted text
2373 if ((p = get_last_insert()) != NULL
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002374 && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int
2375 && !message_filtered(p))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002376 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002377 msg_puts("\n c \". ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002378 dis_msg(p, TRUE);
2379 }
2380
2381 // display last command line
2382 if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002383 && !got_int && !message_filtered(last_cmdline))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002384 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002385 msg_puts("\n c \": ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002386 dis_msg(last_cmdline, FALSE);
2387 }
2388
2389 // display current file name
2390 if (curbuf->b_fname != NULL
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002391 && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int
2392 && !message_filtered(curbuf->b_fname))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002393 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002394 msg_puts("\n c \"% ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002395 dis_msg(curbuf->b_fname, FALSE);
2396 }
2397
2398 // display alternate file name
2399 if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
2400 {
2401 char_u *fname;
2402 linenr_T dummy;
2403
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002404 if (buflist_name_nr(0, &fname, &dummy) != FAIL
2405 && !message_filtered(fname))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002406 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002407 msg_puts("\n c \"# ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002408 dis_msg(fname, FALSE);
2409 }
2410 }
2411
2412 // display last search pattern
2413 if (last_search_pat() != NULL
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002414 && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int
2415 && !message_filtered(last_search_pat()))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002416 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002417 msg_puts("\n c \"/ ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002418 dis_msg(last_search_pat(), FALSE);
2419 }
2420
2421#ifdef FEAT_EVAL
2422 // display last used expression
2423 if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002424 && !got_int && !message_filtered(expr_line))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002425 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002426 msg_puts("\n c \"= ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002427 dis_msg(expr_line, FALSE);
2428 }
2429#endif
2430}
2431
2432/*
2433 * display a string for do_dis()
2434 * truncate at end of screen line
2435 */
2436 static void
2437dis_msg(
2438 char_u *p,
2439 int skip_esc) // if TRUE, ignore trailing ESC
2440{
2441 int n;
2442 int l;
2443
2444 n = (int)Columns - 6;
2445 while (*p != NUL
2446 && !(*p == ESC && skip_esc && *(p + 1) == NUL)
2447 && (n -= ptr2cells(p)) >= 0)
2448 {
2449 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
2450 {
2451 msg_outtrans_len(p, l);
2452 p += l;
2453 }
2454 else
2455 msg_outtrans_len(p++, 1);
2456 }
2457 ui_breakcheck();
2458}
2459
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002460#if defined(FEAT_DND) || defined(PROTO)
2461/*
2462 * Replace the contents of the '~' register with str.
2463 */
2464 void
2465dnd_yank_drag_data(char_u *str, long len)
2466{
2467 yankreg_T *curr;
2468
2469 curr = y_current;
2470 y_current = &y_regs[TILDE_REGISTER];
2471 free_yank_all();
2472 str_to_reg(y_current, MCHAR, str, len, 0L, FALSE);
2473 y_current = curr;
2474}
2475#endif
2476
2477
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002478/*
2479 * Return the type of a register.
2480 * Used for getregtype()
2481 * Returns MAUTO for error.
2482 */
2483 char_u
2484get_reg_type(int regname, long *reglen)
2485{
2486 switch (regname)
2487 {
2488 case '%': // file name
2489 case '#': // alternate file name
2490 case '=': // expression
2491 case ':': // last command line
2492 case '/': // last search-pattern
2493 case '.': // last inserted text
2494# ifdef FEAT_SEARCHPATH
2495 case Ctrl_F: // Filename under cursor
2496 case Ctrl_P: // Path under cursor, expand via "path"
2497# endif
2498 case Ctrl_W: // word under cursor
2499 case Ctrl_A: // WORD (mnemonic All) under cursor
2500 case '_': // black hole: always empty
2501 return MCHAR;
2502 }
2503
2504# ifdef FEAT_CLIPBOARD
2505 regname = may_get_selection(regname);
2506# endif
2507
2508 if (regname != NUL && !valid_yank_reg(regname, FALSE))
2509 return MAUTO;
2510
2511 get_yank_register(regname, FALSE);
2512
2513 if (y_current->y_array != NULL)
2514 {
2515 if (reglen != NULL && y_current->y_type == MBLOCK)
2516 *reglen = y_current->y_width;
2517 return y_current->y_type;
2518 }
2519 return MAUTO;
2520}
2521
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002522#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002523/*
2524 * When "flags" has GREG_LIST return a list with text "s".
2525 * Otherwise just return "s".
2526 */
2527 static char_u *
2528getreg_wrap_one_line(char_u *s, int flags)
2529{
2530 if (flags & GREG_LIST)
2531 {
2532 list_T *list = list_alloc();
2533
2534 if (list != NULL)
2535 {
2536 if (list_append_string(list, NULL, -1) == FAIL)
2537 {
2538 list_free(list);
2539 return NULL;
2540 }
2541 list->lv_first->li_tv.vval.v_string = s;
2542 }
2543 return (char_u *)list;
2544 }
2545 return s;
2546}
2547
2548/*
Bram Moolenaard672dde2020-02-26 13:43:51 +01002549 * Return the contents of a register as a single allocated string or as a list.
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002550 * Used for "@r" in expressions and for getreg().
2551 * Returns NULL for error.
2552 * Flags:
2553 * GREG_NO_EXPR Do not allow expression register
2554 * GREG_EXPR_SRC For the expression register: return expression itself,
2555 * not the result of its evaluation.
Bram Moolenaard672dde2020-02-26 13:43:51 +01002556 * GREG_LIST Return a list of lines instead of a single string.
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002557 */
2558 char_u *
2559get_reg_contents(int regname, int flags)
2560{
2561 long i;
2562 char_u *retval;
2563 int allocated;
2564 long len;
2565
2566 // Don't allow using an expression register inside an expression
2567 if (regname == '=')
2568 {
2569 if (flags & GREG_NO_EXPR)
2570 return NULL;
2571 if (flags & GREG_EXPR_SRC)
2572 return getreg_wrap_one_line(get_expr_line_src(), flags);
2573 return getreg_wrap_one_line(get_expr_line(), flags);
2574 }
2575
2576 if (regname == '@') // "@@" is used for unnamed register
2577 regname = '"';
2578
2579 // check for valid regname
2580 if (regname != NUL && !valid_yank_reg(regname, FALSE))
2581 return NULL;
2582
2583# ifdef FEAT_CLIPBOARD
2584 regname = may_get_selection(regname);
2585# endif
2586
2587 if (get_spec_reg(regname, &retval, &allocated, FALSE))
2588 {
2589 if (retval == NULL)
2590 return NULL;
2591 if (allocated)
2592 return getreg_wrap_one_line(retval, flags);
2593 return getreg_wrap_one_line(vim_strsave(retval), flags);
2594 }
2595
2596 get_yank_register(regname, FALSE);
2597 if (y_current->y_array == NULL)
2598 return NULL;
2599
2600 if (flags & GREG_LIST)
2601 {
2602 list_T *list = list_alloc();
2603 int error = FALSE;
2604
2605 if (list == NULL)
2606 return NULL;
2607 for (i = 0; i < y_current->y_size; ++i)
2608 if (list_append_string(list, y_current->y_array[i], -1) == FAIL)
2609 error = TRUE;
2610 if (error)
2611 {
2612 list_free(list);
2613 return NULL;
2614 }
2615 return (char_u *)list;
2616 }
2617
2618 // Compute length of resulting string.
2619 len = 0;
2620 for (i = 0; i < y_current->y_size; ++i)
2621 {
2622 len += (long)STRLEN(y_current->y_array[i]);
2623 // Insert a newline between lines and after last line if
2624 // y_type is MLINE.
2625 if (y_current->y_type == MLINE || i < y_current->y_size - 1)
2626 ++len;
2627 }
2628
2629 retval = alloc(len + 1);
2630
2631 // Copy the lines of the yank register into the string.
2632 if (retval != NULL)
2633 {
2634 len = 0;
2635 for (i = 0; i < y_current->y_size; ++i)
2636 {
2637 STRCPY(retval + len, y_current->y_array[i]);
2638 len += (long)STRLEN(retval + len);
2639
2640 // Insert a NL between lines and after the last line if y_type is
2641 // MLINE.
2642 if (y_current->y_type == MLINE || i < y_current->y_size - 1)
2643 retval[len++] = '\n';
2644 }
2645 retval[len] = NUL;
2646 }
2647
2648 return retval;
2649}
2650
2651 static int
2652init_write_reg(
2653 int name,
2654 yankreg_T **old_y_previous,
2655 yankreg_T **old_y_current,
2656 int must_append,
2657 int *yank_type UNUSED)
2658{
2659 if (!valid_yank_reg(name, TRUE)) // check for valid reg name
2660 {
2661 emsg_invreg(name);
2662 return FAIL;
2663 }
2664
2665 // Don't want to change the current (unnamed) register
2666 *old_y_previous = y_previous;
2667 *old_y_current = y_current;
2668
2669 get_yank_register(name, TRUE);
2670 if (!y_append && !must_append)
2671 free_yank_all();
2672 return OK;
2673}
2674
2675 static void
2676finish_write_reg(
2677 int name,
2678 yankreg_T *old_y_previous,
2679 yankreg_T *old_y_current)
2680{
2681# ifdef FEAT_CLIPBOARD
2682 // Send text of clipboard register to the clipboard.
2683 may_set_selection();
2684# endif
2685
2686 // ':let @" = "val"' should change the meaning of the "" register
2687 if (name != '"')
2688 y_previous = old_y_previous;
2689 y_current = old_y_current;
2690}
2691
2692/*
2693 * Store string "str" in register "name".
2694 * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
2695 * If "must_append" is TRUE, always append to the register. Otherwise append
2696 * if "name" is an uppercase letter.
2697 * Note: "maxlen" and "must_append" don't work for the "/" register.
2698 * Careful: 'str' is modified, you may have to use a copy!
2699 * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
2700 */
2701 void
2702write_reg_contents(
2703 int name,
2704 char_u *str,
2705 int maxlen,
2706 int must_append)
2707{
2708 write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
2709}
2710
2711 void
2712write_reg_contents_lst(
2713 int name,
2714 char_u **strings,
2715 int maxlen UNUSED,
2716 int must_append,
2717 int yank_type,
2718 long block_len)
2719{
2720 yankreg_T *old_y_previous, *old_y_current;
2721
2722 if (name == '/' || name == '=')
2723 {
2724 char_u *s;
2725
2726 if (strings[0] == NULL)
2727 s = (char_u *)"";
2728 else if (strings[1] != NULL)
2729 {
2730 emsg(_("E883: search pattern and expression register may not "
2731 "contain two or more lines"));
2732 return;
2733 }
2734 else
2735 s = strings[0];
2736 write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
2737 return;
2738 }
2739
2740 if (name == '_') // black hole: nothing to do
2741 return;
2742
2743 if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
2744 &yank_type) == FAIL)
2745 return;
2746
2747 str_to_reg(y_current, yank_type, (char_u *) strings, -1, block_len, TRUE);
2748
2749 finish_write_reg(name, old_y_previous, old_y_current);
2750}
2751
2752 void
2753write_reg_contents_ex(
2754 int name,
2755 char_u *str,
2756 int maxlen,
2757 int must_append,
2758 int yank_type,
2759 long block_len)
2760{
2761 yankreg_T *old_y_previous, *old_y_current;
2762 long len;
2763
2764 if (maxlen >= 0)
2765 len = maxlen;
2766 else
2767 len = (long)STRLEN(str);
2768
2769 // Special case: '/' search pattern
2770 if (name == '/')
2771 {
2772 set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
2773 return;
2774 }
2775
2776 if (name == '#')
2777 {
2778 buf_T *buf;
2779
2780 if (VIM_ISDIGIT(*str))
2781 {
2782 int num = atoi((char *)str);
2783
2784 buf = buflist_findnr(num);
2785 if (buf == NULL)
2786 semsg(_(e_nobufnr), (long)num);
2787 }
2788 else
2789 buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
2790 TRUE, FALSE, FALSE));
2791 if (buf == NULL)
2792 return;
2793 curwin->w_alt_fnum = buf->b_fnum;
2794 return;
2795 }
2796
2797 if (name == '=')
2798 {
2799 char_u *p, *s;
2800
Bram Moolenaar71ccd032020-06-12 22:59:11 +02002801 p = vim_strnsave(str, len);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002802 if (p == NULL)
2803 return;
Bram Moolenaar6b649ac2019-12-07 17:47:22 +01002804 if (must_append && expr_line != NULL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002805 {
Bram Moolenaar6b649ac2019-12-07 17:47:22 +01002806 s = concat_str(expr_line, p);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002807 vim_free(p);
2808 p = s;
2809 }
Bram Moolenaarb4bcea42020-10-28 13:53:50 +01002810 set_expr_line(p, NULL);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002811 return;
2812 }
2813
2814 if (name == '_') // black hole: nothing to do
2815 return;
2816
2817 if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
2818 &yank_type) == FAIL)
2819 return;
2820
2821 str_to_reg(y_current, yank_type, str, len, block_len, FALSE);
2822
2823 finish_write_reg(name, old_y_previous, old_y_current);
2824}
2825#endif // FEAT_EVAL
2826
2827#if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
2828/*
2829 * Put a string into a register. When the register is not empty, the string
2830 * is appended.
2831 */
Bram Moolenaar45fffdf2020-03-24 21:42:01 +01002832 void
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002833str_to_reg(
2834 yankreg_T *y_ptr, // pointer to yank register
2835 int yank_type, // MCHAR, MLINE, MBLOCK, MAUTO
2836 char_u *str, // string to put in register
2837 long len, // length of string
2838 long blocklen, // width of Visual block
2839 int str_list) // TRUE if str is char_u **
2840{
2841 int type; // MCHAR, MLINE or MBLOCK
2842 int lnum;
2843 long start;
2844 long i;
2845 int extra;
2846 int newlines; // number of lines added
2847 int extraline = 0; // extra line at the end
2848 int append = FALSE; // append to last line in register
2849 char_u *s;
2850 char_u **ss;
2851 char_u **pp;
2852 long maxlen;
2853
2854 if (y_ptr->y_array == NULL) // NULL means empty register
2855 y_ptr->y_size = 0;
2856
2857 if (yank_type == MAUTO)
2858 type = ((str_list || (len > 0 && (str[len - 1] == NL
2859 || str[len - 1] == CAR)))
2860 ? MLINE : MCHAR);
2861 else
2862 type = yank_type;
2863
2864 // Count the number of lines within the string
2865 newlines = 0;
2866 if (str_list)
2867 {
2868 for (ss = (char_u **) str; *ss != NULL; ++ss)
2869 ++newlines;
2870 }
2871 else
2872 {
2873 for (i = 0; i < len; i++)
2874 if (str[i] == '\n')
2875 ++newlines;
2876 if (type == MCHAR || len == 0 || str[len - 1] != '\n')
2877 {
2878 extraline = 1;
2879 ++newlines; // count extra newline at the end
2880 }
2881 if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
2882 {
2883 append = TRUE;
2884 --newlines; // uncount newline when appending first line
2885 }
2886 }
2887
2888 // Without any lines make the register empty.
2889 if (y_ptr->y_size + newlines == 0)
2890 {
2891 VIM_CLEAR(y_ptr->y_array);
2892 return;
2893 }
2894
2895 // Allocate an array to hold the pointers to the new register lines.
2896 // If the register was not empty, move the existing lines to the new array.
2897 pp = lalloc_clear((y_ptr->y_size + newlines) * sizeof(char_u *), TRUE);
2898 if (pp == NULL) // out of memory
2899 return;
2900 for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
2901 pp[lnum] = y_ptr->y_array[lnum];
2902 vim_free(y_ptr->y_array);
2903 y_ptr->y_array = pp;
2904 maxlen = 0;
2905
2906 // Find the end of each line and save it into the array.
2907 if (str_list)
2908 {
2909 for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum)
2910 {
Bram Moolenaar6c4c4042021-06-04 19:17:07 +02002911 pp[lnum] = vim_strsave(*ss);
2912 if (type == MBLOCK)
2913 {
2914 int charlen = mb_string2cells(*ss, -1);
2915
2916 if (charlen > maxlen)
2917 maxlen = charlen;
2918 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002919 }
2920 }
2921 else
2922 {
2923 for (start = 0; start < len + extraline; start += i + 1)
2924 {
Bram Moolenaar6c4c4042021-06-04 19:17:07 +02002925 int charlen = 0;
2926
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002927 for (i = start; i < len; ++i) // find the end of the line
Bram Moolenaar24951a62021-06-04 18:33:49 +02002928 {
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002929 if (str[i] == '\n')
2930 break;
Bram Moolenaar6c4c4042021-06-04 19:17:07 +02002931 if (type == MBLOCK)
2932 charlen += mb_ptr2cells_len(str + i, len - i);
Bram Moolenaar24951a62021-06-04 18:33:49 +02002933 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002934 i -= start; // i is now length of line
Bram Moolenaar6e0b5532021-06-04 17:11:47 +02002935 if (charlen > maxlen)
2936 maxlen = charlen;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002937 if (append)
2938 {
2939 --lnum;
2940 extra = (int)STRLEN(y_ptr->y_array[lnum]);
2941 }
2942 else
2943 extra = 0;
2944 s = alloc(i + extra + 1);
2945 if (s == NULL)
2946 break;
2947 if (extra)
2948 mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
2949 if (append)
2950 vim_free(y_ptr->y_array[lnum]);
Bram Moolenaar24951a62021-06-04 18:33:49 +02002951 if (i > 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002952 mch_memmove(s + extra, str + start, (size_t)i);
2953 extra += i;
2954 s[extra] = NUL;
2955 y_ptr->y_array[lnum++] = s;
2956 while (--extra >= 0)
2957 {
2958 if (*s == NUL)
2959 *s = '\n'; // replace NUL with newline
2960 ++s;
2961 }
2962 append = FALSE; // only first line is appended
2963 }
2964 }
2965 y_ptr->y_type = type;
2966 y_ptr->y_size = lnum;
2967 if (type == MBLOCK)
2968 y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
2969 else
2970 y_ptr->y_width = 0;
2971# ifdef FEAT_VIMINFO
2972 y_ptr->y_time_set = vim_time();
2973# endif
2974}
2975#endif // FEAT_CLIPBOARD || FEAT_EVAL || PROTO