xref: /vim-8.2.3635/src/register.c (revision ea2d8d25)
1 /* 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  */
25 static yankreg_T	y_regs[NUM_REGISTERS];
26 
27 static yankreg_T	*y_current;	    // ptr to current yankreg
28 static int		y_append;	    // TRUE when appending
29 static yankreg_T	*y_previous = NULL; // ptr to last written yankreg
30 
31 static int	stuff_yank(int, char_u *);
32 static void	put_reedit_in_typebuf(int silent);
33 static int	put_in_typebuf(char_u *s, int esc, int colon,
34 								 int silent);
35 static int	yank_copy_line(struct block_def *bd, long y_idx);
36 #ifdef FEAT_CLIPBOARD
37 static void	copy_yank_reg(yankreg_T *reg);
38 #endif
39 static void	dis_msg(char_u *p, int skip_esc);
40 
41     yankreg_T *
42 get_y_regs(void)
43 {
44     return y_regs;
45 }
46 
47     yankreg_T *
48 get_y_register(int reg)
49 {
50     return &y_regs[reg];
51 }
52 
53     yankreg_T *
54 get_y_current(void)
55 {
56     return y_current;
57 }
58 
59     yankreg_T *
60 get_y_previous(void)
61 {
62     return y_previous;
63 }
64 
65     void
66 set_y_current(yankreg_T *yreg)
67 {
68     y_current = yreg;
69 }
70 
71     void
72 set_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  */
81 static 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
88 get_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
107 set_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 *
118 get_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;
139     rv = eval_to_string(expr_copy, TRUE);
140     --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 *
149 get_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
162 valid_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
202 get_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 
251 /*
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 *
256 get_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
308 put_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
324 free_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 
336 /*
337  * return TRUE if the current yank register has type MLINE
338  */
339     int
340 yank_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 }
349 
350 /*
351  * Start or stop recording into a yank register.
352  *
353  * Return FAIL for failure, OK otherwise.
354  */
355     int
356 do_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
412 stuff_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 
462 static int execreg_lastc = NUL;
463 
464     int
465 get_execreg_lastc(void)
466 {
467     return execreg_lastc;
468 }
469 
470     void
471 set_execreg_lastc(int lastc)
472 {
473     execreg_lastc = lastc;
474 }
475 
476 /*
477  * 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 *
493 execreg_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 /*
544  * Execute a yank register: copy it into the stuff buffer.
545  *
546  * Return FAIL for failure, OK otherwise.
547  */
548     int
549 do_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 
641 	// Disallow remapping for ":@r".
642 	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;
649 	    char_u *str;
650 	    int	    free_str = FALSE;
651 
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 	    }
659 
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);
676 	    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
696 put_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
725 put_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
764 insert_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
826 get_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
921 cmdline_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 
952 /*
953  * Shift the delete registers: "9 is cleared, "8 becomes "9, etc.
954  */
955     void
956 shift_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
972 yank_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;
992     (void)dict_add_list(v_event, "regcontents", list);
993 
994     buf[0] = (char_u)oap->regname;
995     buf[1] = NUL;
996     (void)dict_add_string(v_event, "regname", buf);
997 
998     buf[0] = get_op_char(oap->op_type);
999     buf[1] = get_extra_op_char(oap->op_type);
1000     buf[2] = NUL;
1001     (void)dict_add_string(v_event, "operator", buf);
1002 
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     }
1014     (void)dict_add_string(v_event, "regtype", buf);
1015 
1016     (void)dict_add_bool(v_event, "visual", oap->is_VIsual);
1017 
1018     // Lock the dictionary and its keys
1019     dict_set_items_ro(v_event);
1020 
1021     recursive = TRUE;
1022     textwinlock++;
1023     apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, FALSE, curbuf);
1024     textwinlock--;
1025     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
1037 init_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
1047 clear_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
1065 free_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 
1095     void
1096 free_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
1110 op_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;
1333 	// Some versions of Vi use ">=" here, some don't...
1334 	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 
1361     if (!cmdmod.lockmarks)
1362     {
1363 	// 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 	}
1371     }
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 
1426 fail:		// free the allocated lines
1427     free_yank(y_idx + 1);
1428     y_current = curr;
1429     return FAIL;
1430 }
1431 
1432     static int
1433 yank_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
1456 copy_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
1488 do_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;
1522     pos_T	orig_start = curbuf->b_op_start;
1523     pos_T	orig_end = curbuf->b_op_end;
1524 
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 	{
1713 	    int viscol = getviscol();
1714 	    int ts = curbuf->b_p_ts;
1715 
1716 	    // Don't need to insert spaces when "p" on the last position of a
1717 	    // tab or "P" on the first position.
1718 	    if (dir == FORWARD ?
1719 #ifdef FEAT_VARTABS
1720 		    tabstop_padding(viscol, ts, curbuf->b_p_vts_array) != 1
1721 #else
1722 		    ts - (viscol % ts) != 1
1723 #endif
1724 		    : curwin->w_cursor.coladd > 0)
1725 		coladvance_force(viscol);
1726 	    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;
1767 	    if (dir != FORWARD && c != NUL && curwin->w_cursor.coladd > 0)
1768 		++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 
1940 	// simple case: insert into current line
1941 	if (y_type == MCHAR && y_size == 1)
1942 	{
1943 	    linenr_T end_lnum = 0; // init for gcc
1944 
1945 	    if (VIsual_active)
1946 	    {
1947 		end_lnum = curbuf->b_visual.vi_end.lnum;
1948 		if (end_lnum < curbuf->b_visual.vi_start.lnum)
1949 		    end_lnum = curbuf->b_visual.vi_start.lnum;
1950 	    }
1951 
1952 	    do {
1953 		totlen = count * yanklen;
1954 		if (totlen > 0)
1955 		{
1956 		    oldp = ml_get(lnum);
1957 		    if (VIsual_active && col > (int)STRLEN(oldp))
1958 		    {
1959 			lnum++;
1960 			continue;
1961 		    }
1962 		    newp = alloc(STRLEN(oldp) + totlen + 1);
1963 		    if (newp == NULL)
1964 			goto end;	// alloc() gave an error message
1965 		    mch_memmove(newp, oldp, (size_t)col);
1966 		    ptr = newp + col;
1967 		    for (i = 0; i < count; ++i)
1968 		    {
1969 			mch_memmove(ptr, y_array[0], (size_t)yanklen);
1970 			ptr += yanklen;
1971 		    }
1972 		    STRMOVE(ptr, oldp + col);
1973 		    ml_replace(lnum, newp, FALSE);
1974 		    // Place cursor on last putted char.
1975 		    if (lnum == curwin->w_cursor.lnum)
1976 		    {
1977 			// make sure curwin->w_virtcol is updated
1978 			changed_cline_bef_curs();
1979 			curwin->w_cursor.col += (colnr_T)(totlen - 1);
1980 		    }
1981 		}
1982 		if (VIsual_active)
1983 		    lnum++;
1984 	    } while (VIsual_active && lnum <= end_lnum);
1985 
1986 	    if (VIsual_active) // reset lnum to the last visual line
1987 		lnum--;
1988 
1989 	    curbuf->b_op_end = curwin->w_cursor;
1990 	    // For "CTRL-O p" in Insert mode, put cursor after last char
1991 	    if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND)))
1992 		++curwin->w_cursor.col;
1993 	    changed_bytes(lnum, col);
1994 	}
1995 	else
1996 	{
1997 	    // Insert at least one line.  When y_type is MCHAR, break the first
1998 	    // line in two.
1999 	    for (cnt = 1; cnt <= count; ++cnt)
2000 	    {
2001 		i = 0;
2002 		if (y_type == MCHAR)
2003 		{
2004 		    // Split the current line in two at the insert position.
2005 		    // First insert y_array[size - 1] in front of second line.
2006 		    // Then append y_array[0] to first line.
2007 		    lnum = new_cursor.lnum;
2008 		    ptr = ml_get(lnum) + col;
2009 		    totlen = (int)STRLEN(y_array[y_size - 1]);
2010 		    newp = alloc(STRLEN(ptr) + totlen + 1);
2011 		    if (newp == NULL)
2012 			goto error;
2013 		    STRCPY(newp, y_array[y_size - 1]);
2014 		    STRCAT(newp, ptr);
2015 		    // insert second line
2016 		    ml_append(lnum, newp, (colnr_T)0, FALSE);
2017 		    vim_free(newp);
2018 
2019 		    oldp = ml_get(lnum);
2020 		    newp = alloc(col + yanklen + 1);
2021 		    if (newp == NULL)
2022 			goto error;
2023 					    // copy first part of line
2024 		    mch_memmove(newp, oldp, (size_t)col);
2025 					    // append to first line
2026 		    mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
2027 		    ml_replace(lnum, newp, FALSE);
2028 
2029 		    curwin->w_cursor.lnum = lnum;
2030 		    i = 1;
2031 		}
2032 
2033 		for (; i < y_size; ++i)
2034 		{
2035 		    if ((y_type != MCHAR || i < y_size - 1)
2036 			    && ml_append(lnum, y_array[i], (colnr_T)0, FALSE)
2037 								      == FAIL)
2038 			    goto error;
2039 		    lnum++;
2040 		    ++nr_lines;
2041 		    if (flags & PUT_FIXINDENT)
2042 		    {
2043 			old_pos = curwin->w_cursor;
2044 			curwin->w_cursor.lnum = lnum;
2045 			ptr = ml_get(lnum);
2046 			if (cnt == count && i == y_size - 1)
2047 			    lendiff = (int)STRLEN(ptr);
2048 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
2049 			if (*ptr == '#' && preprocs_left())
2050 			    indent = 0;     // Leave # lines at start
2051 			else
2052 #endif
2053 			     if (*ptr == NUL)
2054 			    indent = 0;     // Ignore empty lines
2055 			else if (first_indent)
2056 			{
2057 			    indent_diff = orig_indent - get_indent();
2058 			    indent = orig_indent;
2059 			    first_indent = FALSE;
2060 			}
2061 			else if ((indent = get_indent() + indent_diff) < 0)
2062 			    indent = 0;
2063 			(void)set_indent(indent, 0);
2064 			curwin->w_cursor = old_pos;
2065 			// remember how many chars were removed
2066 			if (cnt == count && i == y_size - 1)
2067 			    lendiff -= (int)STRLEN(ml_get(lnum));
2068 		    }
2069 		}
2070 	    }
2071 
2072 error:
2073 	    // Adjust marks.
2074 	    if (y_type == MLINE)
2075 	    {
2076 		curbuf->b_op_start.col = 0;
2077 		if (dir == FORWARD)
2078 		    curbuf->b_op_start.lnum++;
2079 	    }
2080 	    // Skip mark_adjust when adding lines after the last one, there
2081 	    // can't be marks there. But still needed in diff mode.
2082 	    if (curbuf->b_op_start.lnum + (y_type == MCHAR) - 1 + nr_lines
2083 						 < curbuf->b_ml.ml_line_count
2084 #ifdef FEAT_DIFF
2085 						 || curwin->w_p_diff
2086 #endif
2087 						 )
2088 		mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
2089 					     (linenr_T)MAXLNUM, nr_lines, 0L);
2090 
2091 	    // note changed text for displaying and folding
2092 	    if (y_type == MCHAR)
2093 		changed_lines(curwin->w_cursor.lnum, col,
2094 					 curwin->w_cursor.lnum + 1, nr_lines);
2095 	    else
2096 		changed_lines(curbuf->b_op_start.lnum, 0,
2097 					   curbuf->b_op_start.lnum, nr_lines);
2098 
2099 	    // put '] mark at last inserted character
2100 	    curbuf->b_op_end.lnum = lnum;
2101 	    // correct length for change in indent
2102 	    col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
2103 	    if (col > 1)
2104 		curbuf->b_op_end.col = col - 1;
2105 	    else
2106 		curbuf->b_op_end.col = 0;
2107 
2108 	    if (flags & PUT_CURSLINE)
2109 	    {
2110 		// ":put": put cursor on last inserted line
2111 		curwin->w_cursor.lnum = lnum;
2112 		beginline(BL_WHITE | BL_FIX);
2113 	    }
2114 	    else if (flags & PUT_CURSEND)
2115 	    {
2116 		// put cursor after inserted text
2117 		if (y_type == MLINE)
2118 		{
2119 		    if (lnum >= curbuf->b_ml.ml_line_count)
2120 			curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
2121 		    else
2122 			curwin->w_cursor.lnum = lnum + 1;
2123 		    curwin->w_cursor.col = 0;
2124 		}
2125 		else
2126 		{
2127 		    curwin->w_cursor.lnum = lnum;
2128 		    curwin->w_cursor.col = col;
2129 		}
2130 	    }
2131 	    else if (y_type == MLINE)
2132 	    {
2133 		// put cursor on first non-blank in first inserted line
2134 		curwin->w_cursor.col = 0;
2135 		if (dir == FORWARD)
2136 		    ++curwin->w_cursor.lnum;
2137 		beginline(BL_WHITE | BL_FIX);
2138 	    }
2139 	    else	// put cursor on first inserted character
2140 		curwin->w_cursor = new_cursor;
2141 	}
2142     }
2143 
2144     msgmore(nr_lines);
2145     curwin->w_set_curswant = TRUE;
2146 
2147 end:
2148     if (cmdmod.lockmarks)
2149     {
2150 	curbuf->b_op_start = orig_start;
2151 	curbuf->b_op_end = orig_end;
2152     }
2153     if (allocated)
2154 	vim_free(insert_string);
2155     if (regname == '=')
2156 	vim_free(y_array);
2157 
2158     VIsual_active = FALSE;
2159 
2160     // If the cursor is past the end of the line put it at the end.
2161     adjust_cursor_eol();
2162 }
2163 
2164 /*
2165  * Return the character name of the register with the given number.
2166  */
2167     int
2168 get_register_name(int num)
2169 {
2170     if (num == -1)
2171 	return '"';
2172     else if (num < 10)
2173 	return num + '0';
2174     else if (num == DELETION_REGISTER)
2175 	return '-';
2176 #ifdef FEAT_CLIPBOARD
2177     else if (num == STAR_REGISTER)
2178 	return '*';
2179     else if (num == PLUS_REGISTER)
2180 	return '+';
2181 #endif
2182     else
2183     {
2184 #ifdef EBCDIC
2185 	int i;
2186 
2187 	// EBCDIC is really braindead ...
2188 	i = 'a' + (num - 10);
2189 	if (i > 'i')
2190 	    i += 7;
2191 	if (i > 'r')
2192 	    i += 8;
2193 	return i;
2194 #else
2195 	return num + 'a' - 10;
2196 #endif
2197     }
2198 }
2199 
2200 /*
2201  * Return the index of the register "" points to.
2202  */
2203     int
2204 get_unname_register()
2205 {
2206     return y_previous == NULL ? -1 : y_previous - &y_regs[0];
2207 }
2208 
2209 /*
2210  * ":dis" and ":registers": Display the contents of the yank registers.
2211  */
2212     void
2213 ex_display(exarg_T *eap)
2214 {
2215     int		i, n;
2216     long	j;
2217     char_u	*p;
2218     yankreg_T	*yb;
2219     int		name;
2220     int		attr;
2221     char_u	*arg = eap->arg;
2222     int		clen;
2223     int		type;
2224 
2225     if (arg != NULL && *arg == NUL)
2226 	arg = NULL;
2227     attr = HL_ATTR(HLF_8);
2228 
2229     // Highlight title
2230     msg_puts_title(_("\nType Name Content"));
2231     for (i = -1; i < NUM_REGISTERS && !got_int; ++i)
2232     {
2233 	name = get_register_name(i);
2234 	switch (get_reg_type(name, NULL))
2235 	{
2236 	    case MLINE: type = 'l'; break;
2237 	    case MCHAR: type = 'c'; break;
2238 	    default:	type = 'b'; break;
2239 	}
2240 	if (arg != NULL && vim_strchr(arg, name) == NULL
2241 #ifdef ONE_CLIPBOARD
2242 	    // Star register and plus register contain the same thing.
2243 		&& (name != '*' || vim_strchr(arg, '+') == NULL)
2244 #endif
2245 		)
2246 	    continue;	    // did not ask for this register
2247 
2248 #ifdef FEAT_CLIPBOARD
2249 	// Adjust register name for "unnamed" in 'clipboard'.
2250 	// When it's a clipboard register, fill it with the current contents
2251 	// of the clipboard.
2252 	adjust_clip_reg(&name);
2253 	(void)may_get_selection(name);
2254 #endif
2255 
2256 	if (i == -1)
2257 	{
2258 	    if (y_previous != NULL)
2259 		yb = y_previous;
2260 	    else
2261 		yb = &(y_regs[0]);
2262 	}
2263 	else
2264 	    yb = &(y_regs[i]);
2265 
2266 #ifdef FEAT_EVAL
2267 	if (name == MB_TOLOWER(redir_reg)
2268 		|| (redir_reg == '"' && yb == y_previous))
2269 	    continue;	    // do not list register being written to, the
2270 			    // pointer can be freed
2271 #endif
2272 
2273 	if (yb->y_array != NULL)
2274 	{
2275 	    int do_show = FALSE;
2276 
2277 	    for (j = 0; !do_show && j < yb->y_size; ++j)
2278 		do_show = !message_filtered(yb->y_array[j]);
2279 
2280 	    if (do_show || yb->y_size == 0)
2281 	    {
2282 		msg_putchar('\n');
2283 		msg_puts("  ");
2284 		msg_putchar(type);
2285 		msg_puts("  ");
2286 		msg_putchar('"');
2287 		msg_putchar(name);
2288 		msg_puts("   ");
2289 
2290 		n = (int)Columns - 11;
2291 		for (j = 0; j < yb->y_size && n > 1; ++j)
2292 		{
2293 		    if (j)
2294 		    {
2295 			msg_puts_attr("^J", attr);
2296 			n -= 2;
2297 		    }
2298 		    for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0;
2299 									   ++p)
2300 		    {
2301 			clen = (*mb_ptr2len)(p);
2302 			msg_outtrans_len(p, clen);
2303 			p += clen - 1;
2304 		    }
2305 		}
2306 		if (n > 1 && yb->y_type == MLINE)
2307 		    msg_puts_attr("^J", attr);
2308 		out_flush();		    // show one line at a time
2309 	    }
2310 	    ui_breakcheck();
2311 	}
2312     }
2313 
2314     // display last inserted text
2315     if ((p = get_last_insert()) != NULL
2316 		  && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int
2317 						      && !message_filtered(p))
2318     {
2319 	msg_puts("\n  c  \".   ");
2320 	dis_msg(p, TRUE);
2321     }
2322 
2323     // display last command line
2324     if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL)
2325 			       && !got_int && !message_filtered(last_cmdline))
2326     {
2327 	msg_puts("\n  c  \":   ");
2328 	dis_msg(last_cmdline, FALSE);
2329     }
2330 
2331     // display current file name
2332     if (curbuf->b_fname != NULL
2333 	    && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int
2334 					&& !message_filtered(curbuf->b_fname))
2335     {
2336 	msg_puts("\n  c  \"%   ");
2337 	dis_msg(curbuf->b_fname, FALSE);
2338     }
2339 
2340     // display alternate file name
2341     if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int)
2342     {
2343 	char_u	    *fname;
2344 	linenr_T    dummy;
2345 
2346 	if (buflist_name_nr(0, &fname, &dummy) != FAIL
2347 						  && !message_filtered(fname))
2348 	{
2349 	    msg_puts("\n  c  \"#   ");
2350 	    dis_msg(fname, FALSE);
2351 	}
2352     }
2353 
2354     // display last search pattern
2355     if (last_search_pat() != NULL
2356 		 && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int
2357 				      && !message_filtered(last_search_pat()))
2358     {
2359 	msg_puts("\n  c  \"/   ");
2360 	dis_msg(last_search_pat(), FALSE);
2361     }
2362 
2363 #ifdef FEAT_EVAL
2364     // display last used expression
2365     if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL)
2366 				  && !got_int && !message_filtered(expr_line))
2367     {
2368 	msg_puts("\n  c  \"=   ");
2369 	dis_msg(expr_line, FALSE);
2370     }
2371 #endif
2372 }
2373 
2374 /*
2375  * display a string for do_dis()
2376  * truncate at end of screen line
2377  */
2378     static void
2379 dis_msg(
2380     char_u	*p,
2381     int		skip_esc)	    // if TRUE, ignore trailing ESC
2382 {
2383     int		n;
2384     int		l;
2385 
2386     n = (int)Columns - 6;
2387     while (*p != NUL
2388 	    && !(*p == ESC && skip_esc && *(p + 1) == NUL)
2389 	    && (n -= ptr2cells(p)) >= 0)
2390     {
2391 	if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
2392 	{
2393 	    msg_outtrans_len(p, l);
2394 	    p += l;
2395 	}
2396 	else
2397 	    msg_outtrans_len(p++, 1);
2398     }
2399     ui_breakcheck();
2400 }
2401 
2402 #if defined(FEAT_DND) || defined(PROTO)
2403 /*
2404  * Replace the contents of the '~' register with str.
2405  */
2406     void
2407 dnd_yank_drag_data(char_u *str, long len)
2408 {
2409     yankreg_T *curr;
2410 
2411     curr = y_current;
2412     y_current = &y_regs[TILDE_REGISTER];
2413     free_yank_all();
2414     str_to_reg(y_current, MCHAR, str, len, 0L, FALSE);
2415     y_current = curr;
2416 }
2417 #endif
2418 
2419 
2420 /*
2421  * Return the type of a register.
2422  * Used for getregtype()
2423  * Returns MAUTO for error.
2424  */
2425     char_u
2426 get_reg_type(int regname, long *reglen)
2427 {
2428     switch (regname)
2429     {
2430 	case '%':		// file name
2431 	case '#':		// alternate file name
2432 	case '=':		// expression
2433 	case ':':		// last command line
2434 	case '/':		// last search-pattern
2435 	case '.':		// last inserted text
2436 # ifdef FEAT_SEARCHPATH
2437 	case Ctrl_F:		// Filename under cursor
2438 	case Ctrl_P:		// Path under cursor, expand via "path"
2439 # endif
2440 	case Ctrl_W:		// word under cursor
2441 	case Ctrl_A:		// WORD (mnemonic All) under cursor
2442 	case '_':		// black hole: always empty
2443 	    return MCHAR;
2444     }
2445 
2446 # ifdef FEAT_CLIPBOARD
2447     regname = may_get_selection(regname);
2448 # endif
2449 
2450     if (regname != NUL && !valid_yank_reg(regname, FALSE))
2451 	return MAUTO;
2452 
2453     get_yank_register(regname, FALSE);
2454 
2455     if (y_current->y_array != NULL)
2456     {
2457 	if (reglen != NULL && y_current->y_type == MBLOCK)
2458 	    *reglen = y_current->y_width;
2459 	return y_current->y_type;
2460     }
2461     return MAUTO;
2462 }
2463 
2464 #if defined(FEAT_EVAL) || defined(PROTO)
2465 /*
2466  * When "flags" has GREG_LIST return a list with text "s".
2467  * Otherwise just return "s".
2468  */
2469     static char_u *
2470 getreg_wrap_one_line(char_u *s, int flags)
2471 {
2472     if (flags & GREG_LIST)
2473     {
2474 	list_T *list = list_alloc();
2475 
2476 	if (list != NULL)
2477 	{
2478 	    if (list_append_string(list, NULL, -1) == FAIL)
2479 	    {
2480 		list_free(list);
2481 		return NULL;
2482 	    }
2483 	    list->lv_first->li_tv.vval.v_string = s;
2484 	}
2485 	return (char_u *)list;
2486     }
2487     return s;
2488 }
2489 
2490 /*
2491  * Return the contents of a register as a single allocated string or as a list.
2492  * Used for "@r" in expressions and for getreg().
2493  * Returns NULL for error.
2494  * Flags:
2495  *	GREG_NO_EXPR	Do not allow expression register
2496  *	GREG_EXPR_SRC	For the expression register: return expression itself,
2497  *			not the result of its evaluation.
2498  *	GREG_LIST	Return a list of lines instead of a single string.
2499  */
2500     char_u *
2501 get_reg_contents(int regname, int flags)
2502 {
2503     long	i;
2504     char_u	*retval;
2505     int		allocated;
2506     long	len;
2507 
2508     // Don't allow using an expression register inside an expression
2509     if (regname == '=')
2510     {
2511 	if (flags & GREG_NO_EXPR)
2512 	    return NULL;
2513 	if (flags & GREG_EXPR_SRC)
2514 	    return getreg_wrap_one_line(get_expr_line_src(), flags);
2515 	return getreg_wrap_one_line(get_expr_line(), flags);
2516     }
2517 
2518     if (regname == '@')	    // "@@" is used for unnamed register
2519 	regname = '"';
2520 
2521     // check for valid regname
2522     if (regname != NUL && !valid_yank_reg(regname, FALSE))
2523 	return NULL;
2524 
2525 # ifdef FEAT_CLIPBOARD
2526     regname = may_get_selection(regname);
2527 # endif
2528 
2529     if (get_spec_reg(regname, &retval, &allocated, FALSE))
2530     {
2531 	if (retval == NULL)
2532 	    return NULL;
2533 	if (allocated)
2534 	    return getreg_wrap_one_line(retval, flags);
2535 	return getreg_wrap_one_line(vim_strsave(retval), flags);
2536     }
2537 
2538     get_yank_register(regname, FALSE);
2539     if (y_current->y_array == NULL)
2540 	return NULL;
2541 
2542     if (flags & GREG_LIST)
2543     {
2544 	list_T	*list = list_alloc();
2545 	int	error = FALSE;
2546 
2547 	if (list == NULL)
2548 	    return NULL;
2549 	for (i = 0; i < y_current->y_size; ++i)
2550 	    if (list_append_string(list, y_current->y_array[i], -1) == FAIL)
2551 		error = TRUE;
2552 	if (error)
2553 	{
2554 	    list_free(list);
2555 	    return NULL;
2556 	}
2557 	return (char_u *)list;
2558     }
2559 
2560     // Compute length of resulting string.
2561     len = 0;
2562     for (i = 0; i < y_current->y_size; ++i)
2563     {
2564 	len += (long)STRLEN(y_current->y_array[i]);
2565 	// Insert a newline between lines and after last line if
2566 	// y_type is MLINE.
2567 	if (y_current->y_type == MLINE || i < y_current->y_size - 1)
2568 	    ++len;
2569     }
2570 
2571     retval = alloc(len + 1);
2572 
2573     // Copy the lines of the yank register into the string.
2574     if (retval != NULL)
2575     {
2576 	len = 0;
2577 	for (i = 0; i < y_current->y_size; ++i)
2578 	{
2579 	    STRCPY(retval + len, y_current->y_array[i]);
2580 	    len += (long)STRLEN(retval + len);
2581 
2582 	    // Insert a NL between lines and after the last line if y_type is
2583 	    // MLINE.
2584 	    if (y_current->y_type == MLINE || i < y_current->y_size - 1)
2585 		retval[len++] = '\n';
2586 	}
2587 	retval[len] = NUL;
2588     }
2589 
2590     return retval;
2591 }
2592 
2593     static int
2594 init_write_reg(
2595     int		name,
2596     yankreg_T	**old_y_previous,
2597     yankreg_T	**old_y_current,
2598     int		must_append,
2599     int		*yank_type UNUSED)
2600 {
2601     if (!valid_yank_reg(name, TRUE))	    // check for valid reg name
2602     {
2603 	emsg_invreg(name);
2604 	return FAIL;
2605     }
2606 
2607     // Don't want to change the current (unnamed) register
2608     *old_y_previous = y_previous;
2609     *old_y_current = y_current;
2610 
2611     get_yank_register(name, TRUE);
2612     if (!y_append && !must_append)
2613 	free_yank_all();
2614     return OK;
2615 }
2616 
2617     static void
2618 finish_write_reg(
2619     int		name,
2620     yankreg_T	*old_y_previous,
2621     yankreg_T	*old_y_current)
2622 {
2623 # ifdef FEAT_CLIPBOARD
2624     // Send text of clipboard register to the clipboard.
2625     may_set_selection();
2626 # endif
2627 
2628     // ':let @" = "val"' should change the meaning of the "" register
2629     if (name != '"')
2630 	y_previous = old_y_previous;
2631     y_current = old_y_current;
2632 }
2633 
2634 /*
2635  * Store string "str" in register "name".
2636  * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
2637  * If "must_append" is TRUE, always append to the register.  Otherwise append
2638  * if "name" is an uppercase letter.
2639  * Note: "maxlen" and "must_append" don't work for the "/" register.
2640  * Careful: 'str' is modified, you may have to use a copy!
2641  * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
2642  */
2643     void
2644 write_reg_contents(
2645     int		name,
2646     char_u	*str,
2647     int		maxlen,
2648     int		must_append)
2649 {
2650     write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
2651 }
2652 
2653     void
2654 write_reg_contents_lst(
2655     int		name,
2656     char_u	**strings,
2657     int		maxlen UNUSED,
2658     int		must_append,
2659     int		yank_type,
2660     long	block_len)
2661 {
2662     yankreg_T  *old_y_previous, *old_y_current;
2663 
2664     if (name == '/' || name == '=')
2665     {
2666 	char_u	*s;
2667 
2668 	if (strings[0] == NULL)
2669 	    s = (char_u *)"";
2670 	else if (strings[1] != NULL)
2671 	{
2672 	    emsg(_("E883: search pattern and expression register may not "
2673 			"contain two or more lines"));
2674 	    return;
2675 	}
2676 	else
2677 	    s = strings[0];
2678 	write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
2679 	return;
2680     }
2681 
2682     if (name == '_')	    // black hole: nothing to do
2683 	return;
2684 
2685     if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
2686 		&yank_type) == FAIL)
2687 	return;
2688 
2689     str_to_reg(y_current, yank_type, (char_u *) strings, -1, block_len, TRUE);
2690 
2691     finish_write_reg(name, old_y_previous, old_y_current);
2692 }
2693 
2694     void
2695 write_reg_contents_ex(
2696     int		name,
2697     char_u	*str,
2698     int		maxlen,
2699     int		must_append,
2700     int		yank_type,
2701     long	block_len)
2702 {
2703     yankreg_T	*old_y_previous, *old_y_current;
2704     long	len;
2705 
2706     if (maxlen >= 0)
2707 	len = maxlen;
2708     else
2709 	len = (long)STRLEN(str);
2710 
2711     // Special case: '/' search pattern
2712     if (name == '/')
2713     {
2714 	set_last_search_pat(str, RE_SEARCH, TRUE, TRUE);
2715 	return;
2716     }
2717 
2718     if (name == '#')
2719     {
2720 	buf_T	*buf;
2721 
2722 	if (VIM_ISDIGIT(*str))
2723 	{
2724 	    int	num = atoi((char *)str);
2725 
2726 	    buf = buflist_findnr(num);
2727 	    if (buf == NULL)
2728 		semsg(_(e_nobufnr), (long)num);
2729 	}
2730 	else
2731 	    buf = buflist_findnr(buflist_findpat(str, str + STRLEN(str),
2732 							 TRUE, FALSE, FALSE));
2733 	if (buf == NULL)
2734 	    return;
2735 	curwin->w_alt_fnum = buf->b_fnum;
2736 	return;
2737     }
2738 
2739     if (name == '=')
2740     {
2741 	char_u	    *p, *s;
2742 
2743 	p = vim_strnsave(str, len);
2744 	if (p == NULL)
2745 	    return;
2746 	if (must_append && expr_line != NULL)
2747 	{
2748 	    s = concat_str(expr_line, p);
2749 	    vim_free(p);
2750 	    p = s;
2751 	}
2752 	set_expr_line(p);
2753 	return;
2754     }
2755 
2756     if (name == '_')	    // black hole: nothing to do
2757 	return;
2758 
2759     if (init_write_reg(name, &old_y_previous, &old_y_current, must_append,
2760 		&yank_type) == FAIL)
2761 	return;
2762 
2763     str_to_reg(y_current, yank_type, str, len, block_len, FALSE);
2764 
2765     finish_write_reg(name, old_y_previous, old_y_current);
2766 }
2767 #endif	// FEAT_EVAL
2768 
2769 #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
2770 /*
2771  * Put a string into a register.  When the register is not empty, the string
2772  * is appended.
2773  */
2774     void
2775 str_to_reg(
2776     yankreg_T	*y_ptr,		// pointer to yank register
2777     int		yank_type,	// MCHAR, MLINE, MBLOCK, MAUTO
2778     char_u	*str,		// string to put in register
2779     long	len,		// length of string
2780     long	blocklen,	// width of Visual block
2781     int		str_list)	// TRUE if str is char_u **
2782 {
2783     int		type;			// MCHAR, MLINE or MBLOCK
2784     int		lnum;
2785     long	start;
2786     long	i;
2787     int		extra;
2788     int		newlines;		// number of lines added
2789     int		extraline = 0;		// extra line at the end
2790     int		append = FALSE;		// append to last line in register
2791     char_u	*s;
2792     char_u	**ss;
2793     char_u	**pp;
2794     long	maxlen;
2795 
2796     if (y_ptr->y_array == NULL)		// NULL means empty register
2797 	y_ptr->y_size = 0;
2798 
2799     if (yank_type == MAUTO)
2800 	type = ((str_list || (len > 0 && (str[len - 1] == NL
2801 					    || str[len - 1] == CAR)))
2802 							     ? MLINE : MCHAR);
2803     else
2804 	type = yank_type;
2805 
2806     // Count the number of lines within the string
2807     newlines = 0;
2808     if (str_list)
2809     {
2810 	for (ss = (char_u **) str; *ss != NULL; ++ss)
2811 	    ++newlines;
2812     }
2813     else
2814     {
2815 	for (i = 0; i < len; i++)
2816 	    if (str[i] == '\n')
2817 		++newlines;
2818 	if (type == MCHAR || len == 0 || str[len - 1] != '\n')
2819 	{
2820 	    extraline = 1;
2821 	    ++newlines;	// count extra newline at the end
2822 	}
2823 	if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR)
2824 	{
2825 	    append = TRUE;
2826 	    --newlines;	// uncount newline when appending first line
2827 	}
2828     }
2829 
2830     // Without any lines make the register empty.
2831     if (y_ptr->y_size + newlines == 0)
2832     {
2833 	VIM_CLEAR(y_ptr->y_array);
2834 	return;
2835     }
2836 
2837     // Allocate an array to hold the pointers to the new register lines.
2838     // If the register was not empty, move the existing lines to the new array.
2839     pp = lalloc_clear((y_ptr->y_size + newlines) * sizeof(char_u *), TRUE);
2840     if (pp == NULL)	// out of memory
2841 	return;
2842     for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
2843 	pp[lnum] = y_ptr->y_array[lnum];
2844     vim_free(y_ptr->y_array);
2845     y_ptr->y_array = pp;
2846     maxlen = 0;
2847 
2848     // Find the end of each line and save it into the array.
2849     if (str_list)
2850     {
2851 	for (ss = (char_u **) str; *ss != NULL; ++ss, ++lnum)
2852 	{
2853 	    i = (long)STRLEN(*ss);
2854 	    pp[lnum] = vim_strnsave(*ss, i);
2855 	    if (i > maxlen)
2856 		maxlen = i;
2857 	}
2858     }
2859     else
2860     {
2861 	for (start = 0; start < len + extraline; start += i + 1)
2862 	{
2863 	    for (i = start; i < len; ++i)	// find the end of the line
2864 		if (str[i] == '\n')
2865 		    break;
2866 	    i -= start;			// i is now length of line
2867 	    if (i > maxlen)
2868 		maxlen = i;
2869 	    if (append)
2870 	    {
2871 		--lnum;
2872 		extra = (int)STRLEN(y_ptr->y_array[lnum]);
2873 	    }
2874 	    else
2875 		extra = 0;
2876 	    s = alloc(i + extra + 1);
2877 	    if (s == NULL)
2878 		break;
2879 	    if (extra)
2880 		mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra);
2881 	    if (append)
2882 		vim_free(y_ptr->y_array[lnum]);
2883 	    if (i)
2884 		mch_memmove(s + extra, str + start, (size_t)i);
2885 	    extra += i;
2886 	    s[extra] = NUL;
2887 	    y_ptr->y_array[lnum++] = s;
2888 	    while (--extra >= 0)
2889 	    {
2890 		if (*s == NUL)
2891 		    *s = '\n';	    // replace NUL with newline
2892 		++s;
2893 	    }
2894 	    append = FALSE;		    // only first line is appended
2895 	}
2896     }
2897     y_ptr->y_type = type;
2898     y_ptr->y_size = lnum;
2899     if (type == MBLOCK)
2900 	y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
2901     else
2902 	y_ptr->y_width = 0;
2903 # ifdef FEAT_VIMINFO
2904     y_ptr->y_time_set = vim_time();
2905 # endif
2906 }
2907 #endif // FEAT_CLIPBOARD || FEAT_EVAL || PROTO
2908