blob: 0c714c69c50efbbee1001304e41a1917c8fa7e5f [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
Yegappan Lakshmanan41a7f822021-06-16 15:53:17 +0200465/*
466 * Last executed register (@ command)
467 */
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200468static int execreg_lastc = NUL;
469
470 int
471get_execreg_lastc(void)
472{
473 return execreg_lastc;
474}
475
476 void
477set_execreg_lastc(int lastc)
478{
479 execreg_lastc = lastc;
480}
481
482/*
Bram Moolenaar856c1112020-06-17 21:47:23 +0200483 * When executing a register as a series of ex-commands, if the
484 * line-continuation character is used for a line, then join it with one or
485 * more previous lines. Note that lines are processed backwards starting from
486 * the last line in the register.
487 *
488 * Arguments:
489 * lines - list of lines in the register
490 * idx - index of the line starting with \ or "\. Join this line with all the
491 * immediate predecessor lines that start with a \ and the first line
492 * that doesn't start with a \. Lines that start with a comment "\
493 * character are ignored.
494 *
495 * Returns the concatenated line. The index of the line that should be
496 * processed next is returned in idx.
497 */
498 static char_u *
499execreg_line_continuation(char_u **lines, long *idx)
500{
501 garray_T ga;
502 long i = *idx;
503 char_u *p;
504 int cmd_start;
505 int cmd_end = i;
506 int j;
507 char_u *str;
508
509 ga_init2(&ga, (int)sizeof(char_u), 400);
510
511 // search backwards to find the first line of this command.
512 // Any line not starting with \ or "\ is the start of the
513 // command.
514 while (--i > 0)
515 {
516 p = skipwhite(lines[i]);
517 if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' '))
518 break;
519 }
520 cmd_start = i;
521
522 // join all the lines
523 ga_concat(&ga, lines[cmd_start]);
524 for (j = cmd_start + 1; j <= cmd_end; j++)
525 {
526 p = skipwhite(lines[j]);
527 if (*p == '\\')
528 {
529 // Adjust the growsize to the current length to
530 // speed up concatenating many lines.
531 if (ga.ga_len > 400)
532 {
533 if (ga.ga_len > 8000)
534 ga.ga_growsize = 8000;
535 else
536 ga.ga_growsize = ga.ga_len;
537 }
538 ga_concat(&ga, p + 1);
539 }
540 }
541 ga_append(&ga, NUL);
542 str = vim_strsave(ga.ga_data);
543 ga_clear(&ga);
544
545 *idx = i;
546 return str;
547}
548
549/*
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200550 * Execute a yank register: copy it into the stuff buffer.
551 *
552 * Return FAIL for failure, OK otherwise.
553 */
554 int
555do_execreg(
556 int regname,
557 int colon, // insert ':' before each line
558 int addcr, // always add '\n' to end of line
559 int silent) // set "silent" flag in typeahead buffer
560{
561 long i;
562 char_u *p;
563 int retval = OK;
564 int remap;
565
566 // repeat previous one
567 if (regname == '@')
568 {
569 if (execreg_lastc == NUL)
570 {
571 emsg(_("E748: No previously used register"));
572 return FAIL;
573 }
574 regname = execreg_lastc;
575 }
576 // check for valid regname
577 if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
578 {
579 emsg_invreg(regname);
580 return FAIL;
581 }
582 execreg_lastc = regname;
583
584#ifdef FEAT_CLIPBOARD
585 regname = may_get_selection(regname);
586#endif
587
588 // black hole: don't stuff anything
589 if (regname == '_')
590 return OK;
591
592 // use last command line
593 if (regname == ':')
594 {
595 if (last_cmdline == NULL)
596 {
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200597 emsg(_(e_no_previous_command_line));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200598 return FAIL;
599 }
600 // don't keep the cmdline containing @:
601 VIM_CLEAR(new_last_cmdline);
602 // Escape all control characters with a CTRL-V
603 p = vim_strsave_escaped_ext(last_cmdline,
604 (char_u *)"\001\002\003\004\005\006\007"
605 "\010\011\012\013\014\015\016\017"
606 "\020\021\022\023\024\025\026\027"
607 "\030\031\032\033\034\035\036\037",
608 Ctrl_V, FALSE);
609 if (p != NULL)
610 {
611 // When in Visual mode "'<,'>" will be prepended to the command.
612 // Remove it when it's already there.
613 if (VIsual_active && STRNCMP(p, "'<,'>", 5) == 0)
614 retval = put_in_typebuf(p + 5, TRUE, TRUE, silent);
615 else
616 retval = put_in_typebuf(p, TRUE, TRUE, silent);
617 }
618 vim_free(p);
619 }
620#ifdef FEAT_EVAL
621 else if (regname == '=')
622 {
623 p = get_expr_line();
624 if (p == NULL)
625 return FAIL;
626 retval = put_in_typebuf(p, TRUE, colon, silent);
627 vim_free(p);
628 }
629#endif
630 else if (regname == '.') // use last inserted text
631 {
632 p = get_last_insert_save();
633 if (p == NULL)
634 {
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200635 emsg(_(e_no_inserted_text_yet));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200636 return FAIL;
637 }
638 retval = put_in_typebuf(p, FALSE, colon, silent);
639 vim_free(p);
640 }
641 else
642 {
643 get_yank_register(regname, FALSE);
644 if (y_current->y_array == NULL)
645 return FAIL;
646
Bram Moolenaar4b96df52020-01-26 22:00:26 +0100647 // Disallow remapping for ":@r".
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200648 remap = colon ? REMAP_NONE : REMAP_YES;
649
650 // Insert lines into typeahead buffer, from last one to first one.
651 put_reedit_in_typebuf(silent);
652 for (i = y_current->y_size; --i >= 0; )
653 {
654 char_u *escaped;
Bram Moolenaar856c1112020-06-17 21:47:23 +0200655 char_u *str;
656 int free_str = FALSE;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200657
658 // insert NL between lines and after last line if type is MLINE
659 if (y_current->y_type == MLINE || i < y_current->y_size - 1
660 || addcr)
661 {
662 if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL)
663 return FAIL;
664 }
Bram Moolenaar856c1112020-06-17 21:47:23 +0200665
666 // Handle line-continuation for :@<register>
667 str = y_current->y_array[i];
668 if (colon && i > 0)
669 {
670 p = skipwhite(str);
671 if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' '))
672 {
673 str = execreg_line_continuation(y_current->y_array, &i);
674 if (str == NULL)
675 return FAIL;
676 free_str = TRUE;
677 }
678 }
679 escaped = vim_strsave_escape_csi(str);
680 if (free_str)
681 vim_free(str);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200682 if (escaped == NULL)
683 return FAIL;
684 retval = ins_typebuf(escaped, remap, 0, TRUE, silent);
685 vim_free(escaped);
686 if (retval == FAIL)
687 return FAIL;
688 if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, silent)
689 == FAIL)
690 return FAIL;
691 }
692 reg_executing = regname == 0 ? '"' : regname; // disable "q" command
693 }
694 return retval;
695}
696
697/*
698 * If "restart_edit" is not zero, put it in the typeahead buffer, so that it's
699 * used only after other typeahead has been processed.
700 */
701 static void
702put_reedit_in_typebuf(int silent)
703{
704 char_u buf[3];
705
706 if (restart_edit != NUL)
707 {
708 if (restart_edit == 'V')
709 {
710 buf[0] = 'g';
711 buf[1] = 'R';
712 buf[2] = NUL;
713 }
714 else
715 {
716 buf[0] = restart_edit == 'I' ? 'i' : restart_edit;
717 buf[1] = NUL;
718 }
719 if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, silent) == OK)
720 restart_edit = NUL;
721 }
722}
723
724/*
725 * Insert register contents "s" into the typeahead buffer, so that it will be
726 * executed again.
727 * When "esc" is TRUE it is to be taken literally: Escape CSI characters and
728 * no remapping.
729 */
730 static int
731put_in_typebuf(
732 char_u *s,
733 int esc,
734 int colon, // add ':' before the line
735 int silent)
736{
737 int retval = OK;
738
739 put_reedit_in_typebuf(silent);
740 if (colon)
741 retval = ins_typebuf((char_u *)"\n", REMAP_NONE, 0, TRUE, silent);
742 if (retval == OK)
743 {
744 char_u *p;
745
746 if (esc)
747 p = vim_strsave_escape_csi(s);
748 else
749 p = s;
750 if (p == NULL)
751 retval = FAIL;
752 else
753 retval = ins_typebuf(p, esc ? REMAP_NONE : REMAP_YES,
754 0, TRUE, silent);
755 if (esc)
756 vim_free(p);
757 }
758 if (colon && retval == OK)
759 retval = ins_typebuf((char_u *)":", REMAP_NONE, 0, TRUE, silent);
760 return retval;
761}
762
763/*
764 * Insert a yank register: copy it into the Read buffer.
765 * Used by CTRL-R command and middle mouse button in insert mode.
766 *
767 * return FAIL for failure, OK otherwise
768 */
769 int
770insert_reg(
771 int regname,
772 int literally_arg) // insert literally, not as if typed
773{
774 long i;
775 int retval = OK;
776 char_u *arg;
777 int allocated;
778 int literally = literally_arg;
779
780 // It is possible to get into an endless loop by having CTRL-R a in
781 // register a and then, in insert mode, doing CTRL-R a.
782 // If you hit CTRL-C, the loop will be broken here.
783 ui_breakcheck();
784 if (got_int)
785 return FAIL;
786
787 // check for valid regname
788 if (regname != NUL && !valid_yank_reg(regname, FALSE))
789 return FAIL;
790
791#ifdef FEAT_CLIPBOARD
792 regname = may_get_selection(regname);
793#endif
794
795 if (regname == '.') // insert last inserted text
796 retval = stuff_inserted(NUL, 1L, TRUE);
797 else if (get_spec_reg(regname, &arg, &allocated, TRUE))
798 {
799 if (arg == NULL)
800 return FAIL;
801 stuffescaped(arg, literally);
802 if (allocated)
803 vim_free(arg);
804 }
805 else // name or number register
806 {
807 if (get_yank_register(regname, FALSE))
808 literally = TRUE;
809 if (y_current->y_array == NULL)
810 retval = FAIL;
811 else
812 {
813 for (i = 0; i < y_current->y_size; ++i)
814 {
Bram Moolenaar032a2d02020-12-22 17:59:35 +0100815 if (regname == '-')
816 {
817 AppendCharToRedobuff(Ctrl_R);
818 AppendCharToRedobuff(regname);
819 do_put(regname, NULL, BACKWARD, 1L, PUT_CURSEND);
820 }
821 else
822 stuffescaped(y_current->y_array[i], literally);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200823 // Insert a newline between lines and after last line if
824 // y_type is MLINE.
825 if (y_current->y_type == MLINE || i < y_current->y_size - 1)
826 stuffcharReadbuff('\n');
827 }
828 }
829 }
830
831 return retval;
832}
833
834/*
835 * If "regname" is a special register, return TRUE and store a pointer to its
836 * value in "argp".
837 */
838 int
839get_spec_reg(
840 int regname,
841 char_u **argp,
842 int *allocated, // return: TRUE when value was allocated
843 int errmsg) // give error message when failing
844{
845 int cnt;
846
847 *argp = NULL;
848 *allocated = FALSE;
849 switch (regname)
850 {
851 case '%': // file name
852 if (errmsg)
853 check_fname(); // will give emsg if not set
854 *argp = curbuf->b_fname;
855 return TRUE;
856
857 case '#': // alternate file name
858 *argp = getaltfname(errmsg); // may give emsg if not set
859 return TRUE;
860
861#ifdef FEAT_EVAL
862 case '=': // result of expression
863 *argp = get_expr_line();
864 *allocated = TRUE;
865 return TRUE;
866#endif
867
868 case ':': // last command line
869 if (last_cmdline == NULL && errmsg)
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200870 emsg(_(e_no_previous_command_line));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200871 *argp = last_cmdline;
872 return TRUE;
873
874 case '/': // last search-pattern
875 if (last_search_pat() == NULL && errmsg)
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200876 emsg(_(e_no_previous_regular_expression));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200877 *argp = last_search_pat();
878 return TRUE;
879
880 case '.': // last inserted text
881 *argp = get_last_insert_save();
882 *allocated = TRUE;
883 if (*argp == NULL && errmsg)
Bram Moolenaare29a27f2021-07-20 21:07:36 +0200884 emsg(_(e_no_inserted_text_yet));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200885 return TRUE;
886
887#ifdef FEAT_SEARCHPATH
888 case Ctrl_F: // Filename under cursor
889 case Ctrl_P: // Path under cursor, expand via "path"
890 if (!errmsg)
891 return FALSE;
892 *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP
893 | (regname == Ctrl_P ? FNAME_EXP : 0), 1L, NULL);
894 *allocated = TRUE;
895 return TRUE;
896#endif
897
898 case Ctrl_W: // word under cursor
899 case Ctrl_A: // WORD (mnemonic All) under cursor
900 if (!errmsg)
901 return FALSE;
902 cnt = find_ident_under_cursor(argp, regname == Ctrl_W
903 ? (FIND_IDENT|FIND_STRING) : FIND_STRING);
904 *argp = cnt ? vim_strnsave(*argp, cnt) : NULL;
905 *allocated = TRUE;
906 return TRUE;
907
908 case Ctrl_L: // Line under cursor
909 if (!errmsg)
910 return FALSE;
911
912 *argp = ml_get_buf(curwin->w_buffer,
913 curwin->w_cursor.lnum, FALSE);
914 return TRUE;
915
916 case '_': // black hole: always empty
917 *argp = (char_u *)"";
918 return TRUE;
919 }
920
921 return FALSE;
922}
923
924/*
925 * Paste a yank register into the command line.
926 * Only for non-special registers.
927 * Used by CTRL-R command in command-line mode
928 * insert_reg() can't be used here, because special characters from the
929 * register contents will be interpreted as commands.
930 *
931 * return FAIL for failure, OK otherwise
932 */
933 int
934cmdline_paste_reg(
935 int regname,
936 int literally_arg, // Insert text literally instead of "as typed"
937 int remcr) // don't add CR characters
938{
939 long i;
940 int literally = literally_arg;
941
942 if (get_yank_register(regname, FALSE))
943 literally = TRUE;
944 if (y_current->y_array == NULL)
945 return FAIL;
946
947 for (i = 0; i < y_current->y_size; ++i)
948 {
949 cmdline_paste_str(y_current->y_array[i], literally);
950
951 // Insert ^M between lines and after last line if type is MLINE.
952 // Don't do this when "remcr" is TRUE.
953 if ((y_current->y_type == MLINE || i < y_current->y_size - 1) && !remcr)
954 cmdline_paste_str((char_u *)"\r", literally);
955
956 // Check for CTRL-C, in case someone tries to paste a few thousand
957 // lines and gets bored.
958 ui_breakcheck();
959 if (got_int)
960 return FAIL;
961 }
962 return OK;
963}
964
Bram Moolenaar4aea03e2019-09-25 22:37:17 +0200965/*
966 * Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
967 */
968 void
969shift_delete_registers()
970{
971 int n;
972
973 y_current = &y_regs[9];
974 free_yank_all(); // free register nine
975 for (n = 9; n > 1; --n)
976 y_regs[n] = y_regs[n - 1];
977 y_current = &y_regs[1];
978 if (!y_append)
979 y_previous = y_current;
980 y_regs[1].y_array = NULL; // set register one to empty
981}
982
983#if defined(FEAT_EVAL)
984 void
985yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
986{
987 static int recursive = FALSE;
988 dict_T *v_event;
989 list_T *list;
990 int n;
991 char_u buf[NUMBUFLEN + 2];
992 long reglen = 0;
993
994 if (recursive)
995 return;
996
997 v_event = get_vim_var_dict(VV_EVENT);
998
999 list = list_alloc();
1000 if (list == NULL)
1001 return;
1002 for (n = 0; n < reg->y_size; n++)
1003 list_append_string(list, reg->y_array[n], -1);
1004 list->lv_lock = VAR_FIXED;
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001005 (void)dict_add_list(v_event, "regcontents", list);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001006
1007 buf[0] = (char_u)oap->regname;
1008 buf[1] = NUL;
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001009 (void)dict_add_string(v_event, "regname", buf);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001010
1011 buf[0] = get_op_char(oap->op_type);
1012 buf[1] = get_extra_op_char(oap->op_type);
1013 buf[2] = NUL;
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001014 (void)dict_add_string(v_event, "operator", buf);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001015
1016 buf[0] = NUL;
1017 buf[1] = NUL;
1018 switch (get_reg_type(oap->regname, &reglen))
1019 {
1020 case MLINE: buf[0] = 'V'; break;
1021 case MCHAR: buf[0] = 'v'; break;
1022 case MBLOCK:
1023 vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
1024 reglen + 1);
1025 break;
1026 }
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001027 (void)dict_add_string(v_event, "regtype", buf);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001028
Bram Moolenaar6d90c612020-06-29 20:23:32 +02001029 (void)dict_add_bool(v_event, "visual", oap->is_VIsual);
Bram Moolenaar37d16732020-06-12 22:09:01 +02001030
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001031 // Lock the dictionary and its keys
1032 dict_set_items_ro(v_event);
1033
1034 recursive = TRUE;
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02001035 textwinlock++;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001036 apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02001037 textwinlock--;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001038 recursive = FALSE;
1039
1040 // Empty the dictionary, v:event is still valid
1041 dict_free_contents(v_event);
1042 hash_init(&v_event->dv_hashtab);
1043}
1044#endif
1045
1046/*
1047 * set all the yank registers to empty (called from main())
1048 */
1049 void
1050init_yank(void)
1051{
1052 int i;
1053
1054 for (i = 0; i < NUM_REGISTERS; ++i)
1055 y_regs[i].y_array = NULL;
1056}
1057
1058#if defined(EXITFREE) || defined(PROTO)
1059 void
1060clear_registers(void)
1061{
1062 int i;
1063
1064 for (i = 0; i < NUM_REGISTERS; ++i)
1065 {
1066 y_current = &y_regs[i];
1067 if (y_current->y_array != NULL)
1068 free_yank_all();
1069 }
1070}
1071#endif
1072
1073/*
1074 * Free "n" lines from the current yank register.
1075 * Called for normal freeing and in case of error.
1076 */
1077 static void
1078free_yank(long n)
1079{
1080 if (y_current->y_array != NULL)
1081 {
1082 long i;
1083
1084 for (i = n; --i >= 0; )
1085 {
1086#ifdef AMIGA // only for very slow machines
1087 if ((i & 1023) == 1023) // this may take a while
1088 {
1089 // This message should never cause a hit-return message.
1090 // Overwrite this message with any next message.
1091 ++no_wait_return;
1092 smsg(_("freeing %ld lines"), i + 1);
1093 --no_wait_return;
1094 msg_didout = FALSE;
1095 msg_col = 0;
1096 }
1097#endif
1098 vim_free(y_current->y_array[i]);
1099 }
1100 VIM_CLEAR(y_current->y_array);
1101#ifdef AMIGA
1102 if (n >= 1000)
1103 msg("");
1104#endif
1105 }
1106}
1107
Bram Moolenaar45fffdf2020-03-24 21:42:01 +01001108 void
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001109free_yank_all(void)
1110{
1111 free_yank(y_current->y_size);
1112}
1113
1114/*
1115 * Yank the text between "oap->start" and "oap->end" into a yank register.
1116 * If we are to append (uppercase register), we first yank into a new yank
1117 * register and then concatenate the old and the new one (so we keep the old
1118 * one in case of out-of-memory).
1119 *
1120 * Return FAIL for failure, OK otherwise.
1121 */
1122 int
1123op_yank(oparg_T *oap, int deleting, int mess)
1124{
1125 long y_idx; // index in y_array[]
1126 yankreg_T *curr; // copy of y_current
1127 yankreg_T newreg; // new yank register when appending
1128 char_u **new_ptr;
1129 linenr_T lnum; // current line number
1130 long j;
1131 int yanktype = oap->motion_type;
1132 long yanklines = oap->line_count;
1133 linenr_T yankendlnum = oap->end.lnum;
1134 char_u *p;
1135 char_u *pnew;
1136 struct block_def bd;
1137#if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1138 int did_star = FALSE;
1139#endif
1140
1141 // check for read-only register
1142 if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE))
1143 {
1144 beep_flush();
1145 return FAIL;
1146 }
1147 if (oap->regname == '_') // black hole: nothing to do
1148 return OK;
1149
1150#ifdef FEAT_CLIPBOARD
1151 if (!clip_star.available && oap->regname == '*')
1152 oap->regname = 0;
1153 else if (!clip_plus.available && oap->regname == '+')
1154 oap->regname = 0;
1155#endif
1156
1157 if (!deleting) // op_delete() already set y_current
1158 get_yank_register(oap->regname, TRUE);
1159
1160 curr = y_current;
1161 // append to existing contents
1162 if (y_append && y_current->y_array != NULL)
1163 y_current = &newreg;
1164 else
1165 free_yank_all(); // free previously yanked lines
1166
1167 // If the cursor was in column 1 before and after the movement, and the
1168 // operator is not inclusive, the yank is always linewise.
1169 if ( oap->motion_type == MCHAR
1170 && oap->start.col == 0
1171 && !oap->inclusive
1172 && (!oap->is_VIsual || *p_sel == 'o')
1173 && !oap->block_mode
1174 && oap->end.col == 0
1175 && yanklines > 1)
1176 {
1177 yanktype = MLINE;
1178 --yankendlnum;
1179 --yanklines;
1180 }
1181
1182 y_current->y_size = yanklines;
1183 y_current->y_type = yanktype; // set the yank register type
1184 y_current->y_width = 0;
1185 y_current->y_array = lalloc_clear(sizeof(char_u *) * yanklines, TRUE);
1186 if (y_current->y_array == NULL)
1187 {
1188 y_current = curr;
1189 return FAIL;
1190 }
1191#ifdef FEAT_VIMINFO
1192 y_current->y_time_set = vim_time();
1193#endif
1194
1195 y_idx = 0;
1196 lnum = oap->start.lnum;
1197
1198 if (oap->block_mode)
1199 {
1200 // Visual block mode
1201 y_current->y_type = MBLOCK; // set the yank register type
1202 y_current->y_width = oap->end_vcol - oap->start_vcol;
1203
1204 if (curwin->w_curswant == MAXCOL && y_current->y_width > 0)
1205 y_current->y_width--;
1206 }
1207
1208 for ( ; lnum <= yankendlnum; lnum++, y_idx++)
1209 {
1210 switch (y_current->y_type)
1211 {
1212 case MBLOCK:
1213 block_prep(oap, &bd, lnum, FALSE);
Christian Brabandt544a38e2021-06-10 19:39:11 +02001214 if (yank_copy_line(&bd, y_idx, oap->excl_tr_ws) == FAIL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001215 goto fail;
1216 break;
1217
1218 case MLINE:
1219 if ((y_current->y_array[y_idx] =
Christian Brabandt544a38e2021-06-10 19:39:11 +02001220 vim_strsave(ml_get(lnum))) == NULL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001221 goto fail;
1222 break;
1223
1224 case MCHAR:
1225 {
1226 colnr_T startcol = 0, endcol = MAXCOL;
Christian Brabandt544a38e2021-06-10 19:39:11 +02001227 int is_oneChar = FALSE;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001228 colnr_T cs, ce;
1229
1230 p = ml_get(lnum);
1231 bd.startspaces = 0;
1232 bd.endspaces = 0;
1233
1234 if (lnum == oap->start.lnum)
1235 {
1236 startcol = oap->start.col;
1237 if (virtual_op)
1238 {
1239 getvcol(curwin, &oap->start, &cs, NULL, &ce);
1240 if (ce != cs && oap->start.coladd > 0)
1241 {
1242 // Part of a tab selected -- but don't
1243 // double-count it.
1244 bd.startspaces = (ce - cs + 1)
1245 - oap->start.coladd;
1246 startcol++;
1247 }
1248 }
1249 }
1250
1251 if (lnum == oap->end.lnum)
1252 {
1253 endcol = oap->end.col;
1254 if (virtual_op)
1255 {
1256 getvcol(curwin, &oap->end, &cs, NULL, &ce);
1257 if (p[endcol] == NUL || (cs + oap->end.coladd < ce
1258 // Don't add space for double-wide
1259 // char; endcol will be on last byte
1260 // of multi-byte char.
1261 && (*mb_head_off)(p, p + endcol) == 0))
1262 {
1263 if (oap->start.lnum == oap->end.lnum
1264 && oap->start.col == oap->end.col)
1265 {
1266 // Special case: inside a single char
1267 is_oneChar = TRUE;
1268 bd.startspaces = oap->end.coladd
1269 - oap->start.coladd + oap->inclusive;
1270 endcol = startcol;
1271 }
1272 else
1273 {
1274 bd.endspaces = oap->end.coladd
1275 + oap->inclusive;
1276 endcol -= oap->inclusive;
1277 }
1278 }
1279 }
1280 }
1281 if (endcol == MAXCOL)
1282 endcol = (colnr_T)STRLEN(p);
1283 if (startcol > endcol || is_oneChar)
1284 bd.textlen = 0;
1285 else
1286 bd.textlen = endcol - startcol + oap->inclusive;
1287 bd.textstart = p + startcol;
Christian Brabandt544a38e2021-06-10 19:39:11 +02001288 if (yank_copy_line(&bd, y_idx, FALSE) == FAIL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001289 goto fail;
1290 break;
1291 }
1292 // NOTREACHED
1293 }
1294 }
1295
1296 if (curr != y_current) // append the new block to the old block
1297 {
1298 new_ptr = ALLOC_MULT(char_u *, curr->y_size + y_current->y_size);
1299 if (new_ptr == NULL)
1300 goto fail;
1301 for (j = 0; j < curr->y_size; ++j)
1302 new_ptr[j] = curr->y_array[j];
1303 vim_free(curr->y_array);
1304 curr->y_array = new_ptr;
1305#ifdef FEAT_VIMINFO
1306 curr->y_time_set = vim_time();
1307#endif
1308
1309 if (yanktype == MLINE) // MLINE overrides MCHAR and MBLOCK
1310 curr->y_type = MLINE;
1311
1312 // Concatenate the last line of the old block with the first line of
1313 // the new block, unless being Vi compatible.
1314 if (curr->y_type == MCHAR && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL)
1315 {
1316 pnew = alloc(STRLEN(curr->y_array[curr->y_size - 1])
1317 + STRLEN(y_current->y_array[0]) + 1);
1318 if (pnew == NULL)
1319 {
1320 y_idx = y_current->y_size - 1;
1321 goto fail;
1322 }
1323 STRCPY(pnew, curr->y_array[--j]);
1324 STRCAT(pnew, y_current->y_array[0]);
1325 vim_free(curr->y_array[j]);
1326 vim_free(y_current->y_array[0]);
1327 curr->y_array[j++] = pnew;
1328 y_idx = 1;
1329 }
1330 else
1331 y_idx = 0;
1332 while (y_idx < y_current->y_size)
1333 curr->y_array[j++] = y_current->y_array[y_idx++];
1334 curr->y_size = j;
1335 vim_free(y_current->y_array);
1336 y_current = curr;
1337 }
1338 if (curwin->w_p_rnu)
1339 redraw_later(SOME_VALID); // cursor moved to start
1340 if (mess) // Display message about yank?
1341 {
1342 if (yanktype == MCHAR
1343 && !oap->block_mode
1344 && yanklines == 1)
1345 yanklines = 0;
Bram Moolenaar32aa1022019-11-02 22:54:41 +01001346 // Some versions of Vi use ">=" here, some don't...
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001347 if (yanklines > p_report)
1348 {
1349 char namebuf[100];
1350
1351 if (oap->regname == NUL)
1352 *namebuf = NUL;
1353 else
1354 vim_snprintf(namebuf, sizeof(namebuf),
1355 _(" into \"%c"), oap->regname);
1356
1357 // redisplay now, so message is not deleted
1358 update_topline_redraw();
1359 if (oap->block_mode)
1360 {
1361 smsg(NGETTEXT("block of %ld line yanked%s",
1362 "block of %ld lines yanked%s", yanklines),
1363 yanklines, namebuf);
1364 }
1365 else
1366 {
1367 smsg(NGETTEXT("%ld line yanked%s",
1368 "%ld lines yanked%s", yanklines),
1369 yanklines, namebuf);
1370 }
1371 }
1372 }
1373
Bram Moolenaare1004402020-10-24 20:49:43 +02001374 if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001375 {
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001376 // Set "'[" and "']" marks.
1377 curbuf->b_op_start = oap->start;
1378 curbuf->b_op_end = oap->end;
1379 if (yanktype == MLINE && !oap->block_mode)
1380 {
1381 curbuf->b_op_start.col = 0;
1382 curbuf->b_op_end.col = MAXCOL;
1383 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001384 }
1385
1386#ifdef FEAT_CLIPBOARD
1387 // If we were yanking to the '*' register, send result to clipboard.
1388 // If no register was specified, and "unnamed" in 'clipboard', make a copy
1389 // to the '*' register.
1390 if (clip_star.available
1391 && (curr == &(y_regs[STAR_REGISTER])
1392 || (!deleting && oap->regname == 0
1393 && ((clip_unnamed | clip_unnamed_saved) & CLIP_UNNAMED))))
1394 {
1395 if (curr != &(y_regs[STAR_REGISTER]))
1396 // Copy the text from register 0 to the clipboard register.
1397 copy_yank_reg(&(y_regs[STAR_REGISTER]));
1398
1399 clip_own_selection(&clip_star);
1400 clip_gen_set_selection(&clip_star);
1401# ifdef FEAT_X11
1402 did_star = TRUE;
1403# endif
1404 }
1405
1406# ifdef FEAT_X11
1407 // If we were yanking to the '+' register, send result to selection.
Bram Moolenaar37096af2021-03-02 19:04:11 +01001408 // Also copy to the '*' register, in case auto-select is off. But not when
1409 // 'clipboard' has "unnamedplus" and not "unnamed".
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001410 if (clip_plus.available
1411 && (curr == &(y_regs[PLUS_REGISTER])
1412 || (!deleting && oap->regname == 0
1413 && ((clip_unnamed | clip_unnamed_saved) &
Bram Moolenaar37096af2021-03-02 19:04:11 +01001414 CLIP_UNNAMED_PLUS))))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001415 {
1416 if (curr != &(y_regs[PLUS_REGISTER]))
1417 // Copy the text from register 0 to the clipboard register.
1418 copy_yank_reg(&(y_regs[PLUS_REGISTER]));
1419
1420 clip_own_selection(&clip_plus);
1421 clip_gen_set_selection(&clip_plus);
Bram Moolenaar37096af2021-03-02 19:04:11 +01001422 if (!clip_isautosel_star()
1423 && !clip_isautosel_plus()
1424 && !((clip_unnamed | clip_unnamed_saved) == CLIP_UNNAMED_PLUS)
1425 && !did_star
1426 && curr == &(y_regs[PLUS_REGISTER]))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001427 {
1428 copy_yank_reg(&(y_regs[STAR_REGISTER]));
1429 clip_own_selection(&clip_star);
1430 clip_gen_set_selection(&clip_star);
1431 }
1432 }
1433# endif
1434#endif
1435
1436#if defined(FEAT_EVAL)
1437 if (!deleting && has_textyankpost())
1438 yank_do_autocmd(oap, y_current);
1439#endif
1440
1441 return OK;
1442
1443fail: // free the allocated lines
1444 free_yank(y_idx + 1);
1445 y_current = curr;
1446 return FAIL;
1447}
1448
Christian Brabandt544a38e2021-06-10 19:39:11 +02001449/*
1450 * Copy a block range into a register.
1451 * If "exclude_trailing_space" is set, do not copy trailing whitespaces.
1452 */
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001453 static int
Christian Brabandt544a38e2021-06-10 19:39:11 +02001454yank_copy_line(struct block_def *bd, long y_idx, int exclude_trailing_space)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001455{
1456 char_u *pnew;
1457
Bram Moolenaar7d7bcc62021-06-28 21:54:27 +02001458 if (exclude_trailing_space)
1459 bd->endspaces = 0;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001460 if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1))
1461 == NULL)
1462 return FAIL;
1463 y_current->y_array[y_idx] = pnew;
1464 vim_memset(pnew, ' ', (size_t)bd->startspaces);
1465 pnew += bd->startspaces;
1466 mch_memmove(pnew, bd->textstart, (size_t)bd->textlen);
1467 pnew += bd->textlen;
1468 vim_memset(pnew, ' ', (size_t)bd->endspaces);
1469 pnew += bd->endspaces;
Christian Brabandt544a38e2021-06-10 19:39:11 +02001470 if (exclude_trailing_space)
1471 {
1472 int s = bd->textlen + bd->endspaces;
1473
1474 while (VIM_ISWHITE(*(bd->textstart + s - 1)) && s > 0)
1475 {
1476 s = s - (*mb_head_off)(bd->textstart, bd->textstart + s - 1) - 1;
1477 pnew--;
1478 }
1479 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001480 *pnew = NUL;
1481 return OK;
1482}
1483
1484#ifdef FEAT_CLIPBOARD
1485/*
1486 * Make a copy of the y_current register to register "reg".
1487 */
1488 static void
1489copy_yank_reg(yankreg_T *reg)
1490{
1491 yankreg_T *curr = y_current;
1492 long j;
1493
1494 y_current = reg;
1495 free_yank_all();
1496 *y_current = *curr;
1497 y_current->y_array = lalloc_clear(
1498 sizeof(char_u *) * y_current->y_size, TRUE);
1499 if (y_current->y_array == NULL)
1500 y_current->y_size = 0;
1501 else
1502 for (j = 0; j < y_current->y_size; ++j)
1503 if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL)
1504 {
1505 free_yank(j);
1506 y_current->y_size = 0;
1507 break;
1508 }
1509 y_current = curr;
1510}
1511#endif
1512
1513/*
1514 * Put contents of register "regname" into the text.
1515 * Caller must check "regname" to be valid!
1516 * "flags": PUT_FIXINDENT make indent look nice
1517 * PUT_CURSEND leave cursor after end of new text
1518 * PUT_LINE force linewise put (":put")
Christian Brabandt2fa93842021-05-30 22:17:25 +02001519 * PUT_BLOCK_INNER in block mode, do not add trailing spaces
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001520 */
1521 void
1522do_put(
1523 int regname,
Bram Moolenaarc3516f72020-09-08 22:45:35 +02001524 char_u *expr_result, // result for regname "=" when compiled
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001525 int dir, // BACKWARD for 'P', FORWARD for 'p'
1526 long count,
1527 int flags)
1528{
1529 char_u *ptr;
1530 char_u *newp, *oldp;
1531 int yanklen;
1532 int totlen = 0; // init for gcc
1533 linenr_T lnum;
1534 colnr_T col;
1535 long i; // index in y_array[]
1536 int y_type;
1537 long y_size;
1538 int oldlen;
1539 long y_width = 0;
1540 colnr_T vcol;
1541 int delcount;
1542 int incr = 0;
1543 long j;
1544 struct block_def bd;
1545 char_u **y_array = NULL;
1546 long nr_lines = 0;
1547 pos_T new_cursor;
1548 int indent;
1549 int orig_indent = 0; // init for gcc
1550 int indent_diff = 0; // init for gcc
1551 int first_indent = TRUE;
1552 int lendiff = 0;
1553 pos_T old_pos;
1554 char_u *insert_string = NULL;
1555 int allocated = FALSE;
1556 long cnt;
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01001557 pos_T orig_start = curbuf->b_op_start;
1558 pos_T orig_end = curbuf->b_op_end;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001559
1560#ifdef FEAT_CLIPBOARD
1561 // Adjust register name for "unnamed" in 'clipboard'.
1562 adjust_clip_reg(&regname);
1563 (void)may_get_selection(regname);
1564#endif
1565
1566 if (flags & PUT_FIXINDENT)
1567 orig_indent = get_indent();
1568
1569 curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
1570 curbuf->b_op_end = curwin->w_cursor; // default for '] mark
1571
1572 // Using inserted text works differently, because the register includes
1573 // special characters (newlines, etc.).
1574 if (regname == '.')
1575 {
1576 if (VIsual_active)
1577 stuffcharReadbuff(VIsual_mode);
1578 (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
1579 (count == -1 ? 'O' : 'i')), count, FALSE);
1580 // Putting the text is done later, so can't really move the cursor to
1581 // the next character. Use "l" to simulate it.
1582 if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
1583 stuffcharReadbuff('l');
1584 return;
1585 }
1586
1587 // For special registers '%' (file name), '#' (alternate file name) and
1588 // ':' (last command line), etc. we have to create a fake yank register.
Bram Moolenaarc3516f72020-09-08 22:45:35 +02001589 // For compiled code "expr_result" holds the expression result.
1590 if (regname == '=' && expr_result != NULL)
1591 insert_string = expr_result;
1592 else if (get_spec_reg(regname, &insert_string, &allocated, TRUE)
1593 && insert_string == NULL)
1594 return;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001595
1596 // Autocommands may be executed when saving lines for undo. This might
1597 // make "y_array" invalid, so we start undo now to avoid that.
1598 if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL)
1599 goto end;
1600
1601 if (insert_string != NULL)
1602 {
1603 y_type = MCHAR;
1604#ifdef FEAT_EVAL
1605 if (regname == '=')
1606 {
1607 // For the = register we need to split the string at NL
1608 // characters.
1609 // Loop twice: count the number of lines and save them.
1610 for (;;)
1611 {
1612 y_size = 0;
1613 ptr = insert_string;
1614 while (ptr != NULL)
1615 {
1616 if (y_array != NULL)
1617 y_array[y_size] = ptr;
1618 ++y_size;
1619 ptr = vim_strchr(ptr, '\n');
1620 if (ptr != NULL)
1621 {
1622 if (y_array != NULL)
1623 *ptr = NUL;
1624 ++ptr;
1625 // A trailing '\n' makes the register linewise.
1626 if (*ptr == NUL)
1627 {
1628 y_type = MLINE;
1629 break;
1630 }
1631 }
1632 }
1633 if (y_array != NULL)
1634 break;
1635 y_array = ALLOC_MULT(char_u *, y_size);
1636 if (y_array == NULL)
1637 goto end;
1638 }
1639 }
1640 else
1641#endif
1642 {
1643 y_size = 1; // use fake one-line yank register
1644 y_array = &insert_string;
1645 }
1646 }
1647 else
1648 {
1649 get_yank_register(regname, FALSE);
1650
1651 y_type = y_current->y_type;
1652 y_width = y_current->y_width;
1653 y_size = y_current->y_size;
1654 y_array = y_current->y_array;
1655 }
1656
1657 if (y_type == MLINE)
1658 {
1659 if (flags & PUT_LINE_SPLIT)
1660 {
1661 char_u *p;
1662
1663 // "p" or "P" in Visual mode: split the lines to put the text in
1664 // between.
1665 if (u_save_cursor() == FAIL)
1666 goto end;
1667 p = ml_get_cursor();
1668 if (dir == FORWARD && *p != NUL)
1669 MB_PTR_ADV(p);
1670 ptr = vim_strsave(p);
1671 if (ptr == NULL)
1672 goto end;
1673 ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE);
1674 vim_free(ptr);
1675
1676 oldp = ml_get_curline();
1677 p = oldp + curwin->w_cursor.col;
1678 if (dir == FORWARD && *p != NUL)
1679 MB_PTR_ADV(p);
1680 ptr = vim_strnsave(oldp, p - oldp);
1681 if (ptr == NULL)
1682 goto end;
1683 ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
1684 ++nr_lines;
1685 dir = FORWARD;
1686 }
1687 if (flags & PUT_LINE_FORWARD)
1688 {
1689 // Must be "p" for a Visual block, put lines below the block.
1690 curwin->w_cursor = curbuf->b_visual.vi_end;
1691 dir = FORWARD;
1692 }
1693 curbuf->b_op_start = curwin->w_cursor; // default for '[ mark
1694 curbuf->b_op_end = curwin->w_cursor; // default for '] mark
1695 }
1696
1697 if (flags & PUT_LINE) // :put command or "p" in Visual line mode.
1698 y_type = MLINE;
1699
1700 if (y_size == 0 || y_array == NULL)
1701 {
1702 semsg(_("E353: Nothing in register %s"),
1703 regname == 0 ? (char_u *)"\"" : transchar(regname));
1704 goto end;
1705 }
1706
1707 if (y_type == MBLOCK)
1708 {
1709 lnum = curwin->w_cursor.lnum + y_size + 1;
1710 if (lnum > curbuf->b_ml.ml_line_count)
1711 lnum = curbuf->b_ml.ml_line_count + 1;
1712 if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
1713 goto end;
1714 }
1715 else if (y_type == MLINE)
1716 {
1717 lnum = curwin->w_cursor.lnum;
1718#ifdef FEAT_FOLDING
1719 // Correct line number for closed fold. Don't move the cursor yet,
1720 // u_save() uses it.
1721 if (dir == BACKWARD)
1722 (void)hasFolding(lnum, &lnum, NULL);
1723 else
1724 (void)hasFolding(lnum, NULL, &lnum);
1725#endif
1726 if (dir == FORWARD)
1727 ++lnum;
1728 // In an empty buffer the empty line is going to be replaced, include
1729 // it in the saved lines.
1730 if ((BUFEMPTY() ? u_save(0, 2) : u_save(lnum - 1, lnum)) == FAIL)
1731 goto end;
1732#ifdef FEAT_FOLDING
1733 if (dir == FORWARD)
1734 curwin->w_cursor.lnum = lnum - 1;
1735 else
1736 curwin->w_cursor.lnum = lnum;
1737 curbuf->b_op_start = curwin->w_cursor; // for mark_adjust()
1738#endif
1739 }
1740 else if (u_save_cursor() == FAIL)
1741 goto end;
1742
1743 yanklen = (int)STRLEN(y_array[0]);
1744
1745 if (ve_flags == VE_ALL && y_type == MCHAR)
1746 {
1747 if (gchar_cursor() == TAB)
1748 {
Bram Moolenaar6f1f0ca2019-12-01 18:16:18 +01001749 int viscol = getviscol();
1750 int ts = curbuf->b_p_ts;
1751
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001752 // Don't need to insert spaces when "p" on the last position of a
1753 // tab or "P" on the first position.
Bram Moolenaar6f1f0ca2019-12-01 18:16:18 +01001754 if (dir == FORWARD ?
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001755#ifdef FEAT_VARTABS
Bram Moolenaar6f1f0ca2019-12-01 18:16:18 +01001756 tabstop_padding(viscol, ts, curbuf->b_p_vts_array) != 1
1757#else
1758 ts - (viscol % ts) != 1
1759#endif
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001760 : curwin->w_cursor.coladd > 0)
1761 coladvance_force(viscol);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001762 else
1763 curwin->w_cursor.coladd = 0;
1764 }
1765 else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL)
1766 coladvance_force(getviscol() + (dir == FORWARD));
1767 }
1768
1769 lnum = curwin->w_cursor.lnum;
1770 col = curwin->w_cursor.col;
1771
1772 // Block mode
1773 if (y_type == MBLOCK)
1774 {
1775 int c = gchar_cursor();
1776 colnr_T endcol2 = 0;
1777
1778 if (dir == FORWARD && c != NUL)
1779 {
1780 if (ve_flags == VE_ALL)
1781 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
1782 else
1783 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
1784
1785 if (has_mbyte)
1786 // move to start of next multi-byte character
1787 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor());
1788 else
1789 if (c != TAB || ve_flags != VE_ALL)
1790 ++curwin->w_cursor.col;
1791 ++col;
1792 }
1793 else
1794 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2);
1795
1796 col += curwin->w_cursor.coladd;
1797 if (ve_flags == VE_ALL
1798 && (curwin->w_cursor.coladd > 0
1799 || endcol2 == curwin->w_cursor.col))
1800 {
1801 if (dir == FORWARD && c == NUL)
1802 ++col;
Bram Moolenaaref85a9b2020-07-10 20:24:07 +02001803 if (dir != FORWARD && c != NUL && curwin->w_cursor.coladd > 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001804 ++curwin->w_cursor.col;
1805 if (c == TAB)
1806 {
1807 if (dir == BACKWARD && curwin->w_cursor.col)
1808 curwin->w_cursor.col--;
1809 if (dir == FORWARD && col - 1 == endcol2)
1810 curwin->w_cursor.col++;
1811 }
1812 }
1813 curwin->w_cursor.coladd = 0;
1814 bd.textcol = 0;
1815 for (i = 0; i < y_size; ++i)
1816 {
Christian Brabandt2fa93842021-05-30 22:17:25 +02001817 int spaces = 0;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001818 char shortline;
1819
1820 bd.startspaces = 0;
1821 bd.endspaces = 0;
1822 vcol = 0;
1823 delcount = 0;
1824
1825 // add a new line
1826 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
1827 {
1828 if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
1829 (colnr_T)1, FALSE) == FAIL)
1830 break;
1831 ++nr_lines;
1832 }
1833 // get the old line and advance to the position to insert at
1834 oldp = ml_get_curline();
1835 oldlen = (int)STRLEN(oldp);
1836 for (ptr = oldp; vcol < col && *ptr; )
1837 {
1838 // Count a tab for what it's worth (if list mode not on)
1839 incr = lbr_chartabsize_adv(oldp, &ptr, (colnr_T)vcol);
1840 vcol += incr;
1841 }
1842 bd.textcol = (colnr_T)(ptr - oldp);
1843
1844 shortline = (vcol < col) || (vcol == col && !*ptr) ;
1845
1846 if (vcol < col) // line too short, padd with spaces
1847 bd.startspaces = col - vcol;
1848 else if (vcol > col)
1849 {
1850 bd.endspaces = vcol - col;
1851 bd.startspaces = incr - bd.endspaces;
1852 --bd.textcol;
1853 delcount = 1;
1854 if (has_mbyte)
1855 bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol);
1856 if (oldp[bd.textcol] != TAB)
1857 {
1858 // Only a Tab can be split into spaces. Other
1859 // characters will have to be moved to after the
1860 // block, causing misalignment.
1861 delcount = 0;
1862 bd.endspaces = 0;
1863 }
1864 }
1865
1866 yanklen = (int)STRLEN(y_array[i]);
1867
Christian Brabandt2fa93842021-05-30 22:17:25 +02001868 if ((flags & PUT_BLOCK_INNER) == 0)
1869 {
1870 // calculate number of spaces required to fill right side of
1871 // block
1872 spaces = y_width + 1;
1873 for (j = 0; j < yanklen; j++)
1874 spaces -= lbr_chartabsize(NULL, &y_array[i][j], 0);
1875 if (spaces < 0)
1876 spaces = 0;
1877 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001878
1879 // insert the new text
1880 totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces;
1881 newp = alloc(totlen + oldlen + 1);
1882 if (newp == NULL)
1883 break;
1884 // copy part up to cursor to new line
1885 ptr = newp;
1886 mch_memmove(ptr, oldp, (size_t)bd.textcol);
1887 ptr += bd.textcol;
1888 // may insert some spaces before the new text
1889 vim_memset(ptr, ' ', (size_t)bd.startspaces);
1890 ptr += bd.startspaces;
1891 // insert the new text
1892 for (j = 0; j < count; ++j)
1893 {
1894 mch_memmove(ptr, y_array[i], (size_t)yanklen);
1895 ptr += yanklen;
1896
1897 // insert block's trailing spaces only if there's text behind
1898 if ((j < count - 1 || !shortline) && spaces)
1899 {
1900 vim_memset(ptr, ' ', (size_t)spaces);
1901 ptr += spaces;
1902 }
1903 }
1904 // may insert some spaces after the new text
1905 vim_memset(ptr, ' ', (size_t)bd.endspaces);
1906 ptr += bd.endspaces;
1907 // move the text after the cursor to the end of the line.
1908 mch_memmove(ptr, oldp + bd.textcol + delcount,
1909 (size_t)(oldlen - bd.textcol - delcount + 1));
1910 ml_replace(curwin->w_cursor.lnum, newp, FALSE);
1911
1912 ++curwin->w_cursor.lnum;
1913 if (i == 0)
1914 curwin->w_cursor.col += bd.startspaces;
1915 }
1916
1917 changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines);
1918
1919 // Set '[ mark.
1920 curbuf->b_op_start = curwin->w_cursor;
1921 curbuf->b_op_start.lnum = lnum;
1922
1923 // adjust '] mark
1924 curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
1925 curbuf->b_op_end.col = bd.textcol + totlen - 1;
1926 curbuf->b_op_end.coladd = 0;
1927 if (flags & PUT_CURSEND)
1928 {
1929 colnr_T len;
1930
1931 curwin->w_cursor = curbuf->b_op_end;
1932 curwin->w_cursor.col++;
1933
1934 // in Insert mode we might be after the NUL, correct for that
1935 len = (colnr_T)STRLEN(ml_get_curline());
1936 if (curwin->w_cursor.col > len)
1937 curwin->w_cursor.col = len;
1938 }
1939 else
1940 curwin->w_cursor.lnum = lnum;
1941 }
1942 else
1943 {
1944 // Character or Line mode
1945 if (y_type == MCHAR)
1946 {
1947 // if type is MCHAR, FORWARD is the same as BACKWARD on the next
1948 // char
1949 if (dir == FORWARD && gchar_cursor() != NUL)
1950 {
1951 if (has_mbyte)
1952 {
1953 int bytelen = (*mb_ptr2len)(ml_get_cursor());
1954
1955 // put it on the next of the multi-byte character.
1956 col += bytelen;
1957 if (yanklen)
1958 {
1959 curwin->w_cursor.col += bytelen;
1960 curbuf->b_op_end.col += bytelen;
1961 }
1962 }
1963 else
1964 {
1965 ++col;
1966 if (yanklen)
1967 {
1968 ++curwin->w_cursor.col;
1969 ++curbuf->b_op_end.col;
1970 }
1971 }
1972 }
1973 curbuf->b_op_start = curwin->w_cursor;
1974 }
1975 // Line mode: BACKWARD is the same as FORWARD on the previous line
1976 else if (dir == BACKWARD)
1977 --lnum;
1978 new_cursor = curwin->w_cursor;
1979
Bram Moolenaarcd942772020-08-22 21:08:44 +02001980 // simple case: insert into one line at a time
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001981 if (y_type == MCHAR && y_size == 1)
1982 {
Bram Moolenaarcd942772020-08-22 21:08:44 +02001983 linenr_T end_lnum = 0; // init for gcc
1984 linenr_T start_lnum = lnum;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02001985
1986 if (VIsual_active)
1987 {
1988 end_lnum = curbuf->b_visual.vi_end.lnum;
1989 if (end_lnum < curbuf->b_visual.vi_start.lnum)
1990 end_lnum = curbuf->b_visual.vi_start.lnum;
Bram Moolenaarcd942772020-08-22 21:08:44 +02001991 if (end_lnum > start_lnum)
1992 {
1993 pos_T pos;
1994
1995 // "col" is valid for the first line, in following lines
1996 // the virtual column needs to be used. Matters for
1997 // multi-byte characters.
1998 pos.lnum = lnum;
1999 pos.col = col;
2000 pos.coladd = 0;
2001 getvcol(curwin, &pos, NULL, &vcol, NULL);
2002 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002003 }
2004
2005 do {
2006 totlen = count * yanklen;
2007 if (totlen > 0)
2008 {
2009 oldp = ml_get(lnum);
Bram Moolenaarcd942772020-08-22 21:08:44 +02002010 if (lnum > start_lnum)
2011 {
2012 pos_T pos;
2013
2014 pos.lnum = lnum;
2015 if (getvpos(&pos, vcol) == OK)
2016 col = pos.col;
2017 else
2018 col = MAXCOL;
2019 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002020 if (VIsual_active && col > (int)STRLEN(oldp))
2021 {
2022 lnum++;
2023 continue;
2024 }
2025 newp = alloc(STRLEN(oldp) + totlen + 1);
2026 if (newp == NULL)
2027 goto end; // alloc() gave an error message
2028 mch_memmove(newp, oldp, (size_t)col);
2029 ptr = newp + col;
2030 for (i = 0; i < count; ++i)
2031 {
2032 mch_memmove(ptr, y_array[0], (size_t)yanklen);
2033 ptr += yanklen;
2034 }
2035 STRMOVE(ptr, oldp + col);
2036 ml_replace(lnum, newp, FALSE);
2037 // Place cursor on last putted char.
2038 if (lnum == curwin->w_cursor.lnum)
2039 {
2040 // make sure curwin->w_virtcol is updated
2041 changed_cline_bef_curs();
2042 curwin->w_cursor.col += (colnr_T)(totlen - 1);
2043 }
2044 }
2045 if (VIsual_active)
2046 lnum++;
2047 } while (VIsual_active && lnum <= end_lnum);
2048
2049 if (VIsual_active) // reset lnum to the last visual line
2050 lnum--;
2051
2052 curbuf->b_op_end = curwin->w_cursor;
2053 // For "CTRL-O p" in Insert mode, put cursor after last char
2054 if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
2055 ++curwin->w_cursor.col;
2056 changed_bytes(lnum, col);
2057 }
2058 else
2059 {
2060 // Insert at least one line. When y_type is MCHAR, break the first
2061 // line in two.
2062 for (cnt = 1; cnt <= count; ++cnt)
2063 {
2064 i = 0;
2065 if (y_type == MCHAR)
2066 {
2067 // Split the current line in two at the insert position.
2068 // First insert y_array[size - 1] in front of second line.
2069 // Then append y_array[0] to first line.
2070 lnum = new_cursor.lnum;
2071 ptr = ml_get(lnum) + col;
2072 totlen = (int)STRLEN(y_array[y_size - 1]);
2073 newp = alloc(STRLEN(ptr) + totlen + 1);
2074 if (newp == NULL)
2075 goto error;
2076 STRCPY(newp, y_array[y_size - 1]);
2077 STRCAT(newp, ptr);
2078 // insert second line
2079 ml_append(lnum, newp, (colnr_T)0, FALSE);
2080 vim_free(newp);
2081
2082 oldp = ml_get(lnum);
2083 newp = alloc(col + yanklen + 1);
2084 if (newp == NULL)
2085 goto error;
2086 // copy first part of line
2087 mch_memmove(newp, oldp, (size_t)col);
2088 // append to first line
2089 mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
2090 ml_replace(lnum, newp, FALSE);
2091
2092 curwin->w_cursor.lnum = lnum;
2093 i = 1;
2094 }
2095
2096 for (; i < y_size; ++i)
2097 {
2098 if ((y_type != MCHAR || i < y_size - 1)
2099 && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
2100 == FAIL)
2101 goto error;
2102 lnum++;
2103 ++nr_lines;
2104 if (flags & PUT_FIXINDENT)
2105 {
2106 old_pos = curwin->w_cursor;
2107 curwin->w_cursor.lnum = lnum;
2108 ptr = ml_get(lnum);
2109 if (cnt == count && i == y_size - 1)
2110 lendiff = (int)STRLEN(ptr);
2111#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
2112 if (*ptr == '#' && preprocs_left())
2113 indent = 0; // Leave # lines at start
2114 else
2115#endif
2116 if (*ptr == NUL)
2117 indent = 0; // Ignore empty lines
2118 else if (first_indent)
2119 {
2120 indent_diff = orig_indent - get_indent();
2121 indent = orig_indent;
2122 first_indent = FALSE;
2123 }
2124 else if ((indent = get_indent() + indent_diff) < 0)
2125 indent = 0;
2126 (void)set_indent(indent, 0);
2127 curwin->w_cursor = old_pos;
2128 // remember how many chars were removed
2129 if (cnt == count && i == y_size - 1)
2130 lendiff -= (int)STRLEN(ml_get(lnum));
2131 }
2132 }
2133 }
2134
2135error:
2136 // Adjust marks.
2137 if (y_type == MLINE)
2138 {
2139 curbuf->b_op_start.col = 0;
2140 if (dir == FORWARD)
2141 curbuf->b_op_start.lnum++;
2142 }
2143 // Skip mark_adjust when adding lines after the last one, there
2144 // can't be marks there. But still needed in diff mode.
2145 if (curbuf->b_op_start.lnum + (y_type == MCHAR) - 1 + nr_lines
2146 < curbuf->b_ml.ml_line_count
2147#ifdef FEAT_DIFF
2148 || curwin->w_p_diff
2149#endif
2150 )
2151 mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
2152 (linenr_T)MAXLNUM, nr_lines, 0L);
2153
2154 // note changed text for displaying and folding
2155 if (y_type == MCHAR)
2156 changed_lines(curwin->w_cursor.lnum, col,
2157 curwin->w_cursor.lnum + 1, nr_lines);
2158 else
2159 changed_lines(curbuf->b_op_start.lnum, 0,
2160 curbuf->b_op_start.lnum, nr_lines);
2161
2162 // put '] mark at last inserted character
2163 curbuf->b_op_end.lnum = lnum;
2164 // correct length for change in indent
2165 col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
2166 if (col > 1)
2167 curbuf->b_op_end.col = col - 1;
2168 else
2169 curbuf->b_op_end.col = 0;
2170
2171 if (flags & PUT_CURSLINE)
2172 {
2173 // ":put": put cursor on last inserted line
2174 curwin->w_cursor.lnum = lnum;
2175 beginline(BL_WHITE | BL_FIX);
2176 }
2177 else if (flags & PUT_CURSEND)
2178 {
2179 // put cursor after inserted text
2180 if (y_type == MLINE)
2181 {
2182 if (lnum >= curbuf->b_ml.ml_line_count)
2183 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
2184 else
2185 curwin->w_cursor.lnum = lnum + 1;
2186 curwin->w_cursor.col = 0;
2187 }
2188 else
2189 {
2190 curwin->w_cursor.lnum = lnum;
2191 curwin->w_cursor.col = col;
2192 }
2193 }
2194 else if (y_type == MLINE)
2195 {
2196 // put cursor on first non-blank in first inserted line
2197 curwin->w_cursor.col = 0;
2198 if (dir == FORWARD)
2199 ++curwin->w_cursor.lnum;
2200 beginline(BL_WHITE | BL_FIX);
2201 }
2202 else // put cursor on first inserted character
2203 curwin->w_cursor = new_cursor;
2204 }
2205 }
2206
2207 msgmore(nr_lines);
2208 curwin->w_set_curswant = TRUE;
2209
2210end:
Bram Moolenaare1004402020-10-24 20:49:43 +02002211 if (cmdmod.cmod_flags & CMOD_LOCKMARKS)
Bram Moolenaarf4a1d1c2019-11-16 13:50:25 +01002212 {
2213 curbuf->b_op_start = orig_start;
2214 curbuf->b_op_end = orig_end;
2215 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002216 if (allocated)
2217 vim_free(insert_string);
2218 if (regname == '=')
2219 vim_free(y_array);
2220
2221 VIsual_active = FALSE;
2222
2223 // If the cursor is past the end of the line put it at the end.
2224 adjust_cursor_eol();
2225}
2226
2227/*
2228 * Return the character name of the register with the given number.
2229 */
2230 int
2231get_register_name(int num)
2232{
2233 if (num == -1)
2234 return '"';
2235 else if (num < 10)
2236 return num + '0';
2237 else if (num == DELETION_REGISTER)
2238 return '-';
2239#ifdef FEAT_CLIPBOARD
2240 else if (num == STAR_REGISTER)
2241 return '*';
2242 else if (num == PLUS_REGISTER)
2243 return '+';
2244#endif
2245 else
2246 {
2247#ifdef EBCDIC
2248 int i;
2249
2250 // EBCDIC is really braindead ...
2251 i = 'a' + (num - 10);
2252 if (i > 'i')
2253 i += 7;
2254 if (i > 'r')
2255 i += 8;
2256 return i;
2257#else
2258 return num + 'a' - 10;
2259#endif
2260 }
2261}
2262
2263/*
Bram Moolenaarbb861e22020-06-07 18:16:36 +02002264 * Return the index of the register "" points to.
2265 */
2266 int
2267get_unname_register()
2268{
2269 return y_previous == NULL ? -1 : y_previous - &y_regs[0];
2270}
2271
2272/*
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002273 * ":dis" and ":registers": Display the contents of the yank registers.
2274 */
2275 void
2276ex_display(exarg_T *eap)
2277{
2278 int i, n;
2279 long j;
2280 char_u *p;
2281 yankreg_T *yb;
2282 int name;
2283 int attr;
2284 char_u *arg = eap->arg;
2285 int clen;
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002286 int type;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002287
2288 if (arg != NULL && *arg == NUL)
2289 arg = NULL;
2290 attr = HL_ATTR(HLF_8);
2291
2292 // Highlight title
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002293 msg_puts_title(_("\nType Name Content"));
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002294 for (i = -1; i < NUM_REGISTERS && !got_int; ++i)
2295 {
2296 name = get_register_name(i);
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002297 switch (get_reg_type(name, NULL))
2298 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002299 case MLINE: type = 'l'; break;
2300 case MCHAR: type = 'c'; break;
2301 default: type = 'b'; break;
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002302 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002303 if (arg != NULL && vim_strchr(arg, name) == NULL
2304#ifdef ONE_CLIPBOARD
2305 // Star register and plus register contain the same thing.
2306 && (name != '*' || vim_strchr(arg, '+') == NULL)
2307#endif
2308 )
2309 continue; // did not ask for this register
2310
2311#ifdef FEAT_CLIPBOARD
2312 // Adjust register name for "unnamed" in 'clipboard'.
2313 // When it's a clipboard register, fill it with the current contents
2314 // of the clipboard.
2315 adjust_clip_reg(&name);
2316 (void)may_get_selection(name);
2317#endif
2318
2319 if (i == -1)
2320 {
2321 if (y_previous != NULL)
2322 yb = y_previous;
2323 else
2324 yb = &(y_regs[0]);
2325 }
2326 else
2327 yb = &(y_regs[i]);
2328
2329#ifdef FEAT_EVAL
2330 if (name == MB_TOLOWER(redir_reg)
2331 || (redir_reg == '"' && yb == y_previous))
2332 continue; // do not list register being written to, the
2333 // pointer can be freed
2334#endif
2335
2336 if (yb->y_array != NULL)
2337 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002338 int do_show = FALSE;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002339
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002340 for (j = 0; !do_show && j < yb->y_size; ++j)
2341 do_show = !message_filtered(yb->y_array[j]);
2342
2343 if (do_show || yb->y_size == 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002344 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002345 msg_putchar('\n');
2346 msg_puts(" ");
2347 msg_putchar(type);
2348 msg_puts(" ");
2349 msg_putchar('"');
2350 msg_putchar(name);
2351 msg_puts(" ");
2352
2353 n = (int)Columns - 11;
2354 for (j = 0; j < yb->y_size && n > 1; ++j)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002355 {
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002356 if (j)
2357 {
2358 msg_puts_attr("^J", attr);
2359 n -= 2;
2360 }
2361 for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0;
2362 ++p)
2363 {
2364 clen = (*mb_ptr2len)(p);
2365 msg_outtrans_len(p, clen);
2366 p += clen - 1;
2367 }
2368 }
2369 if (n > 1 && yb->y_type == MLINE)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002370 msg_puts_attr("^J", attr);
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002371 out_flush(); // show one line at a time
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002372 }
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002373 ui_breakcheck();
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002374 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002375 }
2376
2377 // display last inserted text
2378 if ((p = get_last_insert()) != NULL
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002379 && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int
2380 && !message_filtered(p))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002381 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002382 msg_puts("\n c \". ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002383 dis_msg(p, TRUE);
2384 }
2385
2386 // display last command line
2387 if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002388 && !got_int && !message_filtered(last_cmdline))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002389 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002390 msg_puts("\n c \": ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002391 dis_msg(last_cmdline, FALSE);
2392 }
2393
2394 // display current file name
2395 if (curbuf->b_fname != NULL
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002396 && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int
2397 && !message_filtered(curbuf->b_fname))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002398 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002399 msg_puts("\n c \"% ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002400 dis_msg(curbuf->b_fname, FALSE);
2401 }
2402
2403 // display alternate file name
2404 if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
2405 {
2406 char_u *fname;
2407 linenr_T dummy;
2408
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002409 if (buflist_name_nr(0, &fname, &dummy) != FAIL
2410 && !message_filtered(fname))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002411 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002412 msg_puts("\n c \"# ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002413 dis_msg(fname, FALSE);
2414 }
2415 }
2416
2417 // display last search pattern
2418 if (last_search_pat() != NULL
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002419 && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int
2420 && !message_filtered(last_search_pat()))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002421 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002422 msg_puts("\n c \"/ ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002423 dis_msg(last_search_pat(), FALSE);
2424 }
2425
2426#ifdef FEAT_EVAL
2427 // display last used expression
2428 if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
Bram Moolenaar8fc42962019-10-26 17:33:13 +02002429 && !got_int && !message_filtered(expr_line))
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002430 {
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002431 msg_puts("\n c \"= ");
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002432 dis_msg(expr_line, FALSE);
2433 }
2434#endif
2435}
2436
2437/*
2438 * display a string for do_dis()
2439 * truncate at end of screen line
2440 */
2441 static void
2442dis_msg(
2443 char_u *p,
2444 int skip_esc) // if TRUE, ignore trailing ESC
2445{
2446 int n;
2447 int l;
2448
2449 n = (int)Columns - 6;
2450 while (*p != NUL
2451 && !(*p == ESC && skip_esc && *(p + 1) == NUL)
2452 && (n -= ptr2cells(p)) >= 0)
2453 {
2454 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
2455 {
2456 msg_outtrans_len(p, l);
2457 p += l;
2458 }
2459 else
2460 msg_outtrans_len(p++, 1);
2461 }
2462 ui_breakcheck();
2463}
2464
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002465#if defined(FEAT_DND) || defined(PROTO)
2466/*
2467 * Replace the contents of the '~' register with str.
2468 */
2469 void
2470dnd_yank_drag_data(char_u *str, long len)
2471{
2472 yankreg_T *curr;
2473
2474 curr = y_current;
2475 y_current = &y_regs[TILDE_REGISTER];
2476 free_yank_all();
2477 str_to_reg(y_current, MCHAR, str, len, 0L, FALSE);
2478 y_current = curr;
2479}
2480#endif
2481
2482
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002483/*
2484 * Return the type of a register.
2485 * Used for getregtype()
2486 * Returns MAUTO for error.
2487 */
2488 char_u
2489get_reg_type(int regname, long *reglen)
2490{
2491 switch (regname)
2492 {
2493 case '%': // file name
2494 case '#': // alternate file name
2495 case '=': // expression
2496 case ':': // last command line
2497 case '/': // last search-pattern
2498 case '.': // last inserted text
2499# ifdef FEAT_SEARCHPATH
2500 case Ctrl_F: // Filename under cursor
2501 case Ctrl_P: // Path under cursor, expand via "path"
2502# endif
2503 case Ctrl_W: // word under cursor
2504 case Ctrl_A: // WORD (mnemonic All) under cursor
2505 case '_': // black hole: always empty
2506 return MCHAR;
2507 }
2508
2509# ifdef FEAT_CLIPBOARD
2510 regname = may_get_selection(regname);
2511# endif
2512
2513 if (regname != NUL && !valid_yank_reg(regname, FALSE))
2514 return MAUTO;
2515
2516 get_yank_register(regname, FALSE);
2517
2518 if (y_current->y_array != NULL)
2519 {
2520 if (reglen != NULL && y_current->y_type == MBLOCK)
2521 *reglen = y_current->y_width;
2522 return y_current->y_type;
2523 }
2524 return MAUTO;
2525}
2526
Bram Moolenaar3691f1e2019-10-24 20:17:00 +02002527#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002528/*
2529 * When "flags" has GREG_LIST return a list with text "s".
2530 * Otherwise just return "s".
2531 */
2532 static char_u *
2533getreg_wrap_one_line(char_u *s, int flags)
2534{
2535 if (flags & GREG_LIST)
2536 {
2537 list_T *list = list_alloc();
2538
2539 if (list != NULL)
2540 {
2541 if (list_append_string(list, NULL, -1) == FAIL)
2542 {
2543 list_free(list);
2544 return NULL;
2545 }
2546 list->lv_first->li_tv.vval.v_string = s;
2547 }
2548 return (char_u *)list;
2549 }
2550 return s;
2551}
2552
2553/*
Bram Moolenaard672dde2020-02-26 13:43:51 +01002554 * Return the contents of a register as a single allocated string or as a list.
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002555 * Used for "@r" in expressions and for getreg().
2556 * Returns NULL for error.
2557 * Flags:
2558 * GREG_NO_EXPR Do not allow expression register
2559 * GREG_EXPR_SRC For the expression register: return expression itself,
2560 * not the result of its evaluation.
Bram Moolenaard672dde2020-02-26 13:43:51 +01002561 * GREG_LIST Return a list of lines instead of a single string.
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002562 */
2563 char_u *
2564get_reg_contents(int regname, int flags)
2565{
2566 long i;
2567 char_u *retval;
2568 int allocated;
2569 long len;
2570
2571 // Don't allow using an expression register inside an expression
2572 if (regname == '=')
2573 {
2574 if (flags & GREG_NO_EXPR)
2575 return NULL;
2576 if (flags & GREG_EXPR_SRC)
2577 return getreg_wrap_one_line(get_expr_line_src(), flags);
2578 return getreg_wrap_one_line(get_expr_line(), flags);
2579 }
2580
2581 if (regname == '@') // "@@" is used for unnamed register
2582 regname = '"';
2583
2584 // check for valid regname
2585 if (regname != NUL && !valid_yank_reg(regname, FALSE))
2586 return NULL;
2587
2588# ifdef FEAT_CLIPBOARD
2589 regname = may_get_selection(regname);
2590# endif
2591
2592 if (get_spec_reg(regname, &retval, &allocated, FALSE))
2593 {
2594 if (retval == NULL)
2595 return NULL;
2596 if (allocated)
2597 return getreg_wrap_one_line(retval, flags);
2598 return getreg_wrap_one_line(vim_strsave(retval), flags);
2599 }
2600
2601 get_yank_register(regname, FALSE);
2602 if (y_current->y_array == NULL)
2603 return NULL;
2604
2605 if (flags & GREG_LIST)
2606 {
2607 list_T *list = list_alloc();
2608 int error = FALSE;
2609
2610 if (list == NULL)
2611 return NULL;
2612 for (i = 0; i < y_current->y_size; ++i)
2613 if (list_append_string(list, y_current->y_array[i], -1) == FAIL)
2614 error = TRUE;
2615 if (error)
2616 {
2617 list_free(list);
2618 return NULL;
2619 }
2620 return (char_u *)list;
2621 }
2622
2623 // Compute length of resulting string.
2624 len = 0;
2625 for (i = 0; i < y_current->y_size; ++i)
2626 {
2627 len += (long)STRLEN(y_current->y_array[i]);
2628 // Insert a newline between lines and after last line if
2629 // y_type is MLINE.
2630 if (y_current->y_type == MLINE || i < y_current->y_size - 1)
2631 ++len;
2632 }
2633
2634 retval = alloc(len + 1);
2635
2636 // Copy the lines of the yank register into the string.
2637 if (retval != NULL)
2638 {
2639 len = 0;
2640 for (i = 0; i < y_current->y_size; ++i)
2641 {
2642 STRCPY(retval + len, y_current->y_array[i]);
2643 len += (long)STRLEN(retval + len);
2644
2645 // Insert a NL between lines and after the last line if y_type is
2646 // MLINE.
2647 if (y_current->y_type == MLINE || i < y_current->y_size - 1)
2648 retval[len++] = '\n';
2649 }
2650 retval[len] = NUL;
2651 }
2652
2653 return retval;
2654}
2655
2656 static int
2657init_write_reg(
2658 int name,
2659 yankreg_T **old_y_previous,
2660 yankreg_T **old_y_current,
2661 int must_append,
2662 int *yank_type UNUSED)
2663{
2664 if (!valid_yank_reg(name, TRUE)) // check for valid reg name
2665 {
2666 emsg_invreg(name);
2667 return FAIL;
2668 }
2669
2670 // Don't want to change the current (unnamed) register
2671 *old_y_previous = y_previous;
2672 *old_y_current = y_current;
2673
2674 get_yank_register(name, TRUE);
2675 if (!y_append && !must_append)
2676 free_yank_all();
2677 return OK;
2678}
2679
2680 static void
2681finish_write_reg(
2682 int name,
2683 yankreg_T *old_y_previous,
2684 yankreg_T *old_y_current)
2685{
2686# ifdef FEAT_CLIPBOARD
2687 // Send text of clipboard register to the clipboard.
2688 may_set_selection();
2689# endif
2690
2691 // ':let @" = "val"' should change the meaning of the "" register
2692 if (name != '"')
2693 y_previous = old_y_previous;
2694 y_current = old_y_current;
2695}
2696
2697/*
2698 * Store string "str" in register "name".
2699 * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
2700 * If "must_append" is TRUE, always append to the register. Otherwise append
2701 * if "name" is an uppercase letter.
2702 * Note: "maxlen" and "must_append" don't work for the "/" register.
2703 * Careful: 'str' is modified, you may have to use a copy!
2704 * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
2705 */
2706 void
2707write_reg_contents(
2708 int name,
2709 char_u *str,
2710 int maxlen,
2711 int must_append)
2712{
2713 write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
2714}
2715
2716 void
2717write_reg_contents_lst(
2718 int name,
2719 char_u **strings,
2720 int maxlen UNUSED,
2721 int must_append,
2722 int yank_type,
2723 long block_len)
2724{
2725 yankreg_T *old_y_previous, *old_y_current;
2726
2727 if (name == '/' || name == '=')
2728 {
2729 char_u *s;
2730
2731 if (strings[0] == NULL)
2732 s = (char_u *)"";
2733 else if (strings[1] != NULL)
2734 {
2735 emsg(_("E883: search pattern and expression register may not "
2736 "contain two or more lines"));
2737 return;
2738 }
2739 else
2740 s = strings[0];
2741 write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
2742 return;
2743 }
2744
2745 if (name == '_') // black hole: nothing to do
2746 return;
2747
2748 if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
2749 &yank_type) == FAIL)
2750 return;
2751
Bram Moolenaar7d7bcc62021-06-28 21:54:27 +02002752 str_to_reg(y_current, yank_type, (char_u *)strings, -1, block_len, TRUE);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002753
2754 finish_write_reg(name, old_y_previous, old_y_current);
2755}
2756
2757 void
2758write_reg_contents_ex(
2759 int name,
2760 char_u *str,
2761 int maxlen,
2762 int must_append,
2763 int yank_type,
2764 long block_len)
2765{
2766 yankreg_T *old_y_previous, *old_y_current;
2767 long len;
2768
2769 if (maxlen >= 0)
2770 len = maxlen;
2771 else
2772 len = (long)STRLEN(str);
2773
2774 // Special case: '/' search pattern
2775 if (name == '/')
2776 {
2777 set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
2778 return;
2779 }
2780
2781 if (name == '#')
2782 {
2783 buf_T *buf;
2784
2785 if (VIM_ISDIGIT(*str))
2786 {
2787 int num = atoi((char *)str);
2788
2789 buf = buflist_findnr(num);
2790 if (buf == NULL)
2791 semsg(_(e_nobufnr), (long)num);
2792 }
2793 else
2794 buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
2795 TRUE, FALSE, FALSE));
2796 if (buf == NULL)
2797 return;
2798 curwin->w_alt_fnum = buf->b_fnum;
2799 return;
2800 }
2801
2802 if (name == '=')
2803 {
2804 char_u *p, *s;
2805
Bram Moolenaar71ccd032020-06-12 22:59:11 +02002806 p = vim_strnsave(str, len);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002807 if (p == NULL)
2808 return;
Bram Moolenaar6b649ac2019-12-07 17:47:22 +01002809 if (must_append && expr_line != NULL)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002810 {
Bram Moolenaar6b649ac2019-12-07 17:47:22 +01002811 s = concat_str(expr_line, p);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002812 vim_free(p);
2813 p = s;
2814 }
Bram Moolenaarb4bcea42020-10-28 13:53:50 +01002815 set_expr_line(p, NULL);
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002816 return;
2817 }
2818
2819 if (name == '_') // black hole: nothing to do
2820 return;
2821
2822 if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
2823 &yank_type) == FAIL)
2824 return;
2825
2826 str_to_reg(y_current, yank_type, str, len, block_len, FALSE);
2827
2828 finish_write_reg(name, old_y_previous, old_y_current);
2829}
2830#endif // FEAT_EVAL
2831
2832#if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
2833/*
2834 * Put a string into a register. When the register is not empty, the string
2835 * is appended.
2836 */
Bram Moolenaar45fffdf2020-03-24 21:42:01 +01002837 void
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002838str_to_reg(
2839 yankreg_T *y_ptr, // pointer to yank register
2840 int yank_type, // MCHAR, MLINE, MBLOCK, MAUTO
2841 char_u *str, // string to put in register
2842 long len, // length of string
2843 long blocklen, // width of Visual block
2844 int str_list) // TRUE if str is char_u **
2845{
2846 int type; // MCHAR, MLINE or MBLOCK
2847 int lnum;
2848 long start;
2849 long i;
2850 int extra;
2851 int newlines; // number of lines added
2852 int extraline = 0; // extra line at the end
2853 int append = FALSE; // append to last line in register
2854 char_u *s;
2855 char_u **ss;
2856 char_u **pp;
2857 long maxlen;
2858
2859 if (y_ptr->y_array == NULL) // NULL means empty register
2860 y_ptr->y_size = 0;
2861
2862 if (yank_type == MAUTO)
2863 type = ((str_list || (len > 0 && (str[len - 1] == NL
2864 || str[len - 1] == CAR)))
2865 ? MLINE : MCHAR);
2866 else
2867 type = yank_type;
2868
2869 // Count the number of lines within the string
2870 newlines = 0;
2871 if (str_list)
2872 {
2873 for (ss = (char_u **) str; *ss != NULL; ++ss)
2874 ++newlines;
2875 }
2876 else
2877 {
2878 for (i = 0; i < len; i++)
2879 if (str[i] == '\n')
2880 ++newlines;
2881 if (type == MCHAR || len == 0 || str[len - 1] != '\n')
2882 {
2883 extraline = 1;
2884 ++newlines; // count extra newline at the end
2885 }
2886 if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
2887 {
2888 append = TRUE;
2889 --newlines; // uncount newline when appending first line
2890 }
2891 }
2892
2893 // Without any lines make the register empty.
2894 if (y_ptr->y_size + newlines == 0)
2895 {
2896 VIM_CLEAR(y_ptr->y_array);
2897 return;
2898 }
2899
2900 // Allocate an array to hold the pointers to the new register lines.
2901 // If the register was not empty, move the existing lines to the new array.
2902 pp = lalloc_clear((y_ptr->y_size + newlines) * sizeof(char_u *), TRUE);
2903 if (pp == NULL) // out of memory
2904 return;
2905 for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
2906 pp[lnum] = y_ptr->y_array[lnum];
2907 vim_free(y_ptr->y_array);
2908 y_ptr->y_array = pp;
2909 maxlen = 0;
2910
2911 // Find the end of each line and save it into the array.
2912 if (str_list)
2913 {
2914 for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum)
2915 {
Bram Moolenaar6c4c4042021-06-04 19:17:07 +02002916 pp[lnum] = vim_strsave(*ss);
2917 if (type == MBLOCK)
2918 {
2919 int charlen = mb_string2cells(*ss, -1);
2920
2921 if (charlen > maxlen)
2922 maxlen = charlen;
2923 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002924 }
2925 }
2926 else
2927 {
2928 for (start = 0; start < len + extraline; start += i + 1)
2929 {
Bram Moolenaar6c4c4042021-06-04 19:17:07 +02002930 int charlen = 0;
2931
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002932 for (i = start; i < len; ++i) // find the end of the line
Bram Moolenaar24951a62021-06-04 18:33:49 +02002933 {
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002934 if (str[i] == '\n')
2935 break;
Bram Moolenaar6c4c4042021-06-04 19:17:07 +02002936 if (type == MBLOCK)
2937 charlen += mb_ptr2cells_len(str + i, len - i);
Bram Moolenaar24951a62021-06-04 18:33:49 +02002938 }
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002939 i -= start; // i is now length of line
Bram Moolenaar6e0b5532021-06-04 17:11:47 +02002940 if (charlen > maxlen)
2941 maxlen = charlen;
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002942 if (append)
2943 {
2944 --lnum;
2945 extra = (int)STRLEN(y_ptr->y_array[lnum]);
2946 }
2947 else
2948 extra = 0;
2949 s = alloc(i + extra + 1);
2950 if (s == NULL)
2951 break;
2952 if (extra)
2953 mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
2954 if (append)
2955 vim_free(y_ptr->y_array[lnum]);
Bram Moolenaar24951a62021-06-04 18:33:49 +02002956 if (i > 0)
Bram Moolenaar4aea03e2019-09-25 22:37:17 +02002957 mch_memmove(s + extra, str + start, (size_t)i);
2958 extra += i;
2959 s[extra] = NUL;
2960 y_ptr->y_array[lnum++] = s;
2961 while (--extra >= 0)
2962 {
2963 if (*s == NUL)
2964 *s = '\n'; // replace NUL with newline
2965 ++s;
2966 }
2967 append = FALSE; // only first line is appended
2968 }
2969 }
2970 y_ptr->y_type = type;
2971 y_ptr->y_size = lnum;
2972 if (type == MBLOCK)
2973 y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
2974 else
2975 y_ptr->y_width = 0;
2976# ifdef FEAT_VIMINFO
2977 y_ptr->y_time_set = vim_time();
2978# endif
2979}
2980#endif // FEAT_CLIPBOARD || FEAT_EVAL || PROTO