move ins_char_bytes

This commit is contained in:
Daniel Hahler
2019-06-09 19:09:24 +02:00
parent 664b6adebe
commit c0f71ef826
2 changed files with 102 additions and 238 deletions

View File

@@ -525,140 +525,118 @@ ins_char(int c)
ins_char_bytes(buf, n); ins_char_bytes(buf, n);
} }
void void ins_char_bytes(char_u *buf, size_t charlen)
ins_char_bytes(char_u *buf, int charlen)
{ {
int c = buf[0]; // Break tabs if needed.
int newlen; // nr of bytes inserted if (virtual_active() && curwin->w_cursor.coladd > 0) {
int oldlen; // nr of bytes deleted (0 when not replacing) coladvance_force(getviscol());
char_u *p; }
char_u *newp;
char_u *oldp;
int linelen; // length of old line including NUL
colnr_T col;
linenr_T lnum = curwin->w_cursor.lnum;
int i;
// Break tabs if needed. size_t col = (size_t)curwin->w_cursor.col;
if (virtual_active() && curwin->w_cursor.coladd > 0) linenr_T lnum = curwin->w_cursor.lnum;
coladvance_force(getviscol()); char_u *oldp = ml_get(lnum);
size_t linelen = STRLEN(oldp) + 1; // length of old line including NUL
col = curwin->w_cursor.col; // The lengths default to the values for when not replacing.
oldp = ml_get(lnum); size_t oldlen = 0; // nr of bytes inserted
linelen = (int)STRLEN(oldp) + 1; size_t newlen = charlen; // nr of bytes deleted (0 when not replacing)
// The lengths default to the values for when not replacing. if (State & REPLACE_FLAG) {
oldlen = 0; if (State & VREPLACE_FLAG) {
newlen = charlen; // Disable 'list' temporarily, unless 'cpo' contains the 'L' flag.
// Returns the old value of list, so when finished,
if (State & REPLACE_FLAG) // curwin->w_p_list should be set back to this.
{ int old_list = curwin->w_p_list;
if (State & VREPLACE_FLAG) if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) {
{ curwin->w_p_list = false;
colnr_T new_vcol = 0; // init for GCC }
colnr_T vcol; // In virtual replace mode each character may replace one or more
int old_list; // characters (zero if it's a TAB). Count the number of bytes to
// be deleted to make room for the new character, counting screen
// Disable 'list' temporarily, unless 'cpo' contains the 'L' flag. // cells. May result in adding spaces to fill a gap.
// Returns the old value of list, so when finished, colnr_T vcol;
// curwin->w_p_list should be set back to this. getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
old_list = curwin->w_p_list; colnr_T new_vcol = vcol + chartabsize(buf, vcol);
if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) while (oldp[col + oldlen] != NUL && vcol < new_vcol) {
curwin->w_p_list = FALSE; vcol += chartabsize(oldp + col + oldlen, vcol);
// Don't need to remove a TAB that takes us to the right
// In virtual replace mode each character may replace one or more // position.
// characters (zero if it's a TAB). Count the number of bytes to if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
// be deleted to make room for the new character, counting screen break;
// cells. May result in adding spaces to fill a gap. }
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL); oldlen += (size_t)(*mb_ptr2len)(oldp + col + oldlen);
new_vcol = vcol + chartabsize(buf, vcol); // Deleted a bit too much, insert spaces.
while (oldp[col + oldlen] != NUL && vcol < new_vcol) if (vcol > new_vcol) {
{ newlen += (size_t)(vcol - new_vcol);
vcol += chartabsize(oldp + col + oldlen, vcol); }
// Don't need to remove a TAB that takes us to the right }
// position. curwin->w_p_list = old_list;
if (vcol > new_vcol && oldp[col + oldlen] == TAB) } else if (oldp[col] != NUL) {
break; // normal replace
oldlen += (*mb_ptr2len)(oldp + col + oldlen); oldlen = (size_t)(*mb_ptr2len)(oldp + col);
// Deleted a bit too much, insert spaces.
if (vcol > new_vcol)
newlen += vcol - new_vcol;
}
curwin->w_p_list = old_list;
}
else if (oldp[col] != NUL)
{
// normal replace
oldlen = (*mb_ptr2len)(oldp + col);
}
// Push the replaced bytes onto the replace stack, so that they can be
// put back when BS is used. The bytes of a multi-byte character are
// done the other way around, so that the first byte is popped off
// first (it tells the byte length of the character).
replace_push(NUL);
for (i = 0; i < oldlen; ++i)
{
if (has_mbyte)
i += replace_push_mb(oldp + col + i) - 1;
else
replace_push(oldp[col + i]);
}
} }
newp = alloc_check((unsigned)(linelen + newlen - oldlen));
if (newp == NULL)
return;
// Copy bytes before the cursor. /* Push the replaced bytes onto the replace stack, so that they can be
if (col > 0) * put back when BS is used. The bytes of a multi-byte character are
mch_memmove(newp, oldp, (size_t)col); * done the other way around, so that the first byte is popped off
* first (it tells the byte length of the character). */
// Copy bytes after the changed character(s). replace_push(NUL);
p = newp + col; for (size_t i = 0; i < oldlen; i++) {
if (linelen > col + oldlen) if (has_mbyte) {
mch_memmove(p + newlen, oldp + col + oldlen, i += (size_t)replace_push_mb(oldp + col + i) - 1;
(size_t)(linelen - col - oldlen)); } else {
replace_push(oldp[col + i]);
// Insert or overwrite the new character. }
mch_memmove(p, buf, charlen);
i = charlen;
// Fill with spaces when necessary.
while (i < newlen)
p[i++] = ' ';
// Replace the line in the buffer.
ml_replace(lnum, newp, FALSE);
// mark the buffer as changed and prepare for displaying
inserted_bytes(lnum, col, newlen - oldlen);
// If we're in Insert or Replace mode and 'showmatch' is set, then briefly
// show the match for right parens and braces.
if (p_sm && (State & INSERT)
&& msg_silent == 0
#ifdef FEAT_INS_EXPAND
&& !ins_compl_active()
#endif
)
{
if (has_mbyte)
showmatch(mb_ptr2char(buf));
else
showmatch(c);
} }
}
#ifdef FEAT_RIGHTLEFT char_u *newp = xmalloc((size_t)(linelen + newlen - oldlen));
if (!p_ri || (State & REPLACE_FLAG))
#endif
{
// Normal insert: move cursor right
curwin->w_cursor.col += charlen;
}
// TODO: should try to update w_row here, to avoid recomputing it later. // Copy bytes before the cursor.
if (col > 0) {
memmove(newp, oldp, (size_t)col);
}
// Copy bytes after the changed character(s).
char_u *p = newp + col;
if (linelen > col + oldlen) {
memmove(p + newlen, oldp + col + oldlen,
(size_t)(linelen - col - oldlen));
}
// Insert or overwrite the new character.
memmove(p, buf, charlen);
// Fill with spaces when necessary.
for (size_t i = charlen; i < newlen; i++) {
p[i] = ' ';
}
// Replace the line in the buffer.
ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying
changed_bytes(lnum, (colnr_T)col);
/*
* If we're in Insert or Replace mode and 'showmatch' is set, then briefly
* show the match for right parens and braces.
*/
if (p_sm && (State & INSERT)
&& msg_silent == 0
&& !ins_compl_active()
) {
showmatch(utf_ptr2char(buf));
}
if (!p_ri || (State & REPLACE_FLAG)) {
// Normal insert: move cursor right
curwin->w_cursor.col += (int)charlen;
}
/*
* TODO: should try to update w_row here, to avoid recomputing it later.
*/
} }
/* /*

View File

@@ -1398,120 +1398,6 @@ void ins_char(int c)
ins_char_bytes(buf, n); ins_char_bytes(buf, n);
} }
void ins_char_bytes(char_u *buf, size_t charlen)
{
// Break tabs if needed.
if (virtual_active() && curwin->w_cursor.coladd > 0) {
coladvance_force(getviscol());
}
size_t col = (size_t)curwin->w_cursor.col;
linenr_T lnum = curwin->w_cursor.lnum;
char_u *oldp = ml_get(lnum);
size_t linelen = STRLEN(oldp) + 1; // length of old line including NUL
// The lengths default to the values for when not replacing.
size_t oldlen = 0; // nr of bytes inserted
size_t newlen = charlen; // nr of bytes deleted (0 when not replacing)
if (State & REPLACE_FLAG) {
if (State & VREPLACE_FLAG) {
// Disable 'list' temporarily, unless 'cpo' contains the 'L' flag.
// Returns the old value of list, so when finished,
// curwin->w_p_list should be set back to this.
int old_list = curwin->w_p_list;
if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) {
curwin->w_p_list = false;
}
// In virtual replace mode each character may replace one or more
// characters (zero if it's a TAB). Count the number of bytes to
// be deleted to make room for the new character, counting screen
// cells. May result in adding spaces to fill a gap.
colnr_T vcol;
getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL);
colnr_T new_vcol = vcol + chartabsize(buf, vcol);
while (oldp[col + oldlen] != NUL && vcol < new_vcol) {
vcol += chartabsize(oldp + col + oldlen, vcol);
// Don't need to remove a TAB that takes us to the right
// position.
if (vcol > new_vcol && oldp[col + oldlen] == TAB) {
break;
}
oldlen += (size_t)(*mb_ptr2len)(oldp + col + oldlen);
// Deleted a bit too much, insert spaces.
if (vcol > new_vcol) {
newlen += (size_t)(vcol - new_vcol);
}
}
curwin->w_p_list = old_list;
} else if (oldp[col] != NUL) {
// normal replace
oldlen = (size_t)(*mb_ptr2len)(oldp + col);
}
/* Push the replaced bytes onto the replace stack, so that they can be
* put back when BS is used. The bytes of a multi-byte character are
* done the other way around, so that the first byte is popped off
* first (it tells the byte length of the character). */
replace_push(NUL);
for (size_t i = 0; i < oldlen; i++) {
if (has_mbyte) {
i += (size_t)replace_push_mb(oldp + col + i) - 1;
} else {
replace_push(oldp[col + i]);
}
}
}
char_u *newp = xmalloc((size_t)(linelen + newlen - oldlen));
// Copy bytes before the cursor.
if (col > 0) {
memmove(newp, oldp, (size_t)col);
}
// Copy bytes after the changed character(s).
char_u *p = newp + col;
if (linelen > col + oldlen) {
memmove(p + newlen, oldp + col + oldlen,
(size_t)(linelen - col - oldlen));
}
// Insert or overwrite the new character.
memmove(p, buf, charlen);
// Fill with spaces when necessary.
for (size_t i = charlen; i < newlen; i++) {
p[i] = ' ';
}
// Replace the line in the buffer.
ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying
changed_bytes(lnum, (colnr_T)col);
/*
* If we're in Insert or Replace mode and 'showmatch' is set, then briefly
* show the match for right parens and braces.
*/
if (p_sm && (State & INSERT)
&& msg_silent == 0
&& !ins_compl_active()
) {
showmatch(utf_ptr2char(buf));
}
if (!p_ri || (State & REPLACE_FLAG)) {
// Normal insert: move cursor right
curwin->w_cursor.col += (int)charlen;
}
/*
* TODO: should try to update w_row here, to avoid recomputing it later.
*/
}
/* /*
* Insert a string at the cursor position. * Insert a string at the cursor position.
* Note: Does NOT handle Replace mode. * Note: Does NOT handle Replace mode.