aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_getln.c86
-rw-r--r--src/nvim/search.c5
2 files changed, 56 insertions, 35 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 7d87e609ca..ca01a158a3 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -125,6 +125,7 @@ typedef struct {
bool gotesc; // true when <ESC> just typed
int do_abbr; // when true check for abbr.
char *lookfor; // string to match
+ int lookforlen;
int hiscnt; // current history line in use
int save_hiscnt; // history line before attempting
// to jump to next match
@@ -385,7 +386,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
if (!use_last_pat) {
char c = *end;
*end = NUL;
- bool empty = empty_pattern_magic(p, strlen(p), magic);
+ bool empty = empty_pattern_magic(p, (size_t)(end - p), magic);
*end = c;
if (empty) {
goto theend;
@@ -538,7 +539,8 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
if (!use_last_pat) {
next_char = ccline.cmdbuff[skiplen + patlen];
ccline.cmdbuff[skiplen + patlen] = NUL;
- if (empty_pattern(ccline.cmdbuff + skiplen, search_delim) && !no_hlsearch) {
+ if (empty_pattern(ccline.cmdbuff + skiplen, (size_t)patlen, search_delim)
+ && !no_hlsearch) {
redraw_all_later(UPD_SOME_VALID);
set_no_hlsearch(true);
}
@@ -900,12 +902,11 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
&& ccline.cmdlen
&& s->firstc != NUL
&& (s->some_key_typed || s->histype == HIST_SEARCH)) {
- size_t cmdbufflen = strlen(ccline.cmdbuff);
- add_to_history(s->histype, ccline.cmdbuff, cmdbufflen, true,
+ add_to_history(s->histype, ccline.cmdbuff, (size_t)ccline.cmdlen, true,
s->histype == HIST_SEARCH ? s->firstc : NUL);
if (s->firstc == ':') {
xfree(new_last_cmdline);
- new_last_cmdline = xstrnsave(ccline.cmdbuff, cmdbufflen);
+ new_last_cmdline = xstrnsave(ccline.cmdbuff, (size_t)ccline.cmdlen);
}
}
@@ -1262,6 +1263,7 @@ static int command_line_execute(VimState *state, int key)
&& s->c != K_LEFT && s->c != K_RIGHT
&& (s->xpc.xp_numfiles > 0 || (s->c != Ctrl_P && s->c != Ctrl_N))) {
XFREE_CLEAR(s->lookfor);
+ s->lookforlen = 0;
}
// When there are matching completions to select <S-Tab> works like
@@ -1440,7 +1442,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
return FAIL;
}
skiplen = 0;
- patlen = (int)strlen(pat);
+ patlen = (int)last_search_pattern_len();
} else {
pat = ccline.cmdbuff + skiplen;
}
@@ -1574,7 +1576,8 @@ static int command_line_erase_chars(CommandLineState *s)
return CMDLINE_NOT_CHANGED;
}
- XFREE_CLEAR(ccline.cmdbuff); // no commandline to return
+ dealloc_cmdbuff(); // no commandline to return
+
if (!cmd_silent && !ui_has(kUICmdline)) {
msg_col = 0;
msg_putchar(' '); // delete ':'
@@ -1702,7 +1705,6 @@ static void command_line_left_right_mouse(CommandLineState *s)
static void command_line_next_histidx(CommandLineState *s, bool next_match)
{
- int j = (int)strlen(s->lookfor);
while (true) {
// one step backwards
if (!next_match) {
@@ -1746,7 +1748,7 @@ static void command_line_next_histidx(CommandLineState *s, bool next_match)
if ((s->c != K_UP && s->c != K_DOWN)
|| s->hiscnt == s->save_hiscnt
|| strncmp(get_histentry(s->histype)[s->hiscnt].hisstr,
- s->lookfor, (size_t)j) == 0) {
+ s->lookfor, (size_t)s->lookforlen) == 0) {
break;
}
}
@@ -1765,30 +1767,34 @@ static int command_line_browse_history(CommandLineState *s)
// save current command string so it can be restored later
if (s->lookfor == NULL) {
- s->lookfor = xstrdup(ccline.cmdbuff);
+ s->lookfor = xstrnsave(ccline.cmdbuff, (size_t)ccline.cmdlen);
s->lookfor[ccline.cmdpos] = NUL;
+ s->lookforlen = ccline.cmdpos;
}
bool next_match = (s->c == K_DOWN || s->c == K_S_DOWN || s->c == Ctrl_N
|| s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN);
command_line_next_histidx(s, next_match);
- if (s->hiscnt != s->save_hiscnt) {
- // jumped to other entry
+ if (s->hiscnt != s->save_hiscnt) { // jumped to other entry
char *p;
+ int plen;
int old_firstc;
- XFREE_CLEAR(ccline.cmdbuff);
+ dealloc_cmdbuff();
+
s->xpc.xp_context = EXPAND_NOTHING;
if (s->hiscnt == get_hislen()) {
p = s->lookfor; // back to the old one
+ plen = s->lookforlen;
} else {
p = get_histentry(s->histype)[s->hiscnt].hisstr;
+ plen = (int)strlen(p);
}
if (s->histype == HIST_SEARCH
&& p != s->lookfor
- && (old_firstc = (uint8_t)p[strlen(p) + 1]) != s->firstc) {
+ && (old_firstc = (uint8_t)p[plen + 1]) != s->firstc) {
int len = 0;
// Correct for the separator character used when
// adding the history entry vs the one used now.
@@ -1827,12 +1833,13 @@ static int command_line_browse_history(CommandLineState *s)
}
}
ccline.cmdbuff[len] = NUL;
+ ccline.cmdpos = ccline.cmdlen = len;
} else {
- alloc_cmdbuff((int)strlen(p));
+ alloc_cmdbuff(plen);
STRCPY(ccline.cmdbuff, p);
+ ccline.cmdpos = ccline.cmdlen = plen;
}
- ccline.cmdpos = ccline.cmdlen = (int)strlen(ccline.cmdbuff);
redrawcmd();
return CMDLINE_CHANGED;
}
@@ -2201,18 +2208,17 @@ static int command_line_not_changed(CommandLineState *s)
/// Guess that the pattern matches everything. Only finds specific cases, such
/// as a trailing \|, which can happen while typing a pattern.
-static bool empty_pattern(char *p, int delim)
+static bool empty_pattern(char *p, size_t len, int delim)
{
- size_t n = strlen(p);
magic_T magic_val = MAGIC_ON;
- if (n > 0) {
+ if (len > 0) {
skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val);
} else {
return true;
}
- return empty_pattern_magic(p, n, magic_val);
+ return empty_pattern_magic(p, len, magic_val);
}
static bool empty_pattern_magic(char *p, size_t len, magic_T magic_val)
@@ -2225,11 +2231,9 @@ static bool empty_pattern_magic(char *p, size_t len, magic_T magic_val)
// true, if the pattern is empty, or the pattern ends with \| and magic is
// set (or it ends with '|' and very magic is set)
- return len == 0 || (len > 1
- && ((p[len - 2] == '\\'
- && p[len - 1] == '|' && magic_val == MAGIC_ON)
- || (p[len - 2] != '\\'
- && p[len - 1] == '|' && magic_val == MAGIC_ALL)));
+ return len == 0 || (len > 1 && p[len - 1] == '|'
+ && ((p[len - 2] == '\\' && magic_val == MAGIC_ON)
+ || (p[len - 2] != '\\' && magic_val == MAGIC_ALL)));
}
handle_T cmdpreview_get_bufnr(void)
@@ -2710,7 +2714,7 @@ static int command_line_changed(CommandLineState *s)
/// Abandon the command line.
static void abandon_cmdline(void)
{
- XFREE_CLEAR(ccline.cmdbuff);
+ dealloc_cmdbuff();
ccline.redraw_state = kCmdRedrawNone;
if (msg_scrolled == 0) {
compute_cmdrow();
@@ -3000,8 +3004,15 @@ bool cmdline_at_end(void)
return (ccline.cmdpos >= ccline.cmdlen);
}
-// Allocate a new command line buffer.
-// Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
+/// Deallocate a command line buffer, updating the buffer size and length.
+static void dealloc_cmdbuff(void)
+{
+ XFREE_CLEAR(ccline.cmdbuff);
+ ccline.cmdlen = ccline.cmdbufflen = 0;
+}
+
+/// Allocate a new command line buffer.
+/// Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
static void alloc_cmdbuff(int len)
{
// give some extra space to avoid having to allocate all the time
@@ -3023,6 +3034,7 @@ void realloc_cmdbuff(int len)
}
char *p = ccline.cmdbuff;
+
alloc_cmdbuff(len); // will get some more
// There isn't always a NUL after the command, but it may need to be
// there, thus copy up to the NUL and add a NUL.
@@ -4509,17 +4521,20 @@ static int open_cmdwin(void)
cmdwin_result = Ctrl_C;
}
// Set the new command line from the cmdline buffer.
- xfree(ccline.cmdbuff);
+ dealloc_cmdbuff();
+
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed
const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
+ size_t plen = (cmdwin_result == K_XF2) ? 2 : 3;
if (histtype == HIST_CMD) {
// Execute the command directly.
- ccline.cmdbuff = xstrdup(p);
+ ccline.cmdbuff = xmemdupz(p, plen);
+ ccline.cmdlen = (int)plen;
+ ccline.cmdbufflen = (int)plen + 1;
cmdwin_result = CAR;
} else {
// First need to cancel what we were doing.
- ccline.cmdbuff = NULL;
stuffcharReadbuff(':');
stuffReadbuff(p);
stuffcharReadbuff(CAR);
@@ -4529,17 +4544,18 @@ static int open_cmdwin(void)
// and don't modify the cmd window.
ccline.cmdbuff = NULL;
} else {
- ccline.cmdbuff = xstrdup(get_cursor_line_ptr());
+ ccline.cmdlen = get_cursor_line_len();
+ ccline.cmdbufflen = ccline.cmdlen + 1;
+ ccline.cmdbuff = xstrnsave(get_cursor_line_ptr(), (size_t)ccline.cmdlen);
}
+
if (ccline.cmdbuff == NULL) {
- ccline.cmdbuff = xstrdup("");
+ ccline.cmdbuff = xmemdupz("", 0);
ccline.cmdlen = 0;
ccline.cmdbufflen = 1;
ccline.cmdpos = 0;
cmdwin_result = Ctrl_C;
} else {
- ccline.cmdlen = (int)strlen(ccline.cmdbuff);
- ccline.cmdbufflen = ccline.cmdlen + 1;
ccline.cmdpos = curwin->w_cursor.col;
// If the cursor is on the last character, it probably should be after it.
if (ccline.cmdpos == ccline.cmdlen - 1 || ccline.cmdpos > ccline.cmdlen) {
diff --git a/src/nvim/search.c b/src/nvim/search.c
index ff6e135df1..2a935f6878 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -380,6 +380,11 @@ char *last_search_pattern(void)
return spats[RE_SEARCH].pat;
}
+size_t last_search_pattern_len(void)
+{
+ return spats[RE_SEARCH].patlen;
+}
+
/// Return true when case should be ignored for search pattern "pat".
/// Uses the 'ignorecase' and 'smartcase' options.
int ignorecase(char *pat)