aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_getln.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_getln.c')
-rw-r--r--src/nvim/ex_getln.c654
1 files changed, 332 insertions, 322 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 479d195966..38432a34db 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -142,12 +142,12 @@ typedef struct command_line_state {
long count;
int indent;
int c;
- int i;
- int j;
int gotesc; // TRUE when <ESC> just typed
int do_abbr; // when TRUE check for abbr.
char_u *lookfor; // string to match
int hiscnt; // current history line in use
+ int save_hiscnt; // history line before attempting
+ // to jump to next match
int histype; // history type to be used
pos_T search_start; // where 'incsearch' starts searching
pos_T save_cursor;
@@ -200,7 +200,7 @@ static Array cmdline_block = ARRAY_DICT_INIT;
*/
typedef void *(*user_expand_func_T)(const char_u *,
int,
- const char_u * const *,
+ typval_T *,
bool);
static histentry_T *(history[HIST_COUNT]) = {NULL, NULL, NULL, NULL, NULL};
@@ -279,6 +279,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
s->old_topfill = curwin->w_topfill;
s->old_botline = curwin->w_botline;
+ assert(indent >= 0);
+
// set some variables for redrawcmd()
ccline.cmdfirstc = (s->firstc == '@' ? 0 : s->firstc);
ccline.cmdindent = (s->firstc > 0 ? s->indent : 0);
@@ -294,7 +296,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
// autoindent for :insert and :append
if (s->firstc <= 0) {
- memset(ccline.cmdbuff, ' ', s->indent);
+ memset(ccline.cmdbuff, ' ', (size_t)s->indent);
ccline.cmdbuff[s->indent] = NUL;
ccline.cmdpos = s->indent;
ccline.cmdspos = s->indent;
@@ -315,7 +317,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
if (!cmd_silent) {
gotocmdline(true);
redrawcmdprompt(); // draw prompt or indent
- set_cmdspos();
+ ccline.cmdspos = cmd_startcol();
if (!msg_scroll) {
msg_ext_clear(false);
}
@@ -382,7 +384,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
bool tl_ret = true;
dict_T *dict = get_vim_var_dict(VV_EVENT);
char firstcbuf[2];
- firstcbuf[0] = firstc > 0 ? firstc : '-';
+ firstcbuf[0] = (char)(firstc > 0 ? firstc : '-');
firstcbuf[1] = 0;
if (has_event(EVENT_CMDLINEENTER)) {
@@ -676,37 +678,37 @@ static int command_line_execute(VimState *state, int key)
// Hitting <Down> after "emenu Name.": complete submenu
if (s->c == K_DOWN && ccline.cmdpos > 0
&& ccline.cmdbuff[ccline.cmdpos - 1] == '.') {
- s->c = p_wc;
+ s->c = (int)p_wc;
} else if (s->c == K_UP) {
// Hitting <Up>: Remove one submenu name in front of the
// cursor
int found = false;
- s->j = (int)(s->xpc.xp_pattern - ccline.cmdbuff);
- s->i = 0;
- while (--s->j > 0) {
+ int j = (int)(s->xpc.xp_pattern - ccline.cmdbuff);
+ int i = 0;
+ while (--j > 0) {
// check for start of menu name
- if (ccline.cmdbuff[s->j] == ' '
- && ccline.cmdbuff[s->j - 1] != '\\') {
- s->i = s->j + 1;
+ if (ccline.cmdbuff[j] == ' '
+ && ccline.cmdbuff[j - 1] != '\\') {
+ i = j + 1;
break;
}
// check for start of submenu name
- if (ccline.cmdbuff[s->j] == '.'
- && ccline.cmdbuff[s->j - 1] != '\\') {
+ if (ccline.cmdbuff[j] == '.'
+ && ccline.cmdbuff[j - 1] != '\\') {
if (found) {
- s->i = s->j + 1;
+ i = j + 1;
break;
} else {
found = true;
}
}
}
- if (s->i > 0) {
- cmdline_del(s->i);
+ if (i > 0) {
+ cmdline_del(i);
}
- s->c = p_wc;
+ s->c = (int)p_wc;
s->xpc.xp_context = EXPAND_NOTHING;
}
}
@@ -728,44 +730,44 @@ static int command_line_execute(VimState *state, int key)
|| ccline.cmdbuff[ccline.cmdpos - 2] != '.'
|| ccline.cmdbuff[ccline.cmdpos - 3] != '.')) {
// go down a directory
- s->c = p_wc;
+ s->c = (int)p_wc;
} else if (STRNCMP(s->xpc.xp_pattern, upseg + 1, 3) == 0
&& s->c == K_DOWN) {
// If in a direct ancestor, strip off one ../ to go down
int found = false;
- s->j = ccline.cmdpos;
- s->i = (int)(s->xpc.xp_pattern - ccline.cmdbuff);
- while (--s->j > s->i) {
- s->j -= utf_head_off(ccline.cmdbuff, ccline.cmdbuff + s->j);
- if (vim_ispathsep(ccline.cmdbuff[s->j])) {
+ int j = ccline.cmdpos;
+ int i = (int)(s->xpc.xp_pattern - ccline.cmdbuff);
+ while (--j > i) {
+ j -= utf_head_off(ccline.cmdbuff, ccline.cmdbuff + j);
+ if (vim_ispathsep(ccline.cmdbuff[j])) {
found = true;
break;
}
}
if (found
- && ccline.cmdbuff[s->j - 1] == '.'
- && ccline.cmdbuff[s->j - 2] == '.'
- && (vim_ispathsep(ccline.cmdbuff[s->j - 3]) || s->j == s->i + 2)) {
- cmdline_del(s->j - 2);
- s->c = p_wc;
+ && ccline.cmdbuff[j - 1] == '.'
+ && ccline.cmdbuff[j - 2] == '.'
+ && (vim_ispathsep(ccline.cmdbuff[j - 3]) || j == i + 2)) {
+ cmdline_del(j - 2);
+ s->c = (int)p_wc;
}
} else if (s->c == K_UP) {
// go up a directory
int found = false;
- s->j = ccline.cmdpos - 1;
- s->i = (int)(s->xpc.xp_pattern - ccline.cmdbuff);
- while (--s->j > s->i) {
- s->j -= utf_head_off(ccline.cmdbuff, ccline.cmdbuff + s->j);
- if (vim_ispathsep(ccline.cmdbuff[s->j])
+ int j = ccline.cmdpos - 1;
+ int i = (int)(s->xpc.xp_pattern - ccline.cmdbuff);
+ while (--j > i) {
+ j -= utf_head_off(ccline.cmdbuff, ccline.cmdbuff + j);
+ if (vim_ispathsep(ccline.cmdbuff[j])
#ifdef BACKSLASH_IN_FILENAME
- && vim_strchr((const char_u *)" *?[{`$%#", ccline.cmdbuff[s->j + 1])
+ && vim_strchr((const char_u *)" *?[{`$%#", ccline.cmdbuff[j + 1])
== NULL
#endif
) {
if (found) {
- s->i = s->j + 1;
+ i = j + 1;
break;
} else {
found = true;
@@ -774,28 +776,28 @@ static int command_line_execute(VimState *state, int key)
}
if (!found) {
- s->j = s->i;
- } else if (STRNCMP(ccline.cmdbuff + s->j, upseg, 4) == 0) {
- s->j += 4;
- } else if (STRNCMP(ccline.cmdbuff + s->j, upseg + 1, 3) == 0
- && s->j == s->i) {
- s->j += 3;
+ j = i;
+ } else if (STRNCMP(ccline.cmdbuff + j, upseg, 4) == 0) {
+ j += 4;
+ } else if (STRNCMP(ccline.cmdbuff + j, upseg + 1, 3) == 0
+ && j == i) {
+ j += 3;
} else {
- s->j = 0;
+ j = 0;
}
- if (s->j > 0) {
+ if (j > 0) {
// TODO(tarruda): this is only for DOS/Unix systems - need to put in
// machine-specific stuff here and in upseg init
- cmdline_del(s->j);
+ cmdline_del(j);
put_on_cmdline(upseg + 1, 3, false);
- } else if (ccline.cmdpos > s->i) {
- cmdline_del(s->i);
+ } else if (ccline.cmdpos > i) {
+ cmdline_del(i);
}
// Now complete in the new directory. Set KeyTyped in case the
// Up key came from a mapping.
- s->c = p_wc;
+ s->c = (int)p_wc;
KeyTyped = true;
}
}
@@ -943,7 +945,7 @@ static int command_line_execute(VimState *state, int key)
}
} else { // typed p_wc first time
s->wim_index = 0;
- s->j = ccline.cmdpos;
+ int j = ccline.cmdpos;
// if 'wildmode' first contains "longest", get longest
// common part
@@ -970,7 +972,7 @@ static int command_line_execute(VimState *state, int key)
if (s->res == OK && s->xpc.xp_numfiles > 1) {
// a "longest" that didn't do anything is skipped (but not
// "list:longest")
- if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == s->j) {
+ if (wim_flags[0] == WIM_LONGEST && ccline.cmdpos == j) {
s->wim_index = 1;
}
if ((wim_flags[s->wim_index] & WIM_LIST)
@@ -1069,13 +1071,13 @@ static void command_line_next_incsearch(CommandLineState *s, bool next_match)
search_flags += SEARCH_KEEP;
}
emsg_off++;
- s->i = searchit(curwin, curbuf, &t, NULL,
- next_match ? FORWARD : BACKWARD,
- pat, s->count, search_flags,
- RE_SEARCH, 0, NULL, NULL);
+ int found = searchit(curwin, curbuf, &t, NULL,
+ next_match ? FORWARD : BACKWARD,
+ pat, s->count, search_flags,
+ RE_SEARCH, 0, NULL, NULL);
emsg_off--;
ui_busy_stop();
- if (s->i) {
+ if (found) {
s->search_start = s->match_start;
s->match_end = t;
s->match_start = t;
@@ -1124,7 +1126,7 @@ static void command_line_next_incsearch(CommandLineState *s, bool next_match)
static void command_line_next_histidx(CommandLineState *s, bool next_match)
{
- s->j = (int)STRLEN(s->lookfor);
+ int j = (int)STRLEN(s->lookfor);
for (;; ) {
// one step backwards
if (!next_match) {
@@ -1137,7 +1139,7 @@ static void command_line_next_histidx(CommandLineState *s, bool next_match)
s->hiscnt--;
} else {
// at top of list
- s->hiscnt = s->i;
+ s->hiscnt = s->save_hiscnt;
break;
}
} else { // one step forwards
@@ -1161,14 +1163,14 @@ static void command_line_next_histidx(CommandLineState *s, bool next_match)
}
if (s->hiscnt < 0 || history[s->histype][s->hiscnt].hisstr == NULL) {
- s->hiscnt = s->i;
+ s->hiscnt = s->save_hiscnt;
break;
}
if ((s->c != K_UP && s->c != K_DOWN)
- || s->hiscnt == s->i
+ || s->hiscnt == s->save_hiscnt
|| STRNCMP(history[s->histype][s->hiscnt].hisstr,
- s->lookfor, (size_t)s->j) == 0) {
+ s->lookfor, (size_t)j) == 0) {
break;
}
}
@@ -1193,7 +1195,7 @@ static int command_line_handle_key(CommandLineState *s)
++ccline.cmdpos;
}
- if (has_mbyte && s->c == K_DEL) {
+ if (s->c == K_DEL) {
ccline.cmdpos += mb_off_next(ccline.cmdbuff,
ccline.cmdbuff + ccline.cmdpos);
}
@@ -1201,43 +1203,30 @@ static int command_line_handle_key(CommandLineState *s)
if (ccline.cmdpos > 0) {
char_u *p;
- s->j = ccline.cmdpos;
- p = ccline.cmdbuff + s->j;
- if (has_mbyte) {
- p = mb_prevptr(ccline.cmdbuff, p);
-
- if (s->c == Ctrl_W) {
- while (p > ccline.cmdbuff && ascii_isspace(*p)) {
- p = mb_prevptr(ccline.cmdbuff, p);
- }
+ int j = ccline.cmdpos;
+ p = mb_prevptr(ccline.cmdbuff, ccline.cmdbuff + j);
- s->i = mb_get_class(p);
- while (p > ccline.cmdbuff && mb_get_class(p) == s->i)
- p = mb_prevptr(ccline.cmdbuff, p);
-
- if (mb_get_class(p) != s->i) {
- p += (*mb_ptr2len)(p);
- }
+ if (s->c == Ctrl_W) {
+ while (p > ccline.cmdbuff && ascii_isspace(*p)) {
+ p = mb_prevptr(ccline.cmdbuff, p);
}
- } else if (s->c == Ctrl_W) {
- while (p > ccline.cmdbuff && ascii_isspace(p[-1])) {
- --p;
+
+ int i = mb_get_class(p);
+ while (p > ccline.cmdbuff && mb_get_class(p) == i) {
+ p = mb_prevptr(ccline.cmdbuff, p);
}
- s->i = vim_iswordc(p[-1]);
- while (p > ccline.cmdbuff && !ascii_isspace(p[-1])
- && vim_iswordc(p[-1]) == s->i)
- --p;
- } else {
- --p;
+ if (mb_get_class(p) != i) {
+ p += utfc_ptr2len(p);
+ }
}
ccline.cmdpos = (int)(p - ccline.cmdbuff);
- ccline.cmdlen -= s->j - ccline.cmdpos;
- s->i = ccline.cmdpos;
+ ccline.cmdlen -= j - ccline.cmdpos;
+ int i = ccline.cmdpos;
- while (s->i < ccline.cmdlen) {
- ccline.cmdbuff[s->i++] = ccline.cmdbuff[s->j++];
+ while (i < ccline.cmdlen) {
+ ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
}
// Truncate at the end, required for multi-byte chars.
@@ -1307,13 +1296,13 @@ static int command_line_handle_key(CommandLineState *s)
status_redraw_curbuf();
return command_line_not_changed(s);
- case Ctrl_U:
+ case Ctrl_U: {
// delete all characters left of the cursor
- s->j = ccline.cmdpos;
- ccline.cmdlen -= s->j;
- s->i = ccline.cmdpos = 0;
- while (s->i < ccline.cmdlen) {
- ccline.cmdbuff[s->i++] = ccline.cmdbuff[s->j++];
+ int j = ccline.cmdpos;
+ ccline.cmdlen -= j;
+ int i = ccline.cmdpos = 0;
+ while (i < ccline.cmdlen) {
+ ccline.cmdbuff[i++] = ccline.cmdbuff[j++];
}
// Truncate at the end, required for multi-byte chars.
@@ -1323,6 +1312,7 @@ static int command_line_handle_key(CommandLineState *s)
}
redrawcmd();
return command_line_changed(s);
+ }
case ESC: // get here if p_wc != ESC or when ESC typed twice
case Ctrl_C:
@@ -1339,15 +1329,15 @@ static int command_line_handle_key(CommandLineState *s)
// putting it in history
return 0; // back to cmd mode
- case Ctrl_R: // insert register
+ case Ctrl_R: { // insert register
putcmdline('"', true);
- ++no_mapping;
- s->i = s->c = plain_vgetc(); // CTRL-R <char>
- if (s->i == Ctrl_O) {
- s->i = Ctrl_R; // CTRL-R CTRL-O == CTRL-R CTRL-R
+ no_mapping++;
+ int i = s->c = plain_vgetc(); // CTRL-R <char>
+ if (i == Ctrl_O) {
+ i = Ctrl_R; // CTRL-R CTRL-O == CTRL-R CTRL-R
}
- if (s->i == Ctrl_R) {
+ if (i == Ctrl_R) {
s->c = plain_vgetc(); // CTRL-R CTRL-R <char>
}
--no_mapping;
@@ -1369,7 +1359,7 @@ static int command_line_handle_key(CommandLineState *s)
}
if (s->c != ESC) { // use ESC to cancel inserting register
- cmdline_paste(s->c, s->i == Ctrl_R, false);
+ cmdline_paste(s->c, i == Ctrl_R, false);
// When there was a serious error abort getting the
// command line.
@@ -1391,6 +1381,7 @@ static int command_line_handle_key(CommandLineState *s)
ccline.special_char = NUL;
redrawcmd();
return command_line_changed(s);
+ }
case Ctrl_D:
if (showmatches(&s->xpc, false) == EXPAND_NOTHING) {
@@ -1409,24 +1400,17 @@ static int command_line_handle_key(CommandLineState *s)
break;
}
- s->i = cmdline_charsize(ccline.cmdpos);
- if (KeyTyped && ccline.cmdspos + s->i >= Columns * Rows) {
+ int cells = cmdline_charsize(ccline.cmdpos);
+ if (KeyTyped && ccline.cmdspos + cells >= Columns * Rows) {
break;
}
- ccline.cmdspos += s->i;
- if (has_mbyte) {
- ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff
- + ccline.cmdpos);
- } else {
- ++ccline.cmdpos;
- }
+ ccline.cmdspos += cells;
+ ccline.cmdpos += utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos);
} while ((s->c == K_S_RIGHT || s->c == K_C_RIGHT
|| (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)))
&& ccline.cmdbuff[ccline.cmdpos] != ' ');
- if (has_mbyte) {
- set_cmdspos_cursor();
- }
+ ccline.cmdspos = cmd_screencol(ccline.cmdpos);
return command_line_not_changed(s);
case K_LEFT:
@@ -1446,7 +1430,7 @@ static int command_line_handle_key(CommandLineState *s)
|| (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)))
&& ccline.cmdbuff[ccline.cmdpos - 1] != ' ');
- set_cmdspos_cursor();
+ ccline.cmdspos = cmd_screencol(ccline.cmdpos);
if (ccline.special_char != NUL) {
putcmdline(ccline.special_char, ccline.special_shift);
}
@@ -1493,22 +1477,19 @@ static int command_line_handle_key(CommandLineState *s)
return command_line_not_changed(s); // Ignore mouse
}
- set_cmdspos();
+ ccline.cmdspos = cmd_startcol();
for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;
- ++ccline.cmdpos) {
- s->i = cmdline_charsize(ccline.cmdpos);
+ ccline.cmdpos++) {
+ int cells = cmdline_charsize(ccline.cmdpos);
if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
- && mouse_col < ccline.cmdspos % Columns + s->i) {
+ && mouse_col < ccline.cmdspos % Columns + cells) {
break;
}
- if (has_mbyte) {
- // Count ">" for double-wide char that doesn't fit.
- correct_cmdspos(ccline.cmdpos, s->i);
- ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff
- + ccline.cmdpos) - 1;
- }
- ccline.cmdspos += s->i;
+ // Count ">" for double-wide char that doesn't fit.
+ correct_screencol(ccline.cmdpos, cells, &ccline.cmdspos);
+ ccline.cmdpos += utfc_ptr2len(ccline.cmdbuff + ccline.cmdpos) - 1;
+ ccline.cmdspos += cells;
}
return command_line_not_changed(s);
@@ -1537,7 +1518,7 @@ static int command_line_handle_key(CommandLineState *s)
case K_S_HOME:
case K_C_HOME:
ccline.cmdpos = 0;
- set_cmdspos();
+ ccline.cmdspos = cmd_startcol();
return command_line_not_changed(s);
case Ctrl_E: // end of command line
@@ -1546,7 +1527,7 @@ static int command_line_handle_key(CommandLineState *s)
case K_S_END:
case K_C_END:
ccline.cmdpos = ccline.cmdlen;
- set_cmdspos_cursor();
+ ccline.cmdspos = cmd_screencol(ccline.cmdpos);
return command_line_not_changed(s);
case Ctrl_A: // all matches
@@ -1613,7 +1594,7 @@ static int command_line_handle_key(CommandLineState *s)
return command_line_not_changed(s);
}
- s->i = s->hiscnt;
+ s->save_hiscnt = s->hiscnt;
// save current command string so it can be restored later
if (s->lookfor == NULL) {
@@ -1625,7 +1606,7 @@ static int command_line_handle_key(CommandLineState *s)
|| s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN);
command_line_next_histidx(s, next_match);
- if (s->hiscnt != s->i) {
+ if (s->hiscnt != s->save_hiscnt) {
// jumped to other entry
char_u *p;
int len = 0;
@@ -1646,35 +1627,35 @@ static int command_line_handle_key(CommandLineState *s)
// adding the history entry vs the one used now.
// First loop: count length.
// Second loop: copy the characters.
- for (s->i = 0; s->i <= 1; ++s->i) {
+ for (int i = 0; i <= 1; i++) {
len = 0;
- for (s->j = 0; p[s->j] != NUL; ++s->j) {
+ for (int j = 0; p[j] != NUL; j++) {
// Replace old sep with new sep, unless it is
// escaped.
- if (p[s->j] == old_firstc
- && (s->j == 0 || p[s->j - 1] != '\\')) {
- if (s->i > 0) {
- ccline.cmdbuff[len] = s->firstc;
+ if (p[j] == old_firstc
+ && (j == 0 || p[j - 1] != '\\')) {
+ if (i > 0) {
+ ccline.cmdbuff[len] = (char_u)s->firstc;
}
} else {
// Escape new sep, unless it is already
// escaped.
- if (p[s->j] == s->firstc
- && (s->j == 0 || p[s->j - 1] != '\\')) {
- if (s->i > 0) {
+ if (p[j] == s->firstc
+ && (j == 0 || p[j - 1] != '\\')) {
+ if (i > 0) {
ccline.cmdbuff[len] = '\\';
}
++len;
}
- if (s->i > 0) {
- ccline.cmdbuff[len] = p[s->j];
+ if (i > 0) {
+ ccline.cmdbuff[len] = p[j];
}
}
++len;
}
- if (s->i == 0) {
+ if (i == 0) {
alloc_cmdbuff(len);
}
}
@@ -1766,9 +1747,9 @@ static int command_line_handle_key(CommandLineState *s)
if (IS_SPECIAL(s->c) || mod_mask != 0) {
put_on_cmdline(get_special_key_name(s->c, mod_mask), -1, true);
} else {
- s->j = utf_char2bytes(s->c, IObuff);
- IObuff[s->j] = NUL; // exclude composing chars
- put_on_cmdline(IObuff, s->j, true);
+ int j = utf_char2bytes(s->c, IObuff);
+ IObuff[j] = NUL; // exclude composing chars
+ put_on_cmdline(IObuff, j, true);
}
return command_line_changed(s);
}
@@ -1810,7 +1791,7 @@ static int command_line_changed(CommandLineState *s)
dict_T *dict = get_vim_var_dict(VV_EVENT);
char firstcbuf[2];
- firstcbuf[0] = s->firstc > 0 ? s->firstc : '-';
+ firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-');
firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline
@@ -1845,10 +1826,11 @@ static int command_line_changed(CommandLineState *s)
s->incsearch_postponed = false;
curwin->w_cursor = s->search_start; // start at old position
save_last_search_pattern();
+ int i;
// If there is no command line, don't do anything
if (ccline.cmdlen == 0) {
- s->i = 0;
+ i = 0;
SET_NO_HLSEARCH(true); // turn off previous highlight
redraw_all_later(SOME_VALID);
} else {
@@ -1861,15 +1843,14 @@ static int command_line_changed(CommandLineState *s)
if (!p_hls) {
search_flags += SEARCH_KEEP;
}
- s->i = do_search(NULL, s->firstc, ccline.cmdbuff, s->count,
- search_flags,
- &tm, NULL);
+ i = do_search(NULL, s->firstc, ccline.cmdbuff, s->count,
+ search_flags, &tm, NULL);
emsg_off--;
// if interrupted while searching, behave like it failed
if (got_int) {
(void)vpeekc(); // remove <C-C> from input stream
got_int = false; // don't abandon the command line
- s->i = 0;
+ i = 0;
} else if (char_avail()) {
// cancelled searching because a char was typed
s->incsearch_postponed = true;
@@ -1877,7 +1858,7 @@ static int command_line_changed(CommandLineState *s)
ui_busy_stop();
}
- if (s->i != 0) {
+ if (i != 0) {
highlight_match = true; // highlight position
} else {
highlight_match = false; // remove highlight
@@ -1892,7 +1873,7 @@ static int command_line_changed(CommandLineState *s)
changed_cline_bef_curs();
update_topline();
- if (s->i != 0) {
+ if (i != 0) {
pos_T save_pos = curwin->w_cursor;
s->match_start = curwin->w_cursor;
@@ -1921,7 +1902,7 @@ static int command_line_changed(CommandLineState *s)
restore_last_search_pattern();
// Leave it at the end to make CTRL-R CTRL-W work.
- if (s->i != 0) {
+ if (i != 0) {
curwin->w_cursor = end_pos;
}
@@ -1978,6 +1959,7 @@ static int command_line_changed(CommandLineState *s)
static void abandon_cmdline(void)
{
XFREE_CLEAR(ccline.cmdbuff);
+ ccline.redraw_state = kCmdRedrawNone;
if (msg_scrolled == 0) {
compute_cmdrow();
}
@@ -2131,58 +2113,52 @@ static int cmdline_charsize(int idx)
return ptr2cells(ccline.cmdbuff + idx);
}
-/*
- * Compute the offset of the cursor on the command line for the prompt and
- * indent.
- */
-static void set_cmdspos(void)
+/// Compute the offset of the cursor on the command line for the prompt and
+/// indent.
+static int cmd_startcol(void)
{
- if (ccline.cmdfirstc != NUL)
- ccline.cmdspos = 1 + ccline.cmdindent;
- else
- ccline.cmdspos = 0 + ccline.cmdindent;
+ return ccline.cmdindent + ((ccline.cmdfirstc != NUL) ? 1 : 0);
}
-/*
- * Compute the screen position for the cursor on the command line.
- */
-static void set_cmdspos_cursor(void)
+
+/// Compute the column position for a byte position on the command line.
+static int cmd_screencol(int bytepos)
{
- int i, m, c;
+ int m; // maximum column
- set_cmdspos();
+ int col = cmd_startcol();
if (KeyTyped) {
m = Columns * Rows;
if (m < 0) /* overflow, Columns or Rows at weird value */
m = MAXCOL;
- } else
+ } else {
m = MAXCOL;
- for (i = 0; i < ccline.cmdlen && i < ccline.cmdpos; ++i) {
- c = cmdline_charsize(i);
- /* Count ">" for double-wide multi-byte char that doesn't fit. */
- if (has_mbyte)
- correct_cmdspos(i, c);
- /* If the cmdline doesn't fit, show cursor on last visible char.
- * Don't move the cursor itself, so we can still append. */
- if ((ccline.cmdspos += c) >= m) {
- ccline.cmdspos -= c;
+ }
+
+ for (int i = 0; i < ccline.cmdlen && i < bytepos;
+ i += utfc_ptr2len(ccline.cmdbuff + i)) {
+ int c = cmdline_charsize(i);
+ // Count ">" for double-wide multi-byte char that doesn't fit.
+ correct_screencol(i, c, &col);
+
+ // If the cmdline doesn't fit, show cursor on last visible char.
+ // Don't move the cursor itself, so we can still append.
+ if ((col += c) >= m) {
+ col -= c;
break;
}
- if (has_mbyte)
- i += (*mb_ptr2len)(ccline.cmdbuff + i) - 1;
}
+ return col;
}
-/*
- * Check if the character at "idx", which is "cells" wide, is a multi-byte
- * character that doesn't fit, so that a ">" must be displayed.
- */
-static void correct_cmdspos(int idx, int cells)
+/// Check if the character at "idx", which is "cells" wide, is a multi-byte
+/// character that doesn't fit, so that a ">" must be displayed.
+static void correct_screencol(int idx, int cells, int *col)
{
if (utfc_ptr2len(ccline.cmdbuff + idx) > 1
&& utf_ptr2cells(ccline.cmdbuff + idx) > 1
- && ccline.cmdspos % Columns + cells > Columns) {
- ccline.cmdspos++;
+ && (*col) % Columns + cells > Columns) {
+ (*col)++;
}
}
@@ -2323,8 +2299,10 @@ add_indent:
char_u *s = skipwhite(p);
// Insert spaces after leading whitespaces.
- memmove(s + num_spaces, s, line_ga.ga_len - (s - p) + 1);
- memset(s, ' ', num_spaces);
+ long move_len = line_ga.ga_len - (s - p) + 1;
+ assert(move_len >= 0);
+ memmove(s + num_spaces, s, (size_t)move_len);
+ memset(s, ' ', (size_t)num_spaces);
line_ga.ga_len += num_spaces;
}
@@ -2377,8 +2355,10 @@ redraw:
while ((old_indent = get_indent_str(p, 8, FALSE)) > indent) {
*--to = NUL;
}
- memmove(to, from, line_ga.ga_len - (from - p) + 1);
- line_ga.ga_len -= from - to;
+ long move_len = line_ga.ga_len - (from - p) + 1;
+ assert(move_len > 0);
+ memmove(to, from, (size_t)move_len);
+ line_ga.ga_len -= (int)(from - to);
// Removed to much indentation, fix it before redrawing.
num_spaces = indent - old_indent;
@@ -2484,7 +2464,7 @@ static void alloc_cmdbuff(int len)
else
len += 20;
- ccline.cmdbuff = xmalloc(len);
+ ccline.cmdbuff = xmalloc((size_t)len);
ccline.cmdbufflen = len;
}
@@ -2521,7 +2501,7 @@ static void realloc_cmdbuff(int len)
static char_u *arshape_buf = NULL;
# if defined(EXITFREE)
-void free_cmdline_buf(void)
+void free_arshape_buf(void)
{
xfree(arshape_buf);
}
@@ -2561,26 +2541,28 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
size_t prev_end = 0;
for (size_t i = 0 ; i < kv_size(colors) ; i++) {
const ParserHighlightChunk chunk = kv_A(colors, i);
+ assert(chunk.start.col < INT_MAX);
+ assert(chunk.end_col < INT_MAX);
if (chunk.start.col != prev_end) {
kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) {
- .start = prev_end,
- .end = chunk.start.col,
+ .start = (int)prev_end,
+ .end = (int)chunk.start.col,
.attr = 0,
}));
}
const int id = syn_name2id((const char_u *)chunk.group);
const int attr = (id == 0 ? 0 : syn_id2attr(id));
kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) {
- .start = chunk.start.col,
- .end = chunk.end_col,
+ .start = (int)chunk.start.col,
+ .end = (int)chunk.end_col,
.attr = attr,
}));
prev_end = chunk.end_col;
}
if (prev_end < (size_t)colored_ccline->cmdlen) {
kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) {
- .start = prev_end,
- .end = (size_t)colored_ccline->cmdlen,
+ .start = (int)prev_end,
+ .end = colored_ccline->cmdlen,
.attr = 0,
}));
}
@@ -2745,8 +2727,8 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
}
if (start != prev_end) {
kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
- .start = prev_end,
- .end = start,
+ .start = (int)prev_end,
+ .end = (int)start,
.attr = 0,
}));
}
@@ -2775,15 +2757,15 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
const int id = syn_name2id((char_u *)group);
const int attr = (id == 0 ? 0 : syn_id2attr(id));
kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
- .start = start,
- .end = end,
+ .start = (int)start,
+ .end = (int)end,
.attr = attr,
}));
i++;
});
if (prev_end < colored_ccline->cmdlen) {
kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
- .start = prev_end,
+ .start = (int)prev_end,
.end = colored_ccline->cmdlen,
.attr = 0,
}));
@@ -2861,15 +2843,16 @@ static void draw_cmdline(int start, int len)
goto draw_cmdline_no_arabicshape;
}
- static int buflen = 0;
+ static size_t buflen = 0;
+ assert(len >= 0);
// Do arabic shaping into a temporary buffer. This is very
// inefficient!
- if (len * 2 + 2 > buflen) {
+ if ((size_t)len * 2 + 2 > buflen) {
// Re-allocate the buffer. We keep it around to avoid a lot of
// alloc()/free() calls.
xfree(arshape_buf);
- buflen = len * 2 + 2;
+ buflen = (size_t)len * 2 + 2;
arshape_buf = xmalloc(buflen);
}
@@ -2927,7 +2910,7 @@ static void draw_cmdline(int start, int len)
}
} else {
prev_c = u8c;
- memmove(arshape_buf + newlen, p, mb_l);
+ memmove(arshape_buf + newlen, p, (size_t)mb_l);
newlen += mb_l;
}
}
@@ -2972,8 +2955,9 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
Array item = ARRAY_DICT_INIT;
ADD(item, INTEGER_OBJ(chunk.attr));
+ assert(chunk.end >= chunk.start);
ADD(item, STRING_OBJ(cbuf_to_string((char *)line->cmdbuff + chunk.start,
- chunk.end-chunk.start)));
+ (size_t)(chunk.end-chunk.start))));
ADD(content, ARRAY_OBJ(item));
}
} else {
@@ -2994,7 +2978,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
}
}
-void ui_ext_cmdline_block_append(int indent, const char *line)
+void ui_ext_cmdline_block_append(size_t indent, const char *line)
{
char *buf = xmallocz(indent + strlen(line));
memset(buf, ' ', indent);
@@ -3073,7 +3057,7 @@ void cmdline_ui_flush(void)
* right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc.
* "c" must be printable (fit in one display cell)!
*/
-void putcmdline(int c, int shift)
+void putcmdline(char c, int shift)
{
if (cmd_silent) {
return;
@@ -3215,7 +3199,7 @@ void put_on_cmdline(char_u *str, int len, int redraw)
c = cmdline_charsize(ccline.cmdpos);
// count ">" for a double-wide char that doesn't fit.
if (has_mbyte) {
- correct_cmdspos(ccline.cmdpos, c);
+ correct_screencol(ccline.cmdpos, c, &ccline.cmdspos);
}
// Stop cursor at the end of the screen, but do increment the
// insert position, so that entering a very long command
@@ -3392,8 +3376,9 @@ void cmdline_paste_str(char_u *s, int literally)
/// Delete characters on the command line, from "from" to the current position.
static void cmdline_del(int from)
{
+ assert(ccline.cmdpos <= ccline.cmdlen);
memmove(ccline.cmdbuff + from, ccline.cmdbuff + ccline.cmdpos,
- (size_t)ccline.cmdlen - ccline.cmdpos + 1);
+ (size_t)ccline.cmdlen - (size_t)ccline.cmdpos + 1);
ccline.cmdlen -= ccline.cmdpos - from;
ccline.cmdpos = from;
}
@@ -3428,7 +3413,7 @@ static void redrawcmdprompt(void)
if (ccline.cmdprompt != NULL) {
msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr);
ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
- // do the reverse of set_cmdspos()
+ // do the reverse of cmd_startcol()
if (ccline.cmdfirstc != NUL) {
ccline.cmdindent--;
}
@@ -3470,7 +3455,7 @@ void redrawcmd(void)
msg_clr_eos();
msg_no_more = FALSE;
- set_cmdspos_cursor();
+ ccline.cmdspos = cmd_screencol(ccline.cmdpos);
if (ccline.special_char != NUL) {
putcmdline(ccline.special_char, ccline.special_shift);
@@ -3514,15 +3499,17 @@ static void cursorcmd(void)
}
if (cmdmsg_rl) {
- msg_row = cmdline_row + (ccline.cmdspos / (int)(Columns - 1));
- msg_col = (int)Columns - (ccline.cmdspos % (int)(Columns - 1)) - 1;
- if (msg_row <= 0)
+ msg_row = cmdline_row + (ccline.cmdspos / (Columns - 1));
+ msg_col = Columns - (ccline.cmdspos % (Columns - 1)) - 1;
+ if (msg_row <= 0) {
msg_row = Rows - 1;
+ }
} else {
- msg_row = cmdline_row + (ccline.cmdspos / (int)Columns);
- msg_col = ccline.cmdspos % (int)Columns;
- if (msg_row >= Rows)
+ msg_row = cmdline_row + (ccline.cmdspos / Columns);
+ msg_col = ccline.cmdspos % Columns;
+ if (msg_row >= Rows) {
msg_row = Rows - 1;
+ }
}
ui_cursor_goto(msg_row, msg_col);
@@ -3624,7 +3611,8 @@ nextwild (
}
i = (int)(xp->xp_pattern - ccline.cmdbuff);
- xp->xp_pattern_len = ccline.cmdpos - i;
+ assert(ccline.cmdpos >= i);
+ xp->xp_pattern_len = (size_t)ccline.cmdpos - (size_t)i;
if (type == WILD_NEXT || type == WILD_PREV) {
// Get next/previous match for a previous expanded pattern.
@@ -3644,7 +3632,7 @@ nextwild (
xfree(p1);
// Longest match: make sure it is not shorter, happens with :help.
if (p2 != NULL && type == WILD_LONGEST) {
- for (j = 0; j < xp->xp_pattern_len; j++) {
+ for (j = 0; (size_t)j < xp->xp_pattern_len; j++) {
if (ccline.cmdbuff[i + j] == '*'
|| ccline.cmdbuff[i + j] == '?') {
break;
@@ -3657,14 +3645,15 @@ nextwild (
}
if (p2 != NULL && !got_int) {
- difflen = (int)STRLEN(p2) - xp->xp_pattern_len;
+ difflen = (int)STRLEN(p2) - (int)xp->xp_pattern_len;
if (ccline.cmdlen + difflen + 4 > ccline.cmdbufflen) {
realloc_cmdbuff(ccline.cmdlen + difflen + 4);
xp->xp_pattern = ccline.cmdbuff + i;
}
+ assert(ccline.cmdpos <= ccline.cmdlen);
memmove(&ccline.cmdbuff[ccline.cmdpos + difflen],
&ccline.cmdbuff[ccline.cmdpos],
- (size_t)ccline.cmdlen - ccline.cmdpos + 1);
+ (size_t)ccline.cmdlen - (size_t)ccline.cmdpos + 1);
memmove(&ccline.cmdbuff[i], p2, STRLEN(p2));
ccline.cmdlen += difflen;
ccline.cmdpos += difflen;
@@ -3861,7 +3850,7 @@ ExpandOne (
size_t len = 0;
for (size_t mb_len; xp->xp_files[0][len]; len += mb_len) {
- mb_len = utfc_ptr2len(&xp->xp_files[0][len]);
+ mb_len = (size_t)utfc_ptr2len(&xp->xp_files[0][len]);
int c0 = utf_ptr2char(&xp->xp_files[0][len]);
for (i = 1; i < xp->xp_numfiles; i++) {
int ci = utf_ptr2char(&xp->xp_files[i][len]);
@@ -4100,7 +4089,8 @@ void cmdline_pum_display(bool changed_array)
*/
static int showmatches(expand_T *xp, int wildmenu)
{
-#define L_SHOWFILE(m) (showtail ? sm_gettail(files_found[m]) : files_found[m])
+#define L_SHOWFILE(m) (showtail \
+ ? sm_gettail(files_found[m], false) : files_found[m])
int num_files;
char_u **files_found;
int i, j, k;
@@ -4132,19 +4122,19 @@ static int showmatches(expand_T *xp, int wildmenu)
|| ui_has(kUIWildmenu);
if (compl_use_pum) {
+ assert(num_files >= 0);
compl_match_arraysize = num_files;
- compl_match_array = xcalloc(compl_match_arraysize, sizeof(pumitem_T));
+ compl_match_array = xcalloc((size_t)compl_match_arraysize,
+ sizeof(pumitem_T));
for (i = 0; i < num_files; i++) {
compl_match_array[i].pum_text = L_SHOWFILE(i);
}
- ssize_t offset = showtail ? sm_gettail(xp->xp_pattern)-xp->xp_pattern : 0;
+ char_u *endpos = (showtail
+ ? sm_gettail(xp->xp_pattern, true) : xp->xp_pattern);
if (ui_has(kUICmdline)) {
- compl_startcol = ccline.cmdpos - strnlen((char *)xp->xp_pattern+offset,
- xp->xp_pattern_len-offset);
+ compl_startcol = (int)(endpos - ccline.cmdbuff);
} else {
- compl_startcol = ccline.cmdspos
- - mb_string2cells_len(xp->xp_pattern+offset,
- xp->xp_pattern_len-offset);
+ compl_startcol = cmd_screencol((int)(endpos - ccline.cmdbuff));
}
compl_selected = -1;
cmdline_pum_display(true);
@@ -4180,14 +4170,15 @@ static int showmatches(expand_T *xp, int wildmenu)
maxlen = j;
}
- if (xp->xp_context == EXPAND_TAGS_LISTFILES)
+ if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
lines = num_files;
- else {
- /* compute the number of columns and lines for the listing */
- maxlen += 2; /* two spaces between file names */
- columns = ((int)Columns + 2) / maxlen;
- if (columns < 1)
+ } else {
+ // compute the number of columns and lines for the listing
+ maxlen += 2; // two spaces between file names
+ columns = (Columns + 2) / maxlen;
+ if (columns < 1) {
columns = 1;
+ }
lines = (num_files + columns - 1) / columns;
}
@@ -4276,7 +4267,7 @@ static int showmatches(expand_T *xp, int wildmenu)
* Private path_tail for showmatches() (and win_redr_status_matches()):
* Find tail of file name path, but ignore trailing "/".
*/
-char_u *sm_gettail(char_u *s)
+char_u *sm_gettail(char_u *s, bool eager)
{
char_u *p;
char_u *t = s;
@@ -4287,9 +4278,13 @@ char_u *sm_gettail(char_u *s)
#ifdef BACKSLASH_IN_FILENAME
&& !rem_backslash(p)
#endif
- )
- had_sep = TRUE;
- else if (had_sep) {
+ ) {
+ if (eager) {
+ t = p+1;
+ } else {
+ had_sep = true;
+ }
+ } else if (had_sep) {
t = p;
had_sep = FALSE;
}
@@ -4329,24 +4324,20 @@ static int expand_showtail(expand_T *xp)
return TRUE;
}
-/*
- * Prepare a string for expansion.
- * When expanding file names: The string will be used with expand_wildcards().
- * Copy "fname[len]" into allocated memory and add a '*' at the end.
- * When expanding other names: The string will be used with regcomp(). Copy
- * the name into allocated memory and prepend "^".
- */
-char_u *
-addstar (
- char_u *fname,
- int len,
- int context /* EXPAND_FILES etc. */
-)
+/// Prepare a string for expansion.
+///
+/// When expanding file names: The string will be used with expand_wildcards().
+/// Copy "fname[len]" into allocated memory and add a '*' at the end.
+/// When expanding other names: The string will be used with regcomp(). Copy
+/// the name into allocated memory and prepend "^".
+///
+/// @param context EXPAND_FILES etc.
+char_u *addstar(char_u *fname, size_t len, int context)
FUNC_ATTR_NONNULL_RET
{
char_u *retval;
- int i, j;
- int new_len;
+ size_t i, j;
+ size_t new_len;
char_u *tail;
int ends_in_star;
@@ -4437,9 +4428,10 @@ addstar (
tail = path_tail(retval);
ends_in_star = (len > 0 && retval[len - 1] == '*');
#ifndef BACKSLASH_IN_FILENAME
- for (i = len - 2; i >= 0; --i) {
- if (retval[i] != '\\')
+ for (ssize_t k = (ssize_t)len - 2; k >= 0; k--) {
+ if (retval[k] != '\\') {
break;
+ }
ends_in_star = !ends_in_star;
}
#endif
@@ -4520,7 +4512,7 @@ set_cmd_context (
int use_ccline // use ccline for info
)
{
- int old_char = NUL;
+ char_u old_char = NUL;
/*
* Avoid a UMR warning from Purify, only save the character if it has been
@@ -4584,8 +4576,9 @@ expand_cmdline (
return EXPAND_NOTHING;
}
- /* add star to file name, or convert to regexp if not exp. files. */
- xp->xp_pattern_len = (int)(str + col - xp->xp_pattern);
+ // add star to file name, or convert to regexp if not exp. files.
+ assert((str + col) - xp->xp_pattern >= 0);
+ xp->xp_pattern_len = (size_t)((str + col) - xp->xp_pattern);
file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
if (p_wic)
@@ -4875,7 +4868,7 @@ void ExpandGeneric(
)
{
int i;
- int count = 0;
+ size_t count = 0;
char_u *str;
// count the number of matching names
@@ -4891,7 +4884,8 @@ void ExpandGeneric(
}
if (count == 0)
return;
- *num_file = count;
+ assert(count < INT_MAX);
+ *num_file = (int)count;
*file = (char_u **)xmalloc(count * sizeof(char_u *));
// copy the matching names into allocated memory
@@ -4952,7 +4946,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
{
char_u *pat;
int i;
- char_u *path;
+ char_u *path = NULL;
garray_T ga;
char_u *buf = xmalloc(MAXPATHL);
size_t l;
@@ -4971,15 +4965,14 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
flags |= EW_FILE | EW_EXEC | EW_SHELLCMD;
bool mustfree = false; // Track memory allocation for *path.
- // For an absolute name we don't use $PATH.
- if (path_is_absolute(pat)) {
- path = (char_u *)" ";
- } else if (pat[0] == '.' && (vim_ispathsep(pat[1])
- || (pat[1] == '.'
- && vim_ispathsep(pat[2])))) {
+ if (pat[0] == '.' && (vim_ispathsep(pat[1])
+ || (pat[1] == '.' && vim_ispathsep(pat[2])))) {
path = (char_u *)".";
} else {
- path = (char_u *)vim_getenv("PATH");
+ // For an absolute name we don't use $PATH.
+ if (!path_is_absolute(pat)) {
+ path = (char_u *)vim_getenv("PATH");
+ }
if (path == NULL) {
path = (char_u *)"";
} else {
@@ -4993,6 +4986,8 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
* current directory, to find "subdir/cmd".
*/
ga_init(&ga, (int)sizeof(char *), 10);
+ hashtab_T found_ht;
+ hash_init(&found_ht);
for (s = path; ; s = e) {
if (*s == NUL) {
if (did_curdir) {
@@ -5004,17 +4999,15 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
did_curdir = true;
}
- if (*s == ' ') {
- s++; // Skip space used for absolute path name.
- }
-
- e = vim_strchr(s, ':');
- if (e == NULL)
+ e = vim_strchr(s, ENV_SEPCHAR);
+ if (e == NULL) {
e = s + STRLEN(s);
+ }
- l = e - s;
- if (l > MAXPATHL - 5)
+ l = (size_t)(e - s);
+ if (l > MAXPATHL - 5) {
break;
+ }
STRLCPY(buf, s, l + 1);
add_pathsep((char *)buf);
l = STRLEN(buf);
@@ -5025,14 +5018,24 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
if (ret == OK) {
ga_grow(&ga, *num_file);
{
- for (i = 0; i < *num_file; ++i) {
- s = (*file)[i];
- if (STRLEN(s) > l) {
- /* Remove the path again. */
- STRMOVE(s, s + l);
- ((char_u **)ga.ga_data)[ga.ga_len++] = s;
- } else
- xfree(s);
+ for (i = 0; i < *num_file; i++) {
+ char_u *name = (*file)[i];
+
+ if (STRLEN(name) > l) {
+ // Check if this name was already found.
+ hash_T hash = hash_hash(name + l);
+ hashitem_T *hi =
+ hash_lookup(&found_ht, (const char *)(name + l),
+ STRLEN(name + l), hash);
+ if (HASHITEM_EMPTY(hi)) {
+ // Remove the path that was prepended.
+ STRMOVE(name, name + l);
+ ((char_u **)ga.ga_data)[ga.ga_len++] = name;
+ hash_add_item(&found_ht, hi, name, hash);
+ name = NULL;
+ }
+ }
+ xfree(name);
}
xfree(*file);
}
@@ -5048,6 +5051,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
if (mustfree) {
xfree(path);
}
+ hash_clear(&found_ht);
}
/// Call "user_expand_func()" to invoke a user defined Vim script function and
@@ -5055,9 +5059,9 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file,
static void * call_user_expand_func(user_expand_func_T user_expand_func,
expand_T *xp, int *num_file, char_u ***file)
{
- int keep = 0;
- char_u num[50];
- char_u *args[3];
+ char_u keep = 0;
+ typval_T args[4];
+ char_u *pat = NULL;
int save_current_SID = current_SID;
void *ret;
struct cmdline_info save_ccline;
@@ -5072,10 +5076,14 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func,
ccline.cmdbuff[ccline.cmdlen] = 0;
}
- args[0] = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
- args[1] = xp->xp_line;
- sprintf((char *)num, "%d", xp->xp_col);
- args[2] = num;
+ pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
+ args[0].v_type = VAR_STRING;
+ args[1].v_type = VAR_STRING;
+ args[2].v_type = VAR_NUMBER;
+ args[3].v_type = VAR_UNKNOWN;
+ args[0].vval.v_string = pat;
+ args[1].vval.v_string = xp->xp_line;
+ args[2].vval.v_number = xp->xp_col;
/* Save the cmdline, we don't know what the function may do. */
save_ccline = ccline;
@@ -5085,7 +5093,7 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func,
ret = user_expand_func(xp->xp_arg,
3,
- (const char_u * const *)args,
+ args,
false);
ccline = save_ccline;
@@ -5093,7 +5101,7 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func,
if (ccline.cmdbuff != NULL)
ccline.cmdbuff[ccline.cmdlen] = keep;
- xfree(args[0]);
+ xfree(pat);
return ret;
}
@@ -5117,14 +5125,14 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file,
e = vim_strchr(s, '\n');
if (e == NULL)
e = s + STRLEN(s);
- const int keep = *e;
+ const char_u keep = *e;
*e = NUL;
const bool skip = xp->xp_pattern[0]
&& vim_regexec(regmatch, s, (colnr_T)0) == 0;
*e = keep;
if (!skip) {
- GA_APPEND(char_u *, &ga, vim_strnsave(s, (int)(e - s)));
+ GA_APPEND(char_u *, &ga, vim_strnsave(s, (size_t)(e - s)));
}
if (*e != NUL) {
@@ -5226,7 +5234,8 @@ static int ExpandRTDir(char_u *pat, int flags, int *num_file, char_u ***file,
}
s++;
*e = NUL;
- memmove(match, s, e - s + 1);
+ assert((e - s) + 1 >= 0);
+ memmove(match, s, (size_t)(e - s) + 1);
}
}
@@ -5262,8 +5271,7 @@ static int ExpandPackAddDir(char_u *pat, int *num_file, char_u ***file)
for (int i = 0; i < ga.ga_len; i++) {
char_u *match = ((char_u **)ga.ga_data)[i];
s = path_tail(match);
- char_u *e = s + STRLEN(s);
- memmove(match, s, e - s + 1);
+ memmove(match, s, STRLEN(s)+1);
}
if (GA_EMPTY(&ga)) {
@@ -5407,7 +5415,9 @@ void init_history(void)
// On copying them to the new arrays, we take the chance to reorder them.
if (newlen != oldlen) {
for (int type = 0; type < HIST_COUNT; type++) {
- histentry_T *temp = newlen ? xmalloc(newlen * sizeof(*temp)) : NULL;
+ histentry_T *temp = (newlen
+ ? xmalloc((size_t)newlen * sizeof(*temp))
+ : NULL);
int j = hisidx[type];
if (j >= 0) {
@@ -5572,7 +5582,6 @@ add_to_history (
)
{
histentry_T *hisptr;
- int len;
if (hislen == 0 || histype == HIST_INVALID) { // no history
return;
@@ -5604,12 +5613,12 @@ add_to_history (
hisptr = &history[histype][hisidx[histype]];
hist_free_entry(hisptr);
- /* Store the separator after the NUL of the string. */
- len = (int)STRLEN(new_entry);
+ // Store the separator after the NUL of the string.
+ size_t len = STRLEN(new_entry);
hisptr->hisstr = vim_strnsave(new_entry, len + 2);
hisptr->timestamp = os_time();
hisptr->additional_elements = NULL;
- hisptr->hisstr[len + 1] = sep;
+ hisptr->hisstr[len + 1] = (char_u)sep;
hisptr->hisnum = ++hisnum[histype];
if (histype == HIST_SEARCH && in_map)
@@ -5663,7 +5672,7 @@ char_u *get_cmdline_str(void)
if (p == NULL)
return NULL;
- return vim_strnsave(p->cmdbuff, p->cmdlen);
+ return vim_strnsave(p->cmdbuff, (size_t)p->cmdlen);
}
/*
@@ -5932,7 +5941,7 @@ void ex_history(exarg_T *eap)
while (ASCII_ISALPHA(*end)
|| vim_strchr((char_u *)":=@>/?", *end) != NULL)
end++;
- histype1 = get_histtype((const char *)arg, end - arg, false);
+ histype1 = get_histtype((const char *)arg, (size_t)(end - arg), false);
if (histype1 == HIST_INVALID) {
if (STRNICMP(arg, "all", end - arg) == 0) {
histype1 = 0;
@@ -5971,13 +5980,14 @@ void ex_history(exarg_T *eap)
if (hist[i].hisstr != NULL
&& hist[i].hisnum >= j && hist[i].hisnum <= k) {
msg_putchar('\n');
- sprintf((char *)IObuff, "%c%6d ", i == idx ? '>' : ' ',
- hist[i].hisnum);
- if (vim_strsize(hist[i].hisstr) > (int)Columns - 10)
+ snprintf((char *)IObuff, IOSIZE, "%c%6d ", i == idx ? '>' : ' ',
+ hist[i].hisnum);
+ if (vim_strsize(hist[i].hisstr) > Columns - 10) {
trunc_string(hist[i].hisstr, IObuff + STRLEN(IObuff),
- (int)Columns - 10, IOSIZE - (int)STRLEN(IObuff));
- else
+ Columns - 10, IOSIZE - (int)STRLEN(IObuff));
+ } else {
STRCAT(IObuff, hist[i].hisstr);
+ }
msg_outtrans(IObuff);
ui_flush();
}
@@ -6138,8 +6148,8 @@ static int open_cmdwin(void)
State = NORMAL;
setmouse();
- /* Trigger CmdwinEnter autocommands. */
- typestr[0] = cmdwin_type;
+ // Trigger CmdwinEnter autocommands.
+ typestr[0] = (char_u)cmdwin_type;
typestr[1] = NUL;
apply_autocmds(EVENT_CMDWINENTER, typestr, typestr, FALSE, curbuf);
if (restart_edit != 0) /* autocmd with ":startinsert" */
@@ -6217,7 +6227,7 @@ static int open_cmdwin(void)
if (ccline.cmdpos > ccline.cmdlen)
ccline.cmdpos = ccline.cmdlen;
if (cmdwin_result == K_IGNORE) {
- set_cmdspos_cursor();
+ ccline.cmdspos = cmd_screencol(ccline.cmdpos);
redrawcmd();
}
}