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