aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-03-18 06:41:58 +0800
committerGitHub <noreply@github.com>2025-03-18 06:41:58 +0800
commit97bbc49cda267b63c773826858f3337721853746 (patch)
tree08092256e24ae8a33645c6262b0587a8d85dd3bd /src
parent08c328b8b079334e7fb38472339c4f8ba1a0df3b (diff)
parentd717f8605a05dad4c050ac1e0731c7aba572fe59 (diff)
downloadrneovim-97bbc49cda267b63c773826858f3337721853746.tar.gz
rneovim-97bbc49cda267b63c773826858f3337721853746.tar.bz2
rneovim-97bbc49cda267b63c773826858f3337721853746.zip
Merge pull request #32935 from zeertzjq/vim-3495497
vim-patch: too many strlen() calls in edit.c
Diffstat (limited to 'src')
-rw-r--r--src/nvim/change.c2
-rw-r--r--src/nvim/edit.c116
-rw-r--r--src/nvim/ops.c2
3 files changed, 69 insertions, 51 deletions
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 28854ae8aa..192e0d9faa 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -1820,7 +1820,7 @@ bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
saved_line[curwin->w_cursor.col] = NUL;
// Remove trailing white space, unless OPENLINE_KEEPTRAIL used.
if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) {
- truncate_spaces(saved_line);
+ truncate_spaces(saved_line, (size_t)curwin->w_cursor.col);
}
ml_replace(curwin->w_cursor.lnum, saved_line, false);
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index c3f204045a..a81d1416f1 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -120,7 +120,8 @@ static colnr_T Insstart_textlen; // length of line when insert started
static colnr_T Insstart_blank_vcol; // vcol for first inserted blank
static bool update_Insstart_orig = true; // set Insstart_orig to Insstart
-static char *last_insert = NULL; // the text of the previous insert, K_SPECIAL is escaped
+/// the text of the previous insert, K_SPECIAL is escaped
+static String last_insert = STRING_INIT;
static int last_insert_skip; // nr of chars in front of previous insert
static int new_insert_skip; // nr of chars in front of current insert
static int did_restart_edit; // "restart_edit" when calling edit()
@@ -1816,12 +1817,12 @@ void change_indent(int type, int amount, int round, bool call_changed_bytes)
/// Truncate the space at the end of a line. This is to be used only in an
/// insert mode. It handles fixing the replace stack for MODE_REPLACE and
/// MODE_VREPLACE modes.
-void truncate_spaces(char *line)
+void truncate_spaces(char *line, size_t len)
{
int i;
// find start of trailing white space
- for (i = (int)strlen(line) - 1; i >= 0 && ascii_iswhite(line[i]); i--) {
+ for (i = (int)len - 1; i >= 0 && ascii_iswhite(line[i]); i--) {
if (State & REPLACE_FLAG) {
replace_join(0); // remove a NUL from the replace stack
}
@@ -2332,8 +2333,8 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
String inserted = get_inserted();
int added = inserted.data == NULL ? 0 : (int)inserted.size - new_insert_skip;
if (did_restart_edit == 0 || added > 0) {
- xfree(last_insert);
- last_insert = inserted.data;
+ xfree(last_insert.data);
+ last_insert = inserted; // structure copy
last_insert_skip = added < 0 ? 0 : new_insert_skip;
} else {
xfree(inserted.data);
@@ -2440,23 +2441,24 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
// Used for the replace command.
void set_last_insert(int c)
{
- xfree(last_insert);
- last_insert = xmalloc(MB_MAXBYTES * 3 + 5);
- char *s = last_insert;
+ xfree(last_insert.data);
+ last_insert.data = xmalloc(MB_MAXBYTES * 3 + 5);
+ char *s = last_insert.data;
// Use the CTRL-V only when entering a special char
if (c < ' ' || c == DEL) {
*s++ = Ctrl_V;
}
s = add_char2buf(c, s);
*s++ = ESC;
- *s++ = NUL;
+ *s = NUL;
+ last_insert.size = (size_t)(s - last_insert.data);
last_insert_skip = 0;
}
#if defined(EXITFREE)
void free_last_insert(void)
{
- XFREE_CLEAR(last_insert);
+ API_CLEAR_STRING(last_insert);
}
#endif
@@ -2692,11 +2694,10 @@ int cursor_down(int n, bool upd_topline)
/// @param no_esc Don't add an ESC at the end
int stuff_inserted(int c, int count, int no_esc)
{
- char *esc_ptr;
char last = NUL;
- char *ptr = get_last_insert();
- if (ptr == NULL) {
+ String *insert = get_last_insert(); // text to be inserted
+ if (insert->data == NULL) {
emsg(_(e_noinstext));
return FAIL;
}
@@ -2705,37 +2706,44 @@ int stuff_inserted(int c, int count, int no_esc)
if (c != NUL) {
stuffcharReadbuff(c);
}
- if ((esc_ptr = strrchr(ptr, ESC)) != NULL) {
- // remove the ESC.
- *esc_ptr = NUL;
+
+ if (insert->size > 0) {
+ // look for the last ESC in 'insert'
+ for (char *p = insert->data + insert->size - 1; p >= insert->data; p--) {
+ if (*p == ESC) {
+ insert->size = (size_t)(p - insert->data);
+ break;
+ }
+ }
}
- // when the last char is either "0" or "^" it will be quoted if no ESC
- // comes after it OR if it will inserted more than once and "ptr"
- // starts with ^D. -- Acevedo
- char *last_ptr = (esc_ptr ? esc_ptr : ptr + strlen(ptr)) - 1;
- if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
- && (no_esc || (*ptr == Ctrl_D && count > 1))) {
- last = *last_ptr;
- *last_ptr = NUL;
+ if (insert->size > 0) {
+ char *p = insert->data + insert->size - 1;
+ // when the last char is either "0" or "^" it will be quoted if no ESC
+ // comes after it OR if it will inserted more than once and "ptr"
+ // starts with ^D. -- Acevedo
+ if ((*p == '0' || *p == '^')
+ && (no_esc || (*insert->data == Ctrl_D && count > 1))) {
+ last = *p;
+ insert->size--;
+ }
}
do {
- stuffReadbuff(ptr);
+ stuffReadbuffLen(insert->data, (ptrdiff_t)insert->size);
// A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^".
- if (last) {
- stuffReadbuff(last == '0' ? "\026\060\064\070" : "\026^");
+ switch (last) {
+ case '0':
+ stuffReadbuffLen(S_LEN("\026\060\064\070"));
+ break;
+ case '^':
+ stuffReadbuffLen(S_LEN("\026^"));
+ break;
+ default:
+ break;
}
} while (--count > 0);
- if (last) {
- *last_ptr = last;
- }
-
- if (esc_ptr != NULL) {
- *esc_ptr = ESC; // put the ESC back
- }
-
// may want to stuff a trailing ESC, to get out of Insert mode
if (!no_esc) {
stuffcharReadbuff(ESC);
@@ -2744,28 +2752,37 @@ int stuff_inserted(int c, int count, int no_esc)
return OK;
}
-char *get_last_insert(void)
+String *get_last_insert(void)
FUNC_ATTR_PURE
{
- if (last_insert == NULL) {
- return NULL;
- }
- return last_insert + last_insert_skip;
+ static String insert = STRING_INIT;
+
+ insert = last_insert.data == NULL ? NULL_STRING : (String){
+ insert.data = last_insert.data + last_insert_skip,
+ insert.size = last_insert.size - (size_t)last_insert_skip,
+ };
+
+ return &insert;
}
// Get last inserted string, and remove trailing <Esc>.
// Returns pointer to allocated memory (must be freed) or NULL.
char *get_last_insert_save(void)
{
- if (last_insert == NULL) {
+ String *insert = get_last_insert();
+
+ if (insert->data == NULL) {
return NULL;
}
- size_t len = strlen(last_insert + last_insert_skip);
- char *s = xmemdupz(last_insert + last_insert_skip, len);
- if (len > 0 && s[len - 1] == ESC) { // remove trailing ESC
- s[len - 1] = NUL;
- }
+ char *s = xmemdupz(insert->data, insert->size);
+ if (insert->size > 0) {
+ // remain trailing ESC
+ insert->size--;
+ if (s[insert->size] == ESC) {
+ s[insert->size] = NUL;
+ }
+ }
return s;
}
@@ -3507,7 +3524,7 @@ static bool ins_start_select(int c)
if (mod_mask) {
const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER,
(char)(uint8_t)mod_mask, NUL };
- stuffReadbuff(buf);
+ stuffReadbuffLen(buf, 3);
}
stuffcharReadbuff(c);
return true;
@@ -4705,11 +4722,12 @@ static char *do_insert_char_pre(int c)
if (!has_event(EVENT_INSERTCHARPRE)) {
return NULL;
}
- buf[utf_char2bytes(c, buf)] = NUL;
+ size_t buflen = (size_t)utf_char2bytes(c, buf);
+ buf[buflen] = NUL;
// Lock the text to avoid weird things from happening.
textlock++;
- set_vim_var_string(VV_CHAR, buf, -1);
+ set_vim_var_string(VV_CHAR, buf, (ptrdiff_t)buflen); // set v:char
char *res = NULL;
if (ins_apply_autocmds(EVENT_INSERTCHARPRE)) {
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 0bda14402f..cac811820b 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -3849,7 +3849,7 @@ void ex_display(exarg_T *eap)
}
// display last inserted text
- if ((p = get_last_insert()) != NULL
+ if ((p = get_last_insert()->data) != NULL
&& (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int
&& !message_filtered(p)) {
msg_puts("\n c \". ");