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