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