📄 ops.c
字号:
*/
void
do_put(regname, dir, count, flags)
int regname;
int dir; /* BACKWARD for 'P', FORWARD for 'p' */
long count;
int flags;
{
char_u *ptr;
char_u *newp, *oldp;
int yanklen;
int oldlen;
int totlen = 0; /* init for gcc */
linenr_t lnum;
colnr_t col;
long i; /* index in y_array[] */
int y_type;
long y_size;
char_u **y_array = NULL;
long nr_lines = 0;
colnr_t vcol;
int delcount;
int incr = 0;
long j;
FPOS new_cursor;
int indent;
int orig_indent = 0; /* init for gcc */
int indent_diff = 0; /* init for gcc */
int first_indent = TRUE;
FPOS old_pos;
struct block_def bd;
char_u *insert_string = NULL;
int allocated = FALSE;
#ifdef MULTI_BYTE
int bMultiByteCode = 0;
#endif
#ifdef USE_CLIPBOARD
if (regname == '*')
clip_get_selection();
#endif
if (flags & PUT_FIXINDENT)
orig_indent = get_indent();
curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */
if (dir == FORWARD)
{
#ifdef MULTI_BYTE
/* put it on the next of the multi-byte character. */
if (is_dbcs)
{
ptr = ml_get(curwin->w_cursor.lnum) + curwin->w_cursor.col;
if (IsLeadByte(*ptr) && (*(ptr + 1) != '\0'))
{
bMultiByteCode = 1;
curbuf->b_op_start.col++;
}
}
#endif
curbuf->b_op_start.col++;
}
curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */
/*
* Using inserted text works differently, because the register includes
* special characters (newlines, etc.).
*/
if (regname == '.')
{
(void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
(count == -1 ? 'O' : 'i')), count, FALSE);
/* Putting the text is done later, so can't really move the cursor to
* the nex character. Use "l" to simulate it. */
if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
stuffcharReadbuff('l');
return;
}
/*
* For special registers '%' (file name), '#' (alternate file name) and
* ':' (last command line), etc. we have to create a fake yank register.
*/
if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
{
if (insert_string == NULL)
return;
}
if (insert_string != NULL)
{
y_type = MCHAR;
if (regname == '=')
{
/* For the = register we need to split the string at NL
* characters. */
/* Loop twice: count the number of lines and save them. */
for (;;)
{
y_size = 0;
ptr = insert_string;
while (ptr != NULL)
{
if (y_array != NULL)
y_array[y_size] = ptr;
++y_size;
ptr = vim_strchr(ptr, '\n');
if (ptr != NULL)
{
if (y_array != NULL)
*ptr = NUL;
++ptr;
/* A trailing '\n' makes the string linewise */
if (*ptr == NUL)
{
y_type = MLINE;
break;
}
}
}
if (y_array != NULL)
break;
y_array = (char_u **)alloc((unsigned)
(y_size * sizeof(char_u *)));
if (y_array == NULL)
goto end;
}
}
else
{
y_size = 1; /* use fake one-line yank register */
y_array = &insert_string;
}
}
else
{
get_yank_register(regname, FALSE);
y_type = y_current->y_type;
y_size = y_current->y_size;
y_array = y_current->y_array;
}
if (count == -1) /* :put command */
{
y_type = MLINE;
count = 1;
}
if (y_size == 0 || y_array == NULL)
{
EMSG2("Nothing in register %s",
regname == 0 ? (char_u *)"\"" : transchar(regname));
goto end;
}
if (y_type == MBLOCK)
{
lnum = curwin->w_cursor.lnum + y_size + 1;
if (lnum > curbuf->b_ml.ml_line_count)
lnum = curbuf->b_ml.ml_line_count + 1;
if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL)
goto end;
}
else if (u_save_cursor() == FAIL)
goto end;
yanklen = STRLEN(y_array[0]);
changed();
lnum = curwin->w_cursor.lnum;
col = curwin->w_cursor.col;
approximate_botline(); /* w_botline might not be valid now */
changed_cline_bef_curs(); /* cursor posn on screen may change */
/*
* block mode
*/
if (y_type == MBLOCK)
{
if (dir == FORWARD && gchar_cursor() != NUL)
{
getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
#ifdef MULTI_BYTE
if (is_dbcs)
{
/* put it on the next of the multi-byte character. */
col += bMultiByteCode + 1;
curwin->w_cursor.col += bMultiByteCode + 1;
}
else
#endif
{
++col;
++curwin->w_cursor.col;
}
}
else
getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
#ifdef SYNTAX_HL
/* recompute syntax hl., starting with current line */
syn_changed(curwin->w_cursor.lnum);
#endif
for (i = 0; i < y_size; ++i)
{
bd.startspaces = 0;
bd.endspaces = 0;
bd.textcol = 0;
vcol = 0;
delcount = 0;
/* add a new line */
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
{
ml_append(curbuf->b_ml.ml_line_count, (char_u *)"",
(colnr_t)1, FALSE);
++nr_lines;
}
oldp = ml_get_curline();
oldlen = STRLEN(oldp);
for (ptr = oldp; vcol < col && *ptr; ++ptr)
{
/* Count a tab for what it's worth (if list mode not on) */
incr = lbr_chartabsize(ptr, (colnr_t)vcol);
vcol += incr;
++bd.textcol;
}
if (vcol < col) /* line too short, padd with spaces */
{
bd.startspaces = col - vcol;
}
else if (vcol > col)
{
bd.endspaces = vcol - col;
bd.startspaces = incr - bd.endspaces;
--bd.textcol;
delcount = 1;
}
yanklen = STRLEN(y_array[i]);
totlen = count * yanklen + bd.startspaces + bd.endspaces;
newp = alloc_check((unsigned)totlen + oldlen + 1);
if (newp == NULL)
break;
/* copy part up to cursor to new line */
ptr = newp;
mch_memmove(ptr, oldp, (size_t)bd.textcol);
ptr += bd.textcol;
/* may insert some spaces before the new text */
copy_spaces(ptr, (size_t)bd.startspaces);
ptr += bd.startspaces;
/* insert the new text */
for (j = 0; j < count; ++j)
{
mch_memmove(ptr, y_array[i], (size_t)yanklen);
ptr += yanklen;
}
/* may insert some spaces after the new text */
copy_spaces(ptr, (size_t)bd.endspaces);
ptr += bd.endspaces;
/* move the text after the cursor to the end of the line. */
mch_memmove(ptr, oldp + bd.textcol + delcount,
(size_t)(oldlen - bd.textcol - delcount + 1));
ml_replace(curwin->w_cursor.lnum, newp, FALSE);
++curwin->w_cursor.lnum;
if (i == 0)
curwin->w_cursor.col += bd.startspaces;
}
/* adjust '] mark */
curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1;
curbuf->b_op_end.col = bd.textcol + totlen - 1;
if (flags & PUT_CURSEND)
{
curwin->w_cursor = curbuf->b_op_end;
curwin->w_cursor.col++;
}
else
curwin->w_cursor.lnum = lnum;
update_topline();
if (flags & PUT_CURSEND)
update_screen(NOT_VALID);
else
update_screen(VALID_TO_CURSCHAR);
}
else /* not block mode */
{
if (y_type == MCHAR)
{
/* if type is MCHAR, FORWARD is the same as BACKWARD on the next char */
if (dir == FORWARD && gchar_cursor() != NUL)
{
#ifdef MULTI_BYTE
if (is_dbcs)
{
/* put it on the next of the multi-byte character. */
col += bMultiByteCode + 1;
if (yanklen)
{
curwin->w_cursor.col += bMultiByteCode + 1;
curbuf->b_op_end.col += bMultiByteCode + 1;
}
}
else
#endif
{
++col;
if (yanklen)
{
++curwin->w_cursor.col;
++curbuf->b_op_end.col;
}
}
}
new_cursor = curwin->w_cursor;
}
else if (dir == BACKWARD)
/* if type is MLINE, BACKWARD is the same as FORWARD on the previous line */
--lnum;
/*
* simple case: insert into current line
*/
if (y_type == MCHAR && y_size == 1)
{
totlen = count * yanklen;
if (totlen)
{
oldp = ml_get(lnum);
newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1));
if (newp == NULL)
goto end; /* alloc() will give error message */
mch_memmove(newp, oldp, (size_t)col);
ptr = newp + col;
for (i = 0; i < count; ++i)
{
mch_memmove(ptr, y_array[0], (size_t)yanklen);
ptr += yanklen;
}
mch_memmove(ptr, oldp + col, STRLEN(oldp + col) + 1);
ml_replace(lnum, newp, FALSE);
/* Put cursor on last putted char. */
curwin->w_cursor.col += (colnr_t)(totlen - 1);
}
curbuf->b_op_end = curwin->w_cursor;
/* For "CTRL-O p" in Insert mode, put cursor after last char */
if (totlen && (restart_edit || (flags & PUT_CURSEND)))
++curwin->w_cursor.col;
update_screenline();
}
else
{
#ifdef SYNTAX_HL
/* recompute syntax hl., starting with current line */
syn_changed(lnum);
#endif
while (--count >= 0)
{
i = 0;
if (y_type == MCHAR)
{
/*
* Split the current line in two at the insert position.
* First insert y_array[size - 1] in front of second line.
* Then append y_array[0] to first line.
*/
ptr = ml_get(lnum) + col;
totlen = STRLEN(y_array[y_size - 1]);
newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1));
if (newp == NULL)
goto error;
STRCPY(newp, y_array[y_size - 1]);
STRCAT(newp, ptr);
/* insert second line */
ml_append(lnum, newp, (colnr_t)0, FALSE);
vim_free(newp);
oldp = ml_get(lnum);
newp = alloc_check((unsigned)(col + yanklen + 1));
if (newp == NULL)
goto error;
/* copy first part of line */
mch_memmove(newp, oldp, (size_t)col);
/* append to first line */
mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1));
ml_replace(lnum, newp, FALSE);
curwin->w_cursor.lnum = lnum;
i = 1;
}
while (i < y_size)
{
if ((y_type != MCHAR || i < y_size - 1) &&
ml_append(lnum, y_array[i], (colnr_t)0, FALSE) == FAIL)
goto error;
lnum++;
i++;
if (flags & PUT_FIXINDENT)
{
old_pos = curwin->w_cursor;
curwin->w_cursor.lnum = lnum;
ptr = ml_get(lnum);
#if defined(SMARTINDENT) || defined(CINDENT)
if (*ptr == '#'
# ifdef SMARTINDENT
&& curbuf->b_p_si
# endif
# ifdef CINDENT
&& curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE)
# endif
)
indent = 0; /* Leave # lines at start */
else
#endif
if (*ptr == NUL)
indent = 0; /* Ignore empty lines */
else if (first_indent)
{
indent_diff = orig_indent - get_indent();
indent = orig_indent;
first_indent = FALSE;
}
else if ((indent = get_indent() + indent_diff) < 0)
indent = 0;
set_indent(indent, TRUE);
curwin->w_cursor = old_pos;
}
++nr_lines;
}
}
/* put '] mark at last inserted character */
curbuf->b_op_end.lnum = lnum;
col = STRLEN(y_array[y_size - 1]);
if (col > 1)
curbuf->b_op_end.col = col - 1;
else
curbuf->b_op_end.col = 0;
if (flags & PUT_CURSEND)
{
/* put cursor after inserted text */
if (y_type == MLINE)
{
if (lnum >= curbuf->b_ml.ml_line_count)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
else
curwin->w_cursor.lnum = lnum + 1;
curwin->w_cursor.col = 0;
}
else
{
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = col;
}
/* the text before the cursor needs redrawing */
redraw_curbuf_later(NOT_VALID);
}
else if (y_type == MLINE)
{
/* put cursor onfirst non-blank in first inserted line */
curwin->w_cursor.col = 0;
if (dir == FORWARD)
++curwin->w_cursor.lnum;
beginline(BL_WHITE | BL_FIX);
}
else /* put cursor on first inserted character */
curwin->w_cursor = new_cursor;
error:
if (y_type == MLINE) /* adjust '[ mark */
{
curbuf->b_op_start.col = 0;
if (dir == FORWARD)
curbuf->b_op_start.lnum++;
}
mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR),
(linenr_t)MAXLNUM, nr_lines, 0L);
update_topline();
update_screen(VALID_TO_CURSCHAR);
}
}
msgmore(nr_lines);
curwin->w_set_curswant = TRUE;
end:
if (allocated)
{
vim_free(insert_string);
if (regname == '=')
vim_free(y_array);
}
if ((flags & PUT_CURSEND) && gchar_cursor() == NUL && curwin->w_cursor.col
&& !(restart_edit || (State & INSERT)))
--curwin->w_cursor.col;
}
/* Return the character name of the register with the given number */
int
get_register_name(num)
int num;
{
if (num == -1)
return '"';
else if (num < 10)
return num + '0';
else if (num == DELETION_REGISTER)
return '-';
#ifdef USE_CLIPBOARD
else if (num == CLIPBOARD_REGISTER)
return '*';
#endif
else
return num + 'a' - 10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -